file-tree.pug 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424
  1. aside.editor-sidebar.full-size(
  2. ng-controller="FileTreeController"
  3. ng-class="{ 'multi-selected': multiSelectedCount > 0 }"
  4. ng-show="ui.view != 'history' || !history.isV2"
  5. vertical-resizable-panes="outline-resizer"
  6. vertical-resizable-panes-toggled-externally-on="outline-toggled"
  7. vertical-resizable-panes-min-size="32"
  8. vertical-resizable-panes-max-size="75%"
  9. )
  10. .file-tree(
  11. vertical-resizable-top
  12. )
  13. .toolbar.toolbar-filetree(ng-if="permissions.write")
  14. a(
  15. href,
  16. ng-click="openNewDocModal()",
  17. tooltip-html="'"+translate('new_file').replace(' ', '<br>')+"'",
  18. tooltip-placement="bottom"
  19. )
  20. i.fa.fa-fw.fa-file
  21. a(
  22. href,
  23. ng-click="openNewFolderModal()",
  24. tooltip-html="'"+translate('new_folder').replace(' ', '<br>')+"'",
  25. tooltip-placement="bottom"
  26. )
  27. i.fa.fa-fw.fa-folder
  28. a(
  29. href,
  30. ng-click="openUploadFileModal()",
  31. tooltip=translate('upload'),
  32. tooltip-placement="bottom"
  33. )
  34. i.fa.fa-fw.fa-upload
  35. .toolbar-right
  36. a(
  37. href,
  38. ng-click="startRenamingSelected()",
  39. tooltip=translate('rename'),
  40. tooltip-placement="bottom",
  41. ng-show="multiSelectedCount == 0"
  42. )
  43. i.fa.fa-fw.fa-pencil
  44. a(
  45. href,
  46. ng-click="openDeleteModalForSelected()",
  47. tooltip=translate('delete'),
  48. tooltip-placement="bottom",
  49. tooltip-append-to-body="true"
  50. )
  51. i.fa.fa-fw.fa-trash-o
  52. .file-tree-inner(
  53. ng-if="rootFolder",
  54. ng-controller="FileTreeRootFolderController",
  55. ng-class="{ 'no-toolbar': !permissions.write }"
  56. )
  57. ul.list-unstyled.file-tree-list(
  58. droppable="permissions.write"
  59. accept=".entity-name"
  60. on-drop-callback="onDrop"
  61. )
  62. li(
  63. ng-show="ui.pdfLayout == 'flat' && (ui.view == 'editor' || ui.view == 'pdf' || ui.view == 'file')"
  64. ng-class="{ 'selected': ui.view == 'pdf' }"
  65. ng-controller="PdfViewToggleController"
  66. )
  67. .entity
  68. .entity-name(
  69. ng-click="togglePdfView()"
  70. )
  71. i.fa.fa-fw.toggle
  72. i.fa.fa-fw.fa-file-pdf-o
  73. | PDF
  74. file-entity(
  75. entity="entity",
  76. permissions="permissions",
  77. ng-repeat="entity in rootFolder.children | orderBy:[orderByFoldersFirst, 'name']"
  78. )
  79. li(ng-show="deletedDocs.length > 0 && ui.view == 'history'")
  80. h3 #{translate("deleted_files")}
  81. li(
  82. ng-class="{ 'selected': entity.selected }",
  83. ng-repeat="entity in deletedDocs | orderBy:'name'",
  84. ng-controller="FileTreeEntityController",
  85. ng-show="ui.view == 'history'"
  86. )
  87. .entity
  88. .entity-name(
  89. ng-click="select($event)"
  90. )
  91. //- Just a spacer to align with folders
  92. i.fa.fa-fw.toggle
  93. i.fa.fa-fw.fa-file
  94. span {{ entity.name }}
  95. .outline-container(
  96. vertical-resizable-bottom
  97. ng-controller="OutlineController"
  98. )
  99. outline-pane(
  100. is-tex-file="isTexFile"
  101. outline="outline"
  102. project-id="project_id"
  103. jump-to-line="jumpToLine"
  104. on-toggle="onToggle"
  105. event-tracking="eventTracking"
  106. highlighted-line="highlightedLine"
  107. )
  108. script(type='text/ng-template', id='entityListItemTemplate')
  109. li(
  110. ng-class="{ 'selected': entity.selected, 'multi-selected': entity.multiSelected }",
  111. ng-controller="FileTreeEntityController"
  112. )
  113. .entity(ng-if="entity.type != 'folder'")
  114. .entity-name(
  115. ng-click="select($event)"
  116. ng-dblclick="permissions.write && startRenaming()"
  117. draggable="permissions.write"
  118. draggable-helper="draggableHelper"
  119. context-menu
  120. data-target="context-menu-{{ entity.id }}"
  121. context-menu-container="body"
  122. context-menu-disabled="!permissions.write"
  123. )
  124. //- Just a spacer to align with folders
  125. i.fa.fa-fw.toggle(ng-if="entity.type != 'folder'")
  126. i.fa.fa-fw(ng-if="entity.type != 'folder'", ng-class="'fa-' + iconTypeFromName(entity.name)")
  127. i.fa.fa-external-link-square.fa-rotate-180.linked-file-highlight(
  128. ng-if="entity.linkedFileData.provider"
  129. )
  130. span(
  131. ng-hide="entity.renaming"
  132. ) {{ entity.renamingToName || entity.name }}
  133. span.rename-input
  134. input(
  135. ng-if="permissions.write",
  136. ng-show="entity.renaming",
  137. ng-model="inputs.name",
  138. ng-blur="finishRenaming()",
  139. select-name-when="entity.renaming",
  140. on-enter="finishRenaming()"
  141. valid-file
  142. )
  143. span.dropdown.entity-menu-toggle(
  144. dropdown,
  145. ng-if="permissions.write"
  146. )
  147. a.dropdown-toggle.file-tree-dropdown-toggle(href, dropdown-toggle, stop-propagation="click")
  148. ul.dropdown-menu.dropdown-menu-right
  149. li
  150. a(
  151. href
  152. ng-click="startRenaming()"
  153. right-click="startRenaming()"
  154. ng-show="!entity.multiSelected"
  155. ) #{translate("rename")}
  156. li
  157. a(
  158. href
  159. ng-click="openDeleteModal()"
  160. right-click="openDeleteModal()"
  161. stop-propagation="click"
  162. ) #{translate("delete")}
  163. div.dropdown.context-menu(
  164. id="context-menu-{{ entity.id }}",
  165. ng-if="permissions.write"
  166. )
  167. ul.dropdown-menu
  168. li
  169. a(
  170. href
  171. ng-click="startRenaming()"
  172. right-click="startRenaming()"
  173. ng-show="!entity.multiSelected"
  174. ) #{translate("rename")}
  175. li
  176. a(
  177. href
  178. ng-click="openDeleteModal()"
  179. right-click="openDeleteModal()"
  180. stop-propagation="click"
  181. ) #{translate("delete")}
  182. .entity(ng-if="entity.type == 'folder'", ng-controller="FileTreeFolderController")
  183. .entity-name(
  184. ng-click="select($event)"
  185. ng-dblclick="permissions.write && startRenaming()"
  186. draggable="permissions.write"
  187. draggable-helper="draggableHelper"
  188. droppable="permissions.write"
  189. accept=".entity-name"
  190. on-drop-callback="onDrop"
  191. )
  192. div(
  193. context-menu
  194. data-target="context-menu-{{ entity.id }}"
  195. context-menu-container="body"
  196. context-menu-disabled="!permissions.write"
  197. )
  198. i.fa.fa-fw.toggle(
  199. ng-if="entity.type == 'folder'"
  200. ng-class="{'fa-angle-right': !expanded, 'fa-angle-down': expanded}"
  201. ng-click="toggleExpanded()"
  202. )
  203. i.fa.fa-fw(
  204. ng-if="entity.type == 'folder'"
  205. ng-class="{\
  206. 'fa-folder': !expanded, \
  207. 'fa-folder-open': expanded \
  208. }"
  209. ng-click="select($event)"
  210. )
  211. span(
  212. ng-hide="entity.renaming"
  213. ) {{ entity.renamingToName || entity.name }}
  214. span.rename-input
  215. input(
  216. ng-if="permissions.write",
  217. ng-show="entity.renaming",
  218. ng-model="inputs.name",
  219. ng-blur="finishRenaming()",
  220. select-name-when="entity.renaming",
  221. on-enter="finishRenaming()"
  222. valid-file
  223. )
  224. span.dropdown.entity-menu-toggle(
  225. dropdown,
  226. ng-if="permissions.write"
  227. )
  228. a.dropdown-toggle.file-tree-dropdown-toggle(href, dropdown-toggle, stop-propagation="click")
  229. ul.dropdown-menu.dropdown-menu-right
  230. li
  231. a(
  232. href
  233. ng-click="startRenaming()"
  234. right-click="startRenaming()"
  235. ng-show="!entity.multiSelected"
  236. ) #{translate("rename")}
  237. li
  238. a(
  239. href
  240. ng-click="openDeleteModal()"
  241. right-click="openDeleteModal()"
  242. stop-propagation="click"
  243. ) #{translate("delete")}
  244. li.divider
  245. li
  246. a(
  247. href
  248. ng-click="openNewDocModal()"
  249. right-click="openNewDocModal()"
  250. ) #{translate("new_file")}
  251. li
  252. a(
  253. href
  254. ng-click="openNewFolderModal()"
  255. right-click="openNewFolderModal()"
  256. ) #{translate("new_folder")}
  257. li
  258. a(
  259. href
  260. ng-click="openUploadFileModal()"
  261. right-click="openUploadFileModal()"
  262. ) #{translate("upload_file")}
  263. .dropdown.context-menu(
  264. ng-if="permissions.write"
  265. id="context-menu-{{ entity.id }}"
  266. )
  267. ul.dropdown-menu
  268. li
  269. a(
  270. href
  271. ng-click="startRenaming()"
  272. right-click="startRenaming()"
  273. ng-show="!entity.multiSelected"
  274. ) #{translate("rename")}
  275. li
  276. a(
  277. href
  278. ng-click="openDeleteModal()"
  279. right-click="openDeleteModal()"
  280. stop-propagation="click"
  281. ) #{translate("delete")}
  282. li.divider
  283. li
  284. a(
  285. href
  286. ng-click="openNewDocModal()"
  287. right-click="openNewDocModal()"
  288. ) #{translate("new_file")}
  289. li
  290. a(
  291. href
  292. ng-click="openNewFolderModal()"
  293. right-click="openNewFolderModal()"
  294. ) #{translate("new_folder")}
  295. li
  296. a(
  297. href
  298. ng-click="openUploadFileModal()"
  299. right-click="openUploadFileModal()"
  300. ) #{translate("upload_file")}
  301. ul.list-unstyled(
  302. ng-if="entity.type == 'folder' && (depth == null || depth < MAX_DEPTH)"
  303. ng-show="expanded"
  304. droppable="permissions.write"
  305. accept=".entity-name"
  306. on-drop-callback="onDrop"
  307. )
  308. file-entity(
  309. entity="child",
  310. permissions="permissions",
  311. ng-repeat="child in entity.children | orderBy:[orderByFoldersFirst, 'name']"
  312. depth="(depth || 0) + 1"
  313. )
  314. .entity-limit-hit(
  315. ng-if="depth === MAX_DEPTH"
  316. ng-show="expanded"
  317. )
  318. i.fa.fa-fw
  319. span.entity-limit-hit-message
  320. | Some files might be hidden
  321. |
  322. i.fa.fa-question-circle.entity-limit-hit-tooltip-trigger(
  323. tooltip="Your project has hit Overleaf's maximum file depth limit. Files within this folder won't be visible."
  324. tooltip-append-to-body="true"
  325. aria-hidden="true"
  326. )
  327. span.sr-only
  328. | Your project has hit Overleaf's maximum file depth limit. Files within this folder won't be visible.
  329. script(type='text/ng-template', id='newFolderModalTemplate')
  330. .modal-header
  331. h3 #{translate("new_folder")}
  332. .modal-body
  333. form(novalidate, name="newFolderForm")
  334. input.form-control(
  335. type="text",
  336. placeholder="Folder Name",
  337. required,
  338. ng-model="inputs.name",
  339. on-enter="create()",
  340. select-name-on="open",
  341. valid-file,
  342. name="name"
  343. )
  344. div.alert.alert-danger.row-spaced-small(ng-show="newFolderForm.name.$error.validFile")
  345. | #{translate('files_cannot_include_invalid_characters')}
  346. div.alert.alert-danger.row-spaced-small(ng-if="error")
  347. div(ng-switch="error")
  348. span(ng-switch-when="already exists") #{translate("file_already_exists")}
  349. span(ng-switch-default) {{error}}
  350. .modal-footer
  351. button.btn.btn-default(
  352. ng-disabled="state.inflight"
  353. ng-click="cancel()"
  354. ) #{translate("cancel")}
  355. button.btn.btn-primary(
  356. ng-disabled="newFolderForm.$invalid || state.inflight"
  357. ng-click="create()"
  358. )
  359. span(ng-hide="state.inflight") #{translate("create")}
  360. span(ng-show="state.inflight") #{translate("creating")}…
  361. script(type='text/ng-template', id='duplicateFileModalTemplate')
  362. .modal-header
  363. h3 #{translate("duplicate_file")}
  364. .modal-body
  365. p #{translate("file_already_exists_in_this_location", { fileName: "'{{ fileName }}'" })}
  366. .modal-footer
  367. button.btn.btn-default(
  368. ng-click="cancel()"
  369. ) #{translate("dismiss")}
  370. include ./new-file-modal
  371. script(type='text/ng-template', id='deleteEntityModalTemplate')
  372. .modal-header
  373. h3 #{translate("delete")} {{ entity.name }}
  374. .modal-body
  375. p !{translate("sure_you_want_to_delete")}
  376. ul
  377. li(ng-repeat="entity in entities") {{entity.name}}
  378. .modal-footer
  379. button.btn.btn-default(
  380. ng-disabled="state.inflight"
  381. ng-click="cancel()"
  382. ) #{translate("cancel")}
  383. button.btn.btn-danger(
  384. ng-disabled="state.inflight"
  385. ng-click="delete()"
  386. )
  387. span(ng-hide="state.inflight") #{translate("delete")}
  388. span(ng-show="state.inflight") #{translate("deleting")}…
  389. script(type='text/ng-template', id='invalidFileNameModalTemplate')
  390. .modal-header
  391. h3 #{translate('invalid_file_name')}
  392. .modal-body
  393. p #{translate('files_cannot_include_invalid_characters')}
  394. .modal-footer
  395. button.btn.btn-default(
  396. ng-click="$close()"
  397. ) #{translate('ok')}