Добрый день! Есть задача скрывать кнопку "Печать" на странице записи в зависимости от некоторых условий. Были внесены изменения в страницу объекта с подключением миксина PrintReportUtilities, при перезагрузке страницы логика скрытия отрабатывает корректно. Но когда открытие страницы происходит через секцию, кнопка все равно отображается, не смотря на то что код на странице отрабатывает и скрывает её. Какие изменения нужно внести в секцию, что бы кнопка так же была скрыта?

Нравится

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

Илья, здравствуйте!

 

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

Пример с изменением страницы в совмещённом режиме есть в статье на академии, которую можно найти по ссылке:

https://academy.terrasoft.ua/docs/developer/elements_and_components/bas…

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

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

Могу ли я как то поменять стандартное поле для фильтраций по условию?

Нравится

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

Добрый день!

 

Первое поле, которое отображается в быстрых фильтрах - это поле, которое соответствует параметру "Первичная колонка для отображения" в настройках объекта. Для базовых объектов мы не рекомендуем изменять этот параметр, так как на нем завязано много логики (например, работа тегов).

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

Добрый день!

 

Есть задача по реализации кнопки-меню с динамическим списком. Нужно создать кнопку по типу Actions или Print.

Я создала метод, который выбирает из списка нужные пункты и добавляет их как пункты меню:

attributes: {
	"ButtonMenu": {dataValueType: this.Terrasoft.DataValueType.COLLECTION},
},
methods: {
	init: function() {
		this.callParent(arguments);
		this.initMenuItems();
	},
initMenuItems:function(){
	var esq = this.Ext.create("Terrasoft.EntitySchemaQuery", {
		rootSchemaName: "MyList"
	});
	esq.addColumn("Caption");
	esq.filters.add("Section", this.Terrasoft.createColumnFilterWithParameter(this.Terrasoft.ComparisonType.EQUAL, "Section.Id", "f7856ad3-fa4c-4106-9a6c-d8dcd87331eb"));
	esq.execute(function (response) {
	        if (!response.success) {
		       return;
	        }
	        var actionMenuItems = Ext.create("Terrasoft.BaseViewModelCollection");
		response.collection.each(function(item) {
 
			var isVisible = this.getVisibility(item.get("Caption"));
			actionMenuItems.addItem(this.getButtonMenuItem({
				"Caption": item.get("Caption"),
				"Click": {bindTo: "callMyProcess"},
				"Enabled": isVisible
			}));
		},this);
		this.set("ButtonMenu", actionMenuItems);
	},this);			
}
},
		diff: /**SCHEMA_DIFF*/[
			{
                "operation": "insert",
                "parentName": "LeftContainer",
                "propertyName": "items",
                "name":"MenuButton",
                "values": {
                    "itemType": Terrasoft.ViewItemType.BUTTON,
                    "style": Terrasoft.controls.ButtonEnums.style.GREEN,
                    "caption": "Test",
                    "menu": {
                        "items": {"bindTo": "ButtonMenu"}
                    }
                }
            }
		]/**SCHEMA_DIFF*/

Когда я вызываю мой метод в методе init страницы раздела, то поставленная задача выполняется. НО портится стиль всех остальных кнопок списков, добавляя стрелку пролистывания как в большие, так и в маленькие списки:

 

Если закоментировать вызов моего метода в методе init, то стрелка в списках пропадает и они отображаются корректно (но в этом случае моя кнопка никогда не инициализирует список).

 

Что сделано не правильно?

Подскажите, пожалуйста, как решить данную задачу.

 

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

Нравится

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

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

 

Реализовал Ваш пример на тестовом сайте, но подобной проблемы не наблюдаю. Похоже, что проблема не в предоставленном коде, а в чем-то другом. Просьба обратиться в техническую поддержку и указать ссылку на сайт, где реализован пример (или предоставить пакет). 

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

Доброго времени! 

У меня интересная задача)
Необходимо сменить ответственного у нескольких записей продаж.

Задача:
1. Поставить фильтр (допустим выдало 100 записей)
2. Нажать "Выбрать все" (показано что выбрано 100)
3. Снять 1 галочку (показано что выбрано 99)
4. Нажать "Изменить ответственного"

Методы:
var selectedRows = this.getSelectedItems();
var selectedRows = this.get("SelectedRows");

Возвращают Id только отображенных записей (29)!

Как получить ожидаемые 99 Id записей?

Нравится

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

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

Когда загружается реестр посылается один запрос (который оптимизирован и загружает не все записи, а 30 – если у вас 100000 записей то не будет накладки по производительности). Когда вы нажимаете «Выбирать все», то не произойдет загрузки всех записей(оптимизация описанная выше), а отправится отдельный запрос который просто вернет количество и обновит название кнопки (при дебаге в network это видно). Чтобы добиться требуемого результата нужно самостоятельно посылать запрос.

Тоже столкнулся с такой проблемой. Самое простое решение, которое я нашел - это использовать функцию, возвращающую запрос на получение записей для экспорта:

                    var esq = this.getExportToExcelEsq();
                    esq.rowCount = -1;
                    esq.getEntityCollection(function (response) {...}, this);

Можно посмотреть, как она работает и заменить её своей. Результатом запроса будут все выделенные записи (99 в Вашем случае).

 

Поправка: в 7.12.2 функция, возвращающая запрос, переехала, теперь так:

var esq = this.getGridDataInitializedEsq(true);
esq.rowCount = -1;

...

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

Добрый день.
Необходимо установить сортировку данных пользовательского раздела по умолчанию по определённому полю объекта.
В BaseSectionV2 используются атрибуты: "sortColumn", "SortColumnIndex", "GridSortDirection".

Так же в свойствах объекта есть свойство "Сортировка в списках".

Но установка значений этих атрибутов и свойства не решила задачу.

Прошу подсказать как решить данный кейс

Нравится

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

Добрый день

В BaseSection есть метод initQuerySorting, в котором происходит установка колонок сортировки. Возможно вы меняли атрибуты после того, как эта функция отработала. Попробуйте продебажить

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

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

Нравится

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

Просто в странице в методе init описан onEntityInitialized, а в разделе - нет. Как вариант можно заместить базовую схему страницы и написать что-то своё:

init: function(callback, scope) {
	var performanceManagerLabel = "";
	if (scope && scope.hasOwnProperty("sandbox")) {
		performanceManagerLabel = scope.sandbox.id;
	} else if (this && this.hasOwnProperty("sandbox")) {
		performanceManagerLabel = this.sandbox.id;
	}
	performanceManager.start(performanceManagerLabel + "_Init");
	this.callParent([function() {
		Terrasoft.chain(
			this.checkAvailability,
			this.initViewModelValuesFromSysSettings,
			this.initActiveViewSettingsProfile,
			this.initData,
			this.initLeftSectionContainerSize,
			function(next) {
				this.canUseWizard(function(result) {
					this.set("CanUseWizard", result);
				}, this);
				this.checkCanManageAnalytics();
				this.initSectionFiltersCollection();
				this.initSortActionItems();
				this.initDataViews();
				this.initActionButtonMenu("Separate", this.getSectionActions());
				this.initSectionViewOptionsButtonMenu(this.getViewOptions());
				this.initDcmActionsDashboardVisibility(function() {
					this.initCanUseDcmDesigner();
				}, this);
				this.initEditPages();
				this.initCardContainer();
				this.initContextHelp();
				this.initAddRecordButtonParameters();
				this.initFolders();
				this.initRowCount();
				this.initIsPageable();
				this.initIsActionButtonsContainerVisible();
				this.initUpdateAction();
				this.initResetAction();
				this.subscribeInitFilterFromStorage();
				this.initActionsButtonHeaderMenuItemCaption();
				this.subscribeSandboxEvents();
				this.mixins.GridUtilities.init.call(this);
				this.subscribeIsCardVisibleChange();
				this.subscribeGetRunProcessesProperties();
				this.initRunProcessButtonMenu(false);
				this.subscribeCanShowTags();
				this.initActionsButtonCaption();
				this.subscibeOnMultiSelectChange();
				this.subscibeOnSelectedRowsChange();
				this.initTags(this.entitySchemaName);
				this.initSectionHeaderContainerVisibility();
				next();
			},
			function(next) {
				this.onSectionInitialized();
				next();
			},
			function() {
				performanceManager.stop(performanceManagerLabel + "_Init");
				performanceManager.start(performanceManagerLabel + "_BeforeRender");
				callback.call(scope);
			}, this);
		this.initHelpUrl(this.Terrasoft.emptyFn, this);
		this.initPrintButtonsMenu(this.Terrasoft.emptyFn, this);
	}, this]);
},
onSectionInitialized: function() {
	debugger;
}

Но работать будет немного криво (пр.: у меня при остановке на дебагере в "GridData" валяется пустая коллекция. Инициализируется она, видимо, позже). Посмотрите, может вам подойдёт.

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

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

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

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