[SSE] Add version history

This commit is contained in:
Julia Radzhabova 2021-06-28 20:18:53 +03:00
parent 8e3bc0869a
commit 3f429b0bc8
13 changed files with 280 additions and 8 deletions

View file

@ -160,6 +160,7 @@ require([
'DataTab', 'DataTab',
'ViewTab', 'ViewTab',
'Common.Controllers.Fonts', 'Common.Controllers.Fonts',
'Common.Controllers.History',
'Common.Controllers.Chat', 'Common.Controllers.Chat',
'Common.Controllers.Comments', 'Common.Controllers.Comments',
'Common.Controllers.Plugins' 'Common.Controllers.Plugins'
@ -196,6 +197,7 @@ require([
'common/main/lib/util/utils', 'common/main/lib/util/utils',
'common/main/lib/util/LocalStorage', 'common/main/lib/util/LocalStorage',
'common/main/lib/controller/Fonts', 'common/main/lib/controller/Fonts',
'common/main/lib/controller/History',
'common/main/lib/controller/Comments', 'common/main/lib/controller/Comments',
'common/main/lib/controller/Chat', 'common/main/lib/controller/Chat',
'common/main/lib/controller/Plugins' 'common/main/lib/controller/Plugins'

View file

@ -56,7 +56,11 @@ define([
'hide': _.bind(this.onHidePlugins, this) 'hide': _.bind(this.onHidePlugins, this)
}, },
'Common.Views.Header': { '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': { 'LeftMenu': {
'file:show': _.bind(this.fileShowHide, this, true), '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('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() { onLaunch: function() {
@ -169,6 +177,8 @@ define([
if (!this.mode.isEditMailMerge && !this.mode.isEditDiagram) if (!this.mode.isEditMailMerge && !this.mode.isEditDiagram)
this.api.asc_registerCallback('asc_onEditCell', _.bind(this.onApiEditCell, this)); this.api.asc_registerCallback('asc_onEditCell', _.bind(this.onApiEditCell, this));
this.leftMenu.getMenu('file').setApi(api); this.leftMenu.getMenu('file').setApi(api);
if (this.mode.canUseHistory)
this.getApplication().getController('Common.Controllers.History').setApi(this.api).setMode(this.mode);
return this; return this;
}, },
@ -224,6 +234,8 @@ define([
this.leftMenu.btnSpellcheck.show(); this.leftMenu.btnSpellcheck.show();
this.leftMenu.setOptionsPanel('spellcheck', this.getApplication().getController('Spellcheck').getView('Spellcheck')); 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); (this.mode.trialMode || this.mode.isBeta) && this.leftMenu.setDeveloperMode(this.mode.trialMode, this.mode.isBeta, this.mode.buildVersion);
/** coauthoring end **/ /** coauthoring end **/
@ -272,10 +284,35 @@ define([
} }
})).show(); })).show();
break; 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; default: close_menu = false;
} }
if (close_menu) { if (close_menu && menu) {
menu.hide(); 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', textNoTextFound : 'Text not found',
newDocumentTitle : 'Unnamed document', newDocumentTitle : 'Unnamed document',
textItemEntireCell : 'Entire cell contents', textItemEntireCell : 'Entire cell contents',
@ -971,6 +1019,8 @@ define([
textWithin: 'Within', textWithin: 'Within',
textSearch: 'Search', textSearch: 'Search',
textLookin: 'Look in', textLookin: 'Look in',
txtUntitled: 'Untitled' txtUntitled: 'Untitled',
textLoadHistory : 'Loading version history...',
leavePageText: 'All unsaved changes in this document will be lost.<br> Click \'Cancel\' then \'Save\' to save them. Click \'OK\' to discard all the unsaved changes.'
}, SSE.Controllers.LeftMenu || {})); }, SSE.Controllers.LeftMenu || {}));
}); });

View file

@ -90,7 +90,8 @@ define([
'TableTemplates', 'TableTemplates',
'ConditionalFormatIcons', 'ConditionalFormatIcons',
'ConditionalFormatIconsPresets', 'ConditionalFormatIconsPresets',
'Common.Collections.TextArt' 'Common.Collections.TextArt',
'Common.Collections.HistoryUsers'
], ],
views: [], views: [],
@ -939,6 +940,7 @@ define([
Common.Gateway.on('downloadas', _.bind(me.onDownloadAs, me)); Common.Gateway.on('downloadas', _.bind(me.onDownloadAs, me));
Common.Gateway.on('setfavorite', _.bind(me.onSetFavorite, me)); Common.Gateway.on('setfavorite', _.bind(me.onSetFavorite, me));
Common.Gateway.on('requestclose', _.bind(me.onRequestClose, 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'}); Common.Gateway.sendInfo({mode:me.appOptions.isEdit?'edit':'view'});
$(document).on('contextmenu', _.bind(me.onContextMenu, me)); $(document).on('contextmenu', _.bind(me.onContextMenu, me));
@ -1142,6 +1144,14 @@ define([
this.getApplication().getController('Common.Controllers.Plugins').setMode(this.appOptions); 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.loadCoAuthSettings();
this.applyModeCommonElements(); this.applyModeCommonElements();
this.applyModeEditorElements(); this.applyModeEditorElements();
@ -2549,6 +2559,157 @@ define([
this._renameDialog.show(Common.Utils.innerWidth() - this._renameDialog.options.width - 15, 30); 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; i<arrColors.length; i++) {
arrVersions[arrVersions.length-i-2].set('arrColors',arrColors);
}
arrColors = [];
}
arrColors.push(user.get('colorval'));
var changes = version.changes, change, i;
if (changes && changes.length>0) {
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; i<arrColors.length; i++) {
arrVersions[arrVersions.length-i-1].set('arrColors',arrColors);
}
arrColors = [];
}
historyStore.reset(arrVersions);
if (currentVersion===null && historyStore.size()>0) {
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() { onGrabFocus: function() {
this.getApplication().getController('DocumentHolder').getView().focus(); this.getApplication().getController('DocumentHolder').getView().focus();
}, },
@ -2953,7 +3114,8 @@ define([
errorPivotWithoutUnderlying: 'The Pivot Table report was saved without the underlying data.<br>Use the \'Refresh\' button to update the report.', errorPivotWithoutUnderlying: 'The Pivot Table report was saved without the underlying data.<br>Use the \'Refresh\' button to update the report.',
txtQuarter: 'Qtr', txtQuarter: 'Qtr',
txtOr: '%1 or %2', txtOr: '%1 or %2',
confirmReplaceFormulaInTable: 'Formulas in the header row will be removed and converted to static text.<br>Do you want to continue?' confirmReplaceFormulaInTable: 'Formulas in the header row will be removed and converted to static text.<br>Do you want to continue?',
txtErrorLoadHistory: 'Loading history failed'
} }
})(), SSE.Controllers.Main || {})) })(), SSE.Controllers.Main || {}))
}); });

View file

@ -356,10 +356,11 @@ define([
this.api.asc_Resize(); this.api.asc_Resize();
}, this); }, this);
var leftPanel = $('#left-menu'); var leftPanel = $('#left-menu'),
histPanel = $('#left-panel-history');
this.viewport.hlayout.on('layout:resizedrag', function() { this.viewport.hlayout.on('layout:resizedrag', function() {
this.api.asc_Resize(); 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);
this.boxSdk = $('#editor_sdk'); this.boxSdk = $('#editor_sdk');
@ -380,6 +381,14 @@ define([
case 'rightmenu': case 'rightmenu':
this.viewport.hlayout.doLayout(); this.viewport.hlayout.doLayout();
break; 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': case 'leftmenu':
var panel = this.viewport.hlayout.items[0]; var panel = this.viewport.hlayout.items[0];
if (panel.resize.el) { if (panel.resize.el) {

View file

@ -16,6 +16,7 @@
<li class="devider"></li> <li class="devider"></li>
<li id="fm-btn-info" class="fm-btn"></li> <li id="fm-btn-info" class="fm-btn"></li>
<li id="fm-btn-rights" class="fm-btn"></li> <li id="fm-btn-rights" class="fm-btn"></li>
<li id="fm-btn-history" class="fm-btn"></li>
<li class="devider" class="fm-btn"></li> <li class="devider" class="fm-btn"></li>
<li id="fm-btn-settings" class="fm-btn"></li> <li id="fm-btn-settings" class="fm-btn"></li>
<li class="devider"></li> <li class="devider"></li>

View file

@ -16,6 +16,7 @@
</div> </div>
</div> </div>
<div id="right-menu" class="layout-item"></div> <div id="right-menu" class="layout-item"></div>
<div id="left-panel-history" class="layout-item"></div>
</div> </div>
</div> </div>
<div id="statusbar" class="layout-item"></div> <div id="statusbar" class="layout-item"></div>

View file

@ -178,6 +178,13 @@ define([
canFocused: false 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 = [];
this.items.push( this.items.push(
new Common.UI.MenuItem({ new Common.UI.MenuItem({
@ -203,6 +210,7 @@ define([
canFocused: false canFocused: false
}), }),
this.miAccess, this.miAccess,
this.miHistory,
this.miSettings, this.miSettings,
this.miHelp, this.miHelp,
new Common.UI.MenuItem({ new Common.UI.MenuItem({
@ -327,6 +335,8 @@ define([
this.panels['help'].setLangConfig(this.mode.lang); this.panels['help'].setLangConfig(this.mode.lang);
} }
this.miHistory[this.mode.canUseHistory&&!this.mode.isDisconnected?'show':'hide']();
if ( this.mode.disableEditing != undefined ) { if ( this.mode.disableEditing != undefined ) {
this.panels['opts'].SetDisabled(this.mode.disableEditing); this.panels['opts'].SetDisabled(this.mode.disableEditing);
delete this.mode.disableEditing; delete this.mode.disableEditing;
@ -456,6 +466,7 @@ define([
btnRenameCaption : 'Rename...', btnRenameCaption : 'Rename...',
btnCloseMenuCaption : 'Close Menu', btnCloseMenuCaption : 'Close Menu',
btnProtectCaption: 'Protect', btnProtectCaption: 'Protect',
btnSaveCopyAsCaption : 'Save Copy as...' btnSaveCopyAsCaption : 'Save Copy as...',
btnHistoryCaption : 'Versions History'
}, SSE.Views.FileMenu || {})); }, SSE.Views.FileMenu || {}));
}); });

View file

@ -40,6 +40,7 @@ define([
/** coauthoring begin **/ /** coauthoring begin **/
'common/main/lib/view/Comments', 'common/main/lib/view/Comments',
'common/main/lib/view/Chat', 'common/main/lib/view/Chat',
'common/main/lib/view/History',
/** coauthoring end **/ /** coauthoring end **/
'common/main/lib/view/SearchDialog', 'common/main/lib/view/SearchDialog',
'common/main/lib/view/Plugins', 'common/main/lib/view/Plugins',
@ -244,6 +245,8 @@ define([
} else } else
if (name == 'spellcheck' && !this.panelSpellcheck) { if (name == 'spellcheck' && !this.panelSpellcheck) {
this.panelSpellcheck = panel.render('#left-panel-spellcheck'); 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); 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 **/ /** coauthoring begin **/
tipComments : 'Comments', tipComments : 'Comments',
tipChat : 'Chat', tipChat : 'Chat',

View file

@ -117,6 +117,15 @@ define([
max: 600, max: 600,
offset: 4 offset: 4
} }
}, { // history versions
el: items[3],
rely: true,
resize: {
hidden: true,
autohide: false,
min: 300,
max: 600
}
}, { }, {
el: items[1], el: items[1],
stretch: true stretch: true

View file

@ -150,6 +150,7 @@ require([
'DataTab', 'DataTab',
'ViewTab', 'ViewTab',
'Common.Controllers.Fonts', 'Common.Controllers.Fonts',
'Common.Controllers.History',
'Common.Controllers.Chat', 'Common.Controllers.Chat',
'Common.Controllers.Comments', 'Common.Controllers.Comments',
'Common.Controllers.Plugins' 'Common.Controllers.Plugins'
@ -186,6 +187,7 @@ require([
'common/main/lib/util/utils', 'common/main/lib/util/utils',
'common/main/lib/util/LocalStorage', 'common/main/lib/util/LocalStorage',
'common/main/lib/controller/Fonts', 'common/main/lib/controller/Fonts',
'common/main/lib/controller/History',
'common/main/lib/controller/Comments', 'common/main/lib/controller/Comments',
'common/main/lib/controller/Chat', 'common/main/lib/controller/Chat',
'common/main/lib/controller/Plugins' 'common/main/lib/controller/Plugins'

View file

@ -120,6 +120,7 @@
@import "../../../../common/main/resources/less/language-dialog.less"; @import "../../../../common/main/resources/less/language-dialog.less";
@import "../../../../common/main/resources/less/winxp_fix.less"; @import "../../../../common/main/resources/less/winxp_fix.less";
@import "../../../../common/main/resources/less/symboltable.less"; @import "../../../../common/main/resources/less/symboltable.less";
@import "../../../../common/main/resources/less/history.less";
// App // App
// -------------------------------------------------- // --------------------------------------------------

View file

@ -72,3 +72,10 @@ label {
max-width: none; max-width: none;
} }
} }
#left-panel-history {
left: 40px;
width: 300px;
height: 100%;
display: none;
}

View file

@ -14,6 +14,12 @@
} }
} }
.left-panel {
#left-panel-history {
height: 100%;
}
}
.left-menu-full-ct { .left-menu-full-ct {
width: 100%; width: 100%;
height: 100%; height: 100%;