Squashed 'bpmn-js-spiffworkflow/' changes from 9dcca6c80..6007a770a

6007a770a fix typo
aa524120b Merge pull request #47 from sartography/dependabot/github_actions/crazy-max/ghaction-github-labeler-5.0.0
75556c020 Bump crazy-max/ghaction-github-labeler from 4.2.0 to 5.0.0
9a5c333de Merge pull request #46 from sartography/feature/better_form_nav
c6c955284 Merge pull request #43 from sartography/bugfix/update-data-input-output-specs
094c573e0 fixing a test.
5fcb47125 Assume established naming conventions over requiring a form schema and ui schema each time as separate inputs. Making this one dropdown for the user form instead of two.
53f45dbaa Merge pull request #45 from sartography/dependabot/github_actions/actions/checkout-4
67765a994 Bump actions/checkout from 3 to 4
dbcd66942 Merge pull request #44 from sartography/dependabot/github_actions/crazy-max/ghaction-github-labeler-4.2.0
b8be0e335 Bump crazy-max/ghaction-github-labeler from 4.1.0 to 4.2.0
7743372d2 update iospec to include refs in input/output sets
6e17bda37 use same version of bpmn-js as arena
2c7fca88f missed a type in spiffworkflow.json
d62f021e3 Merge pull request #42 from sartography/bugfix/lowercase-overridden-tags
c625980c5 update extension names
e92ae2f5a make sure tags with extensions are written to xml correctly
eb37b6d29 Merge pull request #41 from sartography/feature/guest_form_submission
1b390c46c added panel extensions for guest access to human tasks w/ burnettk
f01bece04 Merge pull request #40 from sartography/feature/multiinstance-improvements
b8179146b allow attaching pre/post scripts to MI task or instance tasks

git-subtree-dir: bpmn-js-spiffworkflow
git-subtree-split: 6007a770a5938c993173001a013116cedfc80359
This commit is contained in:
burnettk 2023-10-14 12:30:16 -04:00
parent 7db152f010
commit 392c9a1b44
24 changed files with 4186 additions and 9625 deletions

View File

@ -11,9 +11,9 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Check out the repository
uses: actions/checkout@v3
uses: actions/checkout@v4
- name: Run Labeler
uses: crazy-max/ghaction-github-labeler@v4.1.0
uses: crazy-max/ghaction-github-labeler@v5.0.0
with:
skip-delete: true

View File

@ -12,7 +12,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3 #Checkout Repo
- uses: actions/checkout@v4 #Checkout Repo
- uses: actions/setup-node@v3 #Setup Node
with:
node-version: 18

View File

@ -18,7 +18,7 @@ jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3 #Checkout Repo
- uses: actions/checkout@v4 #Checkout Repo
- uses: actions/setup-node@v3 #Setup Node
- uses: nanasess/setup-chromedriver@v2 #Setup ChromeDriver
with:

View File

@ -160,8 +160,8 @@ bpmnModeler.on('spiff.dmn.edit', (newEvent) => {
* Also handy to get a list of available files that can be used in a given
* context, say json files for a form, or a DMN file for a BusinessRuleTask
*/
bpmnModeler.on('spiff.json_files.requested', (event) => {
event.eventBus.fire('spiff.json_files.returned', {
bpmnModeler.on('spiff.json_schema_files.requested', (event) => {
event.eventBus.fire('spiff.json_schema_files.returned', {
options: [
{ label: 'pizza_form.json', value: 'pizza_form.json' },
{ label: 'credit_card_form.json', value: 'credit_card_form.json' },

View File

@ -30,7 +30,7 @@ export default class IoInterceptor extends CommandInterceptor {
let process = context.parent.businessObject;
let ioSpec = assureIOSpecificationExists(process, bpmnFactory);
let di = context.shape.di;
let generator = new IdGenerator(type_name), ioSpecification = process.get('ioSpecification');
let generator = new IdGenerator(type_name);
let dataIO = bpmnFactory.create(type, { id: generator.next() });
context.shape.businessObject = dataIO;
dataIO.$parent = ioSpec;
@ -40,9 +40,11 @@ export default class IoInterceptor extends CommandInterceptor {
bpmnUpdater.updateBounds(context.shape);
if (type == 'bpmn:DataInput') {
collectionAdd(ioSpecification.get('dataInputs'), dataIO);
collectionAdd(ioSpec.inputSets[0].get('dataInputRefs'), dataIO);
collectionAdd(ioSpec.get('dataInputs'), dataIO);
} else {
collectionAdd(ioSpecification.get('dataOutputs'), dataIO);
collectionAdd(ioSpec.outputSets[0].get('dataOutputRefs'), dataIO);
collectionAdd(ioSpec.get('dataOutputs'), dataIO);
}
}
});
@ -54,8 +56,10 @@ export default class IoInterceptor extends CommandInterceptor {
let process = context.shape.parent.businessObject;
let ioSpec = assureIOSpecificationExists(process, bpmnFactory);
if (type == 'bpmn:DataInput') {
collectionRemove(ioSpec.inputSets[0].get('dataInputRefs'), context.shape.businessObject);
collectionRemove(ioSpec.get('dataInputs'), context.shape.businessObject);
} else {
collectionRemove(ioSpec.outputSets[0].get('dataOutputRefs'), context.shape.businessObject);
collectionRemove(ioSpec.get('dataOutputs'), context.shape.businessObject);
}
if (context.shape.di.$parent) {

View File

@ -148,7 +148,7 @@ function getTextFieldForExtension(eventDetails, label, description, catching) {
const debounce = useService('debounceInput');
const translate = useService('translate');
const root = getRoot(element.businessObject);
const extensionName = (catching) ? 'spiffworkflow:variableName' : 'spiffworkflow:payloadExpression';
const extensionName = (catching) ? 'spiffworkflow:VariableName' : 'spiffworkflow:PayloadExpression';
const getEvent = () => {
const eventDef = element.businessObject.eventDefinitions.find(v => v.$type == eventDefType);

View File

@ -1,5 +1,5 @@
const SPIFF_PARENT_PROP = 'spiffworkflow:properties';
const SPIFF_PROP = 'spiffworkflow:property';
const SPIFF_PARENT_PROP = 'spiffworkflow:Properties';
const SPIFF_PROP = 'spiffworkflow:Property';
const PREFIX = 'spiffworkflow:';
/**

View File

@ -1,16 +1,22 @@
import { ListGroup } from '@bpmn-io/properties-panel';
import {
ListGroup,
CheckboxEntry,
isCheckboxEntryEdited,
} from '@bpmn-io/properties-panel';
import { is, isAny } from 'bpmn-js/lib/util/ModelUtil';
import scriptGroup, { SCRIPT_TYPE } from './SpiffScriptGroup';
import {
ServiceTaskParameterArray,
ServiceTaskOperatorSelect, ServiceTaskResultTextInput,
} from './SpiffExtensionServiceProperties';
import {OPTION_TYPE, SpiffExtensionSelect} from './SpiffExtensionSelect';
import {OPTION_TYPE, spiffExtensionOptions, SpiffExtensionSelect} from './SpiffExtensionSelect';
import {SpiffExtensionLaunchButton} from './SpiffExtensionLaunchButton';
import {SpiffExtensionTextArea} from './SpiffExtensionTextArea';
import {SpiffExtensionTextInput} from './SpiffExtensionTextInput';
import {SpiffExtensionCheckboxEntry} from './SpiffExtensionCheckboxEntry';
import {hasEventDefinition} from 'bpmn-js/lib/util/DiUtil';
import { PropertyDescription } from 'bpmn-js-properties-panel/';
import {setExtensionValue} from "../extensionHelpers";
const LOW_PRIORITY = 500;
@ -57,6 +63,16 @@ export default function ExtensionsPropertiesProvider(
createUserInstructionsGroup(element, translate, moddle, commandStack)
);
}
if (
isAny(element, [
'bpmn:ManualTask',
'bpmn:UserTask',
])
) {
groups.push(
createAllowGuestGroup(element, translate, moddle, commandStack)
);
}
if (
is(element, 'bpmn:BoundaryEvent') &&
hasEventDefinition(element, 'bpmn:SignalEventDefinition') &&
@ -117,10 +133,7 @@ function createScriptGroup(element, translate, moddle, commandStack) {
* @returns The components to add to the properties panel.
*/
function preScriptPostScriptGroup(element, translate, moddle, commandStack) {
return {
id: 'spiff_pre_post_scripts',
label: translate('Pre/Post Scripts'),
entries: [
const entries = [
...scriptGroup({
element,
moddle,
@ -139,10 +152,50 @@ function preScriptPostScriptGroup(element, translate, moddle, commandStack) {
label: 'Post-Script',
description: 'code to execute after this task.',
}),
],
];
const loopCharacteristics = element.businessObject.loopCharacteristics;
if (typeof(loopCharacteristics) !== 'undefined') {
entries.push({
id: 'scriptValence',
component: ScriptValenceCheckbox,
isEdited: isCheckboxEntryEdited,
commandStack,
});
}
return {
id: 'spiff_pre_post_scripts',
label: translate('Pre/Post Scripts'),
entries: entries,
};
}
function ScriptValenceCheckbox(props) {
const { element, commandStack } = props;
const getValue = () => {
return element.businessObject.loopCharacteristics.scriptsOnInstances;
};
const setValue = (value) => {
const loopCharacteristics = element.businessObject.loopCharacteristics;
loopCharacteristics.scriptsOnInstances = value || undefined;
commandStack.execute('element.updateModdleProperties', {
element,
moddleElement: loopCharacteristics,
});
};
return CheckboxEntry({
element,
id: 'selectScriptValence',
label: 'Run scripts on instances',
description: 'By default, scripts will attach to the multiinstance task',
getValue,
setValue,
});
}
/**
* Create a group on the main panel with a select box (for choosing the Data Object to connect)
* @param element
@ -151,6 +204,17 @@ function preScriptPostScriptGroup(element, translate, moddle, commandStack) {
* @returns entries
*/
function createUserGroup(element, translate, moddle, commandStack) {
const updateExtensionProperties = (element, name, value, moddle, commandStack) => {
const uiName = value.replace('schema\.json', 'uischema\.json')
setExtensionValue(element, 'formJsonSchemaFilename', value, moddle, commandStack);
setExtensionValue(element, 'formUiSchemaFilename', uiName, moddle, commandStack);
const matches = spiffExtensionOptions[OPTION_TYPE.json_schema_files].filter((opt) => opt.value === value);
if (matches.length === 0) {
spiffExtensionOptions[OPTION_TYPE.json_schema_files].push({label: value, value: value});
}
}
return {
id: 'user_task_properties',
label: translate('Web Form (with Json Schemas)'),
@ -160,7 +224,7 @@ function createUserGroup(element, translate, moddle, commandStack) {
moddle,
commandStack,
component: SpiffExtensionSelect,
optionType: OPTION_TYPE.json_files,
optionType: OPTION_TYPE.json_schema_files,
name: 'formJsonSchemaFilename',
label: translate('JSON Schema Filename'),
description: translate('Form Description (RSJF)'),
@ -168,29 +232,14 @@ function createUserGroup(element, translate, moddle, commandStack) {
{
component: SpiffExtensionLaunchButton,
element,
moddle,
commandStack,
name: 'formJsonSchemaFilename',
label: translate('Launch Editor'),
event: 'spiff.file.edit',
description: translate('Edit the form description'),
},
{
element,
moddle,
commandStack,
component: SpiffExtensionSelect,
optionType: OPTION_TYPE.json_files,
label: translate('UI Schema Filename'),
event: 'spiff.file.edit',
description: translate('Rules for displaying the form. (RSJF Schema)'),
name: 'formUiSchemaFilename',
},
{
component: SpiffExtensionLaunchButton,
element,
name: 'formUiSchemaFilename',
label: translate('Launch Editor'),
event: 'spiff.file.edit',
description: translate('Edit the form schema'),
listenEvent: 'spiff.jsonSchema.update',
listenFunction: updateExtensionProperties,
description: translate('Edit the form schema')
},
],
};
@ -216,14 +265,14 @@ function createBusinessRuleGroup(element, translate, moddle, commandStack) {
commandStack,
component: SpiffExtensionSelect,
optionType: OPTION_TYPE.dmn_files,
name: 'spiffworkflow:calledDecisionId',
name: 'spiffworkflow:CalledDecisionId',
label: translate('Select Decision Table'),
description: translate('Select a decision table from the list'),
},
{
element,
component: SpiffExtensionLaunchButton,
name: 'spiffworkflow:calledDecisionId',
name: 'spiffworkflow:CalledDecisionId',
label: translate('Launch Editor'),
event: 'spiff.dmn.edit',
description: translate('Modify the Decision Table'),
@ -254,7 +303,7 @@ function createUserInstructionsGroup (
moddle,
commandStack,
component: SpiffExtensionTextArea,
name: 'spiffworkflow:instructionsForEndUser',
name: 'spiffworkflow:InstructionsForEndUser',
label: 'Instructions',
description: 'Displayed above user forms or when this task is executing.',
},
@ -263,7 +312,7 @@ function createUserInstructionsGroup (
moddle,
commandStack,
component: SpiffExtensionLaunchButton,
name: 'spiffworkflow:instructionsForEndUser',
name: 'spiffworkflow:InstructionsForEndUser',
label: translate('Launch Editor'),
event: 'spiff.markdown.edit',
listenEvent: 'spiff.markdown.update',
@ -273,6 +322,55 @@ function createUserInstructionsGroup (
};
}
/**
* Create a group on the main panel with a text box (for choosing the information to display to the user)
* @param element
* @param translate
* @param moddle
* @returns entries
*/
function createAllowGuestGroup (
element,
translate,
moddle,
commandStack
) {
return {
id: 'allow_guest_user',
label: translate('Guest options'),
entries: [
{
element,
moddle,
commandStack,
component: SpiffExtensionCheckboxEntry,
name: 'spiffworkflow:AllowGuest',
label: 'Guest can complete this task',
description: 'Allow a guest user to complete this task without logging in. They will not be allowed to do anything but submit this task. If another task directly follows it that allows guest access, they could also complete that task.',
},
{
element,
moddle,
commandStack,
component: SpiffExtensionTextArea,
name: 'spiffworkflow:GuestConfirmation',
label: 'Guest confirmation',
description: 'This is markdown that is displayed to the user after they complete the task. If this is filled out then the user will not be able to complete additional tasks without a new link to the next task.',
},
{
element,
moddle,
commandStack,
component: SpiffExtensionLaunchButton,
name: 'spiffworkflow:GuestConfirmation',
label: translate('Launch Editor'),
event: 'spiff.markdown.edit',
listenEvent: 'spiff.markdown.update',
}
],
};
}
/**
* Create a group on the main panel with a text box for specifying a
* a Button Label that is associated with a signal event.)
@ -299,7 +397,7 @@ function createSignalButtonGroup (
moddle,
commandStack,
component: SpiffExtensionTextInput,
name: 'spiffworkflow:signalButtonLabel',
name: 'spiffworkflow:SignalButtonLabel',
label: 'Button Label',
description: description
},

View File

@ -16,7 +16,7 @@ const getScriptUnitTestsModdleElement = (shapeElement) => {
return bizObj.extensionElements
.get('values')
.filter(function getInstanceOfType(e) {
return e.$instanceOf('spiffworkflow:unitTests');
return e.$instanceOf('spiffworkflow:UnitTests');
})[0];
};
@ -73,19 +73,19 @@ export function ScriptUnitTestArray(props) {
if (!scriptUnitTestsModdleElement) {
scriptUnitTestsModdleElement = scriptTaskModdleElement.$model.create(
'spiffworkflow:unitTests'
'spiffworkflow:UnitTests'
);
scriptTaskModdleElement.extensionElements
.get('values')
.push(scriptUnitTestsModdleElement);
}
const scriptUnitTestModdleElement = scriptTaskModdleElement.$model.create(
'spiffworkflow:unitTest'
'spiffworkflow:UnitTest'
);
const scriptUnitTestInputModdleElement =
scriptTaskModdleElement.$model.create('spiffworkflow:inputJson');
scriptTaskModdleElement.$model.create('spiffworkflow:InputJson');
const scriptUnitTestOutputModdleElement =
scriptTaskModdleElement.$model.create('spiffworkflow:expectedOutputJson');
scriptTaskModdleElement.$model.create('spiffworkflow:ExpectedOutputJson');
scriptUnitTestModdleElement.id = moddle.ids.nextPrefixed('ScriptUnitTest_');
scriptUnitTestInputModdleElement.value = '{}';
scriptUnitTestOutputModdleElement.value = '{}';

View File

@ -0,0 +1,36 @@
import {useService } from 'bpmn-js-properties-panel';
import {CheckboxEntry} from '@bpmn-io/properties-panel';
import {
getExtensionValue, setExtensionValue
} from '../extensionHelpers';
/**
* A generic properties' editor for text area.
*/
export function SpiffExtensionCheckboxEntry(props) {
const element = props.element;
const commandStack = props.commandStack, moddle = props.moddle;
const name = props.name, label = props.label, description = props.description;
const debounce = useService('debounceInput');
const getValue = () => {
return getExtensionValue(element, name)
}
const setValue = value => {
setExtensionValue(element, name, value, moddle, commandStack)
};
return <CheckboxEntry
id={'extension_' + name}
element={element}
description={description}
label={label}
getValue={getValue}
setValue={setValue}
debounce={debounce}
/>;
}

View File

@ -8,7 +8,7 @@ import {getExtensionValue, setExtensionValue} from '../extensionHelpers';
* update the value and send it back.
*/
export function SpiffExtensionLaunchButton(props) {
const { element, name, event, listenEvent } = props;
const { element, name, event, listenEvent, listenFunction } = props;
const eventBus = useService('eventBus');
return HeaderButton({
className: 'spiffworkflow-properties-panel-button',
@ -28,7 +28,11 @@ export function SpiffExtensionLaunchButton(props) {
const { commandStack, moddle } = props;
// Listen for a response, to update the script.
eventBus.once(listenEvent, (response) => {
if(listenFunction) {
listenFunction(element, name, response.value, moddle, commandStack);
} else {
setExtensionValue(element, name, response.value, moddle, commandStack);
}
});
}

View File

@ -5,10 +5,10 @@ import {
setExtensionValue,
} from '../extensionHelpers';
const spiffExtensionOptions = {};
export const spiffExtensionOptions = {};
export const OPTION_TYPE = {
json_files: 'json_files',
json_schema_files: 'json_schema_files',
dmn_files: 'dmn_files',
};
@ -52,6 +52,10 @@ export function SpiffExtensionSelect(props) {
}
const getOptions = () => {
const optionList = [];
optionList.push({
label: '',
value: '',
});
if (
optionType in spiffExtensionOptions &&
spiffExtensionOptions[optionType] !== null
@ -81,7 +85,7 @@ export function SpiffExtensionSelect(props) {
function requestOptions(eventBus, element, commandStack, optionType) {
// Little backwards, but you want to assure you are ready to catch, before you throw
// or you risk a race condition.
eventBus.once(`spiff.${optionType}.returned`, (event) => {
eventBus.on(`spiff.${optionType}.returned`, (event) => {
spiffExtensionOptions[optionType] = event.options;
});
eventBus.fire(`spiff.${optionType}.requested`, { eventBus });

View File

@ -12,9 +12,11 @@ let serviceTaskOperators = [];
const previouslyUsedServiceTaskParameterValuesHash = {};
const LOW_PRIORITY = 500;
const SERVICE_TASK_OPERATOR_ELEMENT_NAME = `${SPIFFWORKFLOW_XML_NAMESPACE}:serviceTaskOperator`;
const SERVICE_TASK_PARAMETERS_ELEMENT_NAME = `${SPIFFWORKFLOW_XML_NAMESPACE}:parameters`;
const SERVICE_TASK_PARAMETER_ELEMENT_NAME = `${SPIFFWORKFLOW_XML_NAMESPACE}:parameter`;
// I'm not going to change these variable names, but this is actually the name of the modeller
// type (as defined in moddle/spiffworkflow.json) NOT the element name (which is lowercase)
const SERVICE_TASK_OPERATOR_ELEMENT_NAME = `${SPIFFWORKFLOW_XML_NAMESPACE}:ServiceTaskOperator`;
const SERVICE_TASK_PARAMETERS_ELEMENT_NAME = `${SPIFFWORKFLOW_XML_NAMESPACE}:Parameters`;
const SERVICE_TASK_PARAMETER_ELEMENT_NAME = `${SPIFFWORKFLOW_XML_NAMESPACE}:Parameter`;
/**
* A generic properties' editor for text input.

View File

@ -9,8 +9,8 @@ import { ScriptUnitTestArray } from './ScriptUnitTestArray';
export const SCRIPT_TYPE = {
bpmn: 'bpmn:script',
pre: 'spiffworkflow:preScript',
post: 'spiffworkflow:postScript',
pre: 'spiffworkflow:PreScript',
post: 'spiffworkflow:PostScript',
};
function PythonScript(props) {

View File

@ -18,7 +18,7 @@ export function MessagePayload(props) {
return messageElement.extensionElements
.get('values')
.filter(function getInstanceOfType(e) {
return e.$instanceOf('spiffworkflow:messagePayload');
return e.$instanceOf('spiffworkflow:MessagePayload');
})[0];
}
}
@ -37,7 +37,7 @@ export function MessagePayload(props) {
let messagePayloadObject = getMessagePayloadObject();
if (!messagePayloadObject) {
messagePayloadObject = messageElement.$model.create(
'spiffworkflow:messagePayload'
'spiffworkflow:MessagePayload'
);
if (!messageElement.extensionElements) {
messageElement.extensionElements = messageElement.$model.create(

View File

@ -18,7 +18,7 @@ export function MessageVariable(props) {
return messageElement.extensionElements
.get('values')
.filter(function getInstanceOfType(e) {
return e.$instanceOf('spiffworkflow:messageVariable');
return e.$instanceOf('spiffworkflow:MessageVariable');
})[0];
}
}
@ -37,7 +37,7 @@ export function MessageVariable(props) {
let messageVariableObject = getMessageVariableObject();
if (!messageVariableObject) {
messageVariableObject = messageElement.$model.create(
'spiffworkflow:messageVariable'
'spiffworkflow:MessageVariable'
);
if (!messageElement.extensionElements) {
messageElement.extensionElements = messageElement.$model.create(

View File

@ -3,9 +3,10 @@
"uri": "http://spiffworkflow.org/bpmn/schema/1.0/core",
"prefix": "spiffworkflow",
"associations": [],
"xml": { "tagAlias": "lowerCase" },
"types": [
{
"name": "preScript",
"name": "PreScript",
"superClass": [ "Element" ],
"properties": [
{
@ -16,7 +17,7 @@
]
},
{
"name": "postScript",
"name": "PostScript",
"superClass": [ "Element" ],
"properties": [
{
@ -27,7 +28,7 @@
]
},
{
"name": "messagePayload",
"name": "MessagePayload",
"superClass": [ "Element" ],
"properties": [
{
@ -38,7 +39,7 @@
]
},
{
"name": "messageVariable",
"name": "MessageVariable",
"superClass": [ "Element" ],
"properties": [
{
@ -49,7 +50,7 @@
]
},
{
"name": "calledDecisionId",
"name": "CalledDecisionId",
"superClass": [ "Element" ],
"properties": [
{
@ -60,7 +61,7 @@
]
},
{
"name": "instructionsForEndUser",
"name": "InstructionsForEndUser",
"superClass": [ "Element" ],
"properties": [
{
@ -71,7 +72,18 @@
]
},
{
"name": "signalButtonLabel",
"name": "AllowGuest",
"superClass": [ "Element" ],
"properties": [
{
"name": "value",
"isBody": true,
"type": "Boolean"
}
]
},
{
"name": "GuestConfirmation",
"superClass": [ "Element" ],
"properties": [
{
@ -82,20 +94,31 @@
]
},
{
"name": "properties",
"name": "SignalButtonLabel",
"superClass": [ "Element" ],
"properties": [
{
"name": "value",
"isBody": true,
"type": "String"
}
]
},
{
"name": "Properties",
"superClass": [
"Element"
],
"properties": [
{
"name": "properties",
"type": "property",
"type": "Property",
"isMany": true
}
]
},
{
"name": "property",
"name": "Property",
"superClass": [ "Element" ],
"properties": [
{
@ -111,7 +134,7 @@
]
},
{
"name": "serviceTaskOperator",
"name": "ServiceTaskOperator",
"superClass": [
"Element"
],
@ -128,25 +151,25 @@
},
{
"name": "parameterList",
"type": "parameters"
"type": "Parameters"
}
]
},
{
"name": "parameters",
"name": "Parameters",
"superClass": [
"Element"
],
"properties": [
{
"name": "parameters",
"type": "parameter",
"type": "Parameter",
"isMany": true
}
]
},
{
"name": "parameter",
"name": "Parameter",
"superClass": [ "Element" ],
"properties": [
{
@ -167,20 +190,20 @@
]
},
{
"name": "unitTests",
"name": "UnitTests",
"superClass": [
"Element"
],
"properties": [
{
"name": "unitTests",
"type": "unitTest",
"type": "UnitTest",
"isMany": true
}
]
},
{
"name": "unitTest",
"name": "UnitTest",
"superClass": [ "Element" ],
"properties": [
{
@ -190,16 +213,16 @@
},
{
"name": "inputJson",
"type": "inputJson"
"type": "InputJson"
},
{
"name": "expectedOutputJson",
"type": "expectedOutputJson"
"type": "ExpectedOutputJson"
}
]
},
{
"name": "inputJson",
"name": "InputJson",
"superClass": [ "Element" ],
"properties": [
{
@ -210,7 +233,7 @@
]
},
{
"name": "expectedOutputJson",
"name": "ExpectedOutputJson",
"superClass": [ "Element" ],
"properties": [
{
@ -221,7 +244,7 @@
]
},
{
"name": "payloadExpression",
"name": "PayloadExpression",
"superClass": [ "Element" ],
"properties": [
{
@ -232,7 +255,7 @@
]
},
{
"name": "variableName",
"name": "VariableName",
"superClass": [ "Element" ],
"properties": [
{
@ -241,6 +264,20 @@
"type": "String"
}
]
},
{
"name": "ScriptsOnInstances",
"extends": [
"bpmn:MultiInstanceLoopCharacteristics",
"bpmn:StandardLoopCharacteristics"
],
"properties": [
{
"name": "scriptsOnInstances",
"isAttr": true,
"type": "Boolean"
}
]
}
]
}

13342
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -73,7 +73,7 @@
"webpack-cli": "^4.9.2"
},
"peerDependencies": {
"bpmn-js": "*",
"bpmn-js": "^13.0.0",
"bpmn-js-properties-panel": "*",
"diagram-js": "*"
},

View File

@ -49,7 +49,7 @@ describe('Business Rule Properties Panel', function () {
modeler.get('eventBus').once('spiff.dmn_files.requested', return_files);
expectSelected('business_rule_task');
// THEN - a properties panel exists with a section for editing that script
const entry = findEntry('extension_spiffworkflow:calledDecisionId', getPropertiesPanel());
const entry = findEntry('extension_spiffworkflow:CalledDecisionId', getPropertiesPanel());
expect(entry, 'No Entry').to.exist;
const selectList = findSelect(entry);
expect(selectList, 'No Select').to.exist;
@ -60,7 +60,7 @@ describe('Business Rule Properties Panel', function () {
const modeler = getBpmnJS();
modeler.get('eventBus').once('spiff.dmn_files.requested', return_files);
const businessRuleTask = await expectSelected('business_rule_task');
const entry = findEntry('extension_calledDecisionId', getPropertiesPanel());
const entry = findEntry('extension_CalledDecisionId', getPropertiesPanel());
const selectList = findSelect(entry);
changeInput(selectList, 'Decision_Pizza_Price');
@ -73,7 +73,7 @@ describe('Business Rule Properties Panel', function () {
it('should load up the xml and the value for the called decision should match the xml', async function () {
const businessRuleTask = await expectSelected('business_rule_task');
const entry = findEntry('extension_calledDecisionId', getPropertiesPanel());
const entry = findEntry('extension_CalledDecisionId', getPropertiesPanel());
const selectList = findSelect(entry);
expect(selectList.value, "initial value is wrong").to.equal('test_decision');

View File

@ -33,7 +33,8 @@ describe('Input/Output Interceptor', function() {
// THEN - the process should now have an IO Specification
const iospec = canvas.getRootElement().businessObject.ioSpecification;
expect(iospec).to.not.be.null;
expect(iospec.dataInputs.length).to.equal(1)
expect(iospec.dataInputs.length).to.equal(1);
expect(iospec.inputSets[0].dataInputRefs.length).to.equal(1);
}));
@ -60,4 +61,16 @@ describe('Input/Output Interceptor', function() {
modeling.removeShape(dataInput)
expect(canvas.getRootElement().businessObject.ioSpecification).to.be.null;
}));
it('deleting a data input should remove it from the input set', inject(function(canvas, modeling) {
let rootShape = canvas.getRootElement();
const dataInput = modeling.createShape({type: 'bpmn:DataInput'},
{x: 220, y: 220}, rootShape);
const dataOutput = modeling.createShape({type: 'bpmn:DataOutput'},
{x: 240, y: 220}, rootShape);
modeling.removeShape(dataInput);
const iospec = canvas.getRootElement().businessObject.ioSpecification;
expect(iospec.dataInputs.length).to.equal(0);
expect(iospec.inputSets[0].dataInputRefs.length).to.equal(0);
}));
});

View File

@ -62,10 +62,10 @@ describe('Properties Panel Script Tasks', function () {
expect(scriptInput.value).to.equal('x = 100');
});
it('should parse the bpmn:script tag when you open an existing file', async function () {
it('should parse the spiffworkflow:prescript tag when you open an existing file', async function () {
await expectSelected('task_confirm');
const entry = findEntry(
'pythonScript_spiffworkflow:preScript',
'pythonScript_spiffworkflow:PreScript',
PROPERTIES_PANEL_CONTAINER
);
const scriptInput = domQuery('textarea', entry);

View File

@ -18,7 +18,7 @@ import {
} from './helpers';
import extensions from '../../app/spiffworkflow/extensions';
import {query as domQuery} from 'min-dom';
import {default as diagram_xml} from './bpmn/diagram.bpmn';
describe('Properties Panel for User Tasks', function () {
const user_form_xml = require('./bpmn/user_form.bpmn').default;
@ -30,8 +30,8 @@ describe('Properties Panel for User Tasks', function () {
});
function addOptionsToEventBus(bpmnModeler) {
bpmnModeler.on('spiff.json_files.requested', (event) => {
event.eventBus.fire('spiff.json_files.returned', {
bpmnModeler.on('spiff.json_schema_files.requested', (event) => {
event.eventBus.fire('spiff.json_schema_files.returned', {
options: [
{ label: 'pizza_form.json', value: 'pizza_form.json' },
{ label: 'credit_card_form.json', value: 'credit_card_form.json' },
@ -79,9 +79,10 @@ describe('Properties Panel for User Tasks', function () {
const entry = findEntry('extension_formJsonSchemaFilename', group);
const selectList = findSelect(entry);
expect(selectList).to.exist;
expect(selectList.options.length).to.equal(4);
expect(selectList.options[0].label).to.equal('pizza_form.json');
expect(selectList.options[1].label).to.equal('credit_card_form.json');
expect(selectList.options.length).to.equal(5); // including the empty option
expect(selectList.options[0].label).to.equal('');
expect(selectList.options[1].label).to.equal('pizza_form.json');
expect(selectList.options[2].label).to.equal('credit_card_form.json');
changeInput(selectList, 'pizza_form.json');
@ -106,9 +107,35 @@ describe('Properties Panel for User Tasks', function () {
const formJsonSchemaFilenameEntry = findEntry('extension_formJsonSchemaFilename', group);
const formJsonSchemaFilenameInput = findSelect(formJsonSchemaFilenameEntry);
expect(formJsonSchemaFilenameInput.value).to.equal('give_me_a_number_form.json');
const formUiSchemaFilenameEntry = findEntry('extension_formUiSchemaFilename', group);
const formUiSchemaFilenameInput = findSelect(formUiSchemaFilenameEntry);
expect(formUiSchemaFilenameInput.value).to.equal('number_form_schema.json');
});
it('should update both the json and ui extensions if the json file is set', async function () {
await preparePropertiesPanelWithXml(diagram_xml)();
const modeler = getBpmnJS();
addOptionsToEventBus(modeler);
const userElement = await expectSelected('task_confirm');
const group = findGroupEntry('user_task_properties', container);
const button = findButton(
'launch_editor_button_formJsonSchemaFilename',
group
);
expect(button).to.exist;
let launchEvent;
let eventBus = modeler.get('eventBus');
eventBus.on('spiff.file.edit', function (event) {
launchEvent = event;
});
await pressButton(button);
expect(launchEvent.value).to.exist;
eventBus.fire('spiff.jsonSchema.update', {
value: 'new-schema.json',
});
const jsonFile = getExtensionValue(userElement, 'formJsonSchemaFilename');
const uiFile = getExtensionValue(userElement, 'formUiSchemaFilename');
expect(jsonFile).to.equal('new-schema.json');
expect(uiFile).to.equal('new-uischema.json');
});
it('should allow you to change the instructions to the end user', async function () {
@ -129,7 +156,7 @@ describe('Properties Panel for User Tasks', function () {
// The change is reflected in the business object
let instructions = getExtensionValue(
userElement,
'spiffworkflow:instructionsForEndUser'
'spiffworkflow:InstructionsForEndUser'
);
expect(instructions).to.equal('#Hello!');
});