Вопрос

Коллеги, добрый день!

Реализовал кастомную кнопку закрытия обращения с выпадающим меню. Но никак не могу найти, как установить цвет выпадающих кнопок. Мне необходимо все 5-кнопок сделать разными цветами. 

. 

 

А так же интересует каким образом можно добавить для выпадающей кнопки Значок, по аналогии с кнопкой "Экспорт в Excel" в меню "Действия"?

Спасибо!

У меня такой же вопрос

3 комментария

Добрый день

Чтобы реализовать раскраску цветами, то:

1. Каждое меню должно быть уникальное

2. Добавить css стиль

К примеру, у меня есть 2 пункта меню. Чтобы я мог реализовать корректный selector, то мне нужно их как-то назвать. Поэтому, в методе, где формируется menuItem я явно буду указывать Id этого меню. После чего можно будет писать что-то типа:

#myMenuItem {
    background-color: green;
}

 

Теперь по значкам.

Как вы сами заметили, что хотите добавить значок по аналогии, то вам и нужно сделать по аналогии :). Вот как это сделано в BaseSection

Артем Гура,

Спасибо, но не совсем понято как указать id каждого из меню в методе.

Вот мой метод:

getCustomCloseActions: function() {
 
	self = this;
	var actionMenuItems = Ext.create("Terrasoft.BaseViewModelCollection");
		actionMenuItems.addItem(this.getButtonMenuItem({
			"Tag": "5",
			"Caption": "Закрыть с оценкой 5",
			"Click": {bindTo: "OnCustomClosedButtonMenuClick"}
		}));
		actionMenuItems.addItem(this.getButtonMenuItem({
			"Tag": "4",
			"Caption": "Закрыть с оценкой 4",
			"Click": {bindTo: "OnCustomClosedButtonMenuClick"}
		}));
		actionMenuItems.addItem(this.getButtonMenuItem({
			"Tag": "3",
			"Caption": "Закрыть с оценкой 3",
			"Click": {bindTo: "OnCustomClosedButtonMenuClick"}
		}));
		actionMenuItems.addItem(this.getButtonMenuItem({
			"Tag": "2",
			"Caption": "Закрыть с оценкой 2",
			"Click": {bindTo: "OnCustomClosedButtonMenuClick"}
		}));
		actionMenuItems.addItem(this.getButtonMenuItem({
			"Tag": "1",
			"Caption": "Закрыть с оценкой 1",
			"Click": {bindTo: "OnCustomClosedButtonMenuClick"}
		}));
	self.set("CloseButtonMenuItems", actionMenuItems);
 
},

 

Обратите внимание на метод getButtonMenuItem: как он работает по умолчанию, и как он работает, например в BaseSection.

Особенно то, как формируется значок Excel и как генерируется Id.

А дальше сделать всё по аналогии.

Войдите или зарегистрируйтесь, чтобы комментировать
Идея

На данный момент при просмотре  практически любого списка элементов, с ним можно взаимодействовать посредством стандартных кнопок:

 

Однако при взаимодействии с деталями приходится пользоваться сложной системой — выделить строчку с элементом, нажать на троеточие над деталью и только потом выбрать интересующий элемент:

Нельзя ли в будущих версиях «прикрутить» к элементам детали такие же кнопки/подобные элементы взаимодействия?

Одобрена
3 комментария

Здравствуйте, Денис!

Передали данное пожелание команде разработки для анализа возможности внедрения функционала в будущих версиях продукта.

Здравствуйте, Денис, Владимир. Данная функция запланирована на ближайшие релизы. Планируем улучшить UX работы с данными в деталях.

Войдите или зарегистрируйтесь, чтобы комментировать
Вопрос

Сделал редактируемый реест с позицией.
Добавил кнопки вверх и вниз

init: function() {
                                this.callParent(arguments);
                        },
...

onActiveRowAction: function(buttonTag) {
                                var activeRow = this.getActiveRow();
                                var position;
                                switch (buttonTag) {
                                        case "Up":
                                                position = activeRow.get("Position");
                                                if (position > 0) {
                                                        position--;
                                                        this.setPosition(activeRow.get("Id"), position, this.reloadGridData, this);
                                                }
                                                break;
                                        case "Down":
                                                position = activeRow.get("Position");
                                                position++;
                                                this.setPosition(activeRow.get("Id"), position, this.reloadGridData, this);
                                                break;
                                        default:
                                                break;
                                }
                        },

соответственно кнопки удаления теперь не работают.
Как мне сделать чтобы работали?

У меня такой же вопрос

10 комментариев

в методе onActiveRowAction скорее всего забыли:

this.callParent(arguments);

т.е. Ваша логика затерла "родительскую", а подразумевалось ее дополнение.

Игорь то что у меня вначале стоит.

init: function() {
				this.callParent(arguments);
			},

не работает?

это для метода init
я же вам говорю про метод onActiveRowAction
у каждого метода своя само собой цепочка.

вставьте

this.callParent(arguments);

в начале или в конце вашего описания метода onActiveRowAction

Может я не правильно описал сами кнопки

diff: /**SCHEMA_DIFF*/[
			{
				"operation": "merge",
				"name": "DataGrid",
				"values": {
					"className": "Terrasoft.ConfigurationGrid",
					"generator": "ConfigurationGridGenerator.generatePartial",
					"generateControlsConfig": {"bindTo": "generatActiveRowControlsConfig"},
					"changeRow": {"bindTo": "changeRow"},
					"unSelectRow": {"bindTo": "unSelectRow"},
					"onGridClick": {"bindTo": "onGridClick"},
					"activeRowActions": [
						{
							"className": "Terrasoft.Button",
							"style": this.Terrasoft.controls.ButtonEnums.style.TRANSPARENT,
							"tag": "save",
							"markerValue": "save",
							"imageConfig": {"bindTo": "Resources.Images.SaveIcon"}
						},
						{
							"className": "Terrasoft.Button",
							"style": this.Terrasoft.controls.ButtonEnums.style.TRANSPARENT,
							"tag": "cancel",
							"markerValue": "cancel",
							"imageConfig": {"bindTo": "Resources.Images.CancelIcon"}
						},
						{
							"className": "Terrasoft.Button",
							"style": this.Terrasoft.controls.ButtonEnums.style.TRANSPARENT,
							"tag": "remove",
							"markerValue": "remove",
							"imageConfig": {"bindTo": "Resources.Images.RemoveIcon"}
						}
					],
					"initActiveRowKeyMap": {"bindTo": "initActiveRowKeyMap"},
					"activeRowAction": {"bindTo": "onActiveRowAction"},
					"multiSelect": false
				}
			},
			{
				"operation": "insert",
				"name": "DataGridActiveRowUpButton",
				"parentName": "DataGrid",
				"propertyName": "activeRowActions",
				"values": {
					"className": "Terrasoft.Button",
					"style": Terrasoft.controls.ButtonEnums.style.TRANSPARENT,
					"imageConfig": LocalizableHelper.localizableImages.Up,
					"tag": "Up"
				}
			},
			{
				"operation": "insert",
				"name": "DataGridActiveRowDownButton",
				"parentName": "DataGrid",
				"propertyName": "activeRowActions",
				"values": {
					"className": "Terrasoft.Button",
					"style": Terrasoft.controls.ButtonEnums.style.TRANSPARENT,
					"imageConfig": LocalizableHelper.localizableImages.Down,
					"tag": "Down"
				}
			}
		]/**SCHEMA_DIFF*/,
	methods: {
			init: function() {
				this.callParent(arguments);
			},
onActiveRowAction: function(buttonTag) {
				var activeRow = this.getActiveRow();
				var position;
				//this.callParent(arguments);
				switch (buttonTag) {
					case "Up":
						position = activeRow.get("Position");
						if (position > 0) {
							position--;
							this.setPosition(activeRow.get("Id"), position, this.reloadGridData, this);
						}
						break;
					case "Down":
						position = activeRow.get("Position");
						position++;
						this.setPosition(activeRow.get("Id"), position, this.reloadGridData, this);
						break;
					default:
						break;
				}
			},

а зачем закомментировали

//this.callParent(arguments);

не помогло ?

Не помогло.
Вообще все кнопки перестали работать.
Делаю так.
Из базового BaseSectionV2 из метода onActiveRowAction
Копирую и вставляю код

case "delete":
this.deleteRecords();
break;

Только пока не нашел где для cancel и save

в вашем switch case поместите

this.callParent(arguments)

в условие default:

Увы не помогло.

Но ведь метод onActiveRowAction в детали с ред. реестром вызывается из схемы ConfigurationGridUtyilities. Вам не нужно вызывать радителя. Достаточно скопировать весь код замещаемого метода и добавить свою логику в switch.

"Мотков Илья" написал:с ред. реестром вызывается из схемы ConfigurationGridUtyilities.

мне кажется правильнее будет её (ConfigurationGridUtyilities) и замещать. Предусмотрев логику, таким образом, чтобы отличать свой кейс использования от прочих вызовов этого метода в системе.

Войдите или зарегистрируйтесь, чтобы комментировать
Вопрос

У детали есть кнопки Вверх, Вниз, которые управляют позицией детали.
За это отвечает вот этот кусок кода.

setPosition: function(recordId, position, callback, scope) {
                                var data = {
                                        tableName: UsrWorkDR",
                                        primaryColumnValue: recordId,
                                        position: position,
                                        grouppingColumnNames: "
UsrWorkDId"
                                };
                                ServiceHelper.callService("
RightsService", "SetCustomRecordPosition", callback, data, scope);

использую его на своей страничке у детали.
Но выходит сообщение

em>message: Uncaught TypeError: ServiceHelper.callService is not a function em>

Что не так?

У меня такой же вопрос

2 комментария

Конкретно эта ошибка говорит о том что вы скорее всего не добавили переменную ServiceHelper или добавили её в неправильной последовательности в схеме:

Смешно...но ServiceHelper был последним, сделал первым и заработало...подсказку тут нашел тут

Максим спасибо.

Войдите или зарегистрируйтесь, чтобы комментировать
Добрый день!Предлагаю подумать в возвращении кнопок "Да" и "Нет" в диалоге подтверждения на свои места. Интуитивно кнопка "Да" ищется всегда слева. Если это сделано для того, чтобы пользователь сознательно удалял запись, то, на мой взгляд, это не лучшее решение. Пользователь рано или поздно привыкнет к порядку кнопок в BPM и будет очень обидно, когда, например. в MS Word пользователь не сохранит свой документ, т.к. там кнопки расположены в привычном для всех порядке.
Обсуждение
15 комментариев

Добрый день Александр!!!

я считаю, что предложенный вариант компанией Террасофт правильный, так как пользователь как раз интуитивно всегда нажимает на Левую первую кнопку и даже не задумывается, а требуется ему выполнить данное действие или нет. По вопросу сохранения документа Word и всех документов MSOffice то здесь существует автосохранение и в темповой директории всегда можно найти автосохраненную версию документа.

Сохранение присутствует не только в MS Office. Word были приведен как пример, который будет всем понятен. Обычный пользователь не будет искать свой документ в темповых файлах.
Для того и создал тему в идеях, чтобы узнать мнение общественности.

Точку зрения напишу - осуждаю :)
Не умеющих думать и действующих не глядя надо лишать права удалять записи - это вообще приоритет администратора.
А диалог единый для всей системы должен быть. Чтобы подчеркнуть важность кнопки Нет - подсветить ее, и сделать выбранной по умолчанию. Переставлять местами лишнее.

Коллеги, у нас UX тесты тоже показали спорные результаты. Пожалуйста, дайте больше фидбека. Если поддерживаете - голосуйте за идею. Если против - комментируйте. Изменение точечное, сможем внести даже в последние дни перед следующим релизом. Важно понимать, как будет удобно.

Я повторюсь еще раз, что я против данной идеи. Лучше чтобы осталось "Нет" - слева, "Да" - справо. Еще раз повторюсь так пользователь будет более сосредоточенно и осознанно подходить к любому всплывающему информационному сообщению и предупреждению, а не просто игнорировать. Плюс у нас так мозг устроен, что читаем мы текст с Лева на Право. И восприятие информации в наш мозг именно так и поступает. Вот мое мнение.

Я считаю, что за многие годы у людей уже выработалась очень сильная привычка в том, что если кнопок 2, то да слева,если 3 (да, нет, отмена) - то нет посредине. Я лично зашел первый раз в 7.8, точно хотел удалить запись, но с первых двух попыток запись осталась на своем месте(сила привычки), что вызвало некоторое недоумение.
Я не уверен, что не будет обратных ситуаций, в которых пользователь передумав нажмет в "Да", учитывая, что кнопка находится справа. Такого подвоха я просто не ожидал.
Соглашусь с Александром, что подсветки и выбора по-умолчанию более чем достаточно.
У пользователя есть время подумать, пока он ведет мышку к кнопкам.

"Власов Михаил Викторович" написал:так пользователь будет более сосредоточенно и осознанно подходить к любому всплывающему информационному сообщению и предупреждению, а не просто игнорировать.

Поддерживаю. Но считаю, что мнения разработчиков в этом вопросе не стоит ставить в приоритет. Ибо зачастую мышление в использовании продукта сильно разнится с мышлением пользователя.
Считаю, что правильнее было-бы доверять тестам. Возможно следует провести дополнительные тесты.

"Ляутин Вячеслав Андреевич" написал:Поддерживаю. Но считаю, что мнения разработчиков в этом вопросе не стоит ставить в приоритет. Ибо зачастую мышление в использовании продукта сильно разнится с мышлением пользователя.

Не соглашусь с вами Вячеслав. Так как правильный и хороший разработчик в первую Очередь перед разработкой и при разработки программного обеспечения, всегда должен ставить себя на место пользователя. И предугадывать все шаги пользователя еще как минимум на 100-200 шагов вперед. Меня мой преподаватель по программированию именно этому и учил. А я в программирование с 6 класса школы. Застали эволюцию разных программных систем, домашних и персональных компьютеров. Если бы к примеру мой кумир Стив Джобс не ставил бы себя на место пользователя, он бы не придумал такой гениальный продукт как Айфон, Айпад и так далее.

"Пащенко Александр Сергеевич" написал:Я считаю, что за многие годы у людей уже выработалась очень сильная привычка в том, что если кнопок 2, то да слева,если 3 (да, нет, отмена) - то нет посредине. Я лично зашел первый раз в 7.8, точно хотел удалить запись, но с первых двух попыток запись осталась на своем месте(сила привычки), что вызвало некоторое недоумение.

В жизни как и в программе не может быть "Да", "Нет", "Отмена". На любой вопрос поставленный пользователю или человеку, мы должны отвечать всегда утвердительно или "Да", или "Нет". В жизни не бывает 3-его выхода. У тех людей у которых появляется 3 выход, никогда не бывает четкого и поставленного мнения. Данный тип людей всегда сомневается.

Есть еще одно предложение особенно касаемо Удаления записей. Если есть мнение и тесты к примеру показывают, что люди больше нажимают "Да" - слева, "Нет" - справа. То именно для удаления поступить следующим образом. Первый вопрос об удаление задавать где "Да" - слева, "Нет" - справа. А вот уточняющий вопрос сделать так, что "Нет" - слева, "Да" - справа. И вот тогда я думаю мы будем точно уверенны, что пользователь уже подумав выполнит удаление записи.

где то даже данный подход я видел в жизни.

Начнем с того, что данное диалоговое окно пользователь увидит, если произведет определенную последовательность действий. Т.е. ему для начала необходимо выбрать запись (или несколько записей), нажать на кнопку "Действия", выбрать пункт "Удалить" и только потом он увидит данное диалоговое окно. А теперь вопрос: "Осознает ли пользователь, что он желает УДАЛИТЬ запись?".
Лично мне кажется, что да - осознает, поэтому замечание о том, что:

"Власов Михаил Викторович" написал:

пользователь как раз интуитивно всегда нажимает на Левую первую кнопку и даже не задумывается, а требуется ему выполнить данное действие или нет.

не уместно.

Что касается сомой идеи изменения расположения кнопок, то лично я подобного ни в одном популярном ПО не видел.

"Коваленко Владимир Юрьевич" написал:Начнем с того, что данное диалоговое окно пользователь увидит, если произведет определенную последовательность действий. Т.е. ему для начала необходимо выбрать запись (или несколько записей), нажать на кнопку "Действия", выбрать пункт "Удалить" и только потом он увидит данное диалоговое окно. А теперь вопрос: "Осознает ли пользователь, что он желает УДАЛИТЬ запись?".
Лично мне кажется, что да - осознает

Владимир сами задумайтесь сколько раз по ошибки вы удаляли неверные файлы. Я думаю, что это будет более чем 10 раз. Так как темп жизни достаточно велик, что в повседневной жизни, что и на работе. И когда пользователя просят сделать одно, потом подбегает 2-3 и просит сделать совершенно другое, а мозг и руки выполняют еще предыдущую команду по удалению. И есть вероятность, она всегда есть, что пользователь может и неосознанно удалить информацию.

Поэтому я продолжаю защищать предложенное командой Террасофт "Нет" - слева, "Да" - справа.

"Власов Михаил Викторович" написал:всегда должен ставить себя на место пользователя.

Ставить то должен но мозг технаря на мозг гуманитария не так просто подменить. А как показывает моя жизненная практика очень часто разница в мышлении колоссальная. Если бы было достаточно просто поставить себя на место пользователя, то я думаю не было бы технологий юзабилити тестирования, не было-бы целых отделов, у крупных производителей ПО, по тестированию юзабилити. Как по мне это целая наука, которой не было-бы если бы было достаточно предугадывать поведение пользователя на основе собственных довыдов.

Очень часто в подобных вопросах даже не разводят холивар а просто проводят качественное тестирование на целевой аудитории или различных фокус группах. И какими-бы неожиданными ни были результаты тестирования - их принимают за решение.

Конечно понять на сколько реже люди будут допускать ошибки при переносе кнопке довольно сложно, но я думаю что дискуссией в этом топике мы точно не решим этот вопрос :smile:

"Ляутин Вячеслав Андреевич" написал:Конечно понять на сколько реже люди будут допускать ошибки при переносе кнопке довольно сложно, но я думаю что дискуссией в этом топике мы точно не решим этот вопрос

Вопрос сейчас стоит не только о том сколько раз пользователь допустит ошибки но и о Юзабилити. Очень еще интересный пример Возьмем "Окно Microsoft" и "Окно Apple". Как у данных окон располагаются кнопки? у PC - "Свернуть окно", "Расширить окно", "Закрыть окно". у Mac-a "Закрыть окно", "Свернуль окно", "Расширить окно". Плюс у мака они еще и цветами разными выделены. И мне к примеру как пользователю удобно и 1 и во 2 случае работать с окнами. Но как критик предпочтение отдаю Юзабилити Макинтоша. Так же и здесь как бы мы сейчас не разместили клавиши слева на право или справо на лево, всегда рассудит данную ситуацию жизнь и конечный потребитель.

Но для универсальности я бы тогда ввел бы системную настройку Где "true" - означало бы расположение Слева на Право ("Да", "Нет"), и где "false" - расположение Справа на Лево ("Нет", "Да") и как уже пользователю удобно так он и настраивает под себя интерфейс. Вот еще одно из предложений.

Войдите или зарегистрируйтесь, чтобы комментировать
Вопрос

Коллеги, подскажите, как устранить проблему.
Есть 3 кнопки в AcccountSectionV2. Каждая из них вызывает свой бизнес-процесс, первым элементом в которых стоит открытие страницы редактирования (новой Активности, Счёта или Заказа соответственно). Проблема заключается в том, что после нажатия Отмена на странице редактирования (к примеру, страницы редактирования Счёта) все кнопки в карточке контрагента перестают реагировать на нажатия. По журналу бизнес-процессов видно, что привязанные к кнопкам бизнес-процессы не запускаются, т.е. не отрабатывается код кнопок. Он начинает работать, только если обновить страницу.
Часть кода, создающая кнопки:

{
                                "operation": "insert",
                                "parentName": "CombinedModeActionButtonsCardLeftContainer",
                                "propertyName": "items",
                                "name": "MakeInvoiceButton",
                                "values": {
                                        itemType: Terrasoft.ViewItemType.BUTTON,
                                        caption: "+ Счёт",
                                        style: Terrasoft.controls.ButtonEnums.style.BLUE,
                                        click: {bindTo: "onMakeInvoiceButtonClick"},
                                        "layout": {
                                                "column": 1,
                                                "row": 6,
                                                "colSpan": 1
                                        }
                                }
                        }

Часть кода - запуск привязанного бизнес-процесса:
onMakeInvoiceButtonClick: function() {
                                debugger;
                                var AccountId = this.get("ActiveRow");
                                var processArgs = {
                                        sysProcessName: "UsrOnMakeInvoiceButtonClick",
                                        parameters: {
                                                IncomingAccountId: AccountId
                                        }
                                };
                                ProcessModuleUtilities.executeProcess(processArgs);
                        }

Бизнес-процесс:
Схема

У меня такой же вопрос

15 комментариев

Антон,

что видно в консоли браузера в момент нажатия на эти кнопки?

P.S. Прикрепите, пожалуйста, скриншот процесса.

в момент вызова нового процесса в браузере видно следующее сообщение:

При выполнении запроса возникла ошибка
статус ответа: 400 (Bad Request)
url запроса: http://crm:82/0/ServiceModel/ProcessEngineService.svc/UsrOnMakeNeedCall…null
метод: POST
данные запроса: {}

Похоже, что после запуска предыдущего при повторном запуске система не передаёт ID Открытой карточки клиента в повторный процесс. Однако - в журнале процессов нет второго запуска процесса.

Добрый день Антон!!!

конечно Бизнес-процесс у вас маленький, но если честно цель данного бизнес-процесса непонятно. Что вы хотели данным процессом достичь? Проконтролировать заполнено ли определенное поле и если да, то открыть карточку редактирования счета? Или же вы хотели сначала проконтролировать наполняемость всех полей, и если определенные поля заполнены, открыть на редактирование карточку счета. Если так, то в процессе не хватает действий для проверки. Это первое, а второе когда вы Первый раз запустили процесс, то в Процесс (через входящие параметры) запоминает Id контрагента, и когда вы не заново, а продолжаете процесс, тогда система уже начинает с того места где остановилась и при этом помнит уже все входящие параметры.

Михаил, цель простая - открыть предзаполненную карточку счёта из карточки клиента. В начале процесса проверяю условия - указан ли ID контрагента, по которому нужно открыть счёт, а также чтобы тип этого контрагента был равен "Клиент". В иных случаях счёт нам не нужен.
По сути, это аналог кнопки "Добавить" в детали Счета в карточке контрагента.

Последний Ваш комментарий не понял - я отменил выполнение предыдущего процесса и запускаю новый из той же карточки. Вот новый у меня и не начинается из-за того, что система не передаёт второй раз ID контрагента, карточка которого открыта в настоящий момент

"Антон Кравченко" написал: Вот новый у меня и не начинается из-за того, что система не передаёт второй раз ID контрагента, карточка которого открыта в настоящий момент

Антон вопрос так откуда вы вызываете бизнес-процесс из Раздела или Открытой карточки редактирования. Так как обращение и получение Id контрагента будут разными. Если из раздела, то нужно еще проверить, а не включен ли режим "Выбора нескольких записей" и если да получить массив Id и передать в процесс, если это карточка редактирования то напрямую получить "this.get(this.entitySchema.primaryColumnName)" и все. И еще один совет если в Бизнес-процесс передаются Массив значений, Id и не только то обязательно, прежде чем вызвать процесс, вы добавьте условия проверки на "Существование" и "Заполненность" передаваемых значений а уже после запускайте процесс. И уже на экране у вас уже не будут появляться ошибки, а вы будите видеть, что процесс запустился или нет. И вот если уже не запустился это уже будет означать, что сработал ваш "IF". Я бы так сделал.

Михаил, хорошо, давайте проверим:
1. Код кнопки у меня расположен и в *Page и в *Section. Из Section в процесс передаётся this.get("ActiveRow"), из Page - this.get("ID")
2. Режим "Выбора нескольких записей не включен 100%
3. При проверке открыта карточка контрагента через Section (т.е. слева есть список других контрагентов, а ссылка в браузере выглядит как .../ ... Section ... / UsrAccountType1Page / edit / ID
4. Вы пишете про проверку на существование и заполненность. Чем Вам первое условие в моём процессе не нравится? в нём как раз и проверяю, что переданный ID != Guid.Empty

Я подозреваю, что после запуска процесса система как бы "выходит" из режима, когда выделена одна из записей реестра (т.е. this.get("ActiveRow") возвращает null), а после обновления страницы снова выделяет того контрагента, чья карточка на экране (т.е. this.get("ActiveRow") возвращает ID выделенной записи).
Как можно проверить данное предположение?

"Антон Кравченко" написал:в нём как раз и проверяю, что переданный ID != Guid.Empty

Антон во первых в процесс может, через входящий параметр, передаться значение ("", String.Empty, т.е пустое значение) или передаться значение "undefined". Можно конечно это все проверить на C# в бизнес-процессе, но зачем если это можно сделать на клиенте. На C# нужно будет не забывать про правила конвертации, чтобы синтаксис был правильный. На JavaScript это проще. Это всего лишь моя рекомендация.
Возвращаясь к вашему вопросу хочу сказать, что по умолчанию в конфигурациях BPMOnline есть маленький баг. Но он быстро правиться. Проверяется этот баг очень просто. Открываете карточку редактирования (к примеру Контрагента) из раздела. И на карточке в любом LookupEdit поле выполняете "Выбор из справочника" и при выборе к примеру редактируете выбираемую запись сохраняете и смотрите. Если слева, где список контрагентов, теряется фокус. То тогда да, ваше предположение может быть, что при подачи команды  this.get("ActiveRow") возвращается "null" или "неопределено", то тогда я вам подскажу где этот маленький баг исправить. Я его уже давно обнаружил, еще в 7.3. Проведите эксперимент если фокус потеряется, я вам подскажу как это поправить.

Михаил, фокус не теряется при Вашем способе с LookupEdit, однако в нашей ситуации с кнопками теряется - см. скриншоты

Добрый день Антон!!!

выполните замещение схемы GridUtilitiesV2, исправьте Функцию "ensureActiveRowVisible"
ниже приведен исправленный текст функции. Жирным выделена строка, что добавлена.

            /**
             * Прокручивает реестр, чтобы была видна активная строка.
             * @protected
             */
            ensureActiveRowVisible: function() {
                var grid = this.getCurrentGrid();
                var activeRow = this.get("ActiveRow");
                if (grid && activeRow) {
                    var activeRowDom = grid.getDomRow(activeRow);
                    if (activeRowDom && activeRowDom.dom) {
                        // TODO: Добавлена строка по фиксации активной записи реестра
                        grid.setActiveRow(activeRow);
                        var el = activeRowDom.dom;
                        if (el.scrollIntoViewIfNeeded) {
                            el.scrollIntoViewIfNeeded(false);
                        } else {
                            el.scrollIntoView(false);
                        }
                    }
                }
            },

Выполните пожалуйста замещение схемы и проверьте результат. У меня сейчас фокус никогда не теряется. При замещение схемы не забываем копировать не одну функцию а все. Иначе перестанет работать функционал.

Михаил, доброго утра!
Заместил GridUtilitiesV2, полностью скопировал код из замещаемой в замещающую страницу, исправил функцию ensureActiveRowVisible ... и ничего не изменилось - фокус по-прежнему теряется.
P.S. Вы пишете, что жирным выделена добавляемая в функцию ensureActiveRowVisible строка, но в Вашем коде не вижу строки с жирным шрифтом ..

Добрый день Антон!!!

воспроизвел вашу ситуацию на своей базе данных. Действительно Фокус теряется и информация о текущей записи теряется. Буду сегодня в отладчике искать, где происходит сбой. Как найду выход из данной ситуацию. Опубликую результат с ответом.

Антон самый быстрый способ который я нашел и советую вам его использовать. Это сохранение ID в профиль пользователя. Вот как я сделал и после отмены или закрытия карточки редактирования (вызванная из процесса) фокус сейчас у меня нормально возвращается. вот листинг. так же замещаем схему GridUtilitiesV2.

            /**
             * Восстановление выделенной записи в реестре.
             */
            onAfterReRender: function() {
                if (this.cachedActiveRow && !this.get("MultiSelect"))  {
                    var gridData = this.getGridData();
                    if (gridData && gridData.contains(this.cachedActiveRow)) {
                        this.set("ActiveRow", this.cachedActiveRow);
                    }
                } else if (!this.cachedActiveRow && !this.get("MultiSelect"))  {
                    var profile = this.getProfile();
                    var activeRow = !Ext.isEmpty(profile.ActiveRow) ? profile.ActiveRow : this.Terrasoft.GUID_EMPTY;
                    if (!Ext.isEmpty(activeRow)) {
                        this.set("ActiveRow", activeRow);
                    }
                }
            },
            /**
             * Событие на изменение значения ActiveRow.
             */
            onActiveRowChange: function() {
                this.cachedActiveRow = this.get("ActiveRow") || this.cachedActiveRow;
                if (!Ext.isEmpty(this.cachedActiveRow)) {
                    var profile = this.getProfile();
                    var key = this.getProfileKey();
                    if (profile && key) {
                        profile.ActiveRow = this.cachedActiveRow;
                        this.Terrasoft.utils.saveUserProfile(key, profile, false);
                    }
                }
            },

приведенные выше 2 функции замещаем. и пробуем исполнить с Нуля свой процесс отменить. Проверить, что вернулся фокус и продолжить с остановленного месте или заново начать как вам удобно.

Михаил, отлично! Ваше решение работает) Спасибо большое

Я рад Антон. Что вам помог. Вы первую мою доработку тоже к себе в код включите, полезна будет. А так я рад. Будут еще вопросы, проблемы пишите, буду рад вам помочь.

а я её (первую доработку) там и оставил )

Войдите или зарегистрируйтесь, чтобы комментировать

Добрый день. Возникла необходимость в bpmonline 7.5, в контактах, на детали "средства связи", динамически менять список социальных сетей, в зависимости от типа контакта. А также менять тип кнопки добавить (точнее убирать типы адресов и оставлять только кнопку добавить без выпадающего списка), детали "Адрес", тоже в зависимости от типа контакта. Проблема в том что скрипты выполняются только при инициализации страницы, т.е. они работают только если полностью перезагрузить страницу. Пробовал методы updateDetail, reloadDetail. Не работает, хотя reloadDetail, не отработал, вызывал так this.reloadDetail('ContactAddress'). Подскажите пожалуйста, как можно решить эту проблему.

У меня такой же вопрос

11 комментариев

Здравствуйте, Владислав!
Не проще ли вместо перезагрузки детали просто вызывать методы, которые выполняются при инциализщации и устанавливают необходимые параметры?
Вы же используете привязку (bindTo) свойств для управления видимостью и наполнением?

Пробовал, вызывать метод, но не получается. Вот например код для детали средства связи.

define("ContactCommunicationDetail", ["ContactCommunicationDetailResources", "terrasoft", "ViewUtilities", "Contact", "ConfigurationEnums", "ConfigurationConstants","MultiMaskEdit"],
    function(resources, Terrasoft, ViewUtilities, Contact, ConfigurationEnums, ConfigurationConstants,MultiMaskEdit) {
        return {
            entitySchemaName: "ContactCommunication",
 
            attributes: {
                "CommunicationTypes" : {
                    type: Terrasoft.ViewModelColumnType.VIRTUAL_COLUMN,
                    dataValueType: Terrasoft.DataValueType.COLLECTION
                }
            },
            methods: {
                initCommunicationTypesFilters: function(esq) {
                    this.callParent(arguments);
                    var columns = Contact.columns;
                    if (columns !== null) {
                   //     debugger;
                        if(TypeStatus!='60733efc-f36b-1410-a883-16d83cab0980') {
                            if (columns.LinkedIn.usageType === ConfigurationEnums.EntitySchemaColumnUsageType.None) {
                                var InstagtramFilter = Terrasoft.createColumnFilterWithParameter(
                                    Terrasoft.ComparisonType.NOT_EQUAL, "Id", ConfigurationConstants.CommunicationTypes.Instagtram);
                                esq.filters.addItem(InstagtramFilter);
                                var OdnoklasnikiFilter = Terrasoft.createColumnFilterWithParameter(
                                    Terrasoft.ComparisonType.NOT_EQUAL, "Id", ConfigurationConstants.CommunicationTypes.Odnoklasniki);
                                esq.filters.addItem(OdnoklasnikiFilter);
                                var VkontakteFilter = Terrasoft.createColumnFilterWithParameter(
                                    Terrasoft.ComparisonType.NOT_EQUAL, "Id", ConfigurationConstants.CommunicationTypes.Vkontakte);
                                esq.filters.addItem(VkontakteFilter);
                            }
                        }
                    }
                }
            },
 
            diff: /**SCHEMA_DIFF*/[
 
 
            ]/**SCHEMA_DIFF*/
        };
    });

А что вам мешает использовать метод init()?

Владимир, а как вы предлагаете использовать init()?
Я пробовал в детали сделать так

  init:function(){
                    this.callParent(arguments);
                    this.initCommunicationTypesFilters();
                },
                updateDetail: function(config) {
                   this.callParent(arguments);
                   this.init();
 
                },

Но ничего путного не вышло.

Здравствуйте, Владислав!
Я, честно говоря, не совсем понял, как Ваш код должен работать. Возможно Вы не полностью предоставили фрагмент кода, но в условии происходит сравнение:

if(TypeStatus!='60733efc-f36b-1410-a883-16d83cab0980')
...

При этом я не вижу определения переменной TypeStatus. Рекомендую поставить там точку останова и посмотреть, какие условия выполняются.

Андрей, TypeStatus это переменная, которая присваивается в модуле ContactPageV2. При изменении статуса вызывается метод, где присваивается текущее значение статуса и вызывается метод updateDetails.После чего в модуле детали ContactCommunicationDetail и происходит проверка. Если условие выполняется добавляются фильтры, иначе они не добавляются.

attributes: {
            "Type": {
                dependencies: [
                    {
                        columns: ["Type"],
                        methodName: "typeChanged"
                    }
                ]
            }
        },
methods: {
  onEntityInitialized: function() {
                this.callParent(arguments);
                this.typeChanged();
            },
   typeChanged: function() {
       TypeStatus=this.get('Type').value;
         this.updateDetails();}

Сам метод отрабатывает верно, проверял в отладчике, все фильтры добавляются и удаляются, исходя из коллекции фильтров entitySchemaName. Но проблема не в этом, а в том что он работает, только при полной перезагрузке, а значит необходим какой-нибудь метод для обновления детали.

В какой момент Вы хотите обновлять деталь?

Владимир, после изменения поля типа контакта.

Попробуйте вместо this.updateDetail() вызвать this.updateDetail({reloadAll: true});

Иван, пробовал, но не работает. В итоге получилось сделать, но иначе. Воспользовался методом loadDetail в модуле NUI.BasePageV2.js. В карточке при изменении поля, взял часть этого метода и вызывал т.о.

this.sandbox.loadModule("DetailModuleV2", {
                            renderTo: "ContactPageV2ContactAddressContainer",
                            id: "SectionModuleV2_ContactSectionV2_CardModuleV2_detail_ContactAddress"
                        });

Ломухин Владислав Вячеславович,

я попробовал тоже самое, у меня пишет ошибку. но нужно тоже самое. подскажете как это сделать, может быть полный пример кода? спасибо

Войдите или зарегистрируйтесь, чтобы комментировать
Вопрос

Объясняю суть проблемы:
Если пройдем по пути Раздел Счета -> Деталь Задачи (создадим новую, или изменим) -> в карточке задачи щелкаем чтобы выбрать контрагента (контакта и т.д.), появляется список (в нем кнопки Добавить, Изменить, Удалить активны)

В своем созданном разделе, детали, если пройти по такому же пути, раздел - деталь - выбор, то на гриде кнопки не активны.

Может кто сталкивался с такой проблемой, как активировать?

У меня такой же вопрос

1 комментарий

Все разобрался, решение тут

Войдите или зарегистрируйтесь, чтобы комментировать
Вопрос

Добрый день.

Создал реестр. Кнопка ДОБАВИТЬ неактивна.
Соответственно, невозможно создать новую запись.
Подскажите, пожалуйста, как сделать кнопку активной.

Продукт Terrasoft 3.4.1

У меня такой же вопрос

9 комментариев

Права на добавление в "Права доступа к группам таблиц"

Дмитрий, спасибо за ответ. В правах доступа установлены максимальные права на требуемый реестр (см. файл).
Не работает.

а другие кнопки?

Другие кнопки тоже не активны. Но это ни о чем не говорит, так как невозможно проверить, будут ли эти кнопки активны при выборе записи. Так как в реестре нет ни одной записи, то это невозможно проверить.

Ну то что нет возможности проверить - это вы махнули. Можно добавить запись в SQL напрямую, а посмотреть в Террасофте.
У меня несколько идей почему это может быть (если ни одна не поможет, то пересоздайте реестр (лучше полностью, прям с таблицы) или в тех.поддержку):
1) Проверьте принадлежит ли пользователь группе, которой вы дали права.
2) И еще может быть, что вы не дали свойства на добавление датасету. Проверьте в администраторе стоят ли у датасета свойства "Добавление" и "Генерировать запрос на вставку".
3) В каком положении IsEnabled кнопки в гриде в администраторе или где-то в скрипте не завалялась строчка?

btnAdd.IsEnabled = false;

или

frmButtons.IsEnabled = false;

Александр, спасибо.
Проверил все 3 пункта. Все нормально.
Написал в техподдержку.

как вариант еще: не назначен датасет для dlData в сервисе грида

С датасетом тоже все нормально.
Буду пересоздавать раздел.

Ответ из службы поддержки:

В скриптах реестра, в методе инициализации, реестрам задавался атрибут ParentItemFieldName вручную, чего делать не следует, так как если экземпляр реестра размещается на детали, атрибут задастся автоматически. Поэтому, Вы можете закомментить строки в скриптах wnd_OfferingsGridAreaScript и scr_PriceListsGridArea:

// SetAttribute(Window, 'ParentItemFieldName', 'EditionID');

Все заработало. Спасибо

Войдите или зарегистрируйтесь, чтобы комментировать
Вопрос

Какой функцией (скриптом) воспользоваться, чтобы в окне детали установить доступность кнопок "Добавить", "Удалить" и т.п. в зависимости от прав на запись в базовом реестре?

У меня такой же вопрос

1 комментарий

Добрый день, Станислав!

В окнах всех реестров, унаследованных от wnd_BaseGridArea, реализовано такое поведение кнопок, при котором доступ зависит от прав пользователя на собственно таблицу, из которой считываются данные в реестр (а не таблицу родительского раздела, в котором размещена деталь).
Если же нужно реализовать такую модель, чтобы детали раздела были доступны на редактирование в зависимости от доступа пользователя на запись в реестре раздела, придется написать соответствующие функции в скрипте окна реестра детали, которые будут выполнять анализ прав и устанавливать доступность кнопок. Примеры для анализа доступа по группам таблиц см. в скрипте scr_Access, названия функций:

GetCanReadData(TableUSI)
GetCanInsertData(TableUSI)
GetCanCopyData(Dataset)
GetCanDeleteData(Dataset)
GetCanEditData(Dataset)

Для анализа уровня доступа по записям можно воспользоваться функцией (в том же скрипте):
GetIsRecordIDAccessAllowedByTable(Table, RecordID, AccessLevelFieldName)

Желаю успехов!

Войдите или зарегистрируйтесь, чтобы комментировать