DMN selection should be from a dropdown, not by hand entering a process id.

This commit is contained in:
Dan 2022-11-01 14:41:21 -04:00
parent ecb175d727
commit aeeaf1596e
6 changed files with 152 additions and 85 deletions

View File

@ -3,7 +3,7 @@ import {
BpmnPropertiesPanelModule,
BpmnPropertiesProviderModule,
} from 'bpmn-js-properties-panel';
import diagramXML from '../test/spec/bpmn/user_form.bpmn';
import diagramXML from '../test/spec/bpmn/diagram.bpmn';
import spiffworkflow from './spiffworkflow';
import setupFileOperations from './fileOperations';
@ -139,14 +139,20 @@ bpmnModeler.on('callactivity.editor.launch', (newEvent) => {
});
/**
* Also can be good to launch an editor for a call activity.
* Also can be good to launch an editor for a call activity, or DMN
* Not implemented here but imagine opening up a new browser tab
* and showing a different process.
*/
bpmnModeler.on('file.editor.launch', (newEvent) => {
console.log(
'Open new window to edit file: ',
newEvent.fileName
newEvent.value
);
});
bpmnModeler.on('dmn.editor.launch', (newEvent) => {
console.log(
'Open new window to edit DMN table: ',
newEvent.value
);
});
@ -171,6 +177,7 @@ bpmnModeler.on('spiff.options.requested', (event) => {
options: [
{ label: 'Pizza Special Prices', value: 'pizza_prices' },
{ label: 'Topping Prices', value: 'topping_prices' },
{ label: 'Test Decision', value: 'test_decision' },
],
});
}

View File

@ -1,7 +1,6 @@
import { ListGroup } from '@bpmn-io/properties-panel';
import { is, isAny } from 'bpmn-js/lib/util/ModelUtil';
import scriptGroup, { SCRIPT_TYPE } from './SpiffScriptGroup';
import { SpiffExtensionCalledDecision } from './SpiffExtensionCalledDecision';
import { SpiffExtensionTextInput } from './SpiffExtensionTextInput';
import instructionsGroup from './SpiffExtensionInstructionsForEndUser';
import {
@ -9,7 +8,8 @@ import {
ServiceTaskOperatorSelect, ServiceTaskResultTextInput,
} from './SpiffExtensionServiceProperties';
import {OPTION_TYPE, SpiffExtensionSelect} from './SpiffExtensionSelect';
import {SpiffExtensionLaunchFileEditor} from './SpiffExtensionLaunchFileEditor';
import {SpiffExtensionLaunchButton} from './SpiffExtensionLaunchButton';
import {SiffExtensionCalledDecision} from './SpiffExtensionCalledDecision';
const LOW_PRIORITY = 500;
@ -149,10 +149,11 @@ function createUserGroup(element, translate, moddle, commandStack) {
name: 'formJsonSchemaFilename',
},
{
component: SpiffExtensionLaunchFileEditor,
component: SpiffExtensionLaunchButton,
element,
name: 'formJsonSchemaFilename',
label: translate('Launch Editor'),
event: 'file.editor.launch',
description: translate('Edit the form description'),
},
{
@ -162,14 +163,16 @@ function createUserGroup(element, translate, moddle, commandStack) {
component: SpiffExtensionSelect,
optionType: OPTION_TYPE.json,
label: translate('UI Schema Filename'),
event: 'file.editor.launch',
description: translate('Rules for displaying the form. (RSJF Schema)'),
name: 'formUiSchemaFilename',
},
{
component: SpiffExtensionLaunchFileEditor,
component: SpiffExtensionLaunchButton,
element,
name: 'formUiSchemaFilename',
label: translate('Launch Editor'),
event: 'file.editor.launch',
description: translate('Edit the form schema'),
},
],
@ -192,9 +195,21 @@ function createBusinessRuleGroup(element, translate, moddle, commandStack) {
element,
moddle,
commandStack,
component: SpiffExtensionCalledDecision,
label: translate('Decision Id'),
description: translate('Id of the decision'),
name: 'calledDecisionId',
optionType: OPTION_TYPE.dmn,
component: SiffExtensionCalledDecision,
label: translate('Select Decision Table'),
description: translate(
'Select an existing decision table from the list'
),
},
{
component: SpiffExtensionLaunchButton,
element,
name: 'calledDecisionId',
label: translate('Launch Editor'),
event: 'dmn.editor.launch',
description: translate('Modify the Decision Table'),
},
],
};

View File

@ -1,30 +1,30 @@
import { useService } from 'bpmn-js-properties-panel';
import { TextFieldEntry } from '@bpmn-io/properties-panel';
import { SelectEntry } from '@bpmn-io/properties-panel';
const SPIFF_PROP = 'spiffworkflow:calledDecisionId';
let DMN_OPTIONS = [];
/**
* A generic properties' editor for text input.
* Allows you to provide additional SpiffWorkflow extension properties. Just
* uses whatever name is provide on the property, and adds or updates it as
* needed.
*
*
<bpmn:businessRuleTask id="Activity_0t218za">
<bpmn:extensionElements>
<spiffworkflow:calledDecisionId>my_id</spiffworkflow:calledDecisionId>
</bpmn:extensionElements>
</bpmn:businessRuleTask>
*
* @returns {string|null|*}
* Allow selecting a DMN Table from a list of known tables provided through the Event bux.
<bpmn:businessRuleTask id="Activity_0t218za">
<bpmn:extensionElements>
<spiffworkflow:calledDecisionId>my_id</spiffworkflow:calledDecisionId>
</bpmn:extensionElements>
</bpmn:businessRuleTask>
*/
export function SpiffExtensionCalledDecision(props) {
export function SiffExtensionCalledDecision(props) {
const { element } = props;
const { commandStack } = props;
const { moddle } = props;
const { label } = props;
const { description } = props;
const { label, description } = props;
const { name } = props;
const { optionType } = props;
const debounce = useService('debounceInput');
const eventBus = useService('eventBus');
const getPropertyObject = () => {
const bizObj = element.businessObject;
@ -67,15 +67,41 @@ export function SpiffExtensionCalledDecision(props) {
});
};
return (
<TextFieldEntry
id="extension_called_decision"
element={element}
description={description}
label={label}
getValue={getValue}
setValue={setValue}
debounce={debounce}
/>
);
if (DMN_OPTIONS.length === 0) {
requestDmnOptions(eventBus, element, commandStack, optionType);
}
const getOptions = () => {
const optionList = [];
DMN_OPTIONS.forEach((opt) => {
optionList.push({
label: opt.label,
value: opt.value,
});
});
return optionList;
};
return SelectEntry({
id: `extension_${name}`,
element,
label,
description,
getValue,
setValue,
getOptions,
debounce,
});
}
function requestDmnOptions(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.options.returned.dmn`, (event) => {
DMN_OPTIONS = event.options;
commandStack.execute('element.updateProperties', {
element,
properties: {},
});
});
eventBus.fire('spiff.options.requested', { eventBus, optionType });
}

View File

@ -7,15 +7,15 @@ import { getExtensionValue } from '../extensionHelpers';
* would like to edit an external file. Hosting application
* would need to handle saving the file.
*/
export function SpiffExtensionLaunchFileEditor(props) {
const { element, name } = props;
export function SpiffExtensionLaunchButton(props) {
const { element, name, event } = props;
const eventBus = useService('eventBus');
return HeaderButton({
className: 'spiffworkflow-properties-panel-button',
onClick: () => {
const fileName = getExtensionValue(element, name);
eventBus.fire('file.editor.launch', {
fileName,
const value = getExtensionValue(element, name);
eventBus.fire(event, {
value,
});
},
children: 'Launch Editor',

View File

@ -54,8 +54,6 @@ export function SpiffExtensionSelect(props) {
) {
spiffExtensionOptions[optionType] = [];
requestOptions(eventBus, element, commandStack, optionType);
} else {
console.log("Getting here.", spiffExtensionOptions)
}
const getOptions = () => {
const optionList = [];
@ -85,7 +83,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.options.returned.json', (event) => {
eventBus.once(`spiff.options.returned.${optionType}`, (event) => {
spiffExtensionOptions[optionType] = event.options;
commandStack.execute('element.updateProperties', {
element,

View File

@ -1,70 +1,91 @@
import { query as domQuery } from 'min-dom';
import { getBpmnJS } from 'bpmn-js/test/helper';
import {
bootstrapPropertiesPanel, changeInput,
BpmnPropertiesPanelModule,
BpmnPropertiesProviderModule,
} from 'bpmn-js-properties-panel';
import { getBusinessObject } from 'bpmn-js/lib/util/ModelUtil';
import spiffModdleExtension from '../../app/spiffworkflow/moddle/spiffworkflow.json';
import {
bootstrapPropertiesPanel,
changeInput,
expectSelected,
findEntry,
getPropertiesPanel
findSelect,
getPropertiesPanel,
} from './helpers';
import {
query as domQuery,
} from 'min-dom';
import spiffModdleExtension from '../../app/spiffworkflow/moddle/spiffworkflow.json';
import { BpmnPropertiesPanelModule, BpmnPropertiesProviderModule } from 'bpmn-js-properties-panel';
import { getBusinessObject } from 'bpmn-js/lib/util/ModelUtil';
import extensions from '../../app/spiffworkflow/extensions';
describe('Business Rule Properties Panel', function() {
describe('Business Rule Properties Panel', function () {
const xml = require('./bpmn/diagram.bpmn').default;
beforeEach(bootstrapPropertiesPanel(xml, {
debounceInput: false,
additionalModules: [
extensions,
BpmnPropertiesPanelModule,
BpmnPropertiesProviderModule,
],
moddleExtensions: {
spiffworkflow: spiffModdleExtension
},
}));
beforeEach(
bootstrapPropertiesPanel(xml, {
debounceInput: false,
additionalModules: [
extensions,
BpmnPropertiesPanelModule,
BpmnPropertiesProviderModule,
],
moddleExtensions: {
spiffworkflow: spiffModdleExtension,
},
})
);
it('should display a text box to select the called decision id', async function() {
function addOptionsToEventBus(bpmnModeler) {
bpmnModeler.on('spiff.options.requested', (event) => {
if (event.optionType === 'dmn') {
event.eventBus.fire('spiff.options.returned.dmn', {
options: [
{ label: 'Calculate Pizza Price', value: 'Decision_Pizza_Price' },
{ label: 'Viking Availability', value: 'Decision_Vikings' },
{ label: 'Test Decision', value: 'test_decision' },
],
});
}
});
}
it('should display a dropdown to select from available decision tables', async function () {
const modeler = getBpmnJS();
addOptionsToEventBus(modeler);
expectSelected('business_rule_task');
// THEN - a properties panel exists with a section for editing that script
let entry = findEntry('extension_called_decision', getPropertiesPanel());
const entry = findEntry('extension_calledDecisionId', getPropertiesPanel());
expect(entry).to.exist;
const textInput = domQuery('input', entry);
expect(textInput).to.exist;
const selectList = findSelect(entry);
expect(selectList).to.exist;
});
it('should update the spiffworkflow:calledDecisionId tag when you modify the called decision text input', async function() {
it('should update the spiffworkflow:calledDecisionId tag when you modify the called decision select box', async function () {
// IF - a script tag is selected, and you change the script in the properties panel
const modeler = getBpmnJS();
addOptionsToEventBus(modeler);
const businessRuleTask = await expectSelected('business_rule_task');
const entry = findEntry('extension_called_decision', getPropertiesPanel());
const textInput = domQuery('input', entry);
changeInput(textInput, 'wonderful');
const entry = findEntry('extension_calledDecisionId', getPropertiesPanel());
const selectList = findSelect(entry);
changeInput(selectList, 'Decision_Pizza_Price');
// THEN - the script tag in the BPMN Business object / XML is updated as well.
const businessObject = getBusinessObject(businessRuleTask);
expect(businessObject.extensionElements).to.exist;
let element = businessObject.extensionElements.values[0];
expect(element.calledDecisionId).to.equal('wonderful');
const element = businessObject.extensionElements.values[0];
expect(element.calledDecisionId).to.equal('Decision_Pizza_Price');
});
it('should load up the xml and the value for the called decision should match the xml', async 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');
let entry = findEntry('extension_called_decision', getPropertiesPanel());
const textInput = domQuery('input', entry);
expect(textInput.value).to.equal('test_decision');
const entry = findEntry('extension_calledDecisionId', getPropertiesPanel());
const selectList = findSelect(entry);
expect(selectList.value).to.equal('test_decision');
// THEN - the script tag in the BPMN Business object / XML is updated as well.
let businessObject = getBusinessObject(businessRuleTask);
const businessObject = getBusinessObject(businessRuleTask);
expect(businessObject.extensionElements).to.exist;
let element = businessObject.extensionElements.values[0];
const element = businessObject.extensionElements.values[0];
expect(element.calledDecisionId).to.equal('test_decision');
});
});