logo

Создание настроек элемента для моделирования бизнес-процесса в дизайнере

Внимание!
Эта статья актуальна для версии ELMA4 4.1.21 и выше.
Примечание
Для расширения возможностей дизайнера рекомендуется создавать отдельные модули. Это нужно для уменьшения размера данных при работе в самом дизайнере и в системе.

Перед тем как добавлять настройки элемента для моделирования, нужно:

В названии модуля, реализующего настройки элемента для моделирования в дизайнере, рекомендуется добавлять постфикс .Diagram, например, EleWise.ELMA.Workflow.Diagrams.

Реализация

В папке DevServer откройте файл appsettings.json. Затем в тексте сценария в разделе "DevServer" добавьте настройку "DevelopMode": "Pro", как показано на рисунке ниже.

Запустите DevServer командой server.

Реализация в классическом модуле ELMA4

Модуль должен ссылаться на две системные библиотеки: EleWise.ELMA.Workflow и EleWise.ELMA.SDK.Diagrams. Это нужно для реализации элемента для моделирования, его настроек и визуализации.

Сначала добавьте визуальную часть формы элемента. Для этого создайте интерфейс EleWise.ELMA.Workflow.BPMN.Diagrams.Shapes.IWebDiagrammerElementShape:

ExampleElementShape 
internal sealed class ExampleElementShape : IWebDiagrammerElementShape
{
    private Color strokeColor, backgroundColor;

    /// <summary>
    /// Ctor
    /// </summary>
    public ExampleElementShape()
    {
        strokeColor = Color.FromArgb(255, 253, 227, 107);
        backgroundColor = Color.FromArgb(255, 254, 246, 206);
    }

    /// <summary>
    /// Ширина фигуры по-умолчанию
    /// </summary>
    public int Width => 100;

    /// <summary>
    /// Высота фигуры по-умолчанию
    /// </summary>
    public int Height => 100;

    /// <summary>
    /// Толщина границы
    /// </summary>
    public int StrokeWidth => 1;

    /// <summary>
    /// Цвет границы
    /// </summary>
    public Color StrokeColor => strokeColor;

    /// <summary>
    /// Цвет фона
    /// </summary>
    public Color BackgroundColor => backgroundColor;
}

Если в классическом модуле ELMA4 элемент уже создан, добавьте атрибут WebDiagrammerShapeAttribute:

ExampleElement 
[WebDiagrammerShape(typeof(ExampleElementShape))]
public sealed class ExampleElement : BPMNFlowElement
{
    ...
}

Если в классическом модуле элемента нет, добавьте его:

ExampleElement 
[WebDiagrammerShape(typeof(ExampleElementShape))]
public sealed class ExampleElement : BPMNFlowElement
{
    /// <summary>
    /// Элемент панели инструментов
    /// </summary>
    [Component(Order = 100)]
    private class ToolboxItem : IBPMNToolboxItem, IContainingElementIcon
    {
        ...
    }

    /// <summary>
    /// Какое-то собственное свойство
    /// </summary>
    public string SomeImportantField { get; set; }
    ...
}

Примеры

  • Пример реализации панели инструментов:
ToolboxItem 
/// <summary>
/// Элемент панели инструментов
/// </summary>
[Component(Order = 100)]
private class ToolboxItem : IBPMNToolboxItem, IContainingElementIcon
{
    /// <summary>
    /// Имя элемента
    /// </summary>
    public string Name => SR.T("Пример элемента");

    /// <summary>
    /// Uid группы элементов в панели инструментов
    /// </summary>
    public Guid GroupUid => ExampleElementGroup.Uid;

    /// <summary>
    /// Иконка для отображения элементов в панели инструментов в десктопной версии
    /// </summary>
    public Image Image => new Bitmap(16, 16);

    /// <summary>
    /// Тип элемента
    /// </summary>
    public Type ElementType => typeof(ExampleElement);

    /// <summary>
    /// Название иконки в web-версии
    /// </summary>
    public string ElementIcon => "user";
}
  • Пример реализации группы:
ExampleElementGroup 
/// <summary>
/// Группа "Тестовая группа" на панели Toolbox в дизайнере
/// </summary>
[Component(Order = 100)]
internal sealed class ExampleElementGroup : IBPMNToolboxItemGroup
{
    internal static readonly Guid Uid = new Guid("{D308A6B2-C225-41C6-A1CD-D4613D06DDC9}");

    /// <inheritdoc />
    public Guid PanelUid => ExampleElementPanel.Uid;

    /// <inheritdoc />
    public Guid GroupUid => Uid;

    /// <inheritdoc />
    public Guid ParentGroupUid => Guid.Empty;

    /// <inheritdoc />
    public string Name => SR.T("Тестовая группа");
}
  • Пример реализации панели:
ExampleElementGroup 
/// <summary>
/// Панель "тестовая" в toolbox дизайнера
/// </summary>
[Component(Order = 100)]
internal sealed class ExampleElementPanel : IBPMNToolboxItemPanel
{
    internal static readonly Guid Uid = new Guid("{D4FB15CA-D9E3-4D17-A19B-18699C886EBA}");

    /// <inheritdoc />
    public Guid PanelUid => Uid;

    /// <inheritdoc />
    public string Title => SR.T("Тестовая панель");

    /// <inheritdoc />
    public Image Image => null;
}

Теперь можно сформировать пакет с расширением .nupkg и добавить его к источникам пакетов DevServer. Вы также можете установить пакет на сервере ELMA4.

Реализация в модуле КИ

Сначала создайте публичную структуру обмена данными (СОД). Для всех СОД – элементов диаграммера существуют вложенные структуры, так как все типы элементов являются наследниками. В нашем примере нужно указать Базовый класс элемента диаграммы BPMN в качестве вложенной структуры. Чтобы этот тип стал доступен в модуле, в Списке зависимостей модуля выберите Модуль „Элементы диаграммы модуля „Процессы“ Дизайнера конфигурации.

Теперь в публичной СОД в качестве вложенной структуры укажите Базовый класс элемента диаграммы BPMN.

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

Далее создайте маппинг. В настройках СОД перейдите на вкладку Системные и укажите Пространство имен, как показано на рисунке ниже.

Если у вас нет этой настройки или вкладки, проверьте, внесены ли изменения в файл appsettings.json.

Реализация компонента

Для использования компонентов дизайнера в Список зависимостей модуля добавьте следующие модули:

  • Модуль „Процессы“ Дизайнера конфигурации (EleWise.ELMA.Workflow.Designer);
  • Модуль „Диаграммер“ Дизайнера конфигурации (EleWise.ELMA.Diagrams.Designer);
  • Модуль „Элементы диаграммы модуля „Безопасность“ Дизайнера конфигурации.

Для отображения компонентов настроек элементов используйте форму объекта. С её помощью СОД можно связать с целевым компонентом.

В новом компоненте укажите следующие настройки для свойства с входным значением:

  • в поле Отображаемое имя * укажите Model;
  • в поле Тип выберите созданную ранее СОД, например, ExampleElementDTO;
  • включите опцию Входное;
  • установите флажок в настройке Обязательно для заполнения.

Для всех настроек элементов используйте компонент Меню с формой.

Во всех существующих компонентах настроек элементов используется компонент Общая панель действий настроек элемента, который позволяет добавлять дополнительные действия. Если вам не нужно нестандартное оформление панели действий, используйте этот компонент. Разместите его в строке в заголовке компонента меню.

Этот компонент принимает:

  • функцию сохранения;
  • функцию отмены;
  • базовый элемент для моделирования;
  • контракт расширения.

Внешний контракт расширения можно выбрать, если вы хотите использовать нестандартные значения. Это поле необязательно для заполнения.

Пример контроллера с функциями панели действий:

ExampleElementGroup 
private readonly INotificationService notificationService;

/// <summary>
/// Ctor
/// </summary>
/// <param name="notificationService">Сервис нотификаций</param>
public ComponentController(INotificationService notificationService)
{
    this.notificationService = notificationService;
}

/// <summary>
/// Сценарий вычисления значения свойства "Базовый элемент"
/// </summary>
public BaseBPMNElementDTO GetBaseBPMNElement()
{
    return Context.Model.As<BaseBPMNElementDTO>();
}

/// <summary>
/// Действие при сохранении
/// </summary>
public async Task Save()
{
    if (!Component.Validation.IsValid)
    {
        var errorMessage = string.Join("\n",
            Component.Validation.Errors.GroupBy(e => e.ErrorMessage).Select(group => group.Key));
        notificationService.Error(SR.T("Ошибка валидации"), errorMessage, false);
        return;
    }

    await GetBaseBPMNElement().Save(Context.Model.As<ElementDTO>());
}

/// <summary>
/// Действие при отмене
/// </summary>
/// <returns></returns>
public Task Cancel()
{
    return GetBaseBPMNElement().Cancel();
}

/// <summary>
/// Сценарий вычисления значения свойства "Элемент"
/// </summary>
public EleWise.ELMA.SDK.Diagrams.DTO.Model.ElementDTO GetBaseElement()
{
    return Context.Model.As<ElementDTO>();
}

На рисунке ниже представлена форма с настройками элемента с одним полем и общей формой элемента ([Настройки элемента] Общие).

Для привязки компонента к визуальному отображению типа настроек в компоненте настройте реализацию форм Создание, Редактирование и Просмотр.

Теперь можно опубликовать модуль/приложение и импортировать в ELMA4 для проверки работоспособности.