Синхронизация/интеграция server-side
Событийная
Прямая
Модуль, влияющий на ход исполнения маршрута
Блокирующий процесс
SQL-запрос
Приложение, работающее от имени пользователя по API
Ссылки на модули системы
WEB-модуль, встроенный в ARTA Synergy
Дополнительный обработчик для стандартного процесса ARTA Synergy
Внешние модули-компоненты (ВМК)
Добавление ВМК
События для ВМК
Интеграция с Elasticsearch и Kibana для реализации аналитических дашбордов
Существует два основных подхода для интеграции с Synergy:
Прямая интеграция — интеграционные модули разрабатываются с использованием API Synergy и интегрируемых систем. Синхронизация данных между системами и координация обмена между ними остаётся за разработчиком интеграционного модуля
Событийная интеграция — когда какая-либо из подсистем Synergy генерирует различные события, связанные с какими-либо данными. Обработчики этих событий (на стороне Synergy) при необходимости преобразовывают данные событий и передают их интегрируемой системе через какой-либо транспортный уровень
ARTA Synergy предоставляет API для доступа к своим функциям с
помощью rest сервисов. Описание методов API можно посмотреть в
javadoc. Авторизация для всех
методов API — Basic HTTP
, подробнее о
способах авторизации см.
Способы авторизации в ARTA
Synergy
Под «событием» мы будем подразумевать сообщение о каком-либо
изменении в Arta Synergy, содержащее тип события и минимально
необходимые для получения связанной с событием информации либо
воздействия на Synergy данные. Обработчик события (или
событий) — программный модуль, читающий сообщения о событиях
из JMS Queue
или
JMS Topic
и осуществляющий, при
необходимости, доступ к экземпляру Synergy, сгенерировавшему
сообщение, с помощью API Synergy.
Обработчик событий является отдельным от Arta Synergy приложением, которое может работать как на том же сервере приложений, что и Arta Synergy, так и на удалённом.
Кроме этого, обработчик события может иметь собственные конфигурационные файлы, необходимые для реализации целевого назначения.
Обработчик событий может обрабатывать как конкретное событие
(например, event.registers.formdata.add
),
так и класс событий (например,
event.registers.*
).
Обработка события может происходить в 3 этапа:
Получение события
Получение и преобразование необходимых обработчику данных
Передача сформированного пакета данных далее (опционально)
ARTA Synergy генерирует событие в случае, если для этого
события настроены обработчики. Обработчики событий
настраиваются в конфигурационном файле
${jboss.home}/standalone/configuration/arta/api-observation-configuration.xml
.
Сообщение, помещаемое в очередь JMS
,
представляет собой экземпляр
javax.jms.TextMessage
. Тело сообщения
зависит от типа события, его описание можно посмотреть ниже
среди описаний типов событий. Каждое событие содержит свойство
api_event
, указывающее на тип события,
вызвавшего его (содержимое тега
<event>event.registers.formdata.add</event>
в конфигурационном файле).
Например:
<configuration> <listener> <queue>java:jboss/queues/Synergy/UsersQueue</queue> <event>event.users.*</event> </listener> <listener> <queue>java:jboss/queues/Synergy/RegisterCreateDocQueue</queue> <event>event.registers.formdata.add</event> </listener> </configuration>
В этом примере настроены обработчики:
java:jboss/queues/Synergy/UsersQueue
для всех событий класса event.users.*
,
т.е. всех событий, связанных с пользователятми:
event.users.account.change
,
event.users.formdata.change
,
event.users.account.add
и т.д.
java:jboss/queues/Synergy/RegisterCreateDocQueue
для события добавления записи реестра
event.registers.formdata.add
.
Рассмотрим, например, код обработчика очереди
UsersQueue
:
public class UsersMessagesListener implements MessageListener { public void onMessage(Message message) { //Получаем идентификатор пользователя, для которого //сгенерировано событие String userID = ((TextMessage) message).getText(); //Получаем тип события String eventType = message.getStringProperty("api_event"); //Выполнение действие по получению дополнительных данных через API //и прочих операций, зависящих от условий решаемой задачи } }
Ниже описаны типы событий, которые могут быть сгенерированы ARTA Synergy.
Для события
[event.orgstructure.department.formdata.change]
- идентификатор подразделения, для события
[event.orgstructure.position.formdata.change]
- идентификатор должности, для события
[event.users.formdata.change]
-
идентификатор пользователя будет передаваться как основной
параметр, остальные как свойства. Получить их можно следующим
образом:
public void onMessage(Message message) { //Получение идентификатора пользователя/должности/подразделения (В зависимости от события на которое подписаны) String userID = ((TextMessage) message).getText(); //Получаем идентификатор формы String formUUID = message.getStringProperty("formUUID"); }
Данные события генерируются для каждого из нижеописанных случаев изменения данных пользователей:
[event.users.account.change]
Изменение данных полей первичной
карточки пользователя, т.е. параметров его
учётной записи:
Фамилия
Имя
Отчество
Логин
Код для показателей
JID
Личная папка пользователя
[event.users.formdata.change]
Изменение данных карточек
пользователей на основе
форм, ассоциированных с ним
посредством функциональности «Отдел кадров». Для
данного события передаются следующие данные:
userID
- ID
пользователя
formUUID
-
ID
формы карточки пользователя
dataUUID
-
ID
данных по форме
[event.users.account.add]
Добавление новой записи учётной записи пользователя (и
связанными с ней файлами по формам «отдела кадров»)
[event.users.account.delete]
Удаление (пометка «удалённые») учётной записи
пользователя (и связанных с ней файлов по формам
«отдела кадров»)
[event.users.contactdata.change]
Изменение «контактных данных» пользователя —
изменение/добавление записей раздела «Контакты»
профиля пользователя (модуль «Сотрудники») следующих
типов:
Skype
Рабочий телефон
XMPP
Адрес
Мобильный телефон
Почта
Телефон
Для всех событий типа event.users.*
передаваемые данные — ID
пользователя
Synergy.
Данные события генерируются для каждого из нижеописанных случаев c должностями:
[event.orgstructure.position.add]
Добавление новой должности
[event.orgstructure.position.change]
Изменение данных должности -
добавление/изменение/удаление следующей информации:
Общее:
Название должности (на трех языках)
Код для показателей
Подразделение
Шифр
Необходимое количество штатных единиц
Тип назначения целей
Номер
Управление модулями
Показатели - статус активности
[event.orgstructure.position.formdata.change]
Изменение данных карточки
должности на основе
формы, ассоциированной с ней
посредством функциональности «Отдел кадров». Для
данного события передаются следующие данные:
positionID
-
ID
должности
assistantID
-
ID
заместителя, передается
только при изменении данных карточки заместителя
formUUID
-
ID
формы карточки должности
dataUUID
-
ID
данных по форме
[event.orgstructure.position.delete]
Удаление должности
Для всех событий типа
event.orgstructure.position.*
передаваемые данные - ID
должности
Synergy
.
Данные события генерируются для каждого из нижеописанных случаев c подразделениями:
[event.orgstructure.department.add]
Добавление нового департамента
[event.orgstructure.department.change]
Изменение данных подразделения -
добавление/изменение/удаление следующей информации:
Общее:
Информация о подразделении:
Название (на трех языках)
Номер
Код для показателей
Родительское подразделение (для всех узлов, кроме корневого)
Удаленный филиал
Информация о руководителе подразделения:
Название должности (на трех языках)
Тип назначения целей
Руководитель
И.О. руководителя
Заместители:
Название (на трех языках)
Номер
Пользователь
Подразделения, в которых данный пользователь будет выполнять обязанности заместителя
Управление модулями
Показатели - статус активности
Права на дела:
Наследовать права от родительского подразделения
Дело
Тип документа
Замечание
Ввиду особенностей реализации при сохранении подразделения отдельно сохраняется его карточка, отдельно - заместители. Таким образом, в данном случае событие
event.orgstructure.department.change
будет отправлено дважды, а при изменении заместителей через метод APIrest/api/positions/assistant/save
- единожды.
[event.orgstructure.department.formdata.change]
Изменение данных карточки
подразделения на основе
формы, ассоциированной с ней
посредством функциональности «Отдел кадров». Для
данного события передаются следующие данные:
departmentID
-
ID
подразделения
formUUID
-
ID
формы карточки подразделения
dataUUID
-
ID
данных по форме
[event.orgstructure.department.delete]
Удаление подразделения
Для всех событий типа
event.orgstructure.department.*
передаваемые данные - ID
подразделения
Synergy
.
Событие для реестра не генерируются самостоятельно и не имеют предопределенных названий. Для того, чтобы для реестра было сгенерировано событие, необходимо в процесс активации / изменения / удаления реестра добавить процесс «Событие реестра» и указать в поле «Название» его название.
Название события должно начинаться со строки
event.registries.formdata.
. Для
различных событий и для различных реестров могут быть
указаны разные либо одинаковые названия событий в
зависимости от целей решаемой задачи.
Подробнее о настройке и использовании реестров можно узнать в Руководстве Методолога, раздел Реестры, и Руководстве Пользователя, раздел Реестры.
Объекты адресной книги (люди, организации) могут генерировать следующие события:
[event.addressbook.contact.add]
Добавление нового контакта адресной книги
[event.addressbook.contact.change]
Изменение данных контакта адресной книги: добавление /
изменение / удаление записей карточки контакта.
Событие генерируется при изменении:
данных в дополнительной карточке
данных в стандартной карточке:
«Люди»: ФИО, дата рождения, изображение, телефон, мобильный, e-mail, адрес, IM, URL, место работы, примечание, ключевые слова, поля дополнительной карточки, а также доступность контакта
«Организации»: название, изображение, сайт, адрес, телефон, мобильный, e-mail, поля дополнительной карточки, а также доступность контакта
[event.addressbook.contact.change]
Изменение данных контакта адресной книги
[event.addressbook.contact.delete]
Удаление контакта адресной книги
Для всех событий типа
event.addressbook.contact.*
передаваемые данные - это ID
контакта
адресной книги Synergy.
Итерационные задачи по реализации: AB1.
[event.workflow.work.create]
Создание работы
[event.workflow.work.change]
Изменение следующих параметров работы:
название
нагрузка
приоритет
сроки
ключевые слова
повторение
форма завершения
прогресс
[event.workflow.work.completion]
Фактическое завершение работы
[event.workflow.work.expired]
Работа просрочилась
[event.workflow.work.delete]
Удаление работы
Примечание
При добавлении/изменении/удалении комментария к работе, аналогичное событие для документов в очередь не добавляется.
Для события
[event.workflow.work.expired]
используется системная настройка «Интервал проверки работ
на просроченность (в минутах)» (Конфигуратор ->
Настройки системы -> Параметры уведомлений)
Минимальный набор передаваемых данных для всех событий
типа event.workflow.work.*
:
идентификатор работы
Если работа запускается по реестру, то также обязательно передаются:
идентификатор данных по форме записи реестра (свойство
с ключом dataUUID
)
идентификатор документа реестра (свойство с ключом
documentID
)
В случае, если генерируется любое событие по работе,
порожденной мероприятием проекта, в свойствах сообщения
(ключ ArrangementID) передается идентификатор этого
мероприятия (ParentID
).
Для работ по процессу «работа по форме» (вызванного как непосредственно из маршрута реестра, так и из шаблона маршрута), кроме всего прочего, также передаются данные из дополнительных полей, настроенных непосредственно в самом процессе «работа по форме».
[event.projects.arrangement.create]
Создание мероприятия проекта
[event.projects.arrangement.delete]
Удаление мероприятия проекта
[event.projects.arrangement.restore]
Восстановление мероприятия проекта
[event.projects.arrangement.responsibles]
Фактическое изменение списка ответственных за
мероприятие проекта
Примечание: событие изменения списка ответственных не включает случаи, когда выбранному ответственному создается работа-запрос стать ответственным и когда он отказывает в этом запросе. Таким образом, учитывается только фактическое назначение ответственного за мероприятие проекта.
[event.projects.arrangement.progress]
Выставление прогресса мероприятия
Минимальный набор передаваемых данных для всех событий
типа event.projects.arrangement.*
- это
идентификатор мероприятия проекта.
[event.docflow.document.register]
Регистрация документа в журнале
Минимальный набор передаваемых данных в сообщении для
события
[event.docflow.document.register]
-
идентификатор документа.
В свойствах сообщения (ключ registerID
)
передаётся идентификатор журнала.
Итерационные задачи по реализации: AS35.
[event.form.formdata.change]
Создание и сохранение данных по форме
Минимальный набор передаваемых данных в сообщении для
события [event.form.formdata.change]
:
dataUUID - идентификатор данных по форме;
formID - идентификатор формы;
isNew - сохранены ли данные:
true - новые;
false - существующие.
В свойствах сообщения (ключ dataUUID
)
также передаётся идентификатор данных по форме.
Данные события генерируются для каждого из нижеописанных случаев:
Комментарии к работе
[event.comment.work.add]
Добавление
нового комментария к работе
[event.comment.work.change]
Изменение комментария к работе
[event.comment.work.delete]
Удаление комментария к работе
Примечание
При добавлении/изменении/удалении комментария к работе, аналогичное событие для документов в очередь не добавляется.
Комментарии к документу
[event.comment.document.add]
Добавление нового комментария к документу
[event.comment.document.change]
Изменение комментария к документу
[event.comment.document.delete]
Удаление комментария к документу
Личные комментарии
[event.comment.personal.add]
Добавление нового личного комментария
[event.comment.personal.change]
Изменение личного комментария
[event.comment.personal.delete]
Удаление личного комментария
Комментарии к проекту/мероприятию
[event.comment.action.add]
Добавление нового комментария к мероприятию проекта
[event.comment.action.change]
Изменение комментария к мероприятию проекта
[event.comment.action.delete]
Удаление комментария к мероприятию проекта
Для всех событий типа event.comment.*
передаваемые данные зависят от типа комментария и выглядят
следующим образом:
Комментарий к работе:
идентификатор комментария (свойство с ключом
message text
)
идентификатор автора комментария (свойство с
ключом userID
)
идентификатор документа (свойство с ключом
documentID
)
идентификатор работы (свойство с ключом
actionID
)
Комментарий к документу:
идентификатор комментария (свойство с ключом
message text
)
идентификатор автора комментария (свойство с
ключом userID
)
идентификатор документа (свойство с ключом
documentID
)
Личный комментарий:
идентификатор комментария (свойство с ключом
message text
)
идентификатор автора комментария (свойство с
ключом userID
)
идентификатор документа (свойство с ключом
documentID
)
идентификатор работы (свойство с ключом
actionID
)
Комментарий к мероприятию:
идентификатор комментария (свойство с ключом
message text
)
идентификатор автора комментария (свойство с
ключом userID
)
идентификатор проекта (свойство с ключом
projectID
)
идентификатор мероприятия (свойство с ключом
actionID
)
Примечание
В случае, если объектом события является комментарий к проекту, то параметры projectID и actionID будут равны.
Итерационные задачи по реализации: 0345
В ARTA Synergy имеется метод API, позволяет генерировать произвольные события.
URL
метода:
rest/api/events/create
. Типа запроса:
POST
.
Метод принимает следующие обязательные параметры:
eventName
- название события
(строка);
eventMsg
- произвольный
json
(строка).
В случае успешного выполнения метода сервер вернет сообщение «Событие успешно сгенерировано».
Пример:
Событие, генерируемое мобильным клиентом по координатам
GPS
:
eventName=event.ext.gps&eventMsg={"lat":333.333,"lon":222.222}
Итерационные задачи по реализации: API41.
Блокирующий процесс предназначен для того, чтобы предоставить возможность в маршрут активации/изменения/удаления реестра вставить асинхронный вызов внешнего модуля. Основное отличие блокирующего процесса от события реестра (см. События реестров) заключается в том, что:
при использовании блокирующего процесса маршрут реестра дожидается ответа о результате выполнения операции внешним модулем
блокирующий процесс может завершиться положительно или отрицательно, что повлияет на дальнейшую работу маршрута (Если блокирующий процесс завершится отрицательно — процесс остановится, если положительно — то продолжит работу дальше)
Модуль, реализующий блокирующий процесс, должен представлять собой отдельное приложение, задеплоенное на jboss в соответствии с правилами, описанными в разделе Как задеплоить интеграционное приложение.
Запускается код модуля блокирующего процесса через очередь. При старте этапа маршрута, содержащего блокирующий процесс, в очередь добавляется сообщение, которое должен обработать модуль.
Конфигурация блокирующего процесса:
Для того, чтобы добавить блокирующий процесс, необходимо выполнить следующие действия:
Добавить процесс с в маршрут реестра в конфигураторе:
Название процесса должно начинаться с
event.blocking.
и далее строка,
характеризующая суть блокирующего процесса.
Создать очередь JMS для блокирующего процесса. Для этого
необходимо в конфигурационный файл
jboss
(в стандартной установке это
/opt/synergy/jboss/standalone/configuration/standalone-onesynergy.xml
)
в секцию
<subsystem xmlns="urn:jboss:domain:messaging:1.2">
добавить:
<jms-queue name="ExampleQueue"> <entry name="java:jboss/queues/Integration/ExampleQueue"/> <durable>true</durable> </jms-queue>
Связать очередь и процесс через конфигурационный файл
{$jboss.home}/standalone/configuration/arta/api-observation-configuration.xml
,
добавив в него следующее:
<listener> <queue>java:jboss/queues/Integration/ExampleQueue</queue> <event>event.blocking.example</event> </listener>
Обратите внимание, что название блокирующего процесса,
указанное в маршруте в конфигураторе должно быть равно
значению тега в конфигурационном файле
api-observation-configuration.xml
(в данном
примере: event.blocking.example
) и название
очереди должно совпадать со значением тега
queue
конфигурационного файла
api-observation-configuration.xml
(в данном
примере:
java:jboss/queues/Integration/ExampleQueue
)
Сообщение, передаваемое в очередь, является экземпляром
TextMessage
. Содержимым сообщения является
объект JSON с полями:
dataUUID — идентификатор данных по форме записи реестра
executionID — идентификатор блокирующего процесса
documentID — идентификатор документа реестра
После того, как модуль обратится к внешней системе и выполнит
необходимые действия, он должен вызвать метод API Synergy для
того, чтобы возвратить результат выполнения процесса и
продолжить работу маршрута. Для того, чтобы это сделать,
необходимо вызвать метод API
kz.arta.synergy.samples.processes.blocking.ProcessesService#signalProcess
.
Примечание:
Сигнал блокирующему процессу (API - signalProcess) для его разблокировки/блокировки нужно отправлять после того, как этот процесс был запущен, то есть после того как транзакция с запуском процесса была завершена. Для этого, перед отправкой сигнала, проверяйте на наличие такого процесса в БД. В противном случае, блокирующий процесс может завершиться в транзакции, но в маршруте нет.
В примере кода ниже разблокировка маршрута осуществляется в методе
onMessage
. Если время выполнения действия значительно или зависит от внешних факторов (например, доступность интегрируемой системы, или необходимость ввода пользователем данных в интегрируемой системе), то разблокировка маршрута может произойти позже, в любой другой момент времени из другого метода, а сам метод onMessage должен завершиться без ошибок, «запомнив» переданные параметры.
package kz.arta.synergy.samples.processes.blocking; import com.sun.org.apache.xerces.internal.impl.dv.util.Base64; import org.codehaus.jackson.JsonFactory; import org.codehaus.jackson.JsonParser; import org.codehaus.jackson.JsonToken; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.jms.Message; import javax.jms.MessageListener; import javax.jms.TextMessage; import java.io.BufferedReader; import java.io.InputStreamReader; import java.net.HttpURLConnection; import java.net.URL; /** * <p><Пример блокирующего процесса</p> */ public class BlockingQueueListener implements MessageListener { public void onMessage(Message message) { String dataUUID = null; String executionID = null; String documentID = null; if (!(message instanceof TextMessage)){ return; } try { JsonFactory factory = new JsonFactory(); JsonParser parser = factory.createJsonParser(((TextMessage) message).getText()); JsonToken token = null; while ((token = parser.nextToken()) != null) { if (token == JsonToken.FIELD_NAME) { String fieldName = parser.getText(); parser.nextToken(); String value = parser.getText(); if (fieldName.equals("dataUUID")){ dataUUID = value; } else if (fieldName.equals("executionID")){ executionID = value; } else if (fieldName.equals("documentID")){ documentID = value; } } } //Выполнение каких-либо действий …....... //Разблокировка маршрута String address = "http://127.0.0.1:8080/Synergy"; String login = "1"; String password = "1"; String signal = "got_agree"; boolean isSuccess = false; try { URL url = new URL(address + "/rest/api/processes/signal?signal=" + signal + "&executionID=" + executionID + "¶m1=resolution&value1=signal_is_" + signal); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setRequestMethod("GET"); conn.setRequestProperty("Accept", "application/json; charset=utf-8"); String encoded = Base64.encode((login + ":" + password).getBytes()); conn.setRequestProperty("Authorization", "Basic " + encoded); String output; StringBuffer result = new StringBuffer(); BufferedReader br = new BufferedReader(new InputStreamReader((conn.getInputStream()))); while ((output = br.readLine()) != null) { result.append(output); } conn.disconnect(); JsonFactory factory = new JsonFactory(); JsonParser parser = factory.createJsonParser(result.toString()); JsonToken token = null; while ((token = parser.nextToken()) != null) { if (token == JsonToken.FIELD_NAME) { String fieldName = parser.getText(); token = parser.nextToken(); if (fieldName.equals("errorCode") && parser.getText().equals("0")){ isSuccess = true; } } } } catch (Exception exc){ logger.error(exc.getMessage(), exc); } } catch (Exception exc){ logger.error(exc.getMessage(), exc); } } }
Ссылки на модули и различные объекты Synergy можно использовать как внутри основного web-приложения (в этом случае предпочтительно использовать относительные ссылки, чтобы не перезагружать страницу), так и во внешних системах.
Общий вид ссылок:
http[s]://host[:port]/Application?param1=value1¶m2=value2#param3=value3¶m4=value4
где
host - доменное имя или ip-адрес сервера Synergy
port - порт
Application:
Synergy
- основное приложение
Configurator
- Конфигуратор
SynergyAdmin
- административное
приложение
param1, param2 - параметры абсолютной ссылки
param3, param4 - параметры относительной ссылки
Параметры абсолютной ссылки - это, как правило:
locale
- локаль загружаемой системы
nocache
- специальный параметр,
предотвращающий случайное кэширование
остальные параметры можно передавать как параметры относительной ссылки.
Ниже для краткости будем приводить образец относительной ссылки
#submodule=module_id
где module_id
:
workflow
- Потоки работ
calendar
- Ежедневник
repository
- Хранилище
plans
- Проекты
pointers
- Цели и показатели
employees
- Сотрудники
При переходе по ссылке откроется указанный модуль.
#submodule=common&file_identifier=some_file_id&action=open_document&document_identifier=some_doc_id
При переходе по такой ссылке откроется указанный документ с
основным файлом, а если указан
file_identifier
- то откроется документ с
этим файлом.
#submodule=plans&action=open_action&action_identifier=some_action_id&project_identifier=some_project_id
При переходе по такой ссылке откроется указанный проект, а
если указан action_identifier
- то в
проекте будет выделено это мероприятие.
#submodule=employees&innermodule=structure&action=open_user&user_identifier=some_user_id
При переходе по такой ссылке будет открыт модуль «Сотрудники», а в нем - профиль указанного пользователя
Если в абсолютной ссылке указать параметр
noCustomScripting
, то все
пользовательские ВМК, скрипты в формах и пользовательских
компонентах будут отключены. Это можно использовать для
отладки пользовательских компонентов, ВМК и скриптов на
форме.
Web-приложение внешнего модуля открывается в
iframe
в окне основного приложения. При этом
рабочая область внешнего модуля занимает всю область страницы,
кроме панели меню и панели задач:
На данный момент существует пользовательский интерфейс для добавления нового модуля. Для этого нужно перейти в Конфигуратор -> Настройки системы -> Управление модулями -> Внешние модули и нажать на кнопку «Добавить».
В открывшемся окне нужно заполнить следующие поля:
«Идентификатор» - поле должно содержать уникальное значение.
«Название на русском/казахском/английском языке» - название модуля в соответствующем интерфейсе.
«Адрес приложения» - поле для ввода URL.
«Описание модуля» - поле для описания данного модуля.
«Иконка» - задает иконку модуля в пользовательской подсистеме (по умолчанию внешний модуль имеет стандартную иконку). Для того, чтобы изменить стандартную иконку, нужно кликнуть по кнопке «Выберите файл» и в диалоге выбора файла указать файл формата PNG, размер которого не превышает 28х26.
Однако, если необходимо, это можно сделать с помощью SQL-запроса
в таблицу outer_modules
, вставив запись со
следующими полями:
id
— идентификатор модуля, должен
совпадать с идентификатором вашего проекта в репозитории
проектов
nameru
, namekz
,
nameen
— название модуля на русском,
казахском и английском языках соответственно
url
— адрес приложения
description
— описание модуля
active
— активен ли модуль, 1/0.
Для реализации SSO
приложений, ARTA Synergy
при загрузке интегрированного модуля будет в строку URL
добавлять три параметра:
locale
— локаль авторизованного
пользователя
sso_hash
— hash-сумма для идентификации
пользователя.
host
— адрес, с которого загружено
приложение Synergy
Например, если URL приложения
http://host:port/plans_module
, то
запрашиваться будет URL
http://host:port/plans_module?locale=locale_value&sso_hash=sso_hash_value
Интегрированный модуль должен будет будет получить из URL
параметр sso_hash
и запросить по API у ARTA
Synergy информацию об авторизованном пользователе
(идентификатор, имя). Если метод API возвращает информацию о
пользователе, это подтверждает, что данный пользователь
действительно авторизован с данного хоста, в данном браузере.
Далее строка sso_hash
будет использована для
Сессионной
авторизации и вызова API Arta Synergy.
В ARTA Synergy реализована возможность обращения к ее модулям по относительной ссылке. Такая же возможность существует для внешних web-модулей. Переход по ссылке вида:
#submodule=outer&outerModuleID=
значение_из_таблицы_outer_modules
&
прочие_параметры_по_желанию_модуля
активирует в Synergy заданный модуль и передаст ему заданные в
url-e параметры (параметры locale
,
sso_hash
, host
также будут
переданы, несмотря на то, что они отсутствуют в ссылке).
Часто возникает необходимость в этой ссылке передать ссылку на
текущий документ. Для этого можно добавить в ссылку параметр,
значение которого будет равно ${docID}
— эта
строка в web-интерфейсе просмотрщика форм Synergy будет заменена
на идентификатор данного документа.
Цель данного вида интеграции — дать возможность проверить возможность запуска стандартного процесса и, при необходимости, прервать его.
Стандартный функционал платформы ARTA Synergy
дает возможность запретить отправку документов на согласование,
утверждение, если количество уровней оргструктуры между
отправителем и получателем превышает некоторое настроенное
значение. Но в некоторых компаниях существуют более сложные
правила, ограничивающие возможность отправки документов/работ. В
этих случаях необходима разработка данного обработчика.
Обработчик может быть применён к процессам:
«работа» (assignment-single
)
«согласование» (agreement-single
)
«утверждение» (approval-single
)
«ознакомление» (acquaintance-single
)
«отправка документа» (send-document
)
«общий процесс при запуске по формам»
(common-process-by-form
)
«отправка документа по форме»
(send-document-by-form
)
Обработчик представляет собой Java-класс, реализующий интерфейс
kz.arta.synergy.integration.api.bp.StartHandlerIF
.
Данный интерфейс находится в библиотеке
integration-api.jar
, которую можно взять
здесь:
svn://scm.forge.arta.local/svnroot/synergy/trunk/build/artifacts/integration-api.jar
Примечание.
Начиная с итерации 66 данная библиотека входит в стандартный пакет
arta-synergy-synergy
. Она лежит в папке/opt/synergy/jboss/standalone/deployments/Synergy.ear/lib
.
Интерфейс содержит два метода:
makeDecision
— проверяет возможно ли
выполнение процесса
getResolution
— возвращает текст, который
должен быть записан в ход исполнения
Более подробную информацию о полях методов можно посмотреть в
javadoc
к этим методам, которые доступны в
integration-api.jar
(библиотека содержит и
скомпилированные классы, и исходный код).
Установка обработчика для процесса осуществляется с помощью
конфигурационного файла
${jboss.server.config.dir}/arta/process-handlers-configuration.xml
,
имеющего следующий формат:
<?xml version="1.0" encoding="UTF-8"?> <process-handlers-configuration xmlns="http://www.arta.kz/xml/ns/ai" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.arta.kz/xml/ns/arta http://www.arta.kz/xml/ns/ai/process-handlers-configuration .xsd"> <handlers> <handler> <process>assignment-single</process> <handler-providers>kz.arta.synergy.ext.blocking.SendControlHandler</handler-providers> </handler> <handler> <process>agreement-single</process> <handler-providers>kz.arta.synergy.ext.blocking.SendControlHandler</handler-providers> </handler> <handler> <process>approval-single</process> <handler-providers>kz.arta.synergy.ext.blocking.SendControlHandler</handler-providers> </handler> <handler> <process>acquaintance-single</process> <handler-providers>kz.arta.synergy.ext.blocking.SendControlHandler</handler-providers> </handler> <handler> <process>send-document</process> <handler-providers>kz.arta.synergy.ext.blocking.SendControlHandler</handler-providers> </handler> </handlers> </process-handlers-configuration>
Обработчики выполняются последовательно до тех пор, пока метод
makeDecision
одного из них не вернет
false
, после этого процесс прерывается.
Библиотеку, содержащую обработчик необходимо скопировать в папку
/opt/synergy/jboss/standalone/deployments/Synergy.ear/lib
.
После копирования библиотеки обработчика и изменения файла
process-handlers-configuration.xml
JBoss
необходимо перезапустить.
Примечание. Процесс
common-process-by-form
запускает процессы
agreement-single
,
approval-single
,
acquaintance-single
,
assignment-single
(подпроцессы). Поэтому,
если обработчик будет запрещать выполнение подпроцесса и при
этом разрешать выполнение процесса
common-process-by-form
, то подпроцессы все
равно будут прерваны. Аналогично, если выполнение
common-process-by-form
разрешено, а
выполнение подпроцесса запрещено, подпроцессы будут прерваны.
Пример использования
С использованием этого способа интеграции был реализован внешний модуль, ограничивающий перепоручение и отправку каких-либо работ на согласование пользователям определенных групп.
Для установки внешнего модуля из репозитория необходимо
установить пакет
arta-synergy-ext-sendcontrol
.
Далее на остановленном JBoss
в
конфигурационном файле
${jboss.server.config.dir}/arta/process-handlers-configuration.xml
необходимо прописать следующие обработчики процесса:
<?xml version="1.0" encoding="UTF-8"?> <process-handlers-configuration xmlns="http://www.arta.kz/xml/ns/ai" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.arta.kz/xml/ns/arta http://www.arta.kz/xml/ns/ai/process-handlers-configuration .xsd"> <handlers> <handler> <process>assignment-single</process> <handler-providers>kz.arta.synergy.ext.blocking.SendControlHandler</handler-providers> </handler> <handler> <process>agreement-single</process> <handler-providers>kz.arta.synergy.ext.blocking.SendControlHandler</handler-providers> </handler> </handlers> </process-handlers-configuration>
Установка групп (каким группам пользователей Synergy) разрешать
либо блокировать процессы осуществляется с помощью
конфигурационного файла
${jboss.server.config.dir}/arta/ext/send-control.xml
.
Пример настройки:
<?xml version="1.0" encoding="UTF-8"?> <send-control> <!-- Идентификаторы групп, членам которых разрешено отправлять что-либо из блоков `deny` --> <from> <allow>35</allow> </from> <!-- Идентификаторы групп, членам которых могут отправлять что-либо только пользователи групп из блоков `allow`, если таковые есть. В противном случае, никто ничего этим пользователям отправить не сможет. --> <to> <deny comment="Вы не можете отправлять что-либо на согласование данному пользователю">111</deny> </to> </send-control>
private link > Примечание > > В этом примере настроено, что перепоручение и отправка на согласование > возможны только от пользователей группы «35» пользователям группы «111». > При попытке выполнения указанных действий пользователям, не входящим в > группу «111», система отобразит указанную ошибку.
Интеграция с помощью внешнего-модуля компонента предназначена для добавления или замены каких-либо элементов пользовательского web-интерфейса ARTA Synergy. Для этого необходимо описать пользовательский компонент, который и будет служить внешним модулем-компонентом, а затем указать для него место размещения и способ вставки.
Для настройки пользовательских компонентов методологу нужно во вкладке «Процессы» конфигуратора выбрать пункт «Пользовательские компоненты».
Настройка пользовательских компонентов включает в себя настройку следующих полей:
«Название» - название пользовательского компонента, является обязательным полем;
«Исходный код» - код компонента, написанный
на HTML/CSS
. Можно также добавить сюда
и код на javascript
, но делать этого не
рекомендуется, т.к. для js
вызывать
функции отсюда будет сложнее. Для написания скрипта
следует использовать поле «Исходный код
скрипта»;
«Исходный код скрипта» - код скрипта,
написанный на javascript
, с помощью
которого можно настроить содержимое компонента,
обратившись к существующим в системе API, описание которых
можно посмотреть в javadoc
и воспользовавшись возможностью обработать необходимые
клиентские события. Для этого нужно вызвать функцию
$EVENT_BUS.subscribe()
и указать ей в
качестве параметров необходимое событие и функцию, которую
это событие обрабатывает.
$EVENT_BUS.subscribe(new EventHandler
('WORK_USERS_CHANGED', handlerUsersSelected));
Также объект EVENT_BUS
позволяет
отписываться от событий и создавать новые. Для возможности
указания новых событий необходимо обратиться к центру
решений.
«Строгий режим» JavaScript:
Начиная с версии Synergy 3.14, все пользовательские скрипты выполняются с добавлением директивы
use strict
. Эта директива означает, что соответствующий ей код будет выполнятся в так называемом «строгом режиме», поддерживающем стандартJavaScript
ECMAScript5.
Примечание:
Если код скрипта содержит конструкции, не соответствующие стандарту ES5, то они не будут выполняться. Это не является ошибкой Synergy.
Использование пользовательских компонентов как полей формы
В общем случае пользовательские компоненты не участвуют в местах, где могут использоваться какие-либо другие компоненты формы:
отсутствует в полях формы реестра;
отсутствует в фильтрах реестра;
не учитывается при поиске в реестре;
не участвует в сортировке реестра;
отсутствует во всех видах сопоставлений;
не учитывается во всех спец.процессах (например, в условном переходе).
Для того, чтобы пользователький компонент присутствовал в
сопоставлениях, необходимо, чтобы в его модели были
реализованы методы setAsfData
и
getAsfData
(см.
«Создание
нового компонента»), а также чтобы возвращалась
структура компонента вида:
{ "id": "id", "type": "type", "value": "value", "key": "key" }
Для снятия остальных ограничений достаточно реализации метода
getAsfData
и корректности возвращаемой
структуры.
Пример:
В качестве примера расмотрим реализацию пользовательского компонента «Load info», который показывает перегруженных сотрудников при создании работы (данный компонент входит в стандартную поставку Synergy).
Итерационные задачи по реализации: 0193: Компонент предупреждение о перегрузке
Исходный код содержит следующий простой
HTML
код:
<!-- Определим добавляемый элемент, указав для него необходимый стиль. --> <span id = "workloadLable" style="color:red; padding-top: 10px"> </span> <!-- За содержимое элемента будет отвечать исходный код скрипта. -->
Исходный код скрипта устроен более сложным образом. Рассмотрим
реализацию функции получающей данные из
api
:
function ajaxUserWL(ar){ // Функция filtrAr() исключает из массива повторения пользователей. ar = filtreAr(ar); // Используем массив, который подходит под формат `json`, определенный в `api`. // Данный формат необходимо всегда уточнять в javadoc. var req = []; for (var i = 0; i < ar.length; i++){ var r = {userID: ar[i].userId, startDate: getCurrentDateFormated(), finishDate: getCurrentDateFormated()}; req.push(r); } // Вызываем функцию, которая для пользователей из массива req, вызовет // api, возвращающую их загруженность. Перегруженные пользователи // добавляются в массив res и формируют содержимое HTML тага. jQuery.ajax({ // Вызов необходимого api. url: 'rest/person/workload/m', type: 'post', data: JSON.stringify(req), contentType: 'application/json', dataType: 'json', // Функция осуществляет проверку на перегруженность и помещает таких // сотрудников в массив res success: function (data) { res = []; for (var i = 0; i < ar.length; i++) { var user = data[ar[i].userId]; if (user == null) { continue; } for (var j = 0; j < user.length; j++) { // Проверка на перегруженность. if (parseFloat(user[j].value) > 100) { res.push(ar[i]); } } } // Функция определяет формат, в котором будет выводиться инофрмация. overloadUsers(res); } }); }
Итерационные задачи по реализации: 0195: API получения нагрузки
Замечание:
Полную реализацию компонента можно посмотреть в настройках пользовательских компонентов, выбрав компонент «Load info».
Замечание:
Для API, находящихся по
URL
rest/%api/method%, авторизация будет происходить по куки (как в браузере), поэтому его можно вызывать авторизованному в Synergy пользователю. Для API, находящихся по другим адресамURL
, необходимо настроить процесс авторизации (см. Способы авторизации). Сделать это можно например так: вызвать API по адресуhttps://%логин%:%пароль%@%адрес/метода/api%
Для того, чтобы выбрать, где использовать пользовательский компонент, методологу необходимо во вкладке «Процессы» выбрать пункт «Внешние модули-компоненты» и добавить новый внешний модуль-компонент.
Настройка внешнего модуля-компонента включает в себя настройку следующих полей:
«Название» - название внешнего модуля-компонента, является обязательным полем;
«Место размещения» - выбрать один из доступных вариантов для указания места, в котором будет находиться пользовательский компонент. На данный момент доступны следующие альтернативы:
«onLoad» - пользовательский компонент будет выводиться при загрузке приложения;
«Depricated» - место, используемое для вывода пользовательских компонентов в старых версиях, не рекомендуется к применению;
«BPM/Workflow/Create/Work» - пользовательский компонент будет выводиться в диалоговом окне создания работы;
«Shell/TopPanel/Right» - пользовательский компонент будет выводиться на верхней панели оболочки Synergy, левее поля «Поиск».
Для размещения пользовательского компонента в новом месте необходимо его запрашивать у центра решений (в качестве доработки API).
«Название пользовательского компонента» - выбрать один из доступных вариантов пользовательских компонентов, настроенных ранее;
«Тип вставки» - выбрать один из доступных вариантов:
«ADD» - добавляет тег пользовательского компонента к тегу места размещения;
«REPLACE» - удаляются потомки тега места размещения и в него помещается пользовательский тег (замена всех потомков тега места размещения).
Для работы ВМК в Synergy реализована отправка событий в JS EventBus.
Пример использования события из нового проигрывателя форм в JS:
AS.FORMS.bus.on(AS.FORMS.EVENT_TYPE.formShow, function (event, model, view) { var calendarModel = model.getModelWithId('cmp-1'); //Передается идентификатор компонента calendarModel.on(AS.FORMS.EVENT_TYPE.valueChange, function () { var value = calendarModel.getValue(); console.log(value); }); });
Ниже описаны параметры для каждого события.
WORK_USERS_CHANGED - изменены исполнители работы в диалоге создания работы.
в качестве аргумента передается список выбранных пользователей в виде массива JSON с полями: userId, lastname, firstname, patronymic
добавлено в версии 3.0
WORK_DIALOG_UPDATE - обновлен диалог создания работы.
в качестве аргумента передается список выбранных пользователей в виде массива JSON с полями: userId, lastname, firstname, patronymic
добавлено в версии 3.0
SETTINGS_LOADED - загружены настройки приложения.
в качестве аргумента передается null
добавлено в версии 3.3
DEPARTMENT_ENTITY_CHANGED - подразделение обновлено в компоненте формы.
в качестве аргумента передается JSON с полями id и values
values - массив JSON с полями: value - отображаемое имя, key - идентификатор пользователя
добавлено в версии 3.6
FORM_LOADED - компоненты формы прорисованы
в качестве аргумента передаётся пустой JSON объект с полем dataID.
добавлено в версии 3.6
Пример использования события в JS:
$EVENT_BUS.subscribe(new EventHandler('FORM_LOADED', handlerUsersSelected)); function handlerUsersSelected(event, args) { console.log("event FORM_LOADED"); var component = jQuery('img#image_for_portlet'); if (component === null || component.length === 0) { console.log("no success"); return; } console.log("success!!"); console.log(component.parentNode); console.log(component); var mySpan = document.createElement("div"); mySpan.innerHTML = "<div id='portlet_div' ><iframe frameborder = "0" height = "100%" id = "portlet1" src = "http://192.168.2.119:8080/widget/web/guest/home/-/meetups" width = "100%" > </iframe ></div > "; component.replaceWith(mySpan.innerHTML); } var checkAgain = function() { setTimeout(handlerUsersSelected, 5000); };
REGISTRY_SELECTED - нажата кнопка «Создать», когда в навигаторе выделен активный реестр.
в качестве аргумента передаётся JSON объект вида:
registryCode:"reg_code" registryId:"9034810f-5f18-44b9-948a-8f78a5f1ec9d"
добавлено в версии 3.14
Кроме того, атрибуты registryCode
и
registryId
содержатся в элементе списка
реестров, например:
<table cellspacing="0" cellpadding="0" synergytest="RegistryTreeElement" registryid="82356e07-a859-49cc-8adf-896c32725810" registrycode="Заявление_о_приеме_на_работу_(вариант_2,_на_двух_языках)" style="display: inline;" class="commonLabelBold"> <colgroup> <col> </colgroup> <tbody> <tr> <td>007 Заявление о приеме на работу на период</td> <td style="white-space: nowrap;"></td> </tr> </tbody> </table>
USER_CHOOSER_CREATED - обновлено тэговое поле выбора пользователя в диалоге.
в качестве аргумента передаются два параметра: событие и объект, содержащий ссылку на компонент выбор пользователя (в поле args).
добавлено в версии 3.12 Tengri
Пример обработчика события добавления компонента выбора пользователя, который выводит идентификатор компонента в консоль браузера:
function onUserChooserCreated(evt, chooser){ var id = getUserChooserId(chooser.args); console.log(id); }
Оперировать компонентом выбора пользователя можно следующими функциями:
getUserChooserId(chooserComponent)
-
получение идентификатора компонента выбора пользователя;
getUserChooserShowAll(chooserComponent)
- получение настройки «Разрешить добавлять
соисполнителей к работам, не являющихся
подчиненными»
setUserChooserSelectedIds(chooserComponent, arrayOfUsersIds)
- выбрать переданных пользователей;
getUserChooserSelectedIds(chooserComponent)
- получить идентификаторы выбранных пользователей.
Идентификаторы компонентов выбора пользователя:
Диалог создания работы создания работы:
исполнитель - editWorkUserChooser
ответственные -
editWorkResponsibleUserChooser
автор - editWorkAuthorUserChooser
Отправить-> переслать:
адресаты -
sendDocumentUserChooser
Отправить -> перепоручить:
исполнитель -
assignmentSendUserChooser
ответственные -
assignmentSendResponsibleUserChooser
Отправить на согласование, утверждение, ознакомление:
адресаты - sendWorkUserChooser
Отправить по маршруту:
ответственный -
editRouteSendDialog
все остальные компоненты будут иметь идентификатор
userChooser
.
В каждый DOM элемент компонента выбора пользователя
добавляется атрибут userchooser
со
значением идентификатора компонента выбора пользователя.
Основные требования и некоторые детали задачи описаны в соответствующей постановке: «Скриптинг в формах»
В данном же документе описываются все используемые для скриптинга модели, свойства и методы.
Примеры использования скриптинга см. здесь.
Используемые технологии и библиотеки:
jQuery
Underscore
- утилиты
Backbone
- UI компоненты
Marionette
- UI компоненты
jQuery ui
- UI компоненты
math.js
- поддержка математики больших
чисел
base64.js
- добавляет методы btoa, atob
для браузеров, в которых их нет (в частности IE 9, 10)
XregExp.js
- поддержка более сложных
регулярных выражений
Схемы работы проигрывателя:
Общедоступные объекты:
AS
- общее пространство имен
AS.FORMS
- формы
AS.COMPONENTS
- компоненты, которые могут
быть использованы отдельно от проигрывателя форм
AS.SERVICES
- сервисы
AS.LOGGER
- логгер
AS.OPTIONS
- настройки
AS.DICTIONARIES
- кэш справочников
Типы событий:
formShow : 'formShow'
- отображение формы
(построение новой формы)
formDestroy : "formDestroy"
-
метод
destroy
модели проигрывателя
dataLoad: 'dataLoad'
- подгрузка данных
valueChange: 'valueChange'
- изменение
значения модели
markInvalid : 'markInvalid'
-
необходимость отображению подсветить невалидное значение
tableRowAdd: 'tableRowAdd'
- добавление
ряда в таблице
tableRowDelete: 'tableRowDelete'
-
удаление ряда в таблице
dictionaryLoad : 'dictionaryLoad'
-
подгрузка справочника
tagEdit : 'tagEdit'
- редактирование тега
tagDelete : 'tagDelete'
- удаление тега
loadComponentAdditionalInfo : 'loadComponentAdditionalInfo'
- подгрузка дополнительной информации компонента (сейчас
используется для пользовательского компонента)
Особенности реализации:
В области видимости скрипта (добавленный как к компоненту, так и пользовательскому компоненту) имеются следующие переменные:
model
- модель текущего компонента;
view
- отображение текущего компонента;
editable
- режим (просмотр /
редактирование);
model.playerModel
- модель проигрывателя;
view.playerView
- отображение
проигрывателя.
Скрипт (добавленный как к компоненту, так и пользовательскому компоненту) выполняется каждый раз при смене режима проигрывателя (просмотр - редактирование). При этом модель компонента остается та же, а отображение компонента каждый раз пересоздается. Поэтому при написании скриптов следует учесть следующее: если добавляются или переписываются методы модели, либо происходит подписывание на события другой модели, то рекомендуется использовать следующее:
if (!model.inited) { //манипулирование моделями model.inited = true; }
«Строгий режим» JavaScript:
Начиная с версии Synergy 3.14, все пользовательские скрипты
выполняются с добавлением директивы
use strict
. Эта директива означает, что
соответствующий ей код будет выполнятся в так называемом
«строгом
режиме», поддерживающем стандарт
JavaScript
ECMAScript5.
Примечание:
Если код скрипта содержит конструкции, не соответствующие стандарту ES5, то они не будут выполняться. Это не является ошибкой Synergy.
Ссылки для быстрого перехода по документу:
Модели и отображения, которые не имеют специфичных свойств или переопределения методов
Модели и отображения, которые имеют специфичные свойства или методы
Модели и отображения проигрывателя
Модели и отображения компонентов
Утилиты, полезные функции
Для того, чтобы создать экземпляр проигрывателя, необходимо
вызвать метод AS.FORMS.createPlayer()
.
Методы проигрывателя:
Наименование | Аргумент | Описание |
---|---|---|
showFormData |
formUid(*) |
Отображение последней версии формы по ее идентификатору |
showFormData |
formUid(*), version |
Отображение указанной версии формы по ее идентификатору |
showFormData |
formUid(*), version, dataUid |
Отображение формы по сведениям, содержащимся в последней версии данных по форме (параметры formUid и version игнорируются) |
showFormData |
formUid(*), version, dataUid, dataVersion |
Отображение формы по сведениям, содержащимся в указанной версии данных по форме (параметры formUid и version игнорируются) |
showFormByCode |
formCode(*), version |
Отображение формы по ее коду без создания соответствующего экземляра asfData. |
dataLoaded |
definition(*), data |
Построение формы согласно definition и заполнение asfData значением параметра data |
saveFormData |
hander(*) |
Сохранение данных формы, после которого выполняется функция handler с параметром asfDataUUID |
destroy |
Удаления экземпляра проигрывателя |
Примечания:
(*)
- параметр обязателен.
dataLoaded
- вспомогательный метод, вызывающийся при выполнении методовshowFormData
иshowFormByCode
.
Базовая модель.
Наименование | Тип | Описание |
---|---|---|
asfProperty |
asfProperty |
Определение компонента из описания формы |
playerModel |
AS.FORMS.PlayerModel |
Модель проигрывателя |
Базовые свойства модели.
Наименование | Аргумент | Описание |
---|---|---|
getErrors |
Получение ошибок заполнения поля согласно настройкам
| |
isEmpty |
Пустое ли значение | |
getLocale |
Получение локали, настроенной в компоненте | |
isValid |
Валидно ли текущее значение модели согласно
настройкам | |
fireChangeEvents |
Вызов событий изменения значения формы | |
getHTMLValue |
Получение HTML-представления текстового значения поля со стилями | |
doSetValue |
newValue |
Вставить новое значение и отправить уведомление всем подписанным объектам, в т.ч. отображению |
getValue |
Получение значения | |
getTextValue |
Получение текстового значения | |
getAsfData |
Int blockNumber |
Получение |
setAsfData |
asfData |
Вставить значение |
Примечание.
getErrors
возвращает массив ошибок. Если массив пустой, значит ошибки отсутствуют, иначе - его элементы имеют поля:
errorCode
- код ошибки;
id
- идентификатор компонента.Возможные коды ошибок:
emptyValue
wrongValue
deletedValue
valueTooHigh
valueTooSmall
Для одного и того же компонента может быть как несколько ошибок, так может и не быть ни одной.
Базовое отображение.
Наименование | Тип | Описание |
---|---|---|
model |
Наследует AS.FORMS.Model |
Модель |
container |
div |
Контейнер, в котором будет отрисовываться отображение |
input |
input |
Поле ввода для некоторых компонентов:
|
playerView |
Отображение проигрывателя |
Базовые методы отображения.
Наименование | Аргумент | Описание |
---|---|---|
unmarkInvalid |
Убрать пометку неправильно заполненного поля | |
markInvalid |
Пометить поле как неправильно заполненное | |
checkValid |
Проверить корректность текущего значения (если поле
заполнено неверно, то вызовется метод
| |
setEnabled |
boolean enabled |
Сделать доступным или недоступным для редактирования |
setVisible |
boolean visible |
Сделать видимым или невидимым |
updateValueFromModel |
Обновить отображение согласно значению модели |
Примечание.
Если скрывается последний компонент в строке, то вся строка принимает минимальную высоту 18 px.
AS.FORMS.DocAttributeModel
- модель
компонента «Свойства документа»;
AS.FORMS.DocAttributeView
- отображение
компонента «Свойства документа»;
AS.FORMS.DocLinkModel
- модель
компонента «Ссылка на документ»;
AS.FORMS.DocLinkTextView
- отображение
компонента «Ссылка на документ» в режиме редактирования
AS.FORMS.DocLinkView
- отображение
компонента «Ссылка на документ» в режиме просмотра;
AS.FORMS.ImageModel
- модель компонента
«Изображение»;
AS.FORMS.ImageView
- отображение
компонента «Изображение»;
AS.FORMS.LabelModel
- модель компонента
«Неизменяемый текст»;
AS.FORMS.LabelView
- отображение
компонента «Неизменяемый текст»;
AS.FORMS.SimpleModel
- модель
компонентов «Многострочное поле», «Номер», «HTD-редактор»,
«Ход выполнения», «Лист резолюций», «Лист подписей»;
AS.FORMS.TextBoxModel
- модель
текстового поля.
Модели и отображения проигрывателя.
AS.FORMS.PlayerModel
- модель
проигрывателя
Свойства:
Наименование | Тип | Описание |
---|---|---|
models |
Массив AS.FORMS.TableModel |
Массив моделей страниц |
errorDataLoad |
boolean |
|
formId |
string |
Идентификатор формы |
asfDataId |
string |
Идентификатор данных |
nodeId |
string |
Идентификатор ноды данных |
hasChanges |
boolean |
Имеются ли изменения |
formName |
string |
Наименование формы |
formats |
string |
Форматы печати |
defaultPrintFormat |
string |
Формат печати по умолчанию |
hasMobile |
boolean |
Имеется ли мобильное представление |
hasPrintable |
boolean |
Имеется ли печатное представление |
formCode |
string |
Код формы |
Методы:
Наименование | Аргумент | Описание |
---|---|---|
buildModelsDefinition |
definition |
Построить форму по описанию |
getModelWithId |
cmpId, tableId, tableBlockIndex |
Получение модели компонента с указанным идентификатором в указанной таблице и указанном блоке, если идентификатор таблицы не указан, то ищется модель компонента на странице или в статических таблицах |
AS.FORMS.PlayerView
- отображение
проигрывателя
Свойства:
Наименование | Тип | Описание |
---|---|---|
view |
Массив AS.FORMS.TableStaticView |
Массив отображений страниц |
editable |
boolean |
|
Методы:
Наименование | Аргумент | Описание |
---|---|---|
setEditable |
Boolean editable |
Устанавливает режим отображения чтение/запись |
getViewWithId |
cmpId, tableId, tableBlockIndex |
Получение отображения компонента с указанным идентификатором в указанной таблице и указанном блоке, если идентификатор таблицы не указан, то ищется модель компонента на странице или в статических таблицах |
appendTo |
HTML element |
Отображает проигрыватель в заданном компоненте |
destroy |
Модели и отображения компонентов.
AS.FORMS.TableModel
- модель
компонентов «Страница» и «Таблица»
Методы:
Наименование | Аргумент | Описание |
---|---|---|
createRow |
Добавляет блок таблицы | |
removeRow |
Номер блока |
Удаляет блок таблицы |
getTextValue |
Возвращает форматированное значение свертки | |
isHaveHeader |
Есть ли заголовок | |
isPage |
Является ли страницей | |
isStatic |
Является ли статической таблицей | |
isParagraph |
Включена ли свертка |
AS.FORMS.TableStaticView
-
отображение статической таблицы
Методы:
Наименование | Аргумент | Описание |
---|---|---|
getRowsCount |
Возвращает количество рядов таблицы | |
setColumnVisible |
Int columnNumber boolean visible |
Делает столбец таблицы видимым / невидимым |
getInvisibleColumns |
Возвращает список невидимых столбцов | |
getViewWithId |
cmpId, tableId, tableBlockIndex |
Получение отображения компонента с указанным идентификатором в указанной таблице и указанном блоке, если идентификатор таблицы не указан, то ищется модель компонента на странице или в статических таблицах |
AS.FORMS.TableDynamicView
-
отображение динамической таблицы
Методы:
Наименование | Аргумент | Описание |
---|---|---|
setEnabled |
Разрешает либо запрещает пользователю добавлять и удалять блоки, при этом программная возможность остается | |
setColumnVisible |
Int columnNumber boolean visible |
Делает столбец таблицы видимым / невидимым |
getInvisibleColumns |
Возвращает список невидимых столбцов | |
getViewWithId |
cmpId, tableId, tableBlockIndex |
Получение отображения компонента с указанным идентификатором в указанной таблице и указанном блоке, если идентификатор таблицы не указан, то ищется модель компонента на странице или в статических таблицах |
mergeCell |
|
Объединяет ячейки в блоке |
splitCell |
Row, column |
Разъединяет ячейки |
getRowsCount |
Возвращает количество рядов таблицы | |
getBlocksCount |
Возвращает количество блоков таблицы |
AS.FORMS.TableParagraphView
-
отображение динамической таблицы в свертке
AS.FORMS.NumericModel
- модель
компонента «Числовое поле»
Формат asfData
:
AS.FORMS.ComboBoxModel
- модель
компонентов «Выпадающий список», «Выбор вариантов»,
«Переключатель вариантов»
Формат asfData
выпадающего списка:
{ "id": "cmp-7gj2xv", "type": "listbox", "value": "наименование выбранного элемента", "key": "значение выбранного элемента" }
Формат asfData
выбора вариантов:
{ "id": "cmp-7gj2xv", "type": "check", "value": ["значение элемента 1", "значение элемента 2", "значение элемента 3"], "key": ["наименование элемента 1", "наименование элемента 2", "наименование элемента 3] }
Формат asfData
переключателя вариантов:
{ "id": "cmp-7gj2xv", "type": "radio", "value": "значение выбранного элемента", "key": "наименование выбранного элемента" }
Свойства:
Наименование | Тип | Описание |
---|---|---|
listElements |
[{value : «value1», key : «key1»}, …] |
Массив всех элементов компонента не зависимо от фильтра |
listCurrentElements |
[{value : «value1», key : «key1»}, …] |
Массив элементов компонента согласно фильтру, если таковой имеется, либо массив всех элементов |
Методы:
Наименование | Аргумент | Описание |
---|---|---|
updateModelData |
Обновляет данные текущих элементов компонента согласно фильтрам | |
getTextValues |
Получение массива выбранных текстовых значений | |
getValue |
Возвращает массив выбранных идентификаторов | |
setValue |
Идентификатор либо массив идентификаторов |
Вставляет значение |
AS.FORMS.DateModel
- модель
компонента «Дата/время»
Формат asfData
:
{ "id": "cmp-pfa3r5", "type": "date", "value": "2016-маусым-15", "key": "2016-06-15 12:07:00" }
Методы:
Наименование | Аргумент | Описание |
---|---|---|
getValue |
Возвращает строковое представление даты в формате «yyyy-MM-dd HH:mm:ss», например 2016-05-25 16:16:16 | |
setValue |
Принимает строковое значение даты в формате «yyyy-MM-dd HH:mm:ss», например 2016-05-25 16:16:16 |
Вставляет значение |
Примечание.
Значение даты хранится как строка в формате
yyyy-MM-dd HH:mm:ss
. Пустое значение хранится как____-__-__ __:__:__
или какnull
.
AS.FORMS.DateView
- отображение
компонента «Дата/время»
AS.FORMS.FileModel
- модель
компонента «Файл»
Формат asfData
:
{ "id": "cmp-d84aev", "type": "file", "value": "Файл.png", //имя файла "key": "14064b88-633c-4748-b9c6-9fbf8c8a86e6" //идентификатор файла в хранилище }
Методы:
Наименование | Аргумент | Описание |
---|---|---|
getValue |
Возвращает
| |
setValue |
Объект с обязательными полями:
|
Вставляет значение |
AS.FORMS.FileView
- отображение
компонента «Файл»
AS.FORMS.LinkModel
- модель
компонента «Ссылка»
Формат asfData
:
{ "id": "cmp-7u4wuv", "type": "link", "value": "#submodule=common&action=open_document&document_identifier=${docID}", "key": "Документ; false" }
Примечание.
Значение параметра
key
состоит из надписи к ссылке и через «; » (с пробелом) опцию, открывать ли ссылку в новом окне.
Методы:
Наименование | Аргумент | Описание |
---|---|---|
getValue |
Возвращает описание ссылки:
| |
setValue |
Объект с полями:
Например:
|
Вставляет значение |
getTextValue |
Возвращает подпись ссылки | |
isOpenInNew |
Открывать ли ссылку в новом окне | |
setValueFromInput |
Объект с полями:
|
Обновляет значение |
AS.FORMS.LinkView
- отображение
компонента «Ссылка»
AS.FORMS.UserLinkModel
- модель
компонента «Пользователь»
Формат asfData
:
Формат данных для единственного значения:
{ "id": "cmp-7gj2xv", "type": "entity", "value": "Фамилия Имя Отчество", "key": "1ba41729-871f-4575-88d8-5a6c3de6297a", "formatVersion": "V1", "manualTags": {"identifier" : "введенный вручную тэг"} }
Формат данных для множественного значения:
{ "id": "cmp-7gj2xv", "type": "entity", "value": "formattedName1, formattedName2, formattedName3", "key": "identifier1;identifier2;identifier3", "formatVersion": "V1", "manualTags": {"identifier1" : "введенный вручную тэг"} }
Примечание.
manualTags
- это пользователи, для которых были изменены названия вручную.
key
- это список id выбранных пользователей, разделенных «;».Идентификаторы могут иметь приставки:
без приставки - пользователь;
g
- группа (g-идентификатор_группы);
text
- произвольный текст (text-номер_просто_число);
contact
- контакт адресной книги (contact-идентификатор_контакта).
Методы:
Наименование | Аргумент | Описание |
---|---|---|
getValue |
Возвращает массив данных, которые содержат обязательные поля:
а также необязательные:
| |
getSelectedIds |
Возвращает массив строк - идентификаторов выбранных пользователей | |
setValue |
Объект с обязательными полями:
а также необязательные:
|
AS.FORMS.UserLinkView
- отображение
компонента «Пользователь»
AS.FORMS.PositionLinkModel
- модель
компонента «Должность»
Формат asfData
:
{ "id": "cmp-rgi3pr", "type": "entity", "value": "название должности", "key": "f1af818e-cd5d-4390-9e96-b26dd148e42d", "formatVersion": "V1", "manualTags": {"identifier" : "введенный вручную тэг"} }
Примечание.
manualTags
- это должности, для которых были изменены названия вручную.
Методы:
Наименование | Аргумент | Описание |
---|---|---|
getValue |
Возвращает массив данных, которые содержат обязательные поля:
а также необязательные:
| |
getSelectedIds |
Возвращает массив строк - идентификаторов выбранных должностей | |
setValue |
Объект с обязательными полями:
а также необязательные:
|
AS.FORMS.PositionLinkView
-
отображение компонента «Должность»
AS.FORMS.DepartmentLinkModel
- модель
компонента «Подразделение»
Формат asfData
:
Формат данных для единственного значения:
{ "id": "cmp-7gj2xv", "type": "entity", "value": "название подразделения", "key": "4a76ae9b-a460-431a-9edc-c9bf2966f2fb", "formatVersion": "V1", "manualTags": {"identifier" : "введенный вручную тэг"} }
Формат данных для множественного значения:
{ "id": "cmp-7gj2xv", "type": "entity", "value": "name1;; name1;; name3;; name4", "key": "identifier1;identifier2;identifier3", "formatVersion": "V1", "manualTags": {"identifier" : "введенный вручную тэг"} }
Примечание.
manualTags
- это подразделения, для которых были изменены названия вручную.
key
- это список id выбранных подразделений, разделенных «;».Для множественного значения в качестве разделителя наименований
value
используется «;; » (с пробелом после точек с запятой).
Методы:
Наименование | Аргумент | Описание |
---|---|---|
getValue |
Возвращает массив данных, которые содержат обязательные поля:
а также необязательные:
| |
getSelectedIds |
Возвращает массив строк - идентификаторов выбранных подразделений | |
setValue |
Объект с обязательными полями:
а также необязательные:
|
AS.FORMS.DepartmentLinkView
-
отображение компонента «Подразделение»
AS.FORMS.RepeatPeriodModel
- модель
компонента «Период повторения»
Формат asfData
:
Формат данных для значения «Нет»:
{ "id": "cmp-mqk3ik", "type": "repeater", "value": "Нет", "key": "0" }
Формат данных для значения «По дням недели»:
{ "id": "cmp-mqk3ik", "type": "repeater", "value": "По дням недели: Понедельник, Воскресенье", "key": "1|1.0;7.0" }
Примечание.
Значение параметра
value
состоит из типа значения («По дням недели») и через «: » список полных названий дней недели, разделенных «, ».Значение параметра
key
состоит из типа значения (1 - это по дням недели) и через «|» список значений, разделенных «;», каждое значение в форматепорядковый_номер_дня_недели.0
.
Формат данных для значения «По дням месяца»:
{ "id": "cmp-mqk3ik", "type": "repeater", "value": "По дням месяца: 12, 17, 23", "key": "2|12.0;17.0;23.0" }
Примечание.
Значение параметра
value
состоит из типа значения («По дням месяца») и через «: » список дней месяца, разделенных «, ».Значение параметра
key
состоит из типа значения (2 - это по дням месяца) и через «|» список значений, разделенных «;», каждое значение в форматедень_месяца.0
.
Формат данных для значения «Ежегодно»:
{ "id": "cmp-mqk3ik", "type": "repeater", "value": "Ежегодно: 4.1, 5.11, 7.12, 9.30", "key": "4|1.4; 11.5; 12.7; 30.9" }
Примечание.
Значение параметра
value
состоит из типа значения («Ежегодно») и через «: » список дней года, разделенных «, », каждое значение в форматеномер_месяца.номер_дня
.Значение параметра
key
состоит из типа значения (4 - это ежегодно) и через «|» список значений, разделенных «; », каждое значение в форматеномер_дня.номер_месяца
.
Свойства:
Наименование | Тип | Описание |
---|---|---|
type |
Int |
Тип периода (0 - нет, 1 - по дням недели, 2 - по дням месяца, 4 - ежегодно |
Методы:
Наименование | Аргумент | Описание |
---|---|---|
getValue |
Возвращает массив элементов согласно типу, например [«4.1», «5.11», «7.12», «9.30»] | |
setValue |
Строка следующего типа: 4|1.4;11.5;12.7;30.9 |
Вставляет значение |
setValueFromInput |
|
Обновляет значение модели
|
getTypeText |
Возвращает текстовую расшифровку выбранного типа | |
getValueString |
|
Возвращает строчное представление данных |
AS.FORMS.RepeatPeriodView
-
отображение компонента «Период повторения»
AS.FORMS.ProjectLinkModel
- модель
компонента «Ссылка на проект»
Формат asfData
:
{ "id": "cmp-7gj2xv", "type": "projectlink", "value": "Проект: %название%", //для портфеля "Портфель: %название%" "key": "00e24c3d-d3de-423a-9b86-5d501975b922", "valueID": "00e24c3d-d3de-423a-9b86-5d501975b922" }
Методы:
Наименование | Аргумент | Описание |
---|---|---|
getValue |
Возвращает идентификатор выбранного проекта или портфеля | |
setValue |
Идентификатор проекта или портфеля, либо
|
Вставляет значение |
setValueFromInput |
Объект с полями:
|
Обновляет значение компонента |
AS.FORMS.ProjectLinkView
-
отображение компонента «Ссылка на проект»
AS.FORMS.RegistryLinkModel
- модель
компонента «Ссылка на реестр»
Формат asfData
:
{ "id": "cmp-6vrrkp", "type": "reglink", "value": "1111-GPON", //значащее содержимое через «-» "key": "a1b478c0-2d33-11e6-b327-3085a93a6496", "valueID": "a1b478c0-2d33-11e6-b327-3085a93a6496", "username": "Admin Admin Admin", "userID": "1" }
Методы:
Наименование | Аргумент | Описание |
---|---|---|
getValue |
Возвращает идентификатор выбранного документа реестра | |
setValue |
Идентификатор документа реестра |
Вставляет значение |
getRegistryID |
Возвращает идентификатор реестра |
AS.FORMS.RegistryLinkView
-
отображение компонента «Ссылка на реестр»
AS.FORMS.AddressLinkModel
- модель
компонента «Ссылка на адресную книгу»
Формат asfData
:
{ "id": "cmp-7gj2xv", "type": "personlink", "value": "Фамилия Имя Отчество (Организация)", //для организации "Организация (Адрес)" "key": "0:idenitifier", "valueID": "0:identifier" }
Примечание.
Цифра, предваряющая идентификатор, означает тип контакта: 0 - люди, 1 - организация.
Методы:
Наименование | Аргумент | Описание |
---|---|---|
getValue |
Возвращает идентификатор выбранной записи | |
setValue |
Идентификатор записи |
Вставляет значение |
setValueFromInput |
Объект с полями:
|
Обновляет значение компонента |
AS.FORMS.AddressLinkView
-
отображение компонента «Ссылка на адресную книгу»
AS.FORMS.FileLinkModel
- модель
компонента «Ссылка на файл в хранилище»
Формат asfData
:
{ "id": "cmp-5hpcpy", "type": "filelink", "value": "Файл.pdf", //название файла "key": "36afa2d9-cd78-4638-8132-773a69ff0c55" //идентификатор файла }
Методы:
Наименование | Аргумент | Описание |
---|---|---|
getValue |
Возвращает
| |
setValue |
Объект с обязательными полями:
|
Вставляет значение |
AS.FORMS.FileLinkView
- отображение
компонента «Ссылка на файл в хранилище»
События:
Наименование | Аргумент | Описание |
---|---|---|
tagEdit |
|
Возникает при изменении подписи у элемента поля ввода с тегами |
tagDelete |
|
Возникает при удалении элемента поля ввода с тегами |
Методы:
Наименование | Аргумент | Описание |
---|---|---|
Конструктор |
| |
focus |
Переводит фокус на поле ввода | |
addValue |
|
Добавляет значение |
markValidity |
|
Помечает поле правильно либо неправильно заполненным; неправильно заполненное поле обводится красным цветом и подсвечивается |
getValues |
Возвращает список текущих значений поля ввода | |
setValues |
|
Устанавливает значение поля ввода с тегами |
setVisible |
|
Определяет видимость компонента |
setEditable |
|
Доступен ли компонент для редактирования |
getWidget |
Получение компонента, который можно добавить в дом |
Методы:
Наименование | Аргумент | Описание |
---|---|---|
showDropDown |
values - массив значений [{value : «value1», title : «title1», selected : true}, [{value : «value2», title : «title2»}, [{value : «value3», title : «title3»}] anchor - якорный компонент, к которому следует привязать popup minWidth - минимальная ширина handler - callback |
Отображает выпадающий список
В callback передается |
showDatePicker |
value - объект типа Date anchor - якорный компонент, к которому следует привязать popup input - поле ввода даты (можно передать null), используется для передачи фокуса handler : callback |
Отображает компонент выбора даты |
showUserChooserDialog |
values, multiSelectable, isGroupSelectable, showWithoutPosition, filterPositionID, filterDepartmentID, locale, handler |
Отображает диалог выбора пользователей В callback передается массив, содержащий объекты со следующими полями:
а также необязательные:
|
showPositionChooserDialog |
values, multiSelect, filterUserId, filterDepartmentId, showVacant, locale, handler |
Отображает диалог выбора должностей В callback передается массив, содержащий объекты со следующими полями:
а также необязательные:
|
showDepartmentChooserDialog |
values, multiSelectable, filterUserID, filterPositionID, filterDepartmentID, filterChildDepartmentID, locale, handler |
Отображает диалог выбора департаментов В callback передается массив, содержащий объекты со следующими полями:
а также необязательные:
|
showProjectLinkDialog |
handler |
Отображает диалог выбора проекта/портфеля В callback передается массив, содержащий объекты со следующими полями:
|
showRegisterLinkDialog |
registry, handler |
Отображает диалог выбора записи реестра В callback передается идентификатор выбранного документа |
showWaitWindow |
Отображает окно ожидания Каждая платформа реализует свое окно, внутри Synergy это реализовано, для встраивания в другой портал необходимо данный метод переопределить | |
hideWaitWindow |
Скрывает окно ожидания Каждая платформа реализует свое окно, внутри Synergy это реализовано, для встраивания в другой портал необходимо данный метод переопределить | |
unAuthorized |
Url - URLметода API, при вызове которого появилась ошибка 401 |
Скрывает окно ожидания Каждая платформа реализует свое окно, внутри Synergy это реализовано, для встраивания в другой портал необходимо данный метод переопределить |
Методы AS.FORMS.ApiUtils:
Наименование | Аргумент | Описание |
---|---|---|
addAuthHeader |
Добавляет заголовок с параметрами авторизации | |
getFullUrl |
UrlPart - «rest/api/asforms/form_ext?formID=» |
Формирует частичный (при наличии) либо полный URL до метода API |
simpleAsyncGet |
UrlPart - «rest/api/asforms/form_ext?formID=» callback - куда вернуть результат dataType - тип данных data - данные errorHandler — callback в случае ошибки (при ошибке 401 вызовется метод AS.SERVICES.unAuthorized) |
Выполняет GET-запрос к API Synergy Автоматически добавит заголовки |
simpleAsyncPost |
UrlPart - «rest/api/asforms/form_ext?formID=» callback - куда вернуть результат dataType - тип данных data - данные contentType - тип содержания errorHandler — callback в случае ошибки (при ошибке 401 вызовется метод AS.SERVICES.unAuthorized) |
Выполняет GET-запрос к API Synergy Автоматически добавит заголовки |
Методы AS.FORMS.ASFDataUtils:
Наименование | Аргумент | Описание |
---|---|---|
getComponentLocale |
asfProperty |
Получение локали, настроенной в компоненте |
isReadOnly |
model |
Является ли компонент не редактируемым согласно настроек |
getBaseAsfData |
|
Получение базового объекта для формирования данных для сохранения в Synergy. Получив таким образом объект, можно добавить к нему собственные свойства (см. пример ниже) |
Методы AS.FORMS.DateUtils:
Наименование | Аргумент | Описание |
---|---|---|
isEmpty |
DateStr |
Соответствует ли переданная строка пустому значению, например 201-- будет считаться пустым значением |
parseDate |
DateStr |
Возвращает объект дата соответствующей строке, если строка не соответствует формату, то null |
formatDate |
Date, format |
Форматирует дату согласно формату |
getMonthName |
number |
Получение полного названия месяца по номеру |
getMonthShortName |
number |
Получение сокращенного названия месяца по номеру |
getMonthPossessiveName |
number |
Получение названия месяца в родительном падеже |
getWeekDayName |
number |
Получение названия дня недели по номеру |
getWeekDayShortName |
number |
Получение сокращенного названия дня недели по номеру |
Методы AS.FORMS.ComponentUtils:
Наименование | Аргумент | Описание |
---|---|---|
createModel |
Asfproperty, playerModel |
Создание модели компонента |
createView |
Model, playerView, editable |
Создание отображения компонента |
createContainer |
Создание контейнера компонента | |
makeBus |
object |
Делает из любого переданного объекта шину событий, добавляет методы:
|
createFunction |
Code - код, prefixCode - код приставка |
Создание функции из строк кода |
Перед созданием нового компонента необходимо определиться со следующими вопросами:
Какие данные он будет хранить?
Какие ошибки валидации данного компонента существуют?
Как компонент должен выглядеть в режиме просмотра, редактирования, неправильно заполненным в режиме редактирования?
Ответив на эти вопросы, можно приступить к написанию компонента.
Предположим, нужно хранить в качестве значения компонента 3 поля:
identifier
- идентификатор выбранного
значения;
name
- наименование;
info
- дополнительная информация.
Таким образом, в переменной value
модели будет объект, содержащий эти 3
поля. Например:
value = { identifier : 1, name : «Наименование», info : «Дополнительная информация» }
Данный объект необходимо передавать в метод модели
setValue
, а получать в методе модели
getValue
.
Чтобы эти данные сохранялись в файл по форме и поднимались при последующем открытии, необходимо реализовать 2 метода модели:
getAsfData(blockNumber)
setAsfData(asfData)
Необходимо учесть, что поля сохраняемого объекта
asfData
могут иметь лишь следующий перечень
наименований:
value
- обычно это текстовое значение
компонента;
key
- обычно это значение компонента;
valueID
- дополнительный идентификатор;
username
- имя пользователя;
userID
- идентификатор пользователя;
values
- массив строк;
key
- массив строк.
Все эти поля необязательны, но объект, сохраняемый в файле по форме, может иметь только такие свойства.
Пример реализации этих методов:
model.getAsfData = function(blockNumber){ if(model.getValue()) { /*следующий метод сформирует правильную запись для сохранения в файле по форме при этом: model.getValue().title — запишется в поле value model.getValue().value — запишется в поле key*/ var result = AS.FORMS.ASFDataUtils.getBaseAsfData(model.asfProperty, blockNumber, model.getValue().name , model.getValue().identifier); /* дописываем необходимую информацию в поле valueID*/ result.valueID = model.getValue().info ; return result; } else { return AS.FORMS.ASFDataUtils.getBaseAsfData(model.asfProperty, blockNumber); } }; model.setAsfData = function(asfData){ if(!asfData || !asfData.value) { return; } /*читаем данные из объекта из файла по форме: дополнительная информация была сохранена в поле valueID и теперь читаем из него*/ var value = { value : asfData.key, title : asfData.value, info : asfData.valueID}; model.setValue(value); };
Далее необходимо определить список специальных ошибок.
Например, пользователь может выбирать значениями с некоторыми
идентификаторами . Для этого необходимо переопределить метод
модели getSpecialErrors
.
model.getSpecialErrors = function() { if(model.getValue()) { if(model.getValue().identifier == '0') { return {id : model.asfProperty.id, errorCode : AS.FORMS.INPUT_ERROR_TYPE.wrongValue}; } } };
В данном примере проверяется, является ли значение идентификатора равным 0. Если да, то это значит, что компонент неправильно заполнен и возвращается ошибка. Synergy при этом будет показывать, что данные заполнены некорректно.
Работа с моделью теперь завершена.
Далее будем работать с отображением.
Предположим, что на вопрос №3 даны следующие ответы:
В режиме просмотра компонент должен представлять собой просто подпись.
В режиме редактирования - это недоступное для редактирования поле ввода и кнопка, по нажатию на которую открывается диалог выбора записи.
Неправильно заполненное поле должно подсвечивать красным кнопку компонента.
Необходимо инициализировать отображение, в зависимости от режима (просмотр или редактирование).
В области видимости есть переменная
editable
:
editable = false
соответствует режиму
просмотра;
editable = true
соответствует режиму
редактирования.
Для режима просмотра достаточно иметь div
,
куда будет вставлено тестовое описание поля, и реализовать
метод updateValueFromModel
.
Пример:
var textView = jQuery('<div>', {class : "asf-label"}); view.container.append(textView); view.updateValueFromModel = function(){ textView.html(model.getValue().name); };
Создается div
, который добавляется в
контейнер компонента. При любом изменении модели автоматически
вызовется метод updateValueFromModel
и
значение изменится.
Для режима редактирования необходимо создать
div
, кнопку, а также реализовать методы
updateValueFromModel
,
markInvalid
,
unmarkInvalid
.
Пример:
/** * инициализируем внешний вид компонента, див и кнопку */ var inputView = jQuery('<div>', {class : "asf-label", style : "width:calc(100% - 30px)"}); var button = jQuery('<button>', {class : "asf-browseButton"}); view.container.append(inputView); view.container.append(button); /** * обновляем значение отображения в зависимости от значения модели */ view.updateValueFromModel = function(){ inputView.html(model.getValue().name); }; /** * метод помечает поле как неправильно заполненное */ view.markInvalid = function(){ button.css("background-color", "#aa3344"); }; /** * метод убирает пометку неправильно заполненного поля */ view.unmarkInvalid = function(){ button.css("background-color", ""); }; /** * вызываем какой-нибудь диалог выбора пользователя */ button.onclick(function(){ var value = {identifier : "1", name : "name "+math.rand(), info : "additional info"}; // тут прописывается какая-нибудь логика получения этого значения model.setValue(value); });