diff --git a/apps/common/main/lib/view/ReviewChanges.js b/apps/common/main/lib/view/ReviewChanges.js index b1b80fbdef..cdf67c22fd 100644 --- a/apps/common/main/lib/view/ReviewChanges.js +++ b/apps/common/main/lib/view/ReviewChanges.js @@ -789,6 +789,9 @@ define([ if ((!me.btnMailRecepients || !Common.UI.LayoutManager.isElementVisible('toolbar-collaboration-mailmerge')) && separator_last) me.$el.find(separator_last).hide(); +//! NOTE: conflicted code from branch feature/pdf-history. remove if is not relevant and merge is successful +//! Common.NotificationCenter.trigger('tab:visible', 'review', (window.PDFE && (config.isPDFAnnotate || config.isPDFEdit) || !window.PDFE && (config.isEdit || config.canViewReview || me.canComments)) +//! && Common.UI.LayoutManager.isElementVisible('toolbar-collaboration')); var visible = (config.isEdit || config.canViewReview || me.canComments) && Common.UI.LayoutManager.isElementVisible('toolbar-collaboration'); Common.NotificationCenter.trigger('tab:visible', 'review', visible); if (Common.Utils.InternalSettings.get('toolbar-active-tab') && visible) { // collaboration tab has hign priority in view mode diff --git a/apps/pdfeditor/main/app.js b/apps/pdfeditor/main/app.js index 6d2ec5d4bf..f5b08b2dd6 100644 --- a/apps/pdfeditor/main/app.js +++ b/apps/pdfeditor/main/app.js @@ -148,6 +148,7 @@ require([ 'Print', 'FormsTab', 'Common.Controllers.Fonts', + 'Common.Controllers.History', 'Common.Controllers.Chat', 'Common.Controllers.Comments', 'Common.Controllers.Draw', @@ -156,7 +157,8 @@ require([ 'Common.Controllers.ExternalDiagramEditor', // 'Common.Controllers.ExternalOleEditor', 'Common.Controllers.Protection', - 'Common.Controllers.Shortcuts' + 'Common.Controllers.Shortcuts', + 'Common.Controllers.ReviewChanges' ] }); @@ -187,6 +189,7 @@ require([ 'pdfeditor/main/app/controller/FormsTab', 'pdfeditor/main/app/view/ChartSettings', 'common/main/lib/util/utils', + 'common/main/lib/controller/History', 'common/main/lib/controller/Fonts', 'common/main/lib/controller/Comments', 'common/main/lib/controller/Chat', @@ -197,7 +200,8 @@ require([ // 'common/main/lib/controller/ExternalOleEditor', 'common/main/lib/controller/Draw', 'common/main/lib/controller/Protection', - 'common/main/lib/controller/Shortcuts' + 'common/main/lib/controller/Shortcuts', + 'common/main/lib/controller/ReviewChanges' ], function() { const code_path = !window.isIEBrowser ? 'pdfeditor/main/code' : 'pdfeditor/main/ie/code'; app.postLaunchScripts = [ diff --git a/apps/pdfeditor/main/app/controller/LeftMenu.js b/apps/pdfeditor/main/app/controller/LeftMenu.js index ac41cde484..f8f751a195 100644 --- a/apps/pdfeditor/main/app/controller/LeftMenu.js +++ b/apps/pdfeditor/main/app/controller/LeftMenu.js @@ -101,9 +101,9 @@ define([ 'file:close': this.clickToolbarTab.bind(this, 'other'), 'save:disabled': this.changeToolbarSaveState.bind(this) }, - // 'Common.Views.ReviewChanges': { - // 'collaboration:chat': _.bind(this.onShowHideChat, this) - // }, + 'Common.Views.ReviewChanges': { + 'collaboration:chat': _.bind(this.onShowHideChat, this) + }, 'ViewTab': { 'viewtab:navigation': _.bind(this.onShowHideNavigation, this), 'leftmenu:hide': _.bind(this.onLeftMenuHide, this) @@ -123,6 +123,10 @@ define([ Common.NotificationCenter.on('leftmenu:change', _.bind(this.onMenuChange, 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)); Common.NotificationCenter.on('file:print', _.bind(this.clickToolbarPrint, this)); Common.NotificationCenter.on('search:resetmode', _.bind(this.onSetDefaultSearchMode, this)); }, @@ -174,6 +178,8 @@ define([ } /** coauthoring end **/ this.leftMenu.getMenu('file').setApi(api); + if (this.mode.canUseHistory) + this.getApplication().getController('Common.Controllers.History').setApi(this.api).setMode(this.mode); this.getApplication().getController('PageThumbnails').setApi(this.api).setMode(this.mode); this.getApplication().getController('Search').setApi(this.api).setMode(this.mode); this.leftMenu.setOptionsPanel('advancedsearch', this.getApplication().getController('Search').getView('Common.Views.SearchPanel')); @@ -203,6 +209,9 @@ define([ } /** coauthoring end **/ + if (this.mode.canUseHistory) + this.leftMenu.setOptionsPanel('history', this.getApplication().getController('Common.Controllers.History').getView('Common.Views.History')); + if (this.mode.canUseViwerNavigation) { this.leftMenu.setOptionsPanel('navigation', this.getApplication().getController('Navigation').getView('Navigation')); } else { @@ -271,6 +280,31 @@ define([ case 'close-editor': Common.NotificationCenter.trigger('close'); break; case 'switch:mobile': Common.Gateway.switchEditorType('mobile', true); break; case 'suggest': Common.NotificationCenter.trigger('suggest'); break; + case 'history': + if (!this.leftMenu.panelHistory.isVisible()) { + if (this.api.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; } @@ -634,16 +668,16 @@ define([ if (this.leftMenu._state.disabled !== disable) { this.leftMenu._state.disabled = disable; if (this.mode) { - if (disable) { - this.previsEdit = this.mode.isEdit; - this.prevcanEdit = this.mode.canEdit; - this.mode.isEdit = this.mode.canEdit = !disable; - } else { - this.mode.isEdit = this.previsEdit; - this.mode.canEdit = this.prevcanEdit; - } + if (disable) { + this.previsEdit = this.mode.isEdit; + this.prevcanEdit = this.mode.canEdit; + this.mode.isEdit = this.mode.canEdit = !disable; + } else { + this.mode.isEdit = this.previsEdit; + this.mode.canEdit = this.prevcanEdit; } } + } if (disable) this.leftMenu.close(); @@ -653,6 +687,8 @@ define([ this.leftMenu.btnChat.setDisabled(disable); if (!options || options.navigation && options.navigation.disable) this.leftMenu.btnNavigation.setDisabled(disable); + if (!options || options.thumbnails && options.thumbnails.disable) + this.leftMenu.btnThumbnails.setDisabled(disable); this.leftMenu.setDisabledPluginButtons(disable); }, @@ -868,6 +904,17 @@ define([ } }, + showHistory: function() { + if (!this.mode.wopi) { + var maincontroller = PDFE.getController('Main'); + if (!maincontroller.loadMask) + maincontroller.loadMask = new Common.UI.LoadMask({owner: $('#viewport')}); + maincontroller.loadMask.setTitle(this.textLoadHistory); + maincontroller.loadMask.show(); + } + Common.Gateway.requestHistory(); + }, + onShowHideChat: function(state) { if (this.mode.canCoAuthoring && this.mode.canChat && !this.mode.isLightVersion) { if (state) { @@ -962,7 +1009,8 @@ define([ txtUntitled: 'Untitled', txtCompatible: 'The document will be saved to the new format. It will allow to use all the editor features, but might affect the document layout.
Use the \'Compatibility\' option of the advanced settings if you want to make the files compatible with older MS Word versions.', warnDownloadAsPdf: 'Your {0} will be converted to an editable format. This may take a while. The resulting document will be optimized to allow you to edit the text, so it might not look exactly like the original {0}, especially if the original file contained lots of graphics.', - textSelectPath: 'Enter a new name for saving the file copy' + textSelectPath: 'Enter a new name for saving the file copy', + textLoadHistory : 'Loading version history...' }, PDFE.Controllers.LeftMenu || {})); }); \ No newline at end of file diff --git a/apps/pdfeditor/main/app/controller/Main.js b/apps/pdfeditor/main/app/controller/Main.js index e0f53eca3e..7788f92660 100644 --- a/apps/pdfeditor/main/app/controller/Main.js +++ b/apps/pdfeditor/main/app/controller/Main.js @@ -83,6 +83,7 @@ define([ models: [], collections: [ 'Common.Collections.TextArt', + 'Common.Collections.HistoryUsers', ], views: [], @@ -91,9 +92,9 @@ define([ 'FileMenu': { 'settings:apply': _.bind(this.applySettings, this) }, - // 'Common.Views.ReviewChanges': { - // 'settings:apply': _.bind(this.applySettings, this) - // } + 'Common.Views.ReviewChanges': { + 'settings:apply': _.bind(this.applySettings, this) + } }); this.translationTable = { @@ -497,7 +498,6 @@ define([ docInfo.asc_putIsEnabledMacroses(!!enable); enable = !this.editorConfig.customization || (this.editorConfig.customization.plugins!==false); docInfo.asc_putIsEnabledPlugins(!!enable); -// docInfo.put_Review(this.permissions.review); var type = /^(?:(djvu|xps|oxps))$/.exec(data.doc.fileType); var coEditMode = (type && typeof type[1] === 'string') ? 'strict' : // offline viewer for djvu|xps|oxps @@ -544,10 +544,10 @@ define([ Common.NotificationCenter.trigger('api:disconnect'); !old_rights && Common.UI.TooltipManager.showTip({ step: 'changeRights', text: _.isEmpty(data.message) ? this.warnProcessRightsChange : Common.Utils.String.htmlEncode(data.message), target: '#toolbar', maxwidth: 600, showButton: false, automove: true, noHighlight: true, noArrow: true, multiple: true, - callback: function() { - me._state.lostEditingRights = false; + callback: function(){ + me._state.lostEditingRights = false; }}); - } + } }, onDownloadAs: function(format) { @@ -621,10 +621,12 @@ define([ statusBar: true, rightMenu: {clear: !temp, disable: true}, leftMenu: {disable: true, previewMode: true}, - fileMenu: {protect: true}, + fileMenu: {protect: true, history: temp}, navigation: {disable: !temp, previewMode: true}, + thumbnails: {disable: !temp}, comments: {disable: !temp, previewMode: true}, chat: true, + review: true, viewport: true, documentHolder: {clear: !temp, disable: true}, toolbar: true, @@ -651,6 +653,9 @@ define([ if (options.statusBar) { app.getController('Statusbar').getView('Statusbar').SetDisabled(disable); } + if (options.review) { + app.getController('Common.Controllers.ReviewChanges').SetDisabled(disable); + } if (options.viewport) { app.getController('Viewport').SetDisabled(disable); } @@ -864,9 +869,6 @@ define([ if (this.appOptions.isEdit && (id==Asc.c_oAscAsyncAction['Save'] || id==Asc.c_oAscAsyncAction['ForceSaveButton']) && (!this._state.fastCoauth || this._state.usersCount<2)) this.synchronizeChanges(); - // else if (this.appOptions.isEdit && (id==Asc.c_oAscAsyncAction['Save'] || id==Asc.c_oAscAsyncAction['ForceSaveButton'] || id == Asc.c_oAscAsyncAction['ApplyChanges']) && - // this._state.fastCoauth) - // this.getApplication().getController('Common.Controllers.ReviewChanges').synchronizeChanges(); if ( id == Asc.c_oAscAsyncAction['Disconnect']) { this._state.timerDisconnect && clearTimeout(this._state.timerDisconnect); @@ -966,9 +968,9 @@ define([ Common.UI.Menu.Manager.hideAll(); this.disableEditing(true, 'reconnect'); var me = this; - me._state.timerDisconnect = setTimeout(function(){ + me._state.timerDisconnect = setTimeout(function(){ Common.UI.TooltipManager.showTip('disconnect'); - }, me._state.unloadTimer || 0); + }, me._state.unloadTimer || 0); this.getApplication().getController('Statusbar').setStatusCaption(text); return; @@ -1170,6 +1172,7 @@ define([ Common.Gateway.on('applyeditrights', _.bind(me.onApplyEditRights, me)); Common.Gateway.on('processrightschange', _.bind(me.onProcessRightsChange, me)); Common.Gateway.on('processmouse', _.bind(me.onProcessMouse, me)); + Common.Gateway.on('refreshhistory', _.bind(me.onRefreshHistory, me)); Common.Gateway.on('downloadas', _.bind(me.onDownloadAs, me)); Common.Gateway.on('setfavorite', _.bind(me.onSetFavorite, me)); Common.Gateway.on('requestclose', _.bind(me.onRequestClose, me)); @@ -1258,19 +1261,19 @@ define([ !modal ? Common.UI.TooltipManager.showTip({ step: 'licenseError', text: license, header: title, target: '#toolbar', maxwidth: 430, automove: true, noHighlight: true, noArrow: true, textButton: this.textContinue}) : - Common.UI.info({ - maxwidth: 500, + Common.UI.info({ + maxwidth: 500, title: title, - msg : license, - buttons: buttons, - primary: primary, - callback: function(btn) { - if (btn == 'buynow') - window.open('{{PUBLISHER_URL}}', "_blank"); - else if (btn == 'contact') - window.open('mailto:{{SALES_EMAIL}}', "_blank"); - } - }); + msg : license, + buttons: buttons, + primary: primary, + callback: function(btn) { + if (btn == 'buynow') + window.open('{{PUBLISHER_URL}}', "_blank"); + else if (btn == 'contact') + window.open('mailto:{{SALES_EMAIL}}', "_blank"); + } + }); } else if (!this.appOptions.isDesktopApp && !this.appOptions.canBrandingExt && this.editorConfig && this.editorConfig.customization && (this.editorConfig.customization.loaderName || this.editorConfig.customization.loaderLogo || this.editorConfig.customization.font && (this.editorConfig.customization.font.size || this.editorConfig.customization.font.name))) { @@ -1311,7 +1314,7 @@ define([ return; } - if ( this.onServerVersion(params.asc_getBuildVersion()) || !this.onLanguageLoaded() ) return; + if ( this.onServerVersion(params.asc_getBuildVersion()) || !this.onLanguageLoaded()) return; if ( this._isDocReady || this._isPermissionsInited ) { this.api.asc_LoadDocument(); return; @@ -1344,6 +1347,10 @@ define([ this.appOptions.canSwitchMode = this.appOptions.isPDFAnnotate && this.appOptions.canPDFEdit; // switch between View/annotate and pdf edit // this.appOptions.canCoEditing = (this.appOptions.isPDFAnnotate || this.appOptions.isPDFFill) && !(this.appOptions.isDesktopApp && this.appOptions.isOffline); + this.appOptions.canUseHistory = pdfEdit && this.appOptions.canLicense && this.editorConfig.canUseHistory && this.appOptions.canCoAuthoring && !this.appOptions.isOffline; + this.appOptions.canHistoryClose = this.editorConfig.canHistoryClose; + this.appOptions.canHistoryRestore= this.editorConfig.canHistoryRestore; + this.appOptions.canComments = pdfEdit && this.appOptions.canLicense && (this.permissions.comment===undefined ? this.appOptions.isPDFAnnotate : this.permissions.comment) && (this.editorConfig.mode !== 'view'); this.appOptions.canComments = this.appOptions.canComments && !((typeof (this.editorConfig.customization) == 'object') && this.editorConfig.customization.comments===false); this.appOptions.canViewComments = this.appOptions.canComments || pdfEdit && !((typeof (this.editorConfig.customization) == 'object') && this.editorConfig.customization.comments===false); @@ -1655,9 +1662,9 @@ define([ applyModeEditorElements: function() { var me = this, - application = this.getApplication(); - // reviewController = application.getController('Common.Controllers.ReviewChanges'); - // reviewController.setMode(me.appOptions).setConfig({config: me.editorConfig}, me.api).loadDocument({doc:me.document}); + application = this.getApplication(), + reviewController = application.getController('Common.Controllers.ReviewChanges'); + reviewController.setMode(me.appOptions).setConfig({config: me.editorConfig}, me.api).loadDocument({doc:me.document}); if (this.appOptions.isEdit) { if (me.appOptions.isSignatureSupport || me.appOptions.isPasswordSupport) @@ -1704,11 +1711,14 @@ define([ onError: function(id, level, errData) { switch (id) { case Asc.c_oAscError.ID.LoadingScriptError: - this.showTips([this.scriptLoadError]); - this.tooltip && this.tooltip.getBSTip().$tip.css('z-index', 10000); - return; + this.showTips([this.scriptLoadError]); + this.tooltip && this.tooltip.getBSTip().$tip.css('z-index', 10000); + return; case Asc.c_oAscError.ID.CanNotPasteImage: - this.showTips([this.errorCannotPasteImg], {timeout: 7000, hideCloseTip: true}); + this.showTips([this.errorCannotPasteImg], {timeout: 7000, hideCloseTip: true}); + return; + case Asc.c_oAscError.ID.DocumentAndChangeMismatch: + this.getApplication().getController('Common.Controllers.History').onHashError(); return; case Asc.c_oAscError.ID.UpdateVersion: Common.UI.TooltipManager.showTip('updateVersion'); @@ -1723,7 +1733,7 @@ define([ if (this._state.lostEditingRights) { this._state.lostEditingRights = false; return; - } + } this._state.lostEditingRights = true; Common.NotificationCenter.trigger('collaboration:sharingdeny'); var me = this; @@ -2420,7 +2430,7 @@ define([ Common.localStorage.setItem("pdfe-settings-showchanges-strict", 'last'); Common.Utils.InternalSettings.set("pdfe-settings-showchanges-strict", 'last'); this.api.SetCollaborativeMarksShowType(Asc.c_oAscCollaborativeMarksShowType.LastChanges); - // this.getApplication().getController('Common.Controllers.ReviewChanges').applySettings(); + this.getApplication().getController('Common.Controllers.ReviewChanges').applySettings(); } this.onEditComplete(); }, this) @@ -2484,6 +2494,7 @@ define([ var filemenu = this.getApplication().getController('LeftMenu').getView('LeftMenu').getMenu('file'); filemenu.loadDocument({doc:this.document}); filemenu.panels && filemenu.panels['info'] && filemenu.panels['info'].updateInfo(this.document); + this.getApplication().getController('Common.Controllers.ReviewChanges').loadDocument({doc:this.document}); Common.Gateway.metaChange(meta); if (this.appOptions.wopi) { @@ -2758,6 +2769,176 @@ define([ } }, + DisableVersionHistory: function() { + this.editorConfig.canUseHistory = false; + this.appOptions.canUseHistory = false; + }, + + 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(); + appHeader.setCanRename(false); + appHeader.getButton('users') && appHeader.getButton('users').hide(); + appHeader.getButton('share') && appHeader.getButton('share').setVisible(false); + 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, + arrIds = []; + 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 (var ver=versions.length-1, index = 0; ver>=0; ver--, index++) { + 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) { + var color = Common.UI.ExternalUsers.getColor(version.user.id || version.user.name || this.textAnonymous, true); + user = new Common.Models.User({ + id : version.user.id, + username : version.user.name || this.textAnonymous, + colorval : color, + color : this.generateUserColor(color) + }); + usersStore.add(user); + } + var avatar = Common.UI.ExternalUsers.getImage(version.user.id); + (avatar===undefined) && arrIds.push(version.user.id); + arrVersions.push(new Common.Models.HistoryVersion({ + version: version.versionGroup, + revision: version.version, + userid : version.user.id, + username : version.user.name || this.textAnonymous, + usercolor: user.get('color'), + initials : Common.Utils.getUserInitials(AscCommon.UserInfoParser.getParsedName(version.user.name || this.textAnonymous)), + avatar : avatar, + 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, + fileType: 'docx', + index: index + })); + 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 && false) { // hide changes for pdf + 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('hasSubItems', changes.length>1); + arrVersions[arrVersions.length-1].set('documentSha256', changes[changes.length-1].documentSha256); + for (i=changes.length-2; i>=0; i--, index++) { + change = changes[i]; + + user = usersStore.findUser(change.user.id); + if (!user) { + var color = Common.UI.ExternalUsers.getColor(change.user.id || change.user.name || this.textAnonymous, true); + user = new Common.Models.User({ + id : change.user.id, + username : change.user.name || this.textAnonymous, + colorval : color, + color : this.generateUserColor(color) + }); + usersStore.add(user); + } + avatar = Common.UI.ExternalUsers.getImage(change.user.id); + (avatar===undefined) && arrIds.push(change.user.id); + arrVersions.push(new Common.Models.HistoryVersion({ + version: version.versionGroup, + revision: version.version, + changeid: i, + userid : change.user.id, + username : change.user.name || this.textAnonymous, + usercolor: user.get('color'), + initials : Common.Utils.getUserInitials(AscCommon.UserInfoParser.getParsedName(change.user.name || this.textAnonymous)), + avatar : avatar, + created: change.created, + docId: version.key, + docIdPrev: docIdPrev, + selected: false, + canRestore: this.appOptions.canHistoryRestore && this.appOptions.canDownload, + isRevision: false, + isVisible: true, + serverVersion: version.serverVersion, + documentSha256: change.documentSha256, + fileType: 'docx', + hasParent: true, + index: index, + level: 1 + })); + 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); + arrIds.length && Common.UI.ExternalUsers.get('info', arrIds); + } + } + }, + + generateUserColor: function(color) { + return"#"+("000000"+color.toString(16)).substr(-6); + }, + onSaveDocumentBinary: function(data) { Common.Gateway.saveDocument(data); }, diff --git a/apps/pdfeditor/main/app/controller/Toolbar.js b/apps/pdfeditor/main/app/controller/Toolbar.js index 3c76970806..cd2c9506e9 100644 --- a/apps/pdfeditor/main/app/controller/Toolbar.js +++ b/apps/pdfeditor/main/app/controller/Toolbar.js @@ -643,7 +643,7 @@ define([ if (annotPr && annotPr.asc_getCanEditText && annotPr.asc_getCanEditText()) { in_text_annot = true; no_text = false; - } + } } else if (type == Asc.c_oAscTypeSelectElement.PdfPage) { page_deleted = pr.asc_getDeleteLock(); page_rotate_lock = pr.asc_getRotateLock(); @@ -654,7 +654,7 @@ define([ no_text = false; in_text_form = ft===AscPDF.FIELD_TYPES.text || ft===AscPDF.FIELD_TYPES.combobox || ft===AscPDF.FIELD_TYPES.listbox; in_check_form = ft===AscPDF.FIELD_TYPES.checkbox || ft===AscPDF.FIELD_TYPES.radiobutton; - } + } } if (this._state.prcontrolsdisable !== paragraph_locked) { @@ -819,8 +819,8 @@ define([ options.asc_setIsSaveAs(false); me.api.asc_DownloadOrigin(options); } else { - Common.UI.info({ - maxwidth: 500, + Common.UI.info({ + maxwidth: 500, msg: this.errorAccessDeny, callback: function(btn) { Common.NotificationCenter.trigger('edit:complete', toolbar); @@ -1555,6 +1555,13 @@ define([ } me.getApplication().getController('Common.Controllers.ExternalLinks').setConfig({toolbar: me}).setApi(me.api); !config.canComments && me.toolbar.setVisible('comment', false); + + var tab = {action: 'review', caption: me.toolbar.textTabCollaboration, dataHintTitle: 'U', layoutname: 'toolbar-collaboration'}; + var $panel = me.getApplication().getController('Common.Controllers.ReviewChanges').createToolbarPanel(); + if ( $panel ) { + me.toolbar.addTab(tab, $panel, 7); + me.toolbar.setVisible('review', (config.isPDFAnnotate || config.isPDFEdit) && Common.UI.LayoutManager.isElementVisible('toolbar-collaboration') ); // use config.canViewReview in review controller. set visible review tab in view mode only when asc_HaveRevisionsChanges + } } var tab = {caption: me.toolbar.textTabView, action: 'view', extcls: config.isEdit ? 'canedit' : '', layoutname: 'toolbar-view', dataHintTitle: 'W'}; @@ -1600,7 +1607,7 @@ define([ me.toolbar.setVisible('forms', true); Array.prototype.push.apply(me.toolbar.lockControls, forms.getView('FormsTab').getButtons()); - } + } } } }, @@ -1714,6 +1721,30 @@ define([ me.toolbar.btnSubmit.updateHint(me.textRequired); } } + + me.btnsComment = []; + if ( config.canComments ) { + var _set = Common.enumLock; + me.btnsComment = Common.Utils.injectButtons(me.toolbar.$el.find('.slot-comment'), 'tlbtn-addcomment-', 'toolbar__icon btn-big-add-comment', me.toolbar.capBtnComment, [_set.lostConnect], undefined, undefined, undefined, '1', 'bottom', 'small'); + + if ( me.btnsComment.length ) { + var _comments = PDFE.getController('Common.Controllers.Comments').getView(); + me.btnsComment.forEach(function (btn) { + btn.updateHint( _comments.textHintAddComment ); + btn.on('click', function (btn, e) { + Common.NotificationCenter.trigger('app:comment:add', 'toolbar'); + }); + if (btn.cmpEl.closest('#review-changes-panel').length>0) + btn.setCaption(me.toolbar.capBtnAddComment); + }, me); + if (_comments.buttonAddNew) { + _comments.buttonAddNew.options.lock = [ _set.lostConnect ]; + me.btnsComment.add(_comments.buttonAddNew); + } + Array.prototype.push.apply(me.toolbar.lockControls, me.btnsComment); + Array.prototype.push.apply(me.toolbar.toolbarControls, me.btnsComment); + } + } }); }, diff --git a/apps/pdfeditor/main/app/controller/Viewport.js b/apps/pdfeditor/main/app/controller/Viewport.js index 80faedc133..b248b3e443 100644 --- a/apps/pdfeditor/main/app/controller/Viewport.js +++ b/apps/pdfeditor/main/app/controller/Viewport.js @@ -154,10 +154,11 @@ define([ Common.NotificationCenter.on('layout:changed', _.bind(this.onLayoutChanged, this)); $(window).on('resize', _.bind(this.onWindowResize, this)); - var leftPanel = $('#left-menu'); + var leftPanel = $('#left-menu'), + histPanel = $('#left-panel-history'); this.viewport.hlayout.on('layout:resizedrag', function() { this.api.Resize(); - Common.localStorage.setItem('pdfe-mainmenu-width', leftPanel.width() ); + Common.localStorage.setItem('pdfe-mainmenu-width', histPanel.is(':visible') ? (histPanel.width()+SCALE_MIN) : leftPanel.width() ); }, this); this.boxSdk = $('#editor_sdk'); @@ -220,6 +221,14 @@ define([ case 'rightmenu': this.viewport.hlayout.doLayout(); break; + case 'history': + var panel = this.viewport.hlayout.getItem('history'); + 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.getItem('left'); if (panel.resize.el) { diff --git a/apps/pdfeditor/main/app/template/FileMenu.template b/apps/pdfeditor/main/app/template/FileMenu.template index 6989d3ff9f..aa266144f4 100644 --- a/apps/pdfeditor/main/app/template/FileMenu.template +++ b/apps/pdfeditor/main/app/template/FileMenu.template @@ -13,6 +13,7 @@
  • +
  • diff --git a/apps/pdfeditor/main/app/template/Viewport.template b/apps/pdfeditor/main/app/template/Viewport.template index 1d62d20983..02cac83474 100644 --- a/apps/pdfeditor/main/app/template/Viewport.template +++ b/apps/pdfeditor/main/app/template/Viewport.template @@ -11,6 +11,7 @@
    +
    diff --git a/apps/pdfeditor/main/app/view/FileMenu.js b/apps/pdfeditor/main/app/view/FileMenu.js index 1d8927deea..cc21cd2bde 100644 --- a/apps/pdfeditor/main/app/view/FileMenu.js +++ b/apps/pdfeditor/main/app/view/FileMenu.js @@ -254,6 +254,21 @@ define([ iconCls: 'menu__icon btn-users-share' }); + this.miHistory = new Common.UI.MenuItem({ + el : $markup.elementById('#fm-btn-history'), + action : 'history', + caption : this.btnHistoryCaption, + canFocused: false, + dataHint: 1, + dataHintDirection: 'left-top', + dataHintOffset: [-2, 22], + iconCls: 'menu__icon btn-version-history' + }); + if ( !!this.options.miHistory ) { + this.miHistory.setDisabled(this.options.miHistory.isDisabled()); + delete this.options.miHistory; + } + this.miSettings = new Common.UI.MenuItem({ el : $markup.elementById('#fm-btn-settings'), action : 'opts', @@ -313,6 +328,7 @@ define([ this.miNew, this.miInfo, this.miAccess, + this.miHistory, this.miSettings, this.miHelp, this.miBack, @@ -411,6 +427,12 @@ define([ (this.mode.sharingSettingsUrl&&this.mode.sharingSettingsUrl.length || this.mode.canRequestSharingSettings)); this.miAccess[isVisible?'show':'hide'](); + isVisible = this.mode.canUseHistory&&!this.mode.isDisconnected; + // separatorVisible = separatorVisible || isVisible; + this.miHistory[isVisible?'show':'hide'](); + // this.miHistory.$el.find('+.devider')[separatorVisible?'show':'hide'](); + // separatorVisible && (lastSeparator = this.miHistory.$el.find('+.devider')); + isVisible = Common.UI.LayoutManager.isElementVisible('toolbar-file-settings'); this.miSettings[isVisible?'show':'hide'](); isVisible = this.mode.canHelp; @@ -644,9 +666,11 @@ define([ }, SetDisabled: function(disable, options) { - var _btn_protect = this.getButton('protect'); + var _btn_protect = this.getButton('protect'), + _btn_history = this.getButton('history'); options && options.protect && _btn_protect.setDisabled(disable); + options && options.history && _btn_history.setDisabled(disable); options && options.info && (this.panels ? this.panels['info'].setPreviewMode(disable) : this._state.infoPreviewMode = disable ); }, @@ -664,6 +688,9 @@ define([ } else if (type == 'protect') { return this.options.miProtect ? this.options.miProtect : (this.options.miProtect = new Common.UI.MenuItem({})); + } else + if (type == 'history') { + return this.options.miHistory ? this.options.miHistory : (this.options.miHistory = new Common.UI.MenuItem({})); } } else { if (type == 'save') { @@ -674,6 +701,9 @@ define([ }else if (type == 'protect') { return this.miProtect; + }else + if (type == 'history') { + return this.miHistory; } } }, @@ -699,6 +729,7 @@ define([ btnExitCaption : 'Exit', btnFileOpenCaption : 'Open...', btnCloseEditor : 'Close File', - ariaFileMenu : 'File menu' + ariaFileMenu : 'File menu', + btnHistoryCaption : 'Versions History' }, PDFE.Views.FileMenu || {})); }); diff --git a/apps/pdfeditor/main/app/view/LeftMenu.js b/apps/pdfeditor/main/app/view/LeftMenu.js index 8957ac44b7..b9f78fc7cd 100644 --- a/apps/pdfeditor/main/app/view/LeftMenu.js +++ b/apps/pdfeditor/main/app/view/LeftMenu.js @@ -48,6 +48,7 @@ define([ 'common/main/lib/view/Comments', 'common/main/lib/view/Chat', /** coauthoring end **/ + 'common/main/lib/view/History', 'common/main/lib/view/Plugins', 'common/main/lib/view/About', 'pdfeditor/main/app/view/FileMenu', @@ -289,6 +290,9 @@ define([ } else if (name == 'advancedsearch') { this.panelSearch = panel.render('#left-panel-search'); + } else /** coauthoring end **/ + if (name == 'history') { + this.panelHistory = panel.render('#left-panel-history'); } }, @@ -422,6 +426,13 @@ define([ return this; }, + showHistory: function() { + this._state.pluginIsRunning = false; + this.panelHistory.show(); + this.panelHistory.$el.width((parseInt(Common.localStorage.getItem('pdfe-mainmenu-width')) || MENU_SCALE_PART) - SCALE_MIN); + Common.NotificationCenter.trigger('layout:changed', 'history'); + }, + setDeveloperMode: function(mode, beta, version) { if ( !this.$el.is(':visible') ) return; diff --git a/apps/pdfeditor/main/app/view/Viewport.js b/apps/pdfeditor/main/app/view/Viewport.js index 78335dd2ef..c3ef7bdccb 100644 --- a/apps/pdfeditor/main/app/view/Viewport.js +++ b/apps/pdfeditor/main/app/view/Viewport.js @@ -112,7 +112,17 @@ define([ autohide: false, min: 300, max: 600 - }}, { // sdk + }}, { // history versions + el: items[3], + rely: true, + alias: 'history', + resize: { + hidden: true, + autohide: false, + min: 300, + max: 600 + } + }, { // sdk el: items[1], stretch: true }, { diff --git a/apps/pdfeditor/main/app_dev.js b/apps/pdfeditor/main/app_dev.js index 4959b2d1bd..5bb275f8d2 100644 --- a/apps/pdfeditor/main/app_dev.js +++ b/apps/pdfeditor/main/app_dev.js @@ -138,6 +138,7 @@ require([ 'Print', 'FormsTab', 'Common.Controllers.Fonts' + ,'Common.Controllers.History' ,'Common.Controllers.Chat' ,'Common.Controllers.Comments' ,'Common.Controllers.Draw' @@ -147,6 +148,7 @@ require([ // ,'Common.Controllers.ExternalOleEditor' ,'Common.Controllers.Protection' ,'Common.Controllers.Shortcuts' + ,'Common.Controllers.ReviewChanges' ] }); @@ -178,6 +180,7 @@ require([ 'pdfeditor/main/app/view/ChartSettings', 'common/main/lib/util/utils', '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' @@ -187,6 +190,7 @@ require([ ,'common/main/lib/controller/Draw' ,'common/main/lib/controller/Protection' ,'common/main/lib/controller/Shortcuts' + ,'common/main/lib/controller/ReviewChanges' ], function() { app.postLaunchScripts = [ 'common/main/lib/controller/ScreenReaderFocus', diff --git a/apps/pdfeditor/main/locale/en.json b/apps/pdfeditor/main/locale/en.json index 3f4c9cd5c3..67f9340e04 100644 --- a/apps/pdfeditor/main/locale/en.json +++ b/apps/pdfeditor/main/locale/en.json @@ -829,6 +829,32 @@ "Common.Views.RecentFiles.txtOpenRecent": "Open Recent", "Common.Views.RenameDialog.textName": "File name", "Common.Views.RenameDialog.txtInvalidName": "The file name cannot contain any of the following characters: ", + "Common.Views.ReviewChanges.strFast": "Fast", + "Common.Views.ReviewChanges.strFastDesc": "Real-time co-editing. All changes are saved automatically.", + "Common.Views.ReviewChanges.strStrict": "Strict", + "Common.Views.ReviewChanges.strStrictDesc": "Use the 'Save' button to sync the changes you and others make.", + "Common.Views.ReviewChanges.tipCoAuthMode": "Set co-editing mode", + "Common.Views.ReviewChanges.tipCommentRem": "Delete comments", + "Common.Views.ReviewChanges.tipCommentRemCurrent": "Delete current comments", + "Common.Views.ReviewChanges.tipCommentResolve": "Resolve comments", + "Common.Views.ReviewChanges.tipCommentResolveCurrent": "Resolve current comments", + "Common.Views.ReviewChanges.tipHistory": "Show version history", + "Common.Views.ReviewChanges.tipSharing": "Manage document access rights", + "Common.Views.ReviewChanges.txtChat": "Chat", + "Common.Views.ReviewChanges.txtClose": "Close", + "Common.Views.ReviewChanges.txtCoAuthMode": "Co-editing Mode", + "Common.Views.ReviewChanges.txtCommentRemAll": "Delete all comments", + "Common.Views.ReviewChanges.txtCommentRemCurrent": "Delete current comments", + "Common.Views.ReviewChanges.txtCommentRemMy": "Delete my comments", + "Common.Views.ReviewChanges.txtCommentRemMyCurrent": "Delete my current comments", + "Common.Views.ReviewChanges.txtCommentRemove": "Delete", + "Common.Views.ReviewChanges.txtCommentResolve": "Resolve", + "Common.Views.ReviewChanges.txtCommentResolveAll": "Resolve all comments", + "Common.Views.ReviewChanges.txtCommentResolveCurrent": "Resolve current comments", + "Common.Views.ReviewChanges.txtCommentResolveMy": "Resolve my comments", + "Common.Views.ReviewChanges.txtCommentResolveMyCurrent": "Resolve my current comments", + "Common.Views.ReviewChanges.txtHistory": "Version history", + "Common.Views.ReviewChanges.txtSharing": "Sharing", "Common.Views.ReviewPopover.textAdd": "Add", "Common.Views.ReviewPopover.textAddReply": "Add Reply", "Common.Views.ReviewPopover.textCancel": "Cancel", @@ -1425,6 +1451,7 @@ "PDFE.Controllers.LeftMenu.warnDownloadAs": "If you continue saving in this format all features except the text will be lost.
    Are you sure you want to continue?", "PDFE.Controllers.LeftMenu.warnDownloadAsPdf": "Your {0} will be converted to an editable format. This may take a while. The resulting document will be optimized to allow you to edit the text, so it might not look exactly like the original {0}, especially if the original file contained lots of graphics.", "PDFE.Controllers.LeftMenu.warnDownloadAsRTF": "If you continue saving in this format some of the formatting might be lost.
    Are you sure you want to continue?", + "PDFE.Controllers.LeftMenu.textLoadHistory": "Loading version history...", "PDFE.Controllers.Main.applyChangesTextText": "Loading the changes...", "PDFE.Controllers.Main.applyChangesTitleText": "Loading the changes", "PDFE.Controllers.Main.confirmMaxChangesSize": "The size of actions exceeds the limitation set for your server.
    Press \"Undo\" to cancel your last action or press \"Continue\" to keep action locally (you need to download the file or copy its content to make sure nothing is lost).", @@ -1595,6 +1622,7 @@ "PDFE.Controllers.Main.warnNoLicense": "You've reached the limit for simultaneous connections to %1 editors. This document will be opened for viewing only.
    Contact %1 sales team for personal upgrade terms.", "PDFE.Controllers.Main.warnNoLicenseUsers": "You've reached the user limit for %1 editors. Contact %1 sales team for personal upgrade terms.", "PDFE.Controllers.Main.warnProcessRightsChange": "You have been denied the right to edit the file.", + "PDFE.Controllers.Main.txtErrorLoadHistory": "History loading failed", "PDFE.Controllers.Navigation.txtBeginning": "Beginning of document", "PDFE.Controllers.Navigation.txtGotoBeginning": "Go to the beginning of the document", "PDFE.Controllers.Print.textMarginsLast": "Last custom", @@ -2035,6 +2063,7 @@ "PDFE.Views.FileMenu.btnSwitchToMobileCaption": "Switch to Mobile", "PDFE.Views.FileMenu.btnToEditCaption": "Edit Document", "PDFE.Views.FileMenu.textDownload": "Download", + "PDFE.Views.FileMenu.btnHistoryCaption": "Version History", "PDFE.Views.FileMenuPanels.CreateNew.txtBlank": "Blank Document", "PDFE.Views.FileMenuPanels.CreateNew.txtCreateNew": "Create new", "PDFE.Views.FileMenuPanels.DocumentInfo.okButtonText": "Apply", @@ -3019,6 +3048,8 @@ "PDFE.Views.Toolbar.txtRotateRight": "Rotate right", "PDFE.Views.Toolbar.txtSize": "Size", "PDFE.Views.Toolbar.txtUngroup": "Ungroup", + "PDFE.Views.Toolbar.textTabCollaboration": "Collaboration", + "PDFE.Views.Toolbar.capBtnAddComment": "Add Comment", "PDFE.Views.ViewTab.textAlwaysShowToolbar": "Always Show Toolbar", "PDFE.Views.ViewTab.textDarkDocument": "Dark Document", "PDFE.Views.ViewTab.textFill": "Fill", diff --git a/apps/pdfeditor/main/resources/less/app.less b/apps/pdfeditor/main/resources/less/app.less index af0e0a6b68..8775c92800 100644 --- a/apps/pdfeditor/main/resources/less/app.less +++ b/apps/pdfeditor/main/resources/less/app.less @@ -96,6 +96,7 @@ @import "../../../../common/main/resources/less/winxp_fix.less"; @import "../../../../common/main/resources/less/symboltable.less"; @import "../../../../common/main/resources/less/hint-manager.less"; +@import "../../../../common/main/resources/less/history.less"; @import "../../../../common/main/resources/less/bigscaling.less"; @import "../../../../common/main/resources/less/updown-picker.less"; @import "../../../../common/main/resources/less/calendar.less"; diff --git a/apps/pdfeditor/main/resources/less/layout.less b/apps/pdfeditor/main/resources/less/layout.less index e146085ae0..b538a89e86 100644 --- a/apps/pdfeditor/main/resources/less/layout.less +++ b/apps/pdfeditor/main/resources/less/layout.less @@ -71,6 +71,13 @@ label { } } +#left-panel-history { + left: 40px; + width: 300px; + height: 100%; + display: none; +} + #editor_sdk { width: 100%; height: 100%; diff --git a/apps/pdfeditor/main/resources/less/leftmenu.less b/apps/pdfeditor/main/resources/less/leftmenu.less index 5e1d9630d8..d284903ef6 100644 --- a/apps/pdfeditor/main/resources/less/leftmenu.less +++ b/apps/pdfeditor/main/resources/less/leftmenu.less @@ -11,6 +11,12 @@ } } +.left-panel { + #left-panel-history { + height: 100%; + } +} + .left-menu-full-ct { width: 100%; height: 100%;