FileTreeManager.coffee 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282
  1. define [
  2. "models/Doc"
  3. "models/File"
  4. "models/Folder"
  5. "file-tree/FileTreeView"
  6. "utils/Effects"
  7. "utils/Modal"
  8. "libs/backbone"
  9. "libs/jquery.storage"
  10. ], (Doc, File, Folder, FileTreeView, Effects, Modal) ->
  11. class FileTreeManager
  12. constructor: (@ide) ->
  13. _.extend(@, Backbone.Events)
  14. @views = {}
  15. @multiSelectedEntities = []
  16. @ide.on "afterJoinProject", (@project) =>
  17. @populateFileTree()
  18. @project_id = @project.id
  19. if @ide.editor?.current_doc_id?
  20. @openDoc(@ide.editor.current_doc_id)
  21. else if location.hash.length > 1
  22. fileName = location.hash.slice(1)
  23. @openDocByPath(fileName)
  24. else if openDoc_id = $.localStorage("doc.open_id.#{@project_id}") and @getEntity(openDoc_id)
  25. @openDoc(openDoc_id)
  26. else if @project.get("rootDoc_id")?
  27. @openDoc(project.get("rootDoc_id"))
  28. else
  29. $('#settings').click()
  30. @view = new FileTreeView(@)
  31. @ide.sideBarView.addLink
  32. identifier: "file-tree"
  33. element: @view.$el
  34. prepend: true
  35. @view.render()
  36. @listenForUpdates()
  37. populateFileTree: () ->
  38. @view.bindToRootFolder(@project.get("rootFolder"))
  39. listenForUpdates: () ->
  40. @ide.socket.on 'reciveNewDoc', (folder_id, doc) =>
  41. @addEntityToFolder(
  42. new Doc(id: doc._id, name: doc.name)
  43. folder_id
  44. )
  45. @ide.socket.on 'reciveNewFolder', (folder_id, folder) =>
  46. @addEntityToFolder(
  47. new Folder(id: folder._id, name: folder.name)
  48. folder_id
  49. )
  50. @ide.socket.on 'reciveNewFile', (folder_id, file) =>
  51. @addEntityToFolder(
  52. new File(id: file._id, name: file.name)
  53. folder_id
  54. )
  55. @ide.socket.on 'removeEntity', (entity_id) =>
  56. @onDeleteEntity(entity_id)
  57. @ide.socket.on 'reciveEntityRename', (entity_id, newName) =>
  58. @onRenameEntity(entity_id, newName)
  59. @ide.socket.on 'reciveEntityMove', (entity_id, folder_id) =>
  60. @onMoveEntity(entity_id, folder_id)
  61. registerView: (entity_id, view) ->
  62. @views[entity_id] = view
  63. addEntityToFolder: (entity, folder_id) ->
  64. folder = @views[folder_id].model
  65. children = folder.get("children")
  66. children.add(entity)
  67. openDoc: (doc, line) ->
  68. doc_id = doc.id or doc
  69. @trigger "open:doc", doc_id, line: line
  70. @selectEntity(doc_id)
  71. $.localStorage "doc.open_id.#{@project_id}", doc_id
  72. openDocByPath: (path, line) ->
  73. doc_id = @getDocIdOfPath(path)
  74. return null if !doc_id?
  75. @openDoc(doc_id, line)
  76. openFile: (file) ->
  77. @trigger "open:file", file
  78. @selectEntity(file.id)
  79. openFolder: (folder) ->
  80. @selectEntity(folder.id)
  81. selectEntity: (entity_id) ->
  82. if @views[@selected_entity_id]?
  83. @views[@selected_entity_id].deselect()
  84. @selected_entity_id = entity_id
  85. @ide.sideBarView.deselectAll()
  86. @views[entity_id]?.select()
  87. getEntity: (entity_id) ->
  88. @views[entity_id]?.model
  89. getSelectedEntity: () -> @getEntity(@selected_entity_id)
  90. getSelectedEntityId: () -> @getSelectedEntity()?.id
  91. getCurrentFolder: () ->
  92. selected_entity = @getSelectedEntity()
  93. if !selected_entity?
  94. return @project.get("rootFolder")
  95. else if selected_entity instanceof Folder
  96. return selected_entity
  97. else
  98. return selected_entity.collection.parentFolder
  99. getDocIdOfPath: (path) ->
  100. parts = path.split("/")
  101. folder = @project.get("rootFolder")
  102. lastPart = parts.pop()
  103. getChildWithName = (folder, name) ->
  104. foundChild = null
  105. for child in folder.get("children").models
  106. if child.get("name") == name
  107. foundChild = child
  108. return foundChild
  109. for part in parts
  110. folder = getChildWithName(folder, part)
  111. return null if !folder or !(folder instanceof Folder)
  112. doc = getChildWithName(folder, lastPart)
  113. return null if !doc or !(doc instanceof Doc)
  114. return doc.id
  115. getPathOfEntityId: (entity_id) ->
  116. entity = @getEntity(entity_id)
  117. return if !entity?
  118. path = entity.get("name")
  119. while (entity = entity.collection?.parentFolder)
  120. if entity.collection?
  121. # it's not the root folder so keep going
  122. path = entity.get("name") + "/" + path
  123. return path
  124. getNameOfEntityId: (entity_id) ->
  125. entity = @getEntity(entity_id)
  126. return if !entity?
  127. return entity.get("name")
  128. # RENAMING
  129. renameSelected: () ->
  130. entity_id = @getSelectedEntityId()
  131. return if !entity_id?
  132. @views[entity_id]?.startRename()
  133. ga('send', 'event', 'editor-interaction', 'renameEntity', "topMenu")
  134. renameEntity: (entity, name) ->
  135. @ide.socket.emit 'renameEntity', entity.id, entity.get("type"), name
  136. entity.set("name", name)
  137. onRenameEntity: (entity_id, name) ->
  138. @getEntity(entity_id)?.set("name", name)
  139. # MOVING
  140. onMoveEntity: (entity_id, folder_id) ->
  141. entity = @getEntity(entity_id)
  142. destFolder = @getEntity(folder_id)
  143. return if !entity? or !destFolder?
  144. if entity.collection == destFolder.get("children")
  145. # Already in parent folder
  146. return
  147. return if @_isParent(entity_id, folder_id)
  148. entity.collection.remove(entity)
  149. destFolder.get("children").add(entity)
  150. _isParent: (parent_folder_id, child_folder_id) ->
  151. childFolder = @getEntity(child_folder_id)
  152. return false unless childFolder? and childFolder instanceof Folder
  153. parentIds = childFolder.getParentFolderIds()
  154. if parentIds.indexOf(parent_folder_id) > -1
  155. return true
  156. else
  157. return false
  158. moveEntity: (entity_id, folder_id, type) ->
  159. return if @_isParent(entity_id, folder_id)
  160. @ide.socket.emit 'moveEntity', entity_id, folder_id, type
  161. @onMoveEntity(entity_id, folder_id)
  162. # CREATING
  163. showNewEntityModal: (type, defaultName, callback = (name) ->) ->
  164. el = $($("#newEntityModalTemplate").html())
  165. input = el.find("input")
  166. create = _.once () =>
  167. name = input.val()
  168. if name != ""
  169. callback(name)
  170. modal = new Modal
  171. title: "New #{type}"
  172. el: el
  173. buttons: [{
  174. text: "Cancel"
  175. }, {
  176. text: "Create"
  177. callback: create
  178. class: "btn-primary"
  179. }]
  180. input.on "keydown", (e) ->
  181. if e.keyCode == 13 # Enter
  182. create()
  183. modal.remove()
  184. input.val(defaultName.replace("|", ""))
  185. if input[0].setSelectionRange?
  186. # value is "name.tex"
  187. input[0].setSelectionRange(0, defaultName.indexOf("|"))
  188. showNewDocModal: (parentFolder = @getCurrentFolder()) ->
  189. return if !parentFolder?
  190. @showNewEntityModal "Document", "name|.tex", (name) =>
  191. @addDocToFolder parentFolder, name
  192. showNewFolderModal: (parentFolder = @getCurrentFolder()) ->
  193. return if !parentFolder?
  194. @showNewEntityModal "Folder", "name|", (name) =>
  195. @addFolderToFolder parentFolder, name
  196. showUploadFileModal: (parentFolder = @getCurrentFolder()) ->
  197. return if !parentFolder?
  198. @ide.fileUploadManager.showUploadDialog parentFolder.id
  199. addDoc: (folder_id, name) ->
  200. @ide.socket.emit 'addDoc', folder_id, name
  201. addDocToFolder: (parentFolder, name) ->
  202. @addDoc parentFolder.id, name
  203. addFolder: (parent_folder_id, name) ->
  204. @ide.socket.emit 'addFolder', parent_folder_id, name
  205. addFolderToFolder: (parentFolder, name) ->
  206. return if !parentFolder?
  207. @addFolder parentFolder.id, name
  208. # DELETING
  209. confirmDelete: (entity) ->
  210. ga('send', 'event', 'editor-interaction', 'deleteEntity', "topMenu")
  211. Modal.createModal
  212. title: "Confirm Deletion"
  213. message: "Are you sure you want to delete <strong>#{entity.get("name")}</strong>?"
  214. buttons: [{
  215. text: "Cancel"
  216. class: "btn"
  217. },{
  218. text: "Delete"
  219. class: "btn btn-danger"
  220. callback: () => @_doDelete(entity)
  221. }]
  222. confirmDeleteOfSelectedEntity: () ->
  223. entity = @getSelectedEntity()
  224. return if !entity?
  225. @confirmDelete(entity)
  226. _doDelete: (entity) ->
  227. @ide.socket.emit 'deleteEntity', entity.id, entity.get("type")
  228. @onDeleteEntity entity.id
  229. onDeleteEntity: (entity_id) ->
  230. entity = @getEntity(entity_id)
  231. return if !entity?
  232. entity.set("deleted", true)
  233. entity.collection?.remove(entity)
  234. delete @views[entity_id]