Добрый день.
Стоит задача сделать аналог фиксированного фильтра "Ответственный" в р. Контрагенты.
Фильтрация происходит по детали "Сервисы контрагента".
Фильтр в AccountSectionV2:

 initFixedFiltersConfig: function() {
                    var fixedFilterConfig = {
                        entitySchema: this.entitySchema,
                                                        filters: [
                             {
                                                                        name: "AccountServiceItem",
                                                                        caption: resources.localizableStrings.AccountServiceItemFilterCaption, //"Cервисы контрагента"
                                                                        dataValueType: this.Terrasoft.DataValueType.LOOKUP,
                                    //filter: this.getAccountServiceFixedFilter,
                                                                        appendFilter: this.getAccountServiceFixedFilter,
                                                                        columnName:"UsrServiceItem",
                                    //defValue: null,
                                    referenceSchemaName:"UsrAccountServiceItem",
                                    markerValue: "AccountServiceItemFixedFilterBtn",
                                    buttonImageConfig: resources.localizableImages.AccountServiceItemFilterImage,//путь к картинке Сервисов
                                    hint: "",
                                                                    appendCurrentContactMenuItem : false,
                                    addNewFilterCaption : resources.localizableStrings.AccountServiceItemAddNewFilterCaption, //"Выбрать сервисы",
                                    isCustomFilter: true //нужен для запуска пользовательской логики построения фильтра
                                }
                            ]
                    };
                    this.set("FixedFilterConfig", fixedFilterConfig);
                },

                getAccountServiceFixedFilter: function(filterInfo){
                    //Фильтр по детали AccountServiceItem
                    debugger;
                    var filter;
                    if (!Ext.isEmpty(filterInfo.value) && filterInfo.value.length > 0) {
                        filter = Terrasoft.createColumnInFilterWithParameters(
                                                        "[UsrAccountServiceItem:UsrAccount:Id].UsrServiceItem.Id", filterInfo.value);
               
                    }
                    return filter;

                }

Создал замещающий клиентский модуль FixedFilterViewModelV2 (см. прикреплённый файл).

Фильтр работает, НО после перехода между разделами фильтр перестаёт работать, хотя getAccountServiceFixedFilter отрабатывает и контейнер фиксированного фильтра отображается.

Подскажите, кто сталкивался с подобной задачей, что я упустил из виду.
Версия 7.8.0.1005_CustomerCenter

Нравится

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

Коллега, вот же есть идеальная статья по созданию быстрого фильтра - https://academy.terrasoft.ru/documents/technic-sdk/7-7-0/kak-dobavit-v-…

Иначе нужно дебажиться

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

Здравствуйте!

Может проблема в асинхронности вызова - фиксированные фильтры раздела приходят после загрузки реестра?

Однако, Фильтр "Ответственный" в разделе Активности отрабатывает корректно. А я делал по его аналогии.

Предоставьте, пожалуйста, листинг AccountSectionV2.

"Демьяник Алексей" написал:Предоставьте, пожалуйста, листинг AccountSectionV2.

В NUI.ActivitySectionV2 переопределен метод init():

				init: function(callback, scope) {
					this.set("SelectedRows", []);
					this.initFiltersUpdateDelay();
					this.registerGetIsVisibleEmailPageButtonsHandler();
					this.initScheduleGridData();
					this.initSchedulerFloatItemsCollection();
					this.initSchedulerTimeScaleLookupValue();
					this.initMailBoxSyncSettings();
/* вот здесь вызывается метод, который фильтрует записи*/
					this.initFixedFiltersConfig();
					this.initIntervalMenuItems();
					this.callParent([function() {
						this.initSchedulerItemsAmountPerPage(function() {
							callback.call(scope);
						}.bind(this));
					}, this]);
					var sysSettings = ["BuildType"];
					Terrasoft.SysSettings.querySysSettings(sysSettings, function() {
						var buildType = Terrasoft.SysSettings.cachedSettings.BuildType &&
							Terrasoft.SysSettings.cachedSettings.BuildType.value;
						this.set("canUseSyncFeaturesByBuildType", buildType !==
						ConfigurationConstants.BuildType.Public);
					}, this);
					this.initGoogleSyncExists();
					this.initGoogleCalendarLog();
				},

Предполагаю, что Ваш метод не вызывается на init раздела (судя по листингу кода). Отсюда - раздел не фильтруется.

Вызывается, т.к. я переопределил и FixedFilterViewModelV2 (файл прикреплён в первом посте) и добавил свой функционал в метод init (см. блок строк 416-432).

Здравствуйте,
советую не трогать фиксированные фильтры, и воспользоваться решением, предоставленным тут:
http://www.community.terrasoft.ua/forum/topic/15943#comment-60027
По факту это будет то же самое, лукап в панеле фильтров, завязанный на атрибут (вирутальный) по изменению которого вы будете накладывать любую доп. фильтрацию на раздел.
Проверил все на 7.8. работает, и багов при переходе между разделами так же не заметил. Вот пример для раздела контрагентов, фильтрую по значению лукапа с типом город, по детали адреса контрагентов:

Сама замещающая страница секции контрагентов:

define("AccountSectionV2", ["BaseFiltersGenerateModule", "css!UsrMyFilterStyle"], function(BaseFiltersGenerateModule) {
	return {
		entitySchemaName: "Account",
		details: /**SCHEMA_DETAILS*/{
		}/**SCHEMA_DETAILS*/,
		diff: /**SCHEMA_DIFF*/[
			{
				"operation": "insert",
				"name": "MyFilterContainer",
				"parentName": "LeftGridUtilsContainer",
				"propertyName": "items",
				"index": 0,
				"values": {
					"id": "MyFilterContainer",
					"itemType": this.Terrasoft.ViewItemType.CONTAINER,
					"items": []
				}
			},
			{
				"operation": "insert",
				"parentName": "MyFilterContainer",
				"propertyName": "items",
				"name": "UsrCityFilter",
				"values": {
					"bindTo": "UsrCityFilter",
					"caption": "City"
				}
			}
		]/**SCHEMA_DIFF*/,
		attributes: {
			"UsrCityFilter": {
				"dataValueType": Terrasoft.DataValueType.LOOKUP,
				"type": Terrasoft.ViewModelColumnType.VIRTUAL_COLUMN,
				isLookup: true,
				caption: "City",
				referenceSchemaName: "City"
			}
		},
		mixins: {
			LookupQuickAddMixin: "Terrasoft.LookupQuickAddMixin"
		},
		methods: {
 
			onLookupChange: function(newValue, columnName) {
				this.callParent(arguments);
				if (columnName === "UsrCityFilter") {
					this.set("UsrCityFilter", newValue);
					this.onUsrCityFilterChanged();
				}
			},
 
			onUsrCityFilterChanged: function() {
				this.reloadGridData();
			},
 
			initQueryFilters: function(esq) {
				this.callParent(arguments);
 
				var usrCityFilter = this.get("UsrCityFilter");
 
				if (usrCityFilter && usrCityFilter.value) {
					esq.filters.add("UsrCityFilter", this.Terrasoft.createColumnFilterWithParameter(
						this.Terrasoft.ComparisonType.EQUAL, "[AccountAddress:Account:Id].City", usrCityFilter.value));
				} else {
					esq.filters.removeByKey("UsrCityFilter");
				}
			}
 
		}
	};
});

Дополнительные стили для расположения фильтра в том же ряду что и базовые (UsrMyFilterStyle):

#MyFilterContainer {
	display: inline-block;
	float: left;
	position: relative;
	padding-top: 5px;
}
 
#AccountSectionV2UsrCityFilterContainer_Label {
	max-width: 3em;
	min-width: 3em;
}
 
#AccountSectionV2UsrCityFilterContainer_Control {
	width: auto;
}

Результат:

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

Здравствуйте, развивая идею с фильтрацией в initQueryFilters: доработайте поле выбора пользовательским методом открытия формы подбора, примеров справочников с мультивыбором в системе достаточно, можно поискать по ключевому слову «multiSelect: true».
К примеру, в «EmailPageV2» такие есть:

Для контрола «текст» там задается иконка выбора и обработчик её нажатия:

"controlConfig": {
   "className": "Terrasoft.TextEdit",
   "rightIconClasses": ["custom-right-item", "lookup-edit-right-icon"],
   "rightIconClick": {
      "bindTo": "openRecepientLookupEmail"
   }
}

Потом в методе открывается своя форма подбора с мультивыбором, мультивыбор задается в конфиге:

getLookupConfig: function(columnName) {
   var scope = this;
   var callback = function(args) {
      scope.onLookupSelected(args);
   };
   return {
      config: {
         entitySchemaName: "VwRecepientEmail",
         columnName: columnName,
         columns: ["ContactId"],
         filters: Terrasoft.createColumnIsNotNullFilter("ContactId"),
         multiSelect: true
      },
      callback: callback
   };
},

Результат обрабатывается колбеком onLookupSelected
В теле которого само «текстовое» представление фильтра заполняется перечислением выбранных значений с произвольным разделителем, в примере EmailPageV2 это точка с запятой.

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

Илья, спасибо. Сам дошёл до этого варианта. Но при этом плывёт вёрстка и контейнер с фильтрами накладывается на фиксированные фильтры. + при переходе м/у разделами фильтр обнуляется.

На данный момент с фильтром есть две проблемы:
1.После перехода между разделами фильтр очищается. Как сохранить наполнение фильтра?
2. При открытии справочного поля необходима сортировка наполнения справочника. При открытии справочника я передаю в config массив:

sortedColumns:  [{
  name:"Name",
  orderPosition: 0,
  orderDirection: Terrasoft.OrderDirection.ASC
}]

В LookupPageViewModule.initSelectSorting сортировка применяется, однако в GridProfileHelper.initSelectSorting применяется стандартная сортировка по полю для отображения. По умолчанию для справочника это и есть поле Name, т.о. два правила сортировки применяются к одному и тому же полю. В итоге справочник не отсортирован. Как отключить стандартную сортировку?

1. Создать таблицу для кеша значений фильтрации, с колонкой «Ид пользователя», и текстовой строкой, в которую будете при onLookupChange новой фильтрации писать JSON массив значений поля сортировки (в том числе при очистке фильтра, в кеш писать тоже пустой JSON массив), а в «initQueryFilters» проверять таблицу кеша через esq запрос. Если в атрибуте пусто, а в кеше отличный от пустого JSON, восстанавливаете сохраненную в кеше фильтрацию.

2. Приоритет отдается сортировке, сохраненной в профиле, следовательно, либо очистить профиль, и тогда предсохраненной сортировки не останется, будет работать ваша, либо переписывать метод «initSelectSorting» в «GridProfileHelper», проверяя наличие в колонках из select атрибутов “orderDirection”, и если таковые есть, вовсе не применять к этим колонкам сортировку из «profileSortedColumns», но этим вы напрочь запретите пользователю изменить порядок сортировки через кнопку «Вид» -> «Сортировка», в форме выбора лукапа, для полей, сортировка которых передана программно. В общем, если решите замещать «GridProfileHelper», то часть коробочного функционала вы потеряете.

"Мотков Илья" написал:1. Создать таблицу для кеша значений фильтрации, с колонкой «Ид пользователя», и текстовой строкой, в которую будете при onLookupChange новой фильтрации писать JSON массив значений поля сортировки (в том числе при очистке фильтра, в кеш писать тоже пустой JSON массив), а в «initQueryFilters» проверять таблицу кеша через esq запрос. Если в атрибуте пусто, а в кеше отличный от пустого JSON, восстанавливаете сохраненную в кеше фильтрацию.

А разве стандартые фильтры (как быстрые, так и фиксированные) используют таблицу для кэша? Можно подробней о вашем варианте?

QuickFilterModule используют StorageUtilities, что по сути, что-то вроде document.scope в своем пространстве и с методами для хранения по группам, или по ключам. Можете использовать такой кеш, это решит вашу проблему с переходом по разделам. Но при повторном логине, или в другом браузере ваши фильтры слетят в ноль, и при установке будут жить в рамках сеанса.

FolderFilters, FixedFilters, TagFilters так же сохраняются в профиль, то есть, в таблицу в базе данных SysProfileData, к примеру:
SELECT * FROM SysProfileData WHERE [Key] = 'ActivitySectionV2GridDataViewFilters'

Это решает сохранение фильтров даже при выходе и заходе в приложение. В зависимости от того что вам необходимо, используйте первый или второй подход. Храните информацию в document.scope или в StorageUtilities. Либо создавайте свою таблицу для кеша и пишите в неё. Либо можете писать в SysProfileData, только используйте для этого свой уникальный ключ.

P.S. почитайте saveFilter в BaseSectionV2

Спасибо Илья!

Показать все комментарии
Добрый день!Предлагаю подумать в возвращении кнопок "Да" и "Нет" в диалоге подтверждения на свои места. Интуитивно кнопка "Да" ищется всегда слева. Если это сделано для того, чтобы пользователь сознательно удалял запись, то, на мой взгляд, это не лучшее решение. Пользователь рано или поздно привыкнет к порядку кнопок в 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" - расположение Справа на Лево ("Нет", "Да") и как уже пользователю удобно так он и настраивает под себя интерфейс. Вот еще одно из предложений.

Показать все комментарии

22 апреля мы приглашаем всех на грандиозное событие — презентацию новой версии ‪CRM‬-линейки bpm’online 7.8!

Уверены, что изменения, которые произошли в продукте, не оставят вас равнодушными.

За 60 минут в онлайне мы покажем:
1. Интерфейс, который вдохновляет!
2. Дизайнер бизнес-процессов, который позволяет быстро адаптироваться под изменения рынка.
3. CRM-инструменты, с которыми быстрее достигать бизнес-результата.

Подключайтесь к онлайн-трансляции 22 апреля с 10:00 до 11:00 (МСК)!

Узнайте больше на сайте

Нравится

Поделиться

0 комментариев
Показать все комментарии