Добрый день.
Стоит задача сделать аналог фиксированного фильтра "Ответственный" в р. Контрагенты.
Фильтрация происходит по детали "Сервисы контрагента".
Фильтр в AccountSectionV2:
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
Нравится
Коллега, вот же есть идеальная статья по созданию быстрого фильтра - https://academy.terrasoft.ru/documents/technic-sdk/7-7-0/kak-dobavit-v-…
Иначе нужно дебажиться
Илья, в указанной статье показан пример добавления стандартных фильтров.
Мне же нужен фильтр по аналогии с фильтром "Ответственный".
Он реализован, но не срабатывает после перехода между разделами, как я писал выше
Здравствуйте!
Может проблема в асинхронности вызова - фиксированные фильтры раздела приходят после загрузки реестра?
Однако, Фильтр "Ответственный" в разделе Активности отрабатывает корректно. А я делал по его аналогии.
"Демьяник Алексей" написал:Предоставьте, пожалуйста, листинг 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, только используйте для этого свой уникальный ключ.