@elyra/canvas 12.12.3 → 12.15.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.
Files changed (204) hide show
  1. package/.stylelintrc.json +17 -16
  2. package/README.md +1 -1
  3. package/dist/_baseForOwn-7d4e8506.js.map +1 -1
  4. package/dist/_baseForOwn-d38b560e.js.map +1 -1
  5. package/dist/canvas-constants-34cdb7df.js.map +1 -1
  6. package/dist/canvas-constants-3c09c7f6.js.map +1 -1
  7. package/dist/{canvas-controller-e91d037b.js → canvas-controller-720a509c.js} +2 -2
  8. package/dist/canvas-controller-720a509c.js.map +1 -0
  9. package/dist/canvas-controller-73113a1b.js +2 -0
  10. package/dist/canvas-controller-73113a1b.js.map +1 -0
  11. package/dist/common-canvas-21b6ab50.js +2 -0
  12. package/dist/common-canvas-21b6ab50.js.map +1 -0
  13. package/dist/common-canvas-baef2726.js +2 -0
  14. package/dist/common-canvas-baef2726.js.map +1 -0
  15. package/dist/common-canvas.es.js +1 -1
  16. package/dist/common-canvas.es.js.map +1 -1
  17. package/dist/common-canvas.js +1 -1
  18. package/dist/common-canvas.js.map +1 -1
  19. package/dist/common-properties-86de4c9f.js +2 -0
  20. package/dist/common-properties-86de4c9f.js.map +1 -0
  21. package/dist/common-properties-9e579309.js +2 -0
  22. package/dist/common-properties-9e579309.js.map +1 -0
  23. package/dist/createClass-32a0cf0f.js.map +1 -1
  24. package/dist/createClass-6db89a23.js.map +1 -1
  25. package/dist/datarecord-metadata-v3-schema-6b6384ff.js.map +1 -1
  26. package/dist/datarecord-metadata-v3-schema-81228a9a.js.map +1 -1
  27. package/dist/en-7a0f1db1.js.map +1 -1
  28. package/dist/en-8647c347.js.map +1 -1
  29. package/dist/{extends-7fdcdc52.js → extends-1139e06f.js} +2 -2
  30. package/dist/{extends-7fdcdc52.js.map → extends-1139e06f.js.map} +1 -1
  31. package/dist/extends-8d17c85c.js.map +1 -1
  32. package/dist/{flexible-table-a13cb7d0.js → flexible-table-d3598aa8.js} +2 -2
  33. package/dist/flexible-table-d3598aa8.js.map +1 -0
  34. package/dist/{flexible-table-50ce600a.js → flexible-table-fe7fbc13.js} +2 -2
  35. package/dist/flexible-table-fe7fbc13.js.map +1 -0
  36. package/dist/getPrototypeOf-a1c3fe64.js.map +1 -1
  37. package/dist/getPrototypeOf-bf88242f.js.map +1 -1
  38. package/dist/{icon-bf77b2aa.js → icon-918d2dd3.js} +2 -2
  39. package/dist/{icon-bf77b2aa.js.map → icon-918d2dd3.js.map} +1 -1
  40. package/dist/{index-f2c306ba.js → index-669f95a7.js} +2 -2
  41. package/dist/{index-f2c306ba.js.map → index-669f95a7.js.map} +1 -1
  42. package/dist/{index-0e6c8b9c.js → index-6d3404e1.js} +2 -2
  43. package/dist/{index-0e6c8b9c.js.map → index-6d3404e1.js.map} +1 -1
  44. package/dist/isArrayLikeObject-a9c7973b.js.map +1 -1
  45. package/dist/isArrayLikeObject-f3b27f64.js.map +1 -1
  46. package/dist/lib/canvas-controller.es.js +1 -1
  47. package/dist/lib/canvas-controller.js +1 -1
  48. package/dist/lib/canvas.es.js +1 -1
  49. package/dist/lib/canvas.js +1 -1
  50. package/dist/lib/context-menu.es.js +1 -1
  51. package/dist/lib/properties/field-picker.es.js +1 -1
  52. package/dist/lib/properties/field-picker.js +1 -1
  53. package/dist/lib/properties/flexible-table.es.js +1 -1
  54. package/dist/lib/properties/flexible-table.js +1 -1
  55. package/dist/lib/properties.es.js +1 -1
  56. package/dist/lib/properties.js +1 -1
  57. package/dist/lib/tooltip.es.js +1 -1
  58. package/dist/lib/tooltip.es.js.map +1 -1
  59. package/dist/lib/tooltip.js +1 -1
  60. package/dist/lib/tooltip.js.map +1 -1
  61. package/dist/styles/common-canvas.min.css +1 -1
  62. package/dist/styles/common-canvas.min.css.map +1 -1
  63. package/dist/toolbar-29ec7983.js +2 -0
  64. package/dist/toolbar-29ec7983.js.map +1 -0
  65. package/dist/toolbar-3f4b173f.js +2 -0
  66. package/dist/toolbar-3f4b173f.js.map +1 -0
  67. package/locales/command-actions/locales/de.json +50 -8
  68. package/locales/command-actions/locales/en.json +1 -1
  69. package/locales/command-actions/locales/es.json +50 -8
  70. package/locales/command-actions/locales/fr.json +50 -8
  71. package/locales/command-actions/locales/index.js +2 -2
  72. package/locales/command-actions/locales/it.json +50 -8
  73. package/locales/command-actions/locales/ja.json +50 -8
  74. package/locales/command-actions/locales/ko.json +42 -0
  75. package/locales/command-actions/locales/pt-br.json +50 -8
  76. package/locales/command-actions/locales/zh-CN.json +51 -0
  77. package/locales/command-actions/locales/zh-TW.json +51 -0
  78. package/locales/common-canvas/locales/de.json +36 -26
  79. package/locales/common-canvas/locales/en.json +14 -1
  80. package/locales/common-canvas/locales/eo.json +14 -1
  81. package/locales/common-canvas/locales/es.json +36 -26
  82. package/locales/common-canvas/locales/fr.json +36 -26
  83. package/locales/common-canvas/locales/index.js +2 -2
  84. package/locales/common-canvas/locales/it.json +36 -26
  85. package/locales/common-canvas/locales/ja.json +36 -26
  86. package/locales/common-canvas/locales/ko.json +7 -2
  87. package/locales/common-canvas/locales/pt-br.json +36 -26
  88. package/locales/common-canvas/locales/zh-CN.json +37 -0
  89. package/locales/common-canvas/locales/zh-TW.json +37 -0
  90. package/locales/common-properties/locales/de.json +92 -92
  91. package/locales/common-properties/locales/en.json +1 -1
  92. package/locales/common-properties/locales/es.json +92 -92
  93. package/locales/common-properties/locales/fr.json +92 -92
  94. package/locales/common-properties/locales/index.js +2 -2
  95. package/locales/common-properties/locales/it.json +92 -92
  96. package/locales/common-properties/locales/ja.json +92 -92
  97. package/locales/common-properties/locales/ko.json +1 -1
  98. package/locales/common-properties/locales/pt-br.json +92 -92
  99. package/locales/common-properties/locales/zh-CN.json +93 -0
  100. package/locales/common-properties/locales/zh-TW.json +93 -0
  101. package/locales/palette/locales/de.json +9 -9
  102. package/locales/palette/locales/en.json +6 -6
  103. package/locales/palette/locales/es.json +9 -9
  104. package/locales/palette/locales/fr.json +9 -9
  105. package/locales/palette/locales/index.js +2 -2
  106. package/locales/palette/locales/it.json +9 -9
  107. package/locales/palette/locales/ja.json +9 -9
  108. package/locales/palette/locales/pt-br.json +9 -9
  109. package/locales/palette/locales/zh-CN.json +10 -0
  110. package/locales/palette/locales/zh-TW.json +10 -0
  111. package/locales/toolbar/locales/de.json +7 -7
  112. package/locales/toolbar/locales/en.json +1 -1
  113. package/locales/toolbar/locales/es.json +7 -7
  114. package/locales/toolbar/locales/fr.json +7 -7
  115. package/locales/toolbar/locales/index.js +2 -2
  116. package/locales/toolbar/locales/it.json +7 -7
  117. package/locales/toolbar/locales/ja.json +7 -7
  118. package/locales/toolbar/locales/pt-br.json +7 -7
  119. package/locales/toolbar/locales/zh-CN.json +8 -0
  120. package/locales/toolbar/locales/zh-TW.json +8 -0
  121. package/package.json +3 -2
  122. package/src/common-canvas/canvas-controller.js +19 -3
  123. package/src/common-canvas/cc-bottom-panel.jsx +37 -21
  124. package/src/common-canvas/cc-central-items.jsx +1 -1
  125. package/src/common-canvas/cc-contents.jsx +10 -3
  126. package/src/common-canvas/cc-text-toolbar.jsx +141 -0
  127. package/src/common-canvas/cc-toolbar.jsx +8 -6
  128. package/src/common-canvas/common-canvas-utils.js +37 -4
  129. package/src/common-canvas/common-canvas.scss +52 -5
  130. package/src/common-canvas/svg-canvas-d3.scss +172 -23
  131. package/src/common-canvas/svg-canvas-pipeline.js +10 -3
  132. package/src/common-canvas/svg-canvas-renderer.js +93 -341
  133. package/src/common-canvas/svg-canvas-utils-decs.js +0 -5
  134. package/src/common-canvas/svg-canvas-utils-markdown.js +515 -0
  135. package/src/common-canvas/svg-canvas-utils-nodes.js +0 -5
  136. package/src/common-canvas/svg-canvas-utils-textarea.js +472 -0
  137. package/src/common-properties/components/control-item/control-item.scss +1 -1
  138. package/src/common-properties/components/flexible-table/flexible-table.jsx +14 -3
  139. package/src/common-properties/components/flexible-table/flexible-table.scss +20 -0
  140. package/src/common-properties/components/title-editor/title-editor.jsx +2 -2
  141. package/src/common-properties/components/title-editor/title-editor.scss +1 -16
  142. package/src/common-properties/controls/abstract-table.jsx +2 -0
  143. package/src/common-properties/controls/checkbox/checkbox.jsx +1 -1
  144. package/src/common-properties/controls/checkboxset/checkboxset.jsx +36 -11
  145. package/src/common-properties/controls/checkboxset/checkboxset.scss +6 -0
  146. package/src/common-properties/controls/list/list.jsx +1 -0
  147. package/src/common-properties/controls/radioset/radioset.jsx +25 -1
  148. package/src/common-properties/controls/radioset/radioset.scss +19 -0
  149. package/src/common-properties/controls/selectcolumns/selectcolumns.jsx +1 -0
  150. package/src/common-properties/controls/someofselect/someofselect.jsx +1 -0
  151. package/src/common-properties/form/ControlInfo.js +3 -0
  152. package/src/common-properties/form/EditorForm.js +45 -3
  153. package/src/common-properties/panels/action-panel/action-panel.jsx +38 -3
  154. package/src/common-properties/panels/action-panel/action-panel.scss +3 -0
  155. package/src/common-properties/panels/text-panel/text-panel.jsx +38 -7
  156. package/src/common-properties/panels/text-panel/text-panel.scss +4 -3
  157. package/src/common-properties/properties-controller.js +39 -12
  158. package/src/common-properties/ui-conditions/conditions-utils.js +14 -8
  159. package/src/common-properties/util/L10nProvider.js +6 -0
  160. package/src/object-model/config-utils.js +1 -0
  161. package/src/object-model/layout-dimensions.js +14 -2
  162. package/src/object-model/object-model.js +12 -0
  163. package/src/object-model/redux/canvas-store.js +4 -1
  164. package/src/object-model/redux/reducers/bottompanel.js +1 -3
  165. package/src/object-model/redux/reducers/texttoolbar.js +29 -0
  166. package/src/palette/palette-content-list-item.jsx +12 -2
  167. package/src/palette/palette-content-list.jsx +11 -19
  168. package/src/palette/palette-dialog-content-grid.jsx +1 -6
  169. package/src/palette/palette-dialog-content.jsx +13 -11
  170. package/src/palette/palette-flyout-content-category.jsx +90 -57
  171. package/src/palette/palette-flyout-content.jsx +4 -24
  172. package/src/palette/palette.scss +72 -44
  173. package/src/toolbar/toolbar-action-item.jsx +9 -6
  174. package/src/toolbar/toolbar-overflow-item.jsx +1 -0
  175. package/src/toolbar/toolbar.jsx +12 -15
  176. package/src/tooltip/tooltip.jsx +14 -5
  177. package/stats.html +1 -1
  178. package/dist/canvas-controller-de76a796.js +0 -2
  179. package/dist/canvas-controller-de76a796.js.map +0 -1
  180. package/dist/canvas-controller-e91d037b.js.map +0 -1
  181. package/dist/common-canvas-522f6263.js +0 -2
  182. package/dist/common-canvas-522f6263.js.map +0 -1
  183. package/dist/common-canvas-90539c97.js +0 -2
  184. package/dist/common-canvas-90539c97.js.map +0 -1
  185. package/dist/common-properties-245c4711.js +0 -2
  186. package/dist/common-properties-245c4711.js.map +0 -1
  187. package/dist/common-properties-49e6bb67.js +0 -2
  188. package/dist/common-properties-49e6bb67.js.map +0 -1
  189. package/dist/flexible-table-50ce600a.js.map +0 -1
  190. package/dist/flexible-table-a13cb7d0.js.map +0 -1
  191. package/dist/toolbar-1c181339.js +0 -2
  192. package/dist/toolbar-1c181339.js.map +0 -1
  193. package/dist/toolbar-c6fa3cdb.js +0 -2
  194. package/dist/toolbar-c6fa3cdb.js.map +0 -1
  195. package/locales/command-actions/locales/zh-cn.json +0 -9
  196. package/locales/command-actions/locales/zh-tw.json +0 -9
  197. package/locales/common-canvas/locales/zh-cn.json +0 -27
  198. package/locales/common-canvas/locales/zh-tw.json +0 -27
  199. package/locales/common-properties/locales/zh-cn.json +0 -93
  200. package/locales/common-properties/locales/zh-tw.json +0 -93
  201. package/locales/palette/locales/zh-cn.json +0 -10
  202. package/locales/palette/locales/zh-tw.json +0 -10
  203. package/locales/toolbar/locales/zh-cn.json +0 -8
  204. package/locales/toolbar/locales/zh-tw.json +0 -8
@@ -0,0 +1,472 @@
1
+ /*
2
+ * Copyright 2017-2022 Elyra Authors
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+ /* eslint no-invalid-this: "off" */
17
+
18
+ import * as d3Selection from "d3-selection";
19
+ const d3 = Object.assign({}, d3Selection);
20
+
21
+ import { unescape as unescapeText } from "lodash";
22
+
23
+ import Logger from "../logging/canvas-logger.js";
24
+ import CanvasUtils from "./common-canvas-utils.js";
25
+ import SvgCanvasMarkdown from "./svg-canvas-utils-markdown.js";
26
+
27
+ const BACKSPACE_KEY = 8;
28
+ const RETURN_KEY = 13;
29
+ const ESC_KEY = 27;
30
+ const LEFT_ARROW_KEY = 37;
31
+ const UP_ARROW_KEY = 38;
32
+ const RIGHT_ARROW_KEY = 39;
33
+ const DOWN_ARROW_KEY = 40;
34
+ const DELETE_KEY = 46;
35
+ const A_KEY = 65;
36
+ const B_KEY = 66;
37
+ const E_KEY = 69;
38
+ const I_KEY = 73;
39
+ const K_KEY = 75;
40
+ const X_KEY = 88;
41
+ const LAB_KEY = 188; // Left angle bracket <
42
+ const RAB_KEY = 190; // Right angle bracket >
43
+ const SEVEN_KEY = 55;
44
+ const EIGHT_KEY = 56;
45
+
46
+ const SCROLL_PADDING = 12;
47
+
48
+ export default class SvgCanvasTextArea {
49
+
50
+ constructor(config, dispUtils, nodeUtils, decUtils, canvasController,
51
+ canvasDiv, activePipeline, displayCommentsCallback, displayLinksCallback, getCommentToolbarPosCallback) {
52
+
53
+ this.config = config;
54
+ this.dispUtils = dispUtils;
55
+ this.nodeUtils = nodeUtils;
56
+ this.decUtils = decUtils;
57
+ this.canvasController = canvasController;
58
+ this.canvasDiv = canvasDiv;
59
+ this.activePipeline = activePipeline;
60
+ this.displayCommentsCallback = displayCommentsCallback;
61
+ this.displayLinksCallback = displayLinksCallback;
62
+ this.getCommentToolbarPosCallback = getCommentToolbarPosCallback;
63
+
64
+ this.logger = new Logger("SvgCanvasTextArea");
65
+
66
+ // Allows us to track the editing of text (either comments or node labels)
67
+ this.editingText = false;
68
+ this.editingTextId = "";
69
+
70
+ // Keeps track of when text is in the process of being added.
71
+ this.addingTextToTextArea = false;
72
+
73
+ // Keeps track of textarea height.
74
+ this.textAreaHeight = null;
75
+ }
76
+
77
+ isEditingText() {
78
+ return this.editingText;
79
+ }
80
+
81
+ getEditingTextId() {
82
+ return this.editingTextId;
83
+ }
84
+
85
+ displayCommentTextArea(d, parentDomObj) {
86
+ this.editingTextData = {
87
+ id: d.id,
88
+ text: d.content,
89
+ singleLine: false,
90
+ maxCharacters: null,
91
+ allowReturnKey: true,
92
+ textCanBeEmpty: true,
93
+ xPos: 0,
94
+ yPos: 0,
95
+ width: d.width,
96
+ height: d.height,
97
+ className: "d3-comment-entry",
98
+ parentDomObj: parentDomObj,
99
+ keyboardInputCallback: this.config.enableMarkdownInComments ? this.commentKeyboardHandler.bind(this) : null,
100
+ autoSizeCallback: this.autoSizeComment.bind(this),
101
+ saveTextChangesCallback: this.saveCommentChanges.bind(this),
102
+ closeTextAreaCallback: this.closeCommentTextArea.bind(this)
103
+ };
104
+ this.displayTextArea(this.editingTextData);
105
+
106
+ if (this.config.enableMarkdownInComments && this.dispUtils.isDisplayingFullPage()) {
107
+ const pos = this.getCommentToolbarPosCallback(d);
108
+ this.canvasController.openTextToolbar(pos.x, pos.y,
109
+ this.markdownActionHandler.bind(this),
110
+ this.blurInTextToolbar.bind(this));
111
+ }
112
+ }
113
+
114
+ // Handles markdown actions initiated through the keyboard.
115
+ commentKeyboardHandler(d3Event) {
116
+ const action = this.getMarkdownAction(d3Event);
117
+ if (action) {
118
+ if (action !== "return") {
119
+ CanvasUtils.stopPropagationAndPreventDefault(d3Event);
120
+ }
121
+ this.markdownActionHandler(action, d3Event);
122
+ }
123
+ }
124
+
125
+ // Called when the blur event occurs for the text toolbar.
126
+ blurInTextToolbar(evt) {
127
+ // When Cypress tests are running a call to focus() in addTextToTextArea()
128
+ // can cause an incorrect blur event to be generated for the text toolbar
129
+ // (where relatedTarget is null). This flag therefore allows us to avoid
130
+ // thus blue events that occur while addTextToTextArea() is executing.
131
+ if (this.addingTextToTextArea) {
132
+ return;
133
+ }
134
+
135
+ // If there is a relatedTarget and it is set to one of the elements for the
136
+ // textarea, texttoolbar, etc we ignore the blur event.
137
+ if (evt.relatedTarget &&
138
+ (CanvasUtils.getParentElementWithClass(evt.relatedTarget, "d3-comment-entry") ||
139
+ CanvasUtils.getParentElementWithClass(evt.relatedTarget, "text-toolbar") ||
140
+ CanvasUtils.getParentElementWithClass(evt.relatedTarget, "bx--overflow-menu-options__btn"))) {
141
+ return;
142
+ }
143
+
144
+ // If the blur event is ocurring for an object outside of the textarea and
145
+ // text toolbar we save the current text and close the textarea.
146
+ const commentParent = d3.select(this.editingTextData.parentDomObj);
147
+ const foreignObject = commentParent.selectAll(".d3-foreign-object-text-entry");
148
+ const commentEntry = this.canvasDiv.selectAll(".d3-comment-entry");
149
+ const commentEntryElement = commentEntry.node();
150
+ this.saveAndCloseTextArea(foreignObject, this.editingTextData, commentEntryElement.value, evt);
151
+ }
152
+
153
+ // Applies a markdown action to the comment text being edited using
154
+ // the same commands as the toolbar.
155
+ getMarkdownAction(d3Event) {
156
+ if (CanvasUtils.isCmndCtrlPressed(d3Event)) {
157
+ switch (d3Event.keyCode) {
158
+ case B_KEY: return "bold";
159
+ case I_KEY: return "italics";
160
+ case X_KEY: return d3Event.shiftKey ? "strikethrough" : null;
161
+ case SEVEN_KEY: return d3Event.shiftKey ? "numberedList" : null;
162
+ case EIGHT_KEY: return d3Event.shiftKey ? "bulletedList" : null;
163
+ case E_KEY: return "code";
164
+ case K_KEY: return "link";
165
+ case LAB_KEY: return "decreaseHashes";
166
+ case RAB_KEY: return d3Event.shiftKey ? "quote" : "increaseHashes";
167
+ default:
168
+ }
169
+ } else if (d3Event.keyCode === RETURN_KEY) {
170
+ return "return";
171
+ }
172
+
173
+ return null;
174
+ }
175
+
176
+ // Handles any actions requested on the comment text to add markdown
177
+ // characters to the text. evt can be either a d3Event object from D3 when
178
+ // this method is called from keyboard entry in the textarea or it can be
179
+ // a synthetic event object from React when called from the text toolbar.
180
+ markdownActionHandler(action, evt) {
181
+ this.logger.log("markdownActionHandler - action = " + action);
182
+
183
+ const commentEntry = this.canvasDiv.selectAll(".d3-comment-entry");
184
+ const commentEntryElement = commentEntry.node();
185
+ const start = commentEntryElement.selectionStart;
186
+ const end = commentEntryElement.selectionEnd;
187
+ const text = commentEntryElement.value;
188
+
189
+ const mdObj = SvgCanvasMarkdown.processMarkdownAction(action, text, start, end);
190
+ if (mdObj) {
191
+ CanvasUtils.stopPropagationAndPreventDefault(evt);
192
+ this.addTextToTextArea(mdObj, commentEntryElement);
193
+ }
194
+ }
195
+
196
+ // Replaces the text in the currently displayed textarea with the text
197
+ // passed in. We use execCommand because this adds the inserted text to the
198
+ // textarea's undo/redo stack whereas setting the text directly into the
199
+ // textarea control does not.
200
+ addTextToTextArea(mdObj, commentEntryElement) {
201
+ this.addingTextToTextArea = true;
202
+ const text = unescapeText(mdObj.newText);
203
+ commentEntryElement.focus();
204
+ commentEntryElement.select();
205
+ document.execCommand("insertText", false, text);
206
+ commentEntryElement.setSelectionRange(mdObj.newStart, mdObj.newEnd);
207
+ this.addingTextToTextArea = false;
208
+ }
209
+
210
+ autoSizeComment(textArea, foreignObject, data) {
211
+ this.logger.log("autoSizeComment - textAreaHt = " + this.textAreaHeight + " scroll ht = " + textArea.scrollHeight);
212
+
213
+ const scrollHeight = textArea.scrollHeight + SCROLL_PADDING;
214
+ if (this.textAreaHeight < scrollHeight) {
215
+ this.textAreaHeight = scrollHeight;
216
+ foreignObject.style("height", this.textAreaHeight + "px");
217
+ this.activePipeline.getComment(data.id).height = this.textAreaHeight;
218
+ this.displayCommentsCallback();
219
+ this.displayLinksCallback();
220
+ }
221
+ }
222
+
223
+ saveCommentChanges(id, newText, newHeight) {
224
+ const comment = this.activePipeline.getComment(id);
225
+ const data = {
226
+ editType: "editComment",
227
+ editSource: "canvas",
228
+ id: comment.id,
229
+ content: newText,
230
+ width: comment.width,
231
+ height: newHeight,
232
+ x_pos: comment.x_pos,
233
+ y_pos: comment.y_pos,
234
+ pipelineId: this.activePipeline.id
235
+ };
236
+ this.canvasController.editActionHandler(data);
237
+ }
238
+
239
+ closeCommentTextArea() {
240
+ this.canvasController.closeTextToolbar();
241
+ }
242
+
243
+ displayNodeLabelTextArea(node, parentDomObj) {
244
+ d3.select(parentDomObj)
245
+ .selectAll("div")
246
+ .attr("style", "display:none;");
247
+
248
+ this.editingTextData = {
249
+ id: node.id,
250
+ text: node.label,
251
+ singleLine: node.layout.labelSingleLine,
252
+ maxCharacters: node.layout.labelMaxCharacters,
253
+ allowReturnKey: node.layout.labelAllowReturnKey,
254
+ textCanBeEmpty: false,
255
+ xPos: this.nodeUtils.getNodeLabelTextAreaPosX(node),
256
+ yPos: this.nodeUtils.getNodeLabelTextAreaPosY(node),
257
+ width: this.nodeUtils.getNodeLabelTextAreaWidth(node),
258
+ height: this.nodeUtils.getNodeLabelTextAreaHeight(node),
259
+ className: this.nodeUtils.getNodeLabelTextAreaClass(node),
260
+ parentDomObj: parentDomObj,
261
+ autoSizeCallback: this.autoSizeMultiLineLabel.bind(this),
262
+ saveTextChangesCallback: this.saveNodeLabelChanges.bind(this),
263
+ closeTextAreaCallback: this.closeNodeLabelTextArea.bind(this)
264
+ };
265
+ this.displayTextArea(this.editingTextData);
266
+ }
267
+
268
+ // Increases the size of the editable multi-line text area for a label based
269
+ // on the characters entered, and also ensures the maximum number of
270
+ // characters for the label, if one is provided, is not exceeded.
271
+ // This callback works for editable multi-line node labels and also
272
+ // editable multi-line text decorations for either nodes or links.
273
+ autoSizeMultiLineLabel(textArea, foreignObject, data) {
274
+ this.logger.log("autoSizeNodeLabel - textAreaHt = " + this.textAreaHeight + " scroll ht = " + textArea.scrollHeight);
275
+
276
+ // Restrict max characters in case text was pasted in to the text area.
277
+ if (data.maxCharacters &&
278
+ textArea.value.length > data.maxCharacters) {
279
+ textArea.value = textArea.value.substring(0, data.maxCharacters);
280
+ }
281
+ // Temporarily set the height to zero so the scrollHeight will get set to
282
+ // the full height of the text in the textarea. This allows us to close up
283
+ // the text area when the lines of text reduce.
284
+ foreignObject.style("height", 0);
285
+ const scrollHeight = textArea.scrollHeight + SCROLL_PADDING;
286
+ this.textAreaHeight = scrollHeight;
287
+ foreignObject.style("height", this.textAreaHeight + "px");
288
+ }
289
+
290
+ saveNodeLabelChanges(id, newText, newHeight, taData) {
291
+ const data = {
292
+ editType: "setNodeLabel",
293
+ editSource: "canvas",
294
+ nodeId: id,
295
+ label: newText,
296
+ pipelineId: this.activePipeline.id
297
+ };
298
+ this.canvasController.editActionHandler(data);
299
+ }
300
+
301
+ // Called when the node label text area is closed. Sets the style of the
302
+ // div for the node label so the label is displayed (because it was hidden
303
+ // when the text area opened).
304
+ closeNodeLabelTextArea(nodeId) {
305
+ d3.select(this.editingTextData.parentDomObj)
306
+ .selectAll("div")
307
+ .attr("style", null);
308
+ }
309
+
310
+ // Displays a text area for an editable text decoration on either a node
311
+ // or link.
312
+ displayDecLabelTextArea(dec, obj, objType, parentDomObj) {
313
+ this.displayTextArea({
314
+ id: dec.id,
315
+ text: dec.label,
316
+ singleLine: dec.label_single_line || false,
317
+ maxCharacters: dec.label_max_characters || null,
318
+ allowReturnKey: dec.label_allow_return_key || false,
319
+ textCanBeEmpty: false,
320
+ xPos: this.decUtils.getDecLabelTextAreaPosX(),
321
+ yPos: this.decUtils.getDecLabelTextAreaPosY(),
322
+ width: this.decUtils.getDecLabelTextAreaWidth(dec, obj, objType),
323
+ height: this.decUtils.getDecLabelTextAreaHeight(dec, obj, objType),
324
+ className: this.decUtils.getDecLabelTextAreaClass(dec),
325
+ parentDomObj: parentDomObj,
326
+ objId: obj.id,
327
+ objType: objType,
328
+ autoSizeCallback: this.autoSizeMultiLineLabel.bind(this),
329
+ saveTextChangesCallback: this.saveDecLabelChanges.bind(this),
330
+ closeTextAreaCallback: null
331
+ });
332
+ }
333
+
334
+ // Handles saved changes to editable text decorations.
335
+ saveDecLabelChanges(id, newText, newHeight, taData) {
336
+ const data = {
337
+ editType: "editDecorationLabel",
338
+ editSource: "canvas",
339
+ decId: id,
340
+ objId: taData.objId,
341
+ objType: taData.objType,
342
+ label: newText,
343
+ pipelineId: this.activePipeline.id
344
+ };
345
+ this.canvasController.editActionHandler(data);
346
+ }
347
+
348
+ // Displays a text area to allow text entry and editing for: comments;
349
+ // node labels; or text decorations on either a node or link.
350
+ displayTextArea(data) {
351
+ this.textAreaHeight = data.height; // Save for comparison during auto-resize
352
+ this.editingText = true;
353
+ this.editingTextId = data.id;
354
+
355
+ const foreignObject = d3.select(data.parentDomObj)
356
+ .append("foreignObject")
357
+ .attr("class", "d3-foreign-object-text-entry")
358
+ .attr("width", data.width)
359
+ .attr("height", data.height)
360
+ .attr("x", data.xPos)
361
+ .attr("y", data.yPos);
362
+
363
+ const textArea = foreignObject
364
+ .append("xhtml:textarea")
365
+ .attr("class", data.className)
366
+ .text(unescapeText(data.text))
367
+ .on("keydown", (d3Event) => {
368
+ // Don't accept return key press when text is all on one line or
369
+ // if application doesn't want line feeds inserted in the label.
370
+ if ((data.singleLine || !data.allowReturnKey) &&
371
+ d3Event.keyCode === RETURN_KEY) {
372
+ CanvasUtils.stopPropagationAndPreventDefault(d3Event);
373
+ }
374
+ // If user presses ESC key revert back to original text by just
375
+ // closing the text area.
376
+ if (d3Event.keyCode === ESC_KEY) {
377
+ CanvasUtils.stopPropagationAndPreventDefault(d3Event);
378
+ this.textAreaEscKeyPressed = true;
379
+ this.closeTextArea(foreignObject, data);
380
+ }
381
+ // Prevent user entering more than any allowed maximum for characters.
382
+ if (data.maxCharacters &&
383
+ d3Event.target.value.length >= data.maxCharacters &&
384
+ !this.textAreaAllowedKeys(d3Event)) {
385
+ CanvasUtils.stopPropagationAndPreventDefault(d3Event);
386
+ }
387
+ // Call any specific keyboard handler for the type of
388
+ // text being edited.
389
+ if (data.keyboardInputCallback) {
390
+ data.keyboardInputCallback(d3Event);
391
+ }
392
+ })
393
+ .on("keyup", (d3Event) => {
394
+ data.autoSizeCallback(d3Event.target, foreignObject, data);
395
+ })
396
+ .on("paste", (d3Event) => {
397
+ this.logger.log("Text area - Paste - Scroll Ht = " + d3Event.target.scrollHeight);
398
+ // Allow some time for pasted text (from context menu) to be
399
+ // loaded into the text area. Otherwise the text is not there
400
+ // and the auto size does not increase the height correctly.
401
+ setTimeout(data.autoSizeCallback, 500, d3Event.target, foreignObject, data);
402
+ })
403
+ .on("blur", (d3Event, d) => {
404
+ this.logger.log("Text area - blur");
405
+ // If the esc key was pressed to cause the blur event just return
406
+ // so label returns to what it was before editing started.
407
+ if (this.textAreaEscKeyPressed) {
408
+ this.textAreaEscKeyPressed = false;
409
+ return;
410
+ }
411
+
412
+ // If the user clicked on an element in the text toolbar to cause the
413
+ // blur event, just return.
414
+ if (d3Event.relatedTarget && CanvasUtils.getParentElementWithClass(d3Event.relatedTarget, "text-toolbar")) {
415
+ return;
416
+ }
417
+
418
+ this.saveAndCloseTextArea(foreignObject, data, d3Event.target.value, d3Event);
419
+ })
420
+ .on("focus", (d3Event, d) => {
421
+ this.logger.log("Text area - focus");
422
+ data.autoSizeCallback(d3Event.target, foreignObject, data);
423
+ })
424
+ .on("mousedown click dblclick contextmenu", (d3Event, d) => {
425
+ d3Event.stopPropagation(); // Allow default behavior to show system contenxt menu
426
+ });
427
+
428
+ textArea.node().focus();
429
+
430
+ // Set the cusrsor to the end of the text.
431
+ textArea.node().setSelectionRange(data.text.length, data.text.length);
432
+ }
433
+
434
+ saveAndCloseTextArea(foreignObject, data, newValue, d3Event) {
435
+ // If there is no text for the label and textCanBeEmpty is false
436
+ // just return, so label returns to what it was before editing started.
437
+ if (!newValue && !data.textCanBeEmpty) {
438
+ CanvasUtils.stopPropagationAndPreventDefault(d3Event);
439
+ this.closeTextArea(foreignObject, data);
440
+ return;
441
+ }
442
+ const newText = newValue; // Save the text before closing the foreign object
443
+ this.closeTextArea(foreignObject, data);
444
+ if (data.text !== newText || this.textAreaHeight !== data.height) {
445
+ this.isCommentBeingUpdated = true;
446
+ data.saveTextChangesCallback(data.id, newText, this.textAreaHeight, data);
447
+ this.isCommentBeingUpdatd = false;
448
+ }
449
+ }
450
+
451
+ // Closes the text area and resets the flags.
452
+ closeTextArea(foreignObject, data) {
453
+ if (data.closeTextAreaCallback) {
454
+ data.closeTextAreaCallback(data.id);
455
+ }
456
+ foreignObject.remove();
457
+ this.editingText = false;
458
+ this.editingTextId = "";
459
+ }
460
+
461
+ // Returns true if one of the keys that are allowed in the text area, when
462
+ // checking for maximum characters, has been pressed.
463
+ textAreaAllowedKeys(d3Event) {
464
+ return d3Event.keyCode === DELETE_KEY ||
465
+ d3Event.keyCode === BACKSPACE_KEY ||
466
+ d3Event.keyCode === LEFT_ARROW_KEY ||
467
+ d3Event.keyCode === RIGHT_ARROW_KEY ||
468
+ d3Event.keyCode === UP_ARROW_KEY ||
469
+ d3Event.keyCode === DOWN_ARROW_KEY ||
470
+ (d3Event.keyCode === A_KEY && CanvasUtils.isCmndCtrlPressed(d3Event));
471
+ }
472
+ }
@@ -52,7 +52,7 @@
52
52
  }
53
53
  }
54
54
 
55
- .properties-label-container, .properties-summary-link-container {
55
+ .properties-label-container, .properties-summary-link-container, .properties-checkbox-tooltip-container, .properties-radioset-panel {
56
56
  .tooltip-container {
57
57
  display: flex;
58
58
  width: 16px;
@@ -25,7 +25,7 @@ import VirtualizedTable from "./../virtualized-table/virtualized-table.jsx";
25
25
  import { SORT_DIRECTION, STATES, ROW_HEIGHT, ROW_SELECTION } from "./../../constants/constants";
26
26
  import ReactResizeDetector from "react-resize-detector";
27
27
  import classNames from "classnames";
28
- import { has } from "lodash";
28
+ import { has, isEmpty } from "lodash";
29
29
  import defaultMessages from "../../../../locales/common-properties/locales/en.json";
30
30
 
31
31
  class FlexibleTable extends React.Component {
@@ -79,7 +79,7 @@ class FlexibleTable extends React.Component {
79
79
  }
80
80
 
81
81
  // Calculate if checkedAllRows is true
82
- if (this.props.selectedRows) {
82
+ if (this.props.selectedRows && !isEmpty(this.props.data)) {
83
83
  this.setCheckedAll(this.props.selectedRows);
84
84
  }
85
85
 
@@ -506,6 +506,14 @@ class FlexibleTable extends React.Component {
506
506
  </div>)
507
507
  : null;
508
508
 
509
+ const emptyTableContent = isEmpty(this.props.data)
510
+ ? (
511
+ <div className="properties-ft-empty-table">
512
+ {this.props.emptyTablePlaceholder}
513
+ </div>
514
+ )
515
+ : null;
516
+
509
517
  return (
510
518
  <div data-id={"properties-ft-" + this.props.scrollKey} className="properties-ft-control-container" ref={ (ref) => (this.flexibleTable = ref) }>
511
519
  {ftHeader}
@@ -543,6 +551,7 @@ class FlexibleTable extends React.Component {
543
551
  </div>
544
552
  </ReactResizeDetector>
545
553
  </div>
554
+ {emptyTableContent}
546
555
  </div>
547
556
  );
548
557
  }
@@ -550,13 +559,15 @@ class FlexibleTable extends React.Component {
550
559
 
551
560
  FlexibleTable.defaultProps = {
552
561
  showHeader: true,
553
- light: true
562
+ light: true,
563
+ emptyTablePlaceholder: ""
554
564
  };
555
565
 
556
566
  FlexibleTable.propTypes = {
557
567
  sortable: PropTypes.array,
558
568
  columns: PropTypes.array.isRequired,
559
569
  data: PropTypes.array.isRequired,
570
+ emptyTablePlaceholder: PropTypes.string,
560
571
  filterable: PropTypes.array,
561
572
  filterBy: PropTypes.string,
562
573
  filterKeyword: PropTypes.string,
@@ -128,3 +128,23 @@ $row-left-padding: $spacing-02;
128
128
  }
129
129
  }
130
130
  }
131
+
132
+ .properties-ft-empty-table {
133
+ height: calc($spacing-11 + $spacing-08);
134
+ display: flex;
135
+ justify-content: center;
136
+ align-items: center;
137
+ @include carbon--type-style("body-long-01");
138
+ }
139
+
140
+ .properties-light-enabled {
141
+ .properties-ft-empty-table {
142
+ background-color: $ui-background;
143
+ }
144
+ }
145
+
146
+ .properties-light-disabled {
147
+ .properties-ft-empty-table {
148
+ background-color: $ui-01;
149
+ }
150
+ }
@@ -24,7 +24,7 @@ import { TextInput, Button } from "carbon-components-react";
24
24
  import { MESSAGE_KEYS, CONDITION_MESSAGE_TYPE } from "./../../constants/constants";
25
25
  import * as PropertyUtils from "./../../util/property-utils";
26
26
  import classNames from "classnames";
27
- import { Information16, Edit16, Close16 } from "@carbon/icons-react";
27
+ import { Help16, Edit16, Close16 } from "@carbon/icons-react";
28
28
 
29
29
 
30
30
  class TitleEditor extends Component {
@@ -121,7 +121,7 @@ class TitleEditor extends Component {
121
121
  data-id="help"
122
122
  onClick={this.helpClickHandler}
123
123
  tooltipPosition="bottom"
124
- renderIcon={Information16}
124
+ renderIcon={Help16}
125
125
  size="small"
126
126
  iconDescription={helpButtonLabel}
127
127
  hasIconOnly
@@ -34,7 +34,7 @@
34
34
  }
35
35
  .properties-title-editor-btn.help {
36
36
  &.help {
37
- margin: 0 0 0 $spacing-02; // spacing between heading label and help button
37
+ margin-left: $spacing-02; // spacing between heading label and help button
38
38
  }
39
39
  }
40
40
  }
@@ -84,21 +84,6 @@
84
84
  width: calc(100% - 2px); // subtract 2px for input active right border
85
85
  }
86
86
 
87
- .properties-title-editor-btn.help, .properties-title-editor-btn.edit {
88
- fill: $icon-02;
89
- // edit & help buttons size - 32x32
90
- width: $spacing-07;
91
- min-height: $spacing-07;
92
- padding-left: $spacing-04;
93
- padding-right: $spacing-04;
94
- &:hover {
95
- background-color: $ui-03;
96
- }
97
- &:active {
98
- background-color: $ui-03;
99
- }
100
- }
101
-
102
87
  // Close icon without heading
103
88
  .properties-close-button {
104
89
  position: relative;
@@ -458,6 +458,7 @@ export default class AbstractTable extends React.Component {
458
458
  summaryTable
459
459
  rowSelection={ROW_SELECTION.MULTIPLE}
460
460
  light={this.props.controller.getLight()}
461
+ emptyTablePlaceholder={this.props.control.additionalText}
461
462
  />
462
463
  </div>);
463
464
  }
@@ -677,6 +678,7 @@ export default class AbstractTable extends React.Component {
677
678
  selectedRows= {this.props.selectedRows}
678
679
  rowSelection={this.props.control.rowSelection}
679
680
  light={this.props.controller.getLight()}
681
+ emptyTablePlaceholder={this.props.control.additionalText}
680
682
  />);
681
683
  return (
682
684
  <div>
@@ -25,7 +25,7 @@ import { STATES, CARBON_ICONS } from "./../../constants/constants.js";
25
25
  import Tooltip from "./../../../tooltip/tooltip.jsx";
26
26
  import { v4 as uuid4 } from "uuid";
27
27
  import classNames from "classnames";
28
- import Icon from "./../../../icons/icon.jsx";
28
+ import Icon from "./../../../icons/icon";
29
29
 
30
30
  class CheckboxControl extends React.Component {
31
31