Добрый день. Появилась задача добавить кнопку, аналогичную кнопке "Обработать" в почте.
Но просто так добавить кнопку не получилось. Кажется обработчик на кнопку вешается не простым bindTo, как мне казалось в начале.
Пример кода, который получился:
generateEmailButtonsContainerConfig: function() { var buttonItems = []; var processEmailButtonConfig = this.generateEmailProcessedButtonConfig(); buttonItems.push(processEmailButtonConfig); /** Добавляем новую кнопку */ var skipEmailButtonConfig = this.generateSkipEmailButtonConfig(); buttonItems.push(skipEmailButtonConfig); var deleteEmailButtonConfig = this.generateDeleteEmailButtonConfig(); buttonItems.push(deleteEmailButtonConfig); var emailButtonContainerConfig = { "className": "Terrasoft.Container", "classes": {"wrapClassName": ["entity-item-relation-container"]}, "items": buttonItems }; return emailButtonContainerConfig; }, /** НОВАЯ КНОПКА */ generateSkipEmailButtonConfig: function() { return { "className": "Terrasoft.Button", "style": Terrasoft.controls.ButtonEnums.style.RED, "caption": "SKIP", "click": {bindTo: "onSkipEmail"}, "markerValue": "skipingEmail" }; }, /** Метод обработчик кнопки*/ onSkipEmail: function (model) { window.console.log("It's working"); }
Но при нажатии на кнопку - появляется ошибка:
Возможно надо использоваться что-то похожее на fireEvent, но за все время не было необходимости в подобном функционале - поэтому плохо понимаю как и что делать. Вроде в этой статье https://community.terrasoft.ru/articles/kak-sozdat-polzovatelskii-eleme… о чем-то, что мне поможет, говорится. Но без понимая как это все устроено - это какое-то гадание на кофейной гуще.
Конечно, для решения моей задачи есть варианты и попроще, но менее изящные. Просто очень хочется разобраться и сделать именно первоначальную задумку:
Может кто-то реализовывал мой кейс или нечто подобное и сможет поделиться советом?
Нравится
Сергей, насколько понимаю, Вы пытаетесь сделать как для зелёной кнопки EmailProcessedButton, которая описана в CommunicationPanelEmailSchema:
/** * Creates email message action buttons container config. * @protected * @return {Object} Email message action buttons container config. */ generateEmailButtonsContainerConfig: function() { var buttonItems = []; var processEmailButtonConfig = this.generateEmailProcessedButtonConfig(); buttonItems.push(processEmailButtonConfig); var deleteEmailButtonConfig = this.generateDeleteEmailButtonConfig(); buttonItems.push(deleteEmailButtonConfig); var emailButtonContainerConfig = { "className": "Terrasoft.Container", "classes": {"wrapClassName": ["entity-item-relation-container"]}, "items": buttonItems }; return emailButtonContainerConfig; }, /** * Creates "process message" button config. * @protected * @return {Object} "Process message" button config. */ generateEmailProcessedButtonConfig: function() { return { "className": "Terrasoft.Button", "caption": {"bindTo": "Resources.Strings.MarkAsProcessed"}, "style": Terrasoft.controls.ButtonEnums.style.GREEN, "imageConfig": {"bindTo": "Resources.Images.ApplyButtonImage"}, "enabled": {"bindTo": "IsProcessingButtonEnabled"}, "visible": { "bindTo": "IsNeedProcess", "bindConfig": { "converter": "getProcessButtonVisible" } }, "click": {bindTo: "setIsNeedProcessFalse"}, "markerValue": "setNeedProcessFalse" }; },
Но там обработчик setIsNeedProcessFalse в EmailItemSchema не просто одна функция, а несколько в цепочке, одна вызывает другие:
/** * Sets and saves IsNeedProcess value for message. * @param {Function} [callback] Callback function. * @param {Object} [scope] Callback function scope. */ setIsNeedProcessFalse: function(callback, scope) { this.set("IsProcessingButtonEnabled", false); var chain = []; chain.push(this.updateIsNeedProcess); chain.push(this._onSetIsNeedProcessFalse, function() { this.Ext.callback(callback, scope); }); this.set("IsNeedProcess", false); this.Terrasoft.chain.apply(this, chain); }, ... /** * Updates IsNeedProcess value for current user EmailMessageData instances. * @param {Function} [callback] Callback function. * @param {Object} [scope] Callback function scope. */ updateIsNeedProcess: function(callback, scope) { var update = this.getIsNeedProcessUpdate(); if (this.Ext.isEmpty(update)) { this.Ext.callback(callback, scope); return; } update.execute(function() { this.Ext.callback(callback, scope); }, this); }, ... /** * Handle response of save entity request. * @private * @param {Object} [response] Response of save entity request. * @param {Function} [callback] Callback function. * @param {Object} [scope] Callback function scope. */ _handleSaveRequestResponse: function(response, callback, scope) { if (response && response.success) { this.fireEvent("entitySaved", this); this.set("CurrentColumnValue", null); } this.Ext.callback(callback, scope); }, /** * Set IsNeedProcess to false. * @private * @param {Function} [callback] Callback function. * @param {Object} [scope] Callback function scope. */ _onSetIsNeedProcessFalse: function(callback, scope) { this.saveEntity(function(response) { this._handleSaveRequestResponse(response, callback, scope); }, this); },
Если ругается на .apply, видимо, ожидает для Вашей кнопки аналогичной логики. Хотя, там же рядом справа DeleteEmailButton, там без этого всего:
/** * Creates "delete" button config. * @protected * @return {Object} "Delete" button config. */ generateDeleteEmailButtonConfig: function() { return { "className": "Terrasoft.Button", "style": Terrasoft.controls.ButtonEnums.style.TRANSPARENT, "imageConfig": {"bindTo": "Resources.Images.DeleteEmailButtonImage"}, "click": {bindTo: "onDeleteEmail"}, "markerValue": "deleteEmail" }; }, ... /** * Removes email message from emails collection. * @param {Terrasoft.BaseViewModel} model Email message model instance. */ onDeleteEmail: function(model) { this.unsubscribeModelEvents(model); var collection = this.get("EmailCollection"); collection.remove(model); },
Не сравнивали в отладке Вашу кнопку с кнопкой удаления?
Зверев Александр,
Сегодня заметил, что вся логика на самом деле в другой схеме - попробую туда вписать мой метод-обработчик. Может кнопка просто не может найти нужный метод и валится в ошибку. Пока я понял что работает так - EmailItemSchema "втягивает" в себя кнопки и обрабатывает методы у себя и после уже дополняет методами из
CommunicationPanelEmailSchema. Проверю свою догадку и отпишусь о происходящем. Просто изначально не заметил эту привязку. Даже не осознал до конца как я натолкнулся на нее. Но теперь уже немного понятно куда идти
Сергей, попробовал у себя Ваш и стандартный код, кнопка удаления работает, поскольку функция вызывается не напрямую оттуда, а после окошка с подтверждением желания.
Если просто Вашу функцию onSkipEmail перенести в EmailItemSchema, то всё работает, пишет в консоли «It's working».
Зверев Александр,
Все так. Но пришлось еще докрутить логику. Например, включил передачу сообщения и основную логику все равно запускал в
CommunicationPanelEmailSchema (потому что надо было работать с коллекцией писем, не был уверен что смогу это провернуть в EmailItemSchema)
Если кому-то поможет - полученный код ниже
EmailItemSchema:
messages: { "MessageSkipEmail": { mode: Terrasoft.MessageMode.BROADCAST, direction: Terrasoft.MessageDirectionType.BIDIRECTIONAL } }, methods: { /** * Initializes starter values. * @protected * @overridden */ init: function () { this.callParent(arguments); // Регистрация сообщения. this.sandbox.registerMessages(this.messages); }, onSkipEmail: function() { // Регистрация сообщения. var EmailId = this.get("Id"); this.sandbox.publish("MessageSkipEmail", {Id: EmailId}, ["EmailItemSchema"]); } },
CommunicationPanelEmailSchema
messages: { "MessageSkipEmail": { mode: Terrasoft.MessageMode.BROADCAST, direction: Terrasoft.MessageDirectionType.BIDIRECTIONAL } }, methods: { init: function () { this.callParent(arguments); // Регистрация сообщения. Terrasoft.ServerChannel.on(Terrasoft.EventName.ON_MESSAGE, this.onMyBpFinish, this); this.sandbox.subscribe("MessageSkipEmail", function(args) { this.skipingEmail(args.Id);}, this, ["EmailItemSchema"]); }, skipingEmail: function(EmailId) { var collection = this.get("EmailCollection"); var foundItem = collection.collection.items.find(item => item.id === EmailId); var args = { // Имя процесса, который необходимо запустить. sysProcessName: "UsrSkipEmail", // Объект со значением входящего параметра ContactParameter для процесса CustomProcess. parameters: { ID: EmailId } }; // Запуск пользовательского бизнес-процесса. ProcessModuleUtilities.executeProcess(args); collection.remove(foundItem); /** Выкидываем уже обработанное письмо из списка*/ }, generateEmailButtonsContainerConfig: function() { var buttonItems = []; var processEmailButtonConfig = this.generateEmailProcessedButtonConfig(); buttonItems.push(processEmailButtonConfig); /** Добавляем новую кнопку */ var skipEmailButtonConfig = this.generateSkipEmailButtonConfig(); buttonItems.push(skipEmailButtonConfig); var deleteEmailButtonConfig = this.generateDeleteEmailButtonConfig(); buttonItems.push(deleteEmailButtonConfig); var emailButtonContainerConfig = { "className": "Terrasoft.Container", "classes": {"wrapClassName": ["entity-item-relation-container"]}, "items": buttonItems }; return emailButtonContainerConfig; }, /** НОВАЯ КНОПКА */ generateSkipEmailButtonConfig: function() { return { "className": "Terrasoft.Button", //"style": "caption": "Игнорировать", "click": {bindTo: "onSkipEmail"}, "markerValue": "skipingEmail", "enabled": {"bindTo": "IsProcessingButtonEnabled"}, "visible": { "bindTo": "IsNeedProcess", "bindConfig": { "converter": "getProcessButtonVisible" } }, }; },
А в самом БП происходит магия изменения БД, чтобы не запустились скрытые процессы, привязанные к "IsNeedProcess" в EmailMessageData
Вроде теперь все работает как надо, но надо провести обильное тестирование на большом количестве писем. А то письма после обработки все равно привязывались к обращениям и переоткрывали их. Теперь такие письма можно пропускать.