Hook up front end to restore documents

This commit is contained in:
James Allen 2018-03-12 11:47:56 +00:00
parent 075db1e5b9
commit 0a1c543841
11 changed files with 175 additions and 84 deletions

View file

@ -77,6 +77,9 @@ module.exports = HistoryController =
{project_id} = req.params
{version, pathname} = req.body
user_id = AuthenticationController.getLoggedInUserId req
RestoreManager.restoreFile user_id, project_id, version, pathname, (error) ->
RestoreManager.restoreFile user_id, project_id, version, pathname, (error, entity) ->
return next(error) if error?
res.send 204
res.json {
type: entity.type,
id: entity._id
}

View file

@ -7,7 +7,7 @@ Errors = require '../Errors/Errors'
moment = require 'moment'
module.exports = RestoreManager =
restoreFile: (user_id, project_id, version, pathname, callback = (error) ->) ->
restoreFile: (user_id, project_id, version, pathname, callback = (error, entity) ->) ->
RestoreManager._writeFileVersionToDisk project_id, version, pathname, (error, fsPath) ->
return callback(error) if error?
basename = Path.basename(pathname)
@ -18,6 +18,7 @@ module.exports = RestoreManager =
return callback(error) if error?
RestoreManager._addEntityWithUniqueName user_id, project_id, parent_folder_id, basename, fsPath, callback
_findFolderOrRootFolderId: (project_id, dirname, callback = (error, folder_id) ->) ->
# We're going to try to recover the file into the folder it was in previously,
# but this is historical, so the folder may not exist anymore. Fallback to the
@ -46,7 +47,7 @@ module.exports = RestoreManager =
else
callback(error)
else
callback()
callback(null, entity)
_writeFileVersionToDisk: (project_id, version, pathname, callback = (error, fsPath) ->) ->
url = "#{Settings.apis.project_history.url}/project/#{project_id}/version/#{version}/#{encodeURIComponent(pathname)}"

View file

@ -11,7 +11,7 @@ aside.file-tree.file-tree-history(ng-controller="FileTreeController", ng-class="
.entity
.entity-name.entity-name-history(
ng-click="history.selection.pathname = pathname",
ng-class="{ 'deleted': doc.deleted }"
ng-class="{ 'deleted': !!doc.deletedAtV }"
)
i.fa.fa-fw.fa-pencil
span {{ pathname }}

View file

@ -123,78 +123,8 @@ div#history(ng-show="ui.view == 'history'")
i.fa.fa-spin.fa-refresh
|    #{translate("loading")}...
.diff-panel.full-size(ng-controller="HistoryDiffController")
.diff(
ng-if="!!history.diff && !history.diff.loading && !history.diff.deleted && !history.diff.error && !history.diff.binary"
)
.toolbar.toolbar-alt
span.name
| <strong>{{history.diff.highlights.length}} </strong>
ng-pluralize(
count="history.diff.highlights.length",
when="{\
'one': 'change',\
'other': 'changes'\
}"
)
| in <strong>{{history.diff.pathname}}</strong>
.toolbar-right(ng-if="!history.isV2")
a.btn.btn-danger.btn-sm(
href,
ng-click="openRestoreDiffModal()"
) #{translate("restore_to_before_these_changes")}
.toolbar-right(ng-if="history.isV2")
button.btn.btn-danger.btn-sm(
href,
ng-if="history.selection.docs[history.selection.pathname].deleted"
ng-click=""
)
i.fa.fa-fw.fa-step-backward
| Restore this deleted file
.diff-editor.hide-ace-cursor(
ace-editor="history",
theme="settings.theme",
font-size="settings.fontSize",
text="history.diff.text",
highlights="history.diff.highlights",
read-only="true",
resize-on="layout:main:resize",
navigate-highlights="true"
)
.diff.diff-binary(ng-show="history.diff.binary")
.toolbar.toolbar-alt
span.name
strong {{history.diff.pathname}}
.alert.alert-info We're still working on showing image and binary changes, sorry. Stay tuned!
.diff-deleted.text-centered(
ng-show="history.diff.deleted && !history.diff.restoreDeletedSuccess"
)
p.text-serif #{translate("file_has_been_deleted", {filename:"{{ history.diff.doc.name }} "})}
p
a.btn.btn-primary.btn-lg(
href,
ng-click="restoreDeletedDoc()",
ng-disabled="history.diff.restoreInProgress"
) #{translate("restore")}
.diff-deleted.text-centered(
ng-show="history.diff.deleted && history.diff.restoreDeletedSuccess"
)
p.text-serif #{translate("file_restored", {filename:"{{ history.diff.doc.name }} "})}
p.text-serif #{translate("file_restored_back_to_editor")}
p
a.btn.btn-default(
href,
ng-click="backToEditorAfterRestore()",
) #{translate("file_restored_back_to_editor_btn")}
.loading-panel(ng-show="history.diff.loading")
i.fa.fa-spin.fa-refresh
| &nbsp;&nbsp;#{translate("loading")}...
.error-panel(ng-show="history.diff.error")
.alert.alert-danger #{translate("generic_something_went_wrong")}
include ./history/diffPanelV1
include ./history/diffPanelV2
script(type="text/ng-template", id="historyRestoreDiffModalTemplate")
.modal-header

View file

@ -0,0 +1,58 @@
.diff-panel.full-size(ng-if="history.isV2", ng-controller="HistoryDiffController")
.diff(
ng-if="!!history.diff && !history.diff.loading && !history.diff.deleted && !history.diff.error && !history.diff.binary"
)
.toolbar.toolbar-alt
span.name
| <strong>{{history.diff.highlights.length}} </strong>
ng-pluralize(
count="history.diff.highlights.length",
when="{\
'one': 'change',\
'other': 'changes'\
}"
)
| in <strong>{{history.diff.pathname}}</strong>
.toolbar-right
a.btn.btn-danger.btn-sm(
href,
ng-click="openRestoreDiffModal()"
) #{translate("restore_to_before_these_changes")}
.diff-editor.hide-ace-cursor(
ace-editor="history",
theme="settings.theme",
font-size="settings.fontSize",
text="history.diff.text",
highlights="history.diff.highlights",
read-only="true",
resize-on="layout:main:resize",
navigate-highlights="true"
)
.diff-deleted.text-centered(
ng-show="history.diff.deleted && !history.diff.restoreDeletedSuccess"
)
p.text-serif #{translate("file_has_been_deleted", {filename:"{{ history.diff.doc.name }} "})}
p
a.btn.btn-primary.btn-lg(
href,
ng-click="restoreDeletedDoc()",
ng-disabled="history.diff.restoreInProgress"
) #{translate("restore")}
.diff-deleted.text-centered(
ng-show="history.diff.deleted && history.diff.restoreDeletedSuccess"
)
p.text-serif #{translate("file_restored", {filename:"{{ history.diff.doc.name }} "})}
p.text-serif #{translate("file_restored_back_to_editor")}
p
a.btn.btn-default(
href,
ng-click="backToEditorAfterRestore()",
) #{translate("file_restored_back_to_editor_btn")}
.loading-panel(ng-show="history.diff.loading")
i.fa.fa-spin.fa-refresh
| &nbsp;&nbsp;#{translate("loading")}...
.error-panel(ng-show="history.diff.error")
.alert.alert-danger #{translate("generic_something_went_wrong")}

View file

@ -0,0 +1,50 @@
.diff-panel.full-size(ng-if="history.isV2", ng-controller="HistoryV2DiffController")
.diff(
ng-if="!!history.diff && !history.diff.loading && !history.diff.error && !history.diff.binary"
)
.toolbar.toolbar-alt
span.name
| <strong>{{history.diff.highlights.length}} </strong>
ng-pluralize(
count="history.diff.highlights.length",
when="{\
'one': 'change',\
'other': 'changes'\
}"
)
| in <strong>{{history.diff.pathname}}</strong>
.toolbar-right(ng-if="history.selection.docs[history.selection.pathname].deletedAtV")
button.btn.btn-danger.btn-sm(
ng-click="restoreDeletedFile()"
ng-show="!restoreState.error"
ng-disabled="restoreState.inflight"
)
i.fa.fa-fw.fa-step-backward
span(ng-show="!restoreState.inflight")
| Restore this deleted file
span(ng-show="restoreState.inflight")
| Restoring...
span.text-danger(ng-show="restoreState.error")
| Error restoring, sorry
.diff-editor.hide-ace-cursor(
ace-editor="history",
theme="settings.theme",
font-size="settings.fontSize",
text="history.diff.text",
highlights="history.diff.highlights",
read-only="true",
resize-on="layout:main:resize",
navigate-highlights="true"
)
.diff.diff-binary(ng-show="history.diff.binary")
.toolbar.toolbar-alt
span.name
strong {{history.diff.pathname}}
.alert.alert-info We're still working on showing image and binary changes, sorry. Stay tuned!
.loading-panel(ng-show="history.diff.loading")
i.fa.fa-spin.fa-refresh
| &nbsp;&nbsp;#{translate("loading")}...
.error-panel(ng-show="history.diff.error")
.alert.alert-danger #{translate("generic_something_went_wrong")}

View file

@ -5,7 +5,7 @@
],
"verbose": true,
"legacyWatch": true,
"exec": "make compile",
"exec": "make compile || exit 1",
"watch": [
"public/coffee/",
"public/stylesheets/"

View file

@ -4,6 +4,7 @@ define [
"ide/history/util/displayNameForUser"
"ide/history/controllers/HistoryListController"
"ide/history/controllers/HistoryDiffController"
"ide/history/controllers/HistoryV2DiffController"
"ide/history/directives/infiniteScroll"
], (moment, ColorManager, displayNameForUser) ->
class HistoryManager

View file

@ -49,6 +49,13 @@ define [
diff: null
}
restoreFile: (version, pathname) ->
url = "/project/#{@$scope.project_id}/restore_file"
@ide.$http.post(url, {
version, pathname,
_csrf: window.csrfToken
})
MAX_RECENT_UPDATES_TO_SELECT: 5
autoSelectRecentUpdates: () ->
return if @$scope.history.updates.length == 0
@ -204,7 +211,7 @@ define [
# Map of original pathname -> doc summary
docs_summary = Object.create(null)
updatePathnameWithUpdateVersions = (pathname, update, deleted) ->
updatePathnameWithUpdateVersions = (pathname, update, deletedAtV) ->
# docs_summary is indexed by the original pathname the doc
# had at the start, so we have to look this up from the current
# pathname via original_pathname first
@ -222,8 +229,8 @@ define [
doc_summary.toV,
update.toV
)
if deleted?
doc_summary.deleted = true
if deletedAtV?
doc_summary.deletedAtV = deletedAtV
# Put updates in ascending chronological order
updates = updates.slice().reverse()
@ -241,7 +248,7 @@ define [
updatePathnameWithUpdateVersions(add.pathname, update)
if project_op.remove?
remove = project_op.remove
updatePathnameWithUpdateVersions(remove.pathname, update, true)
updatePathnameWithUpdateVersions(remove.pathname, update, remove.atV)
return docs_summary

View file

@ -0,0 +1,39 @@
define [
"base"
], (App) ->
App.controller "HistoryV2DiffController", ($scope, ide, event_tracking) ->
console.log "HistoryV2DiffController!"
$scope.restoreState =
inflight: false
error: false
$scope.restoreDeletedFile = () ->
pathname = $scope.history.selection.pathname
return if !pathname?
version = $scope.history.selection.docs[pathname]?.deletedAtV
return if !version?
event_tracking.sendMB "history-v2-restore-deleted"
$scope.restoreState.inflight = true
$scope.restoreState.error = false
ide.historyManager
.restoreFile(version, pathname)
.then (response) ->
{ data } = response
$scope.restoreState.inflight = false
if data.type == 'doc'
openDoc(data.id)
.catch () ->
$scope.restoreState.error = true
openDoc = (id) ->
iterations = 0
do tryOpen = () ->
if iterations > 5
return
doc = ide.fileTreeManager.findEntityById(id)
if doc?
ide.editorManager.openDoc(doc)
else
setTimeout(tryOpen, 500)

View file

@ -130,12 +130,13 @@ define ['ide/history/HistoryV2Manager'], (HistoryV2Manager) ->
project_ops: [{
remove:
pathname: "main.tex"
atV: 2
}]
fromV: 1, toV: 2
}])
expect(result).to.deep.equal({
"main.tex": { fromV: 0, toV: 2, deleted: true }
"main.tex": { fromV: 0, toV: 2, deletedAtV: 2 }
})
it "should track single deletions", ->
@ -143,10 +144,11 @@ define ['ide/history/HistoryV2Manager'], (HistoryV2Manager) ->
project_ops: [{
remove:
pathname: "main.tex"
atV: 1
}]
fromV: 0, toV: 1
}])
expect(result).to.deep.equal({
"main.tex": { fromV: 0, toV: 1, deleted: true }
"main.tex": { fromV: 0, toV: 1, deletedAtV: 1 }
})