Добрый день коллеги, столкнулся с проблемой, которую не в силах решить, заказчик попросил реализовать новый фильтр в разделе, решением оказался fixedfilter с использованием метода initfixedfilterconfig.

// Добавить фильтр по типу Обращения
initFixedFiltersConfig: function() {
	this.callParent();
	var defvalue = [
		{value: "13fa5292-c957-4452-8bea-97e5cd381ed0",displayValue: "IT"}, 
		{value: "51c2810b-2c34-4046-a4bf-2cca62b3e10a",displayValue: "Maintenance"}
	];
	var ffc = this.get("FixedFilterConfig"); // Прошлые фильтры
	var fixedFilterConfig = {
		name: "KORUSLOOKUPCaseType",
		columnName: "KORUSLOOKUPCaseType",
		caption: "Тип",
		isCustomFilter: true,
		dataValueType: this.Terrasoft.DataValueType.LOOKUP,
		appendCurrentContactMenuItem: false,
        addNewFilterCaption: this.get("Resources.Strings.SelectFilterTypeCaption"), // Выбрать тип
        hint: this.get("Resources.Strings.SelectFilterTypeCaption"), // Выберите тип обращения
		buttonImageConfig: this.get("Resources.Images.SelectFilterTypeImage"),
		defValue: defvalue,
		//appendFilter: this.appendFixedCaseTypeFilter, - добавление фильтра ( не меняет визуал)
		//getFilter: this.appendFixedCaseTypeFilter
	};
	if (ffc != undefined) {
		ffc.filters.push(fixedFilterConfig);
		this.set("FixedFilterConfig", ffc);
	}
},

Фильтр работает как надо, но после последовала просьба очищать фильтр при выборе нового значения , по сути при нажатии на кнопку "Выбрать тип", необходимо реализовать сначала логику кнопки "Очистить"

Изображение удалено.

При этом нельзя затрагивать логику прошлых фильтров. Так же не хотелось бы решать эту задачу методом добавления поля типа Lookup в шапку фильтров

Нравится

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

Добрый день,

 

Реализовать эту функциональность будет крайне сложно, если возможно впринципе, потому что замещения FixedFilterViewModelV2 с моей стороны ничего не дали. Необходимо завязываться на метод lookupSelecting в FixedFilterViewModelV2, потому что колбек функция в ней как раз отвечает за обновление фильтра. В контексте выполнения функции можно сохранить текущий фильтр (вычитать this.$Filters и проверить есть ли там что-то сейчас и если есть, то очищать этот фильтр). Когда в открытом попап окне выбирается новое условие, то колбек вызывает метод addNonPeriodFilterValue, который добавляет к существующей фильтрации ту, которую мы выбираем из попап окна, внутри которого срабатывает метод filterChanged, который обновляет фильтр на UI. То есть, отталкиваться нужно было бы от метода lookupSelecting, но, похоже, это придется полностью переписывать логику View модели и переподключать её к схеме раздела.

Спасибо за ваш ответ, попробую реализовать его или какие-то обходные решения

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

Всем привет!

Пытаюсь сделать кастомные фильтры в секции для разных лукапных полей как это сделано в некоторых секциях для дат и для Ответственного (например Активности). Взял за основу стандартные фильтры, но никак не соображу как сделать это для других колонок - такое ощущение, что там всё захардкожено на колонке Owner, хотя в конфиге можно задать свою колонку. Кто-нибудь разбирался с подобным? Буду признателен за подсказки.

П.С.: Припоминаю, что очень давно делал похожее в версии в 7.7 или 7.8, но там всё выглядело немного по другому и это решение скорее всего не подойдет для новой версии.

 

Заранее спасибо.

Нравится

1 комментарий
Лучший ответ

А вы попробуйте новое дополнение. Я его как раз тестировал с точки зрения кастомных фильтров - 80% потребностей им решилось https://marketplace.terrasoft.ua/app/custom-filter-constructor-creatio

А вы попробуйте новое дополнение. Я его как раз тестировал с точки зрения кастомных фильтров - 80% потребностей им решилось https://marketplace.terrasoft.ua/app/custom-filter-constructor-creatio

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

Добрый день. Подскажите, кто-нибудь уже делал быстрые фильтры, для кастомной детали.

 

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

define("UsrScheduleForAllDayDetail", [], function() {
	return {
		entitySchemaName: "UsrScheduleForAllDay",
		messages: {
			/**
			 * @message GetFixedFilter
			 * ######## ######## FixedFilter.
			 * @param {String} ######## #######.
			 * @return {Object} ######.
			 */
			"GetFixedFilter": {
				mode: this.Terrasoft.MessageMode.PTP,
				direction: this.Terrasoft.MessageDirectionType.PUBLISH
			},
		},
		details: /**SCHEMA_DETAILS*/{}/**SCHEMA_DETAILS*/,
		diff: /**SCHEMA_DIFF*/[
			{
				"operation": "merge",
				"name": "DataGrid",
				"values": {
					"type": "listed",
					"hierarchical": true,
					"sortColumnDirection": { "bindTo": "disableGridSorting" },
					"hierarchicalColumnName": "ParentId",
					"updateExpandHierarchyLevels": {
						"bindTo": "onExpandHierarchyLevels"
					},
					"expandHierarchyLevels": {
						"bindTo": "expandHierarchyLevels"
					}
				}
			},
			{
				"operation": "insert",
				"name": "QuickFilterModuleContainer",
				"parentName": "Detail",
				"propertyName": "items",
				"values": {
					"id": "QuickFilterModuleContainer",
					"selectors": {wrapEl: "#QuickFilterModuleContainer"},
					"itemType": Terrasoft.ViewItemType.CONTAINER,
					"wrapClass": ["quick-filter-module-container-wrapClass"],
					"items": []
				}
			}
		]/**SCHEMA_DIFF*/,
		methods: {
			init: function() {
				this.callParent(arguments);
				this.initFixedFiltersConfig();
			},
			initFixedFiltersConfig: function() {
				var fixedFilterConfig = {
					entitySchema: this.entitySchema,
					filters: [
						{
							name: "PeriodFilter",
							caption: this.get("Resources.Strings.PeriodFilterCaption"),
							dataValueType: this.Terrasoft.DataValueType.DATE,
							startDate: {
								columnName: "UsrDate",
								defValue: this.Terrasoft.startOfWeek(new Date())
							},
							dueDate: {
								columnName: "UsrDate",
								defValue: this.Terrasoft.endOfWeek(new Date())
							}
						}
					]
				};
				this.set("FixedFilterConfig", fixedFilterConfig);
			},

 

Нравится

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

У вас parentName для QuickFilterModuleContainer существует?

Что вообще говорит консоль и отладка?

Золотарев Артем Андреевич пишет:

У вас parentName для QuickFilterModuleContainer существует?

Что вообще говорит консоль и отладка?

 Реализовал деталь в качестве раздела, там же сразу и заработали фильтры

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

Добрый день.
Стоит задача сделать аналог фиксированного фильтра "Ответственный" в р. Контрагенты.
Фильтрация происходит по детали "Сервисы контрагента".
Фильтр в 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

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

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