7.8
Filter
fixedFilter
Section
Технические вопросы
7.x

Пользовательский фиксированный фильтр

Добрый день.
Стоит задача сделать аналог фиксированного фильтра "Ответственный" в р. Контрагенты.
Фильтрация происходит по детали "Сервисы контрагента".
Фильтр в 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():
[javascript]
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();
},
[/javascript]

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

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

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

Сама замещающая страница секции контрагентов:
[javascript]
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");
}
}

}
};
});
[/javascript]

Дополнительные стили для расположения фильтра в том же ряду что и базовые (UsrMyFilterStyle):
[javascript]
#MyFilterContainer {
display: inline-block;
float: left;
position: relative;
padding-top: 5px;
}

#AccountSectionV2UsrCityFilterContainer_Label {
max-width: 3em;
min-width: 3em;
}

#AccountSectionV2UsrCityFilterContainer_Control {
width: auto;
}
[/javascript]

Результат:

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

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

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

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

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

[javascript]
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
};
},
[/javascript]

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

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

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

На данный момент с фильтром есть две проблемы:
1.После перехода между разделами фильтр очищается. Как сохранить наполнение фильтра?
2. При открытии справочного поля необходима сортировка наполнения справочника. При открытии справочника я передаю в config массив:
[javascript]
sortedColumns: [{
name:"Name",
orderPosition: 0,
orderDirection: Terrasoft.OrderDirection.ASC
}]
[/javascript]
В 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

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

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