document-widgets.mak 32KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806
  1. <%inherit file="local:templates.master"/>
  2. <%namespace name="POD" file="pod.templates.pod"/>
  3. <%namespace name="DOCTABS" file="pod.templates.document-widgets-tabs"/>
  4. <%def name="node_treeview_for_set_parent_menu(node_id, node_list, indentation=-1)">
  5. % if indentation==-1:
  6. <li>
  7. <a href="${tg.url('/api/set_parent_node', dict(node_id=node_id, new_parent_id=0))}">
  8. <i class="fa fa-file-text-o"></i> ${_('Home')}
  9. </a>
  10. ${node_treeview_for_set_parent_menu(node_id, node_list, 0)}
  11. </li>
  12. % else:
  13. % if len(node_list)>0:
  14. <ul style="list-style: none;">
  15. % for new_parent_node in node_list:
  16. <li>
  17. <a href="${tg.url('/api/set_parent_node', dict(node_id=node_id, new_parent_id=new_parent_node.node_id))}"><i class="fa fa-file-text-o"></i> ${new_parent_node.getTruncatedLabel(40-indentation*2)}
  18. </a>
  19. ${node_treeview_for_set_parent_menu(node_id, new_parent_node.getStaticChildList(), indentation+1)}
  20. </li>
  21. % endfor
  22. </ul>
  23. % endif
  24. % endif
  25. </%def>
  26. <%def name="ToolbarMenuItemModal(psTargetModalId, psIconClasses, psMenuLabel, psItemClasses='')">
  27. <li class="${psItemClasses}"><a href="#${psTargetModalId}" role="button" data-toggle="modal"><i class="${psIconClasses}"></i> ${psMenuLabel}</a></li>
  28. </%def>
  29. <%def name="ToolbarMenuItemInline(psTargetId, psIconClasses, psMenuLabel)">
  30. <li><a href="#${psTargetId}"><i class="${psIconClasses}"></i> ${psMenuLabel}</a></li>
  31. </%def>
  32. <%def name="ToolbarMenuItemLink(psTargetUrl, psIconClasses, psMenuLabel, psLinkCss='', psLinkTitle='', psOnClick='')">
  33. % if psTargetUrl=='#':
  34. <li class="disabled"><a href="${psTargetUrl}" class="${psLinkCss}" title="${psLinkTitle}" onclick="${psOnClick}"><i class="${psIconClasses}"></i> ${psMenuLabel}</a></li>
  35. % else:
  36. <li><a href="${psTargetUrl}" class="${psLinkCss}" title="${psLinkTitle}" onclick="${psOnClick}"><i class="${psIconClasses}"></i> ${psMenuLabel}</a></li>
  37. % endif
  38. </%def>
  39. <%def name="Toolbar(poNode, plNodeStatusList, plRootNodes, psDivId, user_rights, user)">
  40. <div id="${psDivId}">
  41. ##
  42. ## TOOLBAR ITEMS ARE SHOWN ACCORDING TO THE R/W PERMISSIONS GRANTED TO THE USER
  43. ##
  44. % if user.user_id==poNode.owner_id or (user_rights and user_rights.hasWriteAccess()):
  45. <div class="btn-group">
  46. ${POD.EditButton('current-document-content-edit-button', True)}
  47. <button class="btn btn-small" data-toggle="dropdown" href="#">
  48. <i class="fa fa-signal"></i>
  49. ${_("Change status")}
  50. </button>
  51. <a class="btn btn-small dropdown-toggle" data-toggle="dropdown" href="#">
  52. <span class="caret"></span>
  53. </a>
  54. <ul class="dropdown-menu pull-right">
  55. <li>
  56. <div class="pod-grey strong" ><strong><i class="fa fa-magic"></i> ${_('Current status is...')}</strong><br/></div>
  57. </li>
  58. % for node_status in plNodeStatusList:
  59. % if node_status.status_id==poNode.getStatus().status_id:
  60. ${ToolbarMenuItemLink('#', node_status.icon_id, node_status.label, 'disabled '+node_status.css, h.getExplanationAboutStatus(node_status.status_id, current_node.getStatus().status_id))}
  61. % endif
  62. % endfor
  63. <li class="divider" role="presentation"></li>
  64. <li>
  65. <div class=" strong" ><strong><i class="fa fa-magic"></i> ${_('Change to...')}</strong><br/></div>
  66. <div class="pod-grey"><i>${_('change the status to...')}</i></div>
  67. </li>
  68. % for node_status in plNodeStatusList:
  69. % if node_status.status_id!=poNode.getStatus().status_id:
  70. ${ToolbarMenuItemLink(tg.url('/api/edit_status', dict(node_id=current_node.node_id, node_status=node_status.status_id)), node_status.icon_id, node_status.label, node_status.css, h.getExplanationAboutStatus(node_status.status_id, current_node.getStatus().status_id))}
  71. % endif
  72. % endfor
  73. </ul>
  74. </div>
  75. % endif
  76. <div class="btn-group">
  77. <button class="btn btn-small btn-success" data-toggle="dropdown" href="#">
  78. <i class="fa fa-plus"></i> ${_('Add')}
  79. </button>
  80. <a class="btn btn-small dropdown-toggle" data-toggle="dropdown" href="#"><span class="caret"></span></a>
  81. <ul class="dropdown-menu">
  82. <li>
  83. <div class="btn-success strong" ><strong><i class="fa fa-magic"></i> ${_('Add New...')}</strong><br/></div>
  84. <div class="pod-grey"><i>${_('create a totally new item...')}</i></div>
  85. </li>
  86. ${ToolbarMenuItemModal(h.ID.AddDocumentModalForm(current_node), 'fa fa-file-text-o', _('Document'))}
  87. ${ToolbarMenuItemModal(h.ID.AddFileModalForm(current_node), 'fa fa-paperclip', _('File'))}
  88. ${ToolbarMenuItemModal(h.ID.AddEventModalForm(current_node), 'fa fa-calendar', _('Event'))}
  89. ${ToolbarMenuItemModal(h.ID.AddContactModalForm(current_node), 'fa fa-user', _('Contact'))}
  90. ##
  91. ## FIXME - DA - 07-05-2014 - The link below is not working clean
  92. ##
  93. ${ToolbarMenuItemInline(h.ID.AddCommentInlineForm(), 'fa fa-comments-o', _('Comment'))}
  94. <li class="divider" role="presentation"></li>
  95. <li>
  96. <div class="btn-warning strong" ><strong><i class="fa fa-link"></i> Add Existing...</strong><br/></div>
  97. <div class="pod-grey"><i>link to an existing item...</i></div>
  98. </li>
  99. <li><p class="pod-grey"><i class="fa fa-danger"></i> coming soon!</p></li>
  100. </ul>
  101. </div>
  102. % if user.user_id==poNode.owner_id or (user_rights and user_rights.hasWriteAccess()):
  103. <div class="btn-group pull-right">
  104. <button class="btn btn-small btn-link" data-toggle="dropdown" href="#">
  105. ${_('more ...')}
  106. </button>
  107. <ul class="dropdown-menu">
  108. <li>
  109. <div class="strong" ><strong><i class="fa fa-magic"></i> ${_('Advanced actions...')}</strong><br/></div>
  110. <div class="pod-grey"><i>${_('power user actions...')}</i></div>
  111. </li>
  112. ##
  113. ## Here are MOVE and DELETE buttons
  114. ##
  115. ${ToolbarMenuItemModal(h.ID.MoveDocumentModalForm(current_node), 'fa fa-arrows', _('Move'), 'btn-warning')}
  116. ${ToolbarMenuItemLink(tg.url('/api/edit_status', dict(node_id=poNode.node_id, node_status='deleted')), 'fa fa-trash-o', _('Delete'), 'btn-danger', _('Delete the current document'), 'return confirm(\'{0}\');'.format('Delete current document?'))}
  117. </ul>
  118. </div>
  119. % endif
  120. </div>
  121. </%def>
  122. <%def name="BreadCrumb(poNode, allowed_nodes)">
  123. <ul class="breadcrumb span12">
  124. <li>
  125. <span class="divider">/</span>
  126. <a href="${tg.url('/document/')}">Documents</a>
  127. </li>
  128. % if poNode!=None:
  129. % for breadcrumb_node in poNode.getBreadCrumbNodes():
  130. ##
  131. ## HACK - D.A - 2014-05-29
  132. ## Here we remove forbidden nodes from the breadcrumb
  133. ## This should not be done in the templates!
  134. ##
  135. % if breadcrumb_node in allowed_nodes:
  136. <li>
  137. <span class="divider">/</span>
  138. <a href="${tg.url('/document/%s'%(breadcrumb_node.node_id))}">${breadcrumb_node.getTruncatedLabel(30)}</a>
  139. </li>
  140. % endif
  141. % endfor
  142. <li class="active">
  143. <span class="divider">/</span>
  144. ${poNode.data_label}
  145. </li>
  146. % endif
  147. </ul>
  148. </%def>
  149. <%def name="EditForm(poNode)">
  150. <form
  151. style="display: none;"
  152. id="current-document-content-edit-form"
  153. method="post"
  154. action="${tg.url('/api/edit_label_and_content')}"
  155. >
  156. <div>
  157. ${POD.CancelButton('current-document-content-edit-cancel-button-top', True)}
  158. ${POD.SaveButton('current-document-content-edit-save-button-top', True)}
  159. </div>
  160. <div style="padding: 0.5em 0 0 0">
  161. <input type="hidden" name="node_id" value="${current_node.node_id}"/>
  162. <input type="hidden" name="data_content" id="current_node_textarea" />
  163. <label>
  164. ${_('Title')}
  165. <input
  166. type="text"
  167. name="data_label"
  168. value="${current_node.data_label}"
  169. class="span4"
  170. placeholder="${_('document title')}"
  171. />
  172. </label>
  173. </div>
  174. <div>
  175. ${POD.RichTextEditor('current_node_textarea_wysiwyg', current_node.data_content)}
  176. </div>
  177. <div class="pull-right">
  178. ${POD.CancelButton('current-document-content-edit-cancel-button', True)}
  179. ${POD.SaveButton('current-document-content-edit-save-button', True)}
  180. </div>
  181. </form>
  182. </%def>
  183. <%def name="ShowContent(poNode, psKeywords)">
  184. <div>
  185. % if len(psKeywords)>0 and psKeywords!='':
  186. ${poNode.getContentWithHighlightedKeywords(psKeywords.split(), poNode.getContentWithTags())|n}
  187. % else:
  188. ${poNode.getContentWithTags()|n}
  189. % endif
  190. </div>
  191. </%def>
  192. <%def name="ShowTitle(poNode, psKeywords, psId)">
  193. <h3 id="${psId}" title="Document ${poNode.node_id}: ${poNode.data_label}">
  194. ${poNode.data_label}
  195. <sup class="label ${poNode.getStatus().css}" href="#">
  196. <i class="${poNode.getStatus().icon_id}"></i>
  197. ${poNode.getStatus().label}
  198. </sup>
  199. % if poNode.is_shared==False:
  200. <sup class="label label-info" title="${_('This document is private')}">
  201. <i class="fa fa-key"></i>
  202. ${_('private')}
  203. </sup>
  204. % else:
  205. <sup class="label label-warning" title="${_('This document is shared')}">
  206. <i class="fa fa-group"></i>
  207. ${_('shared')}
  208. </sup>
  209. % endif
  210. ######
  211. ##
  212. ## 2014-05-06 - D.A. - The document is not yet internet-sharable
  213. ##
  214. ## % if poNode.is_public==True:
  215. ## <sup class="label label-warning" href="#">
  216. ## <i class="fa fa-globe"></i>
  217. ## <span title="${_('This document is published through internet at %s')%poNode.public_url_key}">${_('shared')}</span>
  218. ## </sup>
  219. ## % endif
  220. </h3>
  221. </%def>
  222. #######
  223. ##
  224. ## METADATA TAB FUNCTIONS
  225. ##
  226. <%def name="MetadataTab(psAnchorName, psDataToggleName, psTitle, psFontAwesomeIconClass, plItems)">
  227. <a
  228. href="${psAnchorName}"
  229. data-toggle="${psDataToggleName}"
  230. title="${psTitle}"
  231. >
  232. <i class="pod-dark-grey fa ${psFontAwesomeIconClass}"></i>
  233. ${POD.ItemNb(plItems)}
  234. </a>
  235. </%def>
  236. <%def name="FirstTimeFakeDocument()">
  237. <div id='application-document-panel' class="span5">
  238. <div id='current-document-content' class="well">
  239. ${_('<p>We suggest you to start...<br/><br/></p>')|n}
  240. <h4>
  241. <i class="fa fa-angle-double-left fa-3x fa-fw pod-blue" style="vertical-align: middle"></i>
  242. ${_('by working on existing items')}
  243. </h4>
  244. <p class="text-center">${_('or')}</p>
  245. <h4 class="">
  246. <i class="fa fa-angle-double-right fa-3x fa-fw pod-blue" style="vertical-align: middle;"></i>
  247. ${_('by creating a new document')}
  248. <a href="#${h.ID.AddDocumentModalForm()}" role="button" class="btn btn-success" style="float:right;" data-toggle="modal">
  249. <i class="fa fa-plus"></i>
  250. ${_('Create')}
  251. </a>
  252. </h4>
  253. ${DocumentEditModalDialog(None, None, tg.url('/api/create_document'), h.ID.AddDocumentModalForm(), 'Create your first document')}
  254. <div style="clear: both;"></div>
  255. </div>
  256. <script>
  257. </script>
  258. </div>
  259. </%def>
  260. <%def name="DocumentEditModalDialog(poParentNode, poNode, psPostUrl, psModalId, psTitle)">
  261. <div
  262. id="${psModalId}"
  263. class="modal hide"
  264. tabindex="-1"
  265. role="dialog"
  266. aria-labelledby="myModalLabel"
  267. aria-hidden="true">
  268. <div class="modal-header">
  269. ## MODAL HEADER
  270. <button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
  271. <h3 id="myModalLabel">${psTitle}</h3>
  272. ## MODAL HEADER [END]
  273. </div>
  274. <div class="modal-body">
  275. ## MODAL BODY
  276. <form id='${psModalId}-form' method="GET" action="${psPostUrl}">
  277. <div style="padding: 0.5em 0 0 0">
  278. % if poNode!=None:
  279. <input type="hidden" name="node_id" value="${poNode.node_id}"/>
  280. % endif
  281. <input type="hidden" name="parent_id" value="${poParentNode.node_id if poParentNode else 0}"/>
  282. <input type="hidden" name="data_content" id="${psModalId}-textarea" />
  283. <input
  284. type="text"
  285. name="data_label"
  286. value="${poNode.data_label if poNode!=None else ''}"
  287. class="span4"
  288. placeholder="${_('document title')}"
  289. />
  290. </div>
  291. <div>
  292. ${POD.RichTextEditor(psModalId+'-textarea-wysiwyg', poNode.data_content if poNode!=None else '')}
  293. </div>
  294. % if poParentNode and poParentNode.is_shared:
  295. <p>
  296. <input type="checkbox" name="inherit_rights" checked="checked"/>
  297. ${_('Share:')}
  298. <span class="pod-grey">${_('if checked, then copy share properties from current item')}</span>
  299. </p>
  300. % endif
  301. </form>
  302. ## MODAL BODY [END]
  303. </div>
  304. <div class="modal-footer">
  305. ## MODAL FOOTER
  306. <button class="btn" data-dismiss="modal" aria-hidden="true">
  307. <i class="fa fa-ban"></i> ${_('Cancel')}
  308. </button>
  309. <button class="btn btn-success" id="${psModalId}-form-submit-button">
  310. <i class="fa fa-check"></i> ${_('Save changes')}
  311. </button>
  312. ## MODAL FOOTER [END]
  313. <script>
  314. $('#${psModalId}-form-submit-button').click(function(){
  315. $('#${psModalId}-textarea-wysiwyg').cleanHtml();
  316. $('#${psModalId}-textarea').val($('#${psModalId}-textarea-wysiwyg').html());
  317. $('#${psModalId}-form')[0].submit();
  318. });
  319. </script>
  320. </div>
  321. </div>
  322. </%def>
  323. <%def name="FileEditModalDialog(poParentNode, poNode, psPostUrl, psModalId, psTitle)">
  324. <div
  325. id="${psModalId}"
  326. class="modal hide"
  327. tabindex="-1"
  328. role="dialog"
  329. aria-labelledby="myModalLabel"
  330. aria-hidden="true">
  331. <div class="modal-header">
  332. ## MODAL HEADER
  333. <button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
  334. <h3 id="myModalLabel">${psTitle}</h3>
  335. ## MODAL HEADER [END]
  336. </div>
  337. <div class="modal-body">
  338. ## MODAL BODY
  339. <form id='${psModalId}-form' method="POST" action="${psPostUrl}" enctype="multipart/form-data">
  340. % if poNode!=None:
  341. <input type="hidden" name="node_id" value="${poNode.node_id}"/>
  342. % endif
  343. <input type="hidden" name="parent_id" value="${poParentNode.node_id if poParentNode else 0}"/>
  344. <input type="hidden" name="data_content" id="${psModalId}-textarea" />
  345. <div>
  346. <label>
  347. ${_('Title')}
  348. <input
  349. type="text"
  350. name="data_label"
  351. value="${poNode.data_label if poNode!=None else ''}"
  352. class="span4"
  353. placeholder="${_('this field is optionnal')}"
  354. />
  355. </label>
  356. <label>
  357. ${_('Choose a file...')}
  358. <input type="file" class="span4" placeholder="${_('choose a file...')}" name="data_file"/>
  359. </label>
  360. </div>
  361. <div>
  362. <label>${_('File description (optionnal)')}</label>
  363. ${POD.RichTextEditor(psModalId+'-textarea-wysiwyg', poNode.data_content if poNode!=None else '', '')}
  364. </div>
  365. % if poParentNode and poParentNode.is_shared:
  366. <p>
  367. <input type="checkbox" name="inherit_rights" checked="checked"/>
  368. ${_('Share:')}
  369. <span class="pod-grey">${_('if checked, then copy share properties from current item')}</span>
  370. </p>
  371. % endif
  372. </form>
  373. ## MODAL BODY [END]
  374. </div>
  375. <div class="modal-footer">
  376. ## MODAL FOOTER
  377. <button class="btn" data-dismiss="modal" aria-hidden="true">
  378. <i class="fa fa-ban"></i> ${_('Cancel')}
  379. </button>
  380. <button class="btn btn-success" id="${psModalId}-form-submit-button">
  381. <i class="fa fa-check"></i> ${_('Save changes')}
  382. </button>
  383. <script>
  384. $('#${psModalId}-form-submit-button').click(function(){
  385. $('#${psModalId}-textarea-wysiwyg').cleanHtml();
  386. $('#${psModalId}-textarea').val($('#${psModalId}-textarea-wysiwyg').html());
  387. $('#${psModalId}-form')[0].submit();
  388. });
  389. </script>
  390. ## MODAL FOOTER [END]
  391. </div>
  392. </div>
  393. </%def>
  394. <%def name="EventEditModalDialog(poParentNode, poNode, psPostUrl, psModalId, psTitle)">
  395. <div
  396. id="${psModalId}"
  397. class="modal hide"
  398. tabindex="-1"
  399. role="dialog"
  400. aria-labelledby="myModalLabel"
  401. aria-hidden="true">
  402. <div class="modal-header">
  403. ## MODAL HEADER
  404. <button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
  405. <h3 id="myModalLabel">
  406. ${psTitle}
  407. </h3>
  408. ## MODAL HEADER [END]
  409. </div>
  410. <div class="modal-body">
  411. ###### MODAL BODY
  412. <form id='${psModalId}-form' action='${psPostUrl}' method='POST'>
  413. <input type="hidden" name='parent_id' value="${poParentNode.node_id if poParentNode else 0}"/>
  414. <fieldset>
  415. <label>
  416. ${_('Event')}
  417. <input type="text" name='data_label' placeholder="Event"/>
  418. </label>
  419. <label>
  420. ${_('Date and time')}
  421. <div class="datetime-picker-input-div input-append date">
  422. <input name='data_datetime' data-format="dd/MM/yyyy hh:mm" type="text" placeholder="date and time"/>
  423. <span class="add-on"><i data-time-icon="icon-g-clock" data-date-icon="icon-g-calendar"></i></span>
  424. </div>
  425. </label>
  426. <label>
  427. ${_('Event description:')}
  428. <div>
  429. <input type="hidden" name="data_content" id="${psModalId}-textarea" />
  430. ${POD.RichTextEditor(psModalId+'-textarea-wysiwyg', poNode.data_content if poNode!=None else '', 'boldanditalic')}
  431. </div>
  432. </label>
  433. % if poParentNode and poParentNode.is_shared:
  434. <label>
  435. <p>
  436. <input type="checkbox" name="inherit_rights" checked="checked"/>
  437. ${_('Share:')}
  438. <span class="pod-grey">${_('if checked, then copy share properties from current item')}</span>
  439. </p>
  440. <label>
  441. % endif
  442. </fieldset>
  443. </form>
  444. ###### MODAL BODY [END]
  445. </div>
  446. <div class="modal-footer">
  447. ###### MODAL FOOTER
  448. <button class="btn" data-dismiss="modal" aria-hidden="true">
  449. <i class="fa fa-ban"></i> ${_('Cancel')}
  450. </button>
  451. <button class="btn btn-success" id="${psModalId}-form-submit-button">
  452. <i class="fa fa-check"></i> ${_('Save changes')}
  453. </button>
  454. <script>
  455. $('#${psModalId}-form-submit-button').click(function(){
  456. $('#${psModalId}-textarea-wysiwyg').cleanHtml();
  457. $('#${psModalId}-textarea').val($('#${psModalId}-textarea-wysiwyg').html());
  458. $('#${psModalId}-form')[0].submit();
  459. });
  460. </script>
  461. ###### MODAL FOOTER [END]
  462. </div>
  463. </div>
  464. </%def>
  465. <%def name="ContactEditModalDialog(poParentNode, poNode, psPostUrl, psModalId, psTitle)">
  466. <div
  467. id="${psModalId}"
  468. class="modal hide"
  469. tabindex="-1"
  470. role="dialog"
  471. aria-labelledby="myModalLabel"
  472. aria-hidden="true">
  473. <div class="modal-header">
  474. ## MODAL HEADER
  475. <button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
  476. <h3 id="myModalLabel">${psTitle}</h3>
  477. ## MODAL HEADER [END]
  478. </div>
  479. <div class="modal-body">
  480. ## MODAL BODY
  481. <form id='${psModalId}-form' method="POST" action="${psPostUrl}">
  482. % if poNode!=None:
  483. <input type="hidden" name="node_id" value="${poNode.node_id}"/>
  484. % endif
  485. <input type="hidden" name="parent_id" value="${poParentNode.node_id if poParentNode else 0}"/>
  486. <input type="hidden" name="data_content" id="${psModalId}-textarea" />
  487. <div>
  488. <label>
  489. ${_('Contact name and firstname')}
  490. <input
  491. type="text"
  492. name="data_label"
  493. value="${poNode.data_label if poNode!=None else ''}"
  494. class="span4"
  495. placeholder="${_('name, firstname, title...')}"
  496. />
  497. </label>
  498. </div>
  499. <div>
  500. <label>${_('Address, phone, email, company...')}</label>
  501. ${POD.RichTextEditor(psModalId+'-textarea-wysiwyg', poNode.data_content if poNode!=None else '', 'boldanditalic')}
  502. </div>
  503. % if poParentNode and poParentNode.is_shared:
  504. <label>
  505. <p>
  506. <input type="checkbox" name="inherit_rights" checked="checked"/>
  507. ${_('Share:')}
  508. <span class="pod-grey">${_('if checked, then copy share properties from current item')}</span>
  509. </p>
  510. <label>
  511. % endif
  512. </form>
  513. ## MODAL BODY [END]
  514. </div>
  515. <div class="modal-footer">
  516. ## MODAL FOOTER
  517. <button class="btn" data-dismiss="modal" aria-hidden="true">
  518. <i class="fa fa-ban"></i> ${_('Cancel')}
  519. </button>
  520. <button class="btn btn-success" id="${psModalId}-form-submit-button">
  521. <i class="fa fa-check"></i> ${_('Save changes')}
  522. </button>
  523. <script>
  524. $('#${psModalId}-form-submit-button').click(function(){
  525. $('#${psModalId}-textarea-wysiwyg').cleanHtml();
  526. $('#${psModalId}-textarea').val($('#${psModalId}-textarea-wysiwyg').html());
  527. $('#${psModalId}-form')[0].submit();
  528. });
  529. </script>
  530. ## MODAL FOOTER [END]
  531. </div>
  532. </div>
  533. </%def>
  534. <%def name="MoveDocumentModalDialog(poNode, psPostUrl, psModalId, psTitle)">
  535. <div
  536. id="${psModalId}"
  537. class="modal hide"
  538. tabindex="-1"
  539. role="dialog"
  540. aria-labelledby="myModalLabel"
  541. aria-hidden="true">
  542. <div class="modal-header">
  543. ## MODAL HEADER
  544. <button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
  545. <h3 id="myModalLabel">${psTitle}</h3>
  546. ## MODAL HEADER [END]
  547. </div>
  548. <div class="modal-body">
  549. ## MODAL BODY
  550. <p>${_('Select the destination:')}</p>
  551. <div id="${psModalId}-new-parent-selector-treeview"></div>
  552. <script>
  553. /** return true or false if the node should be shown in the "move item" dialog treeview
  554. */
  555. function shouldRemoveNodeFromMoveTreeView(parentTreeItem, currentTreeItem, rootList) {
  556. if(currentTreeItem.id==${poNode.node_id}) {
  557. console.log('Say OK to remove item #'+currentTreeItem.id+' from menu');
  558. return true;
  559. }
  560. return false;
  561. }
  562. $(function () {
  563. $('#${psModalId}-new-parent-selector-treeview').jstree({
  564. "plugins" : [ "wholerow"],
  565. 'core' : {
  566. 'error': function (error) {
  567. console.log('Error ' + error.toString())
  568. },
  569. 'data' : {
  570. 'dataType': 'json',
  571. 'contentType': 'application/json; charset=utf-8',
  572. 'url' : function (node) {
  573. if (node.id==='#') {
  574. return '${tg.url("/api/menu/initialize", dict(current_node_id=poNode._oParent.node_id if poNode._oParent else 0))}';
  575. } else {
  576. return '${tg.url("/api/menu/children")}';
  577. }
  578. },
  579. 'data' : function(node) {
  580. console.log("NODE => "+JSON.stringify(node))
  581. return {
  582. 'id' : node.id
  583. };
  584. },
  585. 'success': function (new_data) {
  586. console.log('loaded new menu data (for move operation)' + new_data)
  587. console.log(new_data);
  588. for (var i = new_data['d'].length; i--;) {
  589. prepareOrRemoveTreeNode(null, new_data['d'][i], new_data['d'], shouldRemoveNodeFromMoveTreeView);
  590. }
  591. return new_data;
  592. },
  593. },
  594. }
  595. });
  596. $('#${psModalId}-new-parent-selector-treeview').on("select_node.jstree", function (e, data) {
  597. new_parent_id_selected = data.selected[0];
  598. $("#${psModalId}-form-new-parent-field").attr("value", new_parent_id_selected)
  599. console.log("About to move document "+${poNode.node_id}+" as child of "+new_parent_id_selected);
  600. });
  601. });
  602. </script>
  603. <form id='${psModalId}-form' method="POST" action="${psPostUrl}" enctype="multipart/form-data">
  604. <input type="hidden" name="node_id" value="${poNode.node_id}"/>
  605. <input type="hidden" name="new_parent_id" value="-1" id="${psModalId}-form-new-parent-field" />
  606. </form>
  607. ## MODAL BODY [END]
  608. </div>
  609. <div class="modal-footer">
  610. ## MODAL FOOTER
  611. <button class="btn" data-dismiss="modal" aria-hidden="true">
  612. <i class="fa fa-ban"></i> ${_('Cancel')}
  613. </button>
  614. <button class="btn btn-success" id="${psModalId}-form-submit-button">
  615. <i class="fa fa-check"></i> ${_('Save changes')}
  616. </button>
  617. <script>
  618. $('#${psModalId}-form-submit-button').click(function(){
  619. $('#${psModalId}-textarea-wysiwyg').cleanHtml();
  620. $('#${psModalId}-textarea').val($('#${psModalId}-textarea-wysiwyg').html());
  621. $('#${psModalId}-form')[0].submit();
  622. });
  623. </script>
  624. ## MODAL FOOTER [END]
  625. </div>
  626. </div>
  627. </%def>
  628. <%def name="TabbedMetadataPanelContent(current_user, current_node)">
  629. <div class="tabbable">
  630. <ul class="nav nav-tabs" style="margin-bottom: 0em;">
  631. <li>${MetadataTab('#subdocuments', 'tab', _('Subdocuments'), 'fa-file-text-o', current_node.getChildren())}</li>
  632. <li>${MetadataTab('#events', 'tab', _('Calendar'), 'fa-calendar', current_node.getEvents())}</li>
  633. <li>${MetadataTab('#contacts', 'tab', _('Address book'), 'fa-user', current_node.getContacts())}</li>
  634. <li class="active">${MetadataTab('#comments', 'tab', _('Comment thread'), 'fa-comments-o', current_node.getComments())}</li>
  635. <li>${MetadataTab('#files', 'tab', _('Attachments'), 'fa-paperclip', current_node.getFiles())}</li>
  636. <li class="pull-right">${MetadataTab('#accessmanagement', 'tab', _('Access Management'), 'fa-key', current_node.getGroupsWithSomeAccess())}</li>
  637. <li class="pull-right">${MetadataTab('#history', 'tab', _('History'), 'fa-history', current_node.getHistory())}</li>
  638. </ul>
  639. ################################
  640. ##
  641. ## PANEL SHOWING ASSOCIATED DATA AND METADATA
  642. ##
  643. ################################
  644. <div class="tab-content">
  645. <div class="tab-pane" id="subdocuments">${DOCTABS.SubdocumentContent(current_node)}</div>
  646. <div class="tab-pane" id="events">${DOCTABS.EventTabContent(current_user, current_node)}</div>
  647. <div class="tab-pane" id="contacts">${DOCTABS.ContactTabContent(current_node)}</div>
  648. <div class="tab-pane active" id="comments">${DOCTABS.CommentTabContent(current_user, current_node)}</div>
  649. <div class="tab-pane" id="files">${DOCTABS.FileTabContent(current_node)}</div>
  650. <div class="tab-pane" id="history">${DOCTABS.HistoryTabContent(current_node)}</div>
  651. <div class="tab-pane" id="accessmanagement">${DOCTABS.AccessManagementTab(current_node, current_user_rights, current_user)}</div>
  652. </div>
  653. </div>
  654. </%def>
  655. <%def name="ContentExplorerPanelContent(user, node)">
  656. <link rel="stylesheet" href="${tg.url('/jstree/dist/themes/default/style.min.css')}" />
  657. <script src="${tg.url('/jstree/dist/jstree.js')}"></script>
  658. <style>
  659. #left-menu-treeview {overflow:hidden;}
  660. #left-menu-treeview:hover {overflow:visible; }
  661. </style>
  662. <h5>${_('Content explorer')}</h5>
  663. <div id="left-menu-treeview"></div>
  664. <script>
  665. function prepareOrRemoveTreeNode(parentTreeViewItem, currentTreeViewItem, rootList, shouldRemoveNodeCallBack) {
  666. // In case parentTreeViewItem is Null, then use rootList as the parent
  667. console.log("node #"+currentTreeViewItem.id+' => '+currentTreeViewItem.node_status);
  668. if(shouldRemoveNodeCallBack && shouldRemoveNodeCallBack(parentTreeViewItem, currentTreeViewItem, rootList)) {
  669. console.log('Will remove node #'+currentTreeViewItem.id+' from tree view');
  670. if(parentTreeViewItem!=null) {
  671. var currentTreeViewItemPosition = parentTreeViewItem.children.indexOf(currentTreeViewItem);
  672. if(currentTreeViewItemPosition != -1) {
  673. parentTreeViewItem.children.splice(currentTreeViewItemPosition, 1);
  674. }
  675. } else {
  676. var currentTreeViewItemPosition = rootList.indexOf(currentTreeViewItem);
  677. if(currentTreeViewItemPosition != -1) {
  678. rootList.splice(currentTreeViewItemPosition, 1);
  679. }
  680. }
  681. } else {
  682. for (var i = currentTreeViewItem.children.length; i--;) {
  683. console.log('processing node #'+currentTreeViewItem.children[i].id);
  684. prepareOrRemoveTreeNode(currentTreeViewItem, currentTreeViewItem.children[i], rootList, shouldRemoveNodeCallBack);
  685. }
  686. }
  687. }
  688. function shouldRemoveNodeDoneCallBack(parentTreeViewItem, currentTreeViewItem, rootList) {
  689. if(currentTreeViewItem.node_status=='done' || currentTreeViewItem.node_status=='closed') {
  690. console.log('Hide item #'+currentTreeViewItem.id+' from menu (status is '+currentTreeViewItem.node_status+')');
  691. return true;
  692. }
  693. return false;
  694. }
  695. $(function () {
  696. $('#left-menu-treeview').jstree({
  697. 'plugins' : [ 'wholerow', 'types' ],
  698. 'core' : {
  699. 'error': function (error) {
  700. console.log('Error ' + error.toString())
  701. },
  702. 'data' : {
  703. 'dataType': 'json',
  704. 'contentType': 'application/json; charset=utf-8',
  705. 'url' : function (node) {
  706. if (node.id==='#') {
  707. return '${tg.url("/api/menu/initialize", dict(current_node_id=node.node_id if node else 0))}';
  708. } else {
  709. return '${tg.url("/api/menu/children")}';
  710. }
  711. },
  712. 'data' : function(node) {
  713. console.log("NODE => "+JSON.stringify(node))
  714. return {
  715. 'id' : node.id
  716. };
  717. },
  718. 'success': function (new_data) {
  719. console.log('loaded new menu data' + new_data)
  720. console.log(new_data);
  721. for (var i = new_data['d'].length; i--;) {
  722. prepareOrRemoveTreeNode(null, new_data['d'][i], new_data['d'], shouldRemoveNodeDoneCallBack);
  723. }
  724. return new_data;
  725. },
  726. },
  727. }
  728. });
  729. $('#left-menu-treeview').on("select_node.jstree", function (e, data) {
  730. url = "${tg.url('/document/')}"+data.selected[0];
  731. console.log("Opening document: "+url);
  732. location.href = url;
  733. });
  734. $('#left-menu-treeview').on("loaded.jstree", function () {
  735. nodes = $('#left-menu-treeview .jstree-node');
  736. console.log("nodes = "+nodes.length);
  737. if (nodes.length<=0) {
  738. $("#left-menu-treeview").append( "<p class='pod-grey'>${_('There is no content yet.')|n}" );
  739. $("#left-menu-treeview").append( "<p><a class=\"btn btn-success\" data-toggle=\"modal\" role=\"button\" href=\"#add-document-modal-form\"><i class=\"fa fa-plus\"></i> ${_('Create a topic')}</a></p>" );
  740. }
  741. });
  742. });
  743. </script>
  744. </%def>