@elyra/canvas 12.41.0 → 12.42.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{_baseIteratee-05ccf6a8.js → _baseIteratee-148093b7.js} +3 -3
- package/dist/{_baseIteratee-05ccf6a8.js.map → _baseIteratee-148093b7.js.map} +1 -1
- package/dist/{canvas-constants-079172c0.js → canvas-constants-13b58448.js} +2 -2
- package/dist/{canvas-constants-079172c0.js.map → canvas-constants-13b58448.js.map} +1 -1
- package/dist/canvas-controller-a53943e4.js +2 -0
- package/dist/canvas-controller-a53943e4.js.map +1 -0
- package/dist/canvas-controller-cb1d7420.js +2 -0
- package/dist/canvas-controller-cb1d7420.js.map +1 -0
- package/dist/common-canvas-42027a3f.js +2 -0
- package/dist/common-canvas-42027a3f.js.map +1 -0
- package/dist/common-canvas-f758ff42.js +2 -0
- package/dist/common-canvas-f758ff42.js.map +1 -0
- package/dist/common-canvas.es.js +1 -1
- package/dist/common-canvas.es.js.map +1 -1
- package/dist/common-canvas.js +1 -1
- package/dist/common-canvas.js.map +1 -1
- package/dist/common-properties-2e1b7ec7.js +2 -0
- package/dist/common-properties-2e1b7ec7.js.map +1 -0
- package/dist/common-properties-5e8870e3.js +2 -0
- package/dist/common-properties-5e8870e3.js.map +1 -0
- package/dist/context-menu-wrapper-49f9a1af.js +2 -0
- package/dist/context-menu-wrapper-49f9a1af.js.map +1 -0
- package/dist/context-menu-wrapper-5d6a399f.js +2 -0
- package/dist/context-menu-wrapper-5d6a399f.js.map +1 -0
- package/dist/{datarecord-metadata-v3-schema-59505bc5.js → datarecord-metadata-v3-schema-98ec66e9.js} +2 -2
- package/dist/{datarecord-metadata-v3-schema-59505bc5.js.map → datarecord-metadata-v3-schema-98ec66e9.js.map} +1 -1
- package/dist/{flexible-table-43e2d052.js → flexible-table-35e9922a.js} +2 -2
- package/dist/{flexible-table-43e2d052.js.map → flexible-table-35e9922a.js.map} +1 -1
- package/dist/{flexible-table-63ffd573.js → flexible-table-7c7de0f9.js} +1 -1
- package/dist/{flexible-table-63ffd573.js.map → flexible-table-7c7de0f9.js.map} +1 -1
- package/dist/{icon-0390f1fe.js → icon-9edff40c.js} +2 -2
- package/dist/{icon-0390f1fe.js.map → icon-9edff40c.js.map} +1 -1
- package/dist/{index-57503b50.js → index-94fec521.js} +2 -2
- package/dist/{index-57503b50.js.map → index-94fec521.js.map} +1 -1
- package/dist/{index-1cd54914.js → index-e2f8a935.js} +2 -2
- package/dist/{index-1cd54914.js.map → index-e2f8a935.js.map} +1 -1
- package/dist/{isArrayLikeObject-36898fcb.js → isArrayLikeObject-7a30aa4b.js} +2 -2
- package/dist/{isArrayLikeObject-36898fcb.js.map → isArrayLikeObject-7a30aa4b.js.map} +1 -1
- package/dist/lib/canvas-controller.es.js +1 -1
- package/dist/lib/canvas-controller.js +1 -1
- package/dist/lib/canvas.es.js +1 -1
- package/dist/lib/canvas.js +1 -1
- package/dist/lib/context-menu.es.js +1 -1
- package/dist/lib/context-menu.js +1 -1
- package/dist/lib/properties/field-picker.es.js +1 -1
- package/dist/lib/properties/field-picker.js +1 -1
- package/dist/lib/properties/flexible-table.es.js +1 -1
- package/dist/lib/properties/flexible-table.js +1 -1
- package/dist/lib/properties.es.js +1 -1
- package/dist/lib/properties.js +1 -1
- package/dist/lib/tooltip.es.js +1 -1
- package/dist/lib/tooltip.es.js.map +1 -1
- package/dist/lib/tooltip.js +1 -1
- package/dist/lib/tooltip.js.map +1 -1
- package/dist/styles/common-canvas.min.css +1 -1
- package/dist/styles/common-canvas.min.css.map +1 -1
- package/dist/toolbar-6acda0a2.js +2 -0
- package/dist/toolbar-6acda0a2.js.map +1 -0
- package/dist/toolbar-d5647da2.js +2 -0
- package/dist/toolbar-d5647da2.js.map +1 -0
- package/package.json +12 -4
- package/src/color-picker/color-picker.jsx +92 -17
- package/src/command-actions/arrangeLayoutAction.js +7 -6
- package/src/command-actions/attachNodeToLinksAction.js +4 -4
- package/src/command-actions/collapseSuperNodeInPlaceAction.js +5 -5
- package/src/command-actions/colorSelectedObjectsAction.js +4 -4
- package/src/command-actions/commonPropertiesAction.js +1 -1
- package/src/command-actions/convertSuperNodeExternalToLocalAction.js +4 -4
- package/src/command-actions/convertSuperNodeLocalToExternalAction.js +4 -4
- package/src/command-actions/createAutoNodeAction.js +14 -5
- package/src/command-actions/createCommentAction.js +4 -10
- package/src/command-actions/createCommentLinkAction.js +4 -4
- package/src/command-actions/createNodeAction.js +13 -4
- package/src/command-actions/createNodeAttachLinksAction.js +4 -4
- package/src/command-actions/createNodeLinkAction.js +13 -4
- package/src/command-actions/createNodeLinkDetachedAction.js +4 -4
- package/src/command-actions/createNodeOnLinkAction.js +4 -4
- package/src/command-actions/createSuperNodeAction.js +7 -7
- package/src/command-actions/deconstructSuperNodeAction.js +5 -5
- package/src/command-actions/deleteLinkAction.js +4 -4
- package/src/command-actions/deleteObjectsAction.js +15 -6
- package/src/command-actions/disconnectObjectsAction.js +13 -4
- package/src/command-actions/displayPreviousPipelineAction.js +4 -4
- package/src/command-actions/displaySubPipelineAction.js +4 -4
- package/src/command-actions/editCommentAction.js +4 -4
- package/src/command-actions/editDecorationLabelAction.js +4 -4
- package/src/command-actions/expandSuperNodeInPlaceAction.js +5 -5
- package/src/command-actions/insertNodeIntoLinkAction.js +4 -4
- package/src/command-actions/moveObjectsAction.js +4 -4
- package/src/command-actions/pasteAction.js +16 -7
- package/src/command-actions/saveToPaletteAction.js +4 -4
- package/src/command-actions/setLinksStyleAction.js +4 -4
- package/src/command-actions/setNodeLabelAction.js +4 -4
- package/src/command-actions/setObjectsStyleAction.js +4 -4
- package/src/command-actions/sizeAndPositionObjectsAction.js +4 -4
- package/src/command-actions/updateLinkAction.js +4 -4
- package/src/common-canvas/canvas-controller-menu-utils.js +1 -1
- package/src/common-canvas/canvas-controller.js +78 -62
- package/src/common-canvas/cc-central-items.jsx +1 -1
- package/src/common-canvas/cc-context-toolbar.jsx +9 -13
- package/src/common-canvas/cc-toolbar.jsx +2 -0
- package/src/common-canvas/svg-canvas-renderer.js +6 -2
- package/src/common-canvas/svg-canvas-utils-drag-det-link.js +8 -1
- package/src/common-canvas/svg-canvas-utils-drag-new-link.js +1 -1
- package/src/common-properties/components/table-buttons/table-buttons.scss +0 -1
- package/src/common-properties/controls/expression/expression-builder/expression-builder.jsx +32 -26
- package/src/common-properties/controls/expression/expression.jsx +146 -117
- package/src/common-properties/controls/expression/expression.scss +43 -45
- package/src/common-properties/controls/expression/languages/CLEM-hint.js +86 -159
- package/src/common-properties/controls/expression/languages/python-hint.js +53 -104
- package/src/common-properties/controls/expression/languages/r-hint.js +55 -130
- package/src/common-properties/properties-controller.js +5 -0
- package/src/context-menu/common-context-menu.jsx +4 -1
- package/src/index.js +12 -2
- package/src/object-model/redux/canvas-store.js +4 -3
- package/src/toolbar/toolbar-action-item.jsx +90 -314
- package/src/toolbar/toolbar-button-item.jsx +354 -0
- package/src/toolbar/toolbar-divider-item.jsx +3 -4
- package/src/toolbar/toolbar-overflow-item.jsx +82 -36
- package/src/toolbar/toolbar-sub-menu-item.jsx +235 -0
- package/src/toolbar/toolbar-sub-menu.jsx +254 -0
- package/src/toolbar/toolbar-sub-panel.jsx +81 -0
- package/src/toolbar/toolbar-sub-utils.js +77 -0
- package/src/toolbar/toolbar.jsx +330 -146
- package/src/toolbar/toolbar.scss +22 -15
- package/src/tooltip/tooltip.jsx +9 -2
- package/stats.html +1 -1
- package/dist/canvas-controller-1e71b405.js +0 -2
- package/dist/canvas-controller-1e71b405.js.map +0 -1
- package/dist/canvas-controller-4bed5320.js +0 -2
- package/dist/canvas-controller-4bed5320.js.map +0 -1
- package/dist/common-canvas-097c5169.js +0 -2
- package/dist/common-canvas-097c5169.js.map +0 -1
- package/dist/common-canvas-e13c0858.js +0 -2
- package/dist/common-canvas-e13c0858.js.map +0 -1
- package/dist/common-properties-706cef87.js +0 -2
- package/dist/common-properties-706cef87.js.map +0 -1
- package/dist/common-properties-9bd69b61.js +0 -2
- package/dist/common-properties-9bd69b61.js.map +0 -1
- package/dist/context-menu-wrapper-3a7fdec8.js +0 -2
- package/dist/context-menu-wrapper-3a7fdec8.js.map +0 -1
- package/dist/context-menu-wrapper-fc85d853.js +0 -2
- package/dist/context-menu-wrapper-fc85d853.js.map +0 -1
- package/dist/toolbar-918ab52e.js +0 -2
- package/dist/toolbar-918ab52e.js.map +0 -1
- package/dist/toolbar-fdb750f9.js +0 -2
- package/dist/toolbar-fdb750f9.js.map +0 -1
- package/src/toolbar/toolbar-action-sub-area.jsx +0 -126
- package/src/toolbar/toolbar-overflow-menu.jsx +0 -77
- package/src/toolbar/toolbar-utils.js +0 -33
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*
|
|
2
|
-
* Copyright 2017-
|
|
2
|
+
* Copyright 2017-2024 Elyra Authors
|
|
3
3
|
*
|
|
4
4
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
5
|
* you may not use this file except in compliance with the License.
|
|
@@ -31,36 +31,40 @@ export default class ExpressionBuilder extends React.Component {
|
|
|
31
31
|
this.onChange = this.onChange.bind(this);
|
|
32
32
|
this.onBlur = this.onBlur.bind(this);
|
|
33
33
|
this.onSelectionChange = this.onSelectionChange.bind(this);
|
|
34
|
-
this.
|
|
35
|
-
|
|
34
|
+
this.getCodemirrorState = this.getCodemirrorState.bind(this);
|
|
36
35
|
}
|
|
37
36
|
|
|
38
37
|
onChange(newValue) {
|
|
39
38
|
const value = (typeof newValue === "string") ? newValue : newValue.toString();
|
|
40
|
-
|
|
39
|
+
const somethingSelected = this.getCodemirrorState()?.selection.ranges.some((r) => !r.empty);
|
|
40
|
+
let cursor = this.getCodemirrorState()?.selection.main.head;
|
|
41
|
+
if (cursor === 0 && !somethingSelected) { // TODO: Doesn't work when I explicitly set the cursor to 0
|
|
42
|
+
// When nothing selected, set cursor at the end of the line
|
|
43
|
+
this.editor.dispatch({ selection: { anchor: this.getCodemirrorState()?.doc.length } });
|
|
44
|
+
cursor = this.getCodemirrorState()?.selection.main.head;
|
|
45
|
+
this.editor.focus();
|
|
46
|
+
}
|
|
41
47
|
let selectionOffset = 1;
|
|
42
|
-
if (
|
|
48
|
+
if (somethingSelected) {
|
|
43
49
|
selectionOffset = 0;
|
|
44
|
-
this.editor.replaceSelection(value);
|
|
50
|
+
this.editor.dispatch(this.getCodemirrorState()?.replaceSelection(value), { scrollIntoView: true });
|
|
51
|
+
this.editor.focus();
|
|
45
52
|
} else {
|
|
46
53
|
let buffer = " ";
|
|
47
|
-
if (this.lastCursorPos) {
|
|
48
|
-
this.editor.setCursor(this.lastCursorPos);
|
|
49
|
-
cursor = this.lastCursorPos;
|
|
50
|
-
}
|
|
51
54
|
// if adding to a parenth/bracket/brace expression, no need for space
|
|
52
|
-
const
|
|
55
|
+
const currentLineNumber = this.getCodemirrorState()?.doc.lineAt(this.getCodemirrorState()?.selection.main.head).number;
|
|
56
|
+
const charBefore = this.getCodemirrorState()?.doc.line(currentLineNumber).text[cursor - 1];
|
|
53
57
|
// edge case of cursor being at line 0, char 0 is still handled here
|
|
54
58
|
if (["(", "[", "{"].indexOf(charBefore) !== -1) {
|
|
55
59
|
buffer = "";
|
|
56
60
|
}
|
|
57
|
-
this.editor.replaceSelection(buffer + value);
|
|
61
|
+
this.editor.dispatch(this.getCodemirrorState()?.replaceSelection(buffer + value), { scrollIntoView: true });
|
|
62
|
+
this.editor.focus();
|
|
58
63
|
}
|
|
59
64
|
this._setSelection(value, cursor, selectionOffset);
|
|
60
65
|
// This is needed to generate a render so that the selection will appear.
|
|
61
|
-
const exprValue = this.
|
|
66
|
+
const exprValue = this.getCodemirrorState()?.doc.toString();
|
|
62
67
|
this.props.controller.updatePropertyValue(this.props.propertyId, exprValue, true);
|
|
63
|
-
this.lastCursorPos = this.editor.getCursor();
|
|
64
68
|
}
|
|
65
69
|
|
|
66
70
|
onSelectionChange(selection) {
|
|
@@ -68,9 +72,8 @@ export default class ExpressionBuilder extends React.Component {
|
|
|
68
72
|
}
|
|
69
73
|
|
|
70
74
|
onBlur(editor, evt) {
|
|
71
|
-
this.lastCursorPos = editor.getCursor();
|
|
72
75
|
const currentValue = this.props.controller.getPropertyValue(this.props.propertyId);
|
|
73
|
-
const newValue =
|
|
76
|
+
const newValue = editor?.viewState?.state?.doc.toString();
|
|
74
77
|
const skipValidate = this.expressionSelectionPanel && evt && this.expressionSelectionPanel.contains(evt.relatedTarget);
|
|
75
78
|
// update property value when value is updated OR value is to be validated
|
|
76
79
|
if (!isEqual(currentValue, newValue) || !skipValidate) {
|
|
@@ -78,38 +81,41 @@ export default class ExpressionBuilder extends React.Component {
|
|
|
78
81
|
}
|
|
79
82
|
}
|
|
80
83
|
|
|
81
|
-
|
|
82
|
-
this.editor
|
|
84
|
+
getCodemirrorState() {
|
|
85
|
+
return this.editor?.viewState?.state;
|
|
83
86
|
}
|
|
84
87
|
|
|
88
|
+
editorDidMount(editor) {
|
|
89
|
+
this.editor = editor;
|
|
90
|
+
}
|
|
85
91
|
|
|
86
92
|
_setSelection(value, cursor, selectionOffset) {
|
|
87
93
|
// first set the selection to the first param holder of new value
|
|
88
94
|
if (typeof value === "string") {
|
|
89
95
|
const firstParam = value.indexOf("?");
|
|
90
96
|
if (firstParam !== -1) {
|
|
91
|
-
const selection = { anchor:
|
|
92
|
-
|
|
97
|
+
const selection = { anchor: cursor + firstParam + selectionOffset + 1, head: cursor + firstParam + selectionOffset };
|
|
98
|
+
this.editor.dispatch({ selection: selection });
|
|
93
99
|
this.onSelectionChange([selection]);
|
|
94
100
|
return;
|
|
95
101
|
}
|
|
96
102
|
}
|
|
97
103
|
// if the newValue doesn't have a param holder
|
|
98
104
|
// set it to the first param holder found in the expression
|
|
99
|
-
const lineCount = this.
|
|
105
|
+
const lineCount = this.getCodemirrorState()?.doc.lines;
|
|
100
106
|
for (let index = 0; index < lineCount; index++) {
|
|
101
|
-
const line = this.
|
|
107
|
+
const line = this.getCodemirrorState()?.doc.line(index + 1).text;
|
|
102
108
|
const paramOffset = line.indexOf("?");
|
|
103
109
|
if (paramOffset !== -1) {
|
|
104
|
-
const selection = { anchor:
|
|
105
|
-
|
|
110
|
+
const selection = { anchor: paramOffset + 1, head: paramOffset };
|
|
111
|
+
this.editor.dispatch({ selection: selection });
|
|
106
112
|
this.onSelectionChange([selection]);
|
|
107
113
|
return;
|
|
108
114
|
}
|
|
109
115
|
}
|
|
110
116
|
// if no parameter holders found then set it to end of insert string
|
|
111
|
-
const insertSelection = { anchor:
|
|
112
|
-
head:
|
|
117
|
+
const insertSelection = { anchor: this.getCodemirrorState()?.selection.main.anchor,
|
|
118
|
+
head: this.getCodemirrorState()?.selection.main.head };
|
|
113
119
|
this.onSelectionChange([insertSelection]);
|
|
114
120
|
return;
|
|
115
121
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*
|
|
2
|
-
* Copyright 2017-
|
|
2
|
+
* Copyright 2017-2024 Elyra Authors
|
|
3
3
|
*
|
|
4
4
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
5
|
* you may not use this file except in compliance with the License.
|
|
@@ -19,11 +19,10 @@
|
|
|
19
19
|
import React from "react";
|
|
20
20
|
import PropTypes from "prop-types";
|
|
21
21
|
import { connect } from "react-redux";
|
|
22
|
-
import { UnControlled as CodeMirror } from "react-codemirror2";
|
|
23
22
|
import Icon from "./../../../icons/icon.jsx";
|
|
24
23
|
import { Button } from "carbon-components-react";
|
|
25
24
|
import classNames from "classnames";
|
|
26
|
-
import { isEqual } from "lodash";
|
|
25
|
+
import { isEqual, concat } from "lodash";
|
|
27
26
|
import ValidationMessage from "./../../components/validation-message";
|
|
28
27
|
import WideFlyout from "./../../components/wide-flyout";
|
|
29
28
|
import { formatMessage } from "./../../util/property-utils";
|
|
@@ -35,76 +34,67 @@ import { STATES } from "./../../constants/constants";
|
|
|
35
34
|
import { get } from "lodash";
|
|
36
35
|
import ExpressionToggle from "./expression-toggle/expression-toggle";
|
|
37
36
|
|
|
38
|
-
import {
|
|
39
|
-
import {
|
|
40
|
-
import {
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
require("codemirror/mode/sql/sql");
|
|
53
|
-
require("codemirror/mode/python/python");
|
|
54
|
-
require("codemirror/mode/r/r");
|
|
55
|
-
registerPython(cm);
|
|
56
|
-
registerR(cm);
|
|
57
|
-
registerClem(cm);
|
|
58
|
-
}
|
|
59
|
-
|
|
37
|
+
import { keymap, placeholder } from "@codemirror/view";
|
|
38
|
+
import { defaultKeymap, indentWithTab, insertNewline } from "@codemirror/commands";
|
|
39
|
+
import { basicSetup, EditorView } from "codemirror";
|
|
40
|
+
import { Compartment } from "@codemirror/state";
|
|
41
|
+
import { tags } from "@lezer/highlight";
|
|
42
|
+
import { HighlightStyle, syntaxHighlighting } from "@codemirror/language";
|
|
43
|
+
import { python } from "@codemirror/lang-python";
|
|
44
|
+
import { r } from "codemirror-lang-r";
|
|
45
|
+
import { sql } from "@codemirror/lang-sql";
|
|
46
|
+
import { javascript } from "@codemirror/lang-javascript";
|
|
47
|
+
|
|
48
|
+
import { getPythonHints } from "./languages/python-hint";
|
|
49
|
+
import { getRHints } from "./languages/r-hint";
|
|
50
|
+
import { clem } from "./languages/CLEM-hint";
|
|
60
51
|
|
|
61
52
|
const pxPerChar = 8.5;
|
|
62
53
|
const pxPerLine = 26;
|
|
63
54
|
const defaultCharPerLine = 30;
|
|
64
55
|
const maxLineHeight = 15 * pxPerLine; // 20 lines
|
|
65
56
|
const minLineHeight = 4 * pxPerLine; // 4 lines
|
|
66
|
-
|
|
67
57
|
class ExpressionControl extends React.Component {
|
|
68
58
|
constructor(props) {
|
|
69
59
|
super(props);
|
|
70
60
|
this.state = {
|
|
71
61
|
showExpressionBuilder: false,
|
|
72
|
-
validationInProgress: false
|
|
62
|
+
validationInProgress: false,
|
|
63
|
+
expressionEditorHeight: 0
|
|
73
64
|
};
|
|
74
|
-
|
|
75
|
-
this.
|
|
65
|
+
this.editable = new Compartment; // eslint-disable-line new-parens
|
|
66
|
+
this.editorRef = React.createRef();
|
|
67
|
+
this.origHint = [];
|
|
76
68
|
this.expressionInfo = this.props.controller.getExpressionInfo();
|
|
77
69
|
this.handleValidate = this.handleValidate.bind(this);
|
|
78
70
|
this.hasValidate = this.hasValidate.bind(this);
|
|
79
71
|
this.cancelExpressionBuilder = this.cancelExpressionBuilder.bind(this);
|
|
80
72
|
this.hideExpressionBuilder = this.hideExpressionBuilder.bind(this);
|
|
81
73
|
this.showExpressionBuilder = this.showExpressionBuilder.bind(this);
|
|
82
|
-
this.editorDidMount = this.editorDidMount.bind(this);
|
|
83
74
|
this.addonHints = this.addonHints.bind(this);
|
|
84
75
|
this.getDatasetFields = this.getDatasetFields.bind(this);
|
|
85
76
|
this.handleBlur = this.handleBlur.bind(this);
|
|
86
|
-
this.
|
|
87
|
-
|
|
88
|
-
this.
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
this.props.onSelectionChange([{ anchor: newPos, head: newPos }]);
|
|
96
|
-
}
|
|
97
|
-
if (this.state.validateIcon) {
|
|
98
|
-
this.setState({
|
|
99
|
-
validateIcon: null
|
|
100
|
-
});
|
|
101
|
-
this.props.controller.updateErrorMessage(this.props.propertyId, DEFAULT_VALIDATION_MESSAGE);
|
|
102
|
-
}
|
|
103
|
-
};
|
|
77
|
+
this.createCodeMirrorEditor = this.createCodeMirrorEditor.bind(this);
|
|
78
|
+
this.events = this.events.bind(this);
|
|
79
|
+
this.handleUpdate = this.handleUpdate.bind(this);
|
|
80
|
+
this.setCodeMirrorEditable = this.setCodeMirrorEditable.bind(this);
|
|
81
|
+
this.getCodemirrorState = this.getCodemirrorState.bind(this);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
componentDidMount() {
|
|
85
|
+
this.createCodeMirrorEditor();
|
|
104
86
|
}
|
|
105
87
|
|
|
106
88
|
// this is needed to ensure expression builder selection works.
|
|
107
89
|
componentDidUpdate(prevProps) {
|
|
90
|
+
// When code is edited in expression builder, reflect changes in expression flyout
|
|
91
|
+
if (!isEqual(this.getCodemirrorState()?.doc.toString(), this.props.value)) {
|
|
92
|
+
this.editor.dispatch({ changes: { from: 0, to: this.getCodemirrorState()?.doc.length, insert: this.props.value } });
|
|
93
|
+
}
|
|
94
|
+
// Toggle editable mode in Codemirror editor
|
|
95
|
+
if (!isEqual(prevProps.state, this.props.state)) {
|
|
96
|
+
this.setCodeMirrorEditable(!(this.props.state === STATES.DISABLED));
|
|
97
|
+
}
|
|
108
98
|
if (
|
|
109
99
|
this.props.selectionRange &&
|
|
110
100
|
this.props.selectionRange.length > 0 &&
|
|
@@ -112,17 +102,21 @@ class ExpressionControl extends React.Component {
|
|
|
112
102
|
this.editor
|
|
113
103
|
) {
|
|
114
104
|
this.props.selectionRange.forEach((selected) => {
|
|
115
|
-
this.editor.
|
|
105
|
+
this.editor.dispatch({ selection: selected });
|
|
116
106
|
});
|
|
117
107
|
this.editor.focus();
|
|
118
108
|
}
|
|
119
109
|
}
|
|
120
110
|
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
111
|
+
getCodemirrorState() {
|
|
112
|
+
return this.editor?.viewState?.state;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// Set codemirror editor non-editable when disabled
|
|
116
|
+
setCodeMirrorEditable(value) {
|
|
117
|
+
this.editor.dispatch({
|
|
118
|
+
effects: this.editable.reconfigure(EditorView.editable.of(value))
|
|
119
|
+
});
|
|
126
120
|
}
|
|
127
121
|
|
|
128
122
|
// get the set of dataset field names
|
|
@@ -130,39 +124,24 @@ class ExpressionControl extends React.Component {
|
|
|
130
124
|
const results = [];
|
|
131
125
|
const fields = this.props.controller.getDatasetMetadataFields();
|
|
132
126
|
for (const field of fields) {
|
|
133
|
-
results.push(field.name);
|
|
127
|
+
results.push({ label: field.name, type: "variable" });
|
|
134
128
|
}
|
|
135
129
|
return results;
|
|
136
130
|
}
|
|
137
131
|
|
|
138
132
|
// Add the dataset field names to the autocomplete list
|
|
139
|
-
addonHints(
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
if (this.origHint) {
|
|
144
|
-
// get the list of autocomplete names from the language autocomplete handler
|
|
145
|
-
results = this.origHint(editor, options);
|
|
146
|
-
|
|
147
|
-
// add to the start of the autocomplete list the set of dataset field names that complete the
|
|
148
|
-
// string that has been entered.
|
|
149
|
-
var parameters = this.getDatasetFields();
|
|
150
|
-
for (var i = 0; i < parameters.length; ++i) {
|
|
151
|
-
const parameter = parameters[i];
|
|
152
|
-
if (parameter.lastIndexOf(token.string, 0) === 0 && results.list.indexOf(parameter) === -1) {
|
|
153
|
-
results.list.unshift(parameter);
|
|
154
|
-
} else if (token.string === " " && token.type === null) {
|
|
155
|
-
results.list.unshift(parameter);
|
|
156
|
-
}
|
|
157
|
-
}
|
|
133
|
+
addonHints(context) {
|
|
134
|
+
const word = context.matchBefore(/\w*/);
|
|
135
|
+
if (word.from === word.to && !context.explicit) {
|
|
136
|
+
return null;
|
|
158
137
|
}
|
|
159
|
-
return
|
|
138
|
+
return {
|
|
139
|
+
from: word.from,
|
|
140
|
+
options: concat(this.origHint, this.getDatasetFields())
|
|
141
|
+
};
|
|
160
142
|
}
|
|
161
143
|
|
|
162
|
-
|
|
163
|
-
// that will add data set filed names to autocomplete list.
|
|
164
|
-
editorDidMount(editor, next) {
|
|
165
|
-
this.editor = editor;
|
|
144
|
+
createCodeMirrorEditor() {
|
|
166
145
|
// set the default height, should be between 4 and 20 lines
|
|
167
146
|
const controlWidth = (this.expressionEditorDiv) ? this.expressionEditorDiv.clientWidth : 0;
|
|
168
147
|
const charPerLine = (controlWidth > 0) ? controlWidth / pxPerChar : defaultCharPerLine;
|
|
@@ -172,9 +151,8 @@ class ExpressionControl extends React.Component {
|
|
|
172
151
|
// let an explicit prop override the calculated height
|
|
173
152
|
height = this.props.control.rows ? pxPerLine * this.props.control.rows : height;
|
|
174
153
|
height = this.props.height ? this.props.height : height;
|
|
175
|
-
this.
|
|
154
|
+
this.setState({ expressionEditorHeight: Math.max(Math.floor(height), minLineHeight) });
|
|
176
155
|
|
|
177
|
-
this.origHint = editor.getHelper({ line: 0, ch: 0 }, "hint");
|
|
178
156
|
// this next line is a hack to overcome a Codemirror problem. To support SparkSQL, a subset of SQL,
|
|
179
157
|
// we need to register with Codemirror the language as the value of "text/x-hive". When Codemirror
|
|
180
158
|
// registers the autocomplete addon it registers is as "sql" not the subset "text/x-hive"
|
|
@@ -183,22 +161,61 @@ class ExpressionControl extends React.Component {
|
|
|
183
161
|
let language = this.props.control.language;
|
|
184
162
|
switch (this.props.control.language) {
|
|
185
163
|
case "text/x-hive":
|
|
186
|
-
language =
|
|
164
|
+
language = sql();
|
|
187
165
|
break;
|
|
188
166
|
case "text/x-python":
|
|
189
|
-
language =
|
|
167
|
+
language = python();
|
|
168
|
+
this.origHint = getPythonHints();
|
|
190
169
|
break;
|
|
191
170
|
case "text/x-rsrc":
|
|
192
|
-
language =
|
|
171
|
+
language = r();
|
|
172
|
+
this.origHint = getRHints();
|
|
173
|
+
break;
|
|
174
|
+
case "javascript":
|
|
175
|
+
language = javascript();
|
|
193
176
|
break;
|
|
194
177
|
default:
|
|
178
|
+
language = clem();
|
|
195
179
|
}
|
|
196
|
-
if (cm) {
|
|
197
|
-
cm.registerHelper("hint", language, this.addonHints);
|
|
198
|
-
}
|
|
199
180
|
|
|
181
|
+
// Custom completions add to the language completions
|
|
182
|
+
const customCompletions = language.language.data.of({
|
|
183
|
+
autocomplete: this.addonHints
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
// Syntax highlighting
|
|
187
|
+
const myHighlightStyle = HighlightStyle.define([
|
|
188
|
+
{ tag: tags.keyword, class: "cm-keyword" },
|
|
189
|
+
{ tag: tags.number, class: "cm-number" },
|
|
190
|
+
{ tag: tags.definition(tags.name), class: "cm-def" },
|
|
191
|
+
{ tag: tags.comment, class: "cm-comment" },
|
|
192
|
+
{ tag: tags.variableName, class: "cm-variable" },
|
|
193
|
+
{ tag: tags.punctuation, class: "cm-punctuation" },
|
|
194
|
+
{ tag: tags.propertyName, class: "cm-property" },
|
|
195
|
+
{ tag: tags.operator, class: "cm-operator" },
|
|
196
|
+
{ tag: tags.string, class: "cm-string" },
|
|
197
|
+
{ tag: tags.meta, class: "cm-meta" }
|
|
198
|
+
]);
|
|
199
|
+
|
|
200
|
+
this.editor = new EditorView({
|
|
201
|
+
doc: this.props.value,
|
|
202
|
+
extensions: [
|
|
203
|
+
keymap.of([{ key: "Enter", run: insertNewline }, indentWithTab, defaultKeymap]), // This should be before basicSetup to insertNewLine on "Enter"
|
|
204
|
+
customCompletions,
|
|
205
|
+
syntaxHighlighting(myHighlightStyle),
|
|
206
|
+
basicSetup,
|
|
207
|
+
this.events(),
|
|
208
|
+
language,
|
|
209
|
+
placeholder(this.props.control.additionalText),
|
|
210
|
+
this.handleUpdate(),
|
|
211
|
+
this.editable.of(EditorView.editable.of(!(this.props.state === STATES.DISABLED)))
|
|
212
|
+
],
|
|
213
|
+
parent: this.editorRef.current
|
|
214
|
+
});
|
|
215
|
+
|
|
216
|
+
// Set editor in the expression-builder
|
|
200
217
|
if (this.props.editorDidMount) {
|
|
201
|
-
this.props.editorDidMount(editor
|
|
218
|
+
this.props.editorDidMount(this.editor);
|
|
202
219
|
}
|
|
203
220
|
}
|
|
204
221
|
|
|
@@ -232,7 +249,6 @@ class ExpressionControl extends React.Component {
|
|
|
232
249
|
validateIcon: response.type,
|
|
233
250
|
validationInProgress: false
|
|
234
251
|
});
|
|
235
|
-
this.editor.display.input.blur();
|
|
236
252
|
});
|
|
237
253
|
}
|
|
238
254
|
|
|
@@ -240,28 +256,56 @@ class ExpressionControl extends React.Component {
|
|
|
240
256
|
return typeof this.props.controller.getHandlers().validationHandler === "function";
|
|
241
257
|
}
|
|
242
258
|
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
259
|
+
// Event handlers for CM6
|
|
260
|
+
events() {
|
|
261
|
+
const that = this;
|
|
262
|
+
const eventHandlers = EditorView.domEventHandlers({
|
|
263
|
+
blur(evt, view) {
|
|
264
|
+
that.handleBlur(view, evt);
|
|
249
265
|
}
|
|
250
|
-
}
|
|
266
|
+
});
|
|
267
|
+
return eventHandlers;
|
|
251
268
|
}
|
|
252
269
|
|
|
253
270
|
handleBlur(editor, evt) {
|
|
254
|
-
|
|
271
|
+
const cancelButtonClicked = evt && evt.relatedTarget && evt.relatedTarget.classList.contains("properties-cancel-button");
|
|
272
|
+
if (this.props.onBlur && !cancelButtonClicked) {
|
|
255
273
|
// this will ensure the expression builder can save values onBlur
|
|
256
274
|
this.props.onBlur(editor, evt);
|
|
257
275
|
} else {
|
|
258
|
-
const newValue =
|
|
276
|
+
const newValue = editor?.viewState?.state?.doc.toString();
|
|
259
277
|
// don't validate when opening the expression builder
|
|
260
278
|
const skipValidate = evt && evt.relatedTarget && evt.relatedTarget.classList.contains("properties-expression-button");
|
|
261
279
|
this.props.controller.updatePropertyValue(this.props.propertyId, newValue, skipValidate);
|
|
262
280
|
}
|
|
263
281
|
}
|
|
264
282
|
|
|
283
|
+
handleUpdate() {
|
|
284
|
+
const onUpdate = EditorView.updateListener.of((viewUpdate) => {
|
|
285
|
+
if (viewUpdate.docChanged) {
|
|
286
|
+
// this is needed when a single character is added into the expression builder because
|
|
287
|
+
// entering chars does not go through onChange() in expression builder.
|
|
288
|
+
// This is needed to adjust the selection position in code mirror.
|
|
289
|
+
if (
|
|
290
|
+
Array.isArray(viewUpdate.changedRanges) &&
|
|
291
|
+
viewUpdate.changedRanges.length === 1 &&
|
|
292
|
+
Math.abs(viewUpdate.changes.newLength - viewUpdate.changes.length) === 1 &&
|
|
293
|
+
this.props.onSelectionChange
|
|
294
|
+
) {
|
|
295
|
+
const newPos = viewUpdate.changedRanges[0].toB;
|
|
296
|
+
this.props.onSelectionChange([{ anchor: newPos, head: newPos }]);
|
|
297
|
+
}
|
|
298
|
+
if (this.state.validateIcon) {
|
|
299
|
+
this.setState({
|
|
300
|
+
validateIcon: null
|
|
301
|
+
});
|
|
302
|
+
this.props.controller.updateErrorMessage(this.props.propertyId, DEFAULT_VALIDATION_MESSAGE);
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
});
|
|
306
|
+
return onUpdate;
|
|
307
|
+
}
|
|
308
|
+
|
|
265
309
|
_showBuilderButton() {
|
|
266
310
|
// only show the button if there are function lists available and
|
|
267
311
|
// not explicitly told not to by the this.props.builder
|
|
@@ -276,7 +320,6 @@ class ExpressionControl extends React.Component {
|
|
|
276
320
|
messageInfo = null;
|
|
277
321
|
}
|
|
278
322
|
|
|
279
|
-
const theme = (this.props.state === STATES.DISABLED) ? "disabled" : messageType;
|
|
280
323
|
const reactIntl = this.props.controller.getReactIntl();
|
|
281
324
|
|
|
282
325
|
const button = this._showBuilderButton() ? (
|
|
@@ -309,15 +352,7 @@ class ExpressionControl extends React.Component {
|
|
|
309
352
|
{validateIcon}
|
|
310
353
|
</div>)
|
|
311
354
|
: null;
|
|
312
|
-
|
|
313
|
-
mode: this.props.control.language,
|
|
314
|
-
placeholder: this.props.control.additionalText,
|
|
315
|
-
theme: theme + " custom",
|
|
316
|
-
readOnly: (this.props.state === STATES.DISABLED) ? "nocursor" : false,
|
|
317
|
-
extraKeys: { "Ctrl-Space": "autocomplete" },
|
|
318
|
-
autoRefresh: true,
|
|
319
|
-
lineNumbers: true
|
|
320
|
-
};
|
|
355
|
+
|
|
321
356
|
const applyLabel = formatMessage(reactIntl, MESSAGE_KEYS.APPLYBUTTON_LABEL);
|
|
322
357
|
const rejectLabel = formatMessage(reactIntl, MESSAGE_KEYS.REJECTBUTTON_LABEL);
|
|
323
358
|
const expressonTitle = formatMessage(reactIntl, MESSAGE_KEYS.EXPRESSION_BUILDER_TITLE);
|
|
@@ -367,6 +402,8 @@ class ExpressionControl extends React.Component {
|
|
|
367
402
|
/>);
|
|
368
403
|
}
|
|
369
404
|
|
|
405
|
+
const codemirrorClassName = classNames(`elyra-CodeMirror ${messageType} ${this.props.state}`);
|
|
406
|
+
|
|
370
407
|
return (
|
|
371
408
|
<div className="properties-expression-editor-wrapper" >
|
|
372
409
|
{this.props.controlItem}
|
|
@@ -377,15 +414,7 @@ class ExpressionControl extends React.Component {
|
|
|
377
414
|
<div ref={ (ref) => (this.expressionEditorDiv = ref) } data-id={ControlUtils.getDataId(this.props.propertyId)}
|
|
378
415
|
className={className}
|
|
379
416
|
>
|
|
380
|
-
<
|
|
381
|
-
ref= { (ref) => (this.codeMirror = ref)}
|
|
382
|
-
options={mirrorOptions}
|
|
383
|
-
onChange={this.handleChange}
|
|
384
|
-
onKeyDown={this.handleKeyDown}
|
|
385
|
-
onBlur={this.handleBlur}
|
|
386
|
-
editorDidMount={this.editorDidMount}
|
|
387
|
-
value={this.props.value}
|
|
388
|
-
/>
|
|
417
|
+
<div className={codemirrorClassName} ref={this.editorRef} style={{ height: this.state.expressionEditorHeight }} />
|
|
389
418
|
<ValidationMessage state={this.props.state} messageInfo={messageInfo} inTable={this.props.tableControl} />
|
|
390
419
|
</div>
|
|
391
420
|
</div>
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*
|
|
2
|
-
* Copyright 2017-
|
|
2
|
+
* Copyright 2017-2024 Elyra Authors
|
|
3
3
|
*
|
|
4
4
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
5
|
* you may not use this file except in compliance with the License.
|
|
@@ -17,80 +17,78 @@
|
|
|
17
17
|
@import "./expression-builder/expression-builder";
|
|
18
18
|
@import "./expression-toggle/expression-toggle";
|
|
19
19
|
|
|
20
|
-
.
|
|
21
|
-
.
|
|
20
|
+
.elyra-CodeMirror {
|
|
21
|
+
.cm-editor {
|
|
22
|
+
height: inherit;
|
|
22
23
|
width: 100%;
|
|
23
24
|
background: $field-02;
|
|
24
25
|
color: $text-01;
|
|
25
26
|
|
|
26
|
-
.
|
|
27
|
+
.cm-gutters {
|
|
27
28
|
border-right: none;
|
|
28
29
|
background-color: inherit;
|
|
29
30
|
}
|
|
30
31
|
|
|
31
|
-
.
|
|
32
|
-
|
|
33
|
-
.CodeMirror-line-like {
|
|
32
|
+
.cm-content {
|
|
33
|
+
.cm-line {
|
|
34
34
|
padding-left: $spacing-03;
|
|
35
|
+
@include carbon--type-style("code-02");
|
|
35
36
|
}
|
|
36
|
-
.
|
|
37
|
-
opacity: 0.5;
|
|
37
|
+
.cm-placeholder {
|
|
38
38
|
@include carbon--type-style("code-02");
|
|
39
39
|
}
|
|
40
|
-
.
|
|
40
|
+
.cm-cursor {
|
|
41
41
|
border-left: 1px solid $text-01;
|
|
42
42
|
}
|
|
43
|
-
.
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
.CodeMirror-line {
|
|
50
|
-
padding-left: $spacing-03;
|
|
43
|
+
.cm-lineNumbers .cm-gutterElement {
|
|
44
|
+
@include carbon--type-style("body-short-01");
|
|
45
|
+
}
|
|
46
|
+
}
|
|
51
47
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
48
|
+
.cm-tooltip-autocomplete {
|
|
49
|
+
z-index: 1110;
|
|
50
|
+
ul {
|
|
51
|
+
white-space: normal; // Wraps the long autocompletion text on multiple lines
|
|
56
52
|
}
|
|
57
53
|
}
|
|
58
54
|
}
|
|
59
55
|
|
|
60
|
-
.cm-
|
|
61
|
-
|
|
62
|
-
.cm-s-warning.CodeMirror { border: $spacing-01 solid $support-03; }
|
|
63
|
-
|
|
64
|
-
.cm-s-disabled.CodeMirror { opacity: 0.5}
|
|
56
|
+
.cm-line .cm-keyword { color: $link-01; }
|
|
65
57
|
|
|
66
|
-
.cm-
|
|
58
|
+
.cm-line .cm-number { color: $text-02; }
|
|
67
59
|
|
|
68
|
-
.cm-
|
|
60
|
+
.cm-line .cm-def { color: $support-01; }
|
|
69
61
|
|
|
70
|
-
.cm-
|
|
62
|
+
.cm-line .cm-comment { color: $support-02; }
|
|
71
63
|
|
|
72
|
-
.cm-
|
|
73
|
-
|
|
74
|
-
.cm-
|
|
75
|
-
.cm-
|
|
76
|
-
.cm-s-custom .cm-property,
|
|
77
|
-
.cm-s-custom .cm-operator {
|
|
64
|
+
.cm-line .cm-variable,
|
|
65
|
+
.cm-line .cm-punctuation,
|
|
66
|
+
.cm-line .cm-property,
|
|
67
|
+
.cm-line .cm-operator {
|
|
78
68
|
color: $text-01;
|
|
79
69
|
}
|
|
80
|
-
.cm-s-custom .cm-variable-2 { color: $text-01; }
|
|
81
70
|
|
|
82
|
-
.cm-
|
|
71
|
+
.cm-line .cm-string { color: $text-error; }
|
|
83
72
|
|
|
84
|
-
.cm-
|
|
73
|
+
.cm-line .cm-meta { color: $ui-01; }
|
|
74
|
+
}
|
|
85
75
|
|
|
86
|
-
|
|
76
|
+
.elyra-CodeMirror.disabled {
|
|
77
|
+
.cm-editor {
|
|
78
|
+
opacity: 0.5;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
87
81
|
|
|
88
|
-
|
|
82
|
+
.elyra-CodeMirror.warning {
|
|
83
|
+
.cm-editor {
|
|
84
|
+
border: $spacing-01 solid $support-03;
|
|
85
|
+
}
|
|
89
86
|
}
|
|
90
87
|
|
|
91
|
-
|
|
92
|
-
.
|
|
93
|
-
|
|
88
|
+
.elyra-CodeMirror.error {
|
|
89
|
+
.cm-editor {
|
|
90
|
+
border: $spacing-01 solid $support-01;
|
|
91
|
+
}
|
|
94
92
|
}
|
|
95
93
|
|
|
96
94
|
.properties-expression-editor {
|
|
@@ -104,7 +102,7 @@
|
|
|
104
102
|
}
|
|
105
103
|
|
|
106
104
|
.properties-light-disabled {
|
|
107
|
-
.CodeMirror {
|
|
105
|
+
.elyra-CodeMirror .cm-editor {
|
|
108
106
|
background: $field-01;
|
|
109
107
|
}
|
|
110
108
|
}
|