From 2de75d5f03cb90acb93a41edfdb47dbb704db42d Mon Sep 17 00:00:00 2001 From: Julia Radzhabova Date: Thu, 2 Feb 2023 20:48:41 +0300 Subject: [PATCH] Refactoring mentions --- .../main/lib/controller/ExternalUsers.js | 83 +++++++++ apps/common/main/lib/view/ReviewPopover.js | 174 ++++++++---------- .../main/app/controller/Main.js | 4 +- .../main/app/controller/Main.js | 4 +- .../main/app/controller/Main.js | 4 +- 5 files changed, 172 insertions(+), 97 deletions(-) create mode 100644 apps/common/main/lib/controller/ExternalUsers.js diff --git a/apps/common/main/lib/controller/ExternalUsers.js b/apps/common/main/lib/controller/ExternalUsers.js new file mode 100644 index 0000000000..c58057a857 --- /dev/null +++ b/apps/common/main/lib/controller/ExternalUsers.js @@ -0,0 +1,83 @@ +/* + * + * (c) Copyright Ascensio System SIA 2010-2023 + * + * This program is a free software product. You can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License (AGPL) + * version 3 as published by the Free Software Foundation. In accordance with + * Section 7(a) of the GNU AGPL its Section 15 shall be amended to the effect + * that Ascensio System SIA expressly excludes the warranty of non-infringement + * of any third-party rights. + * + * This program is distributed WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For + * details, see the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html + * + * You can contact Ascensio System SIA at 20A-12 Ernesta Birznieka-Upisha + * street, Riga, Latvia, EU, LV-1050. + * + * The interactive user interfaces in modified source and object code versions + * of the Program must display Appropriate Legal Notices, as required under + * Section 5 of the GNU AGPL version 3. + * + * Pursuant to Section 7(b) of the License you must retain the original Product + * logo when distributing the program. Pursuant to Section 7(e) we decline to + * grant you any rights under trademark law for use of our trademarks. + * + * All the Product's GUI elements, including illustrations and icon sets, as + * well as technical writing content are licensed under the terms of the + * Creative Commons Attribution-ShareAlike 4.0 International. See the License + * terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode + * +*/ +/** + * ExternalUsers.js + * + * Created by Julia Radzhabova on 02 February 2023 + * Copyright (c) 2023 Ascensio System SIA. All rights reserved. + * + */ +if (Common === undefined) + var Common = {}; + +if (Common.UI === undefined) { + Common.UI = {}; +} + +Common.UI.ExternalUsers = new( function() { + var externalUsers = [], + getCallback, + isUsersLoading = false; + + var _get = function(callback) { + if (isUsersLoading) return; + + getCallback = null; + if (externalUsers.length>0) + callback(externalUsers); + else { + getCallback = callback; + isUsersLoading = true; + Common.Gateway.requestUsers(); + } + }; + + var _init = function(canRequestUsers) { + if (!canRequestUsers) return; + + Common.Gateway.on('setusers', function(data) { + externalUsers = data.users || []; + isUsersLoading = false; + getCallback && getCallback(externalUsers); + getCallback = null; + }); + Common.NotificationCenter.on('mentions:clearusers', function() { + externalUsers = []; + }); + }; + + return { + init: _init, + get: _get + } +})(); diff --git a/apps/common/main/lib/view/ReviewPopover.js b/apps/common/main/lib/view/ReviewPopover.js index 3b25e6d8f5..e5bdab8ad3 100644 --- a/apps/common/main/lib/view/ReviewPopover.js +++ b/apps/common/main/lib/view/ReviewPopover.js @@ -105,7 +105,6 @@ define([ this.canRequestSendNotify = options.canRequestSendNotify; this.mentionShare = options.mentionShare; this.api = options.api; - this.externalUsers = []; this._state = {commentsVisible: false, reviewVisible: false}; _options.tpl = _.template(this.template)(_options); @@ -115,11 +114,6 @@ define([ Common.UI.Window.prototype.initialize.call(this, _options); - if (this.canRequestUsers) { - Common.Gateway.on('setusers', _.bind(this.setUsers, this)); - Common.NotificationCenter.on('mentions:clearusers', _.bind(this.clearUsers, this)); - } - return this; }, render: function (comments, review) { @@ -1166,17 +1160,6 @@ define([ this.commentsView.setStore(this.commentsStore); }, - setUsers: function(data) { - this.externalUsers = data.users || []; - this.isUsersLoading = false; - this._state.emailSearch && this.onEmailListMenu(this._state.emailSearch.str, this._state.emailSearch.left, this._state.emailSearch.right); - this._state.emailSearch = null; - }, - - clearUsers: function() { - this.externalUsers = []; - }, - getPopover: function(options) { if (!this.popover) this.popover = new Common.Views.ReviewPopover(options); @@ -1201,96 +1184,99 @@ define([ } }, - onEmailListMenu: function(str, left, right, show) { - var me = this, - users = me.externalUsers, - menu = me.emailMenu; - - if (users.length<1) { + onEmailListMenu: function(str, left, right) { + if (typeof str == 'string') { this._state.emailSearch = { str: str, left: left, right: right }; - - if (this.isUsersLoading) return; - - this.isUsersLoading = true; - Common.Gateway.requestUsers(); - return; + Common.UI.ExternalUsers.get(this.onEmailListMenuCallback.bind(this)); + } else { + this._state.emailSearch = null; + this.emailMenu.rendered && this.emailMenu.cmpEl.css('display', 'none'); } - if (typeof str == 'string') { - var menuContainer = me.$window.find(Common.Utils.String.format('#menu-container-{0}', menu.id)), - textbox = this.commentsView.getTextBox(), - textboxDom = textbox ? textbox[0] : null, - showPoint = textboxDom ? [textboxDom.offsetLeft, textboxDom.offsetTop + textboxDom.clientHeight + 3] : [0, 0]; + }, - if (!menu.rendered) { - // Prepare menu container - if (menuContainer.length < 1) { - menuContainer = $(Common.Utils.String.format('', menu.id)); - me.$window.append(menuContainer); - } + onEmailListMenuCallback: function(users) { + if (!this._state.emailSearch || users.length<1) return; - menu.render(menuContainer); - menu.cmpEl.css('min-width', textboxDom ? textboxDom.clientWidth : 220); - menu.cmpEl.attr({tabindex: "-1"}); - menu.on('hide:after', function(){ - setTimeout(function(){ - var tb = me.commentsView.getTextBox(); - tb && tb.focus(); - }, 10); + var me = this, + menu = me.emailMenu, + str = this._state.emailSearch.str, + left = this._state.emailSearch.left, + right = this._state.emailSearch.right; + + this._state.emailSearch = null; + + var menuContainer = me.$window.find(Common.Utils.String.format('#menu-container-{0}', menu.id)), + textbox = this.commentsView.getTextBox(), + textboxDom = textbox ? textbox[0] : null, + showPoint = textboxDom ? [textboxDom.offsetLeft, textboxDom.offsetTop + textboxDom.clientHeight + 3] : [0, 0]; + + if (!menu.rendered) { + // Prepare menu container + if (menuContainer.length < 1) { + menuContainer = $(Common.Utils.String.format('', menu.id)); + me.$window.append(menuContainer); + } + + menu.render(menuContainer); + menu.cmpEl.css('min-width', textboxDom ? textboxDom.clientWidth : 220); + menu.cmpEl.attr({tabindex: "-1"}); + menu.on('hide:after', function(){ + setTimeout(function(){ + var tb = me.commentsView.getTextBox(); + tb && tb.focus(); + }, 10); + }); + } + + for (var i = 0; i < menu.items.length; i++) { + menu.removeItem(menu.items[i]); + i--; + } + + if (users.length>0) { + str = str.toLowerCase(); + if (str.length>0) { + users = _.filter(users, function(item) { + return (item.email && 0 === item.email.toLowerCase().indexOf(str) || item.name && 0 === item.name.toLowerCase().indexOf(str)) }); } - - for (var i = 0; i < menu.items.length; i++) { - menu.removeItem(menu.items[i]); - i--; - } - - if (users.length>0) { - str = str.toLowerCase(); - if (str.length>0) { - users = _.filter(users, function(item) { - return (item.email && 0 === item.email.toLowerCase().indexOf(str) || item.name && 0 === item.name.toLowerCase().indexOf(str)) - }); - } - var tpl = _.template('' + - '
<%= Common.Utils.String.htmlEncode(caption) %>
' + - '
<%= Common.Utils.String.htmlEncode(options.value) %>
' + - '
'), + var tpl = _.template('' + + '
<%= Common.Utils.String.htmlEncode(caption) %>
' + + '
<%= Common.Utils.String.htmlEncode(options.value) %>
' + + '
'), + divider = false; + _.each(users, function(menuItem, index) { + if (divider && !menuItem.hasAccess) { divider = false; - _.each(users, function(menuItem, index) { - if (divider && !menuItem.hasAccess) { - divider = false; - menu.addItem(new Common.UI.MenuItem({caption: '--'})); - } + menu.addItem(new Common.UI.MenuItem({caption: '--'})); + } - if (menuItem.email && menuItem.name) { - var mnu = new Common.UI.MenuItem({ - caption : menuItem.name, - value : menuItem.email, - template : tpl - }).on('click', function(item, e) { - me.insertEmailToTextbox(item.options.value, left, right); - }); - menu.addItem(mnu); - if (menuItem.hasAccess) - divider = true; - } - }); - } + if (menuItem.email && menuItem.name) { + var mnu = new Common.UI.MenuItem({ + caption : menuItem.name, + value : menuItem.email, + template : tpl + }).on('click', function(item, e) { + me.insertEmailToTextbox(item.options.value, left, right); + }); + menu.addItem(mnu); + if (menuItem.hasAccess) + divider = true; + } + }); + } - if (menu.items.length>0) { - menuContainer.css({left: showPoint[0], top : showPoint[1]}); - menu.menuAlignEl = textbox; - menu.show(); - menu.cmpEl.css('display', ''); - menu.alignPosition('bl-tl', -5); - menu.scroller.update({alwaysVisibleY: true}); - } else { - menu.rendered && menu.cmpEl.css('display', 'none'); - } + if (menu.items.length>0) { + menuContainer.css({left: showPoint[0], top : showPoint[1]}); + menu.menuAlignEl = textbox; + menu.show(); + menu.cmpEl.css('display', ''); + menu.alignPosition('bl-tl', -5); + menu.scroller.update({alwaysVisibleY: true}); } else { menu.rendered && menu.cmpEl.css('display', 'none'); } diff --git a/apps/documenteditor/main/app/controller/Main.js b/apps/documenteditor/main/app/controller/Main.js index 3986e41755..7fbf03cc11 100644 --- a/apps/documenteditor/main/app/controller/Main.js +++ b/apps/documenteditor/main/app/controller/Main.js @@ -55,7 +55,8 @@ define([ 'documenteditor/main/app/collection/EquationGroups', 'common/main/lib/controller/FocusManager', 'common/main/lib/controller/HintManager', - 'common/main/lib/controller/LayoutManager' + 'common/main/lib/controller/LayoutManager', + 'common/main/lib/controller/ExternalUsers' ], function () { 'use strict'; @@ -1601,6 +1602,7 @@ define([ this.getApplication().getController('Common.Controllers.Plugins').setMode(this.appOptions, this.api); this.editorConfig.customization && Common.UI.LayoutManager.init(this.editorConfig.customization.layout, this.appOptions.canBrandingExt); this.editorConfig.customization && Common.UI.FeaturesManager.init(this.editorConfig.customization.features, this.appOptions.canBrandingExt); + Common.UI.ExternalUsers.init(this.appOptions.canRequestUsers); if (this.appOptions.canComments) Common.NotificationCenter.on('comments:cleardummy', _.bind(this.onClearDummyComment, this)); diff --git a/apps/presentationeditor/main/app/controller/Main.js b/apps/presentationeditor/main/app/controller/Main.js index aefd89306b..b4f7f088eb 100644 --- a/apps/presentationeditor/main/app/controller/Main.js +++ b/apps/presentationeditor/main/app/controller/Main.js @@ -56,7 +56,8 @@ define([ 'presentationeditor/main/app/collection/EquationGroups', 'common/main/lib/controller/FocusManager', 'common/main/lib/controller/HintManager', - 'common/main/lib/controller/LayoutManager' + 'common/main/lib/controller/LayoutManager', + 'common/main/lib/controller/ExternalUsers' ], function () { 'use strict'; PE.Controllers.Main = Backbone.Controller.extend(_.extend((function() { @@ -1256,6 +1257,7 @@ define([ this.getApplication().getController('Common.Controllers.Plugins').setMode(this.appOptions); this.editorConfig.customization && Common.UI.LayoutManager.init(this.editorConfig.customization.layout, this.appOptions.canBrandingExt); this.editorConfig.customization && Common.UI.FeaturesManager.init(this.editorConfig.customization.features, this.appOptions.canBrandingExt); + Common.UI.ExternalUsers.init(this.appOptions.canRequestUsers); // change = true by default in editor this.appOptions.canLiveView = !!params.asc_getLiveViewerSupport() && (this.editorConfig.mode === 'view'); // viewer: change=false when no flag canLiveViewer (i.g. old license), change=true by default when canLiveViewer==true diff --git a/apps/spreadsheeteditor/main/app/controller/Main.js b/apps/spreadsheeteditor/main/app/controller/Main.js index fcf4352825..d056e2ebac 100644 --- a/apps/spreadsheeteditor/main/app/controller/Main.js +++ b/apps/spreadsheeteditor/main/app/controller/Main.js @@ -59,7 +59,8 @@ define([ 'spreadsheeteditor/main/app/controller/FormulaDialog', 'common/main/lib/controller/FocusManager', 'common/main/lib/controller/HintManager', - 'common/main/lib/controller/LayoutManager' + 'common/main/lib/controller/LayoutManager', + 'common/main/lib/controller/ExternalUsers' ], function () { 'use strict'; @@ -1356,6 +1357,7 @@ define([ this.getApplication().getController('Common.Controllers.Plugins').setMode(this.appOptions); this.editorConfig.customization && Common.UI.LayoutManager.init(this.editorConfig.customization.layout, this.appOptions.canBrandingExt); this.editorConfig.customization && Common.UI.FeaturesManager.init(this.editorConfig.customization.features, this.appOptions.canBrandingExt); + Common.UI.ExternalUsers.init(this.appOptions.canRequestUsers); } this.appOptions.canUseHistory = this.appOptions.canLicense && this.editorConfig.canUseHistory && this.appOptions.canCoAuthoring && !this.appOptions.isOffline;