+
{ this._translate('Expression Language') }
@@ -93,10 +104,66 @@ export default class ExpressionLanguage {
}
});
+
+ components.onGetComponent('context-menu', (context = {}) => {
+ if (
+ context.contextMenuType === 'input-edit'
+ ) {
+ return () => {
+ const { inputExpression } = context.input;
+
+ if (!this._shouldDisplayContextMenuEntry(inputExpression)) {
+ return;
+ }
+
+ const expressionLanguage = this._getElementExpressionLanguage(inputExpression);
+
+ const options = expressionLanguages.getAll();
+
+ return
+
+
+
+ this.onChange(inputExpression, value) }
+ options={ options } />
+
+
;
+ };
+ }
+ });
+ }
+
+ onChange(element, expressionLanguage) {
+ this._modeling.editExpressionLanguage(element, expressionLanguage);
+ }
+
+ _shouldDisplayContextMenuEntry(element) {
+ const expressionLanguages = this._expressionLanguages.getAll();
+
+ if (expressionLanguages.length > 1) {
+ return true;
+ }
+
+ const expressionLanguage = this._getElementExpressionLanguage(element);
+
+ return expressionLanguage !== this._getDefaultElementExpressionLanguage(element);
+ }
+
+ _getElementExpressionLanguage(element) {
+ return getBusinessObject(element).expressionLanguage
+ || this._getDefaultElementExpressionLanguage(element);
}
- onChange(cell, expressionLanguage) {
- this._modeling.editExpressionLanguage(cell.businessObject, expressionLanguage);
+ _getDefaultElementExpressionLanguage(element) {
+ return this._expressionLanguages.getDefault(
+ isInput(element.col) ? 'inputCell' : 'outputCell').value;
}
}
diff --git a/packages/dmn-js-decision-table/test/spec/expression-language.dmn b/packages/dmn-js-decision-table/test/spec/expression-language.dmn
index 990348cee..326867cd1 100644
--- a/packages/dmn-js-decision-table/test/spec/expression-language.dmn
+++ b/packages/dmn-js-decision-table/test/spec/expression-language.dmn
@@ -3,7 +3,7 @@
-
+
status
diff --git a/packages/dmn-js-decision-table/test/spec/features/decision-table-head/editor/input/InputEditorCellSpec.js b/packages/dmn-js-decision-table/test/spec/features/decision-table-head/editor/input/InputEditorCellSpec.js
index cebd415fb..6d0135813 100644
--- a/packages/dmn-js-decision-table/test/spec/features/decision-table-head/editor/input/InputEditorCellSpec.js
+++ b/packages/dmn-js-decision-table/test/spec/features/decision-table-head/editor/input/InputEditorCellSpec.js
@@ -90,17 +90,6 @@ describe('decision-table-head/editor - input', function() {
}));
- it('should display FEEL per default', function() {
-
- // given
- const editorEl = openEditor('input1');
- const inputEl = getControl('.ref-language input', editorEl);
-
- // then
- expect(inputEl).to.have.property('value', 'feel');
- });
-
-
describe('should edit input label', function() {
beforeEach(function() {
diff --git a/packages/dmn-js-decision-table/test/spec/features/decision-table-head/editor/input/InputEditorSpec.js b/packages/dmn-js-decision-table/test/spec/features/decision-table-head/editor/input/InputEditorSpec.js
index d36fb3897..7222a7488 100644
--- a/packages/dmn-js-decision-table/test/spec/features/decision-table-head/editor/input/InputEditorSpec.js
+++ b/packages/dmn-js-decision-table/test/spec/features/decision-table-head/editor/input/InputEditorSpec.js
@@ -57,12 +57,6 @@ class Root extends Component {
this.state = {
text: '',
- expressionLanguage: '',
- expressionLanguages: [],
- defaultExpressionLanguage: {
- value: 'feel',
- label: 'FEEL'
- },
label: null
};
}
diff --git a/packages/dmn-js-decision-table/test/spec/features/expression-language/ExpressionLanguageSpec.js b/packages/dmn-js-decision-table/test/spec/features/expression-language/ExpressionLanguageSpec.js
index f7f0264b6..9b5b39acb 100644
--- a/packages/dmn-js-decision-table/test/spec/features/expression-language/ExpressionLanguageSpec.js
+++ b/packages/dmn-js-decision-table/test/spec/features/expression-language/ExpressionLanguageSpec.js
@@ -1,6 +1,7 @@
import { bootstrapModeler, getDecisionTable, inject } from 'test/helper';
-import { query as domQuery } from 'min-dom';
+import { query as domQuery, queryAll as domQueryAll } from 'min-dom';
+import { find } from 'min-dash';
import TestContainer from 'mocha-test-container-support';
@@ -9,7 +10,7 @@ import {
triggerInputSelectChange
} from 'dmn-js-shared/test/util/EventUtil';
-import simpleXML from '../../simple.dmn';
+import elXML from '../../expression-language.dmn';
import ContextMenuModule from 'src/features/context-menu';
import CoreModule from 'src/core';
@@ -43,36 +44,21 @@ const CUSTOM_EXPRESSION_LANGUAGES = [{
describe('expression language', function() {
- beforeEach(bootstrapModeler(simpleXML, {
- expressionLanguages: {
- options: CUSTOM_EXPRESSION_LANGUAGES
- },
- modules: [
- ContextMenuModule,
- CoreModule,
- ExpressionLanguageModule,
- InteractionEventsModule,
- ModelingModule,
- DecisionRulesEditorModule,
- KeyboardModule
- ],
- debounceInput: false
- }));
-
let testContainer;
beforeEach(function() {
testContainer = TestContainer.get(this);
});
- function openContextMenu(elementId) {
+ function openContextMenu(elementId, type = 'expression-language', ctx = {}) {
getDecisionTable().invoke(function(contextMenu) {
contextMenu.open({
x: 0,
y: 0
}, {
- contextMenuType: 'expression-language',
- id: elementId
+ contextMenuType: type,
+ id: elementId,
+ ...ctx
});
});
@@ -80,37 +66,171 @@ describe('expression language', function() {
}
- it('should edit expression language - input', inject(function(elementRegistry) {
+ describe('basic', function() {
- // given
- const inputSelect = openContextMenu('inputEntry1');
+ beforeEach(bootstrapModeler(elXML, {
+ modules: [
+ ContextMenuModule,
+ CoreModule,
+ ExpressionLanguageModule,
+ InteractionEventsModule,
+ ModelingModule,
+ DecisionRulesEditorModule,
+ KeyboardModule
+ ],
+ debounceInput: false
+ }));
- const input = domQuery('.dms-input', inputSelect);
- // when
- triggerInputEvent(input, 'foo');
+ it('should edit expression language - input', inject(function(elementRegistry) {
- // then
- const expressionLanguage =
- elementRegistry.get('inputEntry1').businessObject.expressionLanguage;
+ // given
+ const inputSelect = openContextMenu('inputEntry1');
+
+ const input = domQuery('.dms-input', inputSelect);
+
+ // when
+ triggerInputEvent(input, 'foo');
+
+ // then
+ const expressionLanguage =
+ elementRegistry.get('inputEntry1').businessObject.expressionLanguage;
+
+ expect(expressionLanguage).to.equal('foo');
+ }));
+
+
+ it('should display context menu entry if cell\'s EL is non-default', function() {
+
+ // when
+ openContextMenu('inputEntry1', 'context-menu');
+
+ // then
+ const entries = domQueryAll('.context-menu-group-entry', testContainer);
+ const entry = find(entries, entry => {
+ return entry.textContent === 'Change Cell Expression Language';
+ });
+
+ expect(entry).to.exist;
+ });
+
+
+ it('should display if the input\'s expression language is non-default',
+ inject(function(elementRegistry) {
+
+ // given
+ const input = elementRegistry.get('input1');
+
+ // when
+ openContextMenu('input1', 'input-edit', { input: input.businessObject });
+
+ // then
+ const entry = domQuery('.ref-language', testContainer);
+
+ expect(entry).to.exist;
+ })
+ );
+
+
+ it('should NOT display if the cell\'s expression language is the only one available',
+ function() {
+
+ // when
+ openContextMenu('inputEntry2', 'context-menu');
+
+ // then
+ const entries = domQueryAll('.context-menu-group-entry', testContainer);
+ const entry = find(entries, entry => {
+ return entry.textContent === 'Change Cell Expression Language';
+ });
- expect(expressionLanguage).to.equal('foo');
- }));
+ expect(entry).not.to.exist;
+ }
+ );
- it('should edit expression language - select', inject(function(elementRegistry) {
+ it('should NOT display if the input\'s expression language is the only one available',
+ inject(function(elementRegistry) {
- // given
- const inputSelect = openContextMenu('inputEntry1');
+ // given
+ const input = elementRegistry.get('input2');
- // when
- triggerInputSelectChange(inputSelect, 'javascript', testContainer);
+ // when
+ openContextMenu('input2', 'input-edit', { input: input.businessObject });
- // then
- const expressionLanguage =
+ // then
+ const entry = domQuery('.ref-language', testContainer);
+
+ expect(entry).not.to.exist;
+ })
+ );
+ });
+
+
+ describe('custom expression languages', function() {
+
+
+ beforeEach(bootstrapModeler(elXML, {
+ expressionLanguages: {
+ options: CUSTOM_EXPRESSION_LANGUAGES
+ },
+ modules: [
+ ContextMenuModule,
+ CoreModule,
+ ExpressionLanguageModule,
+ InteractionEventsModule,
+ ModelingModule,
+ DecisionRulesEditorModule,
+ KeyboardModule
+ ],
+ debounceInput: false
+ }));
+
+ it('should edit expression language - select', inject(function(elementRegistry) {
+
+ // given
+ const inputSelect = openContextMenu('inputEntry1');
+
+ // when
+ triggerInputSelectChange(inputSelect, 'javascript', testContainer);
+
+ // then
+ const expressionLanguage =
elementRegistry.get('inputEntry1').businessObject.expressionLanguage;
- expect(expressionLanguage).to.equal('javascript');
- }));
+ expect(expressionLanguage).to.equal('javascript');
+ }));
+
+
+ it('should display context menu entry if multiple ELs are available', function() {
-});
\ No newline at end of file
+ // when
+ openContextMenu('inputEntry2', 'context-menu');
+
+ // then
+ const entries = domQueryAll('.context-menu-group-entry', testContainer);
+ const entry = find(entries, entry => {
+ return entry.textContent === 'Change Cell Expression Language';
+ });
+
+ expect(entry).to.exist;
+ });
+
+
+ it('should display input entry if multiple ELs are available',
+ inject(function(elementRegistry) {
+
+ // given
+ const input = elementRegistry.get('input2');
+
+ // when
+ openContextMenu('input2', 'input-edit', { input: input.businessObject });
+
+ // then
+ const entry = domQuery('.ref-language', testContainer);
+
+ expect(entry).to.exist;
+ })
+ );
+ });
+});
diff --git a/packages/dmn-js-literal-expression/src/features/literal-expression-properties/components/LiteralExpressionPropertiesEditorComponent.js b/packages/dmn-js-literal-expression/src/features/literal-expression-properties/components/LiteralExpressionPropertiesEditorComponent.js
index 4f06351cc..983ebd6e6 100644
--- a/packages/dmn-js-literal-expression/src/features/literal-expression-properties/components/LiteralExpressionPropertiesEditorComponent.js
+++ b/packages/dmn-js-literal-expression/src/features/literal-expression-properties/components/LiteralExpressionPropertiesEditorComponent.js
@@ -30,19 +30,16 @@ export default class LiteralExpressionPropertiesComponent extends Component {
this._viewer = context.injector.get('viewer');
this._modeling = context.injector.get('modeling');
- this._expressionLanguages = context.injector.get('expressionLanguages');
const decision = this._viewer.getDecision();
this.state = {
name: decision.variable.name,
- typeRef: decision.variable.typeRef,
- expressionLanguage: getExpressionLanguage(decision.decisionLogic)
+ typeRef: decision.variable.typeRef
};
this.setVariableName = this.setVariableName.bind(this);
this.setVariableType = this.setVariableType.bind(this);
- this.setExpressionLanguage = this.setExpressionLanguage.bind(this);
}
setVariableName(name) {
@@ -69,26 +66,8 @@ export default class LiteralExpressionPropertiesComponent extends Component {
}
}
- setExpressionLanguage(expressionLanguage) {
- if (expressionLanguage === '') {
- this._modeling.editExpressionLanguage(undefined);
-
- this.setState({
- expressionLanguage: undefined
- });
- } else {
- this._modeling.editExpressionLanguage(expressionLanguage);
-
- this.setState({
- expressionLanguage
- });
- }
- }
-
render() {
- const { expressionLanguage, name, typeRef } = this.state;
-
- const languageOptions = this._expressionLanguages.getAll();
+ const { name, typeRef } = this.state;
return (
@@ -115,29 +94,79 @@ export default class LiteralExpressionPropertiesComponent extends Component {
-
- Expression Language: |
-
-
-
-
- |
-
+
);
}
}
+class ExpressionLanguage extends Component {
+ constructor(props, context) {
+ super(props, context);
-// helpers //////////////////////
+ this._viewer = context.injector.get('viewer');
+ this._modeling = context.injector.get('modeling');
+ this._expressionLanguages = context.injector.get('expressionLanguages');
-function getExpressionLanguage(literalExpression) {
- return (literalExpression && literalExpression.expressionLanguage)
- ? literalExpression.expressionLanguage.toLowerCase()
- : undefined;
-}
\ No newline at end of file
+ this.setExpressionLanguage = this.setExpressionLanguage.bind(this);
+ }
+
+ setExpressionLanguage(expressionLanguage) {
+ if (expressionLanguage === '') {
+ this._modeling.editExpressionLanguage(undefined);
+ } else {
+ this._modeling.editExpressionLanguage(expressionLanguage);
+ }
+ }
+
+ _getExpressionLanguage() {
+ const decision = this._viewer.getDecision();
+ const literalExpression = decision.decisionLogic;
+
+ return (literalExpression && literalExpression.expressionLanguage)
+ ? literalExpression.expressionLanguage.toLowerCase()
+ : this._getDefaultExpressionLanguage();
+ }
+
+ _getDefaultExpressionLanguage() {
+ return this._expressionLanguages.getDefault().value;
+ }
+
+ _shouldRender() {
+ const expressionLanguages = this._expressionLanguages.getAll();
+
+ if (expressionLanguages.length > 1) {
+ return true;
+ }
+
+ const expressionLanguage = this._getExpressionLanguage();
+
+ return expressionLanguage !== this._getDefaultExpressionLanguage();
+ }
+
+ render() {
+ if (!this._shouldRender()) {
+ return null;
+ }
+
+ const expressionLanguage = this._getExpressionLanguage();
+
+ const languageOptions = this._expressionLanguages.getAll();
+
+ return (
+
+ Expression Language: |
+
+
+
+
+ |
+
+ );
+ }
+}
diff --git a/packages/dmn-js-literal-expression/test/spec/expression-language.dmn b/packages/dmn-js-literal-expression/test/spec/expression-language.dmn
new file mode 100644
index 000000000..2e0825515
--- /dev/null
+++ b/packages/dmn-js-literal-expression/test/spec/expression-language.dmn
@@ -0,0 +1,16 @@
+
+
+
+
+
+ calendar.getSeason(date)
+
+
+
+
+
+
+
+
+
+
diff --git a/packages/dmn-js-literal-expression/test/spec/features/literal-expression-properties/LiteralExpressionEditorPropertiesSpec.js b/packages/dmn-js-literal-expression/test/spec/features/literal-expression-properties/LiteralExpressionEditorPropertiesSpec.js
index 75a8559fc..1cd9a1e55 100644
--- a/packages/dmn-js-literal-expression/test/spec/features/literal-expression-properties/LiteralExpressionEditorPropertiesSpec.js
+++ b/packages/dmn-js-literal-expression/test/spec/features/literal-expression-properties/LiteralExpressionEditorPropertiesSpec.js
@@ -14,6 +14,7 @@ import {
import TestContainer from 'mocha-test-container-support';
import literalExpressionXML from '../../literal-expression.dmn';
+import nonDefaultExpressionLanguageXML from '../../expression-language.dmn';
import LiteralExpressionPropertiesEditorModule
from 'src/features/literal-expression-properties/editor';
@@ -45,19 +46,6 @@ const CUSTOM_EXPRESSION_LANGUAGES = [{
describe('literal expression properties editor', function() {
- beforeEach(bootstrapModeler(literalExpressionXML, {
- expressionLanguages: {
- options: CUSTOM_EXPRESSION_LANGUAGES
- },
- modules: [
- CoreModule,
- LiteralExpressionPropertiesEditorModule,
- ExpressionLanguagesModule,
- ModelingModule
- ],
- debounceInput: false
- }));
-
let testContainer;
beforeEach(function() {
@@ -65,116 +53,167 @@ describe('literal expression properties editor', function() {
});
- it('should render', function() {
+ describe('basics', function() {
- // then
- expect(domQuery('.literal-expression-properties', testContainer)).to.exist;
- });
+ beforeEach(bootstrapModeler(literalExpressionXML, {
+ modules: [
+ CoreModule,
+ LiteralExpressionPropertiesEditorModule,
+ ExpressionLanguagesModule,
+ ModelingModule
+ ],
+ debounceInput: false
+ }));
+
+ it('should render', function() {
+
+ // then
+ expect(domQuery('.literal-expression-properties', testContainer)).to.exist;
+ });
- it('should edit variable name', inject(function(viewer) {
+ it('should edit variable name', inject(function(viewer) {
- // given
- const input = domQuery('.variable-name-input', testContainer);
+ // given
+ const input = domQuery('.variable-name-input', testContainer);
- // when
- triggerInputEvent(input, 'foo');
+ // when
+ triggerInputEvent(input, 'foo');
- // then
- expect(viewer.getDecision().variable.name).to.equal('foo');
- }));
+ // then
+ expect(viewer.getDecision().variable.name).to.equal('foo');
+ }));
- it('should edit variable type - input', inject(function(viewer) {
+ it('should edit variable type - input', inject(function(viewer) {
- // given
- const inputSelect = domQuery('.variable-type-select', testContainer);
+ // given
+ const inputSelect = domQuery('.variable-type-select', testContainer);
- const input = domQuery('.dms-input', inputSelect);
+ const input = domQuery('.dms-input', inputSelect);
- // when
- triggerInputEvent(input, 'foo');
+ // when
+ triggerInputEvent(input, 'foo');
- // then
- expect(viewer.getDecision().variable.typeRef).to.equal('foo');
- }));
+ // then
+ expect(viewer.getDecision().variable.typeRef).to.equal('foo');
+ }));
- it('should edit variable type - select', inject(function(viewer) {
+ it('should edit variable type - select', inject(function(viewer) {
- // given
- const inputSelect = domQuery('.variable-type-select', testContainer);
+ // given
+ const inputSelect = domQuery('.variable-type-select', testContainer);
- // when
- triggerInputSelectChange(inputSelect, 'boolean', testContainer);
+ // when
+ triggerInputSelectChange(inputSelect, 'boolean', testContainer);
- // then
- expect(viewer.getDecision().variable.typeRef).to.equal('boolean');
- }));
+ // then
+ expect(viewer.getDecision().variable.typeRef).to.equal('boolean');
+ }));
- it('should remove variable type', inject(function(viewer) {
+ it('should remove variable type', inject(function(viewer) {
- // given
- const inputSelect = domQuery('.variable-type-select', testContainer);
+ // given
+ const inputSelect = domQuery('.variable-type-select', testContainer);
- triggerInputSelectChange(inputSelect, 'boolean', testContainer);
+ triggerInputSelectChange(inputSelect, 'boolean', testContainer);
- const input = domQuery('.dms-input', inputSelect);
+ const input = domQuery('.dms-input', inputSelect);
- // when
- triggerInputEvent(input, '');
+ // when
+ triggerInputEvent(input, '');
- // then
- expect(viewer.getDecision().variable.typeRef).to.not.exist;
- }));
+ // then
+ expect(viewer.getDecision().variable.typeRef).to.not.exist;
+ }));
- it('should edit expression language - input', inject(function(viewer) {
+ it('should NOT display expression language if decision\'s EL is default', function() {
- // given
- const inputSelect = domQuery('.expression-language-select', testContainer);
+ // given
+ const inputSelect = domQuery('.expression-language-select', testContainer);
+
+ // then
+ expect(inputSelect).not.to.exist;
+ });
+ });
- const input = domQuery('.dms-input', inputSelect);
- // when
- triggerInputEvent(input, 'foo');
+ describe('non-default expression language', function() {
- // then
- expect(viewer.getDecision().decisionLogic.expressionLanguage)
- .to.equal('foo');
- }));
+ beforeEach(bootstrapModeler(nonDefaultExpressionLanguageXML, {
+ modules: [
+ CoreModule,
+ LiteralExpressionPropertiesEditorModule,
+ ExpressionLanguagesModule,
+ ModelingModule
+ ],
+ debounceInput: false
+ }));
- it('should edit expression language - select', inject(function(viewer) {
+ it('should edit expression language - input', inject(function(viewer) {
- // given
- const inputSelect = domQuery('.expression-language-select', testContainer);
+ // given
+ const inputSelect = domQuery('.expression-language-select', testContainer);
- // when
- triggerInputSelectChange(inputSelect, 'javascript', testContainer);
+ const input = domQuery('.dms-input', inputSelect);
- // then
- expect(viewer.getDecision().decisionLogic.expressionLanguage)
- .to.equal('javascript');
- }));
+ // when
+ triggerInputEvent(input, 'foo');
+
+ // then
+ expect(viewer.getDecision().decisionLogic.expressionLanguage)
+ .to.equal('foo');
+ }));
+ });
- it('should remove expression language', inject(function(viewer) {
+ describe('custom expression languages', function() {
- // given
- const inputSelect = domQuery('.expression-language-select', testContainer);
+ beforeEach(bootstrapModeler(literalExpressionXML, {
+ expressionLanguages: {
+ options: CUSTOM_EXPRESSION_LANGUAGES
+ },
+ modules: [
+ CoreModule,
+ LiteralExpressionPropertiesEditorModule,
+ ExpressionLanguagesModule,
+ ModelingModule
+ ],
+ debounceInput: false
+ }));
- triggerInputSelectChange(inputSelect, 'python', testContainer);
- const input = domQuery('.dms-input', inputSelect);
+ it('should edit expression language - select', inject(function(viewer) {
- // when
- triggerInputEvent(input, '');
+ // given
+ const inputSelect = domQuery('.expression-language-select', testContainer);
- // then
- expect(viewer.getDecision().decisionLogic.expressionLanguage)
- .to.not.exist;
- }));
+ // when
+ triggerInputSelectChange(inputSelect, 'javascript', testContainer);
+
+ // then
+ expect(viewer.getDecision().decisionLogic.expressionLanguage)
+ .to.equal('javascript');
+ }));
+
+
+ it('should remove expression language', inject(function(viewer) {
+
+ // given
+ const inputSelect = domQuery('.expression-language-select', testContainer);
+ const input = domQuery('.dms-input', inputSelect);
+
+ // when
+ triggerInputEvent(input, '');
+
+ // then
+ expect(viewer.getDecision().decisionLogic.expressionLanguage)
+ .to.not.exist;
+ }));
+ });
});
\ No newline at end of file
diff --git a/packages/dmn-js-literal-expression/test/spec/literal-expression.dmn b/packages/dmn-js-literal-expression/test/spec/literal-expression.dmn
index 2e0825515..9d5b7410b 100644
--- a/packages/dmn-js-literal-expression/test/spec/literal-expression.dmn
+++ b/packages/dmn-js-literal-expression/test/spec/literal-expression.dmn
@@ -2,7 +2,7 @@
-
+
calendar.getSeason(date)