define [ "ide/file-tree/directives/fileEntity" "ide/file-tree/directives/draggable" "ide/file-tree/directives/droppable" "ide/file-tree/controllers/FileTreeController" "ide/file-tree/controllers/FileTreeEntityController" "ide/file-tree/controllers/FileTreeFolderController" ], () -> class FileTreeManager constructor: (@ide, @$scope) -> @$scope.$on "project:joined", => @loadRootFolder() @_bindToSocketEvents() _bindToSocketEvents: () -> @ide.socket.on "reciveNewDoc", (parent_folder_id, doc) => parent_folder = @findEntityById(parent_folder_id) or @$scope.rootFolder @$scope.$apply () -> parent_folder.children.push { name: doc.name id: doc._id type: "doc" } @ide.socket.on "reciveNewFile", (parent_folder_id, file) => parent_folder = @findEntityById(parent_folder_id) or @$scope.rootFolder @$scope.$apply () -> parent_folder.children.push { name: file.name id: file._id type: "file" } @ide.socket.on "reciveNewFolder", (parent_folder_id, folder) => parent_folder = @findEntityById(parent_folder_id) or @$scope.rootFolder @$scope.$apply () -> parent_folder.children.push { name: folder.name id: folder._id type: "folder" children: [] } @ide.socket.on "reciveEntityRename", (entity_id, name) => entity = @findEntityById(entity_id) return if !entity? @$scope.$apply () -> entity.name = name @ide.socket.on "removeEntity", (entity_id) => entity = @findEntityById(entity_id) return if !entity? @$scope.$apply () => @_deleteEntityFromScope entity @ide.socket.on "reciveEntityMove", (entity_id, folder_id) => entity = @findEntityById(entity_id) folder = @findEntityById(folder_id) @$scope.$apply () => @_moveEntityInScope(entity, folder) findEntityById: (id) -> @_findEntityByIdInFolder @$scope.rootFolder, id _findEntityByIdInFolder: (folder, id) -> for entity in folder.children or [] if entity.id == id return entity else if entity.children? result = @_findEntityByIdInFolder(entity, id) return result if result? return null forEachEntity: (callback = (entity, parent_folder) ->) -> @_forEachEntityInFolder(@$scope.rootFolder, callback) _forEachEntityInFolder: (folder, callback) -> for entity in folder.children or [] callback(entity, folder) if entity.children? @_forEachEntityInFolder(entity, callback) # forEachFolder: (callback) -> # @forEachEntity (entity) -> # if entity.type == "folder" # callback(entity) loadRootFolder: () -> @$scope.rootFolder = @_parseFolder(@$scope.project.rootFolder[0]) _parseFolder: (rawFolder) -> folder = { name: rawFolder.name id: rawFolder._id type: "folder" children: [] } for doc in rawFolder.docs or [] folder.children.push { name: doc.name id: doc._id type: "doc" } for file in rawFolder.fileRefs or [] folder.children.push { name: file.name id: file._id type: "file" } for childFolder in rawFolder.folders or [] folder.children.push @_parseFolder(childFolder) return folder getCurrentFolder: () -> # Return the root folder if nothing is selected @_getCurrentFolder(@$scope.rootFolder) or @$scope.rootFolder _getCurrentFolder: (startFolder = @$scope.rootFolder) -> for entity in startFolder.children or [] # The 'current' folder is either the one selected, or # the one containing the selected doc/file if entity.selected if entity.type == "folder" return entity else return startFolder if entity.type == "folder" result = @_getCurrentFolder(entity) return result if result? return null createDocInCurrentFolder: (name, callback = (error, doc) ->) -> # We'll wait for the socket.io notification to actually # add the doc for us. parent_folder = @getCurrentFolder() $.ajax { url: "/project/#{@ide.project_id}/doc" type: "POST" contentType: "application/json; charset=utf-8" data: JSON.stringify { name: name, parent_folder_id: parent_folder?.id _csrf: window.csrfToken } dataType: "json" success: (doc) -> callback(null, doc) failure: (error) -> callback(error) } createFolderInCurrentFolder: (name, callback = (error, doc) ->) -> # We'll wait for the socket.io notification to actually # add the folder for us. parent_folder = @getCurrentFolder() $.ajax { url: "/project/#{@ide.project_id}/folder" type: "POST" contentType: "application/json; charset=utf-8" data: JSON.stringify { name: name, parent_folder_id: parent_folder?.id _csrf: window.csrfToken } dataType: "json" success: (folder) -> callback(null, folder) failure: (error) -> callback(error) } renameEntity: (entity, name, callback = (error) ->) -> return if entity.name == name entity.name = name $.ajax { url: "/project/#{@ide.project_id}/#{entity.type}/#{entity.id}/rename" type: "POST" contentType: "application/json; charset=utf-8" data: JSON.stringify { name: name, _csrf: window.csrfToken } dataType: "json" success: () -> callback() failure: (error) -> callback(error) } deleteEntity: (entity, callback = (error) ->) -> # We'll wait for the socket.io notification to # delete from scope. $.ajax { url: "/project/#{@ide.project_id}/#{entity.type}/#{entity.id}" type: "DELETE" contentType: "application/json; charset=utf-8" headers: "X-Csrf-Token": window.csrfToken dataType: "json" success: () -> callback() failure: (error) -> callback(error) } moveEntity: (entity, parent_folder, callback = (error) ->) -> @_moveEntityInScope(entity, parent_folder) $.ajax { url: "/project/#{@ide.project_id}/#{entity.type}/#{entity.id}/move" type: "POST" contentType: "application/json; charset=utf-8" headers: "X-Csrf-Token": window.csrfToken data: JSON.stringify { folder_id: parent_folder.id } dataType: "json" success: () -> callback() failure: (error) -> callback(error) } _deleteEntityFromScope: (entity) -> parent_folder = null @forEachEntity (possible_entity, folder) -> if possible_entity == entity parent_folder = folder if parent_folder? index = parent_folder.children.indexOf(entity) if index > -1 parent_folder.children.splice(index, 1) _moveEntityInScope: (entity, parent_folder) -> return if entity in parent_folder.children @_deleteEntityFromScope(entity) parent_folder.children.push(entity)