review-panel.pug 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628
  1. #review-panel
  2. .rp-in-editor-widgets
  3. a.rp-track-changes-indicator(
  4. href
  5. ng-if="editor.wantTrackChanges"
  6. ng-click="toggleReviewPanel();"
  7. ng-class="{ 'rp-track-changes-indicator-on-dark' : darkTheme }"
  8. ) !{translate("track_changes_is_on")}
  9. a.rp-bulk-actions-btn(
  10. href
  11. ng-if="reviewPanel.nVisibleSelectedChanges > 1"
  12. ng-click="showBulkAcceptDialog();"
  13. )
  14. i.fa.fa-check
  15. |  #{translate("accept_all")}
  16. | ({{ reviewPanel.nVisibleSelectedChanges }})
  17. a.rp-bulk-actions-btn(
  18. href
  19. ng-if="reviewPanel.nVisibleSelectedChanges > 1"
  20. ng-click="showBulkRejectDialog();"
  21. )
  22. i.fa.fa-times
  23. |  #{translate("reject_all")}
  24. | ({{ reviewPanel.nVisibleSelectedChanges }})
  25. if hasFeature('track-changes')
  26. a.rp-add-comment-btn(
  27. href
  28. ng-if="reviewPanel.entries[editor.open_doc_id]['add-comment'] != null && permissions.comment"
  29. ng-click="addNewComment();"
  30. )
  31. i.fa.fa-comment
  32. |  #{translate("add_comment")}
  33. a.review-panel-toggler(
  34. href
  35. ng-click="handleTogglerClick($event);"
  36. )
  37. .review-panel-toolbar
  38. resolved-comments-dropdown(
  39. class="rp-flex-block"
  40. entries="reviewPanel.resolvedComments"
  41. threads="reviewPanel.commentThreads"
  42. resolved-ids="reviewPanel.resolvedThreadIds"
  43. docs="docs"
  44. on-open="refreshResolvedCommentsDropdown();"
  45. on-unresolve="unresolveComment(threadId);"
  46. on-delete="deleteThread(entryId, docId, threadId);"
  47. is-loading="reviewPanel.dropdown.loading"
  48. permissions="permissions"
  49. )
  50. span.review-panel-toolbar-label
  51. span.review-panel-toolbar-icon-on(
  52. ng-if="editor.wantTrackChanges === true"
  53. )
  54. i.fa.fa-circle
  55. span(ng-click="toggleFullTCStateCollapse();")
  56. span(ng-if="editor.wantTrackChanges === false") !{translate("track_changes_is_off")}
  57. span(ng-if="editor.wantTrackChanges === true") !{translate("track_changes_is_on")}
  58. span.rp-tc-state-collapse(
  59. ng-class="{ 'rp-tc-state-collapse-on': reviewPanel.fullTCStateCollapsed }"
  60. )
  61. i.fa.fa-angle-down
  62. ul.rp-tc-state(
  63. review-panel-collapse-height="reviewPanel.fullTCStateCollapsed"
  64. )
  65. li.rp-tc-state-item.rp-tc-state-item-everyone
  66. span.rp-tc-state-item-name(
  67. tooltip=translate('tc_switch_everyone_tip')
  68. tooltip-placement="left"
  69. tooltip-append-to-body="true"
  70. tooltip-popup-delay="1000"
  71. ) !{translate("tc_everyone")}
  72. review-panel-toggle(
  73. description="Track changes for everyone"
  74. ng-model="reviewPanel.trackChangesOnForEveryone"
  75. on-toggle="toggleTrackChangesForEveryone(isOn);"
  76. is-disabled="!project.features.trackChanges || !permissions.write"
  77. )
  78. li.rp-tc-state-item(
  79. ng-repeat="member in reviewPanel.formattedProjectMembers"
  80. )
  81. span.rp-tc-state-item-name(
  82. ng-class="{ 'rp-tc-state-item-name-disabled' : reviewPanel.trackChangesOnForEveryone}"
  83. style="color: hsl({{ member.hue }}, 70%, 40%);"
  84. tooltip=translate('tc_switch_user_tip')
  85. tooltip-placement="left"
  86. tooltip-append-to-body="true"
  87. tooltip-popup-delay="1000"
  88. ) {{ member.name }}
  89. review-panel-toggle(
  90. description="Track changes for {{ member.name }}"
  91. ng-model="reviewPanel.trackChangesState[member.id].value"
  92. on-toggle="toggleTrackChangesForUser(isOn, member.id);"
  93. is-disabled="reviewPanel.trackChangesOnForEveryone || !project.features.trackChanges || !permissions.write"
  94. )
  95. li.rp-tc-state-separator
  96. li.rp-tc-state-item.rp-tc-state-item-guests
  97. span.rp-tc-state-item-name(
  98. ng-class="{ 'rp-tc-state-item-name-disabled' : reviewPanel.trackChangesOnForEveryone}"
  99. tooltip=translate('tc_switch_guests_tip')
  100. tooltip-placement="left"
  101. tooltip-append-to-body="true"
  102. tooltip-popup-delay="1000"
  103. ) !{translate("tc_guests")}
  104. review-panel-toggle(
  105. description="Track changes for guests"
  106. ng-model="reviewPanel.trackChangesOnForGuests"
  107. on-toggle="toggleTrackChangesForGuests(isOn);"
  108. is-disabled="reviewPanel.trackChangesOnForEveryone || !project.features.trackChanges || !permissions.write || !reviewPanel.trackChangesForGuestsAvailable"
  109. )
  110. .rp-entry-list(
  111. review-panel-sorted
  112. ng-if="reviewPanel.subView === SubViews.CUR_FILE"
  113. )
  114. .rp-entry-list-inner
  115. .rp-entry-wrapper(
  116. ng-repeat="(entry_id, entry) in reviewPanel.entries[editor.open_doc_id]"
  117. ng-if="entry.visible"
  118. )
  119. div(ng-if="entry.type === 'insert' || entry.type === 'delete'")
  120. change-entry(
  121. entry="entry"
  122. user="users[entry.metadata.user_id]"
  123. on-reject="rejectChanges(entry.entry_ids);"
  124. on-accept="acceptChanges(entry.entry_ids);"
  125. on-indicator-click="toggleReviewPanel();"
  126. on-body-click="gotoEntry(editor.open_doc_id, entry)"
  127. permissions="permissions"
  128. )
  129. div(ng-if="entry.type === 'aggregate-change'")
  130. aggregate-change-entry(
  131. entry="entry"
  132. user="users[entry.metadata.user_id]"
  133. on-reject="rejectChanges(entry.entry_ids);"
  134. on-accept="acceptChanges(entry.entry_ids);"
  135. on-indicator-click="toggleReviewPanel();"
  136. on-body-click="gotoEntry(editor.open_doc_id, entry)"
  137. permissions="permissions"
  138. )
  139. div(ng-if="entry.type === 'comment'")
  140. comment-entry(
  141. entry="entry"
  142. threads="reviewPanel.commentThreads"
  143. on-resolve="resolveComment(entry, entry_id)"
  144. on-reply="submitReply(entry, entry_id);"
  145. on-indicator-click="toggleReviewPanel();"
  146. on-save-edit="saveEdit(entry.thread_id, comment)"
  147. on-delete="deleteComment(entry.thread_id, comment)"
  148. on-body-click="gotoEntry(editor.open_doc_id, entry)"
  149. permissions="permissions"
  150. ng-if="!reviewPanel.loadingThreads"
  151. )
  152. div(ng-if="entry.type === 'add-comment' && permissions.comment")
  153. add-comment-entry(
  154. on-start-new="startNewComment();"
  155. on-submit="submitNewComment(content);"
  156. on-cancel="cancelNewComment();"
  157. )
  158. div(ng-if="entry.type === 'bulk-actions'")
  159. bulk-actions-entry(
  160. on-bulk-accept="showBulkAcceptDialog();"
  161. on-bulk-reject="showBulkRejectDialog();"
  162. n-entries="reviewPanel.nVisibleSelectedChanges"
  163. )
  164. .rp-entry-list(
  165. ng-if="reviewPanel.subView === SubViews.OVERVIEW"
  166. )
  167. .rp-loading(ng-if="reviewPanel.overview.loading")
  168. i.fa.fa-spinner.fa-spin
  169. .rp-overview-file(
  170. ng-repeat="doc in docs"
  171. ng-if="!reviewPanel.overview.loading"
  172. )
  173. .rp-overview-file-header(
  174. ng-if="(reviewPanel.entries[doc.doc.id] != null) && (reviewPanel.entries[doc.doc.id] | notEmpty)"
  175. ng-click="reviewPanel.overview.docsCollapsedState[doc.doc.id] = ! reviewPanel.overview.docsCollapsedState[doc.doc.id]"
  176. )
  177. span.rp-overview-file-header-collapse(
  178. ng-class="{ 'rp-overview-file-header-collapse-on': reviewPanel.overview.docsCollapsedState[doc.doc.id] }"
  179. )
  180. i.fa.fa-angle-down
  181. | {{ doc.path }}
  182. span.rp-overview-file-num-entries(
  183. ng-show="reviewPanel.overview.docsCollapsedState[doc.doc.id]"
  184. )  ({{ reviewPanel.entries[doc.doc.id] | numKeys }})
  185. .rp-overview-file-entries(
  186. review-panel-collapse-height="reviewPanel.overview.docsCollapsedState[doc.doc.id]"
  187. )
  188. .rp-entry-wrapper(
  189. ng-repeat="(entry_id, entry) in reviewPanel.entries[doc.doc.id] | orderOverviewEntries"
  190. ng-if="!(entry.type === 'comment' && reviewPanel.commentThreads[entry.thread_id].resolved === true)"
  191. )
  192. div(ng-if="entry.type === 'insert' || entry.type === 'delete'")
  193. change-entry(
  194. entry="entry"
  195. user="users[entry.metadata.user_id]"
  196. ng-click="gotoEntry(doc.doc.id, entry)"
  197. permissions="permissions"
  198. )
  199. div(ng-if="entry.type === 'aggregate-change'")
  200. aggregate-change-entry(
  201. entry="entry"
  202. user="users[entry.metadata.user_id]"
  203. ng-click="gotoEntry(editor.open_doc_id, entry)"
  204. permissions="permissions"
  205. )
  206. div(ng-if="entry.type === 'comment'")
  207. comment-entry(
  208. entry="entry"
  209. threads="reviewPanel.commentThreads"
  210. on-reply="submitReply(entry, entry_id);"
  211. on-save-edit="saveEdit(entry.thread_id, comment)"
  212. on-delete="deleteComment(entry.thread_id, comment)"
  213. ng-click="gotoEntry(doc.doc.id, entry)"
  214. permissions="permissions"
  215. )
  216. .rp-nav
  217. a.rp-nav-item(
  218. href
  219. ng-click="setSubView(SubViews.CUR_FILE);"
  220. ng-class="{ 'rp-nav-item-active' : reviewPanel.subView === SubViews.CUR_FILE }"
  221. )
  222. i.fa.fa-file-text-o
  223. span.rp-nav-label #{translate("current_file")}
  224. a.rp-nav-item(
  225. href
  226. ng-click="setSubView(SubViews.OVERVIEW);"
  227. ng-class="{ 'rp-nav-item-active' : reviewPanel.subView === SubViews.OVERVIEW }"
  228. )
  229. i.fa.fa-list
  230. span.rp-nav-label #{translate("overview")}
  231. .rp-unsupported-msg-wrapper
  232. .rp-unsupported-msg
  233. i.fa.fa-5x.fa-exclamation-triangle
  234. p.rp-unsupported-msg-title Track Changes support in rich text mode is a work in progress.
  235. p You can see tracked insertions and deletions, but you can't see comments and changes in this side bar yet.
  236. p We're working hard to add them as soon as they're ready.
  237. script(type='text/ng-template', id='changeEntryTemplate')
  238. div
  239. .rp-entry-callout(
  240. ng-class="'rp-entry-callout-' + entry.type"
  241. )
  242. .rp-entry-indicator(
  243. ng-switch="entry.type"
  244. ng-class="{ 'rp-entry-indicator-focused': entry.focused }"
  245. ng-click="onIndicatorClick();"
  246. )
  247. i.fa.fa-pencil(ng-switch-when="insert")
  248. i.rp-icon-delete(ng-switch-when="delete")
  249. .rp-entry(
  250. ng-class="[ 'rp-entry-' + entry.type, (entry.focused ? 'rp-entry-focused' : '')]"
  251. )
  252. .rp-entry-body
  253. .rp-entry-action-icon(ng-switch="entry.type")
  254. i.fa.fa-pencil(ng-switch-when="insert")
  255. i.rp-icon-delete(ng-switch-when="delete")
  256. .rp-entry-details
  257. .rp-entry-description(ng-switch="entry.type")
  258. span(ng-switch-when="insert") #{translate("tracked_change_added")} 
  259. ins.rp-content-highlight {{ entry.content | limitTo:(isCollapsed ? contentLimit : entry.content.length) }}
  260. a.rp-collapse-toggle(
  261. href
  262. ng-if="needsCollapsing"
  263. ng-click="toggleCollapse();"
  264. ) {{ isCollapsed ? '… (#{translate("show_all")})' : ' (#{translate("show_less")})' }}
  265. span(ng-switch-when="delete") #{translate("tracked_change_deleted")} 
  266. del.rp-content-highlight {{ entry.content | limitTo:(isCollapsed ? contentLimit : entry.content.length) }}
  267. a.rp-collapse-toggle(
  268. href
  269. ng-if="needsCollapsing"
  270. ng-click="toggleCollapse();"
  271. ) {{ isCollapsed ? '… (#{translate("show_all")})' : ' (#{translate("show_less")})' }}
  272. .rp-entry-metadata
  273. | {{ entry.metadata.ts | date : 'MMM d, y h:mm a' }} • 
  274. span.rp-entry-user(ng-switch="user.name" style="color: hsl({{ user.hue }}, 70%, 40%);")
  275. span(ng-switch-when="undefined") #{translate("anonymous")}
  276. span(ng-switch-default) {{ user.name }}
  277. .rp-entry-actions(ng-if="permissions.write")
  278. a.rp-entry-button(href, ng-click="onReject();")
  279. i.fa.fa-times
  280. |  #{translate("reject")}
  281. a.rp-entry-button(href, ng-click="onAccept();")
  282. i.fa.fa-check
  283. |  #{translate("accept")}
  284. script(type='text/ng-template', id='aggregateChangeEntryTemplate')
  285. div
  286. .rp-entry-callout.rp-entry-callout-aggregate
  287. .rp-entry-indicator(
  288. ng-class="{ 'rp-entry-indicator-focused': entry.focused }"
  289. ng-click="onIndicatorClick();"
  290. )
  291. i.fa.fa-pencil
  292. .rp-entry.rp-entry-aggregate(
  293. ng-class="{ 'rp-entry-focused': entry.focused }"
  294. )
  295. .rp-entry-body
  296. .rp-entry-action-icon
  297. i.fa.fa-pencil
  298. .rp-entry-details
  299. .rp-entry-description
  300. | #{translate("aggregate_changed")} 
  301. del.rp-content-highlight
  302. | {{ entry.metadata.replaced_content | limitTo:(isDeletionCollapsed ? contentLimit : entry.metadata.replaced_contentlength) }}
  303. a.rp-collapse-toggle(
  304. href
  305. ng-if="deletionNeedsCollapsing"
  306. ng-click="toggleDeletionCollapse();"
  307. ) {{ isDeletionCollapsed ? '… (#{translate("show_all")})' : ' (#{translate("show_less")})' }}
  308. | #{translate("aggregate_to")} 
  309. ins.rp-content-highlight
  310. | {{ entry.content | limitTo:(isInsertionCollapsed ? contentLimit : entry.contentlength) }}
  311. a.rp-collapse-toggle(
  312. href
  313. ng-if="insertionNeedsCollapsing"
  314. ng-click="toggleInsertionCollapse();"
  315. ) {{ isInsertionCollapsed ? '… (#{translate("show_all")})' : ' (#{translate("show_less")})' }}
  316. .rp-entry-metadata
  317. | {{ entry.metadata.ts | date : 'MMM d, y h:mm a' }} • 
  318. span.rp-entry-user(ng-switch="user.name" style="color: hsl({{ user.hue }}, 70%, 40%);")
  319. span(ng-switch-when="undefined") #{translate("anonymous")}
  320. span(ng-switch-default) {{ user.name }}
  321. .rp-entry-actions(ng-if="permissions.write")
  322. a.rp-entry-button(href, ng-click="onReject();")
  323. i.fa.fa-times
  324. |  #{translate("reject")}
  325. a.rp-entry-button(href, ng-click="onAccept();")
  326. i.fa.fa-check
  327. |  #{translate("accept")}
  328. script(type='text/ng-template', id='commentEntryTemplate')
  329. .rp-comment-wrapper(
  330. ng-class="{ 'rp-comment-wrapper-resolving': state.animating }"
  331. )
  332. .rp-entry-callout.rp-entry-callout-comment
  333. .rp-entry-indicator(
  334. ng-class="{ 'rp-entry-indicator-focused': entry.focused }"
  335. ng-click="onIndicatorClick();"
  336. )
  337. i.fa.fa-comment
  338. .rp-entry.rp-entry-comment(
  339. ng-class="{ 'rp-entry-focused': entry.focused, 'rp-entry-comment-resolving': state.animating }"
  340. )
  341. .rp-loading(ng-if="!threads[entry.thread_id].submitting && (!threads[entry.thread_id] || threads[entry.thread_id].messages.length == 0)")
  342. | #{translate("no_comments")}
  343. .rp-comment-loaded
  344. .rp-comment(
  345. ng-repeat="comment in threads[entry.thread_id].messages track by comment.id"
  346. )
  347. p.rp-comment-content
  348. span(ng-if="!comment.editing")
  349. span.rp-entry-user(
  350. style="color: hsl({{ comment.user.hue }}, 70%, 40%);",
  351. ) {{ comment.user.name }}: 
  352. span(ng-bind-html="comment.content | linky:'_blank':{rel: 'noreferrer noopener'}")
  353. textarea.rp-comment-input(
  354. expandable-text-area
  355. ng-if="comment.editing"
  356. ng-model="comment.content"
  357. ng-keypress="saveEditOnEnter($event, comment);"
  358. ng-blur="saveEdit(comment)"
  359. autofocus
  360. stop-propagation="click"
  361. )
  362. .rp-entry-metadata(ng-if="!comment.editing")
  363. span(ng-if="!comment.deleting") {{ comment.timestamp | date : 'MMM d, y h:mm a' }}
  364. span.rp-comment-actions(ng-if="comment.user.isSelf && !comment.deleting")
  365. |  • 
  366. a(href, ng-click="startEditing(comment)") #{translate("edit")}
  367. span(ng-if="threads[entry.thread_id].messages.length > 1")
  368. |  • 
  369. a(href, ng-click="confirmDelete(comment)") #{translate("delete")}
  370. span.rp-confim-delete(ng-if="comment.user.isSelf && comment.deleting")
  371. | #{translate("are_you_sure")}
  372. | • 
  373. a(href, ng-click="doDelete(comment)") #{translate("delete")}
  374. |  • 
  375. a(href, ng-click="cancelDelete(comment)") #{translate("cancel")}
  376. .rp-loading(ng-if="threads[entry.thread_id].submitting")
  377. i.fa.fa-spinner.fa-spin
  378. .rp-comment-reply(ng-if="permissions.comment")
  379. textarea.rp-comment-input(
  380. expandable-text-area
  381. ng-model="entry.replyContent"
  382. ng-keypress="handleCommentReplyKeyPress($event);"
  383. stop-propagation="click"
  384. placeholder=translate("hit_enter_to_reply")
  385. )
  386. .rp-entry-actions
  387. button.rp-entry-button(
  388. ng-click="animateAndCallOnResolve();"
  389. ng-if="permissions.comment && permissions.write"
  390. )
  391. i.fa.fa-inbox
  392. |  #{translate("resolve")}
  393. button.rp-entry-button(
  394. ng-click="onReply();"
  395. ng-if="permissions.comment"
  396. ng-disabled="!entry.replyContent.length"
  397. )
  398. i.fa.fa-reply
  399. |  #{translate("reply")}
  400. script(type='text/ng-template', id='resolvedCommentEntryTemplate')
  401. .rp-resolved-comment
  402. div
  403. .rp-resolved-comment-context
  404. | #{translate("quoted_text_in")} 
  405. span.rp-resolved-comment-context-file {{ thread.docName }}
  406. p.rp-resolved-comment-context-quote
  407. span {{ thread.content | limitTo:(isCollapsed ? contentLimit : thread.content.length)}}
  408. a.rp-collapse-toggle(
  409. href
  410. ng-if="needsCollapsing"
  411. ng-click="toggleCollapse();"
  412. )  {{ isCollapsed ? '… (#{translate("show_all")})' : ' (#{translate("show_less")})' }}
  413. .rp-comment(
  414. ng-repeat="comment in thread.messages track by comment.id"
  415. )
  416. p.rp-comment-content
  417. span.rp-entry-user(
  418. style="color: hsl({{ comment.user.hue }}, 70%, 40%);"
  419. ng-if="$first || comment.user.id !== thread.messages[$index - 1].user.id"
  420. ) {{ comment.user.name }}: 
  421. span(ng-bind-html="comment.content | linky:'_blank':{rel: 'noreferrer noopener'}")
  422. .rp-entry-metadata
  423. | {{ comment.timestamp | date : 'MMM d, y h:mm a' }}
  424. .rp-comment.rp-comment-resolver
  425. p.rp-comment-resolver-content
  426. span.rp-entry-user(
  427. style="color: hsl({{ thread.resolved_by_user.hue }}, 70%, 40%);"
  428. ) {{ thread.resolved_by_user.name }}: 
  429. | #{translate("mark_as_resolved")}.
  430. .rp-entry-metadata
  431. | {{ thread.resolved_at | date : 'MMM d, y h:mm a' }}
  432. .rp-entry-actions(ng-if="permissions.comment && permissions.write")
  433. a.rp-entry-button(
  434. href
  435. ng-click="onUnresolve({ 'threadId': thread.threadId });"
  436. )
  437. |  #{translate("reopen")}
  438. a.rp-entry-button(
  439. href
  440. ng-click="onDelete({ 'entryId': thread.entryId, 'docId': thread.docId, 'threadId': thread.threadId });"
  441. )
  442. |  #{translate("delete")}
  443. script(type='text/ng-template', id='addCommentEntryTemplate')
  444. div
  445. .rp-entry-callout.rp-entry-callout-add-comment
  446. .rp-entry.rp-entry-add-comment(
  447. ng-class="[ (state.isAdding ? 'rp-entry-adding-comment' : ''), (entry.focused ? 'rp-entry-focused' : '')]"
  448. )
  449. a.rp-add-comment-btn(
  450. href
  451. ng-if="!state.isAdding"
  452. ng-click="startNewComment();"
  453. )
  454. i.fa.fa-comment
  455. |  #{translate("add_comment")}
  456. div(ng-if="state.isAdding")
  457. .rp-new-comment
  458. textarea.rp-comment-input(
  459. expandable-text-area
  460. ng-model="state.content"
  461. ng-keypress="handleCommentKeyPress($event);"
  462. placeholder=translate("add_your_comment_here")
  463. focus-on="comment:new:open"
  464. )
  465. .rp-entry-actions
  466. button.rp-entry-button.rp-entry-button-cancel(
  467. ng-click="cancelNewComment();"
  468. )
  469. i.fa.fa-times
  470. |  #{translate("cancel")}
  471. button.rp-entry-button(
  472. ng-click="submitNewComment()"
  473. ng-disabled="!state.content.length"
  474. )
  475. i.fa.fa-comment
  476. |  #{translate("comment")}
  477. script(type='text/ng-template', id='bulkActionsEntryTemplate')
  478. div(ng-if="nEntries > 1")
  479. .rp-entry-callout.rp-entry-callout-bulk-actions
  480. .rp-entry.rp-entry-bulk-actions
  481. a.rp-bulk-actions-btn(
  482. href
  483. ng-click="bulkReject();"
  484. )
  485. i.fa.fa-times
  486. |  #{translate("reject_all")}
  487. | ({{ nEntries }})
  488. a.rp-bulk-actions-btn(
  489. href
  490. ng-click="bulkAccept();"
  491. )
  492. i.fa.fa-check
  493. |  #{translate("accept_all")}
  494. | ({{ nEntries }})
  495. script(type='text/ng-template', id='resolvedCommentsDropdownTemplate')
  496. .resolved-comments
  497. .resolved-comments-backdrop(
  498. ng-class="{ 'resolved-comments-backdrop-visible' : state.isOpen }"
  499. ng-click="state.isOpen = false"
  500. )
  501. a.resolved-comments-toggle(
  502. href
  503. ng-click="toggleOpenState();"
  504. tooltip=translate("resolved_comments")
  505. tooltip-placement="bottom"
  506. tooltip-append-to-body="true"
  507. )
  508. i.fa.fa-inbox
  509. .resolved-comments-dropdown(
  510. ng-class="{ 'resolved-comments-dropdown-open' : state.isOpen }"
  511. )
  512. .rp-loading(ng-if="isLoading")
  513. i.fa.fa-spinner.fa-spin
  514. .resolved-comments-scroller(
  515. ng-if="!isLoading"
  516. )
  517. resolved-comment-entry(
  518. ng-repeat="thread in resolvedComments | orderBy:'resolved_at':true"
  519. thread="thread"
  520. on-unresolve="handleUnresolve(threadId);"
  521. on-delete="handleDelete(entryId, docId, threadId);"
  522. permissions="permissions"
  523. )
  524. .rp-loading(ng-if="!resolvedComments.length")
  525. | #{translate("no_resolved_threads")}.
  526. script(type="text/ng-template", id="trackChangesUpgradeModalTemplate")
  527. .modal-header
  528. button.close(
  529. type="button"
  530. data-dismiss="modal"
  531. ng-click="cancel()"
  532. aria-label="Close"
  533. )
  534. span(aria-hidden="true") ×
  535. h3 #{translate("upgrade_to_track_changes")}
  536. .modal-body
  537. .teaser-video-container
  538. video.teaser-video(autoplay, loop)
  539. source(ng-src="{{ '/img/teasers/track-changes/teaser-track-changes.mp4' }}", type="video/mp4")
  540. img(src="/img/teasers/track-changes/teaser-track-changes.gif")
  541. h4.teaser-title #{translate("see_changes_in_your_documents_live")}
  542. p.small(ng-show="startedFreeTrial")
  543. | #{translate("refresh_page_after_starting_free_trial")}
  544. .row
  545. .col-md-10.col-md-offset-1
  546. ul.list-unstyled
  547. li
  548. i.fa.fa-check  
  549. | #{translate("track_any_change_in_real_time")}
  550. li
  551. i.fa.fa-check  
  552. | #{translate("review_your_peers_work")}
  553. li
  554. i.fa.fa-check  
  555. | #{translate("accept_or_reject_each_changes_individually")}
  556. .row.text-center
  557. div(ng-show="user.allowedFreeTrial" ng-controller="FreeTrialModalController")
  558. a.btn.btn-success(
  559. href
  560. ng-click="startFreeTrial('track-changes')"
  561. ng-show="project.owner._id == user.id"
  562. ) #{translate("try_it_for_free")}
  563. div(ng-show="!user.allowedFreeTrial" ng-controller="UpgradeModalController")
  564. a.btn.btn-success(
  565. href
  566. ng-click="upgradePlan('project-sharing')"
  567. ng-show="project.owner._id == user.id"
  568. ) #{translate("upgrade")}
  569. p(ng-show="project.owner._id != user.id"): strong #{translate("please_ask_the_project_owner_to_upgrade_to_track_changes")}
  570. .modal-footer()
  571. button.btn.btn-default(
  572. ng-click="cancel()"
  573. )
  574. span #{translate("close")}
  575. script(type="text/ng-template", id="bulkActionsModalTemplate")
  576. .modal-header
  577. button.close(
  578. type="button"
  579. data-dismiss="modal"
  580. ng-click="cancel()"
  581. aria-label="Close"
  582. )
  583. span(aria-hidden="true") ×
  584. h3 {{ isAccept ? '#{translate("accept_all")}' : '#{translate("reject_all")}' }}
  585. .modal-body
  586. p(ng-if="isAccept") #{translate("bulk_accept_confirm", { nChanges: "{{ nChanges }}"})}
  587. p(ng-if="!isAccept") #{translate("bulk_reject_confirm", { nChanges: "{{ nChanges }}"})}
  588. .modal-footer()
  589. button.btn.btn-default(
  590. ng-click="cancel()"
  591. )
  592. span #{translate("cancel")}
  593. button.btn.btn-primary(
  594. ng-click="confirm()"
  595. )
  596. span #{translate("ok")}