Пользовательские формы

OpenBPM Tasklist поддерживает использование собственных React-компонентов в качестве форм для старта процессов и выполнения пользовательских задач. Это позволяет создавать интерфейсы, максимально адаптированные под конкретные бизнес-процессы.

Основные принципы

Каждая форма в OpenBPM Tasklist соответствует значению formKey, указанному в BPMN-диаграмме. Если formKey совпадает с зарегистрированным компонентом, Tasklist автоматически отобразит нужную форму.

Поддерживаются два типа форм:

  • Стартовые формы (Start Forms) — отображаются при запуске процесса

  • Формы задач (Task Forms) — отображаются при выполнении пользовательских задач

Создание пользовательской формы

  1. В BPMN-редакторе укажите тип формы Embedded or External Task Form и задайте значение поля Form key (например, newVisit).

  2. В проекте создайте новую форму в каталоге:

    src/custom-forms/
  3. Определите компонент React, который реализует интерфейс:

    • CustomStartFormProps — для стартовых форм

    • CustomTaskFormProps — для форм задач

Пример стартовой формы

// src/custom-forms/NewVisitForm.tsx
import {Button, DatePicker, Flex, Form, type FormProps, Input, Typography} from "antd";
import type {CustomStartFormProps} from "@features/custom-forms/types.ts";
import dayjs, {type Dayjs} from "dayjs";

const {Title} = Typography;

// a type with list of output process variables
export interface NewVisitVariables {
    visitDate: Dayjs; // will be automatically formatted to string
    contactName: string;
    contactEmail: string;
}

export const NewVisitForm = (props: CustomStartFormProps<NewVisitVariables>) => { //here the required type of props is used
    const {onSubmit: startProcess, submitInProgress, onCancel} = props;

    const handleSend: FormProps<NewVisitVariables>["onFinish"] = (formValues) => {
        // generate a business key for a new process instance
        const businessKey = "Visit by" + formValues.visitDate.format('DD/MM/YYYY HH:MM');

        // start a process with variables and business key
        startProcess(formValues, businessKey);
    };
    return (
        <>
            <Title level={4}>New visit</Title>
            <Form onFinish={handleSend} layout="vertical">
                <Form.Item<NewVisitVariables> label="Visit date"
                                              name="visitDate"
                                              rules={[{required: true, message: "Please input a date!"}]}>
                    <DatePicker minDate={dayjs()} showTime showSecond={false}
                                disabledHours={() => [...Array(9).keys(), 21, 22, 23]}
                                format="MM/DD/YYYY HH:mm"
                                maxDate={dayjs().add(2, "week")} minuteStep={30}/>
                </Form.Item>

                <Form.Item<NewVisitVariables>
                    label="Contact name"
                    name="contactName"
                    rules={[{required: true, message: "Please input your name!"}]}
                >
                    <Input/>
                </Form.Item>

                <Form.Item<NewVisitVariables> label="Contact Email" name="contactEmail"
                                              rules={[{required: true, message: "Please input your email!"},
                                                  {type: "email", message: "The input is not valid E-mail!"}]}>
                    <Input/>
                </Form.Item>

                <Form.Item label={null}>
                    <Flex gap="small">
                        <Button type="primary" htmlType="submit" loading={submitInProgress}>
                            Send
                        </Button>
                        <Button onClick={onCancel}>
                            Close
                        </Button>
                    </Flex>
                </Form.Item>
            </Form>
        </>
    );
};

Пример формы задачи

// src/custom-forms/CheckVisitForm.tsx
import type {CustomTaskFormProps} from "@features/custom-forms/types.ts";
import {Button, Descriptions, type DescriptionsProps, Flex, Form, Space, Switch, Typography} from "antd";
import dayjs from "dayjs";

export interface VisitInputVariables {
    visitDate: string;
    contactName: string;
    contactEmail: string;
}

export interface CheckResultVariables {
    approved: boolean;
}

export const CheckVisitDetailsForm = (props: CustomTaskFormProps<VisitInputVariables, CheckResultVariables>) => {
    const {onSubmit: handleComplete, submitInProgress, onCancel, inputVariables} = props;

    const items: DescriptionsProps["items"] = [
        {
            key: "date",
            label: 'Visit Date',
            children: <Typography>{dayjs(inputVariables.visitDate).format("DD/MM/YYYY HH:MM")}</Typography>,
        },
        {
            key: "contact",
            label: 'Contact',
            children: <Typography>{inputVariables.contactName} ({inputVariables.contactEmail})</Typography>,
        },
    ];
    return (
        <>
            <Space direction="vertical">
                <Descriptions items={items} column={1}/>
                <Form onFinish={handleComplete}>
                    <Form.Item<CheckResultVariables> label="Approved" name="approved">
                        <Switch/>
                    </Form.Item>
                    <Form.Item label={null}>
                        <Flex gap="small">
                            <Button type="primary" htmlType="submit" loading={submitInProgress}>
                                Complete
                            </Button>
                            <Button onClick={onCancel}>
                                Close
                            </Button>
                        </Flex>
                    </Form.Item>
                </Form>
            </Space>

        </>
    );
};

Регистрация пользовательских форм

Чтобы форма отображалась в интерфейсе Tasklist, её необходимо зарегистрировать в конфигурационном файле.

  1. Откройте файл:

    src/features/custom-forms/config.ts
  2. Добавьте запись в массив customFormConfigs, указав ключ формы (formKey) и компонент:

    // src/features/custom-forms/config.ts
    
    import type {CustomFormConfig} from "./types.ts";
    import {NewVisitForm} from "../../custom-forms/NewVisitForm.tsx";
    import {CheckVisitDetailsForm} from "../../custom-forms/CheckVisitDetailsForm.tsx";
    
    // Configuration for custom task and start forms used in the business process diagrams
    export const customFormConfigs: CustomFormConfig[] = [
        // added configuration for a custom start form
        {
            formKey: "newVisit",
            component: NewVisitForm,
        },
    
        // added configuration for a custom user task form
        {
            formKey: "checkVIsitDetails",
            component: CheckVisitDetailsForm,
        }
    ];
  3. После этого Tasklist автоматически отобразит форму при открытии задачи или запуске процесса, где совпадает formKey.

Типы Embedded и Generated форм не поддерживаются. Для всех пользовательских сценариев рекомендуется использовать кастомные или Camunda form.