├── .github ├── CONTRIBUTING.md ├── ISSUE_TEMPLATE.md └── workflows │ ├── CI.yml │ └── CODE_SCANNING.yml ├── .gitignore ├── CHANGELOG.md ├── LICENSE ├── README.md ├── codecov.yml ├── docs ├── RELEASE_CHECKLIST.md └── screenshot.png ├── eslint.config.mjs ├── karma.config.js ├── package-lock.json ├── package.json ├── renovate.json ├── rollup.config.mjs ├── src ├── cmd │ ├── MultiCommandHandler.js │ └── index.js ├── context │ ├── BpmnPropertiesPanelContext.js │ └── index.js ├── contextProvider │ ├── camunda-platform │ │ ├── TooltipProvider.js │ │ └── index.js │ └── zeebe │ │ ├── TooltipProvider.js │ │ └── index.js ├── entries │ ├── FeelEntryWithContext.js │ └── ReferenceSelect.js ├── hooks │ ├── index.js │ └── useService.js ├── icons │ ├── bpmn-empty-state.svg │ ├── bpmn-icon-association.svg │ ├── bpmn-icon-business-rule-task.svg │ ├── bpmn-icon-call-activity.svg │ ├── bpmn-icon-collaboration.svg │ ├── bpmn-icon-conditional-flow.svg │ ├── bpmn-icon-connection.svg │ ├── bpmn-icon-data-input-output-association.svg │ ├── bpmn-icon-data-input.svg │ ├── bpmn-icon-data-object.svg │ ├── bpmn-icon-data-output.svg │ ├── bpmn-icon-data-store.svg │ ├── bpmn-icon-default-flow.svg │ ├── bpmn-icon-end-event-cancel.svg │ ├── bpmn-icon-end-event-compensation.svg │ ├── bpmn-icon-end-event-error.svg │ ├── bpmn-icon-end-event-escalation.svg │ ├── bpmn-icon-end-event-link.svg │ ├── bpmn-icon-end-event-message.svg │ ├── bpmn-icon-end-event-multiple.svg │ ├── bpmn-icon-end-event-none.svg │ ├── bpmn-icon-end-event-signal.svg │ ├── bpmn-icon-end-event-terminate.svg │ ├── bpmn-icon-event-subprocess-expanded.svg │ ├── bpmn-icon-gateway-complex.svg │ ├── bpmn-icon-gateway-eventbased.svg │ ├── bpmn-icon-gateway-none.svg │ ├── bpmn-icon-gateway-or.svg │ ├── bpmn-icon-gateway-parallel.svg │ ├── bpmn-icon-gateway-xor.svg │ ├── bpmn-icon-group.svg │ ├── bpmn-icon-intermediate-event-catch-cancel.svg │ ├── bpmn-icon-intermediate-event-catch-compensation.svg │ ├── bpmn-icon-intermediate-event-catch-condition.svg │ ├── bpmn-icon-intermediate-event-catch-error.svg │ ├── bpmn-icon-intermediate-event-catch-escalation.svg │ ├── bpmn-icon-intermediate-event-catch-link.svg │ ├── bpmn-icon-intermediate-event-catch-message.svg │ ├── bpmn-icon-intermediate-event-catch-multiple.svg │ ├── bpmn-icon-intermediate-event-catch-non-interrupting-condition.svg │ ├── bpmn-icon-intermediate-event-catch-non-interrupting-escalation.svg │ ├── bpmn-icon-intermediate-event-catch-non-interrupting-message.svg │ ├── bpmn-icon-intermediate-event-catch-non-interrupting-multiple.svg │ ├── bpmn-icon-intermediate-event-catch-non-interrupting-parallel.svg │ ├── bpmn-icon-intermediate-event-catch-non-interrupting-signal.svg │ ├── bpmn-icon-intermediate-event-catch-non-interrupting-timer.svg │ ├── bpmn-icon-intermediate-event-catch-parallel-multiple.svg │ ├── bpmn-icon-intermediate-event-catch-signal.svg │ ├── bpmn-icon-intermediate-event-catch-timer.svg │ ├── bpmn-icon-intermediate-event-none.svg │ ├── bpmn-icon-intermediate-event-throw-compensation.svg │ ├── bpmn-icon-intermediate-event-throw-escalation.svg │ ├── bpmn-icon-intermediate-event-throw-link.svg │ ├── bpmn-icon-intermediate-event-throw-message.svg │ ├── bpmn-icon-intermediate-event-throw-multiple.svg │ ├── bpmn-icon-intermediate-event-throw-signal.svg │ ├── bpmn-icon-lane.svg │ ├── bpmn-icon-manual-task.svg │ ├── bpmn-icon-message-flow.svg │ ├── bpmn-icon-participant.svg │ ├── bpmn-icon-process.svg │ ├── bpmn-icon-receive-task.svg │ ├── bpmn-icon-script-task.svg │ ├── bpmn-icon-send-task.svg │ ├── bpmn-icon-service-task.svg │ ├── bpmn-icon-start-event-compensation.svg │ ├── bpmn-icon-start-event-condition.svg │ ├── bpmn-icon-start-event-error.svg │ ├── bpmn-icon-start-event-escalation.svg │ ├── bpmn-icon-start-event-message.svg │ ├── bpmn-icon-start-event-multiple.svg │ ├── bpmn-icon-start-event-non-interrupting-condition.svg │ ├── bpmn-icon-start-event-non-interrupting-escalation.svg │ ├── bpmn-icon-start-event-non-interrupting-message.svg │ ├── bpmn-icon-start-event-non-interrupting-multiple.svg │ ├── bpmn-icon-start-event-non-interrupting-parallel-multiple.svg │ ├── bpmn-icon-start-event-non-interrupting-signal.svg │ ├── bpmn-icon-start-event-non-interrupting-timer.svg │ ├── bpmn-icon-start-event-none.svg │ ├── bpmn-icon-start-event-parallel-multiple.svg │ ├── bpmn-icon-start-event-signal.svg │ ├── bpmn-icon-start-event-timer.svg │ ├── bpmn-icon-subprocess-collapsed.svg │ ├── bpmn-icon-subprocess-expanded.svg │ ├── bpmn-icon-task-none.svg │ ├── bpmn-icon-text-annotation.svg │ ├── bpmn-icon-transaction.svg │ ├── bpmn-icon-user-task.svg │ ├── bpmn-multiple-state.svg │ └── index.js ├── index.js ├── provider │ ├── HOCs │ │ ├── index.js │ │ ├── withProps.js │ │ ├── withTooltipContainer.js │ │ └── withVariableContext.js │ ├── bpmn │ │ ├── BpmnPropertiesProvider.js │ │ ├── index.js │ │ ├── properties │ │ │ ├── AdHocCompletionProps.js │ │ │ ├── CompensationProps.js │ │ │ ├── DocumentationProps.js │ │ │ ├── ErrorProps.js │ │ │ ├── EscalationProps.js │ │ │ ├── ExecutableProps.js │ │ │ ├── IdProps.js │ │ │ ├── LinkProps.js │ │ │ ├── MessageProps.js │ │ │ ├── MultiInstanceProps.js │ │ │ ├── NameProps.js │ │ │ ├── ProcessProps.js │ │ │ ├── SignalProps.js │ │ │ ├── TimerProps.js │ │ │ └── index.js │ │ └── utils │ │ │ └── EventDefinitionUtil.js │ ├── camunda-platform │ │ ├── CamundaPlatformPropertiesProvider.js │ │ ├── index.js │ │ ├── properties │ │ │ ├── AsynchronousContinuationsProps.js │ │ │ ├── BusinessKeyProps.js │ │ │ ├── CallActivityProps.js │ │ │ ├── CalledBpmnProps.js │ │ │ ├── CalledCmmnProps.js │ │ │ ├── CandidateStarterProps.js │ │ │ ├── ConditionProps.js │ │ │ ├── ConnectorInputProps.js │ │ │ ├── ConnectorOutputProps.js │ │ │ ├── DelegateVariableMappingProps.js │ │ │ ├── DmnImplementationProps.js │ │ │ ├── Error.js │ │ │ ├── ErrorProps.js │ │ │ ├── ErrorsProps.js │ │ │ ├── EscalationProps.js │ │ │ ├── ExternalTaskPriorityProps.js │ │ │ ├── FieldInjection.js │ │ │ ├── FieldInjectionProps.js │ │ │ ├── FormDataProps.js │ │ │ ├── FormField.js │ │ │ ├── FormFieldConstraint.js │ │ │ ├── FormFieldProperty.js │ │ │ ├── FormFieldValue.js │ │ │ ├── FormProps.js │ │ │ ├── FormTypeProps.js │ │ │ ├── HistoryCleanupProps.js │ │ │ ├── IdProps.js │ │ │ ├── ImplementationProps.js │ │ │ ├── ImplementationTypeProps.js │ │ │ ├── InMappingPropagationProps.js │ │ │ ├── InMappingProps.js │ │ │ ├── InOutMapping.js │ │ │ ├── InitiatorProps.js │ │ │ ├── InputOutputParameter.js │ │ │ ├── InputProps.js │ │ │ ├── JobExecutionProps.js │ │ │ ├── ListProps.js │ │ │ ├── ListenerProps.js │ │ │ ├── MapProps.js │ │ │ ├── MultiInstanceProps.js │ │ │ ├── OutMappingPropagationProps.js │ │ │ ├── OutMappingProps.js │ │ │ ├── OutputProps.js │ │ │ ├── ProcessProps.js │ │ │ ├── ProcessVariablesProps.js │ │ │ ├── ScriptProps.js │ │ │ ├── ScriptTaskProps.js │ │ │ ├── TasklistProps.js │ │ │ ├── TimerProps.js │ │ │ ├── UserAssignmentProps.js │ │ │ ├── VersionTagProps.js │ │ │ └── index.js │ │ └── utils │ │ │ ├── ConnectorUtil.js │ │ │ ├── FormTypeUtils.js │ │ │ ├── ImplementationTypeUtils.js │ │ │ └── InputOutputUtil.js │ ├── shared │ │ ├── ExtensionPropertiesProps.js │ │ └── ExtensionProperty.js │ └── zeebe │ │ ├── ZeebePropertiesProvider.js │ │ ├── index.js │ │ ├── properties │ │ ├── ActiveElementsProps.js │ │ ├── AdHocCompletionProps.js │ │ ├── AssignmentDefinitionProps.js │ │ ├── BusinessRuleImplementationProps.js │ │ ├── CalledDecisionProps.js │ │ ├── ConditionProps.js │ │ ├── ErrorProps.js │ │ ├── EscalationProps.js │ │ ├── ExecutionListener.js │ │ ├── ExecutionListenersProps.js │ │ ├── FormProps.js │ │ ├── Header.js │ │ ├── HeaderProps.js │ │ ├── InputOutputParameter.js │ │ ├── InputPropagationProps.js │ │ ├── InputProps.js │ │ ├── MessageProps.js │ │ ├── MultiInstanceProps.js │ │ ├── OutputPropagationProps.js │ │ ├── OutputProps.js │ │ ├── PriorityDefinitionProps.js │ │ ├── ScriptImplementationProps.js │ │ ├── ScriptProps.js │ │ ├── SignalProps.js │ │ ├── TargetProps.js │ │ ├── TaskDefinitionProps.js │ │ ├── TaskListener.js │ │ ├── TaskListenersProps.js │ │ ├── TaskScheduleProps.js │ │ ├── TimerProps.js │ │ ├── UserTaskImplementationProps.js │ │ ├── VersionTagProps.js │ │ ├── index.js │ │ └── shared │ │ │ ├── Binding.js │ │ │ ├── Listener.js │ │ │ └── VersionTag.js │ │ └── utils │ │ ├── CalledElementUtil.js │ │ ├── FormUtil.js │ │ ├── HeadersUtil.js │ │ ├── InputOutputUtil.js │ │ ├── TimerUtil.js │ │ └── ZeebeServiceTaskUtil.js ├── render │ ├── BpmnPropertiesPanel.js │ ├── BpmnPropertiesPanelRenderer.js │ ├── PanelHeaderProvider.js │ ├── PanelPlaceholderProvider.js │ └── index.js └── utils │ ├── ElementUtil.js │ ├── EventDefinitionUtil.js │ ├── ExtensionElementsUtil.js │ ├── FormalExpressionUtil.js │ └── ValidationUtil.js ├── tasks └── wiredeps └── test ├── .eslintrc ├── TestHelper.js ├── coverageBundle.js ├── distro └── distroSpec.js ├── fixtures ├── a11y-c7.bpmn ├── a11y-c8.bpmn ├── integration.bpmn ├── service-task.bpmn └── simple.bpmn ├── spec ├── BpmnPropertiesPanel.spec.js ├── BpmnPropertiesPanelRenderer.spec.js ├── PanelHeaderProvider.spec.js ├── extension │ └── ExamplePropertiesProvider.js ├── mocks │ └── index.js ├── provider │ ├── HOCs │ │ ├── withTooltipContainer.bpmn │ │ ├── withTooltipContainer.spec.js │ │ ├── withVariableContext.bpmn │ │ └── withVariableContext.spec.js │ ├── bpmn │ │ ├── AdHocCompletionProps.bpmn │ │ ├── AdHocCompletionProps.spec.js │ │ ├── BpmnPropertiesProvider.bpmn │ │ ├── BpmnPropertiesProvider.spec.js │ │ ├── CompensationProps.bpmn │ │ ├── CompensationProps.spec.js │ │ ├── DocumentationProps.bpmn │ │ ├── DocumentationProps.spec.js │ │ ├── ErrorProps.bpmn │ │ ├── ErrorProps.spec.js │ │ ├── EscalationProps.bpmn │ │ ├── EscalationProps.spec.js │ │ ├── ExecutableProps.bpmn │ │ ├── ExecutableProps.participants.bpmn │ │ ├── ExecutableProps.spec.js │ │ ├── IdProps.bpmn │ │ ├── IdProps.spec.js │ │ ├── LinkProps.bpmn │ │ ├── LinkProps.spec.js │ │ ├── MessageProps.bpmn │ │ ├── MessageProps.spec.js │ │ ├── MultiInstanceProps.bpmn │ │ ├── MultiInstanceProps.spec.js │ │ ├── NameProps.bpmn │ │ ├── NameProps.spec.js │ │ ├── ProcessProps.bpmn │ │ ├── ProcessProps.spec.js │ │ ├── ReferenceSelect.spec.js │ │ ├── SignalProps.bpmn │ │ ├── SignalProps.spec.js │ │ ├── TimerProps.bpmn │ │ └── TimerProps.spec.js │ ├── camunda-platform │ │ ├── AsynchronousContinuationsProps.bpmn │ │ ├── AsynchronousContinuationsProps.spec.js │ │ ├── BusinessKeyProps.bpmn │ │ ├── BusinessKeyProps.spec.js │ │ ├── CallActivityProps.bpmn │ │ ├── CallActivityProps.spec.js │ │ ├── CamundaPlatformPropertiesProvider-Collaboration.bpmn │ │ ├── CamundaPlatformPropertiesProvider-Process.bpmn │ │ ├── CamundaPlatformPropertiesProvider.spec.js │ │ ├── CandidateStarterProps-Collaboration.bpmn │ │ ├── CandidateStarterProps-Process.bpmn │ │ ├── CandidateStarterProps.spec.js │ │ ├── ConditionProps.bpmn │ │ ├── ConditionProps.spec.js │ │ ├── ConnectorInputProps.bpmn │ │ ├── ConnectorInputProps.spec.js │ │ ├── ConnectorOutputProps.bpmn │ │ ├── ConnectorOutputProps.spec.js │ │ ├── DmnImplementationProps.bpmn │ │ ├── DmnImplementationProps.spec.js │ │ ├── Error.spec.js │ │ ├── ErrorProps.bpmn │ │ ├── ErrorProps.spec.js │ │ ├── ErrorsProps.bpmn │ │ ├── ErrorsProps.spec.js │ │ ├── EscalationProps.bpmn │ │ ├── EscalationProps.spec.js │ │ ├── ExternalTaskPriority-Collaboration.bpmn │ │ ├── ExternalTaskPriority-Process.bpmn │ │ ├── ExternalTaskPriorityProps.spec.js │ │ ├── FieldInjection.spec.js │ │ ├── FieldInjectionProps.spec.js │ │ ├── FieldInjectonProps.bpmn │ │ ├── FormDataProps.bpmn │ │ ├── FormDataProps.spec.js │ │ ├── FormField.bpmn │ │ ├── FormField.spec.js │ │ ├── FormFieldConstraint.spec.js │ │ ├── FormFieldProperty.spec.js │ │ ├── FormFieldValue.spec.js │ │ ├── FormProps.bpmn │ │ ├── FormProps.spec.js │ │ ├── FormTypeProps.spec.js │ │ ├── HistoryCleanupProps-collaboration.bpmn │ │ ├── HistoryCleanupProps-process.bpmn │ │ ├── HistoryCleanupProps.spec.js │ │ ├── ImplementationProps.bpmn │ │ ├── ImplementationProps.spec.js │ │ ├── ImplementationTypeProps.spec.js │ │ ├── InMappingPropagationProps.bpmn │ │ ├── InMappingPropagationProps.spec.js │ │ ├── InMappingProps.bpmn │ │ ├── InMappingProps.spec.js │ │ ├── InOutMapping.bpmn │ │ ├── InOutMapping.spec.js │ │ ├── InitiatorProps.bpmn │ │ ├── InitiatorProps.spec.js │ │ ├── InputOutputParameter.bpmn │ │ ├── InputOutputParameter.spec.js │ │ ├── InputProps.bpmn │ │ ├── InputProps.spec.js │ │ ├── JobExecutionProps-Collaboration.bpmn │ │ ├── JobExecutionProps-Process.bpmn │ │ ├── JobExecutionProps.spec.js │ │ ├── ListProps.bpmn │ │ ├── ListProps.spec.js │ │ ├── ListenerProps.bpmn │ │ ├── ListenerProps.spec.js │ │ ├── MapProps.bpmn │ │ ├── MapProps.spec.js │ │ ├── MultiInstanceProps.bpmn │ │ ├── MultiInstanceProps.spec.js │ │ ├── OutMappingPropagationProps.bpmn │ │ ├── OutMappingPropagationProps.spec.js │ │ ├── OutMappingProps.bpmn │ │ ├── OutMappingProps.spec.js │ │ ├── OutputProps.bpmn │ │ ├── OutputProps.spec.js │ │ ├── ProcessProps.bpmn │ │ ├── ProcessProps.spec.js │ │ ├── ProcessVariablesProps-collaboration.bpmn │ │ ├── ProcessVariablesProps-process.bpmn │ │ ├── ProcessVariablesProps.spec.js │ │ ├── ScriptProps.bpmn │ │ ├── ScriptProps.spec.js │ │ ├── ScriptTaskProps.spec.js │ │ ├── TasklistProps-collaboration.bpmn │ │ ├── TasklistProps-process.bpmn │ │ ├── TasklistProps.spec.js │ │ ├── TimerProps.bpmn │ │ ├── TimerProps.spec.js │ │ ├── UserAssignmentProps.bpmn │ │ ├── UserAssignmentProps.spec.js │ │ ├── VersionTagProps-collaboration.bpmn │ │ ├── VersionTagProps-process.bpmn │ │ └── VersionTagProps.spec.js │ ├── shared │ │ ├── ExtensionPropertiesProps.camunda.bpmn │ │ ├── ExtensionPropertiesProps.spec.js │ │ ├── ExtensionPropertiesProps.zeebe.bpmn │ │ ├── ExtensionProperty.bpmn │ │ └── ExtensionProperty.spec.js │ └── zeebe │ │ ├── ActiveElementsCollectionProps.bpmn │ │ ├── ActiveElementsCollectionProps.spec.js │ │ ├── AdHocCompletionProps.bpmn │ │ ├── AdHocCompletionProps.spec.js │ │ ├── AssignmentDefinitionProps.bpmn │ │ ├── AssignmentDefinitionProps.spec.js │ │ ├── BusinessRuleImplementationProps.bpmn │ │ ├── BusinessRuleImplementationProps.spec.js │ │ ├── CalledDecisionProps.bpmn │ │ ├── CalledDecisionProps.spec.js │ │ ├── ConditionProps.bpmn │ │ ├── ConditionProps.spec.js │ │ ├── ErrorProps.bpmn │ │ ├── ErrorProps.spec.js │ │ ├── EscalationProps.bpmn │ │ ├── EscalationProps.spec.js │ │ ├── ExecutionListenerProps.bpmn │ │ ├── ExecutionListenerProps.spec.js │ │ ├── Forms.bpmn │ │ ├── Forms.spec.js │ │ ├── Header.bpmn │ │ ├── Header.spec.js │ │ ├── HeaderProps.bpmn │ │ ├── HeaderProps.spec.js │ │ ├── InputOutputParameter.bpmn │ │ ├── InputOutputParameter.spec.js │ │ ├── InputPropagationProps.bpmn │ │ ├── InputPropagationProps.spec.js │ │ ├── InputProps.bpmn │ │ ├── InputProps.spec.js │ │ ├── MessageProps.bpmn │ │ ├── MessageProps.spec.js │ │ ├── MultiInstanceProps.bpmn │ │ ├── MultiInstanceProps.spec.js │ │ ├── OutputPropagationProps.bpmn │ │ ├── OutputPropagationProps.spec.js │ │ ├── OutputProps.bpmn │ │ ├── OutputProps.spec.js │ │ ├── PriorityDefinitionProps.bpmn │ │ ├── PriorityDefinitionProps.spec.js │ │ ├── ScriptImplementationProps.bpmn │ │ ├── ScriptImplementationProps.spec.js │ │ ├── ScriptProps.bpmn │ │ ├── ScriptProps.spec.js │ │ ├── SignalProps.bpmn │ │ ├── SignalProps.spec.js │ │ ├── TargetProps.bpmn │ │ ├── TargetProps.spec.js │ │ ├── TaskDefinitionProps.bpmn │ │ ├── TaskDefinitionProps.spec.js │ │ ├── TaskListenerProps.bpmn │ │ ├── TaskListenerProps.spec.js │ │ ├── TaskScheduleProps.bpmn │ │ ├── TaskScheduleProps.spec.js │ │ ├── TimerProps.bpmn │ │ ├── TimerProps.spec.js │ │ ├── UserTaskImplementationProps.bpmn │ │ ├── UserTaskImplementationProps.spec.js │ │ ├── VersionTagProps-collaboration.bpmn │ │ ├── VersionTagProps-process.bpmn │ │ ├── VersionTagProps.spec.js │ │ ├── ZeebePropertiesProvider.bpmn │ │ └── ZeebePropertiesProvider.spec.js └── utils │ ├── ImplementationTypeUtils.spec.js │ ├── TimerUtil.bpmn │ └── TimerUtilSpec.js ├── test.css ├── testBundle.js └── util └── KeyEvents.js /.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 8 | 9 | 10 | ### Expected Behavior 11 | 12 | 13 | ### Actual Behavior 14 | 15 | 16 | ### Steps to reproduce the Behavior 17 | -------------------------------------------------------------------------------- /.github/workflows/CI.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | on: [ push, pull_request ] 3 | jobs: 4 | Build: 5 | runs-on: ubuntu-latest 6 | continue-on-error: ${{ matrix.integration }} 7 | strategy: 8 | matrix: 9 | integration: [ true ] 10 | integration-deps: 11 | - diagram-js@11.9 bpmn-js@11.5 12 | - "@bpmn-io/properties-panel@3" 13 | include: 14 | - integration-deps: "" # as defined in package.json 15 | integration: false 16 | 17 | steps: 18 | - name: Checkout 19 | uses: actions/checkout@v4 20 | - name: Use Node.js 21 | uses: actions/setup-node@v4 22 | with: 23 | node-version: 20 24 | cache: 'npm' 25 | - name: Install dependencies 26 | run: npm ci 27 | - name: Install dependencies for integration test 28 | if: ${{ matrix.integration-deps != '' }} 29 | run: npm install ${{ matrix.integration-deps }} 30 | - name: Project setup 31 | uses: bpmn-io/actions/setup@latest 32 | - name: Build 33 | if: ${{ matrix.integration-deps != '' }} 34 | run: npm run all 35 | - name: Build with coverage 36 | if: ${{ matrix.integration-deps == '' }} 37 | env: 38 | COVERAGE: 1 39 | run: npm run all 40 | - name: Upload coverage 41 | if: ${{ matrix.integration-deps == '' }} 42 | uses: codecov/codecov-action@v5 43 | with: 44 | fail_ci_if_error: true 45 | env: 46 | CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} 47 | -------------------------------------------------------------------------------- /.github/workflows/CODE_SCANNING.yml: -------------------------------------------------------------------------------- 1 | name: "Code Scanning" 2 | 3 | on: 4 | push: 5 | branches: [ master, develop ] 6 | pull_request: 7 | branches: [ master, develop ] 8 | paths-ignore: 9 | - '**/*.md' 10 | 11 | jobs: 12 | CodeQL-Build: 13 | # CodeQL runs on ubuntu-latest, windows-latest, and macos-latest 14 | runs-on: ubuntu-latest 15 | 16 | permissions: 17 | # required for all workflows 18 | security-events: write 19 | 20 | steps: 21 | - name: Checkout repository 22 | uses: actions/checkout@v4 23 | 24 | # Initializes the CodeQL tools for scanning. 25 | - name: Initialize CodeQL 26 | uses: github/codeql-action/init@v3 27 | with: 28 | languages: javascript 29 | config: | 30 | paths-ignore: 31 | - '**/test' 32 | 33 | - name: Perform CodeQL Analysis 34 | uses: github/codeql-action/analyze@v3 35 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | coverage 3 | dist 4 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 camunda Services GmbH 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. -------------------------------------------------------------------------------- /codecov.yml: -------------------------------------------------------------------------------- 1 | comment: off 2 | 3 | parsers: 4 | javascript: 5 | enable_partials: yes -------------------------------------------------------------------------------- /docs/RELEASE_CHECKLIST.md: -------------------------------------------------------------------------------- 1 | # RELEASE CHECKLIST 2 | 3 | ```markdown 4 | * [ ] make sure changes in upstream libraries are merged and released 5 | * `bpmn-js`, `diagram-js`, `*-moddle` 6 | * [ ] make sure dependencies to upstream libraries are updated and can be installed (`rm -rf node_modules && npm i && npm run all` works) 7 | * [ ] update CHANGELOG 8 | * [ ] perform integration test locally using [properties-panel example](https://github.com/bpmn-io/bpmn-js-examples/tree/master/properties-panel) 9 | * [ ] perform semantic release 10 | * [ ] (if appropriate) write blog post 11 | * [ ] (if appropriate) spread the word 12 | ``` 13 | -------------------------------------------------------------------------------- /docs/screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bpmn-io/bpmn-js-properties-panel/1a70a653833b23ac558618a0e4ed309765cef0b6/docs/screenshot.png -------------------------------------------------------------------------------- /eslint.config.mjs: -------------------------------------------------------------------------------- 1 | import bpmnIoPlugin from 'eslint-plugin-bpmn-io'; 2 | import reactHooksPlugin from 'eslint-plugin-react-hooks'; 3 | import importPlugin from 'eslint-plugin-import'; 4 | 5 | const files = { 6 | build: [ 7 | '*.js', 8 | '*.mjs', 9 | 'test/distro/distroSpec.js' 10 | ], 11 | test: [ 12 | 'test/**/*.js' 13 | ], 14 | ignored: [ 15 | 'dist' 16 | ] 17 | }; 18 | 19 | 20 | export default [ 21 | { 22 | ignores: files.ignored 23 | }, 24 | 25 | // build 26 | ...bpmnIoPlugin.configs.node.map(config => { 27 | return { 28 | ...config, 29 | files: files.build 30 | }; 31 | }), 32 | 33 | // lib + test 34 | ...bpmnIoPlugin.configs.browser.map(config => { 35 | return { 36 | ...config, 37 | ignores: files.build 38 | }; 39 | }), 40 | ...bpmnIoPlugin.configs.jsx.map(config => { 41 | return { 42 | ...config, 43 | ignores: files.build 44 | }; 45 | }), 46 | 47 | // misc 48 | { 49 | plugins: { 50 | 'react-hooks': reactHooksPlugin, 51 | import: importPlugin 52 | }, 53 | rules: { 54 | ...reactHooksPlugin.configs.recommended.rules, 55 | 'import/first': 'error', 56 | 'import/no-amd': 'error', 57 | 'import/no-webpack-loader-syntax': 'error', 58 | 'react-hooks/exhaustive-deps': 'off' 59 | }, 60 | ignores: files.build 61 | }, 62 | { 63 | rules: { 64 | 'react/display-name': 'off', 65 | 'react/no-unescaped-entities': 'off' 66 | } 67 | }, 68 | 69 | // test 70 | ...bpmnIoPlugin.configs.mocha.map(config => { 71 | return { 72 | ...config, 73 | files: files.test 74 | }; 75 | }), 76 | { 77 | languageOptions: { 78 | globals: { 79 | sinon: true, 80 | require: true 81 | }, 82 | }, 83 | files: files.test 84 | } 85 | ]; 86 | -------------------------------------------------------------------------------- /renovate.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://docs.renovatebot.com/renovate-schema.json", 3 | "extends": [ 4 | "github>bpmn-io/renovate-config:recommended" 5 | ] 6 | } 7 | -------------------------------------------------------------------------------- /rollup.config.mjs: -------------------------------------------------------------------------------- 1 | import alias from '@rollup/plugin-alias'; 2 | import babel from '@rollup/plugin-babel'; 3 | import commonjs from '@rollup/plugin-commonjs'; 4 | import json from '@rollup/plugin-json'; 5 | import reactSvg from 'rollup-plugin-react-svg'; 6 | import resolve from '@rollup/plugin-node-resolve'; 7 | 8 | import { 9 | readFileSync 10 | } from 'fs'; 11 | 12 | const pkg = importPkg(); 13 | 14 | const nonbundledDependencies = Object.keys({ ...pkg.dependencies, ...pkg.peerDependencies }); 15 | const nonExternalDependencies = [ 'preact-markup' ]; 16 | 17 | export default [ 18 | { 19 | input: 'src/index.js', 20 | output: [ 21 | { 22 | sourcemap: true, 23 | format: 'umd', 24 | file: pkg['umd:main'], 25 | name: 'BpmnJSPropertiesPanel' 26 | } 27 | ], 28 | plugins: pgl() 29 | }, 30 | { 31 | input: 'src/index.js', 32 | output: [ 33 | { 34 | sourcemap: true, 35 | format: 'commonjs', 36 | file: pkg.main 37 | }, 38 | { 39 | sourcemap: true, 40 | format: 'esm', 41 | file: pkg.module 42 | } 43 | ], 44 | external: externalDependencies(), 45 | plugins: pgl() 46 | } 47 | ]; 48 | 49 | function pgl(plugins = []) { 50 | return [ 51 | ...plugins, 52 | alias({ 53 | entries: [ 54 | { find: 'react', replacement: '@bpmn-io/properties-panel/preact/compat' }, 55 | { find: 'preact', replacement: '@bpmn-io/properties-panel/preact' } 56 | ] 57 | }), 58 | reactSvg(), 59 | babel({ 60 | babelHelpers: 'bundled', 61 | plugins: [ 62 | [ '@babel/plugin-transform-react-jsx', { 63 | 'importSource': '@bpmn-io/properties-panel/preact', 64 | 'runtime': 'automatic' 65 | } ] 66 | ] 67 | }), 68 | json(), 69 | resolve({ 70 | mainFields: [ 71 | 'browser', 72 | 'module', 73 | 'main' 74 | ] 75 | }), 76 | commonjs() 77 | ]; 78 | } 79 | 80 | function externalDependencies() { 81 | return id => { 82 | return nonbundledDependencies.find(dep => id.startsWith(dep)) && 83 | !nonExternalDependencies.find(dep => id.startsWith(dep)); 84 | }; 85 | } 86 | 87 | function importPkg() { 88 | return JSON.parse(readFileSync('./package.json', { encoding:'utf8' })); 89 | } -------------------------------------------------------------------------------- /src/cmd/MultiCommandHandler.js: -------------------------------------------------------------------------------- 1 | import { 2 | forEach 3 | } from 'min-dash'; 4 | 5 | /** 6 | * A handler that combines and executes multiple commands. 7 | * 8 | * All updates are bundled on the command stack and executed in one step. 9 | * This also makes it possible to revert the changes in one step. 10 | * 11 | * Example use case: remove the camunda:formKey attribute and in addition 12 | * add all form fields needed for the camunda:formData property. 13 | */ 14 | export default class MultiCommandHandler { 15 | constructor(commandStack) { 16 | this._commandStack = commandStack; 17 | } 18 | 19 | preExecute(context) { 20 | const commandStack = this._commandStack; 21 | 22 | forEach(context, function(command) { 23 | commandStack.execute(command.cmd, command.context); 24 | }); 25 | } 26 | } 27 | 28 | MultiCommandHandler.$inject = [ 'commandStack' ]; -------------------------------------------------------------------------------- /src/cmd/index.js: -------------------------------------------------------------------------------- 1 | import { 2 | forEach 3 | } from 'min-dash'; 4 | 5 | import MultiCommandHandler from './MultiCommandHandler'; 6 | 7 | const HANDLERS = { 8 | 'properties-panel.multi-command-executor': MultiCommandHandler 9 | }; 10 | 11 | 12 | function CommandInitializer(eventBus, commandStack) { 13 | 14 | eventBus.on('diagram.init', function() { 15 | forEach(HANDLERS, function(handler, id) { 16 | commandStack.registerHandler(id, handler); 17 | }); 18 | }); 19 | } 20 | 21 | CommandInitializer.$inject = [ 'eventBus', 'commandStack' ]; 22 | 23 | export default { 24 | __init__: [ CommandInitializer ] 25 | }; -------------------------------------------------------------------------------- /src/context/BpmnPropertiesPanelContext.js: -------------------------------------------------------------------------------- 1 | import { 2 | createContext 3 | } from '@bpmn-io/properties-panel/preact'; 4 | 5 | const BpmnPropertiesPanelContext = createContext({ 6 | selectedElement: null, 7 | injector: null, 8 | getService() { return null; } 9 | }); 10 | 11 | export default BpmnPropertiesPanelContext; -------------------------------------------------------------------------------- /src/context/index.js: -------------------------------------------------------------------------------- 1 | export { default as BpmnPropertiesPanelContext } from './BpmnPropertiesPanelContext'; -------------------------------------------------------------------------------- /src/contextProvider/camunda-platform/TooltipProvider.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable react-hooks/rules-of-hooks */ 2 | 3 | import { 4 | useService 5 | } from '../../hooks'; 6 | 7 | const TooltipProvider = { 8 | 'historyTimeToLive': (element) => { 9 | 10 | const translate = useService('translate'); 11 | 12 | return ( 13 |
14 |

15 | { translate('Number of days before this resource is being cleaned up. If specified, takes precedence over the engine configuration.') }{ ' '} 16 | { translate('Learn more.') } 17 |

18 |
19 | ); 20 | } 21 | }; 22 | 23 | export default TooltipProvider; 24 | -------------------------------------------------------------------------------- /src/contextProvider/camunda-platform/index.js: -------------------------------------------------------------------------------- 1 | export { default as TooltipProvider } from './TooltipProvider'; -------------------------------------------------------------------------------- /src/contextProvider/zeebe/index.js: -------------------------------------------------------------------------------- 1 | export { default as TooltipProvider } from './TooltipProvider'; -------------------------------------------------------------------------------- /src/entries/FeelEntryWithContext.js: -------------------------------------------------------------------------------- 1 | import { FeelEntry as BaseFeelEntry, FeelTextAreaEntry as BaseFeelTextAreaEntry } from '@bpmn-io/properties-panel'; 2 | import { withTooltipContainer, withVariableContext } from '../provider/HOCs'; 3 | 4 | export const FeelEntry = withTooltipContainer(BaseFeelEntry); 5 | export const FeelTextAreaEntry = withTooltipContainer(BaseFeelTextAreaEntry); 6 | 7 | export const FeelEntryWithVariableContext = withVariableContext(FeelEntry); 8 | export const FeelTextAreaEntryWithVariableContext = withVariableContext(FeelTextAreaEntry); -------------------------------------------------------------------------------- /src/entries/ReferenceSelect.js: -------------------------------------------------------------------------------- 1 | import { 2 | useEffect 3 | } from '@bpmn-io/properties-panel/preact/hooks'; 4 | 5 | import { 6 | query as domQuery 7 | } from 'min-dom'; 8 | 9 | import { 10 | SelectEntry, 11 | usePrevious 12 | } from '@bpmn-io/properties-panel'; 13 | 14 | 15 | export default function ReferenceSelectEntry(props) { 16 | const { 17 | autoFocusEntry, 18 | element, 19 | getOptions 20 | } = props; 21 | 22 | const options = getOptions(element); 23 | const prevOptions = usePrevious(options); 24 | 25 | // auto focus specifc other entry when options changed 26 | useEffect(() => { 27 | if (autoFocusEntry && prevOptions && options.length > prevOptions.length) { 28 | 29 | const entry = domQuery(`[data-entry-id="${autoFocusEntry}"]`); 30 | 31 | const focusableInput = domQuery('.bio-properties-panel-input', entry); 32 | 33 | if (focusableInput) { 34 | focusableInput.select(); 35 | } 36 | } 37 | }, [ options ]); 38 | 39 | return ( 40 | 41 | ); 42 | } -------------------------------------------------------------------------------- /src/hooks/index.js: -------------------------------------------------------------------------------- 1 | export { useService } from './useService'; -------------------------------------------------------------------------------- /src/hooks/useService.js: -------------------------------------------------------------------------------- 1 | import { 2 | useContext 3 | } from '@bpmn-io/properties-panel/preact/hooks'; 4 | 5 | import { BpmnPropertiesPanelContext } from '../context'; 6 | 7 | export function useService(type, strict) { 8 | const { 9 | getService 10 | } = useContext(BpmnPropertiesPanelContext); 11 | 12 | return getService(type, strict); 13 | } -------------------------------------------------------------------------------- /src/icons/bpmn-empty-state.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /src/icons/bpmn-icon-association.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/icons/bpmn-icon-business-rule-task.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /src/icons/bpmn-icon-call-activity.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/icons/bpmn-icon-collaboration.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /src/icons/bpmn-icon-conditional-flow.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/icons/bpmn-icon-connection.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/icons/bpmn-icon-data-input-output-association.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /src/icons/bpmn-icon-data-input.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/icons/bpmn-icon-data-object.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/icons/bpmn-icon-data-output.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/icons/bpmn-icon-default-flow.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/icons/bpmn-icon-end-event-cancel.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/icons/bpmn-icon-end-event-compensation.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/icons/bpmn-icon-end-event-error.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/icons/bpmn-icon-end-event-escalation.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/icons/bpmn-icon-end-event-link.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/icons/bpmn-icon-end-event-message.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/icons/bpmn-icon-end-event-multiple.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/icons/bpmn-icon-end-event-none.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/icons/bpmn-icon-end-event-signal.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/icons/bpmn-icon-end-event-terminate.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/icons/bpmn-icon-gateway-eventbased.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/icons/bpmn-icon-gateway-none.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/icons/bpmn-icon-gateway-or.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/icons/bpmn-icon-intermediate-event-catch-escalation.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/icons/bpmn-icon-intermediate-event-catch-signal.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/icons/bpmn-icon-intermediate-event-none.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/icons/bpmn-icon-intermediate-event-throw-compensation.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/icons/bpmn-icon-intermediate-event-throw-escalation.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/icons/bpmn-icon-intermediate-event-throw-link.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/icons/bpmn-icon-intermediate-event-throw-message.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/icons/bpmn-icon-intermediate-event-throw-multiple.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/icons/bpmn-icon-intermediate-event-throw-signal.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/icons/bpmn-icon-lane.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/icons/bpmn-icon-message-flow.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/icons/bpmn-icon-participant.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/icons/bpmn-icon-receive-task.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/icons/bpmn-icon-send-task.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/icons/bpmn-icon-start-event-compensation.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/icons/bpmn-icon-start-event-condition.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/icons/bpmn-icon-start-event-error.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/icons/bpmn-icon-start-event-escalation.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/icons/bpmn-icon-start-event-message.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/icons/bpmn-icon-start-event-multiple.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/icons/bpmn-icon-start-event-none.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/icons/bpmn-icon-start-event-parallel-multiple.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/icons/bpmn-icon-start-event-signal.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/icons/bpmn-icon-start-event-timer.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/icons/bpmn-icon-subprocess-collapsed.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/icons/bpmn-icon-subprocess-expanded.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/icons/bpmn-icon-task-none.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/icons/bpmn-icon-text-annotation.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/icons/bpmn-icon-transaction.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/icons/bpmn-multiple-state.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | export { default as BpmnPropertiesPanelModule } from './render'; 2 | export { default as BpmnPropertiesProviderModule } from './provider/bpmn'; 3 | export { default as ZeebePropertiesProviderModule } from './provider/zeebe'; 4 | export { default as CamundaPlatformPropertiesProviderModule } from './provider/camunda-platform'; 5 | export { TooltipProvider as ZeebeTooltipProvider } from './contextProvider/zeebe'; 6 | export { TooltipProvider as CamundaPlatformTooltipProvider } from './contextProvider/camunda-platform'; 7 | 8 | // hooks 9 | export { useService } from './hooks'; 10 | -------------------------------------------------------------------------------- /src/provider/HOCs/index.js: -------------------------------------------------------------------------------- 1 | export { withProps } from './withProps'; 2 | export { withVariableContext } from './withVariableContext'; 3 | export { withTooltipContainer } from './withTooltipContainer'; -------------------------------------------------------------------------------- /src/provider/HOCs/withProps.js: -------------------------------------------------------------------------------- 1 | export function withProps(Component, otherProps) { 2 | return props => { 3 | return ; 4 | }; 5 | } -------------------------------------------------------------------------------- /src/provider/HOCs/withTooltipContainer.js: -------------------------------------------------------------------------------- 1 | import { useMemo } from '@bpmn-io/properties-panel/preact/hooks'; 2 | import { useService } from '../../hooks'; 3 | 4 | export function withTooltipContainer(Component) { 5 | return props => { 6 | const tooltipContainer = useMemo(() => { 7 | const config = useService('config'); 8 | 9 | return config && config.propertiesPanel && config.propertiesPanel.feelTooltipContainer; 10 | }, [ ]); 11 | 12 | return ; 15 | }; 16 | } -------------------------------------------------------------------------------- /src/provider/HOCs/withVariableContext.js: -------------------------------------------------------------------------------- 1 | import { getVariablesForElement } from '@bpmn-io/extract-process-variables/zeebe'; 2 | import { useEffect, useState } from '@bpmn-io/properties-panel/preact/hooks'; 3 | import { useService } from '../../hooks'; 4 | 5 | const fallbackResolver = { 6 | getVariablesForElement: bo => getVariablesForElement(bo) 7 | }; 8 | 9 | export function withVariableContext(Component) { 10 | return props => { 11 | const { bpmnElement, element } = props; 12 | 13 | const bo = (bpmnElement || element).businessObject; 14 | 15 | const [ variables, setVariables ] = useState([]); 16 | const eventBus = useService('eventBus'); 17 | 18 | const variableResolver = useServiceIfAvailable('variableResolver', fallbackResolver); 19 | 20 | useEffect(() => { 21 | const extractVariables = async () => { 22 | 23 | const variables = await variableResolver.getVariablesForElement(bo, element); 24 | 25 | setVariables(variables.map(variable => { 26 | return { 27 | ...variable, 28 | info: variable.info || 29 | (variable.origin && ('Written in ' + variable.origin.map(origin => origin.name || origin.id).join(', '))) 30 | }; 31 | })); 32 | }; 33 | 34 | // The callback must return undefined, so the event propagation is not canceled. 35 | // Cf. https://github.com/camunda/camunda-modeler/issues/3392 36 | const callback = () => { 37 | extractVariables(); 38 | }; 39 | 40 | eventBus.on('commandStack.changed', callback); 41 | callback(); 42 | 43 | return () => { 44 | eventBus.off('commandStack.changed', callback); 45 | }; 46 | }, [ bo ]); 47 | 48 | return ; 49 | }; 50 | } 51 | 52 | // helpers ////////// 53 | 54 | function useServiceIfAvailable(service, fallback) { 55 | const resolved = useService(service, false); 56 | 57 | if (!resolved) { 58 | return fallback; 59 | } 60 | 61 | return resolved; 62 | } 63 | -------------------------------------------------------------------------------- /src/provider/bpmn/index.js: -------------------------------------------------------------------------------- 1 | import BpmnPropertiesProvider from './BpmnPropertiesProvider'; 2 | 3 | export default { 4 | __init__: [ 'bpmnPropertiesProvider' ], 5 | bpmnPropertiesProvider: [ 'type', BpmnPropertiesProvider ] 6 | }; -------------------------------------------------------------------------------- /src/provider/bpmn/properties/ExecutableProps.js: -------------------------------------------------------------------------------- 1 | import { 2 | is 3 | } from 'bpmn-js/lib/util/ModelUtil'; 4 | 5 | import { CheckboxEntry, isCheckboxEntryEdited } from '@bpmn-io/properties-panel'; 6 | 7 | import { 8 | useService 9 | } from '../../../hooks'; 10 | 11 | 12 | /** 13 | * @typedef { import('@bpmn-io/properties-panel').EntryDefinition } Entry 14 | */ 15 | 16 | /** 17 | * @returns {Array} entries 18 | */ 19 | export function ExecutableProps(props) { 20 | const { 21 | element 22 | } = props; 23 | 24 | if (!is(element, 'bpmn:Process') && !hasProcessRef(element)) { 25 | return []; 26 | } 27 | 28 | return [ 29 | { 30 | id: 'isExecutable', 31 | component: Executable, 32 | isEdited: isCheckboxEntryEdited 33 | } 34 | ]; 35 | } 36 | 37 | function Executable(props) { 38 | const { 39 | element 40 | } = props; 41 | 42 | const modeling = useService('modeling'); 43 | const commandStack = useService('commandStack'); 44 | const translate = useService('translate'); 45 | 46 | let getValue, setValue; 47 | 48 | setValue = (value) => { 49 | modeling.updateProperties(element, { 50 | isExecutable: value 51 | }); 52 | }; 53 | 54 | getValue = (element) => { 55 | return element.businessObject.isExecutable; 56 | }; 57 | 58 | // handle properties on processRef level for participants 59 | if (is(element, 'bpmn:Participant')) { 60 | 61 | const process = element.businessObject.get('processRef'); 62 | 63 | setValue = (value) => { 64 | commandStack.execute( 65 | 'element.updateModdleProperties', 66 | { 67 | element, 68 | moddleElement: process, 69 | properties: { 70 | isExecutable: value 71 | } 72 | } 73 | ); 74 | }; 75 | 76 | getValue = () => { 77 | return process.get('isExecutable'); 78 | }; 79 | 80 | } 81 | 82 | return CheckboxEntry({ 83 | element, 84 | id: 'isExecutable', 85 | label: translate('Executable'), 86 | getValue, 87 | setValue 88 | }); 89 | } 90 | 91 | 92 | // helper ///////////////////// 93 | 94 | function hasProcessRef(element) { 95 | return is(element, 'bpmn:Participant') && element.businessObject.get('processRef'); 96 | } -------------------------------------------------------------------------------- /src/provider/bpmn/properties/IdProps.js: -------------------------------------------------------------------------------- 1 | import { 2 | getBusinessObject, 3 | is 4 | } from 'bpmn-js/lib/util/ModelUtil'; 5 | 6 | import { TextFieldEntry, isTextFieldEntryEdited } from '@bpmn-io/properties-panel'; 7 | 8 | import { useCallback } from '@bpmn-io/properties-panel/preact/hooks'; 9 | 10 | import { 11 | useService 12 | } from '../../../hooks'; 13 | 14 | import { 15 | isIdValid 16 | } from '../../../utils/ValidationUtil'; 17 | 18 | 19 | /** 20 | * @typedef { import('@bpmn-io/properties-panel').EntryDefinition } Entry 21 | */ 22 | 23 | /** 24 | * @returns {Array} entries 25 | */ 26 | export function IdProps() { 27 | return [ 28 | { 29 | id: 'id', 30 | component: Id, 31 | isEdited: isTextFieldEntryEdited 32 | } 33 | ]; 34 | } 35 | 36 | function Id(props) { 37 | const { 38 | element 39 | } = props; 40 | 41 | const modeling = useService('modeling'); 42 | const debounce = useService('debounceInput'); 43 | const translate = useService('translate'); 44 | 45 | const setValue = (value, error) => { 46 | if (error) { 47 | return; 48 | } 49 | 50 | modeling.updateProperties(element, { 51 | id: value 52 | }); 53 | }; 54 | 55 | const getValue = useCallback((element) => { 56 | return getBusinessObject(element).id; 57 | }, [ element ]); 58 | 59 | const validate = useCallback((value) => { 60 | const businessObject = getBusinessObject(element); 61 | 62 | return isIdValid(businessObject, value, translate); 63 | }, [ element, translate ]); 64 | 65 | return TextFieldEntry({ 66 | element, 67 | id: 'id', 68 | label: translate(is(element, 'bpmn:Participant') ? 'Participant ID' : 'ID'), 69 | getValue, 70 | setValue, 71 | debounce, 72 | validate 73 | }); 74 | } -------------------------------------------------------------------------------- /src/provider/bpmn/properties/LinkProps.js: -------------------------------------------------------------------------------- 1 | import { TextFieldEntry, isTextFieldEntryEdited } from '@bpmn-io/properties-panel'; 2 | 3 | import { 4 | useService 5 | } from '../../../hooks'; 6 | 7 | import { 8 | getLinkEventDefinition, 9 | isLinkSupported 10 | } from '../utils/EventDefinitionUtil'; 11 | 12 | /** 13 | * @typedef { import('@bpmn-io/properties-panel').EntryDefinition } Entry 14 | */ 15 | 16 | /** 17 | * @returns {Array} entries 18 | */ 19 | export function LinkProps(props) { 20 | const { 21 | element 22 | } = props; 23 | 24 | if (!isLinkSupported(element)) { 25 | return []; 26 | } 27 | 28 | return [ 29 | { 30 | id: 'linkName', 31 | component: LinkName, 32 | isEdited: isTextFieldEntryEdited 33 | }, 34 | ]; 35 | } 36 | 37 | function LinkName(props) { 38 | const { element } = props; 39 | 40 | const commandStack = useService('commandStack'); 41 | const translate = useService('translate'); 42 | const debounce = useService('debounceInput'); 43 | 44 | const linkEventDefinition = getLinkEventDefinition(element); 45 | 46 | const getValue = () => { 47 | return linkEventDefinition.get('name'); 48 | }; 49 | 50 | const setValue = (value) => { 51 | commandStack.execute('element.updateModdleProperties', { 52 | element, 53 | moddleElement: linkEventDefinition, 54 | properties: { 55 | name: value 56 | } 57 | }); 58 | }; 59 | 60 | return TextFieldEntry({ 61 | element, 62 | id: 'linkName', 63 | label: translate('Name'), 64 | getValue, 65 | setValue, 66 | debounce 67 | }); 68 | } 69 | -------------------------------------------------------------------------------- /src/provider/bpmn/properties/index.js: -------------------------------------------------------------------------------- 1 | export { AdHocCompletionProps } from './AdHocCompletionProps'; 2 | export { CompensationProps } from './CompensationProps'; 3 | export { DocumentationProps } from './DocumentationProps'; 4 | export { ErrorProps } from './ErrorProps'; 5 | export { EscalationProps } from './EscalationProps'; 6 | export { ExecutableProps } from './ExecutableProps'; 7 | export { IdProps } from './IdProps'; 8 | export { LinkProps } from './LinkProps'; 9 | export { MessageProps } from './MessageProps'; 10 | export { MultiInstanceProps } from './MultiInstanceProps'; 11 | export { NameProps } from './NameProps'; 12 | export { ProcessProps } from './ProcessProps'; 13 | export { SignalProps } from './SignalProps'; 14 | export { TimerProps } from './TimerProps'; 15 | -------------------------------------------------------------------------------- /src/provider/camunda-platform/index.js: -------------------------------------------------------------------------------- 1 | import CamundaPlatformPropertiesProvider from './CamundaPlatformPropertiesProvider'; 2 | 3 | export default { 4 | __init__: [ 'camundaPlatformPropertiesProvider' ], 5 | camundaPlatformPropertiesProvider: [ 'type', CamundaPlatformPropertiesProvider ] 6 | }; -------------------------------------------------------------------------------- /src/provider/camunda-platform/properties/EscalationProps.js: -------------------------------------------------------------------------------- 1 | import { 2 | is 3 | } from 'bpmn-js/lib/util/ModelUtil'; 4 | 5 | import { TextFieldEntry, isTextFieldEntryEdited } from '@bpmn-io/properties-panel'; 6 | 7 | import { 8 | useService 9 | } from '../../../hooks'; 10 | 11 | import { 12 | getEscalationEventDefinition, 13 | isEscalationSupported 14 | } from '../../bpmn/utils/EventDefinitionUtil'; 15 | 16 | /** 17 | * @typedef { import('@bpmn-io/properties-panel').EntryDefinition } Entry 18 | */ 19 | 20 | /** 21 | * @returns {Array} entries 22 | */ 23 | export function EscalationProps(props) { 24 | const { 25 | element, 26 | entries 27 | } = props; 28 | 29 | if (!(isEscalationSupported(element) && canHaveEscalationVariables(element))) { 30 | return entries; 31 | } 32 | 33 | entries.push( 34 | { 35 | id: 'escalationCodeVariable', 36 | component: EscalationCodeVariable, 37 | isEdited: isTextFieldEntryEdited 38 | } 39 | ); 40 | 41 | return entries; 42 | } 43 | 44 | function EscalationCodeVariable(props) { 45 | const { element } = props; 46 | 47 | const commandStack = useService('commandStack'); 48 | const translate = useService('translate'); 49 | const debounce = useService('debounceInput'); 50 | 51 | const escalationEventDefinition = getEscalationEventDefinition(element); 52 | 53 | const getValue = () => { 54 | return escalationEventDefinition.get('camunda:escalationCodeVariable'); 55 | }; 56 | 57 | const setValue = (value) => { 58 | return commandStack.execute( 59 | 'element.updateModdleProperties', 60 | { 61 | element, 62 | moddleElement: escalationEventDefinition, 63 | properties: { 64 | 'camunda:escalationCodeVariable': value 65 | } 66 | } 67 | ); 68 | }; 69 | 70 | return TextFieldEntry({ 71 | element, 72 | id: 'escalationCodeVariable', 73 | label: translate('Code variable'), 74 | description: translate('Define the name of the variable that will contain the escalation code.'), 75 | getValue, 76 | setValue, 77 | debounce 78 | }); 79 | } 80 | 81 | 82 | // helper /////////////////////// 83 | 84 | function canHaveEscalationVariables(element) { 85 | return is(element, 'bpmn:StartEvent') || is(element, 'bpmn:BoundaryEvent'); 86 | } -------------------------------------------------------------------------------- /src/provider/camunda-platform/properties/FormFieldValue.js: -------------------------------------------------------------------------------- 1 | import { TextFieldEntry } from '@bpmn-io/properties-panel'; 2 | 3 | import { 4 | useService 5 | } from '../../../hooks'; 6 | 7 | 8 | export default function FormFieldValue(props) { 9 | 10 | const { 11 | element, 12 | idPrefix, 13 | value 14 | } = props; 15 | 16 | const entries = [ 17 | { 18 | id: idPrefix + '-id', 19 | component: Id, 20 | idPrefix, 21 | value, 22 | element 23 | }, 24 | { 25 | id: idPrefix + '-name', 26 | component: Name, 27 | idPrefix, 28 | value, 29 | element 30 | } ]; 31 | 32 | return entries; 33 | } 34 | 35 | function Id(props) { 36 | const { 37 | idPrefix, 38 | element, 39 | value 40 | } = props; 41 | 42 | const commandStack = useService('commandStack'), 43 | translate = useService('translate'), 44 | debounce = useService('debounceInput'); 45 | 46 | const setValue = (val) => { 47 | commandStack.execute('element.updateModdleProperties', { 48 | element, 49 | moddleElement: value, 50 | properties: { 51 | id: val 52 | } 53 | }); 54 | }; 55 | 56 | const getValue = () => { 57 | return value.id; 58 | }; 59 | 60 | return TextFieldEntry({ 61 | element: value, 62 | id: idPrefix + '-id', 63 | label: translate('ID'), 64 | getValue, 65 | setValue, 66 | debounce 67 | }); 68 | } 69 | 70 | function Name(props) { 71 | const { 72 | idPrefix, 73 | element, 74 | value 75 | } = props; 76 | 77 | const commandStack = useService('commandStack'), 78 | translate = useService('translate'), 79 | debounce = useService('debounceInput'); 80 | 81 | const setValue = (val) => { 82 | commandStack.execute('element.updateModdleProperties', { 83 | element, 84 | moddleElement: value, 85 | properties: { 86 | name: val 87 | } 88 | }); 89 | }; 90 | 91 | const getValue = () => { 92 | return value.name; 93 | }; 94 | 95 | return TextFieldEntry({ 96 | element: value, 97 | id: idPrefix + '-name', 98 | label: translate('Name'), 99 | getValue, 100 | setValue, 101 | debounce 102 | }); 103 | } 104 | -------------------------------------------------------------------------------- /src/provider/camunda-platform/properties/HistoryCleanupProps.js: -------------------------------------------------------------------------------- 1 | import { 2 | getBusinessObject, 3 | is 4 | } from 'bpmn-js/lib/util/ModelUtil'; 5 | 6 | import { TextFieldEntry, isTextFieldEntryEdited } from '@bpmn-io/properties-panel'; 7 | 8 | import { 9 | useService 10 | } from '../../../hooks'; 11 | 12 | 13 | export function HistoryCleanupProps(props) { 14 | const { 15 | element 16 | } = props; 17 | 18 | const businessObject = getBusinessObject(element); 19 | 20 | if (!is(element, 'bpmn:Process') && 21 | !(is(element, 'bpmn:Participant') && businessObject.get('processRef'))) { 22 | return []; 23 | } 24 | 25 | return [ 26 | { 27 | id: 'historyTimeToLive', 28 | component: HistoryTimeToLive, 29 | isEdited: isTextFieldEntryEdited 30 | }, 31 | ]; 32 | } 33 | 34 | function HistoryTimeToLive(props) { 35 | const { element } = props; 36 | 37 | const commandStack = useService('commandStack'); 38 | const translate = useService('translate'); 39 | const debounce = useService('debounceInput'); 40 | 41 | const process = getProcess(element); 42 | 43 | const getValue = () => { 44 | return process.get('camunda:historyTimeToLive') || ''; 45 | }; 46 | 47 | const setValue = (value) => { 48 | commandStack.execute('element.updateModdleProperties', { 49 | element, 50 | moddleElement: process, 51 | properties: { 52 | 'camunda:historyTimeToLive': value 53 | } 54 | }); 55 | }; 56 | 57 | return TextFieldEntry({ 58 | element, 59 | id: 'historyTimeToLive', 60 | label: translate('Time to live'), 61 | getValue, 62 | setValue, 63 | debounce 64 | }); 65 | } 66 | 67 | 68 | // helper ////////////////// 69 | 70 | function getProcess(element) { 71 | return is(element, 'bpmn:Process') ? 72 | getBusinessObject(element) : 73 | getBusinessObject(element).get('processRef'); 74 | } 75 | -------------------------------------------------------------------------------- /src/provider/camunda-platform/properties/IdProps.js: -------------------------------------------------------------------------------- 1 | import { 2 | getBusinessObject, 3 | is 4 | } from 'bpmn-js/lib/util/ModelUtil'; 5 | 6 | import { TextFieldEntry, isTextFieldEntryEdited } from '@bpmn-io/properties-panel'; 7 | 8 | import { useCallback } from '@bpmn-io/properties-panel/preact/hooks'; 9 | 10 | import { 11 | useService 12 | } from '../../../hooks'; 13 | 14 | import { 15 | isIdValid 16 | } from '../../../utils/ValidationUtil'; 17 | 18 | 19 | /** 20 | * @typedef { import('@bpmn-io/properties-panel').EntryDefinition } Entry 21 | */ 22 | 23 | /** 24 | * @returns {Array} entries 25 | */ 26 | export function IdProps() { 27 | return [ 28 | { 29 | id: 'id', 30 | component: Id, 31 | isEdited: isTextFieldEntryEdited 32 | } 33 | ]; 34 | } 35 | 36 | function Id(props) { 37 | const { 38 | element 39 | } = props; 40 | 41 | const modeling = useService('modeling'); 42 | const debounce = useService('debounceInput'); 43 | const translate = useService('translate'); 44 | 45 | const setValue = (value, error) => { 46 | if (error) { 47 | return; 48 | } 49 | 50 | modeling.updateProperties(element, { 51 | id: value 52 | }); 53 | }; 54 | 55 | const getValue = useCallback((element) => { 56 | return getBusinessObject(element).id; 57 | }, [ element ]); 58 | 59 | const validate = useCallback((value) => { 60 | const businessObject = getBusinessObject(element); 61 | 62 | return isIdValid(businessObject, value, translate); 63 | }, [ element, translate ]); 64 | 65 | const description = is(element, 'bpmn:Process') ? 66 | translate('This maps to the process definition key.') 67 | : null; 68 | 69 | return TextFieldEntry({ 70 | element, 71 | id: 'id', 72 | label: translate(is(element, 'bpmn:Participant') ? 'Participant ID' : 'ID'), 73 | getValue, 74 | setValue, 75 | debounce, 76 | validate, 77 | description 78 | }); 79 | } -------------------------------------------------------------------------------- /src/provider/camunda-platform/properties/InitiatorProps.js: -------------------------------------------------------------------------------- 1 | import { 2 | getBusinessObject, 3 | is 4 | } from 'bpmn-js/lib/util/ModelUtil'; 5 | 6 | import { TextFieldEntry, isTextFieldEntryEdited } from '@bpmn-io/properties-panel'; 7 | 8 | import { 9 | useService 10 | } from '../../../hooks'; 11 | 12 | 13 | export function InitiatorProps(props) { 14 | const { 15 | element 16 | } = props; 17 | 18 | if (!isInitiator(element)) { 19 | return []; 20 | } 21 | 22 | return [ 23 | { 24 | id: 'initiator', 25 | component: Initiator, 26 | isEdited: isTextFieldEntryEdited 27 | }, 28 | ]; 29 | } 30 | 31 | function Initiator(props) { 32 | const { element } = props; 33 | 34 | const commandStack = useService('commandStack'); 35 | const translate = useService('translate'); 36 | const debounce = useService('debounceInput'); 37 | 38 | const businessObject = getBusinessObject(element); 39 | 40 | const getValue = () => { 41 | return businessObject.get('camunda:initiator'); 42 | }; 43 | 44 | const setValue = (value) => { 45 | commandStack.execute('element.updateModdleProperties', { 46 | element, 47 | moddleElement: businessObject, 48 | properties: { 49 | 'camunda:initiator': value 50 | } 51 | }); 52 | }; 53 | 54 | return TextFieldEntry({ 55 | element, 56 | id: 'initiator', 57 | label: translate('Initiator'), 58 | getValue, 59 | setValue, 60 | debounce 61 | }); 62 | } 63 | 64 | 65 | // helper /////////////////// 66 | 67 | function isInitiator(element) { 68 | return is(element, 'camunda:Initiator') && !is(element.parent, 'bpmn:SubProcess'); 69 | } -------------------------------------------------------------------------------- /src/provider/camunda-platform/properties/InputProps.js: -------------------------------------------------------------------------------- 1 | import InputOutputParameter from './InputOutputParameter'; 2 | 3 | import { 4 | AddParameterCmd, 5 | areInputParametersSupported, 6 | getInputParameters, 7 | getInputOutput 8 | } from '../utils/InputOutputUtil'; 9 | 10 | import { without } from 'min-dash'; 11 | 12 | 13 | export function InputProps(props) { 14 | const { 15 | element, 16 | injector 17 | } = props; 18 | 19 | if (!areInputParametersSupported(element)) { 20 | return null; 21 | } 22 | 23 | const inputParameters = getInputParameters(element) || []; 24 | 25 | const bpmnFactory = injector.get('bpmnFactory'), 26 | commandStack = injector.get('commandStack'); 27 | 28 | const items = inputParameters.map((parameter, index) => { 29 | const id = element.id + '-inputParameter-' + index; 30 | 31 | return { 32 | id, 33 | label: parameter.get('name') || '', 34 | entries: InputOutputParameter({ 35 | idPrefix: id, 36 | element, 37 | parameter 38 | }), 39 | autoFocusEntry: id + '-name', 40 | remove: removeFactory({ element, commandStack, parameter }) 41 | }; 42 | }); 43 | 44 | function add(event) { 45 | event.stopPropagation(); 46 | 47 | commandStack.execute( 48 | 'properties-panel.multi-command-executor', 49 | AddParameterCmd(element, 'camunda:InputParameter', bpmnFactory) 50 | ); 51 | } 52 | 53 | return { 54 | items, 55 | add, 56 | }; 57 | } 58 | 59 | function removeFactory(props) { 60 | const { 61 | commandStack, 62 | element, 63 | parameter 64 | } = props; 65 | 66 | return function(event) { 67 | event.stopPropagation(); 68 | 69 | const inputOutput = getInputOutput(element); 70 | 71 | if (!inputOutput) { 72 | return; 73 | } 74 | 75 | commandStack.execute('element.updateModdleProperties', { 76 | element, 77 | moddleElement: inputOutput, 78 | properties: { 79 | inputParameters: without(inputOutput.get('inputParameters'), parameter) 80 | } 81 | }); 82 | }; 83 | } 84 | -------------------------------------------------------------------------------- /src/provider/camunda-platform/properties/OutputProps.js: -------------------------------------------------------------------------------- 1 | import InputOutputParameter from './InputOutputParameter'; 2 | 3 | import { 4 | AddParameterCmd, 5 | areOutputParametersSupported, 6 | getOutputParameters, 7 | getInputOutput 8 | } from '../utils/InputOutputUtil'; 9 | 10 | import { without } from 'min-dash'; 11 | 12 | 13 | export function OutputProps({ element, injector }) { 14 | 15 | if (!areOutputParametersSupported(element)) { 16 | return null; 17 | } 18 | 19 | const outputParameters = getOutputParameters(element) || []; 20 | 21 | const bpmnFactory = injector.get('bpmnFactory'), 22 | commandStack = injector.get('commandStack'); 23 | 24 | const items = outputParameters.map((parameter, index) => { 25 | const id = element.id + '-outputParameter-' + index; 26 | 27 | return { 28 | id, 29 | label: parameter.get('name') || '', 30 | entries: InputOutputParameter({ 31 | idPrefix: id, 32 | element, 33 | parameter 34 | }), 35 | autoFocusEntry: id + '-name', 36 | remove: removeFactory({ commandStack, element, parameter }) 37 | }; 38 | }); 39 | 40 | return { 41 | items, 42 | add: addFactory({ bpmnFactory, commandStack, element }), 43 | }; 44 | } 45 | 46 | function removeFactory({ commandStack, element, parameter }) { 47 | return function(event) { 48 | event.stopPropagation(); 49 | 50 | const inputOutput = getInputOutput(element); 51 | 52 | if (!inputOutput) { 53 | return; 54 | } 55 | 56 | commandStack.execute('element.updateModdleProperties', { 57 | element, 58 | moddleElement: inputOutput, 59 | properties: { 60 | outputParameters: without(inputOutput.get('outputParameters'), parameter) 61 | } 62 | }); 63 | }; 64 | } 65 | 66 | function addFactory({ bpmnFactory, commandStack, element }) { 67 | return function(event) { 68 | event.stopPropagation(); 69 | 70 | commandStack.execute( 71 | 'properties-panel.multi-command-executor', 72 | AddParameterCmd(element, 'camunda:OutputParameter', bpmnFactory) 73 | ); 74 | }; 75 | } 76 | -------------------------------------------------------------------------------- /src/provider/camunda-platform/properties/ProcessProps.js: -------------------------------------------------------------------------------- 1 | import { is } from 'bpmn-js/lib/util/ModelUtil'; 2 | 3 | import { TextFieldEntry, isTextFieldEntryEdited } from '@bpmn-io/properties-panel'; 4 | 5 | import { useCallback } from '@bpmn-io/properties-panel/preact/hooks'; 6 | 7 | import { 8 | useService 9 | } from '../../../hooks'; 10 | 11 | import { 12 | isIdValid 13 | } from '../../../utils/ValidationUtil'; 14 | 15 | /** 16 | * @typedef { import('@bpmn-io/properties-panel').EntryDefinition } Entry 17 | */ 18 | 19 | /** 20 | * @returns {Array} entries 21 | */ 22 | export function ProcessProps(props) { 23 | const { 24 | element 25 | } = props; 26 | 27 | if (!hasProcessRef(element)) { 28 | return []; 29 | } 30 | 31 | return [ 32 | { 33 | id: 'processId', 34 | component: ProcessId, 35 | isEdited: isTextFieldEntryEdited 36 | } 37 | ]; 38 | } 39 | 40 | function ProcessId(props) { 41 | const { element } = props; 42 | 43 | const commandStack = useService('commandStack'); 44 | const translate = useService('translate'); 45 | const debounce = useService('debounceInput'); 46 | const process = element.businessObject.get('processRef'); 47 | 48 | const getValue = () => { 49 | return process.get('id'); 50 | }; 51 | 52 | const setValue = (value, error) => { 53 | if (error) { 54 | return; 55 | } 56 | 57 | commandStack.execute( 58 | 'element.updateModdleProperties', 59 | { 60 | element, 61 | moddleElement: process, 62 | properties: { 63 | id: value 64 | } 65 | } 66 | ); 67 | }; 68 | 69 | const validate = useCallback((value) => { 70 | return isIdValid(process, value, translate); 71 | }, [ process, translate ]); 72 | 73 | const description = is(element, 'bpmn:Participant') ? 74 | translate('This maps to the process definition key.') 75 | : null; 76 | 77 | return TextFieldEntry({ 78 | element, 79 | id: 'processId', 80 | label: translate('Process ID'), 81 | getValue, 82 | setValue, 83 | debounce, 84 | validate, 85 | description 86 | }); 87 | } 88 | 89 | 90 | // helper //////////////// 91 | 92 | function hasProcessRef(element) { 93 | return is(element, 'bpmn:Participant') && element.businessObject.get('processRef'); 94 | } -------------------------------------------------------------------------------- /src/provider/camunda-platform/properties/ScriptTaskProps.js: -------------------------------------------------------------------------------- 1 | import { 2 | is, 3 | getBusinessObject 4 | } from 'bpmn-js/lib/util/ModelUtil'; 5 | 6 | import { TextFieldEntry, isTextFieldEntryEdited } from '@bpmn-io/properties-panel'; 7 | 8 | import { 9 | useService 10 | } from '../../../hooks'; 11 | 12 | import { 13 | ScriptProps 14 | } from './ScriptProps'; 15 | 16 | 17 | export function ScriptTaskProps(props) { 18 | const { 19 | element 20 | } = props; 21 | 22 | if (!is(element, 'bpmn:ScriptTask')) { 23 | return []; 24 | } 25 | 26 | const entries = [ 27 | ...ScriptProps({ element }) 28 | ]; 29 | 30 | entries.push({ 31 | id: 'scriptResultVariable', 32 | component: ResultVariable, 33 | isEdited: isTextFieldEntryEdited 34 | }); 35 | 36 | return entries; 37 | } 38 | 39 | function ResultVariable(props) { 40 | const { element } = props; 41 | 42 | const commandStack = useService('commandStack'); 43 | const translate = useService('translate'); 44 | const debounce = useService('debounceInput'); 45 | 46 | const businessObject = getBusinessObject(element); 47 | 48 | const getValue = () => { 49 | return businessObject.get('camunda:resultVariable'); 50 | }; 51 | 52 | 53 | const setValue = (value) => { 54 | commandStack.execute('element.updateModdleProperties', { 55 | element, 56 | moddleElement: businessObject, 57 | properties: { 58 | 'camunda:resultVariable': value 59 | } 60 | }); 61 | }; 62 | 63 | return TextFieldEntry({ 64 | element, 65 | id: 'scriptResultVariable', 66 | label: translate('Result variable'), 67 | getValue, 68 | setValue, 69 | debounce 70 | }); 71 | } -------------------------------------------------------------------------------- /src/provider/camunda-platform/properties/TasklistProps.js: -------------------------------------------------------------------------------- 1 | import { 2 | getBusinessObject, 3 | is 4 | } from 'bpmn-js/lib/util/ModelUtil'; 5 | 6 | import { CheckboxEntry } from '@bpmn-io/properties-panel'; 7 | 8 | import { 9 | useService 10 | } from '../../../hooks'; 11 | 12 | 13 | export function TasklistProps(props) { 14 | const { 15 | element 16 | } = props; 17 | 18 | const businessObject = getBusinessObject(element); 19 | 20 | const isEdited = (node) => { 21 | return node && !node.checked; 22 | }; 23 | 24 | if (!is(element, 'bpmn:Process') && 25 | !(is(element, 'bpmn:Participant') && businessObject.get('processRef'))) { 26 | return []; 27 | } 28 | 29 | return [ 30 | { 31 | id: 'isStartableInTasklist', 32 | component: Startable, 33 | isEdited 34 | }, 35 | ]; 36 | } 37 | 38 | function Startable(props) { 39 | const { element } = props; 40 | 41 | const commandStack = useService('commandStack'); 42 | const translate = useService('translate'); 43 | 44 | const process = getProcess(element); 45 | 46 | const getValue = () => { 47 | return process.get('camunda:isStartableInTasklist'); 48 | }; 49 | 50 | const setValue = (value) => { 51 | commandStack.execute('element.updateModdleProperties', { 52 | element, 53 | moddleElement: process, 54 | properties: { 55 | 'camunda:isStartableInTasklist': value 56 | } 57 | }); 58 | }; 59 | 60 | return CheckboxEntry({ 61 | element, 62 | id: 'isStartableInTasklist', 63 | label: translate('Startable'), 64 | getValue, 65 | setValue 66 | }); 67 | } 68 | 69 | 70 | // helper ////////////////// 71 | 72 | function getProcess(element) { 73 | return is(element, 'bpmn:Process') ? 74 | getBusinessObject(element) : 75 | getBusinessObject(element).get('processRef'); 76 | } 77 | -------------------------------------------------------------------------------- /src/provider/camunda-platform/properties/VersionTagProps.js: -------------------------------------------------------------------------------- 1 | import { 2 | getBusinessObject, 3 | is 4 | } from 'bpmn-js/lib/util/ModelUtil'; 5 | 6 | import { TextFieldEntry, isTextFieldEntryEdited } from '@bpmn-io/properties-panel'; 7 | 8 | import { 9 | useService 10 | } from '../../../hooks'; 11 | 12 | 13 | export function VersionTagProps(props) { 14 | const { 15 | element 16 | } = props; 17 | 18 | const businessObject = getBusinessObject(element); 19 | 20 | if (!is(element, 'bpmn:Process') && 21 | !(is(element, 'bpmn:Participant') && businessObject.get('processRef'))) { 22 | return []; 23 | } 24 | 25 | return [ 26 | { 27 | id: 'versionTag', 28 | component: VersionTag, 29 | isEdited: isTextFieldEntryEdited 30 | }, 31 | ]; 32 | } 33 | 34 | function VersionTag(props) { 35 | const { element } = props; 36 | 37 | const commandStack = useService('commandStack'); 38 | const translate = useService('translate'); 39 | const debounce = useService('debounceInput'); 40 | 41 | const process = getProcess(element); 42 | 43 | const getValue = () => { 44 | return process.get('camunda:versionTag') || ''; 45 | }; 46 | 47 | const setValue = (value) => { 48 | commandStack.execute('element.updateModdleProperties', { 49 | element, 50 | moddleElement: process, 51 | properties: { 52 | 'camunda:versionTag': value 53 | } 54 | }); 55 | }; 56 | 57 | return TextFieldEntry({ 58 | element, 59 | id: 'versionTag', 60 | label: translate('Version tag'), 61 | getValue, 62 | setValue, 63 | debounce 64 | }); 65 | } 66 | 67 | 68 | // helper ////////////////// 69 | 70 | function getProcess(element) { 71 | return is(element, 'bpmn:Process') ? 72 | getBusinessObject(element) : 73 | getBusinessObject(element).get('processRef'); 74 | } -------------------------------------------------------------------------------- /src/provider/camunda-platform/properties/index.js: -------------------------------------------------------------------------------- 1 | export { AsynchronousContinuationsProps } from './AsynchronousContinuationsProps'; 2 | export { BusinessKeyProps } from './BusinessKeyProps'; 3 | export { CallActivityProps } from './CallActivityProps'; 4 | export { CandidateStarterProps } from './CandidateStarterProps'; 5 | export { ConditionProps } from './ConditionProps'; 6 | export { ConnectorInputProps } from './ConnectorInputProps'; 7 | export { ConnectorOutputProps } from './ConnectorOutputProps'; 8 | export { ErrorProps } from './ErrorProps'; 9 | export { ErrorsProps } from './ErrorsProps'; 10 | export { EscalationProps } from './EscalationProps'; 11 | export { ExternalTaskPriorityProps } from './ExternalTaskPriorityProps'; 12 | export { FieldInjectionProps } from './FieldInjectionProps'; 13 | export { FormDataProps } from './FormDataProps'; 14 | export { FormProps } from './FormProps'; 15 | export { HistoryCleanupProps } from './HistoryCleanupProps'; 16 | export { ImplementationProps } from './ImplementationProps'; 17 | export { InitiatorProps } from './InitiatorProps'; 18 | export { InMappingPropagationProps } from './InMappingPropagationProps'; 19 | export { InMappingProps } from './InMappingProps'; 20 | export { InputProps } from './InputProps'; 21 | export { JobExecutionProps } from './JobExecutionProps'; 22 | export { MultiInstanceProps } from './MultiInstanceProps'; 23 | export { OutMappingPropagationProps } from './OutMappingPropagationProps'; 24 | export { OutMappingProps } from './OutMappingProps'; 25 | export { OutputProps } from './OutputProps'; 26 | export { ExecutionListenerProps } from './ListenerProps'; 27 | export { TaskListenerProps } from './ListenerProps'; 28 | export { ProcessVariablesProps } from './ProcessVariablesProps'; 29 | export { ScriptTaskProps } from './ScriptTaskProps'; 30 | export { TasklistProps } from './TasklistProps'; 31 | export { UserAssignmentProps } from './UserAssignmentProps'; 32 | export { VersionTagProps } from './VersionTagProps'; 33 | export { TimerProps } from './TimerProps'; 34 | export { IdProps } from './IdProps'; 35 | export { ProcessProps } from './ProcessProps'; 36 | -------------------------------------------------------------------------------- /src/provider/camunda-platform/utils/ConnectorUtil.js: -------------------------------------------------------------------------------- 1 | import { 2 | getExtensionElementsList 3 | } from '../../../utils/ExtensionElementsUtil'; 4 | 5 | import { 6 | getImplementationType, 7 | getServiceTaskLikeBusinessObject 8 | } from './ImplementationTypeUtils'; 9 | 10 | export function areConnectorsSupported(element) { 11 | const businessObject = getServiceTaskLikeBusinessObject(element); 12 | return businessObject && getImplementationType(businessObject) === 'connector'; 13 | } 14 | 15 | export function getConnectors(businessObject) { 16 | return getExtensionElementsList(businessObject, 'camunda:Connector'); 17 | } 18 | 19 | export function getConnector(element) { 20 | const businessObject = getServiceTaskLikeBusinessObject(element); 21 | const connectors = getConnectors(businessObject); 22 | 23 | return connectors[0]; 24 | } -------------------------------------------------------------------------------- /src/provider/camunda-platform/utils/FormTypeUtils.js: -------------------------------------------------------------------------------- 1 | import { isDefined } from 'min-dash'; 2 | 3 | import { 4 | getBusinessObject, 5 | is 6 | } from 'bpmn-js/lib/util/ModelUtil'; 7 | 8 | export function getFormRefBinding(element) { 9 | const businessObject = getBusinessObject(element); 10 | 11 | return businessObject.get('camunda:formRefBinding') || 'latest'; 12 | } 13 | 14 | export function getFormType(element) { 15 | const businessObject = getBusinessObject(element); 16 | 17 | if (isDefined(businessObject.get('camunda:formKey'))) { 18 | return 'formKey'; 19 | } else if (isDefined(businessObject.get('camunda:formRef'))) { 20 | return 'formRef'; 21 | } 22 | } 23 | 24 | export function isFormSupported(element) { 25 | return (is(element, 'bpmn:StartEvent') && !is(element.parent, 'bpmn:SubProcess')) 26 | || is(element, 'bpmn:UserTask'); 27 | } -------------------------------------------------------------------------------- /src/provider/shared/ExtensionProperty.js: -------------------------------------------------------------------------------- 1 | import { TextFieldEntry } from '@bpmn-io/properties-panel'; 2 | 3 | import { 4 | useService 5 | } from '../../hooks'; 6 | 7 | 8 | export default function ExtensionProperty(props) { 9 | 10 | const { 11 | idPrefix, 12 | property 13 | } = props; 14 | 15 | const entries = [ { 16 | id: idPrefix + '-name', 17 | component: NameProperty, 18 | idPrefix, 19 | property 20 | },{ 21 | id: idPrefix + '-value', 22 | component: ValueProperty, 23 | idPrefix, 24 | property 25 | } ]; 26 | 27 | return entries; 28 | } 29 | 30 | function NameProperty(props) { 31 | const { 32 | idPrefix, 33 | element, 34 | property 35 | } = props; 36 | 37 | const commandStack = useService('commandStack'); 38 | const translate = useService('translate'); 39 | const debounce = useService('debounceInput'); 40 | 41 | const setValue = (value) => { 42 | commandStack.execute('element.updateModdleProperties', { 43 | element, 44 | moddleElement: property, 45 | properties: { 46 | name: value 47 | } 48 | }); 49 | }; 50 | 51 | const getValue = () => { 52 | return property.name; 53 | }; 54 | 55 | return TextFieldEntry({ 56 | element: property, 57 | id: idPrefix + '-name', 58 | label: translate('Name'), 59 | getValue, 60 | setValue, 61 | debounce 62 | }); 63 | } 64 | 65 | function ValueProperty(props) { 66 | const { 67 | idPrefix, 68 | element, 69 | property 70 | } = props; 71 | 72 | const commandStack = useService('commandStack'); 73 | const translate = useService('translate'); 74 | const debounce = useService('debounceInput'); 75 | 76 | const setValue = (value) => { 77 | commandStack.execute('element.updateModdleProperties', { 78 | element, 79 | moddleElement: property, 80 | properties: { 81 | value 82 | } 83 | }); 84 | }; 85 | 86 | const getValue = () => { 87 | return property.value; 88 | }; 89 | 90 | return TextFieldEntry({ 91 | element: property, 92 | id: idPrefix + '-value', 93 | label: translate('Value'), 94 | getValue, 95 | setValue, 96 | debounce 97 | }); 98 | } -------------------------------------------------------------------------------- /src/provider/zeebe/index.js: -------------------------------------------------------------------------------- 1 | import ZeebePropertiesProvider from './ZeebePropertiesProvider'; 2 | 3 | export default { 4 | __init__: [ 'zeebePropertiesProvider' ], 5 | zeebePropertiesProvider: [ 'type', ZeebePropertiesProvider ] 6 | }; -------------------------------------------------------------------------------- /src/provider/zeebe/properties/AdHocCompletionProps.js: -------------------------------------------------------------------------------- 1 | import { is, getBusinessObject } from 'bpmn-js/lib/util/ModelUtil'; 2 | 3 | import { 4 | isFeelEntryEdited, 5 | } from '@bpmn-io/properties-panel'; 6 | 7 | import { useService } from '../../../hooks'; 8 | import { FeelEntryWithVariableContext } from '../../../entries/FeelEntryWithContext'; 9 | import { createOrUpdateFormalExpression } from '../../../utils/FormalExpressionUtil'; 10 | 11 | /** 12 | * @typedef { import('@bpmn-io/properties-panel').EntryDefinition } Entry 13 | */ 14 | 15 | /** 16 | * @returns {Array} entries 17 | */ 18 | export function AdHocCompletionProps(props) { 19 | const { element } = props; 20 | 21 | if (!is(element, 'bpmn:AdHocSubProcess')) { 22 | return []; 23 | } 24 | 25 | return [ 26 | { 27 | id: 'completionCondition', 28 | component: CompletionCondition, 29 | isEdited: isFeelEntryEdited, 30 | } 31 | ]; 32 | } 33 | 34 | function CompletionCondition(props) { 35 | const { element } = props; 36 | 37 | const bpmnFactory = useService('bpmnFactory'); 38 | const debounce = useService('debounceInput'); 39 | const commandStack = useService('commandStack'); 40 | const translate = useService('translate'); 41 | 42 | const getValue = () => { 43 | const expression = getBusinessObject(element).get('completionCondition'); 44 | return expression && expression.get('body'); 45 | }; 46 | 47 | const setValue = (value) => { 48 | return createOrUpdateFormalExpression( 49 | element, 50 | getBusinessObject(element), 51 | 'completionCondition', 52 | value, 53 | bpmnFactory, 54 | commandStack 55 | ); 56 | }; 57 | 58 | return FeelEntryWithVariableContext({ 59 | element, 60 | id: 'completionCondition', 61 | label: translate('Completion condition'), 62 | feel: 'required', 63 | getValue, 64 | setValue, 65 | debounce, 66 | }); 67 | } -------------------------------------------------------------------------------- /src/provider/zeebe/properties/ErrorProps.js: -------------------------------------------------------------------------------- 1 | import { 2 | is 3 | } from 'bpmn-js/lib/util/ModelUtil'; 4 | 5 | import { 6 | isFeelEntryEdited 7 | } from '@bpmn-io/properties-panel'; 8 | 9 | import { useService } from '../../../hooks'; 10 | 11 | 12 | import { 13 | getError 14 | } from '../../bpmn/utils/EventDefinitionUtil'; 15 | 16 | import { FeelEntryWithVariableContext } from '../../../entries/FeelEntryWithContext'; 17 | 18 | 19 | export function ErrorProps(props) { 20 | const { 21 | element 22 | } = props; 23 | 24 | const error = getError(element); 25 | 26 | const entries = []; 27 | 28 | if (error && is(element, 'bpmn:ThrowEvent')) { 29 | entries.push( 30 | { 31 | id: 'errorCode', 32 | component: ErrorCode, 33 | isEdited: isFeelEntryEdited 34 | } 35 | ); 36 | } 37 | 38 | return entries; 39 | } 40 | 41 | 42 | function ErrorCode(props) { 43 | const { element } = props; 44 | 45 | const commandStack = useService('commandStack'); 46 | const translate = useService('translate'); 47 | const debounce = useService('debounceInput'); 48 | 49 | const error = getError(element); 50 | 51 | const getValue = () => { 52 | return error.get('errorCode'); 53 | }; 54 | 55 | const setValue = (value) => { 56 | return commandStack.execute( 57 | 'element.updateModdleProperties', 58 | { 59 | element, 60 | moddleElement: error, 61 | properties: { 62 | errorCode: value 63 | } 64 | } 65 | ); 66 | }; 67 | 68 | return FeelEntryWithVariableContext({ 69 | element, 70 | id: 'errorCode', 71 | label: translate('Code'), 72 | feel: 'optional', 73 | getValue, 74 | setValue, 75 | debounce 76 | }); 77 | } 78 | -------------------------------------------------------------------------------- /src/provider/zeebe/properties/EscalationProps.js: -------------------------------------------------------------------------------- 1 | import { 2 | is 3 | } from 'bpmn-js/lib/util/ModelUtil'; 4 | 5 | import { 6 | isFeelEntryEdited 7 | } from '@bpmn-io/properties-panel'; 8 | 9 | import { 10 | useService 11 | } from '../../../hooks'; 12 | 13 | import { 14 | getEscalation 15 | } from '../../bpmn/utils/EventDefinitionUtil'; 16 | 17 | import { FeelEntryWithVariableContext } from '../../../entries/FeelEntryWithContext'; 18 | 19 | 20 | /** 21 | * @typedef { import('@bpmn-io/properties-panel').EntryDefinition } Entry 22 | */ 23 | 24 | /** 25 | * @returns {Array} entries 26 | */ 27 | export function EscalationProps(props) { 28 | const { 29 | element 30 | } = props; 31 | 32 | // update throw events only 33 | if (!is(element, 'bpmn:ThrowEvent')) { 34 | return []; 35 | } 36 | 37 | const escalation = getEscalation(element); 38 | 39 | const entries = []; 40 | 41 | if (escalation) { 42 | entries.push( 43 | { 44 | id: 'escalationCode', 45 | component: EscalationCode, 46 | isEdited: isFeelEntryEdited 47 | } 48 | ); 49 | } 50 | 51 | return entries; 52 | } 53 | 54 | function EscalationCode(props) { 55 | const { element } = props; 56 | 57 | const commandStack = useService('commandStack'); 58 | const translate = useService('translate'); 59 | const debounce = useService('debounceInput'); 60 | 61 | const escalation = getEscalation(element); 62 | 63 | const getValue = () => { 64 | return escalation.get('escalationCode'); 65 | }; 66 | 67 | const setValue = (value) => { 68 | return commandStack.execute( 69 | 'element.updateModdleProperties', 70 | { 71 | element, 72 | moddleElement: escalation, 73 | properties: { 74 | escalationCode: value 75 | } 76 | } 77 | ); 78 | }; 79 | 80 | return FeelEntryWithVariableContext({ 81 | element, 82 | id: 'escalationCode', 83 | label: translate('Code'), 84 | feel: 'optional', 85 | getValue, 86 | setValue, 87 | debounce 88 | }); 89 | } 90 | -------------------------------------------------------------------------------- /src/provider/zeebe/properties/Header.js: -------------------------------------------------------------------------------- 1 | import { TextFieldEntry, TextAreaEntry } from '@bpmn-io/properties-panel'; 2 | 3 | import { 4 | useService 5 | } from '../../../hooks'; 6 | 7 | 8 | export default function Header(props) { 9 | 10 | const { 11 | idPrefix, 12 | header 13 | } = props; 14 | 15 | const entries = [ { 16 | id: idPrefix + '-key', 17 | component: KeyProperty, 18 | header, 19 | idPrefix 20 | },{ 21 | id: idPrefix + '-value', 22 | component: ValueProperty, 23 | header, 24 | idPrefix 25 | } ]; 26 | 27 | return entries; 28 | } 29 | 30 | function KeyProperty(props) { 31 | const { 32 | idPrefix, 33 | element, 34 | header 35 | } = props; 36 | 37 | const commandStack = useService('commandStack'); 38 | const translate = useService('translate'); 39 | const debounce = useService('debounceInput'); 40 | 41 | const setValue = (value) => { 42 | commandStack.execute('element.updateModdleProperties', { 43 | element, 44 | moddleElement: header, 45 | properties: { 46 | key: value 47 | } 48 | }); 49 | }; 50 | 51 | const getValue = (header) => { 52 | return header.key; 53 | }; 54 | 55 | return TextFieldEntry({ 56 | element: header, 57 | id: idPrefix + '-key', 58 | label: translate('Key'), 59 | getValue, 60 | setValue, 61 | debounce 62 | }); 63 | } 64 | 65 | function ValueProperty(props) { 66 | const { 67 | idPrefix, 68 | element, 69 | header 70 | } = props; 71 | 72 | const commandStack = useService('commandStack'); 73 | const translate = useService('translate'); 74 | const debounce = useService('debounceInput'); 75 | 76 | const setValue = (value) => { 77 | commandStack.execute('element.updateModdleProperties', { 78 | element, 79 | moddleElement: header, 80 | properties: { 81 | value 82 | } 83 | }); 84 | }; 85 | 86 | const getValue = (header) => { 87 | return header.value; 88 | }; 89 | 90 | return TextAreaEntry({ 91 | element: header, 92 | id: idPrefix + '-value', 93 | label: translate('Value'), 94 | getValue, 95 | setValue, 96 | debounce, 97 | autoResize: true 98 | }); 99 | } -------------------------------------------------------------------------------- /src/provider/zeebe/properties/SignalProps.js: -------------------------------------------------------------------------------- 1 | import { isFeelEntryEdited } from '@bpmn-io/properties-panel'; 2 | 3 | import { FeelEntryWithVariableContext } from '../../../entries/FeelEntryWithContext'; 4 | 5 | import { 6 | useService 7 | } from '../../../hooks'; 8 | 9 | import { 10 | getSignal, 11 | isSignalSupported 12 | } from '../../../utils/EventDefinitionUtil'; 13 | 14 | /** 15 | * @typedef { import('@bpmn-io/properties-panel').EntryDefinition } Entry 16 | */ 17 | 18 | export const EMPTY_OPTION = ''; 19 | export const CREATE_NEW_OPTION = 'create-new'; 20 | 21 | /** 22 | * @returns {Entry[]} 23 | */ 24 | export function SignalProps(props) { 25 | const { 26 | element 27 | } = props; 28 | 29 | if (!isSignalSupported(element)) { 30 | return []; 31 | } 32 | 33 | const signal = getSignal(element); 34 | 35 | let entries = []; 36 | 37 | if (signal) { 38 | entries = [ 39 | ...entries, 40 | { 41 | id: 'signalName', 42 | component: SignalName, 43 | isEdited: isFeelEntryEdited 44 | }, 45 | ]; 46 | } 47 | 48 | return entries; 49 | } 50 | 51 | function SignalName(props) { 52 | const { element } = props; 53 | 54 | const commandStack = useService('commandStack'); 55 | const translate = useService('translate'); 56 | const debounce = useService('debounceInput'); 57 | 58 | const signal = getSignal(element); 59 | 60 | const getValue = () => { 61 | return signal.get('name'); 62 | }; 63 | 64 | const setValue = (value) => { 65 | return commandStack.execute( 66 | 'element.updateModdleProperties', 67 | { 68 | element, 69 | moddleElement: signal, 70 | properties: { 71 | name: value 72 | } 73 | } 74 | ); 75 | }; 76 | 77 | return FeelEntryWithVariableContext({ 78 | element, 79 | id: 'signalName', 80 | label: translate('Name'), 81 | feel: 'optional', 82 | getValue, 83 | setValue, 84 | debounce 85 | }); 86 | } -------------------------------------------------------------------------------- /src/provider/zeebe/properties/TaskListener.js: -------------------------------------------------------------------------------- 1 | import { SelectEntry } from '@bpmn-io/properties-panel'; 2 | 3 | import { 4 | useService 5 | } from '../../../hooks'; 6 | 7 | import { ListenerType, Retries } from './shared/Listener'; 8 | 9 | // ensure types are in logical order 10 | export const EVENT_TYPE = [ 11 | 'creating', 12 | 'assigning', 13 | 'updating', 14 | 'completing', 15 | 'canceling', 16 | ]; 17 | 18 | export const EVENT_TO_LABEL = { 19 | creating: 'Creating', 20 | assigning: 'Assigning', 21 | updating: 'Updating', 22 | completing: 'Completing', 23 | canceling: 'Canceling', 24 | }; 25 | 26 | export function TaskListenerEntries(props) { 27 | 28 | const { 29 | idPrefix, 30 | listener 31 | } = props; 32 | 33 | return [ 34 | { 35 | id: idPrefix + '-eventType', 36 | component: EventType, 37 | idPrefix, 38 | listener, 39 | eventTypes: EVENT_TYPE 40 | }, 41 | { 42 | id: idPrefix + '-listenerType', 43 | component: ListenerType, 44 | idPrefix, 45 | listener 46 | }, 47 | { 48 | id: idPrefix + '-retries', 49 | component: Retries, 50 | idPrefix, 51 | listener 52 | } 53 | ]; 54 | } 55 | 56 | function EventType(props) { 57 | const { 58 | idPrefix, 59 | element, 60 | listener, 61 | eventTypes 62 | } = props; 63 | 64 | const modeling = useService('modeling'); 65 | const translate = useService('translate'); 66 | 67 | const getOptions = () => { 68 | return eventTypes.map(eventType => ({ 69 | value: eventType, 70 | label: translate(EVENT_TO_LABEL[eventType]) 71 | })); 72 | }; 73 | 74 | const setValue = (value) => { 75 | modeling.updateModdleProperties(element, listener, { 76 | eventType: value 77 | }); 78 | }; 79 | 80 | const getValue = () => { 81 | return listener.get('eventType'); 82 | }; 83 | 84 | return SelectEntry({ 85 | element, 86 | id: idPrefix + '-eventType', 87 | label: translate('Event type'), 88 | getValue, 89 | setValue, 90 | getOptions 91 | }); 92 | } 93 | 94 | 95 | -------------------------------------------------------------------------------- /src/provider/zeebe/properties/index.js: -------------------------------------------------------------------------------- 1 | export { ActiveElementsProps } from './ActiveElementsProps'; 2 | export { AdHocCompletionProps } from './AdHocCompletionProps'; 3 | export { AssignmentDefinitionProps } from './AssignmentDefinitionProps'; 4 | export { BusinessRuleImplementationProps } from './BusinessRuleImplementationProps'; 5 | export { CalledDecisionProps } from './CalledDecisionProps'; 6 | export { ConditionProps } from './ConditionProps'; 7 | export { ErrorProps } from './ErrorProps'; 8 | export { EscalationProps } from './EscalationProps'; 9 | export { ExecutionListenersProps } from './ExecutionListenersProps'; 10 | export { FormProps } from './FormProps'; 11 | export { HeaderProps } from './HeaderProps'; 12 | export { InputPropagationProps } from './InputPropagationProps'; 13 | export { InputProps } from './InputProps'; 14 | export { MessageProps } from './MessageProps'; 15 | export { MultiInstanceProps } from './MultiInstanceProps'; 16 | export { OutputPropagationProps } from './OutputPropagationProps'; 17 | export { OutputProps } from './OutputProps'; 18 | export { PriorityDefinitionProps } from './PriorityDefinitionProps'; 19 | export { ScriptImplementationProps } from './ScriptImplementationProps'; 20 | export { ScriptProps } from './ScriptProps'; 21 | export { SignalProps } from './SignalProps'; 22 | export { TargetProps } from './TargetProps'; 23 | export { TaskDefinitionProps } from './TaskDefinitionProps'; 24 | export { TaskListenersProps } from './TaskListenersProps'; 25 | export { TaskScheduleProps } from './TaskScheduleProps'; 26 | export { TimerProps } from './TimerProps'; 27 | export { UserTaskImplementationProps } from './UserTaskImplementationProps'; 28 | export { VersionTagProps } from './VersionTagProps'; -------------------------------------------------------------------------------- /src/provider/zeebe/properties/shared/Listener.js: -------------------------------------------------------------------------------- 1 | import { FeelEntryWithVariableContext } from '../../../../entries/FeelEntryWithContext'; 2 | 3 | import { useService } from '../../../../hooks'; 4 | 5 | export function ListenerType(props) { 6 | const { 7 | idPrefix, 8 | element, 9 | listener 10 | } = props; 11 | 12 | const modeling = useService('modeling'); 13 | const translate = useService('translate'); 14 | const debounce = useService('debounceInput'); 15 | 16 | const setValue = (value) => { 17 | modeling.updateModdleProperties(element, listener, { 18 | type: value 19 | }); 20 | }; 21 | 22 | const getValue = () => { 23 | return listener.get('type'); 24 | }; 25 | 26 | return FeelEntryWithVariableContext({ 27 | element, 28 | id: idPrefix + '-listenerType', 29 | label: translate('Listener type'), 30 | getValue, 31 | setValue, 32 | debounce, 33 | feel: 'optional' 34 | }); 35 | } 36 | 37 | export function Retries(props) { 38 | const { 39 | idPrefix, 40 | element, 41 | listener 42 | } = props; 43 | 44 | const modeling = useService('modeling'); 45 | const translate = useService('translate'); 46 | const debounce = useService('debounceInput'); 47 | 48 | const setValue = (value) => { 49 | modeling.updateModdleProperties(element, listener, { 50 | retries: value 51 | }); 52 | }; 53 | 54 | const getValue = () => { 55 | return listener.get('retries'); 56 | }; 57 | 58 | return FeelEntryWithVariableContext({ 59 | element, 60 | id: idPrefix + '-retries', 61 | label: translate('Retries'), 62 | getValue, 63 | setValue, 64 | debounce, 65 | feel: 'optional' 66 | }); 67 | } -------------------------------------------------------------------------------- /src/provider/zeebe/utils/CalledElementUtil.js: -------------------------------------------------------------------------------- 1 | import { 2 | getBusinessObject 3 | } from 'bpmn-js/lib/util/ModelUtil'; 4 | 5 | import { 6 | getExtensionElementsList 7 | } from '../../../utils/ExtensionElementsUtil'; 8 | 9 | 10 | export function getPropagateAllChildVariables(element) { 11 | const calledElement = getCalledElement(element); 12 | 13 | return calledElement ? calledElement.get('propagateAllChildVariables') : undefined; 14 | } 15 | 16 | export function getPropagateAllParentVariables(element) { 17 | const calledElement = getCalledElement(element); 18 | 19 | return calledElement ? calledElement.get('propagateAllParentVariables') : undefined; 20 | } 21 | 22 | export function getProcessId(element) { 23 | const calledElement = getCalledElement(element); 24 | 25 | return calledElement ? calledElement.get('processId') : ''; 26 | } 27 | 28 | export function getBindingType(element) { 29 | const calledElement = getCalledElement(element); 30 | 31 | return calledElement ? calledElement.get('bindingType') : ''; 32 | } 33 | 34 | export function getCalledElement(element) { 35 | const calledElements = getCalledElements(element); 36 | return calledElements[0]; 37 | } 38 | 39 | function getCalledElements(element) { 40 | const bo = getBusinessObject(element); 41 | const extElements = getExtensionElementsList(bo, 'zeebe:CalledElement'); 42 | return extElements; 43 | } 44 | -------------------------------------------------------------------------------- /src/provider/zeebe/utils/HeadersUtil.js: -------------------------------------------------------------------------------- 1 | import { 2 | getBusinessObject, 3 | is 4 | } from 'bpmn-js/lib/util/ModelUtil'; 5 | 6 | import { 7 | getExtensionElementsList 8 | } from '../../../utils/ExtensionElementsUtil'; 9 | 10 | import { isZeebeServiceTask } from './ZeebeServiceTaskUtil'; 11 | 12 | export function areHeadersSupported(element) { 13 | return is(element, 'bpmn:UserTask') || isZeebeServiceTask(element); 14 | } 15 | 16 | /** 17 | * Get first zeebe:TaskHeaders element for a specific element. 18 | * 19 | * @param {ModdleElement} element 20 | * 21 | * @return {ModdleElement} a zeebe:TaskHeader element 22 | */ 23 | export function getTaskHeaders(element) { 24 | const businessObject = getBusinessObject(element); 25 | 26 | return getExtensionElementsList(businessObject, 'zeebe:TaskHeaders')[0]; 27 | } 28 | 29 | /** 30 | * Retrieve all zeebe:Header elements for a specific element. 31 | * 32 | * @param {ModdleElement} element 33 | * 34 | * @return {Array} a list of zeebe:Header elements 35 | */ 36 | export function getHeaders(element) { 37 | const taskHeaders = getTaskHeaders(element); 38 | 39 | return taskHeaders ? taskHeaders.get('values') : []; 40 | } 41 | -------------------------------------------------------------------------------- /src/provider/zeebe/utils/TimerUtil.js: -------------------------------------------------------------------------------- 1 | import { 2 | getBusinessObject, 3 | is, 4 | isAny 5 | } from 'bpmn-js/lib/util/ModelUtil'; 6 | 7 | 8 | export function getTimerEventDefinition(element) { 9 | const businessObject = getBusinessObject(element); 10 | 11 | return businessObject.get('eventDefinitions').find(eventDefinition => { 12 | return is(eventDefinition, 'bpmn:TimerEventDefinition'); 13 | }); 14 | } 15 | 16 | /** 17 | * Check whether a given timer expression type is supported for a given element. 18 | * 19 | * @param {string} type 20 | * @param {Element|ModdleElement} element 21 | * 22 | * @return {boolean} 23 | */ 24 | export function isTimerExpressionTypeSupported(type, element) { 25 | const businessObject = getBusinessObject(element); 26 | 27 | switch (type) { 28 | case 'timeDate': 29 | return isAny(element, [ 30 | 'bpmn:BoundaryEvent', 31 | 'bpmn:IntermediateCatchEvent', 32 | 'bpmn:StartEvent' 33 | ]); 34 | 35 | case 'timeCycle': 36 | if (is(element, 'bpmn:StartEvent') && (!hasParentEventSubProcess(businessObject)) || !isInterrupting(businessObject)) { 37 | return true; 38 | } 39 | 40 | if (is(element, 'bpmn:BoundaryEvent') && !isInterrupting(businessObject)) { 41 | return true; 42 | } 43 | 44 | return false; 45 | 46 | case 'timeDuration': 47 | if (isAny(element, [ 48 | 'bpmn:BoundaryEvent', 49 | 'bpmn:IntermediateCatchEvent' 50 | ])) { 51 | return true; 52 | } 53 | 54 | if (is(element, 'bpmn:StartEvent') && hasParentEventSubProcess(businessObject)) { 55 | return true; 56 | } 57 | 58 | return false; 59 | 60 | default: 61 | return false; 62 | } 63 | } 64 | 65 | function isInterrupting(businessObject) { 66 | if (is(businessObject, 'bpmn:BoundaryEvent')) { 67 | return businessObject.get('cancelActivity') !== false; 68 | } 69 | 70 | return businessObject.get('isInterrupting') !== false; 71 | } 72 | 73 | function hasParentEventSubProcess(businessObject) { 74 | const parent = businessObject.$parent; 75 | 76 | return parent && is(parent, 'bpmn:SubProcess') && parent.get('triggeredByEvent'); 77 | } -------------------------------------------------------------------------------- /src/provider/zeebe/utils/ZeebeServiceTaskUtil.js: -------------------------------------------------------------------------------- 1 | import { 2 | is, 3 | isAny 4 | } from 'bpmn-js/lib/util/ModelUtil'; 5 | 6 | import { 7 | getMessageEventDefinition 8 | } from '../../bpmn/utils/EventDefinitionUtil'; 9 | 10 | import { 11 | getBusinessObject 12 | } from 'bpmn-js/lib/util/ModelUtil'; 13 | 14 | import { 15 | getExtensionElementsList 16 | } from '../../../utils/ExtensionElementsUtil'; 17 | 18 | 19 | export function isZeebeServiceTask(element) { 20 | if (!is(element, 'zeebe:ZeebeServiceTask')) return false; 21 | 22 | if (is(element, 'bpmn:EndEvent') || is(element, 'bpmn:IntermediateThrowEvent')) { 23 | return !!getMessageEventDefinition(element); 24 | } 25 | 26 | // BusinessRuleTask and ScriptTask are ServiceTasks only if they have a TaskDefinition 27 | // (ie. if the implementation is set to ==JobWorker) 28 | if (isAny(element, [ 'bpmn:BusinessRuleTask', 'bpmn:ScriptTask' ]) && !getTaskDefinition(element)) { 29 | return false; 30 | } 31 | 32 | return true; 33 | } 34 | 35 | export function isMessageEndEvent(element) { 36 | return is(element, 'bpmn:EndEvent') && !!getMessageEventDefinition(element); 37 | } 38 | 39 | export function isMessageThrowEvent(element) { 40 | return is(element, 'bpmn:IntermediateThrowEvent') && !!getMessageEventDefinition(element); 41 | } 42 | 43 | // helper //////////////// 44 | 45 | function getTaskDefinition(element) { 46 | const businessObject = getBusinessObject(element); 47 | 48 | return getExtensionElementsList(businessObject, 'zeebe:TaskDefinition')[0]; 49 | } 50 | -------------------------------------------------------------------------------- /src/render/PanelPlaceholderProvider.js: -------------------------------------------------------------------------------- 1 | import EmptyIcon from '../icons/bpmn-empty-state.svg'; 2 | import MultipleIcon from '../icons/bpmn-multiple-state.svg'; 3 | 4 | export const PanelPlaceholderProvider = (translate) => { 5 | if (!translate) translate = (text) => text; 6 | return { 7 | getEmpty: () => { 8 | return { 9 | text: translate('Select an element to edit its properties.'), 10 | icon: EmptyIcon 11 | }; 12 | }, 13 | 14 | getMultiple: () => { 15 | return { 16 | text: translate('Multiple elements are selected. Select a single element to edit its properties.'), 17 | icon: MultipleIcon 18 | }; 19 | } 20 | }; 21 | }; -------------------------------------------------------------------------------- /src/render/index.js: -------------------------------------------------------------------------------- 1 | import BpmnPropertiesPanelRenderer from './BpmnPropertiesPanelRenderer'; 2 | 3 | import Commands from '../cmd'; 4 | import { DebounceInputModule, FeelPopupModule } from '@bpmn-io/properties-panel'; 5 | 6 | export default { 7 | __depends__: [ 8 | Commands, 9 | DebounceInputModule, 10 | FeelPopupModule 11 | ], 12 | __init__: [ 13 | 'propertiesPanel' 14 | ], 15 | propertiesPanel: [ 'type', BpmnPropertiesPanelRenderer ] 16 | }; -------------------------------------------------------------------------------- /src/utils/ElementUtil.js: -------------------------------------------------------------------------------- 1 | import Ids from 'ids'; 2 | 3 | import { 4 | is 5 | } from 'bpmn-js/lib/util/ModelUtil'; 6 | 7 | /** 8 | * Create a new element and (optionally) set its parent. 9 | * 10 | * @param {string} type 11 | * @param {Object} properties 12 | * @param {import('bpmn-js/lib/model/Types').ModdleElement} parent 13 | * @param {import('bpmn-js/lib/features/modeling/BpmnFactory').default} bpmnFactory 14 | * 15 | * @returns {import('bpmn-js/lib/model/Types').ModdleElement} 16 | */ 17 | export function createElement(type, properties, parent, bpmnFactory) { 18 | const element = bpmnFactory.create(type, properties); 19 | 20 | if (parent) { 21 | element.$parent = parent; 22 | } 23 | 24 | return element; 25 | } 26 | 27 | /** 28 | * generate a semantic id with given prefix 29 | */ 30 | export function nextId(prefix) { 31 | const ids = new Ids([ 32,32,1 ]); 32 | 33 | return ids.nextPrefixed(prefix); 34 | } 35 | 36 | export function getRoot(businessObject) { 37 | let parent = businessObject; 38 | 39 | while (parent.$parent) { 40 | parent = parent.$parent; 41 | } 42 | 43 | return parent; 44 | } 45 | 46 | export function filterElementsByType(objectList, type) { 47 | const list = objectList || []; 48 | 49 | return list.filter(element => is(element, type)); 50 | } 51 | 52 | export function findRootElementsByType(businessObject, referencedType) { 53 | const root = getRoot(businessObject); 54 | 55 | return filterElementsByType(root.get('rootElements'), referencedType); 56 | } 57 | 58 | export function findRootElementById(businessObject, type, id) { 59 | const elements = findRootElementsByType(businessObject, type); 60 | 61 | return elements.find(element => element.id === id); 62 | } 63 | -------------------------------------------------------------------------------- /src/utils/ValidationUtil.js: -------------------------------------------------------------------------------- 1 | const SPACE_REGEX = /\s/; 2 | 3 | // for QName validation as per http://www.w3.org/TR/REC-xml/#NT-NameChar 4 | const QNAME_REGEX = /^([a-z][\w-.]*:)?[a-z_][\w-.]*$/i; 5 | 6 | // for ID validation as per BPMN Schema (QName - Namespace) 7 | const ID_REGEX = /^[a-z_][\w-.]*$/i; 8 | 9 | /** 10 | * checks whether the id value is valid 11 | * 12 | * @param {ModdleElement} element 13 | * @param {String} idValue 14 | * @param {Function} translate 15 | * 16 | * @return {String} error message 17 | */ 18 | export function isIdValid(element, idValue, translate) { 19 | const assigned = element.$model.ids.assigned(idValue); 20 | const idAlreadyExists = assigned && assigned !== element; 21 | 22 | if (!idValue) { 23 | return translate('ID must not be empty.'); 24 | } 25 | 26 | if (idAlreadyExists) { 27 | return translate('ID must be unique.'); 28 | } 29 | 30 | return validateId(idValue, translate); 31 | } 32 | 33 | export function validateId(idValue, translate) { 34 | 35 | if (containsSpace(idValue)) { 36 | return translate('ID must not contain spaces.'); 37 | } 38 | 39 | if (!ID_REGEX.test(idValue)) { 40 | 41 | if (QNAME_REGEX.test(idValue)) { 42 | return translate('ID must not contain prefix.'); 43 | } 44 | 45 | return translate('ID must be a valid QName.'); 46 | } 47 | } 48 | 49 | export function containsSpace(value) { 50 | return SPACE_REGEX.test(value); 51 | } -------------------------------------------------------------------------------- /tasks/wiredeps: -------------------------------------------------------------------------------- 1 | #! /bin/bash 2 | 3 | wire() { 4 | echo "Attempting to install $1@$2"; 5 | 6 | npm install "$1@bpmn-io/$1#$2"; 7 | 8 | if [ $? -ne 0 ]; then 9 | echo "Falling back to $1@master"; 10 | 11 | npm install "$1@bpmn-io/$1#master"; 12 | fi 13 | } 14 | 15 | FEATURE_BRANCH= 16 | 17 | if [ "$TRAVIS_TAG" == "" ]; then 18 | if [ "$TRAVIS_PULL_REQUEST_BRANCH" != "" ]; then 19 | FEATURE_BRANCH="$TRAVIS_PULL_REQUEST_BRANCH"; 20 | else 21 | FEATURE_BRANCH="$TRAVIS_BRANCH"; 22 | fi 23 | 24 | wire "diagram-js" "$FEATURE_BRANCH"; 25 | wire "bpmn-js" "$FEATURE_BRANCH"; 26 | 27 | fi -------------------------------------------------------------------------------- /test/.eslintrc: -------------------------------------------------------------------------------- 1 | 2 | { 3 | "extends": [ 4 | "plugin:bpmn-io/mocha" 5 | ], 6 | "globals": { 7 | "sinon": true 8 | } 9 | } -------------------------------------------------------------------------------- /test/coverageBundle.js: -------------------------------------------------------------------------------- 1 | const allTests = require.context('.', true, /.spec\.js$/); 2 | 3 | allTests.keys().forEach(allTests); 4 | 5 | const allSources = require.context('../src', true, /.*\.js$/); 6 | 7 | allSources.keys().forEach(allSources); -------------------------------------------------------------------------------- /test/distro/distroSpec.js: -------------------------------------------------------------------------------- 1 | const { 2 | expect 3 | } = require('chai'); 4 | 5 | const fs = require('fs'), 6 | path = require('path'); 7 | 8 | const DIST_DIR = path.join(__dirname, '../../dist'); 9 | 10 | describe('modules', function() { 11 | 12 | it('should expose CJS bundle', verifyExists('index.js')); 13 | 14 | }); 15 | 16 | function verifyExists(relativePath) { 17 | return function() { 18 | 19 | // given 20 | const filePath = path.join(DIST_DIR, relativePath); 21 | 22 | // then 23 | expect(fs.existsSync(filePath), `file ${relativePath} does not exist`).to.be.true; 24 | }; 25 | } 26 | -------------------------------------------------------------------------------- /test/spec/mocks/index.js: -------------------------------------------------------------------------------- 1 | class Canvas { 2 | getRootElement() {} 3 | } 4 | 5 | 6 | export class ElementRegistry { 7 | constructor() { 8 | this.elements = []; 9 | } 10 | 11 | setElements(elements) { 12 | this.elements = elements; 13 | } 14 | 15 | get(id) { 16 | return this.elements.find(e => e.id === id); 17 | } 18 | } 19 | 20 | export class EventBus { 21 | constructor() { 22 | this.listeners = {}; 23 | } 24 | 25 | on(event, priority, callback) { 26 | if (!callback) { 27 | callback = priority; 28 | } 29 | 30 | if (!this.listeners[ event ]) { 31 | this.listeners[ event ] = []; 32 | } 33 | 34 | this.listeners[ event ].push(callback); 35 | } 36 | 37 | off() {} 38 | 39 | fire(event, context) { 40 | if (this.listeners[ event ]) { 41 | this.listeners[ event ].forEach(callback => callback(context)); 42 | } 43 | } 44 | } 45 | 46 | export class Injector { 47 | 48 | constructor(options = {}) { 49 | this._options = options; 50 | } 51 | 52 | get(type) { 53 | 54 | if (type === 'elementRegistry') { 55 | return this._options.elementRegistry || new ElementRegistry(); 56 | } 57 | 58 | if (type === 'eventBus') { 59 | return this._options.eventBus || new EventBus(); 60 | } 61 | 62 | if (type === 'canvas') { 63 | return new Canvas(); 64 | } 65 | } 66 | } 67 | 68 | export function getProviders() { 69 | return [ { 70 | getGroups: () => (groups) => groups 71 | } ]; 72 | } -------------------------------------------------------------------------------- /test/spec/provider/HOCs/withTooltipContainer.bpmn: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /test/spec/provider/HOCs/withVariableContext.bpmn: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /test/spec/provider/bpmn/ErrorProps.bpmn: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /test/spec/provider/bpmn/ExecutableProps.bpmn: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /test/spec/provider/bpmn/ExecutableProps.participants.bpmn: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /test/spec/provider/bpmn/IdProps.bpmn: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /test/spec/provider/bpmn/LinkProps.bpmn: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /test/spec/provider/camunda-platform/ConnectorInputProps.bpmn: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | Connector_1 14 | 15 | 16 | 17 | 18 | 19 | 20 | Connector_2 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /test/spec/provider/camunda-platform/ConnectorOutputProps.bpmn: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | Connector_1 14 | 15 | 16 | 17 | 18 | 19 | 20 | Connector_2 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /test/spec/provider/camunda-platform/ExternalTaskPriority-Collaboration.bpmn: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /test/spec/provider/camunda-platform/HistoryCleanupProps-collaboration.bpmn: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /test/spec/provider/camunda-platform/HistoryCleanupProps-process.bpmn: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /test/spec/provider/camunda-platform/InitiatorProps.bpmn: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /test/spec/provider/camunda-platform/JobExecutionProps-Collaboration.bpmn: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /test/spec/provider/camunda-platform/ListProps.bpmn: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | value1 10 | value2 11 | value2 12 | 13 | 14 | value 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /test/spec/provider/camunda-platform/MapProps.bpmn: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | value1 10 | value2 11 | value3 12 | 13 | 14 | value 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /test/spec/provider/camunda-platform/ScriptProps.bpmn: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | script 6 | 7 | 8 | 9 | 10 | script 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /test/spec/provider/camunda-platform/TasklistProps-collaboration.bpmn: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /test/spec/provider/camunda-platform/TasklistProps-process.bpmn: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /test/spec/provider/camunda-platform/UserAssignmentProps.bpmn: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /test/spec/provider/camunda-platform/VersionTagProps-collaboration.bpmn: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /test/spec/provider/camunda-platform/VersionTagProps-process.bpmn: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /test/spec/provider/shared/ExtensionProperty.bpmn: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /test/spec/provider/zeebe/BusinessRuleImplementationProps.bpmn: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /test/spec/provider/zeebe/CalledDecisionProps.bpmn: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /test/spec/provider/zeebe/Header.bpmn: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /test/spec/provider/zeebe/InputOutputParameter.bpmn: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /test/spec/provider/zeebe/ScriptImplementationProps.bpmn: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /test/spec/provider/zeebe/ScriptProps.bpmn: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /test/spec/provider/zeebe/UserTaskImplementationProps.bpmn: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /test/spec/provider/zeebe/VersionTagProps-collaboration.bpmn: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /test/spec/provider/zeebe/VersionTagProps-process.bpmn: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /test/spec/utils/TimerUtilSpec.js: -------------------------------------------------------------------------------- 1 | import { 2 | bootstrapCamundaCloudModeler, 3 | inject 4 | } from 'test/TestHelper'; 5 | 6 | import { isTimerExpressionTypeSupported } from '../../../src/provider/zeebe/utils/TimerUtil'; 7 | 8 | import diagramXML from './TimerUtil.bpmn'; 9 | 10 | 11 | describe('camunda-cloud/util - TimerUtil', function() { 12 | 13 | beforeEach(bootstrapCamundaCloudModeler(diagramXML)); 14 | 15 | 16 | expectTimerExpressionTypesSupported('timer start event', 'TimerStartEvent_1', { 17 | timeCycle: true, 18 | timeDate: true, 19 | timeDuration: false 20 | }); 21 | 22 | 23 | expectTimerExpressionTypesSupported('timer intermediate catch event', 'TimerIntermediateCatchEvent_1', { 24 | timeCycle: false, 25 | timeDate: true, 26 | timeDuration: true 27 | }); 28 | 29 | 30 | expectTimerExpressionTypesSupported('non-interrupting timer boundary event', 'NonInterruptingTimerBoundaryEvent_1', { 31 | timeCycle: true, 32 | timeDate: true, 33 | timeDuration: true 34 | }); 35 | 36 | 37 | expectTimerExpressionTypesSupported('timer boundary event', 'TimerBoundaryEvent_1', { 38 | timeCycle: false, 39 | timeDate: true, 40 | timeDuration: true 41 | }); 42 | 43 | 44 | expectTimerExpressionTypesSupported('non-interrupting timer start event (event sub-process)', 'NonInterruptingTimerStartEvent_1', { 45 | timeCycle: true, 46 | timeDate: true, 47 | timeDuration: true 48 | }); 49 | 50 | 51 | expectTimerExpressionTypesSupported('timer start event (event sub-process)', 'TimerStartEvent_2', { 52 | timeCycle: false, 53 | timeDate: true, 54 | timeDuration: true 55 | }); 56 | 57 | }); 58 | 59 | 60 | 61 | // helpers ////////// 62 | 63 | function expectTimerExpressionTypesSupported(elementType, elementId, expressionTypes) { 64 | it(`should support expression types for ${ elementType }`, inject(function(elementRegistry) { 65 | const element = elementRegistry.get(elementId); 66 | 67 | for (const expressionType in expressionTypes) { 68 | expect(isTimerExpressionTypeSupported(expressionType, element)).to.equal(expressionTypes[ expressionType ]); 69 | } 70 | })); 71 | } -------------------------------------------------------------------------------- /test/test.css: -------------------------------------------------------------------------------- 1 | @import url('https://fonts.googleapis.com/css2?family=IBM+Plex+Sans:wght@300;400;500;600&display=swap'); 2 | 3 | * { 4 | box-sizing: border-box; 5 | } 6 | 7 | html, 8 | body { 9 | height: 100%; 10 | margin: 0; 11 | font-family: 'IBM Plex Sans', sans-serif; 12 | } 13 | 14 | .test-container { 15 | display: flex; 16 | flex-direction: column; 17 | height: 100vh !important; 18 | } 19 | 20 | .test-content-container { 21 | display: flex; 22 | flex: 1; 23 | flex-direction: row; 24 | overflow: hidden; 25 | } 26 | 27 | .modeler-container { 28 | flex: 1; 29 | } 30 | 31 | .properties-container { 32 | flex: none; 33 | width: 300px; 34 | border-left: solid 1px #cccccc; 35 | } 36 | 37 | .properties-container .bio-properties-panel { 38 | --font-family: 'IBM Plex Sans', sans-serif !important; 39 | } -------------------------------------------------------------------------------- /test/testBundle.js: -------------------------------------------------------------------------------- 1 | const allTests = require.context('.', true, /.spec\.js$/); 2 | 3 | allTests.keys().forEach(allTests); -------------------------------------------------------------------------------- /test/util/KeyEvents.js: -------------------------------------------------------------------------------- 1 | import { 2 | assign, 3 | isString, 4 | omit 5 | } from 'min-dash'; 6 | 7 | /** 8 | * Create a fake key event for testing purposes. 9 | * 10 | * @param {String|number} key the key or keyCode/charCode 11 | * @param {Object} [attrs] 12 | * @param {string} [attrs.type] 13 | * 14 | * @return {Event} 15 | */ 16 | export function createKeyEvent(key, attrs) { 17 | if (!attrs) { 18 | attrs = {}; 19 | } 20 | 21 | var event = document.createEvent('Events') || new document.defaultView.CustomEvent('keyEvent'); 22 | 23 | // init and mark as bubbles / cancelable 24 | event.initEvent(attrs.type || 'keydown', false, true); 25 | 26 | var keyAttrs = isString(key) ? { key: key } : { keyCode: key, which: key }; 27 | 28 | return assign(event, keyAttrs, omit(attrs, [ 'type' ])); 29 | } --------------------------------------------------------------------------------