Информеры

Введение

Информером называют кнопку-ссылку (см. SBIS3.CONTROLS/Menu/MenuLink), отображаемую в специальной области страницы веб-приложения online.sbis.ru, которая предназначена для уведомления пользователя о значимых событиях: число непрочитанных сообщений/чатов, пропущенные звонки, полученные поощрения или взыскания, приближающийся отпуск сотрудника — вот ряд информеров (см. изображение ниже), уже внедренных в веб-приложение online.

На изображении выше панель информеров реализована на основе контрола SBIS3.ENGINE/Controls/Informer.

Список отображаемых информеров формируется при запросе пользователем страницы веб-приложения online.sbis.ru. Для этого внутри Основного сервиса приложения публикуется сервисное событие configuration.getInformers, которое существует только в рамках этого сервиса и недоступно другим сервисам БЛ и клиентским приложениям (см. Работа с событиями в рамках одного рабочего процесса). Это событие отслеживается в прикладном коде, и при его наступлении выполняются обработчики, которые возвращают конфигурацию отображаемых информеров. Прикладной код описывается в сервисных модулях, которые добавлены в состав Основного сервиса приложения.

Далее в статье будет рассмотрен процесс добавления информера. Для отладки работы информера Вы можете использовать локальный отладочный стенд online.sbis.ru (см. Развертывание локального стенда online.sbis.ru).

Конфигурация информера на бизнес-логике

Подписка на событие configuration.getInformers

Для начала создайте новый сервисный модуль или используйте уже существующий. Такой модуль должен быть добавлен в список зависимостей Основного сервиса приложения, чтобы на публикуемое событие можно было подписаться (установить обработчик).

В корне директории сервисного модуля создайте файл on_event.py. В файл добавьте код, который будет выполняться при окончании загрузки модуля:

def OnEndAllLoadModules(answer):
   import event
   event.SetLocalCallback("configuration.getInformers", <метод-обработчик>)

Здесь <метод-обработчик> — это прикладной метод БЛ с произвольным количеством параметров (Custom method), возвращающий RecordSet с конфигурацией информеров, где одна запись описывает один добавляемый информер. Метод БЛ вызывается при наступлении события configuration.getInformers. Метод может быть определен в текущем сервисном модуле или располагаться в любых других, принадлежащих Основному сервису приложения.

Создание обработчика, который возвращает конфигурацию информера

Для создания метода-обработчика, который возвращает конфигурацию добавляемых информеров, используют справочник объектов. Тип метода — метод с произвольным количеством параметров (Custom method).

Конфигурация информеров возвращается методом в виде таблицы Result type: Table, где запись имеет поля, описанные в следующей таблице.

ИмяТип / БЛ-типОписание
nameString / TextИмя информера.
orderInt / Integer (2 bytes)Порядок информера на панели.
captionString / TextТекст информера. Исходное значение расчитывается на БЛ.
iconString / TextОписание иконки информера.
classNameString / TextСвойство className информера, пользовательские CSS-классы.
tooltipString / TextПодсказка при наведении мыши на информер.
visibleBooleanФлаг видимости информера.
sourceJSON / HashTableМассив с описанием источника(ов) для обновления информера (см. Таблица 2).
initModuleString / TextИмя модуля обработки действий, связанных с информером (см. Таблица 2)
userDataJSON / HashTableПользовательские данные, которые нужно передать на клиент.

Таблица 1. Формат записи с описанием информера

ИмяТип / БЛ-типОписание
typeStringтип источника, может быть одим из:
  • serverEvent — сервисное событие;
  • event — событие на клиенте;
  • localStorage — слежка за значением в localStorage;
  • custom — собственная подписка на обновление.
channelStringИмя канала для события.
eventStringИмя события в канале.
nameStringИмя ключа в localStorage.

Таблица 2. Формат описания источника

Пример передачи обработчика

Разберем реализацию обработчика серверного события на примере информера сообщений. Подписываемся на сервисное событие: создадим файл on_event.py в корне сервисного модуля "Обмен сообщениями". Добавляем туда следующее содержимое:

def OnEndAllLoadModules(answer):
   import event
   event.SetLocalCallback("configuration.getInformers", "Персона.ПолучитьИнформер")

Теперь нужно добавить метод, который мы указали в качестве обработчика. Для этого воспользуемся Genie (см. Изображение). Как было сказано выше, метод должен возвращать рекордсет (Result type: Table) с описанием информеров (Return values, см. Таблица 1). Метод реализован на Python (Method type: Python).

Далее приведен код метода "Персона.ПолучитьИнформер".

from informers import cmnfn

#подключаем из пакета informers модуль cmnfn, с функциями-помощниками
rfmt = cmnfn.getInfFormat()
rs = CreateRecordSet(rfmt)

#new message
inf = CreateRecord(rfmt)
data = {
   'name':'NewMsg',
   'icon':'sprite:icon-16 icon-EmptyMessage icon-primary action-hover',
   'visible':True,
   'tooltip':'Отправить новое сообщение',
   'initModule':'SBIS3.Informers.MsgInit',
   'order':1}
for k,v in data.items():
   inf[k].From(v)
rs.AddRow(inf)

#unread messages
inf = CreateRecord(rfmt)
data={
   'name':'UnreadMsg',
   'tooltip':'Перейти к переписке',
   'className':'informer-short-margin',
   'initModule':'SBIS3.Informers.MsgInit',
   'order':2}
for k,v in data.items():
   inf[k].From(v)
cpt = Персона.СКоличествоНепрочитанных(None, None)
inf['caption'].From((str(cpt) + ' ' + cmnfn.wordCaseByNumber(cpt, ['сообщение', 'сообщения', 'сообщений'])) if (cpt > 0) else '')
inf['visible'].From(True if (cpt > 0) else False)
inf['source'].From([{
   'type': 'event', # событие на клиенте
   'channel':'messages', # имя канала
   'event': 'onMessage' # имя события
}])
rs.AddRow(inf)

return rs

Здесь, метод возвращает в рекордсете описание 2-х информеров — "новое сообщение" (NewMsg) и "непрочитанные сообщения" (UnreadMsg). "Непрочитанные сообщения" слушают событие "onMessage" в канале "messages" на клиенте.

Если информер подписывается на сервисное событие, например, "reclamation.task-added", параметр source.type выглядит следующим образом:

inf['source'].From([{
   'type': 'serverEvent', # сервисное событие
   'channel':'reclamation', # имя сервиса
   'event': 'task-added' # название события (того, что произошло)
}])

Про правила именования серверных событий читать здесь.

Используются следующие хелперы из пакета informers:

МетодОписание
getInfFormatВозвращает RecordFormat с форматом описания информера (см. Таблица 1).
wordCaseByNumberМетод склонения существительных в зависимости от переданного значения.

Конфигурация обработчиков информера для клиентской части приложения

Для обработки событий инициализации, обновления или активации информера на клиентской части приложения, необходимо создать новый JS-модуль, в котором описать обработчики для каждого из событий. Название модуля передают в качестве значения для параметра initModule (см. Таблица 1). Модуль возвращает объект с описанием обработчиков.

Обработчик init на событие инициализации информера

init (informer, config, self) — обработка вызывается после создания компонента информера. Необходима, если нужно выполнить дополнительные действия по готовности информера.

Параметры метода:

  1. informer — активный экземпляр компонента, представляющего собой информер.
  2. config — Record, переданный из метода БЛ, описывающий конфигурацию информера.
  3. self – экземпляр компонента типа "Группа кнопок" с информерами.

Обработчик actionHandler на событие активации информера

actionHandler (informer, config, self) — метод обработки активации информера.

Параметры метода:

  1. informer — активный экземпляр компонента, представляющего собой информер.
  2. config — Record, переданный из метода БЛ, описывающий конфигурацию информера.
  3. self – экземпляр компонента типа "Группа кнопок" с информерами.

Пример кода обработки активании для информеров сообщений:

actionHandler: function (instance, record) {
   switch (record.get('name')) {
      case "NewMsg":
         loadMsgFilesForNotificator().addCallback(function () {
            require(['SBIS3.Contacts.MessagePanel'], function (messagePanel) {
               messagePanel.open();
            });
         });
         break;
      case "UnreadMsg":
         require(['SBIS3.Contacts.FunctionsCommon'], function (fnCommon) {
            fnCommon.showMessageInformer(false, false);
         });
         break;
   }
}

Любая из описанных выше функций может отсутствовать в модуле. В этом случае считается, что обработка действия над информером не нужна. А в случае с методом modify считается, что источник возвращает данные в формате, описывающем состояние информера.

Компонент, используемый в качестве информера – SBIS3.CONTROLS/Menu/MenuLink – кнопка ссылка с поддержкой меню. Чтобы добавить меню, при инициализации (функция init) нужно вызвать метод instance.setItems(menuObject). При задании меню в качестве параметров keyField (поле с ключем) и hierField (поле иерархии) используются значения "id" и "parent" соответственно.

var menuObject = [
   {
      'id': 1,
      'title': 'item 1'
   },
   {
      'id': 2,
      'title': 'item 2'
   },
   {
      'id': 3,
      'parent': 2,
      'title': 'subitem 2.1'
   }
];
ПараметрЗначение
Поле с ключем (keyField)id
Поле иерархии (hierField)parent

Обработчик suctomSubscribe для пользовательской подписки

customSubscribe (informer, config) — вызывается, если в конфигурации в качестве типа источника source.type указан "custom" — собственная подписка на обновление информера.

Параметры метода:

  1. informer — активный экземпляр компонента, представляющего собой информер.
  2. config — Record, переданный из метода БЛ, описывающий конфигурацию информера.

Обработчик modify для данных из источника

modify (informer, config, source, payload) — метод обработки данных из источника для информера. Данный метод должен вернуть новое состояние информера. Состояние описывается следующими параметрами:

  • caption — заголовок;
  • icon — иконка;
  • tooltip — подсказка;
  • visible — видимость.

Параметры метода:

  1. informer — активный экземпляр компонента, представляющего собой информер.
  2. config — Record, переданный из метода БЛ, описывающий конфигурацию информера.
  3. source — объект, описывающий источник данных (см. Таблицу 2).
  4. payload — данные из источника.

Пример кода обработки данных из источника:

modify: function (instance, record, source, data) {
   var res = {};
   if (source.type == 'event' && source.channel == 'messages') {
      if (source.event == 'onMessage') {

         // data — unread number
         res.caption = '';
         if (data) {
            res.caption = [data, ' ', wordCaseByNumber(data, 'сообщений', 'сообщение', 'сообщения')].join('');
            res.visible = true;
         } else {
            res.visible = false;
         }
         return res;
      }
   }
}

Параметры, которые не были возвращены методом modify, оставляют своё прежнее значение. Так, подсказка (tooltip) и иконка (icon) информера из примера останутся прежними после получения данных из источника. Будут обновлены только заголовок (caption) и флаг видимости (visible).

Общий вид JS-модуля без реализации методов

define('SBIS3/MyNamespace/MyInformerInitModule', [], function () {
   return {
      /**
       * инициализация
       * @param instance инстанс информера
       * @param record запись с настройками информера
       */
      init: function (instance, record) {
      },

      /**
       * собственная подписка на обновление (если это указано в настройках информера)
       * @param instance инстанс информера
       * @param record запись с настройками информера
       */
      customSubscribe: function (instance, record) {
      },

      /**
       * обработка данных из источника
       * @param instance инстанс информера
       * @param record запись с настройками информера
       * @param source объект с описанием источника
       * @param data данные из источника данных
       */
      modify: function (instance, record, source, data) {
      },

      /**
       * обработчик активации информера
       * @param instance инстанс информера
       * @param record запись с настройками информера
       */
      actionHandler: function (instance, record) {
      }
   }
});

Обновление данных информеров на клиентской части приложения

Чтобы обновить какие-либо данные информера на клиенте, необходимо использовать связанную с этим информером запись из коллекции. Эта запись передаётся передаётся в параметре config (2-й параметр) в каждый из методов работы с информерами, описанных выше:

  • init (informer, config, self)
  • customSubscribe (informer, config)
  • modify (informer, config, source, payload)
  • actionHandler (informer, config, self)

Формат данных config — см. Таблицу 1. Список изменяемых данных в записи config:

  • caption
  • icon
  • className
  • tooltip
  • visible
  • userData

Если в init-модуле используется собственная подписка, связанную запись можно взять при вызове функции init.

При изменении значения в связанной записи автоматически обновляется соответствующий информер.

Порядок отображения информеров

Параметр order (см. Таблица 1) при описании информера задаёт порядок. Информеры с меньшим значением order выводятся левее информеров с большим значением. Чтобы иметь возможность добавлять новые информеры, не трогая описание старых, порядок лучше делать кратным 10.

Далее приведён текущий список информеров (для компонентов — их старые названия) и их порядок.

Информер/Группа информеровOrder
1. Сообщения, Чаты1 – 9
2. Звонки, Видеозвонки10 – 19
3. SBIS3.NP.InformerEreport20 – 29
4. SBIS3.EDO.AutoSignInformer30 – 39
5. Поощрения/Взыскания40 – 49
6. Напоминалка отпуска50 – 59
7. SBIS3.Reclamations.informer60 – 69
8. Информер лицензии70 – 79
9. Остальные информеры100-...