user_workspace_widgets.mak 19KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411
  1. <%namespace name="TIM" file="tracim.templates.pod"/>
  2. <%namespace name="ICON" file="tracim.templates.widgets.icon"/>
  3. <%def name="BREADCRUMB(dom_id, breadcrumb_items)">
  4. <ul id="${dom_id}" class="breadcrumb" style="margin-top: -1.5em; display: none;">
  5. % for item in breadcrumb_items:
  6. % if item.is_active:
  7. <li class="active">${TIM.ICO(16, item.icon)} ${item.label}</li>
  8. % else:
  9. <li>${TIM.ICO(16, item.icon)} <a href="${item.url}">${item.label}</a></li>
  10. % endif
  11. % endfor
  12. </ul>
  13. </%def>
  14. <%def name="EMPTY_CONTENT(empty_content_label)"><p class="pod-empty">${empty_content_label|n}</p></%def>
  15. <%def name="DATA_TARGET_BUTTON(dom_id, label)"><a data-toggle="collapse" data-target="#${dom_id}"><b>${label}</b></a></%def>
  16. <%def name="SECURED_SECTION_TITLE(user, workspace, dom_id, label, action_dom_id='', action_label='', icon_size='', icon_path='')">
  17. <h4 id="${dom_id}">
  18. ${TIM.ICO(icon_size, icon_path) if icon_path else ''}
  19. ${label}
  20. ## Button is shown for contributors (or more), not for readers
  21. % if h.user_role(user, workspace)>1:
  22. % if action_dom_id and action_label:
  23. <small style="margin-left: 1em;"> ${DATA_TARGET_BUTTON(action_dom_id, action_label)}</small>
  24. % endif
  25. % endif
  26. </h4>
  27. </%def>
  28. <%def name="FOLDER_LIST(dom_id, workspace_id, folders)">
  29. % if len(folders)<=0:
  30. ${EMPTY_CONTENT(_('No folder found.'))|n}
  31. % else:
  32. <table id="${dom_id}" class="table table-striped table-hover">
  33. % for folder in folders:
  34. <tr>
  35. <td><a href="${tg.url('/workspaces/{}/folders/{}'.format(workspace_id, folder.id))}">${TIM.ICO(16, 'places/jstree-folder')} ${folder.label}</a></td>
  36. <td>
  37. % if folder.content_nb.all==0:
  38. <span class="pod-empty-item">${_('This folder is empty')}</span>
  39. % else:
  40. % if folder.folder_nb.all>=1:
  41. ${_('{nb_total} subfolder(s)').format(nb_total=folder.folder_nb.all)|n}
  42. % endif
  43. % if folder.thread_nb.all>=1:
  44. ${_('{nb_total} thread(s) &mdash; {nb_open} open').format(nb_total=folder.thread_nb.all, nb_open=folder.thread_nb.open)|n}
  45. <br/>
  46. % endif
  47. % if folder.file_nb.all>=1:
  48. ${_('{nb_total} file(s) &mdash; {nb_open} open').format(nb_total=folder.file_nb.all, nb_open=folder.file_nb.open)|n}
  49. <br/>
  50. % endif
  51. % if folder.page_nb.all>=1:
  52. ${_('{nb_total} page(s) &mdash; {nb_open} open').format(nb_total=folder.page_nb.all, nb_open=folder.page_nb.open)|n}
  53. <br/>
  54. % endif
  55. % endif
  56. </td>
  57. </tr>
  58. % endfor
  59. </table>
  60. % endif
  61. </%def>
  62. <%def name="PAGE_LIST(dom_id, workspace_id, pages)">
  63. % if len(pages)<=0:
  64. ${EMPTY_CONTENT(_('No page found.'))}
  65. % else:
  66. <table id="${dom_id}" class="table table-striped table-hover">
  67. <tr>
  68. <th>${_('Type')}</th>
  69. <th>${_('Title')}</th>
  70. <th colspan="2">${_('Status')}</th>
  71. </tr>
  72. % for page in pages:
  73. <tr>
  74. <td>
  75. <span class="tracim-less-visible"><i class="fa fa-file-text-o fa-tw"></i> page</span>
  76. </td>
  77. <td>
  78. <a href="${tg.url('/workspaces/{}/folders/{}/pages/{}'.format(workspace_id, page.folder.id, page.id))}">${page.label}</a>
  79. </td>
  80. <td>
  81. % if 'open' == page.status.id:
  82. <i class="fa fa-fw fa-square-o"></i>
  83. % elif 'closed-validated' == page.status.id:
  84. <i class="fa fa-fw fa-check-square-o"></i>
  85. % elif 'closed-unvalidated' == page.status.id:
  86. <i class="fa fa-fw fa-check-square-o"></i>
  87. % elif 'closed-deprecated' == page.status.id:
  88. <i class="fa fa-fw fa-bell-slash-o"></i>
  89. % else:
  90. <i class="fa fa-fw fa-close"></i>
  91. % endif
  92. </td>
  93. <td>
  94. ${page.status.label}
  95. ## ${page.status.id}
  96. ## ${TIM.ICO(16, page.status.icon)} <span class="${page.status.css}">${page.status.label}</span>
  97. </td>
  98. </tr>
  99. % endfor
  100. </table>
  101. % endif
  102. </%def>
  103. <%def name="FILE_LIST(dom_id, workspace_id, files)">
  104. % if len(files)<=0:
  105. ${EMPTY_CONTENT(_('No file found.'))}
  106. % else:
  107. <table id="${dom_id}" class="table table-striped table-hover">
  108. % for curfile in files:
  109. <tr>
  110. <td><a href="${tg.url('/workspaces/{}/folders/{}/files/{}'.format(workspace_id, curfile.folder.id, curfile.id))}">${TIM.ICO(16, 'mimetypes/text-html')} ${curfile.label}</a></td>
  111. <td>
  112. ${TIM.ICO(16, curfile.status.icon)} <span class="${curfile.status.css}">${curfile.status.label}</span>
  113. </td>
  114. </tr>
  115. % endfor
  116. </table>
  117. % endif
  118. </%def>
  119. <%def name="THREAD_LIST(dom_id, workspace_id, threads)">
  120. % if len(threads)<=0:
  121. ${EMPTY_CONTENT(_('No thread found.'))}
  122. % else:
  123. <table id="${dom_id}" class="table table-striped table-hover">
  124. % for thread in threads:
  125. <tr>
  126. <td><a href="${tg.url('/workspaces/{}/folders/{}/threads/{}'.format(workspace_id, thread.folder.id, thread.id))}">${TIM.ICO(16, 'apps/internet-group-chat')} ${thread.label}</a></td>
  127. <td>${TIM.ICO(16, thread.status.icon)} <span class="${thread.status.css}">${thread.status.label}</span></td>
  128. <td>${_('{} message(s)').format(thread.comment_nb)}</td>
  129. </tr>
  130. % endfor
  131. </table>
  132. % endif
  133. </%def>
  134. <%def name="TREEVIEW(dom_id, selected_id='', uniq_workspace='0')">
  135. <%
  136. get_root_url = tg.url("/workspaces/treeview_root", dict(current_id=selected_id))
  137. get_children_url = tg.url("/workspaces/treeview_children")
  138. %>
  139. ${TREEVIEW_DYNAMIC(dom_id, selected_id, get_root_url, get_children_url)}
  140. </%def>
  141. <%def name="TREEVIEW_DYNAMIC(dom_id, selected_id, get_root_url, get_children_url, mode='link_to_document', updatable_field_id=None)">
  142. ## If mode is 'link to document', then a click on a tree item will open the given document as main page
  143. ## If mode is 'move_mode', then a click will update the value of hidden field with dom id: '${dom_id}-treeview-hidden-field'
  144. ## TODO - D.A. - 2014-09-25 - Select default node
  145. <div id="${dom_id}">
  146. <div id="${dom_id}-treeview"></div>
  147. % if not updatable_field_id:
  148. <input type='hidden' id='${dom_id}-treeview-hidden-field' name='folder_id' value=''/>
  149. % endif
  150. <script>
  151. $(function () {
  152. $('#${dom_id}-treeview').jstree({
  153. 'plugins' : [ 'wholerow', 'types' ],
  154. "types" : {
  155. "default" : {
  156. "icon" : "fa fa-folder-open-o t-folder-color"
  157. },
  158. "page" : {
  159. "icon" : "fa fa-file-text-o t-page-color"
  160. },
  161. "file" : {
  162. "icon" : "fa fa-paperclip t-file-color"
  163. },
  164. "thread" : {
  165. "icon" : "fa fa-comments-o t-thread-color"
  166. },
  167. "workspace" : {
  168. "icon" : "fa fa-bank"
  169. },
  170. },
  171. 'core' : {
  172. 'error': function (error) {
  173. console.log('Error ' + error.toString())
  174. },
  175. 'data' : {
  176. 'dataType': 'json',
  177. 'contentType': 'application/json; charset=utf-8',
  178. 'url' : function (node) {
  179. if (node.id==='#') {
  180. return '${get_root_url|n}'
  181. } else {
  182. return '${get_children_url|n}'
  183. }
  184. },
  185. 'data' : function(node) {
  186. console.log("NODE => "+JSON.stringify(node))
  187. return {
  188. 'id' : node.id
  189. };
  190. },
  191. 'success': function (new_data) {
  192. console.log('loaded new menu data' + JSON.stringify(new_data))
  193. return new_data;
  194. },
  195. },
  196. }
  197. });
  198. ##
  199. ## INFO - D.A. - 2014-10-17
  200. ## Look comment at top of this function in order to get information about the next if/then/else
  201. ##
  202. % if mode=='link_to_document':
  203. $('#${dom_id}-treeview').on("select_node.jstree", function (e, data) {
  204. // click event is intercepted, so we fake a click() by getting the href value
  205. // of child link and put it as current document location
  206. url = $('#'+data.selected[0]+' > a').attr('href');
  207. location.href = url;
  208. });
  209. % else:
  210. $('#${dom_id}-treeview').on("select_node.jstree", function (e, data) {
  211. // on click, the form hidden field is updated
  212. ## FIXME - REMOVE alert('about to update value of field '+'#${dom_id}-treeview-hidden-field');
  213. ## FIXME - REMOVE alert('new value will be '+$('#'+data.selected[0]+' > a').attr('id'));
  214. ## FIXME - REMOVE alert('data is '+data.selected[0]+ ' => '+$('#'+data.selected[0]+' > a')[0]);
  215. % if not updatable_field_id:
  216. $('#${dom_id}-treeview-hidden-field').val(data.selected[0]);
  217. % else: # in this case, we will update another hidden field
  218. $('#${updatable_field_id}').val(data.selected[0]);
  219. % endif
  220. });
  221. % endif
  222. $('#${dom_id}-treeview').on("loaded.jstree", function () {
  223. nodes = $('#${dom_id}-treeview .jstree-node');
  224. console.log("nodes = "+nodes.length);
  225. if (nodes.length<=0) {
  226. ## TODO - D.A. - 2014-11-06 - Parameterize the fake_api.current_user access
  227. $("#${dom_id}-treeview").append( "<p class='pod-grey'>${_('You have no workspace.')|n}" );
  228. % if fake_api.current_user.profile.id >= 2:
  229. $("#${dom_id}-treeview").append( "<p><a class=\"btn btn-success\" href=\"${tg.url('/admin/workspaces')}\" ><i class=\"fa fa-plus\"></i> ${_('Create a workspace')}</a></p>" );
  230. % else:
  231. $("#${dom_id}-treeview").append( "<p class=\"alert alert-info\"><b>${_('Contact the administrator.')}</b></p>" );
  232. % endif
  233. }
  234. });
  235. });
  236. </script>
  237. </div>
  238. </%def>
  239. <%def name="SECURED_SHOW_CHANGE_STATUS_FOR_FILE(user, workspace, item)">
  240. <% target_url = tg.url('/workspaces/{wid}/folders/{fid}/files/{pid}/put_status?status={{status_id}}').format(wid=item.workspace.id, fid=item.parent.id, pid=item.id) %>
  241. <% allow_status_change = h.user_role(user, workspace)>=2 and item.selected_revision=='latest' %>
  242. ${SHOW_CHANGE_STATUS(item, target_url, allow_status_change)}
  243. </%def>
  244. <%def name="SECURED_SHOW_CHANGE_STATUS_FOR_PAGE(user, workspace, item)">
  245. <% target_url = tg.url('/workspaces/{wid}/folders/{fid}/pages/{pid}/put_status?status={{status_id}}').format(wid=item.workspace.id, fid=item.parent.id, pid=item.id) %>
  246. <% allow_status_change = h.user_role(user, workspace)>=2 and item.selected_revision=='latest' %>
  247. ${SHOW_CHANGE_STATUS(item, target_url, allow_status_change)}
  248. </%def>
  249. <%def name="SECURED_SHOW_CHANGE_STATUS_FOR_THREAD(user, workspace, item)">
  250. <% target_url = tg.url('/workspaces/{wid}/folders/{fid}/threads/{pid}/put_status?status={{status_id}}').format(wid=item.workspace.id, fid=item.parent.id, pid=item.id) %>
  251. <% allow_status_change = h.user_role(user, workspace)>=2 and item.selected_revision=='latest' %>
  252. ## The user can't change status if he is a simple reader
  253. ${SHOW_CHANGE_STATUS(item, target_url, allow_status_change)}
  254. </%def>
  255. <%def name="SHOW_CHANGE_STATUS(item, target_url, allow_to_change_status=False)">
  256. <div class="btn-group pull-right">
  257. % if not allow_to_change_status:
  258. <button type="button" class="btn btn-default disable btn-link" title="${_('This operation is locked')}">
  259. <span class="${item.status.css}">${item.status.label} ${ICON.FA_FW_2X(item.status.icon)}</span>
  260. </button>
  261. % else:
  262. <button type="button" class="btn btn-default btn-link dropdown-toggle" data-toggle="dropdown">
  263. <span class="${item.status.css}">${item.status.label} ${ICON.FA_FW_2X(item.status.icon)}</span>
  264. </button>
  265. <ul class="dropdown-menu" role="menu">
  266. % for status in h.AllStatus(item.type):
  267. % if status.id == 'closed-deprecated':
  268. <li class="divider"></li>
  269. % endif
  270. <li class="text-right"><a
  271. class="${('', 'pod-status-selected')[status.id==item.status.id]}"
  272. href="${target_url.format(status_id=status.id)}">
  273. <span class="${status.css}">
  274. ${status.label} ${ICON.FA_FW(status.icon)}
  275. </span>
  276. </a></li>
  277. % endfor
  278. </ul>
  279. % endif
  280. </div>
  281. </%def>
  282. <%def name="SECURED_TIMELINE_ITEM(user, item)">
  283. ## <% created_localized = h.get_with_timezone(item.created) %>
  284. ## <div class="row t-odd-or-even t-hacky-thread-comment-border-top">
  285. ## <div class="col-sm-7 col-sm-offset-3">
  286. ## <div class="t-timeline-item">
  287. ## ## <i class="fa fa-fw fa-3x fa-comment-o t-less-visible" style="margin-left: -1.5em; float:left;"></i>
  288. ## ${ICON.FA_FW('fa fa-3x fa-comment-o t-less-visible t-timeline-item-icon')}
  289. ##
  290. ## <h5 style="margin: 0;">
  291. ## <span class="tracim-less-visible">${_('<strong>{}</strong> wrote:').format(item.owner.name)|n}</span>
  292. ##
  293. ## <div class="pull-right text-right t-timeline-item-moment" title="${h.date_time(created_localized)|n}">
  294. ## ${_('{delta} ago').format(delta=item.created_as_delta)}
  295. ##
  296. ## % if h.is_item_still_editable(item) and item.owner.id==user.id:
  297. ## <br/>
  298. ## ## <div class="btn-group">
  299. ## <a class="t-timeline-comment-delete-button" href="${item.urls.delete}">
  300. ## ${_('delete')} ${ICON.FA('fa fa-trash-o')}
  301. ## ## ${TIM.ICO_TOOLTIP(16, 'status/user-trash-full', h.delete_label_for_item(item))}
  302. ## </a>
  303. ## ## </div>
  304. ## % endif
  305. ## </div>
  306. ## </h5>
  307. ## <div class="t-timeline-item-content">
  308. ## <div>${item.content|n}</div>
  309. ## <br/>
  310. ## </div>
  311. ## </div>
  312. ## </div>
  313. ## </div>
  314. </%def>
  315. <%def name="SECURED_HISTORY_VIRTUAL_EVENT(user, event)">
  316. <% created_localized = h.get_with_timezone(event.created) %>
  317. <% is_new_css_class = 't-is-new-content' if event.is_new else '' %>
  318. <div class="t-odd-or-even t-hacky-thread-comment-border-top ${is_new_css_class}">
  319. <div class="">
  320. <div class="t-timeline-item">
  321. ## <i class="fa fa-fw fa-3x fa-comment-o t-less-visible" style="margin-left: -1.5em; float:left;"></i>
  322. ${ICON.FA_FW('fa fa-3x t-less-visible t-timeline-item-icon '+event.type.icon)}
  323. <h5 style="margin: 0;">
  324. % if 'comment' == event.type.id:
  325. <span class="tracim-less-visible">${_('<strong>{}</strong> wrote:').format(event.owner.name)|n}</span>
  326. %else:
  327. <span class="tracim-less-visible">${_('{} by <strong>{}</strong>').format(event.label, event.owner.name)|n}</span>
  328. % endif
  329. <div class="pull-right text-right t-timeline-item-moment" title="${h.date_time(created_localized)|n}">
  330. ${_('{delta} ago').format(delta=event.created_as_delta)}
  331. % if h.is_item_still_editable(CFG, event) and event.owner.id==user.id:
  332. <br/>
  333. <a class="t-timeline-comment-delete-button" href="${event.urls.delete}">
  334. ${_('delete')} ${ICON.FA('fa fa-trash-o')}
  335. </a>
  336. % endif
  337. </div>
  338. </h5>
  339. <div class="t-timeline-item-content">
  340. <div>${event.content|n}</div>
  341. <br/>
  342. </div>
  343. </div>
  344. </div>
  345. </div>
  346. </%def>
  347. <%def name="SECURED_HISTORY_VIRTUAL_EVENT_AS_TABLE_ROW(user, event, current_revision_id)">
  348. <% created_localized = h.get_with_timezone(event.created) %>
  349. <%
  350. warning_or_not = ('', 'warning')[current_revision_id==event.id]
  351. row_css = 't-is-new-content' if event.is_new else warning_or_not
  352. %>
  353. <tr class="${row_css}">
  354. <td class="t-less-visible">
  355. <span class="label label-default">${ICON.FA_FW(event.type.icon)} ${event.type.label}</span>
  356. </td>
  357. <td title="${h.date_time(created_localized)|n}">${_('{delta} ago').format(delta=event.created_as_delta)}</td>
  358. <td>${event.owner.name}</td>
  359. ## FIXME - REMOVE <td>${event}</td>
  360. % if 'comment' == event.type.id:
  361. <td colspan="2">
  362. ${event.content|n}
  363. </td>
  364. % else:
  365. <td>
  366. % if event.type.id in ('creation', 'edition', 'revision'):
  367. <a href="${'?revision_id={}'.format(event.id)}">${_('View revision')}</a>
  368. % endif
  369. </td>
  370. <td class="t-less-visible" title="${_('Currently shown')}">
  371. % if warning_or_not:
  372. ${ICON.FA_FW('fa fa-caret-left')}&nbsp;${_('shown')}
  373. % endif
  374. </td>
  375. % endif
  376. </tr>
  377. </%def>