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

Выделение цветом в Расписании активностей при определенных условиях

Здравствуйте! Мне нужно, чтобы в Расписании выделялись цветом те задачи, которые имеют в заголовке слово "Свободно".

Если реализовать через такой код

define("ActivitySectionV2", [],
    function () {
        return {
            // Название схемы раздела.
            entitySchemaName: "Activity",
                details: /**SCHEMA_DETAILS*/{}/**SCHEMA_DETAILS*/,
                diff: /**SCHEMA_DIFF*/[]/**SCHEMA_DIFF*/,
            methods: {
                // Переопределение базового метода, который модифицирует строку данных перед загрузкой в реестр.
                prepareResponseCollectionItem: function (item) {
                    this.callParent(arguments);
                    item.customStyle = null;
                    var running = item.get("Title");
                    //Если условие подходит, меняем цвет записи на темно-серый, а фон на светло-зеленый.
                    if (running.indexOf('Свободно')+1) {
                        item.customStyle = {
                            'color': "darkgrey",
                            'background': "#D8FBC2"
                        }
                    }
                }
            }
        };
    });


то в разделе активность поменяла свой цвет а вот в расписании не поменяла.

 

Как сделать так чтобы в расписании активность поменяла свой цвет если в заголовке есть слово "Свободно"?
Версия BpmOnline sales commerce 7.8.3.1978

Нравится

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

Извините за оффтопик.
Не делали бы вы для раскраски реестров парсинг текста заголовка, ляжет и погибнет у вас система как объемы данных нарастут... это же неиндексируемое поле, да еще поиск по тексту...
Тут бы признак сделать типа булевского поля, и по нему обрабатывать. А булевское поле заполнять например тем самым парсингом названия при сохранении активности.

по теме
посмотрите в ActivitySectionV2 поиском по тексту "FontColor" -найдете в diff описание конфига для отображения элементов расписания. Возможно поможет замещение и замена bindto для fontcolor на новый атрибут... но это предположение :)

Раскраска активностей в расписании

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

Анализ
Таблица расписания определена внутри пакета NUI в модуле ActivitySectionV2, как элемент в объекте diff с именем Schedule. В данный элемент вложен объект itemBindingConfig, который отвечает за привязку свойств активности к каждому из элементов расписания. В данном случае нас интересуют два значения, а именно: background, устанавливающий цвет фона элемента расписания и fontColor, определяющий цвет текста на нём.
Привязанные методы (то, что идёт после bindTo, например, getScheduleItemTitle) определяются внутри пакета UIv2 в модуле ActivitySectionGridRowViewModel. Привязанные поля есть ничто иное, как загруженные из базы данных поля схемы Activity, список которых определяется внутри модуля ActivitySectionV2 в методе getGridDataColumns. Обратите внимание, что по умолчанию background и fontColor привязаны к полям, которых нет в схеме Activity (Background и FontColor соотвественно).
Внутренняя логика поведения элемента расписания определена в файле schedule-item.js (класс Terrasoft.controls.ScheduleItem). После анализа этого кода становится ясно, что в случае, если background определён, то CSS стиль элемента меняется, в противном случае – нет. То же касается и fontColor:
[javascript]

if (background && isSelected) {
out.push('');
} else if (background && !isSelected) {
out.push('');
} else if (!background && isSelected) {
out.push('');
} else {
out.push('');
}

[/javascript]
Также можно заметить ещё одну особенность. Свойства background и fontColor не применяется для элементов, выделенных пользователем нажатием мыши:
[javascript]

itemBodyEl.setStyle({
"backgroundColor": (isSelected) ? "" : this.background,
"color": (isSelected) ? "" : this.fontColor
});

[/javascript]
Не совсем понятно, с чем это может быть связанно. Тем не менее изменять логику внутренних модулей системы не рекомендуется, и придётся довольствоваться тем, что предоставили нам разработчики.

Реализация
Шаг 1. Добавление справочника.
Первым шагом будет добавление справочника ActivitySchedulerColor. Дадим ему заголовок «Цвет активности в расписании» и добавим следующие поля:

  • ActivityPriority с типом Справочник, который ссылается на «Приоритет активности».
  • BackgroundColor с типом Строка
  • FontColor с типом Строка

Добавим для каждого приоритета запись в справочнике. Выборочно присвоим некоторым из них значения цветов, а некоторые оставим пустыми.

Шаг 2. Добавление хелпера.
Далее необходимо добавить клиентский модуль, который будет загружать значения цветов из добавленного нами справочника и возвращать конкретные цвета по Id приоритета:
[javascript]
define("ActivitySectionGridRowHelper", ["terrasoft"], function(Terrasoft) {
var activitySchedulerColor = {};

//Возвращает соответствующие priorityId цвета из справочника ActivitySchedulerColor
//Перед вызовом этого метода, необходимо загрузить данные из справочника методом loadActivitySchedulerColors
function getActivitySchedulerColor(priorityId) {
return activitySchedulerColor[priorityId];
}

//Загружает данные из справочника ActivitySchedulerColor (Цвета активностей)
function loadActivitySchedulerColors() {
var esq = Ext.create("Terrasoft.EntitySchemaQuery", {rootSchemaName: "ActivitySchedulerColor"});
esq.addColumn("ActivityPriority", "ActivityPriority");
esq.addColumn("BackgroundColor", "BackgroundColor");
esq.addColumn("FontColor", "FontColor");
esq.getEntityCollection(function(response) {
Terrasoft.each(response.collection.collection.items, function(item) {
activitySchedulerColor[item.values.ActivityPriority.value] = {
"backgroundColor":item.values.BackgroundColor,
"fontColor":item.values.FontColor
};
}, this);
});
}

return {
GetActivitySchedulerColor: getActivitySchedulerColor,
LoadActivitySchedulerColors: loadActivitySchedulerColors
};
});
[/javascript]
Шаг 3. Замещение модуля ActivitySectionV2.
Следующим шагом будет переопределение схемы ActivitySectionV2. Здесь нужно изменить привязку значений для таблицы расписания, добавить поле Priority в выборку данных для таблицы расписания и вызвать из хелпера метод loadActivitySchedulerColors:
[javascript]
define("ActivitySectionV2", ["ActivitySectionGridRowHelper"],
function(ActivitySectionGridRowHelper) {
return {
entitySchemaName: "Activity",
details: /**SCHEMA_DETAILS*/{}/**SCHEMA_DETAILS*/,
diff: /**SCHEMA_DIFF*/[
{
"operation": "merge",
"name": "Schedule",
"values": {
"itemBindingConfig": {
"itemId": {"bindTo": "Id"},
"title": {"bindTo": "getScheduleItemTitle"},
"changeTitle": {"bindTo": "onTitleChanged"},
"startDate": {"bindTo": "StartDate"},
"changeStartDate": {"bindTo": "onStartDateChanged"},
"dueDate": {"bindTo": "DueDate"},
"changeDueDate": {"bindTo": "onDueDateChanged"},
"status": {"bindTo": "getScheduleItemStatus"},
"changeStatus": {"bindTo": "onStatusChanged"},
"background": {"bindTo": "getBackground"},
"fontColor": {"bindTo": "getFontColor"},
"isBold": {"bindTo": "IsBold"},
"isItalic": {"bindTo": "IsItalic"},
"isUnderline": {"bindTo": "IsUnderline"},
"markerValue": {"bindTo": "getScheduleItemHint"}
}
}
}
]/**SCHEMA_DIFF*/,
methods: {
getGridDataColumns: function() {
var baseGridDataColumns = this.callParent(arguments);
var gridDataColumns = {
"Account": {path: "Account"},
"StartDate": {path: "StartDate"},
"DueDate": {path: "DueDate"},
"ShowInScheduler": {path: "ShowInScheduler"},
"Status": {path: "Status"},
"Status.Finish": {path: "Status.Finish"},
"ProcessElementId": {
path: "ProcessElementId",
dataValueType: 0
},
"Priority": {path: "Priority"}
};
return Ext.apply(baseGridDataColumns, gridDataColumns);
},
init: function () {
this.callParent(arguments);
ActivitySectionGridRowHelper.LoadActivitySchedulerColors();
}
}
};
});
[/javascript]

Шаг 4. Замещение модуля ActivitySectionGridRowViewModel.

В данный модуль нам необходимо добавить два метода getBackground и getFontColor, к которым мы привязали значения полей background и fontColor. Однако, так как все методы объявлены внутри Ext.define, придётся копировать весь код модуля:
[javascript]
define("ActivitySectionGridRowViewModel", ["ext-base", "terrasoft", "ActivitySectionGridRowHelper","BaseSectionGridRowViewModel"],
function(Ext, Terrasoft, ActivitySectionGridRowHelper) {

/**
* @class Terrasoft.configuration.ActivitySectionGridRowViewModel
*/
Ext.define("Terrasoft.configuration.ActivitySectionGridRowViewModel", {
extend: "Terrasoft.BaseSectionGridRowViewModel",
alternateClassName: "Terrasoft.ActivitySectionGridRowViewModel",

/**
* Возвращает значение всплывающей подсказки для элемента в расписании.
* @return {String} Значение всплывающей подсказки для элемента в расписании.
*/
getScheduleItemHint: function() {
var timeFormat = Terrasoft.Resources.CultureSettings.timeFormat;
var startDate = Ext.Date.format(this.get("StartDate"), timeFormat);
var dueDate = Ext.Date.format(this.get("DueDate"), timeFormat);
var title = this.get("Title");
var account = this.get("Account");
var accountDisplayValue = (account) ? account.displayValue + ": " : "";
return Ext.String.format("{0}-{1} {2}{3}", startDate, dueDate, accountDisplayValue, title);
},

/**
* Возвращает статус элемента расписания.
* @return {Terrasoft.ScheduleItemStatus} Статус элемента расписания.
*/
getScheduleItemStatus: function() {
var isFinished = this.get("Status.Finish");
var dueDate = this.get("DueDate");
if (dueDate <= new Date() && !isFinished) {
return Terrasoft.ScheduleItemStatus.OVERDUE;
} else if (isFinished) {
return Terrasoft.ScheduleItemStatus.DONE;
}
return Terrasoft.ScheduleItemStatus.NEW;
},

/**
* Возвращает значение заголовка элемента в расписании.
* @return {String} Значение заголовка элемента в расписании.
*/
getScheduleItemTitle: function() {
var title = this.get("Title");
var account = this.get("Account");
var accountDisplayValue = (account) ? account.displayValue + ": " : "";
return Ext.String.format("{0}{1}", accountDisplayValue, title);
},

/**
* inheritdoc Terrasoft.BaseGridRowViewModel#getEntitySchemaQuery
*/
getEntitySchemaQuery: function() {
var esq = this.callParent(arguments);
if (!esq.columns.contains("Status.Finish")) {
esq.addColumn("Status.Finish");
}
return esq;
},

/**
* inheritdoc Terrasoft.BaseViewModel#setColumnValues
*/
setColumnValues: function(entity) {
this.set("Status.Finish", entity.get("Status.Finish"));
this.callParent(arguments);
},

/**
* Обрабатывает событие изменения поля "Начало".
* @protected
* @param {Date} date Новое значение даты.
*/
onStartDateChanged: function(date) {
this.set("StartDate", date);
this,
this.saveEntity(Terrasoft.emptyFn, this);
},

/**
* Обрабатывает событие изменения поля "Завершение".
* @protected
* @param {Date} date Новое значение даты.
*/
onDueDateChanged: function(date) {
this.set("DueDate", date);
this.saveEntity(Terrasoft.emptyFn, this);
},

/**
* Обрабатывает событие изменения поля "Заголовок".
* @protected
*/
onTitleChanged: Terrasoft.emptyFn,

/**
* Обрабатывает событие изменения поля "Состояние".
* @protected
*/
onStatusChanged: Terrasoft.emptyFn,
getBackground: function() {
var priority = this.get("Priority");
var activitySchedulerColor = ActivitySectionGridRowHelper.GetActivitySchedulerColor(priority.value);
var backgroundColor = activitySchedulerColor.backgroundColor;
return backgroundColor;
},
getFontColor: function() {
var priority = this.get("Priority");
var activitySchedulerColor = ActivitySectionGridRowHelper.GetActivitySchedulerColor(priority.value);
var fontColor = activitySchedulerColor.fontColor;
return fontColor;
}
});

return Terrasoft.ActivitySectionGridRowViewModel;
});
[/javascript]

Результат
В результате должно получится что-то вроде:

Для активности «Развернуть стенд» указан приоритет для которого не указан цвет в справочнике ActivitySchedulerColor. Соответственно, для него работает стандартная логика и он окрашивается в соответствии со своим статусом и временем.
Для приоритетов активностей «Позвонить клиенту» и «Написать Hello, World!» в справочнике ActivitySchedulerColor указан цвет, и они окрашиваются по добавленной логике.

Добрый день.

При реализации данного таска на шаге:

Шаг 4. Замещение модуля ActivitySectionGridRowViewModel.

появилась ошибка: "Замещение модулей запрещено".

Хотя в настройке модуля параметр "Запретить замещение" не установлен.

Можете подсказать, в чём может быть причина?

С 2016 года архитектура системы изменилась. Модули замещать запрещено, начиная с версии 7.13.1.

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