From 3f429b0bc83da976937ba8d202e9445d9c8cd75f Mon Sep 17 00:00:00 2001 From: Julia Radzhabova Date: Mon, 28 Jun 2021 20:18:53 +0300 Subject: [PATCH] [SSE] Add version history --- apps/spreadsheeteditor/main/app.js | 2 + .../main/app/controller/LeftMenu.js | 56 +++++- .../main/app/controller/Main.js | 166 +++++++++++++++++- .../main/app/controller/Viewport.js | 13 +- .../main/app/template/FileMenu.template | 1 + .../main/app/template/Viewport.template | 1 + .../main/app/view/FileMenu.js | 13 +- .../main/app/view/LeftMenu.js | 11 ++ .../main/app/view/Viewport.js | 9 + apps/spreadsheeteditor/main/app_dev.js | 2 + .../main/resources/less/app.less | 1 + .../main/resources/less/layout.less | 7 + .../main/resources/less/leftmenu.less | 6 + 13 files changed, 280 insertions(+), 8 deletions(-) diff --git a/apps/spreadsheeteditor/main/app.js b/apps/spreadsheeteditor/main/app.js index 2057534be..2adb3fef1 100644 --- a/apps/spreadsheeteditor/main/app.js +++ b/apps/spreadsheeteditor/main/app.js @@ -160,6 +160,7 @@ require([ 'DataTab', 'ViewTab', 'Common.Controllers.Fonts', + 'Common.Controllers.History', 'Common.Controllers.Chat', 'Common.Controllers.Comments', 'Common.Controllers.Plugins' @@ -196,6 +197,7 @@ require([ 'common/main/lib/util/utils', 'common/main/lib/util/LocalStorage', 'common/main/lib/controller/Fonts', + 'common/main/lib/controller/History', 'common/main/lib/controller/Comments', 'common/main/lib/controller/Chat', 'common/main/lib/controller/Plugins' diff --git a/apps/spreadsheeteditor/main/app/controller/LeftMenu.js b/apps/spreadsheeteditor/main/app/controller/LeftMenu.js index 2127bd08e..88096da1d 100644 --- a/apps/spreadsheeteditor/main/app/controller/LeftMenu.js +++ b/apps/spreadsheeteditor/main/app/controller/LeftMenu.js @@ -56,7 +56,11 @@ define([ 'hide': _.bind(this.onHidePlugins, this) }, 'Common.Views.Header': { - 'file:settings': _.bind(this.clickToolbarSettings,this) + 'file:settings': _.bind(this.clickToolbarSettings,this), + 'history:show': function () { + if ( !this.leftMenu.panelHistory.isVisible() ) + this.clickMenuFileItem('header', 'history'); + }.bind(this) }, 'LeftMenu': { 'file:show': _.bind(this.fileShowHide, this, true), @@ -98,6 +102,10 @@ define([ } }); Common.NotificationCenter.on('app:comment:add', _.bind(this.onAppAddComment, this)); + Common.NotificationCenter.on('collaboration:history', _.bind(function () { + if ( !this.leftMenu.panelHistory.isVisible() ) + this.clickMenuFileItem(null, 'history'); + }, this)); }, onLaunch: function() { @@ -169,6 +177,8 @@ define([ if (!this.mode.isEditMailMerge && !this.mode.isEditDiagram) this.api.asc_registerCallback('asc_onEditCell', _.bind(this.onApiEditCell, this)); this.leftMenu.getMenu('file').setApi(api); + if (this.mode.canUseHistory) + this.getApplication().getController('Common.Controllers.History').setApi(this.api).setMode(this.mode); return this; }, @@ -224,6 +234,8 @@ define([ this.leftMenu.btnSpellcheck.show(); this.leftMenu.setOptionsPanel('spellcheck', this.getApplication().getController('Spellcheck').getView('Spellcheck')); } + if (this.mode.canUseHistory) + this.leftMenu.setOptionsPanel('history', this.getApplication().getController('Common.Controllers.History').getView('Common.Views.History')); (this.mode.trialMode || this.mode.isBeta) && this.leftMenu.setDeveloperMode(this.mode.trialMode, this.mode.isBeta, this.mode.buildVersion); /** coauthoring end **/ @@ -272,10 +284,35 @@ define([ } })).show(); break; + case 'history': + if (!this.leftMenu.panelHistory.isVisible()) { + if (this.api.asc_isDocumentModified()) { + var me = this; + this.api.asc_stopSaving(); + Common.UI.warning({ + closable: false, + width: 500, + title: this.notcriticalErrorTitle, + msg: this.leavePageText, + buttons: ['ok', 'cancel'], + primary: 'ok', + callback: function(btn) { + if (btn == 'ok') { + me.api.asc_undoAllChanges(); + me.api.asc_continueSaving(); + me.showHistory(); + } else + me.api.asc_continueSaving(); + } + }); + } else + this.showHistory(); + } + break; default: close_menu = false; } - if (close_menu) { + if (close_menu && menu) { menu.hide(); } }, @@ -954,6 +991,17 @@ define([ } }, + showHistory: function() { + if (!this.mode.wopi) { + var maincontroller = this.getApplication().getController('Main'); + if (!maincontroller.loadMask) + maincontroller.loadMask = new Common.UI.LoadMask({owner: $('#viewport')}); + maincontroller.loadMask.setTitle(this.textLoadHistory); + maincontroller.loadMask.show(); + } + Common.Gateway.requestHistory(); + }, + textNoTextFound : 'Text not found', newDocumentTitle : 'Unnamed document', textItemEntireCell : 'Entire cell contents', @@ -971,6 +1019,8 @@ define([ textWithin: 'Within', textSearch: 'Search', textLookin: 'Look in', - txtUntitled: 'Untitled' + txtUntitled: 'Untitled', + textLoadHistory : 'Loading version history...', + leavePageText: 'All unsaved changes in this document will be lost.
Click \'Cancel\' then \'Save\' to save them. Click \'OK\' to discard all the unsaved changes.' }, SSE.Controllers.LeftMenu || {})); }); \ No newline at end of file diff --git a/apps/spreadsheeteditor/main/app/controller/Main.js b/apps/spreadsheeteditor/main/app/controller/Main.js index 28f486644..555ccc576 100644 --- a/apps/spreadsheeteditor/main/app/controller/Main.js +++ b/apps/spreadsheeteditor/main/app/controller/Main.js @@ -90,7 +90,8 @@ define([ 'TableTemplates', 'ConditionalFormatIcons', 'ConditionalFormatIconsPresets', - 'Common.Collections.TextArt' + 'Common.Collections.TextArt', + 'Common.Collections.HistoryUsers' ], views: [], @@ -939,6 +940,7 @@ define([ Common.Gateway.on('downloadas', _.bind(me.onDownloadAs, me)); Common.Gateway.on('setfavorite', _.bind(me.onSetFavorite, me)); Common.Gateway.on('requestclose', _.bind(me.onRequestClose, me)); + Common.Gateway.on('refreshhistory',_.bind(me.onRefreshHistory, me)); Common.Gateway.sendInfo({mode:me.appOptions.isEdit?'edit':'view'}); $(document).on('contextmenu', _.bind(me.onContextMenu, me)); @@ -1142,6 +1144,14 @@ define([ this.getApplication().getController('Common.Controllers.Plugins').setMode(this.appOptions); } + this.appOptions.canUseHistory = this.appOptions.canLicense && this.editorConfig.canUseHistory && this.appOptions.canCoAuthoring && !this.appOptions.isOffline; + this.appOptions.canHistoryClose = this.editorConfig.canHistoryClose; + this.appOptions.canHistoryRestore= this.editorConfig.canHistoryRestore; + + if ( this.appOptions.isLightVersion ) { + this.appOptions.canUseHistory = false; + } + this.loadCoAuthSettings(); this.applyModeCommonElements(); this.applyModeEditorElements(); @@ -2549,6 +2559,157 @@ define([ this._renameDialog.show(Common.Utils.innerWidth() - this._renameDialog.options.width - 15, 30); }, + onRefreshHistory: function(opts) { + if (!this.appOptions.canUseHistory) return; + + this.loadMask && this.loadMask.hide(); + if (opts.data.error || !opts.data.history) { + var historyStore = this.getApplication().getCollection('Common.Collections.HistoryVersions'); + if (historyStore && historyStore.size()>0) { + historyStore.each(function(item){ + item.set('canRestore', false); + }); + } + Common.UI.alert({ + title: this.notcriticalErrorTitle, + msg: (opts.data.error) ? opts.data.error : this.txtErrorLoadHistory, + iconCls: 'warn', + buttons: ['ok'], + callback: _.bind(function(btn){ + this.onEditComplete(); + }, this) + }); + } else { + this.api.asc_coAuthoringDisconnect(); + this.headerView.setCanRename(false); + this.headerView.getButton('users') && this.headerView.getButton('users').hide(); + this.getApplication().getController('LeftMenu').getView('LeftMenu').showHistory(); + this.disableEditing(true); + this._renameDialog && this._renameDialog.close(); + var versions = opts.data.history, + historyStore = this.getApplication().getCollection('Common.Collections.HistoryVersions'), + currentVersion = null; + if (historyStore) { + var arrVersions = [], ver, version, group = -1, prev_ver = -1, arrColors = [], docIdPrev = '', + usersStore = this.getApplication().getCollection('Common.Collections.HistoryUsers'), user = null, usersCnt = 0; + + for (ver=versions.length-1; ver>=0; ver--) { + version = versions[ver]; + if (version.versionGroup===undefined || version.versionGroup===null) + version.versionGroup = version.version; + if (version) { + if (!version.user) version.user = {}; + docIdPrev = (ver>0 && versions[ver-1]) ? versions[ver-1].key : version.key + '0'; + user = usersStore.findUser(version.user.id); + if (!user) { + user = new Common.Models.User({ + id : version.user.id, + username : version.user.name, + colorval : Asc.c_oAscArrUserColors[usersCnt], + color : this.generateUserColor(Asc.c_oAscArrUserColors[usersCnt++]) + }); + usersStore.add(user); + } + + arrVersions.push(new Common.Models.HistoryVersion({ + version: version.versionGroup, + revision: version.version, + userid : version.user.id, + username : version.user.name, + usercolor: user.get('color'), + created: version.created, + docId: version.key, + markedAsVersion: (group!==version.versionGroup), + selected: (opts.data.currentVersion == version.version), + canRestore: this.appOptions.canHistoryRestore && (ver < versions.length-1), + isExpanded: true, + serverVersion: version.serverVersion + })); + if (opts.data.currentVersion == version.version) { + currentVersion = arrVersions[arrVersions.length-1]; + } + group = version.versionGroup; + if (prev_ver!==version.version) { + prev_ver = version.version; + arrColors.reverse(); + for (i=0; i0) { + arrVersions[arrVersions.length-1].set('docIdPrev', docIdPrev); + if (!_.isEmpty(version.serverVersion) && version.serverVersion == this.appOptions.buildVersion) { + arrVersions[arrVersions.length-1].set('changeid', changes.length-1); + arrVersions[arrVersions.length-1].set('hasChanges', changes.length>1); + for (i=changes.length-2; i>=0; i--) { + change = changes[i]; + + user = usersStore.findUser(change.user.id); + if (!user) { + user = new Common.Models.User({ + id : change.user.id, + username : change.user.name, + colorval : Asc.c_oAscArrUserColors[usersCnt], + color : this.generateUserColor(Asc.c_oAscArrUserColors[usersCnt++]) + }); + usersStore.add(user); + } + + arrVersions.push(new Common.Models.HistoryVersion({ + version: version.versionGroup, + revision: version.version, + changeid: i, + userid : change.user.id, + username : change.user.name, + usercolor: user.get('color'), + created: change.created, + docId: version.key, + docIdPrev: docIdPrev, + selected: false, + canRestore: this.appOptions.canHistoryRestore && this.appOptions.canDownload, + isRevision: false, + isVisible: true, + serverVersion: version.serverVersion + })); + arrColors.push(user.get('colorval')); + } + } + } else if (ver==0 && versions.length==1) { + arrVersions[arrVersions.length-1].set('docId', version.key + '1'); + } + } + } + if (arrColors.length>0) { + arrColors.reverse(); + for (i=0; i0) { + currentVersion = historyStore.at(0); + currentVersion.set('selected', true); + } + // if (currentVersion) + // this.getApplication().getController('Common.Controllers.History').onSelectRevision(null, null, currentVersion); + } + } + }, + + DisableVersionHistory: function() { + this.editorConfig.canUseHistory = false; + this.appOptions.canUseHistory = false; + }, + + generateUserColor: function(color) { + return"#"+("000000"+color.toString(16)).substr(-6); + }, + onGrabFocus: function() { this.getApplication().getController('DocumentHolder').getView().focus(); }, @@ -2953,7 +3114,8 @@ define([ errorPivotWithoutUnderlying: 'The Pivot Table report was saved without the underlying data.
Use the \'Refresh\' button to update the report.', txtQuarter: 'Qtr', txtOr: '%1 or %2', - confirmReplaceFormulaInTable: 'Formulas in the header row will be removed and converted to static text.
Do you want to continue?' + confirmReplaceFormulaInTable: 'Formulas in the header row will be removed and converted to static text.
Do you want to continue?', + txtErrorLoadHistory: 'Loading history failed' } })(), SSE.Controllers.Main || {})) }); diff --git a/apps/spreadsheeteditor/main/app/controller/Viewport.js b/apps/spreadsheeteditor/main/app/controller/Viewport.js index 525c719ab..fc3e15791 100644 --- a/apps/spreadsheeteditor/main/app/controller/Viewport.js +++ b/apps/spreadsheeteditor/main/app/controller/Viewport.js @@ -356,10 +356,11 @@ define([ this.api.asc_Resize(); }, this); - var leftPanel = $('#left-menu'); + var leftPanel = $('#left-menu'), + histPanel = $('#left-panel-history'); this.viewport.hlayout.on('layout:resizedrag', function() { this.api.asc_Resize(); - Common.localStorage.setItem('sse-mainmenu-width',leftPanel.width()); + Common.localStorage.setItem('sse-mainmenu-width',histPanel.is(':visible') ? (histPanel.width()+SCALE_MIN) : leftPanel.width()); }, this); this.boxSdk = $('#editor_sdk'); @@ -380,6 +381,14 @@ define([ case 'rightmenu': this.viewport.hlayout.doLayout(); break; + case 'history': + var panel = this.viewport.hlayout.items[1]; + if (panel.resize.el) { + this.boxSdk.css('border-left', ''); + panel.resize.el.show(); + } + this.viewport.hlayout.doLayout(); + break; case 'leftmenu': var panel = this.viewport.hlayout.items[0]; if (panel.resize.el) { diff --git a/apps/spreadsheeteditor/main/app/template/FileMenu.template b/apps/spreadsheeteditor/main/app/template/FileMenu.template index a2c9eb462..8bb022a44 100644 --- a/apps/spreadsheeteditor/main/app/template/FileMenu.template +++ b/apps/spreadsheeteditor/main/app/template/FileMenu.template @@ -16,6 +16,7 @@
  • +
  • diff --git a/apps/spreadsheeteditor/main/app/template/Viewport.template b/apps/spreadsheeteditor/main/app/template/Viewport.template index e9dd6ee38..1628f2610 100644 --- a/apps/spreadsheeteditor/main/app/template/Viewport.template +++ b/apps/spreadsheeteditor/main/app/template/Viewport.template @@ -16,6 +16,7 @@
    +
    diff --git a/apps/spreadsheeteditor/main/app/view/FileMenu.js b/apps/spreadsheeteditor/main/app/view/FileMenu.js index 3b6256650..0be1c83df 100644 --- a/apps/spreadsheeteditor/main/app/view/FileMenu.js +++ b/apps/spreadsheeteditor/main/app/view/FileMenu.js @@ -178,6 +178,13 @@ define([ canFocused: false }); + this.miHistory = new Common.UI.MenuItem({ + el : $markup.elementById('#fm-btn-history'), + action : 'history', + caption : this.btnHistoryCaption, + canFocused: false + }); + this.items = []; this.items.push( new Common.UI.MenuItem({ @@ -203,6 +210,7 @@ define([ canFocused: false }), this.miAccess, + this.miHistory, this.miSettings, this.miHelp, new Common.UI.MenuItem({ @@ -327,6 +335,8 @@ define([ this.panels['help'].setLangConfig(this.mode.lang); } + this.miHistory[this.mode.canUseHistory&&!this.mode.isDisconnected?'show':'hide'](); + if ( this.mode.disableEditing != undefined ) { this.panels['opts'].SetDisabled(this.mode.disableEditing); delete this.mode.disableEditing; @@ -456,6 +466,7 @@ define([ btnRenameCaption : 'Rename...', btnCloseMenuCaption : 'Close Menu', btnProtectCaption: 'Protect', - btnSaveCopyAsCaption : 'Save Copy as...' + btnSaveCopyAsCaption : 'Save Copy as...', + btnHistoryCaption : 'Versions History' }, SSE.Views.FileMenu || {})); }); diff --git a/apps/spreadsheeteditor/main/app/view/LeftMenu.js b/apps/spreadsheeteditor/main/app/view/LeftMenu.js index 8cca99aab..8b261c325 100644 --- a/apps/spreadsheeteditor/main/app/view/LeftMenu.js +++ b/apps/spreadsheeteditor/main/app/view/LeftMenu.js @@ -40,6 +40,7 @@ define([ /** coauthoring begin **/ 'common/main/lib/view/Comments', 'common/main/lib/view/Chat', + 'common/main/lib/view/History', /** coauthoring end **/ 'common/main/lib/view/SearchDialog', 'common/main/lib/view/Plugins', @@ -244,6 +245,8 @@ define([ } else if (name == 'spellcheck' && !this.panelSpellcheck) { this.panelSpellcheck = panel.render('#left-panel-spellcheck'); + } else if (name == 'history') { + this.panelHistory = panel.render('#left-panel-history'); } }, @@ -423,6 +426,14 @@ define([ this.limitHint && this.limitHint.css('top', top); }, + showHistory: function() { + this._state.pluginIsRunning = false; + this._state.historyIsRunning = true; + this.panelHistory.show(); + this.panelHistory.$el.width((parseInt(Common.localStorage.getItem('sse-mainmenu-width')) || MENU_SCALE_PART) - SCALE_MIN); + Common.NotificationCenter.trigger('layout:changed', 'history'); + }, + /** coauthoring begin **/ tipComments : 'Comments', tipChat : 'Chat', diff --git a/apps/spreadsheeteditor/main/app/view/Viewport.js b/apps/spreadsheeteditor/main/app/view/Viewport.js index d866e501a..baa0d58c9 100644 --- a/apps/spreadsheeteditor/main/app/view/Viewport.js +++ b/apps/spreadsheeteditor/main/app/view/Viewport.js @@ -117,6 +117,15 @@ define([ max: 600, offset: 4 } + }, { // history versions + el: items[3], + rely: true, + resize: { + hidden: true, + autohide: false, + min: 300, + max: 600 + } }, { el: items[1], stretch: true diff --git a/apps/spreadsheeteditor/main/app_dev.js b/apps/spreadsheeteditor/main/app_dev.js index 86e790254..a5a63c7e5 100644 --- a/apps/spreadsheeteditor/main/app_dev.js +++ b/apps/spreadsheeteditor/main/app_dev.js @@ -150,6 +150,7 @@ require([ 'DataTab', 'ViewTab', 'Common.Controllers.Fonts', + 'Common.Controllers.History', 'Common.Controllers.Chat', 'Common.Controllers.Comments', 'Common.Controllers.Plugins' @@ -186,6 +187,7 @@ require([ 'common/main/lib/util/utils', 'common/main/lib/util/LocalStorage', 'common/main/lib/controller/Fonts', + 'common/main/lib/controller/History', 'common/main/lib/controller/Comments', 'common/main/lib/controller/Chat', 'common/main/lib/controller/Plugins' diff --git a/apps/spreadsheeteditor/main/resources/less/app.less b/apps/spreadsheeteditor/main/resources/less/app.less index a92f42255..3573f82e4 100644 --- a/apps/spreadsheeteditor/main/resources/less/app.less +++ b/apps/spreadsheeteditor/main/resources/less/app.less @@ -120,6 +120,7 @@ @import "../../../../common/main/resources/less/language-dialog.less"; @import "../../../../common/main/resources/less/winxp_fix.less"; @import "../../../../common/main/resources/less/symboltable.less"; +@import "../../../../common/main/resources/less/history.less"; // App // -------------------------------------------------- diff --git a/apps/spreadsheeteditor/main/resources/less/layout.less b/apps/spreadsheeteditor/main/resources/less/layout.less index 54b5f4216..73e06aa0c 100644 --- a/apps/spreadsheeteditor/main/resources/less/layout.less +++ b/apps/spreadsheeteditor/main/resources/less/layout.less @@ -71,4 +71,11 @@ label { .tooltip-inner { max-width: none; } +} + +#left-panel-history { + left: 40px; + width: 300px; + height: 100%; + display: none; } \ No newline at end of file diff --git a/apps/spreadsheeteditor/main/resources/less/leftmenu.less b/apps/spreadsheeteditor/main/resources/less/leftmenu.less index 778e54c5d..1d6fb4a66 100644 --- a/apps/spreadsheeteditor/main/resources/less/leftmenu.less +++ b/apps/spreadsheeteditor/main/resources/less/leftmenu.less @@ -14,6 +14,12 @@ } } +.left-panel { + #left-panel-history { + height: 100%; + } +} + .left-menu-full-ct { width: 100%; height: 100%;