Skip to content

Commit

Permalink
feat: add FEEL editor for table cells
Browse files Browse the repository at this point in the history
Closes #774
  • Loading branch information
barmac committed Sep 25, 2023
1 parent 7c78310 commit 9d47d2f
Show file tree
Hide file tree
Showing 9 changed files with 215 additions and 67 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -251,3 +251,18 @@
width: 20px;
right: 0;
}

/* cell editor */
.dmn-decision-table-container .cell-editor__placeholder {
position: absolute;
}

.dmn-decision-table-container .cell-editor:focus-within .cell-editor__placeholder,
.dmn-decision-table-container .cell-editor:focus-within .dmn-expression-language {
display: none;
}

.dmn-decision-table-container .cell-editor,
.dmn-decision-table-container .cell-editor .cm-scroller {
line-height: normal;
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import {
import cssEscape from 'css.escape';

import {
setRange,
getRange
} from 'selection-ranges';

Expand Down Expand Up @@ -109,6 +108,6 @@ export function ensureFocus(el) {
const range = getRange(focusEl);

if (!range || range.end === 0) {
setRange(focusEl, { start: 5000, end: 5000 });
window.getSelection().setPosition(focusEl.firstChild, focusEl.firstChild.length);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ import { isString } from 'min-dash';

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

import EditableComponent from 'dmn-js-shared/lib/components/EditableComponent';
import ContentEditable from 'dmn-js-shared/lib/components/ContentEditable';
import LiteralExpression from 'dmn-js-shared/lib/components/LiteralExpression';

import { Cell } from 'table-js/lib/components';

Expand All @@ -14,22 +15,14 @@ export default class DecisionRulesCellEditorComponent extends Component {
constructor(props, context) {
super(props, context);

this.state = {
isFocussed: false
};

this.changeCellValue = this.changeCellValue.bind(this);
this.onFocus = this.onFocus.bind(this);
this.onBlur = this.onBlur.bind(this);
this.onElementsChanged = this.onElementsChanged.bind(this);
}


onElementsChanged() {
this.forceUpdate();
}


componentWillMount() {
const { injector } = this.context;

Expand All @@ -42,35 +35,18 @@ export default class DecisionRulesCellEditorComponent extends Component {
changeSupport.onElementsChanged(cell.id, this.onElementsChanged);
}


componentWillUnmount() {
const { cell } = this.props;

this._changeSupport.offElementsChanged(cell.id, this.onElementsChanged);
}


changeCellValue(value) {
const { cell } = this.props;

this._modeling.editCell(cell.businessObject, value);
}


onFocus() {
this.setState({
isFocussed: true
});
}


onBlur() {
this.setState({
isFocussed: false
});
}


render() {
const {
cell,
Expand All @@ -80,8 +56,6 @@ export default class DecisionRulesCellEditorComponent extends Component {
colIndex
} = this.props;

const { isFocussed } = this.state;

const isUnaryTest = is(cell, 'dmn:UnaryTests');
const businessObject = cell.businessObject;

Expand All @@ -94,12 +68,7 @@ export default class DecisionRulesCellEditorComponent extends Component {
data-col-id={ col.id }
>
<TableCellEditor
className="cell-editor"
placeholder={ isUnaryTest ? '-' : '' }
ctrlForNewline={ true }
onFocus={ this.onFocus }
onBlur={ this.onBlur }
isFocussed={ isFocussed }
onChange={ this.changeCellValue }
value={ businessObject.text }
businessObject={ businessObject } />
Expand All @@ -108,8 +77,42 @@ export default class DecisionRulesCellEditorComponent extends Component {
}
}

class FeelEditor extends Component {
constructor(props, context) {
super(props, context);
this.state = { focussed: false };

class TableCellEditor extends EditableComponent {
this.onFocus = this.onFocus.bind(this);
this.onBlur = this.onBlur.bind(this);
}

onFocus() {
this.setState({ focussed: true });
}

onBlur() {
this.setState({ focussed: false });
}

render() {
if (this.state.focussed) {
return <LiteralExpression
{ ...this.props }
autoFocus={ true }
onBlur={ this.onBlur }
/>;
}

return <div onClick={ this.onFocus }>
<ContentEditable
{ ...this.props }
onFocus={ this.onFocus }
/>
</div>;
}
}

class TableCellEditor extends Component {

constructor(props, context) {
super(props, context);
Expand Down Expand Up @@ -164,10 +167,27 @@ class TableCellEditor extends EditableComponent {
return this._expressionLanguages.getDefault(elementType);
}

getEditor() {
return this.isFEEL() ? FeelEditor : ContentEditable;
}

isFEEL() {
return this.getExpressionLanguage() === 'feel';
}

getExpressionLanguage() {
const { businessObject } = this.props;

return businessObject.expressionLanguage ||
this.getDefaultExpressionLanguage(businessObject).value;
}

render() {
const {
businessObject,
isFocussed
placeholder,
value,
onChange
} = this.props;

const description = this.getDescription(businessObject);
Expand All @@ -178,21 +198,23 @@ class TableCellEditor extends EditableComponent {

const isScript = this.isScript(businessObject);

const Editor = this.getEditor();

return (
<div className={ this.getClassName() }>
<div className="cell-editor">
{
isString(description)
&& !isFocussed
&& <div className="description-indicator"></div>
}
<Editor
className={ isScript ? 'script-editor' : null }
ctrlForNewline={ true }
onInput={ onChange }
value={ value }
placeholder={ placeholder }
/>
{
this.getEditor({
className: isScript ? 'script-editor' : null
})
}
{
!isDefaultExpressionLanguage &&
!isFocussed && (
!isDefaultExpressionLanguage && (
<span
className="dms-badge dmn-expression-language"
title={ this._translate(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ export default class Keyboard {
this._node = node;

// bind key events
domEvent.bind(node, 'keydown', this._keyHandler, true);
domEvent.bind(node, 'keydown', this._keyHandler);

this._fire('bind');
}
Expand All @@ -118,7 +118,7 @@ export default class Keyboard {
this._fire('unbind');

// unbind key events
domEvent.unbind(node, 'keydown', this._keyHandler, true);
domEvent.unbind(node, 'keydown', this._keyHandler);
}

this._node = null;
Expand Down
14 changes: 14 additions & 0 deletions packages/dmn-js-decision-table/test/helper/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -259,3 +259,17 @@ export function insertCSS(name, css) {

head.appendChild(style);
}

/**
* Execute function and resolve in next frame.
*
* @param {Function} fn
*/
export function act(fn) {
fn();
return new Promise(resolve => {
requestAnimationFrame(() => {
resolve();
});
});
}
Loading

0 comments on commit 9d47d2f

Please sign in to comment.