Skip to content

Commit

Permalink
feat: support zeebe:userTask
Browse files Browse the repository at this point in the history
  • Loading branch information
barmac committed Feb 21, 2024
1 parent b6792df commit 022f027
Show file tree
Hide file tree
Showing 9 changed files with 731 additions and 30 deletions.
17 changes: 16 additions & 1 deletion src/provider/zeebe/ZeebePropertiesProvider.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@ import {
TargetProps,
TaskDefinitionProps,
TaskScheduleProps,
TimerProps
TimerProps,
UserTaskImplementationProps
} from './properties';

import { ExtensionPropertiesProps } from '../shared/ExtensionPropertiesProps';
Expand All @@ -39,6 +40,7 @@ const ZEEBE_GROUPS = [
CalledDecisionGroup,
ScriptImplementationGroup,
ScriptGroup,
UserTaskImplementationGroup,
TaskDefinitionGroup,
AssignmentDefinitionGroup,
FormGroup,
Expand Down Expand Up @@ -255,6 +257,19 @@ function ScriptImplementationGroup(element) {
return group.entries.length ? group : null;
}

function UserTaskImplementationGroup(element) {
const group = {
id: 'userTaskImplementation',
label: 'Implementation',
entries: [
...UserTaskImplementationProps({ element })
],
component: Group
};

return group.entries.length ? group : null;
}

function AssignmentDefinitionGroup(element) {
const group = {
id: 'assignmentDefinition',
Expand Down
114 changes: 91 additions & 23 deletions src/provider/zeebe/properties/FormProps.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import {
SelectEntry,
TextFieldEntry,
TextAreaEntry,
isSelectEntryEdited,
isTextFieldEntryEdited,
isTextAreaEntryEdited
} from '@bpmn-io/properties-panel';
Expand All @@ -28,9 +27,12 @@ import {
getFormType,
getRootElement,
getUserTaskForm,
isZeebeUserTask,
userTaskFormIdToFormKey
} from '../utils/FormUtil';

const NONE_VALUE = 'none';


export function FormProps(props) {
const { element } = props;
Expand All @@ -42,7 +44,7 @@ export function FormProps(props) {
const entries = [ {
id: 'formType',
component: FormType,
isEdited: isSelectEntryEdited
isEdited: node => node.value !== NONE_VALUE
} ];

const formType = getFormType(element);
Expand All @@ -62,7 +64,13 @@ export function FormProps(props) {
} else if (formType === FORM_TYPES.CUSTOM_FORM) {
entries.push({
id: 'customFormKey',
component: CustomFormKey,
component: CustomForm,
isEdited: isTextFieldEntryEdited
});
} else if (formType === FORM_TYPES.EXTERNAL_REFERENCE) {
entries.push({
id: 'externalReference',
component: ExternalReference,
isEdited: isTextFieldEntryEdited
});
}
Expand All @@ -78,28 +86,15 @@ function FormType(props) {
translate = useService('translate');

const getValue = () => {
return getFormType(element) || '';
return getFormType(element) || NONE_VALUE;
};

const setValue = (value) => {
if (value === FORM_TYPES.CAMUNDA_FORM_EMBEDDED) {
setUserTaskForm(injector, element, '');
} else if (value === FORM_TYPES.CAMUNDA_FORM_LINKED) {
setFormId(injector, element, '');
} else if (value === FORM_TYPES.CUSTOM_FORM) {
setCustomFormKey(injector, element, '');
} else {
removeFormDefinition(injector, element);
}
setFormType(injector, element, value);
};

const getOptions = () => {
return [
{ value: '', label: translate('<none>') },
{ value: FORM_TYPES.CAMUNDA_FORM_LINKED, label: translate('Camunda Form (linked)') },
{ value: FORM_TYPES.CAMUNDA_FORM_EMBEDDED, label: translate('Camunda Form (embedded)') },
{ value: FORM_TYPES.CUSTOM_FORM, label: translate('Custom form key') }
];
return getFormTypeOptions(translate, element);
};

return SelectEntry({
Expand All @@ -112,6 +107,37 @@ function FormType(props) {
});
}

function setFormType(injector, element, value) {
if (value === FORM_TYPES.CAMUNDA_FORM_EMBEDDED) {
setUserTaskForm(injector, element, '');
} else if (value === FORM_TYPES.CAMUNDA_FORM_LINKED) {
setFormId(injector, element, '');
} else if (value === FORM_TYPES.CUSTOM_FORM) {
setCustomFormKey(injector, element, '');
} else if (value === FORM_TYPES.EXTERNAL_REFERENCE) {
setExternalReference(injector, element, '');
} else {
removeFormDefinition(injector, element);
}
}

function getFormTypeOptions(translate, element) {
if (isZeebeUserTask(element)) {
return [
{ value: NONE_VALUE, label: translate('<none>') },
{ value: FORM_TYPES.CAMUNDA_FORM_LINKED, label: translate('Camunda Form') },
{ value: FORM_TYPES.EXTERNAL_REFERENCE, label: translate('External form reference') }
];
}

return [
{ value: NONE_VALUE, label: translate('<none>') },
{ value: FORM_TYPES.CAMUNDA_FORM_LINKED, label: translate('Camunda Form (linked)') },
{ value: FORM_TYPES.CAMUNDA_FORM_EMBEDDED, label: translate('Camunda Form (embedded)') },
{ value: FORM_TYPES.CUSTOM_FORM, label: translate('Custom form key') }
];
}


function FormConfiguration(props) {
const { element } = props;
Expand Down Expand Up @@ -165,16 +191,16 @@ function FormId(props) {
});
}


function CustomFormKey(props) {
function CustomForm(props) {
const { element } = props;

const debounce = useService('debounceInput'),
injector = useService('injector'),
translate = useService('translate');

const getValue = () => {
return getFormDefinition(element).get('formKey');
const formDefinition = getFormDefinition(element);
return formDefinition.get('formKey');
};

const setValue = (value) => {
Expand All @@ -184,7 +210,33 @@ function CustomFormKey(props) {
return TextFieldEntry({
element,
id: 'customFormKey',
label: translate('Form key'),
label: translate('Custom form key'),
getValue,
setValue,
debounce
});
}

function ExternalReference(props) {
const { element } = props;

const debounce = useService('debounceInput'),
injector = useService('injector'),
translate = useService('translate');

const getValue = () => {
const formDefinition = getFormDefinition(element);
return formDefinition.get('externalReference');
};

const setValue = (value) => {
setExternalReference(injector, element, isUndefined(value) ? '' : value);
};

return TextFieldEntry({
element,
id: 'externalReference',
label: translate('External form reference'),
getValue,
setValue,
debounce
Expand Down Expand Up @@ -370,6 +422,22 @@ function setCustomFormKey(injector, element, formKey) {
]);
}

function setExternalReference(injector, element, externalReference) {
let {
commands,
formDefinition
} = getOrCreateFormDefintition(injector, element);

const commandStack = injector.get('commandStack');

commandStack.execute('properties-panel.multi-command-executor', [
...commands,
createUpdateModdlePropertiesCommand(element, formDefinition, {
externalReference
})
]);
}

function setUserTaskForm(injector, element, body) {
let {
commands,
Expand Down
125 changes: 125 additions & 0 deletions src/provider/zeebe/properties/UserTaskImplementationProps.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
import {
getBusinessObject
} from 'bpmn-js/lib/util/ModelUtil';

import {
is
} from 'bpmn-js/lib/util/ModelUtil';

import { SelectEntry } from '@bpmn-io/properties-panel';

import {
addExtensionElements,
getExtensionElementsList,
removeExtensionElements
} from '../../../utils/ExtensionElementsUtil';

import {
createElement
} from '../../../utils/ElementUtil';

import { useService } from '../../../hooks';

export const ZEEBE_USER_TASK_IMPLEMENTATION_OPTION = 'zeebeUserTask',
JOB_WORKER_IMPLEMENTATION_OPTION = 'jobWorker';


export function UserTaskImplementationProps(props) {
const {
element
} = props;

if (!is(element, 'bpmn:UserTask')) {
return [];
}

return [
{
id: 'userTaskImplementation',
component: UserTaskImplementation,
isEdited: () => isUserTaskImplementationEdited(element)
}
];
}

function UserTaskImplementation(props) {
const {
element,
id
} = props;

const commandStack = useService('commandStack');
const bpmnFactory = useService('bpmnFactory');
const translate = useService('translate');

const getValue = () => {
if (getZeebeUserTask(element)) {
return ZEEBE_USER_TASK_IMPLEMENTATION_OPTION;
}

return JOB_WORKER_IMPLEMENTATION_OPTION;
};

/**
* Set value by either creating or removing zeebe:userTask extension element.
* Note that they must not exist both at the same time, however this
* will be ensured by a camunda-bpmn-js behavior (and not by the propPanel).
*/
const setValue = (value) => {
if (value === ZEEBE_USER_TASK_IMPLEMENTATION_OPTION) {
createZeebeUserTask(element, bpmnFactory, commandStack);
} else if (value === JOB_WORKER_IMPLEMENTATION_OPTION) {
removeZeebeUserTask(element, commandStack);
}
};

const getOptions = () => {

const options = [
{ value: ZEEBE_USER_TASK_IMPLEMENTATION_OPTION, label: translate('Zeebe user task') },
{ value: JOB_WORKER_IMPLEMENTATION_OPTION, label: translate('Job worker') }
];

return options;
};

return SelectEntry({
element,
id,
label: translate('Implementation'),
getValue,
setValue,
getOptions
});
}


// helper ///////////////////////
function createZeebeUserTask(element, bpmnFactory, commandStack) {
const businessObject = getBusinessObject(element);

const zeebeUserTask = createElement(
'zeebe:UserTask',
{},
businessObject,
bpmnFactory
);

addExtensionElements(element, businessObject, zeebeUserTask, bpmnFactory, commandStack);
}

function removeZeebeUserTask(element, commandStack) {
const zeebeUserTask = getZeebeUserTask(element);

removeExtensionElements(element, getBusinessObject(element), zeebeUserTask, commandStack);
}

function isUserTaskImplementationEdited(element) {
return getZeebeUserTask(element);
}

function getZeebeUserTask(element) {
const businessObject = getBusinessObject(element);

return getExtensionElementsList(businessObject, 'zeebe:UserTask')[0];
}
1 change: 1 addition & 0 deletions src/provider/zeebe/properties/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,4 @@ export { TargetProps } from './TargetProps';
export { TaskDefinitionProps } from './TaskDefinitionProps';
export { TaskScheduleProps } from './TaskScheduleProps';
export { TimerProps } from './TimerProps';
export { UserTaskImplementationProps } from './UserTaskImplementationProps';
Loading

0 comments on commit 022f027

Please sign in to comment.