document.mak 21KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418
  1. <%inherit file="local:templates.master"/>
  2. <%namespace name="POD" file="pboard.templates.pod"/>
  3. <%def name="title()">
  4. pod :: document ${current_node.getTruncatedLabel(40)} [#${current_node.node_id} / ${current_node.getStatus().label}]
  5. </%def>
  6. <%def name="node_treeview_for_set_parent_menu(node_id, node_list, indentation=-1)">
  7. % if indentation==-1:
  8. <li><a href="${tg.url('/api/set_parent_node?node_id=%i&new_parent_id=0'%(current_node.node_id))}">${_('Home')}</a>
  9. ${node_treeview_for_set_parent_menu(node_id, node_list, 0)}
  10. </li>
  11. % else:
  12. % if len(node_list)>0:
  13. <ul>
  14. % for new_parent_node in node_list:
  15. <li>
  16. <a href="${tg.url('/api/set_parent_node?node_id=%i&new_parent_id=%i'%(node_id, new_parent_node.node_id))}">${new_parent_node.getTruncatedLabel(40-indentation*2)}</a>
  17. ${node_treeview_for_set_parent_menu(node_id, new_parent_node.getStaticChildList(), indentation+1)}
  18. </li>
  19. % endfor
  20. </ul>
  21. % endif
  22. % endif
  23. </%def>
  24. <%def name="node_treeview(node_list, indentation=-1)">
  25. % if indentation==-1:
  26. <div id='pod-menu-item-0' class="pod-toolbar-parent" style="padding-left: 0.5em; position: relative;">
  27. <a class="toggle-child-menu-items"><i class='fa fa-folder-open'></i></a>
  28. <a href="?node=0" title="${_('Root')}">
  29. ${_('Root')}
  30. </a>
  31. <div class="pod-toolbar">
  32. <a href="${tg.url('/api/create_document?parent_id=0')}" title="${_('Add child document')}"><i class="fa fa-plus-circle"></i></a>
  33. </div>
  34. </div>
  35. <div id="pod-menu-item-0-children">${node_treeview(node_list, 0)}</div>
  36. % else:
  37. % if len(node_list)>0:
  38. % for node in node_list:
  39. <div id='pod-menu-item-${node.node_id}' class="pod-toolbar-parent ${'pod-status-active' if node.node_id==current_node.node_id else ''}" style="padding-left: ${(indentation+2)*0.5}em; position: relative;">
  40. <a class="toggle-child-menu-items"><i class='${node.getIconClass()}'></i></a>
  41. <a href="${tg.url('/document/%s'%(node.node_id))}" title="${node.data_label}">
  42. % if node.getStatus().status_family=='closed' or node.getStatus().status_family=='invisible':
  43. <strike>
  44. % endif
  45. ${node.getTruncatedLabel(32-0.8*(indentation+1))}
  46. % if node.getStatus().status_family=='closed' or node.getStatus().status_family=='invisible':
  47. </strike>
  48. % endif
  49. </a>
  50. <div class="pod-toolbar">
  51. <a href="${tg.url('/api/move_node_upper?node_id=%i'%(node.node_id))}" title="${_('Move up')}"><i class="fa fa-arrow-up"></i></a>
  52. <a href="${tg.url('/api/move_node_lower?node_id=%i'%(node.node_id))}" title="${_('Move down')}"><i class="fa fa-arrow-down"></i></a>
  53. <a href="${tg.url('/api/create_document?parent_id=%i'%(node.node_id))}" title="${_('Add child document')}"><i class="fa fa-plus-circle"></i></a>
  54. </div>
  55. <div class="pod-status ${node.getStatus().css}" title='${node.getStatus().label}'>
  56. <i class='${node.getStatus().icon}'></i>
  57. </div>
  58. </div>
  59. <div id="pod-menu-item-${node.node_id}-children">${node_treeview(node.getStaticChildList(), indentation+1)}</div>
  60. % endfor
  61. % endif
  62. % endif
  63. </%def>
  64. <%def name="node_treeview_in_select_field(node_list, indentation, selected_id=0)">
  65. % if len(node_list)>0:
  66. % if indentation==0:
  67. <option style="margin-left: ${0.5*indentation}em; color: #CCC;" value="0">no parent...</option>
  68. % endif
  69. % for node in node_list:
  70. % if selected_id!=node.node_id:
  71. <option style="margin-left: ${0.5*indentation}em;" value="${node.node_id}">${node.data_label}</option>
  72. % else:
  73. <option style="margin-left: ${0.5*indentation}em;" value="${node.node_id}" selected>${node.data_label}</option>
  74. % endif
  75. ${node_treeview_in_select_field(node.getChildren(), indentation+1, selected_id)}
  76. % endfor
  77. % endif
  78. </%def>
  79. <div class="row">
  80. <div id='application-left-panel' class="span3">
  81. <div>
  82. ${node_treeview(root_node_list)}
  83. </div>
  84. </div>
  85. <div id='application-main-panel' class="span9">
  86. % if current_node.parent_id!=None and current_node.parent_id!=0:
  87. <div class="btn-group">
  88. <a class="btn " href="${tg.url('/document/%i'%current_node.parent_id)}" title="${_("Go to parent document")}"><i class="fa fa-hand-o-left"></i></a>
  89. </div>
  90. % endif
  91. <div class="btn-group">
  92. <button class="btn" data-toggle="dropdown" href="#">${_("Change status")}</button>
  93. <a class="btn dropdown-toggle" data-toggle="dropdown" href="#"><span class="caret"></span></a>
  94. <ul class="dropdown-menu">
  95. % for node_status in node_status_list:
  96. % if node_status.status_id==current_node.getStatus().status_id:
  97. <li title="${h.getExplanationAboutStatus(node_status.status_id, current_node.getStatus().status_id)}">
  98. <a class="${node_status.css}" href="#" style="color: #999;">
  99. <i class="${node_status.icon_id}"></i> ${node_status.label}
  100. </a>
  101. </li>
  102. % else:
  103. <li title="${h.getExplanationAboutStatus(node_status.status_id, current_node.getStatus().status_id)}">
  104. <a class="${node_status.css}" href="${tg.url('/api/edit_status?node_id=%i&node_status=%s'%(current_node.node_id, node_status.status_id))}">
  105. <i class="${node_status.icon_id}"></i> ${node_status.label}
  106. </a>
  107. </li>
  108. % endif
  109. % endfor
  110. </ul>
  111. </div>
  112. <div class="btn-group">
  113. ${POD.EditButton('current-document-content-edit-button', True)}
  114. <a class="btn" href="#" data-toggle="dropdown"><i class="icon-g-move"></i> ${_('Move to')} <span class="caret"></span></a>
  115. <ul class="dropdown-menu">
  116. ${node_treeview_for_set_parent_menu(current_node.node_id, root_node_list)}
  117. </ul>
  118. <a href='${tg.url('/api/edit_status?node_id=%i&node_status=%s'%(current_node.node_id, 'deleted'))}' id='current-document-force-delete-button' class="btn" onclick="return confirm('${_('Delete current document?')}');"><i class="fa fa-trash-o"></i> ${_('Delete')}</a>
  119. </div>
  120. <div class="row">
  121. <div id='application-document-panel' class="span5">
  122. <p>
  123. <div id='current-document-content' class="">
  124. <h3 id="current-document-title">#${current_node.node_id} - ${current_node.data_label}
  125. <span class="label ${current_node.getStatus().css}" href="#">${current_node.getStatus().label}</a>
  126. </h3>
  127. ${current_node.getContentWithTags()|n}
  128. </div>
  129. <form style='display: none;' id="current-document-content-edit-form" method='post' action='${tg.url('/api/edit_label_and_content')}'>
  130. <input type='hidden' name='node_id' value='${current_node.node_id}'/>
  131. <input type="hidden" name='data_content' id="current_node_textarea" />
  132. <input type='text' name='data_label' value='${current_node.data_label}' class="span4" placeholder="document title" />
  133. ${POD.RichTextEditor('current_node_textarea_wysiwyg', current_node.data_content)}
  134. ${POD.CancelButton('current-document-content-edit-cancel-button', True)}
  135. ${POD.SaveButton('current-document-content-edit-save-button', True)}
  136. </form>
  137. </p>
  138. </div>
  139. ## FIXME - D.A - 2013-11-07 - The following div should be span4 instead of span3 but some bug make it impossible
  140. <div id='application-metadata-panel' class="span4">
  141. <div class="tabbable">
  142. <ul class="nav nav-tabs">
  143. ## FIXME - D.A. - 2013-11-07 - TO REMOVE OR TO REACTIVATE <li class="active"><a href="#tags" data-toggle="tab" title="${_('Tags')}"><i class='icon-g-tags'></i></a></li>
  144. <li class="active"><a href="#events" data-toggle="tab" title="History"><i class="pod-dark-grey fa fa-calendar"></i>${POD.ItemNb(current_node.getEvents())}</a></li>
  145. <li><a href="#contacts" data-toggle="tab" title="Contacts"><i class="pod-dark-grey fa fa-user"></i>${POD.ItemNb(current_node.getContacts())}</a></li>
  146. <li><a href="#comments" data-toggle="tab" title="Comments"><i class="pod-dark-grey fa fa-comments-o"></i>${POD.ItemNb(current_node.getComments())}</a></li>
  147. <li><a href="#files" data-toggle="tab" title="Files"><i class="pod-dark-grey fa fa-file-text-o"></i>${POD.ItemNb(current_node.getFiles())}</a></li>
  148. </ul>
  149. <div class="tab-content">
  150. ################################
  151. ##
  152. ## PANEL SHOWING LIST OF TAGS
  153. ##
  154. ################################
  155. <!-- DEBUG - D.A. - 2013-11-07 - Not using tags for th moment
  156. <div class="tab-pane" id="tags">
  157. <div class="well">
  158. <p>
  159. <i>
  160. ${_('Tags are automatically extracted from document content:')}
  161. <ul>
  162. <li>${_('<code>@visible_keyword</code> is a visible keyword generating a tag.')|n}</li>
  163. <li>
  164. ${_('<code>@invisible_keyword</code> is an <u>invisible</u> keyword generating a tag.')|n}</li>
  165. </ul>
  166. </i>
  167. </p>
  168. % for tag in current_node.getTagList():
  169. ${POD.Badge(tag)}
  170. % endfor
  171. </div>
  172. </div>
  173. -->
  174. ################################
  175. ##
  176. ## PANEL SHOWING LIST OF EVENTS
  177. ##
  178. ################################
  179. <div class="tab-pane active" id="events">
  180. ${POD.AddButton('current-document-add-event-button', True, _(' Add event'))}
  181. <form style='display: none;' id='current-document-add-event-form' action='${tg.url('/api/create_event')}' method='post' class="well">
  182. <input type="hidden" name='parent_id' value='${current_node.node_id}'/>
  183. <fieldset>
  184. <legend>Add an event</legend>
  185. <label>
  186. <input type="text" name='data_label' placeholder="Event"/>
  187. </label>
  188. <label>
  189. <div class="datetime-picker-input-div input-append date">
  190. <input name='data_datetime' data-format="dd/MM/yyyy hh:mm" type="text" placeholder="date and time"/>
  191. <span class="add-on"><i data-time-icon="icon-g-clock" data-date-icon="icon-g-calendar"></i></span>
  192. </div>
  193. </label>
  194. <label>
  195. <div>
  196. <input type="hidden" id="add_event_data_content_textarea" name='data_content' />
  197. ${POD.RichTextEditor('add_event_data_content_textarea_wysiwyg', '', 'boldanditalic|undoredo|fullscreen')}
  198. </div>
  199. </label>
  200. <label class="checkbox">
  201. <input disabled name='add_reminder' type="checkbox"> add a reminder
  202. </label>
  203. <label>
  204. <div class="datetime-picker-input-div input-append date">
  205. <input disabled name='data_reminder_datetime' data-format="dd/MM/yyyy hh:mm" type="text" placeholder="date and time"/>
  206. <span class="add-on"><i data-time-icon="icon-g-clock" data-date-icon="icon-g-calendar"></i></span>
  207. </div>
  208. </label>
  209. ${POD.CancelButton('current-document-add-event-cancel-button', True)}
  210. ${POD.SaveButton('current-document-add-event-save-button', True)}
  211. </fieldset>
  212. </form>
  213. % if len(current_node.getEvents())<=0:
  214. <p><i>${_('No history for the moment.')}</i></p>
  215. % else:
  216. <table class="table table-striped table-hover table-condensed">
  217. <thead>
  218. <tr>
  219. <th>Date</th>
  220. <th>Time</th>
  221. <th>
  222. Event
  223. </th>
  224. <th>
  225. <a href="" title="Add an event"><i class="icon-g-plus"></i></a>
  226. </th>
  227. </tr>
  228. </thead>
  229. % for event in current_node.getEvents():
  230. <tr class="item-with-data-popoverable" data-content="${event.data_content}" rel="popover" data-placement="left" data-trigger="hover">
  231. <td>${event.getFormattedDate(event.data_datetime)}</td>
  232. <td>${event.getFormattedTime(event.data_datetime)}</td>
  233. <td>${event.data_label}</td>
  234. </tr>
  235. ## FIXME <script>
  236. ## $('.item-with-data-popoverable').popover({ html: true});
  237. ## </script>
  238. % endfor
  239. </table>
  240. % endif
  241. </div>
  242. ##############################
  243. ##
  244. ## PANEL SHOWING LIST OF CONTACTS
  245. ##
  246. ##############################
  247. <div class="tab-pane" id="contacts">
  248. <!-- ADD CONTACT FORM -->
  249. ${POD.AddButton('current-document-add-contact-button', True, _(' Add contact'))}
  250. <form style='display: none;' id='current-document-add-contact-form' action='${tg.url('/api/create_contact')}' method='post' class="well">
  251. <input type="hidden" name='parent_id' value='${current_node.node_id}'/>
  252. <fieldset>
  253. <legend>${_('Add a contact')}</legend>
  254. <label>
  255. <input type="text" name='data_label' placeholder="Title"/>
  256. </label>
  257. <label>
  258. <div>
  259. <input type="hidden" id="add_contact_data_content_textarea" name='data_content' />
  260. ${POD.RichTextEditor('add_contact_data_content_textarea_wysiwyg', '', 'boldanditalic|undoredo|fullscreen')}
  261. </div>
  262. </label>
  263. ${POD.CancelButton('current-document-add-contact-cancel-button', True)}
  264. ${POD.SaveButton('current-document-add-contact-save-button', True)}
  265. </fieldset>
  266. </form>
  267. <!-- LIST OF CONTACT NODES -->
  268. % for contact in current_node.getContacts():
  269. <div class="well">
  270. <legend class="text-info">
  271. ${contact.data_label}
  272. ## TODO - 2013-11-20 - Use the right form in order to update meta-data
  273. <a class="pull-right" href="${tg.url('/document/%i'%contact.node_id)}"><i class="fa fa-edit"></i></a>
  274. </legend>
  275. <div>
  276. ## FIXME - D.A. - 2013-11-15 - Implement localisation stuff <a style='float: right;' href="" title='${_('Search on google maps')}'><i class='icon-g-google-maps'></i></a>
  277. ${contact.data_content|n}
  278. </div>
  279. </div>
  280. % endfor
  281. </div>
  282. ################################
  283. ##
  284. ## PANEL SHOWING LIST OF COMMENTS
  285. ##
  286. ################################
  287. <div class="tab-pane" id="comments">
  288. <!-- ADD COMMENT FORM -->
  289. ${POD.AddButton('current-document-add-comment-button', True, _(' Add comment'))}
  290. <form style='display: none;' id='current-document-add-comment-form' action='${tg.url('/api/create_comment')}' method='post' class="well">
  291. <input type="hidden" name='parent_id' value='${current_node.node_id}'/>
  292. <fieldset>
  293. <legend>${_('Add a comment')}</legend>
  294. <label>
  295. <input type="text" name='data_label' placeholder="Title"/>
  296. </label>
  297. <label>
  298. <div>
  299. <input type="hidden" id="add_comment_data_content_textarea" name='data_content' />
  300. ${POD.RichTextEditor('add_comment_data_content_textarea_wysiwyg', '', 'boldanditalic|undoredo|fullscreen')}
  301. </div>
  302. </label>
  303. ${POD.CancelButton('current-document-add-comment-cancel-button', True)}
  304. ${POD.SaveButton('current-document-add-comment-save-button', True)}
  305. </fieldset>
  306. </form>
  307. <!-- LIST OF COMMENTS -->
  308. % if len(current_node.getComments())<=0:
  309. <p><i>${_('No comments.')}</i></p>
  310. % else:
  311. <table class="table table-striped table-hover table-condensed">
  312. % for comment in current_node.getComments():
  313. <tr title="Last updated: ${comment.updated_at}">
  314. <td>
  315. <i>The ${comment.getFormattedDate(comment.updated_at)} at ${comment.getFormattedTime(comment.updated_at)}: </i><br/>
  316. <b>${comment.data_label}</b>
  317. ## TODO - 2013-11-20 - Use the right form in order to update meta-data
  318. <a class="pull-right" href="${tg.url('/document/%i'%comment.node_id)}"><i class="fa fa-edit"></i></a>
  319. <br/>
  320. <p>
  321. ${comment.data_content|n}
  322. </p>
  323. </td>
  324. </tr>
  325. % endfor
  326. </table>
  327. % endif
  328. </div>
  329. ################################
  330. ##
  331. ## PANEL SHOWING LIST OF FILES
  332. ##
  333. ################################
  334. <div class="tab-pane" id="files">
  335. <!-- ADD FILE FORM -->
  336. ${POD.AddButton('current-document-add-file-button', True, _(' Add file'))}
  337. <form style='display: none;' id='current-document-add-file-form' enctype="multipart/form-data" action='${tg.url('/api/create_file')}' method='post' class="well">
  338. <input type="hidden" name='parent_id' value='${current_node.node_id}'/>
  339. <fieldset>
  340. <legend>${_('Add a file')}</legend>
  341. <label>
  342. <input type="text" name='data_label' placeholder="Title"/>
  343. </label>
  344. <label>
  345. <input type="file" name='data_file' placeholder="choose a file..."/>
  346. </label>
  347. <label>
  348. <div>
  349. <input type="hidden" id="add_file_data_content_textarea" name='data_content' />
  350. ${POD.RichTextEditor('add_file_data_content_textarea_wysiwyg', '', 'boldanditalic|undoredo|fullscreen')}
  351. </div>
  352. </label>
  353. ${POD.CancelButton('current-document-add-file-cancel-button', True)}
  354. ${POD.SaveButton('current-document-add-file-save-button', True)}
  355. </fieldset>
  356. </form>
  357. <!-- LIST OF FILES -->
  358. % if len(current_node.getFiles())<=0:
  359. <p><i>${_('No files.')}</i></p>
  360. % else:
  361. <table class="table table-striped table-hover table-condensed">
  362. % for current_file in current_node.getFiles():
  363. <tr title="Last updated: ${current_file.updated_at}">
  364. <td>
  365. <a href="${tg.url('/api/get_file_content/%s'%(current_file.node_id))}" title="${_("Download file")}">
  366. <i class="fa fa-2x fa-file-text-o"></i>
  367. </a>
  368. ## FIXME - SHOW THUMBNAIL WHEN IT WILL BE OK<img src="${tg.url('/api/get_file_content_thumbnail/%s'%(current_file.node_id))}" class="img-polaroid">
  369. </td>
  370. <td>
  371. <b>${current_file.data_label}</b>
  372. <a class="pull-right" href="${tg.url('/api/get_file_content/%s'%(current_file.node_id))}" title="${_("Download file")}">
  373. <i class="fa fa-download"></i>
  374. </a>
  375. <a class="pull-right" href="${tg.url('/document/%i'%current_file.node_id)}" title="${_("Edit title or comment")}"><i class="fa fa-edit"></i></a>
  376. <br/>
  377. <p>
  378. ${current_file.data_content|n}
  379. </p>
  380. </td>
  381. </tr>
  382. % endfor
  383. </table>
  384. % endif
  385. </div>
  386. </div>
  387. </div>
  388. </div>
  389. </div>
  390. </div>
  391. </div>
  392. </div>