Add in restore button to track changes

This commit is contained in:
James Allen 2014-03-11 12:13:46 +00:00
parent e364fd9c5f
commit afb8bb6a42
12 changed files with 113 additions and 27 deletions

View file

@ -6,7 +6,7 @@ module.exports = TrackChangesController =
proxyToTrackChangesApi: (req, res, next = (error) ->) ->
url = settings.apis.trackchanges.url + req.url
logger.log url: url, "proxying to track-changes api"
getReq = request.get(url)
getReq = request(url: url, method: req.method)
getReq.pipe(res)
getReq.on "error", (error) ->
logger.error err: error, "track-changes API error"

View file

@ -125,6 +125,7 @@ module.exports = class Router
app.get "/project/:Project_id/doc/:doc_id/updates", SecutiryManager.requestCanAccessProject, TrackChangesController.proxyToTrackChangesApi
app.get "/project/:Project_id/doc/:doc_id/diff", SecutiryManager.requestCanAccessProject, TrackChangesController.proxyToTrackChangesApi
app.post "/project/:Project_id/doc/:doc_id/version/:version_id/restore", SecutiryManager.requestCanAccessProject, TrackChangesController.proxyToTrackChangesApi
app.post '/project/:project_id/leave', AuthenticationController.requireLogin(), CollaboratorsController.removeSelfFromProject
app.get '/project/:Project_id/collaborators', SecutiryManager.requestCanAccessProject(allow_auth_token: true), CollaboratorsController.getCollaborators

View file

@ -140,8 +140,7 @@
button.btn.btn-primary ok
script(type="text/template")#genericModalButtonTemplate
a(href="#",class="btn {{ class }}") {{ text }}
button(class="btn {{ class }}") {{ text }}
script(type="text/template")#editorPanelTemplate
#editorArea(style='display: none;')
@ -445,6 +444,9 @@
div.color-square(style="background-color: hsl({{hue}}, 100%, 70%);")
span {{name}}
div(class='restore')
a(href="#") Restore to here
script(type='text/template')#changeListTemplate
ul.change-list.nav.nav-pills.nav-stacked
li.loading-changes Loading...

View file

@ -144,6 +144,11 @@ define [
# it's not the root folder so keep going
path = entity.get("name") + "/" + path
return path
getNameOfEntityId: (entity_id) ->
entity = @getEntity(entity_id)
return if !entity?
return entity.get("name")
# RENAMING
renameSelected: () ->

View file

@ -49,4 +49,7 @@ define [
find: (id) ->
@loadedModel ||= {}
return @loadedModel[id]
getAnonymousUser: () ->
return User.findOrBuild("anonymous", { first_name: "Anonymous", email: "anon@sharelatex.com" })
}

View file

@ -70,6 +70,9 @@ define [
delete @hoverFromIndex
@resetHoverStates()
view.on "click:restore", (e) =>
@trigger "restore", view.model
view.resetSelector(index, @selectedFromIndex, @selectedToIndex)
resetAllSelectors: () ->
@ -77,11 +80,11 @@ define [
view.resetSelector(i, @selectedFromIndex, @selectedToIndex)
resetHoverStates: () ->
if @hoverToIndex?
if @hoverToIndex? and @hoverToIndex != @selectedToIndex
@$("ul").addClass("hover-state")
for view, i in @itemViews
view.resetHoverState(i, @selectedFromIndex, @hoverToIndex)
else if @hoverFromIndex?
else if @hoverFromIndex? and @hoverFromIndex != @selectedFromIndex
@$("ul").addClass("hover-state")
for view, i in @itemViews
view.resetHoverState(i, @hoverFromIndex, @selectedToIndex)
@ -152,6 +155,7 @@ define [
@trigger "mouseenter:from", args...
"mouseleave .change-selector-from": (args...) ->
@trigger "mouseleave:from", args...
"click .restore a": "onRestoreClick"
template : $("#changeListItemTemplate").html()
@ -183,6 +187,10 @@ define [
onFromSelectorClick: (e) ->
@trigger "selected:from", e, @
onRestoreClick: (e) ->
e.preventDefault()
@trigger "click:restore", e, @
isSelectedFrom: () ->
@$(".change-selector-from").is(":checked")

View file

@ -3,21 +3,23 @@ define [
"track-changes/models/Diff"
"track-changes/ChangeListView"
"track-changes/DiffView"
], (ChangeList, Diff, ChangeListView, DiffView) ->
"utils/Modal"
"moment"
], (ChangeList, Diff, ChangeListView, DiffView, Modal, moment) ->
class TrackChangesManager
template: $("#trackChangesPanelTemplate").html()
constructor: (@ide) ->
@$el = $(@template)
$("#editorWrapper").append(@$el)
@hideEl()
@hide()
@ide.editor.on "change:doc", () =>
@hideEl()
@hide()
@$el.find(".track-changes-close").on "click", (e) =>
e.preventDefault
@hideEl()
@hide()
show: () ->
@project_id = window.userSettings.project_id
@ -44,14 +46,50 @@ define [
)
@diff.fetch()
@changeListView.on "restore", (change) =>
@restore(change)
@showEl()
showEl: ->
@ide.editor.hide()
@$el.show()
hideEl: () ->
hide: () ->
@ide.editor.show()
@$el.hide()
restore: (change) ->
name = @ide.fileTreeManager.getNameOfEntityId(@doc_id)
date = moment(change.get("start_ts")).format("Do MMM YYYY, h:mm:ss a")
modal = new Modal({
title: "Restore document"
message: "Are you sure you want to restore <strong>#{name}</strong> to before the changes on #{date}"
buttons: [{
text: "Cancel"
}, {
text: "Restore"
class: "btn-success"
close: false
callback: ($button) =>
$button.text("Restoring...")
$button.prop("disabled", true)
@doRestore change.get("version"), (error) =>
modal.remove()
@hide()
}]
})
doRestore: (version, callback = (error) ->) ->
$.ajax {
url: "/project/#{@project_id}/doc/#{@doc_id}/version/#{version}/restore"
type: "POST"
headers:
"X-CSRF-Token": window.csrfToken
success: () ->
callback()
error: (error) ->
callback(error)
}
return TrackChangesManager

View file

@ -4,9 +4,13 @@ define [
], (User)->
Change = Backbone.Model.extend
parse: (change) ->
return {
model = {
start_ts: change.meta.start_ts
end_ts: change.meta.end_ts
user: User.findOrBuild(change.meta.user.id, change.meta.user)
version: change.v
}
}
if change.meta.user?
model.user = User.findOrBuild(change.meta.user.id, change.meta.user)
else
model.user = User.getAnonymousUser()
return model

View file

@ -8,6 +8,9 @@ define [
parse: (diff) ->
for entry in diff.diff
if entry.meta? and entry.meta.user?
entry.meta.user = User.findOrBuild(entry.meta.user.id, entry.meta.user)
if entry.meta?
if entry.meta.user?
entry.meta.user = User.findOrBuild(entry.meta.user.id, entry.meta.user)
else
entry.meta.user = User.getAnonymousUser()
return diff

View file

@ -19,8 +19,9 @@ define [
button.on "click", (e) ->
e.preventDefault()
if buttonOptions.callback?
buttonOptions.callback()
self.remove()
buttonOptions.callback(button)
if !buttonOptions.close? or buttonOptions.close
self.remove()
@$el.modal
# make sure we control when the modal is hidden
@ -39,7 +40,6 @@ define [
@$el.find('input').focus()
remove: () ->
@$el.modal("hide")
Backbone.View.prototype.remove.call(this)

View file

@ -71,11 +71,9 @@
ul.change-list {
li {
padding: 6px 4px;
position: relative;
border-bottom: 1px solid #ccc;
cursor: pointer;
min-height: 38px;
.change-selectors {
.change-selector-from {
position: absolute;
@ -98,7 +96,8 @@
}
}
.change-description {
padding-left: 26px;
padding: 6px 4px 6px 30px;
min-height: 38px;
}
.change-name {
font-size: 0.9em;
@ -112,6 +111,15 @@
margin-right: 4px;
margin-bottom: -1px;
}
.restore {
a {
display: block;
padding: 4px;
text-align: center;
border-top: 1px solid #ccc;
}
display: none;
}
&:hover {
background-color: #eaeaea;
}
@ -137,12 +145,16 @@
li.selected-from {
.change-selectors {
.range {
bottom: 10px;
bottom: 37px;
}
.change-selector-from {
opacity: 1;
bottom: 32px;
}
}
.restore {
display: block;
}
}
}
ul.change-list.hover-state {
@ -182,5 +194,12 @@
}
}
}
li.selected-from.hover-selected-from {
.change-selectors {
.range {
bottom: 37px;
}
}
}
}
}

View file

@ -7,13 +7,13 @@ SandboxedModule = require('sandboxed-module')
describe "TrackChangesController", ->
beforeEach ->
@TrackChangesController = SandboxedModule.require modulePath, requires:
"request" : @request = {}
"request" : @request = sinon.stub()
"settings-sharelatex": @settings = {}
"logger-sharelatex": @logger = {log: sinon.stub(), error: sinon.stub()}
describe "proxyToTrackChangesApi", ->
beforeEach ->
@req = { url: "/mock/url" }
@req = { url: "/mock/url", method: "POST" }
@res = "mock-res"
@next = sinon.stub()
@settings.apis =
@ -23,13 +23,16 @@ describe "TrackChangesController", ->
events: {}
pipe: sinon.stub()
on: (event, handler) -> @events[event] = handler
@request.get = sinon.stub().returns @proxy
@request.returns @proxy
@TrackChangesController.proxyToTrackChangesApi @req, @res, @next
describe "successfully", ->
it "should call the track changes api", ->
@request.get
.calledWith("#{@settings.apis.trackchanges.url}#{@req.url}")
@request
.calledWith({
url: "#{@settings.apis.trackchanges.url}#{@req.url}"
method: @req.method
})
.should.equal true
it "should pipe the response to the client", ->