\ No newline at end of file
diff --git a/apps/documenteditor/main/app/template/RightMenu.template b/apps/documenteditor/main/app/template/RightMenu.template
index 90cb7c62bb..0f09cade57 100644
--- a/apps/documenteditor/main/app/template/RightMenu.template
+++ b/apps/documenteditor/main/app/template/RightMenu.template
@@ -10,6 +10,8 @@
+
+
@@ -23,6 +25,8 @@
+
+
\ No newline at end of file
diff --git a/apps/documenteditor/main/app/template/SendForSigningSettings.template b/apps/documenteditor/main/app/template/SendForSigningSettings.template
new file mode 100644
index 0000000000..429a71faf1
--- /dev/null
+++ b/apps/documenteditor/main/app/template/SendForSigningSettings.template
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/apps/documenteditor/main/app/view/FillingStatusSettings.js b/apps/documenteditor/main/app/view/FillingStatusSettings.js
new file mode 100644
index 0000000000..39712be187
--- /dev/null
+++ b/apps/documenteditor/main/app/view/FillingStatusSettings.js
@@ -0,0 +1,107 @@
+/*
+ * (c) Copyright Ascensio System SIA 2010-2024
+ *
+ * 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-6 Ernesta Birznieka-Upish
+ * 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
+ *
+ */
+/**
+ * FillingStatusSettings.js
+ *
+ * Created on 10.03.2026
+ *
+ */
+
+define([
+ 'text!documenteditor/main/app/template/FillingStatusSettings.template',
+ 'jquery',
+ 'underscore',
+ 'backbone',
+ 'common/main/lib/component/Button'
+], function (menuTemplate, $, _, Backbone) {
+ 'use strict';
+
+ DE.Views.FillingStatusSettings = Backbone.View.extend(_.extend({
+ el: '#id-filling-status-settings',
+
+ // Compile our stats template
+ template: _.template(menuTemplate),
+
+ // Delegated events for creating new items, and clearing completed ones.
+ events: {
+ },
+
+ options: {
+ alias: 'FillingStatusSettings'
+ },
+
+ initialize: function () {
+ this._state = {};
+ this._locked = false;
+
+ this.render();
+ },
+
+ render: function () {
+ const items = [
+ { email: 'user333@gmail.com', name: 'Anyone', date: '1/20/2026 9:00 PM', status: 'done' },
+ { email: 'test@yandex.ru', name: 'User1', date: null, status: 'done' },
+ { email: 'test@yandex.ru', name: 'User2', date: null, status: 'done' }
+ ];
+ const el = this.$el || $(this.el);
+ el.html(this.template({
+ scope: this,
+ items: items,
+ isAllDone: items.every(function(item) { return item.status == 'done'})
+ }));
+ },
+
+ setApi: function(api) {
+ this.api = api;
+ return this;
+ },
+
+ ChangeSettings: function(props) {
+
+ },
+
+ setLocked: function (locked) {
+ this._locked = locked;
+ },
+
+ setMode: function(mode) {
+ this.mode = mode;
+ },
+
+ disableControls: function(disable) {
+
+ },
+
+ txtTitle: 'Filling status',
+
+ }, DE.Views.FillingStatusSettings || {}));
+});
\ No newline at end of file
diff --git a/apps/documenteditor/main/app/view/RightMenu.js b/apps/documenteditor/main/app/view/RightMenu.js
index 182a489d41..538cb81a99 100644
--- a/apps/documenteditor/main/app/view/RightMenu.js
+++ b/apps/documenteditor/main/app/view/RightMenu.js
@@ -39,6 +39,7 @@
var SCALE_MIN = 40;
var MENU_SCALE_PART = 260;
var MENU_BASE_WIDTH = 220;
+// var MENU_BASE_WIDTH = 360;
define([
'text!documenteditor/main/app/template/RightMenu.template',
@@ -59,6 +60,8 @@ define([
'documenteditor/main/app/view/TextArtSettings',
'documenteditor/main/app/view/SignatureSettings',
'documenteditor/main/app/view/FormSettings',
+ 'documenteditor/main/app/view/FillingStatusSettings',
+ 'documenteditor/main/app/view/SendForSigningSettings',
'common/main/lib/component/Scroller',
'common/main/lib/component/ListView',
], function (menuTemplate, $, _, Backbone) {
@@ -253,6 +256,39 @@ define([
this.formSettings = new DE.Views.FormSettings();
}
+ if (false) {
+ this.btnFillingStatus = new Common.UI.Button({
+ hint: this.txtFormSettings,
+ asctype: Common.Utils.documentSettingsType.FillingStatus,
+ enableToggle: true,
+ disabled: true,
+ iconCls: 'btn-field',
+ toggleGroup: 'tabpanelbtnsGroup',
+ allowMouseEventsOnDisabled: true
+ });
+ this._settings[Common.Utils.documentSettingsType.FillingStatus] = {panel: "id-filling-status-settings", btn: this.btnFillingStatus};
+ this.btnFillingStatus.setElement($markup.findById('#id-right-menu-filling-status'), false);
+ this.btnFillingStatus.render().setVisible(true);
+ this.btnFillingStatus.on('click', this.onBtnMenuClick.bind(this));
+ this.fillingStatusSettings = new DE.Views.FillingStatusSettings();
+ }
+
+ if (!mode.canRequestStartFilling) {
+ this.btnSendForSigning = new Common.UI.Button({
+ hint: this.txtSendForSigning,
+ asctype: Common.Utils.documentSettingsType.SendForSigning,
+ enableToggle: true,
+ disabled: false,
+ iconCls: 'btn-field',
+ toggleGroup: 'tabpanelbtnsGroup',
+ allowMouseEventsOnDisabled: true
+ });
+ this._settings[Common.Utils.documentSettingsType.SendForSigning] = {panel: "id-send-for-signing-settings", btn: this.btnSendForSigning};
+ this.btnSendForSigning.setElement($markup.findById('#id-right-menu-send-for-signing'), false);
+ this.btnSendForSigning.render().setVisible(true);
+ this.btnSendForSigning.on('click', this.onBtnMenuClick.bind(this));
+ this.sendForSigningSettings = new DE.Views.SendForSigningSettings();
+ }
if (_.isUndefined(this.scroller)) {
this.scroller = new Common.UI.Scroller({
@@ -289,6 +325,8 @@ define([
if (this.mergeSettings) this.mergeSettings.setApi(api).on('editcomplete', _fire_editcomplete);
if (this.signatureSettings) this.signatureSettings.setApi(api).on('editcomplete', _fire_editcomplete);
if (this.formSettings) this.formSettings.setApi(api).on('editcomplete', _fire_editcomplete).on('updatescroller', _updateScroller);
+ if (this.fillingStatusSettings) this.fillingStatusSettings.setApi(api).on('editcomplete', _fire_editcomplete).on('updatescroller', _updateScroller);
+ if (this.sendForSigningSettings) this.sendForSigningSettings.setApi(api).on('editcomplete', _fire_editcomplete).on('updatescroller', _updateScroller);
},
setMode: function(mode) {
@@ -300,6 +338,8 @@ define([
this.chartSettings && this.chartSettings.setMode(mode);
// this.headerSettings && this.headerSettings.setMode(mode);
this.signatureSettings && this.signatureSettings.setMode(mode);
+ this.fillingStatusSettings && this.fillingStatusSettings.setMode(mode);
+ this.sendForSigningSettings && this.sendForSigningSettings.setMode(mode);
},
onBtnMenuClick: function(btn, e) {
@@ -402,7 +442,7 @@ define([
setButtons: function () {
var allButtons = [this.btnText, this.btnTable, this.btnImage, this.btnShape, this.btnChart, this.btnTextArt,
- this.btnMailMerge, this.btnSignature, this.btnForm];
+ this.btnMailMerge, this.btnSignature, this.btnForm, this.btnFillingStatus, this.btnSendForSigning];
Common.UI.SideMenu.prototype.setButtons.apply(this, [allButtons]);
},
@@ -434,6 +474,7 @@ define([
txtMailMergeSettings: 'Mail Merge Settings',
txtSignatureSettings: 'Signature Settings',
txtFormSettings: 'Form Settings',
+ txtSendForSigning: 'Send for signing',
ariaRightMenu: 'Right menu'
}, DE.Views.RightMenu || {}));
});
\ No newline at end of file
diff --git a/apps/documenteditor/main/app/view/SendForSigningSettings.js b/apps/documenteditor/main/app/view/SendForSigningSettings.js
new file mode 100644
index 0000000000..83509afbfd
--- /dev/null
+++ b/apps/documenteditor/main/app/view/SendForSigningSettings.js
@@ -0,0 +1,302 @@
+/*
+ * (c) Copyright Ascensio System SIA 2010-2024
+ *
+ * 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-6 Ernesta Birznieka-Upish
+ * 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
+ *
+ */
+/**
+ * SendForSigningSettings.js
+ *
+ * Created on 10.03.2026
+ *
+ */
+
+define([
+ 'text!documenteditor/main/app/template/SendForSigningSettings.template',
+ 'jquery',
+ 'underscore',
+ 'backbone',
+ 'common/main/lib/component/Button'
+], function (menuTemplate, $, _, Backbone) {
+ 'use strict';
+
+ DE.Views.SendForSigningSettings = Backbone.View.extend(_.extend({
+ el: '#id-send-for-signing-settings',
+
+ // Compile our stats template
+ template: _.template(menuTemplate),
+
+ // Delegated events for creating new items, and clearing completed ones.
+ events: {
+ },
+
+ options: {
+ alias: 'SendForSigningSettings'
+ },
+
+ initialize: function (options) {
+ this._initSettings = true;
+ this._state = {
+ isUsersListLoading: false
+ };
+ this._locked = false;
+
+ this.users = [];
+ this.render();
+
+
+ // TODO: if (config.canRequestUsers)???
+ this._state.isUsersListLoading = true;
+ Common.UI.ExternalUsers.get('filler');
+ Common.NotificationCenter.on('mentions:setusers', _.bind(this.onUsersListLoad, this));
+ },
+
+ render: function () {
+ const el = this.$el || $(this.el);
+ el.html(this.template({
+ scope: this
+ }));
+ },
+
+ createDelayedElements: function() {
+ this._initSettings = false;
+ const me = this;
+ const $markup = this.$el || $(this.el);
+
+ this._updateRolesListHeight();
+ this.scrollerOptions = {
+ el: $markup.find('#id-send-for-signing-settings-roles-list'),
+ wheelSpeed: 8,
+ alwaysVisibleY: true
+ };
+ this.scroller = new Common.UI.Scroller(this.scrollerOptions);
+
+ this.sendBtn = new Common.UI.Button({
+ el: $markup.find('#id-send-for-signing-settings-send-btn'),
+ disabled: true
+ });
+ this.sendBtn.on('click', _.bind(this.onSend, this));
+
+ this.cancelBtn = $markup.find('#id-send-for-signing-settings-cancel-btn');
+ this.cancelBtn.on('click', _.bind(this.onCancel, this));
+
+ const oForm = this.api.asc_GetOForm();
+ this.rolesCollection = new Backbone.Collection();
+ this.rolesCollection.on('reset', function(newCollection, details) {
+ me._renderRolesList();
+ }, this);
+ this.setRoles(oForm ? oForm.asc_getAllRoles() : []);
+
+ $(window).on('resize', _.bind(this.onWindowResize, this));
+ },
+
+ setApi: function(api) {
+ this.api = api;
+ if (this.api) {
+ this.api.asc_registerCallback('asc_onUpdateOFormRoles', _.bind(this.onRefreshRolesList, this));
+ }
+ return this;
+ },
+
+ ChangeSettings: function(props) {
+ if (this._initSettings) {
+ this.createDelayedElements();
+ }
+ },
+
+ setLocked: function (locked) {
+ this._locked = locked;
+ },
+
+ setMode: function(mode) {
+ this.mode = mode;
+ },
+
+ disableControls: function(disable) {
+
+ },
+
+ updateDisableSendButton: function() {
+ const hasEmptyUser = this.rolesCollection.some(function(role) {
+ return !role.get('user');
+ });
+ this.sendBtn.setDisabled(hasEmptyUser);
+ },
+
+ setRoles: function(roles) {
+ const oldArray = this.rolesCollection.toJSON();
+ const oldMap = {};
+ const newArray = (roles).map(function(role) {
+ role = role.asc_getSettings();
+ let color = role.asc_getColor();
+ color && (color = Common.Utils.ThemeColor.getHexColor(color.get_r(), color.get_g(), color.get_b()));
+ return {
+ name: role.asc_getName(),
+ color: color,
+ user: null
+ }
+ });
+
+ oldArray.forEach(function(item) {
+ oldMap[item.name] = item;
+ });
+
+ // Arrays are merged by 'name', only the `user` field is carried over from the old array
+ const resultArray = newArray.map(function(item) {
+ if (oldMap.hasOwnProperty(item.name)) {
+ item.user = oldMap[item.name].user;
+ }
+ return item;
+ });
+
+ this.rolesCollection.reset(resultArray);
+ },
+
+ onUsersListLoad: function(type, users, isPaginated) {
+ if (this._state.isUsersListLoading && type!=='filler') return;
+
+ this._state.isUsersListLoading = false;
+ this.users = (users || []).map(function(user) {
+ return {
+ id: user.id,
+ name: user.name,
+ email: user.email,
+ image: user.image,
+ initials: Common.Utils.getUserInitials(user.name)
+ }
+ });
+ },
+
+ onSend: function() {
+ const roles = this.rolesCollection.map(function(role) {
+ return {
+ name: role.get('name'),
+ color: role.get('color'),
+ user: role.get('user')
+ }
+ });
+ DE.getController('Main').onStartFilling(true, roles);
+ },
+
+ onCancel: function() {
+ // TODO: Move this out of the component by emitting an event
+ const rightmenuController = DE.getController('RightMenu');
+ rightmenuController.closeSendForSigning();
+ },
+
+ onRefreshRolesList: function(roles) {
+ if (this._initSettings) return;
+ this.setRoles(roles);
+ },
+
+ onWindowResize: function() {
+ this._updateRolesListHeight();
+ this.scroller.update(this.scrollerOptions);
+ },
+
+ _renderRolesList: function() {
+ const me = this;
+ const userCmbOptions = this.users.map(function(user) {
+ return Object.assign({value: user.id, displayValue: user.name || user.email}, user);
+ });
+
+ this.$el.find('#id-send-for-signing-settings-roles-list').empty();
+ this.rolesCollection.each(function(role, index) {
+ const $item = $(
+ '