diff --git a/services/web/app/coffee/Features/History/HistoryController.coffee b/services/web/app/coffee/Features/History/HistoryController.coffee
index 9563db2a24..ecb596823c 100644
--- a/services/web/app/coffee/Features/History/HistoryController.coffee
+++ b/services/web/app/coffee/Features/History/HistoryController.coffee
@@ -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
+ }
diff --git a/services/web/app/coffee/Features/History/RestoreManager.coffee b/services/web/app/coffee/Features/History/RestoreManager.coffee
index 185b90c233..fe1b0445de 100644
--- a/services/web/app/coffee/Features/History/RestoreManager.coffee
+++ b/services/web/app/coffee/Features/History/RestoreManager.coffee
@@ -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)}"
diff --git a/services/web/app/views/project/editor/history-file-tree.pug b/services/web/app/views/project/editor/history-file-tree.pug
index 9015dfe258..3356dc2249 100644
--- a/services/web/app/views/project/editor/history-file-tree.pug
+++ b/services/web/app/views/project/editor/history-file-tree.pug
@@ -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 }}
diff --git a/services/web/app/views/project/editor/history.pug b/services/web/app/views/project/editor/history.pug
index 6558aabbbc..d24dfcf670 100644
--- a/services/web/app/views/project/editor/history.pug
+++ b/services/web/app/views/project/editor/history.pug
@@ -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
- | {{history.diff.highlights.length}}
- ng-pluralize(
- count="history.diff.highlights.length",
- when="{\
- 'one': 'change',\
- 'other': 'changes'\
- }"
- )
- | in {{history.diff.pathname}}
- .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
- | #{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
diff --git a/services/web/app/views/project/editor/history/diffPanelV1.pug b/services/web/app/views/project/editor/history/diffPanelV1.pug
new file mode 100644
index 0000000000..c7e45c8405
--- /dev/null
+++ b/services/web/app/views/project/editor/history/diffPanelV1.pug
@@ -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
+ | {{history.diff.highlights.length}}
+ ng-pluralize(
+ count="history.diff.highlights.length",
+ when="{\
+ 'one': 'change',\
+ 'other': 'changes'\
+ }"
+ )
+ | in {{history.diff.pathname}}
+ .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
+ | #{translate("loading")}...
+ .error-panel(ng-show="history.diff.error")
+ .alert.alert-danger #{translate("generic_something_went_wrong")}
\ No newline at end of file
diff --git a/services/web/app/views/project/editor/history/diffPanelV2.pug b/services/web/app/views/project/editor/history/diffPanelV2.pug
new file mode 100644
index 0000000000..eb43eb2e9e
--- /dev/null
+++ b/services/web/app/views/project/editor/history/diffPanelV2.pug
@@ -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
+ | {{history.diff.highlights.length}}
+ ng-pluralize(
+ count="history.diff.highlights.length",
+ when="{\
+ 'one': 'change',\
+ 'other': 'changes'\
+ }"
+ )
+ | in {{history.diff.pathname}}
+ .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
+ | #{translate("loading")}...
+ .error-panel(ng-show="history.diff.error")
+ .alert.alert-danger #{translate("generic_something_went_wrong")}
\ No newline at end of file
diff --git a/services/web/nodemon.frontend.json b/services/web/nodemon.frontend.json
index a5897558c0..d0f321fa14 100644
--- a/services/web/nodemon.frontend.json
+++ b/services/web/nodemon.frontend.json
@@ -5,7 +5,7 @@
],
"verbose": true,
"legacyWatch": true,
- "exec": "make compile",
+ "exec": "make compile || exit 1",
"watch": [
"public/coffee/",
"public/stylesheets/"
diff --git a/services/web/public/coffee/ide/history/HistoryManager.coffee b/services/web/public/coffee/ide/history/HistoryManager.coffee
index 8c77d97965..cdc39ffd05 100644
--- a/services/web/public/coffee/ide/history/HistoryManager.coffee
+++ b/services/web/public/coffee/ide/history/HistoryManager.coffee
@@ -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
diff --git a/services/web/public/coffee/ide/history/HistoryV2Manager.coffee b/services/web/public/coffee/ide/history/HistoryV2Manager.coffee
index 574190c870..a145eceaa1 100644
--- a/services/web/public/coffee/ide/history/HistoryV2Manager.coffee
+++ b/services/web/public/coffee/ide/history/HistoryV2Manager.coffee
@@ -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
diff --git a/services/web/public/coffee/ide/history/controllers/HistoryV2DiffController.coffee b/services/web/public/coffee/ide/history/controllers/HistoryV2DiffController.coffee
new file mode 100644
index 0000000000..9c08d659f7
--- /dev/null
+++ b/services/web/public/coffee/ide/history/controllers/HistoryV2DiffController.coffee
@@ -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)
+
\ No newline at end of file
diff --git a/services/web/test/unit_frontend/coffee/ide/history/HistoryV2ManagerTests.coffee b/services/web/test/unit_frontend/coffee/ide/history/HistoryV2ManagerTests.coffee
index 358268310e..9d0e103e0c 100644
--- a/services/web/test/unit_frontend/coffee/ide/history/HistoryV2ManagerTests.coffee
+++ b/services/web/test/unit_frontend/coffee/ide/history/HistoryV2ManagerTests.coffee
@@ -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 }
})