mirror of
https://github.com/overleaf/overleaf.git
synced 2024-11-21 20:47:08 -05:00
Rename files
This commit is contained in:
parent
f1eee96c85
commit
242a866bce
14 changed files with 163 additions and 20 deletions
|
@ -36,3 +36,31 @@ module.exports = EditorHttpController =
|
||||||
EditorController.addFolder project_id, parent_folder_id, name, (error, doc) ->
|
EditorController.addFolder project_id, parent_folder_id, name, (error, doc) ->
|
||||||
return next(error) if error?
|
return next(error) if error?
|
||||||
res.json doc
|
res.json doc
|
||||||
|
|
||||||
|
renameEntity: (req, res, next) ->
|
||||||
|
project_id = req.params.Project_id
|
||||||
|
entity_id = req.params.entity_id
|
||||||
|
entity_type = req.params.entity_type
|
||||||
|
name = req.body.name
|
||||||
|
EditorController.renameEntity project_id, entity_id, entity_type, name, (error) ->
|
||||||
|
return next(error) if error?
|
||||||
|
res.send 204
|
||||||
|
|
||||||
|
moveEntity: (req, res, next) ->
|
||||||
|
project_id = req.params.Project_id
|
||||||
|
entity_id = req.params.entity_id
|
||||||
|
entity_type = req.params.entity_type
|
||||||
|
folder_id = req.body.folder_id
|
||||||
|
EditorController.moveEntity project_id, entity_id, folder_id, entity_type, (error) ->
|
||||||
|
return next(error) if error?
|
||||||
|
res.send 204
|
||||||
|
|
||||||
|
deleteEntity: (req, res, next) ->
|
||||||
|
project_id = req.params.Project_id
|
||||||
|
entity_id = req.params.entity_id
|
||||||
|
entity_type = req.params.entity_type
|
||||||
|
EditorController.deleteEntity project_id, entity_id, entity_type, (error) ->
|
||||||
|
return next(error) if error?
|
||||||
|
res.send 204
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -90,6 +90,10 @@ module.exports = class Router
|
||||||
app.post '/project/:Project_id/doc', SecurityManager.requestCanModifyProject, EditorHttpController.addDoc
|
app.post '/project/:Project_id/doc', SecurityManager.requestCanModifyProject, EditorHttpController.addDoc
|
||||||
app.post '/project/:Project_id/folder', SecurityManager.requestCanModifyProject, EditorHttpController.addFolder
|
app.post '/project/:Project_id/folder', SecurityManager.requestCanModifyProject, EditorHttpController.addFolder
|
||||||
|
|
||||||
|
app.post '/project/:Project_id/:entity_type/:entity_id/rename', SecurityManager.requestCanModifyProject, EditorHttpController.renameEntity
|
||||||
|
app.post '/project/:Project_id/:entity_type/:entity_id/move', SecurityManager.requestCanModifyProject, EditorHttpController.moveEntity
|
||||||
|
app.post '/project/:Project_id/:entity_type/:entity_id/delete', SecurityManager.requestCanModifyProject, EditorHttpController.deleteEntity
|
||||||
|
|
||||||
app.post '/project/:Project_id/compile', SecurityManager.requestCanAccessProject, CompileController.compile
|
app.post '/project/:Project_id/compile', SecurityManager.requestCanAccessProject, CompileController.compile
|
||||||
app.get '/Project/:Project_id/output/output.pdf', SecurityManager.requestCanAccessProject, CompileController.downloadPdf
|
app.get '/Project/:Project_id/output/output.pdf', SecurityManager.requestCanAccessProject, CompileController.downloadPdf
|
||||||
app.get /^\/project\/([^\/]*)\/output\/(.*)$/,
|
app.get /^\/project\/([^\/]*)\/output\/(.*)$/,
|
||||||
|
|
|
@ -15,7 +15,6 @@ block scripts
|
||||||
block content
|
block content
|
||||||
|
|
||||||
.editor(ng-controller="IdeController")
|
.editor(ng-controller="IdeController")
|
||||||
|
|
||||||
.loading-screen(ng-show="state.loading")
|
.loading-screen(ng-show="state.loading")
|
||||||
.container
|
.container
|
||||||
h3 Loading...
|
h3 Loading...
|
||||||
|
|
|
@ -23,7 +23,12 @@ aside#file-tree.ui-layout-west(ng-controller="FileTreeController")
|
||||||
i.fa.fa-upload
|
i.fa.fa-upload
|
||||||
|
|
||||||
.toolbar-right
|
.toolbar-right
|
||||||
a(href, tooltip="Rename", tooltip-placement="bottom")
|
a(
|
||||||
|
href,
|
||||||
|
ng-click="startRenamingSelected()",
|
||||||
|
tooltip="Rename",
|
||||||
|
tooltip-placement="bottom"
|
||||||
|
)
|
||||||
i.fa.fa-pencil
|
i.fa.fa-pencil
|
||||||
a(href, tooltip="Delete", tooltip-placement="bottom", tooltip-append-to-body="true")
|
a(href, tooltip="Delete", tooltip-placement="bottom", tooltip-append-to-body="true")
|
||||||
i.fa.fa-trash-o
|
i.fa.fa-trash-o
|
||||||
|
@ -41,11 +46,23 @@ script(type='text/ng-template', id='entityListItemTemplate')
|
||||||
ng-controller="FileTreeEntityController"
|
ng-controller="FileTreeEntityController"
|
||||||
)
|
)
|
||||||
.entity(ng-if="entity.type == 'doc'")
|
.entity(ng-if="entity.type == 'doc'")
|
||||||
.entity-name(ng-click="select()")
|
.entity-name(
|
||||||
|
ng-click="select()"
|
||||||
|
ng-dblclick="startRenaming()"
|
||||||
|
)
|
||||||
//- Just a spacer to align with folders
|
//- Just a spacer to align with folders
|
||||||
i.fa.fa-fw.toggle
|
i.fa.fa-fw.toggle
|
||||||
i.fa.fa-fw.fa-file
|
i.fa.fa-fw.fa-file
|
||||||
| {{ entity.name }}
|
span(
|
||||||
|
ng-hide="entity.renaming"
|
||||||
|
) {{ entity.name }}
|
||||||
|
input(
|
||||||
|
ng-show="entity.renaming",
|
||||||
|
ng-model="inputs.name",
|
||||||
|
ng-blur="finishRenaming()",
|
||||||
|
focus-input="entity.renaming",
|
||||||
|
on-enter="finishRenaming()"
|
||||||
|
)
|
||||||
|
|
||||||
.entity(ng-if="entity.type == 'file'")
|
.entity(ng-if="entity.type == 'file'")
|
||||||
.entity-name(ng-click="select()")
|
.entity-name(ng-click="select()")
|
||||||
|
@ -82,7 +99,7 @@ script(type='text/ng-template', id='newDocModalTemplate')
|
||||||
placeholder="File Name",
|
placeholder="File Name",
|
||||||
required,
|
required,
|
||||||
ng-model="inputs.name",
|
ng-model="inputs.name",
|
||||||
ng-enter="create()",
|
on-enter="create()",
|
||||||
focus-on="open"
|
focus-on="open"
|
||||||
)
|
)
|
||||||
.modal-footer
|
.modal-footer
|
||||||
|
@ -107,7 +124,7 @@ script(type='text/ng-template', id='newFolderModalTemplate')
|
||||||
placeholder="Folder Name",
|
placeholder="Folder Name",
|
||||||
required,
|
required,
|
||||||
ng-model="inputs.name",
|
ng-model="inputs.name",
|
||||||
ng-enter="create()",
|
on-enter="create()",
|
||||||
focus-on="open"
|
focus-on="open"
|
||||||
)
|
)
|
||||||
.modal-footer
|
.modal-footer
|
||||||
|
|
|
@ -312,7 +312,7 @@ block content
|
||||||
placeholder="New Folder Name",
|
placeholder="New Folder Name",
|
||||||
required,
|
required,
|
||||||
ng-model="inputs.newTagName",
|
ng-model="inputs.newTagName",
|
||||||
ng-enter="create()",
|
on-enter="create()",
|
||||||
focus-on="open"
|
focus-on="open"
|
||||||
)
|
)
|
||||||
.modal-footer
|
.modal-footer
|
||||||
|
@ -332,7 +332,7 @@ block content
|
||||||
placeholder="Project Name",
|
placeholder="Project Name",
|
||||||
ng-model="inputs.projectName",
|
ng-model="inputs.projectName",
|
||||||
required,
|
required,
|
||||||
ng-enter="rename()",
|
on-enter="rename()",
|
||||||
focus-on="open"
|
focus-on="open"
|
||||||
)
|
)
|
||||||
.modal-footer
|
.modal-footer
|
||||||
|
@ -354,7 +354,7 @@ block content
|
||||||
placeholder="New Project Name",
|
placeholder="New Project Name",
|
||||||
required,
|
required,
|
||||||
ng-model="inputs.projectName",
|
ng-model="inputs.projectName",
|
||||||
ng-enter="clone()",
|
on-enter="clone()",
|
||||||
focus-on="open"
|
focus-on="open"
|
||||||
)
|
)
|
||||||
.modal-footer
|
.modal-footer
|
||||||
|
@ -379,7 +379,7 @@ block content
|
||||||
placeholder="Project Name",
|
placeholder="Project Name",
|
||||||
required,
|
required,
|
||||||
ng-model="inputs.projectName",
|
ng-model="inputs.projectName",
|
||||||
ng-enter="create()",
|
on-enter="create()",
|
||||||
focus-on="open"
|
focus-on="open"
|
||||||
)
|
)
|
||||||
.modal-footer
|
.modal-footer
|
||||||
|
|
10
services/web/public/coffee/app/directives/onEnter.coffee
Normal file
10
services/web/public/coffee/app/directives/onEnter.coffee
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
define [
|
||||||
|
"base"
|
||||||
|
], (App) ->
|
||||||
|
App.directive 'onEnter', () ->
|
||||||
|
return (scope, element, attrs) ->
|
||||||
|
element.bind "keydown keypress", (event) ->
|
||||||
|
if event.which == 13
|
||||||
|
scope.$apply () ->
|
||||||
|
scope.$eval(attrs.onEnter, event: event)
|
||||||
|
event.preventDefault()
|
|
@ -4,7 +4,9 @@ define [
|
||||||
"ide/directives/layout"
|
"ide/directives/layout"
|
||||||
"ide/services/ide"
|
"ide/services/ide"
|
||||||
"directives/focusOn"
|
"directives/focusOn"
|
||||||
|
"directives/focusInput"
|
||||||
"directives/fineUpload"
|
"directives/fineUpload"
|
||||||
|
"directives/onEnter"
|
||||||
], (
|
], (
|
||||||
App
|
App
|
||||||
FileTreeManager
|
FileTreeManager
|
||||||
|
|
|
@ -154,3 +154,20 @@ define [
|
||||||
callback(null, folder)
|
callback(null, folder)
|
||||||
failure: (error) -> callback(error)
|
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)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,6 +24,9 @@ define [
|
||||||
$scope.orderByFoldersFirst = (entity) ->
|
$scope.orderByFoldersFirst = (entity) ->
|
||||||
return 0 if entity.type == "folder"
|
return 0 if entity.type == "folder"
|
||||||
return 1
|
return 1
|
||||||
|
|
||||||
|
$scope.startRenamingSelected = () ->
|
||||||
|
$scope.$broadcast "rename:selected"
|
||||||
]
|
]
|
||||||
|
|
||||||
App.controller "NewDocModalController", [
|
App.controller "NewDocModalController", [
|
||||||
|
|
|
@ -2,8 +2,21 @@ define [
|
||||||
"base"
|
"base"
|
||||||
], (App) ->
|
], (App) ->
|
||||||
App.controller "FileTreeEntityController", ["$scope", "ide", ($scope, ide) ->
|
App.controller "FileTreeEntityController", ["$scope", "ide", ($scope, ide) ->
|
||||||
$scope.select = ($event) ->
|
$scope.select = () ->
|
||||||
ide.fileTreeManager.forEachEntity (entity) ->
|
ide.fileTreeManager.forEachEntity (entity) ->
|
||||||
entity.selected = false
|
entity.selected = false
|
||||||
$scope.entity.selected = true
|
$scope.entity.selected = true
|
||||||
|
|
||||||
|
$scope.inputs =
|
||||||
|
name: $scope.entity.name
|
||||||
|
|
||||||
|
$scope.startRenaming = () ->
|
||||||
|
$scope.entity.renaming = true
|
||||||
|
|
||||||
|
$scope.finishRenaming = () ->
|
||||||
|
delete $scope.entity.renaming
|
||||||
|
ide.fileTreeManager.renameEntity($scope.entity, $scope.inputs.name)
|
||||||
|
|
||||||
|
$scope.$on "rename:selected", () ->
|
||||||
|
$scope.startRenaming() if $scope.entity.selected
|
||||||
]
|
]
|
|
@ -8,5 +8,6 @@ define [
|
||||||
"directives/focusOn"
|
"directives/focusOn"
|
||||||
"directives/equals"
|
"directives/equals"
|
||||||
"directives/fineUpload"
|
"directives/fineUpload"
|
||||||
|
"directives/onEnter"
|
||||||
], () ->
|
], () ->
|
||||||
angular.bootstrap(document.body, ["SharelatexApp"])
|
angular.bootstrap(document.body, ["SharelatexApp"])
|
|
@ -1,14 +1,6 @@
|
||||||
define [
|
define [
|
||||||
"base"
|
"base"
|
||||||
], (App) ->
|
], (App) ->
|
||||||
App.directive 'ngEnter', () ->
|
|
||||||
return (scope, element, attrs) ->
|
|
||||||
element.bind "keydown keypress", (event) ->
|
|
||||||
if event.which == 13
|
|
||||||
scope.$apply () ->
|
|
||||||
scope.$eval(attrs.ngEnter, event: event)
|
|
||||||
event.preventDefault()
|
|
||||||
|
|
||||||
App.filter "formatDate", () ->
|
App.filter "formatDate", () ->
|
||||||
(date, format = "Do MMM YYYY, h:mm a") ->
|
(date, format = "Do MMM YYYY, h:mm a") ->
|
||||||
moment(date).format(format)
|
moment(date).format(format)
|
||||||
|
|
|
@ -96,6 +96,9 @@
|
||||||
&:hover {
|
&:hover {
|
||||||
background-color: @gray-lightest;
|
background-color: @gray-lightest;
|
||||||
}
|
}
|
||||||
|
input {
|
||||||
|
line-height: 1.6;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
i.fa-folder-open, i.fa-folder {
|
i.fa-folder-open, i.fa-folder {
|
||||||
|
|
|
@ -89,3 +89,57 @@ describe "EditorHttpController", ->
|
||||||
.calledWith(@folder)
|
.calledWith(@folder)
|
||||||
.should.equal true
|
.should.equal true
|
||||||
|
|
||||||
|
describe "renameEntity", ->
|
||||||
|
beforeEach ->
|
||||||
|
@req.params =
|
||||||
|
Project_id: @project_id
|
||||||
|
entity_id: @entity_id = "entity-id-123"
|
||||||
|
entity_type: @entity_type = "entity-type"
|
||||||
|
@req.body =
|
||||||
|
name: @name = "new-name"
|
||||||
|
@EditorController.renameEntity = sinon.stub().callsArg(4)
|
||||||
|
@EditorHttpController.renameEntity @req, @res
|
||||||
|
|
||||||
|
it "should call EditorController.renameEntity", ->
|
||||||
|
@EditorController.renameEntity
|
||||||
|
.calledWith(@project_id, @entity_id, @entity_type, @name)
|
||||||
|
.should.equal true
|
||||||
|
|
||||||
|
it "should send back a success response", ->
|
||||||
|
@res.send.calledWith(204).should.equal true
|
||||||
|
|
||||||
|
describe "moveEntity", ->
|
||||||
|
beforeEach ->
|
||||||
|
@req.params =
|
||||||
|
Project_id: @project_id
|
||||||
|
entity_id: @entity_id = "entity-id-123"
|
||||||
|
entity_type: @entity_type = "entity-type"
|
||||||
|
@req.body =
|
||||||
|
folder_id: @folder_id = "folder-id-123"
|
||||||
|
@EditorController.moveEntity = sinon.stub().callsArg(4)
|
||||||
|
@EditorHttpController.moveEntity @req, @res
|
||||||
|
|
||||||
|
it "should call EditorController.moveEntity", ->
|
||||||
|
@EditorController.moveEntity
|
||||||
|
.calledWith(@project_id, @entity_id, @folder_id, @entity_type)
|
||||||
|
.should.equal true
|
||||||
|
|
||||||
|
it "should send back a success response", ->
|
||||||
|
@res.send.calledWith(204).should.equal true
|
||||||
|
|
||||||
|
describe "deleteEntity", ->
|
||||||
|
beforeEach ->
|
||||||
|
@req.params =
|
||||||
|
Project_id: @project_id
|
||||||
|
entity_id: @entity_id = "entity-id-123"
|
||||||
|
entity_type: @entity_type = "entity-type"
|
||||||
|
@EditorController.deleteEntity = sinon.stub().callsArg(3)
|
||||||
|
@EditorHttpController.deleteEntity @req, @res
|
||||||
|
|
||||||
|
it "should call EditorController.deleteEntity", ->
|
||||||
|
@EditorController.deleteEntity
|
||||||
|
.calledWith(@project_id, @entity_id, @entity_type)
|
||||||
|
.should.equal true
|
||||||
|
|
||||||
|
it "should send back a success response", ->
|
||||||
|
@res.send.calledWith(204).should.equal true
|
||||||
|
|
Loading…
Reference in a new issue