mirror of
https://github.com/overleaf/overleaf.git
synced 2024-11-21 20:47:08 -05:00
Allow renaming of tags
This commit is contained in:
parent
1a86e69d1f
commit
1bd5aef85f
9 changed files with 201 additions and 44 deletions
|
@ -27,3 +27,15 @@ module.exports =
|
|||
TagsHandler.deleteTag user_id, tag_id, (error) ->
|
||||
return next(error) if error?
|
||||
res.status(204).end()
|
||||
|
||||
renameTag: (req, res, next) ->
|
||||
user_id = req.session.user._id
|
||||
tag_id = req.params.tag_id
|
||||
name = req.body?.name
|
||||
if !name?
|
||||
return res.status(400).end()
|
||||
else
|
||||
logger.log {user_id, tag_id, name}, "renaming tag"
|
||||
TagsHandler.renameTag user_id, tag_id, name, (error) ->
|
||||
return next(error) if error?
|
||||
res.status(204).end()
|
||||
|
|
|
@ -5,6 +5,23 @@ logger = require("logger-sharelatex")
|
|||
|
||||
oneSecond = 1000
|
||||
module.exports =
|
||||
renameTag: (user_id, tag_id, name, callback = (error) ->) ->
|
||||
url = "#{settings.apis.tags.url}/user/#{user_id}/tag/#{tag_id}/rename"
|
||||
request.post {
|
||||
url: url
|
||||
json:
|
||||
name: name
|
||||
}, (err, res, body) ->
|
||||
if err?
|
||||
logger.err {err, user_id, tag_id, name}, "error renaming tag in tag api"
|
||||
return callback(err)
|
||||
else if res.statusCode >= 200 and res.statusCode < 300
|
||||
return callback(null)
|
||||
else
|
||||
err = new Error("tags api returned a failure status code: #{res.statusCode}")
|
||||
logger.err {err, user_id, tag_id, name}, "tags api returned failure status code: #{res.statusCode}"
|
||||
return callback(err)
|
||||
|
||||
deleteTag: (user_id, tag_id, callback = (error) ->) ->
|
||||
url = "#{settings.apis.tags.url}/user/#{user_id}/tag/#{tag_id}"
|
||||
request.del url, (err, res, body) ->
|
||||
|
|
|
@ -134,6 +134,7 @@ module.exports = class Router
|
|||
webRouter.get '/tag', AuthenticationController.requireLogin(), TagsController.getAllTags
|
||||
webRouter.post '/project/:project_id/tag', AuthenticationController.requireLogin(), TagsController.processTagsUpdate
|
||||
webRouter.delete '/tag/:tag_id', AuthenticationController.requireLogin(), TagsController.deleteTag
|
||||
webRouter.post '/tag/:tag_id/rename', AuthenticationController.requireLogin(), TagsController.renameTag
|
||||
|
||||
# Deprecated in favour of /internal/project/:project_id but still used by versioning
|
||||
apiRouter.get '/project/:project_id/details', AuthenticationController.httpAuth, ProjectApiController.getProjectDetails
|
||||
|
|
|
@ -56,6 +56,35 @@ script(type='text/ng-template', id='deleteTagModalTemplate')
|
|||
span(ng-show="state.inflight") #{translate("deleting")}...
|
||||
span(ng-show="!state.inflight") #{translate("delete")}
|
||||
|
||||
script(type='text/ng-template', id='renameTagModalTemplate')
|
||||
.modal-header
|
||||
button.close(
|
||||
type="button"
|
||||
data-dismiss="modal"
|
||||
ng-click="cancel()"
|
||||
) ×
|
||||
h3 #{translate("rename_tag")}
|
||||
.modal-body
|
||||
form(name="renameTagForm", novalidate)
|
||||
input.form-control(
|
||||
type="text",
|
||||
placeholder="Tag Name",
|
||||
ng-model="inputs.tagName",
|
||||
required,
|
||||
on-enter="rename()",
|
||||
focus-on="open"
|
||||
)
|
||||
.modal-footer
|
||||
.modal-footer-left
|
||||
span.text-danger.error(ng-show="state.error") #{translate("generic_something_went_wrong")}
|
||||
button.btn.btn-default(ng-click="cancel()") #{translate("cancel")}
|
||||
button.btn.btn-primary(
|
||||
ng-click="rename()",
|
||||
ng-disabled="renameTagForm.$invalid || state.inflight"
|
||||
)
|
||||
span(ng-show="!state.inflight") #{translate("rename")}
|
||||
span(ng-show="state.inflight") #{translate("renaming")}...
|
||||
|
||||
script(type='text/ng-template', id='renameProjectModalTemplate')
|
||||
.modal-header
|
||||
button.close(
|
||||
|
|
|
@ -74,10 +74,10 @@
|
|||
role="menu"
|
||||
)
|
||||
li
|
||||
a(href)
|
||||
a(href, ng-click="renameTag(tag)", stop-propagation="click")
|
||||
| #{translate("rename")}
|
||||
li
|
||||
a(href, ng-click="deleteTag(tag)")
|
||||
a(href, ng-click="deleteTag(tag)", stop-propagation="click")
|
||||
| #{translate("delete")}
|
||||
li(ng-cloak)
|
||||
a.tag(href, ng-click="openNewTagModal()")
|
||||
|
|
|
@ -1,23 +1,6 @@
|
|||
define [
|
||||
"base"
|
||||
], (App) ->
|
||||
|
||||
|
||||
App.controller 'NewTagModalController', ($scope, $modalInstance, $timeout) ->
|
||||
$scope.inputs =
|
||||
newTagName: ""
|
||||
|
||||
$modalInstance.opened.then () ->
|
||||
$timeout () ->
|
||||
$scope.$broadcast "open"
|
||||
, 200
|
||||
|
||||
$scope.create = () ->
|
||||
$modalInstance.close($scope.inputs.newTagName)
|
||||
|
||||
$scope.cancel = () ->
|
||||
$modalInstance.dismiss('cancel')
|
||||
|
||||
App.controller 'RenameProjectModalController', ($scope, $modalInstance, $timeout, projectName) ->
|
||||
$scope.inputs =
|
||||
projectName: projectName
|
||||
|
@ -102,28 +85,3 @@ define [
|
|||
$scope.onComplete = (error, name, response) ->
|
||||
if response.project_id?
|
||||
window.location = '/project/' + response.project_id
|
||||
|
||||
App.controller 'DeleteTagModalController', ($scope, $modalInstance, $http, tag) ->
|
||||
$scope.tag = tag
|
||||
$scope.state =
|
||||
inflight: false
|
||||
error: false
|
||||
|
||||
$scope.delete = () ->
|
||||
$scope.state.inflight = true
|
||||
$scope.state.error = false
|
||||
$http({
|
||||
method: "DELETE"
|
||||
url: "/tag/#{tag._id}"
|
||||
headers:
|
||||
"X-CSRF-Token": window.csrfToken
|
||||
})
|
||||
.success () ->
|
||||
$scope.state.inflight = false
|
||||
$modalInstance.close()
|
||||
.error () ->
|
||||
$scope.state.inflight = false
|
||||
$scope.state.error = true
|
||||
|
||||
$scope.cancel = () ->
|
||||
$modalInstance.dismiss('cancel')
|
|
@ -25,6 +25,17 @@ define [
|
|||
)
|
||||
modalInstance.result.then () ->
|
||||
$scope.tags = $scope.tags.filter (t) -> t != tag
|
||||
|
||||
$scope.renameTag = (tag) ->
|
||||
modalInstance = $modal.open(
|
||||
templateUrl: "renameTagModalTemplate"
|
||||
controller: "RenameTagModalController"
|
||||
resolve:
|
||||
tag: () -> tag
|
||||
existing_tags: () -> $scope.tags
|
||||
)
|
||||
modalInstance.result.then (new_name) ->
|
||||
tag.name = new_name
|
||||
|
||||
App.controller "TagDropdownItemController", ($scope) ->
|
||||
$scope.recalculateProjectsInTag = () ->
|
||||
|
@ -49,3 +60,75 @@ define [
|
|||
$scope.$watch "selectedProjects", () ->
|
||||
$scope.recalculateProjectsInTag()
|
||||
$scope.recalculateProjectsInTag()
|
||||
|
||||
App.controller 'NewTagModalController', ($scope, $modalInstance, $timeout) ->
|
||||
$scope.inputs =
|
||||
newTagName: ""
|
||||
|
||||
$modalInstance.opened.then () ->
|
||||
$timeout () ->
|
||||
$scope.$broadcast "open"
|
||||
, 200
|
||||
|
||||
$scope.create = () ->
|
||||
$modalInstance.close($scope.inputs.newTagName)
|
||||
|
||||
$scope.cancel = () ->
|
||||
$modalInstance.dismiss('cancel')
|
||||
|
||||
App.controller 'RenameTagModalController', ($scope, $modalInstance, $timeout, $http, tag, existing_tags) ->
|
||||
$scope.inputs =
|
||||
tagName: tag.name
|
||||
|
||||
$scope.state =
|
||||
inflight: false
|
||||
error: false
|
||||
|
||||
$modalInstance.opened.then () ->
|
||||
$timeout () ->
|
||||
$scope.$broadcast "open"
|
||||
, 200
|
||||
|
||||
$scope.rename = () ->
|
||||
name = $scope.inputs.tagName
|
||||
$scope.state.inflight = true
|
||||
$scope.state.error = false
|
||||
$http
|
||||
.post "/tag/#{tag._id}/rename", {
|
||||
_csrf: window.csrfToken,
|
||||
name: name
|
||||
}
|
||||
.success () ->
|
||||
$scope.state.inflight = false
|
||||
$modalInstance.close(name)
|
||||
.error () ->
|
||||
$scope.state.inflight = false
|
||||
$scope.state.error = true
|
||||
|
||||
$scope.cancel = () ->
|
||||
$modalInstance.dismiss('cancel')
|
||||
|
||||
App.controller 'DeleteTagModalController', ($scope, $modalInstance, $http, tag) ->
|
||||
$scope.tag = tag
|
||||
$scope.state =
|
||||
inflight: false
|
||||
error: false
|
||||
|
||||
$scope.delete = () ->
|
||||
$scope.state.inflight = true
|
||||
$scope.state.error = false
|
||||
$http({
|
||||
method: "DELETE"
|
||||
url: "/tag/#{tag._id}"
|
||||
headers:
|
||||
"X-CSRF-Token": window.csrfToken
|
||||
})
|
||||
.success () ->
|
||||
$scope.state.inflight = false
|
||||
$modalInstance.close()
|
||||
.error () ->
|
||||
$scope.state.inflight = false
|
||||
$scope.state.error = true
|
||||
|
||||
$scope.cancel = () ->
|
||||
$modalInstance.dismiss('cancel')
|
||||
|
|
|
@ -15,6 +15,7 @@ describe 'Tags controller', ->
|
|||
addTag: sinon.stub().callsArgWith(3)
|
||||
removeProject: sinon.stub().callsArgWith(3)
|
||||
deleteTag: sinon.stub().callsArg(2)
|
||||
renameTag: sinon.stub().callsArg(3)
|
||||
@controller = SandboxedModule.require modulePath, requires:
|
||||
"./TagsHandler":@handler
|
||||
'logger-sharelatex':
|
||||
|
@ -68,3 +69,34 @@ describe 'Tags controller', ->
|
|||
it "should return 204 status code", ->
|
||||
@res.status.calledWith(204).should.equal true
|
||||
@res.end.called.should.equal true
|
||||
|
||||
describe "renameTag", ->
|
||||
beforeEach ->
|
||||
@req.params.tag_id = @tag_id = "tag-id-123"
|
||||
@req.session.user._id = @user_id = "user-id-123"
|
||||
|
||||
describe "with a name", ->
|
||||
beforeEach ->
|
||||
@req.body = name: @name = "new-name"
|
||||
@controller.renameTag @req, @res
|
||||
|
||||
it "should delete the tag in the backend", ->
|
||||
@handler.renameTag
|
||||
.calledWith(@user_id, @tag_id, @name)
|
||||
.should.equal true
|
||||
|
||||
it "should return 204 status code", ->
|
||||
@res.status.calledWith(204).should.equal true
|
||||
@res.end.called.should.equal true
|
||||
|
||||
describe "without a name", ->
|
||||
beforeEach ->
|
||||
@controller.renameTag @req, @res
|
||||
|
||||
it "should not call the backend", ->
|
||||
@handler.renameTag.called.should.equal false
|
||||
|
||||
it "should return 400 (bad request) status code", ->
|
||||
@res.status.calledWith(400).should.equal true
|
||||
@res.end.called.should.equal true
|
||||
|
|
@ -126,4 +126,29 @@ describe 'TagsHandler', ->
|
|||
|
||||
it "should call the callback with an Error", ->
|
||||
@callback.calledWith(new Error()).should.equal true
|
||||
|
||||
describe "renameTag", ->
|
||||
describe "successfully", ->
|
||||
beforeEach ->
|
||||
@request.post = sinon.stub().callsArgWith(1, null, {statusCode: 204}, "")
|
||||
@handler.renameTag user_id, tag_id, @name = "new-name", @callback
|
||||
|
||||
it "should send a request to the tag backend", ->
|
||||
@request.post
|
||||
.calledWith({
|
||||
url: "#{tagsUrl}/user/#{user_id}/tag/#{tag_id}/rename"
|
||||
json:
|
||||
name: @name
|
||||
})
|
||||
.should.equal true
|
||||
|
||||
it "should call the callback with no error", ->
|
||||
@callback.calledWith(null).should.equal true
|
||||
|
||||
describe "with error", ->
|
||||
beforeEach ->
|
||||
@request.post = sinon.stub().callsArgWith(1, null, {statusCode: 500}, "")
|
||||
@handler.renameTag user_id, tag_id, "name", @callback
|
||||
|
||||
it "should call the callback with an Error", ->
|
||||
@callback.calledWith(new Error()).should.equal true
|
||||
|
|
Loading…
Reference in a new issue