@elyra/canvas 12.11.0 → 12.12.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 (166) hide show
  1. package/dist/_baseForOwn-7d4e8506.js +2 -0
  2. package/dist/_baseForOwn-7d4e8506.js.map +1 -0
  3. package/dist/_baseForOwn-d38b560e.js +2 -0
  4. package/dist/_baseForOwn-d38b560e.js.map +1 -0
  5. package/dist/canvas-constants-34cdb7df.js +2 -0
  6. package/dist/canvas-constants-34cdb7df.js.map +1 -0
  7. package/dist/canvas-constants-3c09c7f6.js +2 -0
  8. package/dist/canvas-constants-3c09c7f6.js.map +1 -0
  9. package/dist/canvas-controller-d9da9919.js +2 -0
  10. package/dist/canvas-controller-d9da9919.js.map +1 -0
  11. package/dist/canvas-controller-e023521c.js +2 -0
  12. package/dist/canvas-controller-e023521c.js.map +1 -0
  13. package/dist/canvas-logger-815781bb.js.map +1 -1
  14. package/dist/canvas-logger-a0f1beaa.js.map +1 -1
  15. package/dist/common-canvas-3c5daa65.js +2 -0
  16. package/dist/common-canvas-3c5daa65.js.map +1 -0
  17. package/dist/common-canvas-bdfb8c87.js +2 -0
  18. package/dist/common-canvas-bdfb8c87.js.map +1 -0
  19. package/dist/common-canvas.es.js +1 -1
  20. package/dist/common-canvas.es.js.map +1 -1
  21. package/dist/common-canvas.js +1 -1
  22. package/dist/common-canvas.js.map +1 -1
  23. package/dist/common-properties-8727d6f9.js +2 -0
  24. package/dist/common-properties-8727d6f9.js.map +1 -0
  25. package/dist/common-properties-87fef545.js +2 -0
  26. package/dist/common-properties-87fef545.js.map +1 -0
  27. package/dist/{datarecord-metadata-v3-schema-d7ad05cd.js → datarecord-metadata-v3-schema-6b6384ff.js} +2 -2
  28. package/dist/{datarecord-metadata-v3-schema-d7ad05cd.js.map → datarecord-metadata-v3-schema-6b6384ff.js.map} +1 -1
  29. package/dist/{datarecord-metadata-v3-schema-bda88f2e.js → datarecord-metadata-v3-schema-81228a9a.js} +2 -2
  30. package/dist/{datarecord-metadata-v3-schema-bda88f2e.js.map → datarecord-metadata-v3-schema-81228a9a.js.map} +1 -1
  31. package/dist/en-7a0f1db1.js +2 -0
  32. package/dist/en-7a0f1db1.js.map +1 -0
  33. package/dist/en-8647c347.js +2 -0
  34. package/dist/en-8647c347.js.map +1 -0
  35. package/dist/{extends-39f57612.js → extends-cf86ca1c.js} +2 -2
  36. package/dist/{extends-39f57612.js.map → extends-cf86ca1c.js.map} +1 -1
  37. package/dist/extends-e9462902.js +7 -0
  38. package/dist/{extends-51d9ddcc.js.map → extends-e9462902.js.map} +1 -1
  39. package/dist/flexible-table-d4a68ebb.js +2 -0
  40. package/dist/flexible-table-d4a68ebb.js.map +1 -0
  41. package/dist/flexible-table-f0c164d2.js +2 -0
  42. package/dist/flexible-table-f0c164d2.js.map +1 -0
  43. package/dist/{icon-d6909a68.js → icon-c85b53bd.js} +2 -2
  44. package/dist/{icon-d6909a68.js.map → icon-c85b53bd.js.map} +1 -1
  45. package/dist/{icon-811ffddd.js → icon-caf4caca.js} +2 -2
  46. package/dist/{icon-811ffddd.js.map → icon-caf4caca.js.map} +1 -1
  47. package/dist/index-beefcd21.js +2 -0
  48. package/dist/index-beefcd21.js.map +1 -0
  49. package/dist/index-fb90b885.js +2 -0
  50. package/dist/index-fb90b885.js.map +1 -0
  51. package/dist/isArrayLikeObject-a9c7973b.js +2 -0
  52. package/dist/isArrayLikeObject-a9c7973b.js.map +1 -0
  53. package/dist/isArrayLikeObject-f3b27f64.js +2 -0
  54. package/dist/isArrayLikeObject-f3b27f64.js.map +1 -0
  55. package/dist/lib/canvas-controller.es.js +1 -1
  56. package/dist/lib/canvas-controller.js +1 -1
  57. package/dist/lib/canvas.es.js +1 -1
  58. package/dist/lib/canvas.js +1 -1
  59. package/dist/lib/command-stack.es.js +1 -1
  60. package/dist/lib/command-stack.es.js.map +1 -1
  61. package/dist/lib/command-stack.js +1 -1
  62. package/dist/lib/command-stack.js.map +1 -1
  63. package/dist/lib/context-menu.es.js +1 -1
  64. package/dist/lib/context-menu.es.js.map +1 -1
  65. package/dist/lib/context-menu.js +1 -1
  66. package/dist/lib/context-menu.js.map +1 -1
  67. package/dist/lib/properties/field-picker.es.js +1 -1
  68. package/dist/lib/properties/field-picker.js +1 -1
  69. package/dist/lib/properties/flexible-table.es.js +1 -1
  70. package/dist/lib/properties/flexible-table.js +1 -1
  71. package/dist/lib/properties.es.js +1 -1
  72. package/dist/lib/properties.js +1 -1
  73. package/dist/lib/tooltip.es.js +1 -1
  74. package/dist/lib/tooltip.es.js.map +1 -1
  75. package/dist/lib/tooltip.js +1 -1
  76. package/dist/lib/tooltip.js.map +1 -1
  77. package/dist/styles/common-canvas.min.css +1 -1
  78. package/dist/styles/common-canvas.min.css.map +1 -1
  79. package/dist/{toolbar-335252dd.js → toolbar-a5ec3435.js} +2 -2
  80. package/dist/{toolbar-85e6c77b.js.map → toolbar-a5ec3435.js.map} +1 -1
  81. package/dist/{toolbar-85e6c77b.js → toolbar-cca1d9a9.js} +2 -2
  82. package/dist/{toolbar-335252dd.js.map → toolbar-cca1d9a9.js.map} +1 -1
  83. package/locales/command-actions/locales/en.json +8 -8
  84. package/locales/command-actions/locales/eo.json +8 -8
  85. package/locales/common-canvas/locales/en.json +3 -1
  86. package/locales/common-canvas/locales/eo.json +2 -0
  87. package/package.json +9 -10
  88. package/src/command-actions/sizeAndPositionObjectsAction.js +5 -0
  89. package/src/command-stack/command-stack.js +16 -30
  90. package/src/command-stack/internal-stack.js +89 -0
  91. package/src/common-canvas/canvas-controller.js +41 -4
  92. package/src/common-canvas/cc-contents.jsx +6 -1
  93. package/src/common-canvas/cc-toolbar.jsx +14 -4
  94. package/src/common-canvas/common-canvas-utils.js +89 -13
  95. package/src/common-canvas/common-canvas.scss +3 -1
  96. package/src/common-canvas/constants/canvas-constants.js +12 -0
  97. package/src/common-canvas/svg-canvas-d3.js +8 -0
  98. package/src/common-canvas/svg-canvas-renderer.js +497 -287
  99. package/src/common-canvas/svg-canvas-utils-links.js +61 -26
  100. package/src/common-canvas/svg-canvas-utils-nodes.js +0 -10
  101. package/src/common-properties/actions/button/button.jsx +45 -13
  102. package/src/common-properties/actions/button/button.scss +4 -8
  103. package/src/common-properties/common-properties.jsx +2 -1
  104. package/src/common-properties/components/control-item/control-item.jsx +7 -1
  105. package/src/common-properties/components/field-picker/field-picker.jsx +7 -8
  106. package/src/common-properties/components/flexible-table/flexible-table.jsx +45 -10
  107. package/src/common-properties/components/virtualized-table/virtualized-table.jsx +72 -20
  108. package/src/common-properties/constants/constants.js +18 -0
  109. package/src/common-properties/controls/abstract-table.jsx +3 -3
  110. package/src/common-properties/controls/checkbox/checkbox.jsx +6 -0
  111. package/src/common-properties/controls/expression/expression-builder/expression-select-field-function.jsx +4 -2
  112. package/src/common-properties/controls/expression/expression.jsx +1 -1
  113. package/src/common-properties/controls/expression/expression.scss +3 -1
  114. package/src/common-properties/controls/multiselect/multiselect.jsx +4 -4
  115. package/src/common-properties/controls/someofselect/someofselect.jsx +1 -1
  116. package/src/common-properties/form/ActionInfo.js +3 -1
  117. package/src/common-properties/form/EditorForm.js +7 -3
  118. package/src/common-properties/properties-controller.js +2 -1
  119. package/src/common-properties/properties-main/properties-main.jsx +4 -2
  120. package/src/common-properties/util/L10nProvider.js +3 -0
  121. package/src/object-model/api-pipeline.js +1 -5
  122. package/src/object-model/config-utils.js +1 -0
  123. package/src/object-model/object-model.js +61 -12
  124. package/src/object-model/pipeline-in-handler.js +5 -0
  125. package/src/object-model/pipeline-out-handler.js +5 -0
  126. package/src/object-model/redux/canvas-store.js +16 -0
  127. package/src/object-model/redux/reducers/canvasinfo.js +12 -8
  128. package/src/object-model/redux/reducers/canvastoolbar.js +3 -0
  129. package/src/object-model/redux/reducers/nodes.js +11 -0
  130. package/src/toolbar/toolbar-action-item.jsx +2 -2
  131. package/src/tooltip/tooltip.jsx +30 -1
  132. package/src/tooltip/tooltip.scss +11 -0
  133. package/stats.html +1 -1
  134. package/dist/canvas-constants-7f93e705.js +0 -2
  135. package/dist/canvas-constants-7f93e705.js.map +0 -1
  136. package/dist/canvas-constants-ac5daafb.js +0 -2
  137. package/dist/canvas-constants-ac5daafb.js.map +0 -1
  138. package/dist/canvas-controller-183ff6a7.js +0 -2
  139. package/dist/canvas-controller-183ff6a7.js.map +0 -1
  140. package/dist/canvas-controller-d70a731e.js +0 -2
  141. package/dist/canvas-controller-d70a731e.js.map +0 -1
  142. package/dist/common-canvas-3e832a84.js +0 -2
  143. package/dist/common-canvas-3e832a84.js.map +0 -1
  144. package/dist/common-canvas-c50cb3f3.js +0 -2
  145. package/dist/common-canvas-c50cb3f3.js.map +0 -1
  146. package/dist/common-properties-4f471b2b.js +0 -2
  147. package/dist/common-properties-4f471b2b.js.map +0 -1
  148. package/dist/common-properties-9161cd27.js +0 -2
  149. package/dist/common-properties-9161cd27.js.map +0 -1
  150. package/dist/en-2ed89528.js +0 -2
  151. package/dist/en-2ed89528.js.map +0 -1
  152. package/dist/en-e93855cc.js +0 -2
  153. package/dist/en-e93855cc.js.map +0 -1
  154. package/dist/extends-51d9ddcc.js +0 -7
  155. package/dist/flexible-table-154a3359.js +0 -2
  156. package/dist/flexible-table-154a3359.js.map +0 -1
  157. package/dist/flexible-table-5e4a1e6d.js +0 -2
  158. package/dist/flexible-table-5e4a1e6d.js.map +0 -1
  159. package/dist/index-4fd90a14.js +0 -2
  160. package/dist/index-4fd90a14.js.map +0 -1
  161. package/dist/index-6d138021.js +0 -2
  162. package/dist/index-6d138021.js.map +0 -1
  163. package/dist/isArrayLikeObject-31e5e646.js +0 -2
  164. package/dist/isArrayLikeObject-31e5e646.js.map +0 -1
  165. package/dist/isArrayLikeObject-7c33c7fd.js +0 -2
  166. package/dist/isArrayLikeObject-7c33c7fd.js.map +0 -1
@@ -20,7 +20,8 @@ import CanvasUtils from "./common-canvas-utils.js";
20
20
  import { ASSOC_RIGHT_SIDE_CURVE, ASSOCIATION_LINK, COMMENT_LINK, NODE_LINK,
21
21
  ASSOC_VAR_CURVE_LEFT, ASSOC_VAR_CURVE_RIGHT, ASSOC_VAR_DOUBLE_BACK_LEFT, ASSOC_VAR_DOUBLE_BACK_RIGHT,
22
22
  LINK_TYPE_CURVE, LINK_TYPE_ELBOW, LINK_TYPE_STRAIGHT,
23
- LINK_DIR_TOP_BOTTOM, LINK_DIR_BOTTOM_TOP }
23
+ LINK_DIR_TOP_BOTTOM, LINK_DIR_BOTTOM_TOP,
24
+ NORTH, SOUTH, EAST, WEST }
24
25
  from "./constants/canvas-constants";
25
26
 
26
27
  const CLOCKWISE = false;
@@ -53,27 +54,32 @@ export default class SvgCanvasLinks {
53
54
 
54
55
  // Returns an object containing the x and y coordinates of the start position
55
56
  // of a straight line which extends from the node passed in to the
56
- // end position which is also an x, y coordinate.
57
- getNewStraightNodeLinkStartPos(srcNode, endPos) {
58
- let srcCenterX;
59
- let srcCenterY;
60
-
61
- if (srcNode.layout.drawNodeLinkLineFromTo === "image_center" && !CanvasUtils.isExpanded(srcNode)) {
62
- srcCenterX = this.nodeUtils.getNodeImageCenterPosX(srcNode);
63
- srcCenterY = this.nodeUtils.getNodeImageCenterPosY(srcNode);
57
+ // end position which is also an x, y coordinate. If an originInfo object is
58
+ // passed in we use it to offset the origin position for the line.
59
+ getNewStraightNodeLinkStartPos(node, endPos, originInfo) {
60
+ let originX;
61
+ let originY;
62
+
63
+ if (node.layout.drawNodeLinkLineFromTo === "image_center" && !CanvasUtils.isExpanded(node)) {
64
+ originX = this.nodeUtils.getNodeImageCenterPosX(node);
65
+ originY = this.nodeUtils.getNodeImageCenterPosY(node);
64
66
  } else {
65
- srcCenterX = this.nodeUtils.getNodeCenterPosX(srcNode);
66
- srcCenterY = this.nodeUtils.getNodeCenterPosY(srcNode);
67
+ if (originInfo) {
68
+ ({ x: originX, y: originY } = this.getCenterOffset(node, originInfo));
69
+ } else {
70
+ originX = this.nodeUtils.getNodeCenterPosX(node);
71
+ originY = this.nodeUtils.getNodeCenterPosY(node);
72
+ }
67
73
  }
68
74
 
69
75
  return CanvasUtils.getOuterCoord(
70
- srcNode.x_pos,
71
- srcNode.y_pos,
72
- srcNode.width,
73
- srcNode.height,
76
+ node.x_pos,
77
+ node.y_pos,
78
+ node.width,
79
+ node.height,
74
80
  this.canvasLayout.linkGap,
75
- srcCenterX,
76
- srcCenterY,
81
+ originX,
82
+ originY,
77
83
  endPos.x,
78
84
  endPos.y);
79
85
  }
@@ -134,15 +140,15 @@ export default class SvgCanvasLinks {
134
140
  return minInitialLine;
135
141
  }
136
142
 
137
- getLinkCoords(linkType, srcObj, srcPortId, trgNode, trgPortId, assocLinkVariation) {
143
+ getLinkCoords(link, srcObj, srcPortId, trgNode, trgPortId, assocLinkVariation) {
138
144
  let coords = null;
139
- if (linkType === NODE_LINK) {
145
+ if (link.type === NODE_LINK) {
140
146
  if (this.canvasLayout.linkType === LINK_TYPE_STRAIGHT) {
141
- coords = this.getNodeLinkCoordsForStraightLine(srcObj, trgNode);
147
+ coords = this.getNodeLinkCoordsForStraightLine(srcObj, trgNode, link);
142
148
  } else {
143
149
  coords = this.getNodeLinkCoordsForPorts(srcObj, srcPortId, trgNode, trgPortId);
144
150
  }
145
- } else if (linkType === ASSOCIATION_LINK) {
151
+ } else if (link.type === ASSOCIATION_LINK) {
146
152
  if (this.config.enableAssocLinkType === ASSOC_RIGHT_SIDE_CURVE) {
147
153
  coords = this.getAssociationCurveLinkCoords(srcObj, trgNode, assocLinkVariation);
148
154
  } else {
@@ -154,7 +160,7 @@ export default class SvgCanvasLinks {
154
160
  return coords;
155
161
  }
156
162
 
157
- getNodeLinkCoordsForStraightLine(srcNode, trgNode) {
163
+ getNodeLinkCoordsForStraightLine(srcNode, trgNode, link) {
158
164
  let srcCenterX;
159
165
  let srcCenterY;
160
166
  let trgCenterX;
@@ -164,16 +170,24 @@ export default class SvgCanvasLinks {
164
170
  srcCenterX = this.nodeUtils.getNodeImageCenterPosX(srcNode);
165
171
  srcCenterY = this.nodeUtils.getNodeImageCenterPosY(srcNode);
166
172
  } else {
167
- srcCenterX = this.nodeUtils.getNodeCenterPosX(srcNode);
168
- srcCenterY = this.nodeUtils.getNodeCenterPosY(srcNode);
173
+ if (link && link.srcOriginInfo) {
174
+ ({ x: srcCenterX, y: srcCenterY } = this.getCenterOffset(srcNode, link.srcOriginInfo));
175
+ } else {
176
+ srcCenterX = this.nodeUtils.getNodeCenterPosX(srcNode);
177
+ srcCenterY = this.nodeUtils.getNodeCenterPosY(srcNode);
178
+ }
169
179
  }
170
180
 
171
181
  if (trgNode.layout.drawNodeLinkLineFromTo === "image_center" && !CanvasUtils.isExpanded(trgNode)) {
172
182
  trgCenterX = this.nodeUtils.getNodeImageCenterPosX(trgNode);
173
183
  trgCenterY = this.nodeUtils.getNodeImageCenterPosY(trgNode);
174
184
  } else {
175
- trgCenterX = this.nodeUtils.getNodeCenterPosX(trgNode);
176
- trgCenterY = this.nodeUtils.getNodeCenterPosY(trgNode);
185
+ if (link && link.trgOriginInfo) {
186
+ ({ x: trgCenterX, y: trgCenterY } = this.getCenterOffset(trgNode, link.trgOriginInfo));
187
+ } else {
188
+ trgCenterX = this.nodeUtils.getNodeCenterPosX(trgNode);
189
+ trgCenterY = this.nodeUtils.getNodeCenterPosY(trgNode);
190
+ }
177
191
  }
178
192
 
179
193
  const startPos = CanvasUtils.getOuterCoord(
@@ -201,6 +215,27 @@ export default class SvgCanvasLinks {
201
215
  return { x1: startPos.x, y1: startPos.y, x2: endPos.x, y2: endPos.y };
202
216
  }
203
217
 
218
+ getCenterOffset(node, originInfo) {
219
+ const parts = originInfo.len + 1;
220
+ const index = originInfo.idx + 1;
221
+
222
+ let x = 0;
223
+ let y = 0;
224
+
225
+ if (originInfo.dir === NORTH ||
226
+ originInfo.dir === SOUTH) {
227
+ x = node.x_pos + ((node.width / parts) * index);
228
+ y = this.nodeUtils.getNodeCenterPosY(node);
229
+
230
+ } else if (originInfo.dir === EAST ||
231
+ originInfo.dir === WEST) {
232
+ x = this.nodeUtils.getNodeCenterPosX(node);
233
+ y = node.y_pos + ((node.height / parts) * index);
234
+ }
235
+
236
+ return { x, y };
237
+ }
238
+
204
239
  getNodeLinkCoordsForPorts(srcNode, srcPortId, trgNode, trgPortId) {
205
240
  let srcX = srcNode.width + srcNode.layout.outputPortRightPosX;
206
241
  let srcY = srcNode.layout.outputPortRightPosY;
@@ -363,16 +363,6 @@ export default class SvgCanvasNodes {
363
363
  return y + Number(yOffset);
364
364
  }
365
365
 
366
- // Returns true if either the cardinality of the default input port or
367
- // the default output port of the node passed in is maxed out based on
368
- // the array of links passed in.
369
- isNodeDefaultPortsCardinalityAtMax(node, links) {
370
- const defInputPort = CanvasUtils.getDefaultInputPortId(node);
371
- const defOutputPort = CanvasUtils.getDefaultOutputPortId(node);
372
- return CanvasUtils.isSrcCardinalityAtMax(defOutputPort, node, links) ||
373
- CanvasUtils.isTrgCardinalityAtMax(defInputPort, node, links);
374
- }
375
-
376
366
  // Returns the X offset for the port which references the nodeId passed in
377
367
  // based on the precalculated X coordinate of the port.
378
368
  getSupernodePortXOffset(nodeId, ports) {
@@ -18,10 +18,11 @@ import React from "react";
18
18
  import PropTypes from "prop-types";
19
19
  import { connect } from "react-redux";
20
20
  import { Button } from "carbon-components-react";
21
- import { STATES } from "./../../constants/constants.js";
21
+ import { STATES, CARBON_BUTTON_KIND, CARBON_BUTTON_SIZE } from "./../../constants/constants.js";
22
22
  import Tooltip from "./../../../tooltip/tooltip.jsx";
23
23
  import classNames from "classnames";
24
24
  import { v4 as uuid4 } from "uuid";
25
+ import { has } from "lodash";
25
26
 
26
27
  class ButtonAction extends React.Component {
27
28
  constructor(props) {
@@ -32,6 +33,35 @@ class ButtonAction extends React.Component {
32
33
  this.uuid = uuid4();
33
34
  }
34
35
 
36
+ getActionButtonKind() {
37
+ if (!has(this.props, "action.button.kind")) {
38
+ return CARBON_BUTTON_KIND.TERTIARY;
39
+ }
40
+ switch (this.props.action.button.kind) {
41
+ case CARBON_BUTTON_KIND.PRIMARY: return CARBON_BUTTON_KIND.PRIMARY;
42
+ case CARBON_BUTTON_KIND.SECONDARY: return CARBON_BUTTON_KIND.SECONDARY;
43
+ case CARBON_BUTTON_KIND.TERTIARY: return CARBON_BUTTON_KIND.TERTIARY;
44
+ case CARBON_BUTTON_KIND.GHOST: return CARBON_BUTTON_KIND.GHOST;
45
+ case CARBON_BUTTON_KIND.DANGER: return CARBON_BUTTON_KIND.DANGER;
46
+ case CARBON_BUTTON_KIND.DANGER_TERTIARY: return CARBON_BUTTON_KIND.DANGER_TERTIARY;
47
+ case CARBON_BUTTON_KIND.DANGER_GHOST: return CARBON_BUTTON_KIND.DANGER_GHOST;
48
+ default: return CARBON_BUTTON_KIND.TERTIARY;
49
+ }
50
+ }
51
+
52
+ getActionButtonSize() {
53
+ if (!has(this.props, "action.button.size")) {
54
+ return CARBON_BUTTON_SIZE.SMALL;
55
+ }
56
+ switch (this.props.action.button.size) {
57
+ case CARBON_BUTTON_SIZE.SMALL: return CARBON_BUTTON_SIZE.SMALL;
58
+ case CARBON_BUTTON_SIZE.MEDIUM: return CARBON_BUTTON_SIZE.DEFAULT; // TODO: update this after upgrading to carbon 11.x
59
+ case CARBON_BUTTON_SIZE.LARGE: return CARBON_BUTTON_SIZE.LARGE;
60
+ case CARBON_BUTTON_SIZE.EXTRA_LARGE: return CARBON_BUTTON_SIZE.EXTRA_LARGE;
61
+ default: return CARBON_BUTTON_SIZE.SMALL;
62
+ }
63
+ }
64
+
35
65
  applyAction() {
36
66
  // fire event and let the application determine how to handle the action
37
67
  const actionHandler = this.props.controller.getHandlers().actionHandler;
@@ -44,18 +74,18 @@ class ButtonAction extends React.Component {
44
74
  render() {
45
75
  const className = classNames("properties-action-button", { "hide": this.props.state === STATES.HIDDEN });
46
76
  const disabled = this.props.state === STATES.DISABLED;
77
+ const actionButtonKind = this.getActionButtonKind();
78
+ const actionButtonSize = this.getActionButtonSize();
47
79
  const button = (
48
- <div className={className} data-id={this.props.action.name}>
49
- <Button
50
- type="button"
51
- size="small"
52
- kind="tertiary"
53
- onClick={this.applyAction}
54
- disabled={disabled}
55
- >
56
- {this.props.action.label.text}
57
- </Button>
58
- </div>
80
+ <Button
81
+ type="button"
82
+ size={actionButtonSize}
83
+ kind={actionButtonKind}
84
+ onClick={this.applyAction}
85
+ disabled={disabled}
86
+ >
87
+ {this.props.action.label.text}
88
+ </Button>
59
89
  );
60
90
 
61
91
  let display = button;
@@ -79,7 +109,9 @@ class ButtonAction extends React.Component {
79
109
  }
80
110
 
81
111
  return (
82
- display
112
+ <div className={className} data-id={this.props.action.name}>
113
+ {display}
114
+ </div>
83
115
  );
84
116
  }
85
117
  }
@@ -18,17 +18,13 @@
18
18
  * Fixed in new versions
19
19
  */
20
20
  .properties-action-button {
21
- padding: $spacing-03 $spacing-02 $spacing-03 0;
21
+ display: inline-block;
22
22
  &.hide {
23
23
  display: none;
24
24
  }
25
- > button {
26
- padding: 0 $spacing-03;
27
- }
28
25
  }
29
26
 
30
- .properties-action-panel {
31
- .properties-action-button {
32
- padding-bottom: 0; // .properties-action-panel adds 8px bottom padding
33
- }
27
+ // TODO: Remove first part after all controls are accessible - CSS for inaccessible controls
28
+ .properties-control-item > .properties-action-button, .properties-ctrl-wrapper > .properties-action-button {
29
+ padding-top: $spacing-05;
34
30
  }
@@ -258,7 +258,8 @@ CommonProperties.propTypes = {
258
258
  buttonIconHandler: PropTypes.func,
259
259
  validationHandler: PropTypes.func,
260
260
  titleChangeHandler: PropTypes.func,
261
- propertiesActionLabelHandler: PropTypes.func
261
+ propertiesActionLabelHandler: PropTypes.func,
262
+ tooltipLinkHandler: PropTypes.func
262
263
  }),
263
264
  customPanels: PropTypes.array,
264
265
  customControls: PropTypes.array,
@@ -49,9 +49,15 @@ class ControlItem extends React.Component {
49
49
  description = <div className="properties-control-description">{this.props.control.description.text}</div>;
50
50
  // only show tooltip when control enabled and visible
51
51
  } else {
52
+ // If tooltip has a link, add propertyId in the link object
53
+ if (this.props.control.description.link) {
54
+ this.props.control.description.link.propertyId = this.props.propertyId;
55
+ }
52
56
  tooltip = (<Tooltip
53
57
  id={`${this.uuid}-tooltip-label-${this.props.control.name}`}
54
58
  tip={this.props.control.description.text}
59
+ link={this.props.control.description.link ? this.props.control.description.link : null}
60
+ tooltipLinkHandler={this.props.controller.getHandlers().tooltipLinkHandler}
55
61
  direction="bottom"
56
62
  disable={hidden || disabled}
57
63
  showToolTipOnClick
@@ -97,8 +103,8 @@ class ControlItem extends React.Component {
97
103
  >
98
104
  {label}
99
105
  {description}
100
- {action}
101
106
  {this.props.controlObj}
107
+ {action}
102
108
  </div>
103
109
  );
104
110
  }
@@ -250,17 +250,16 @@ export default class FieldPicker extends React.Component {
250
250
  updateFieldSelections(rowsIndex) {
251
251
  const fields = this.getVisibleData();
252
252
  const currField = Array.from(this.state.selectedFields);
253
+ // Remove previously selected fields
253
254
  let current = currField.filter(function(value, index, arr) {
254
255
  const idx = fields.findIndex((field) => field.name === currField[index]);
255
- return (idx === -1 || rowsIndex.includes(idx));
256
+ return (idx === -1);
256
257
  });
257
- for (let i = 0; i < rowsIndex.length; i++) {
258
- const field = fields[rowsIndex[i]];
259
- if (field && !current.includes(field)) {
260
- const fieldName = field.name;
261
- current.push(fieldName);
262
- }
263
- }
258
+ // Add new selections in current
259
+ rowsIndex.forEach((rowIndex) => {
260
+ current.push(fields[rowIndex].name);
261
+ });
262
+
264
263
  current = Array.from(new Set(current));
265
264
  this.setState({
266
265
  selectedFields: current
@@ -62,6 +62,7 @@ class FlexibleTable extends React.Component {
62
62
  this._adjustTableHeight = this._adjustTableHeight.bind(this);
63
63
  this.handleCheckedRow = this.handleCheckedRow.bind(this);
64
64
  this.handleCheckedAllRows = this.handleCheckedAllRows.bind(this);
65
+ this.handleCheckedMultipleRows = this.handleCheckedMultipleRows.bind(this);
65
66
  }
66
67
 
67
68
  componentDidMount() {
@@ -244,7 +245,7 @@ class FlexibleTable extends React.Component {
244
245
  let newHeight = this.state.tableHeight;
245
246
  const rowHeight = 2; // in rem
246
247
  const headerHeight = 2; // in rem
247
- const rows = typeof this.props.rows !== "undefined" ? this.props.rows : 4;
248
+ const rows = typeof this.props.rows !== "undefined" ? this.props.rows : 5.5;
248
249
  if (Array.isArray(this.props.data) && this.props.data.length < rows) {
249
250
  newHeight = (rowHeight * this.props.data.length + headerHeight) + "rem";
250
251
  } else if (rows > 0) {
@@ -254,7 +255,7 @@ class FlexibleTable extends React.Component {
254
255
  } else if (rows === -1) {
255
256
  if (this.flexibleTable) {
256
257
  const labelAndDescriptionHeight = 50; // possible dynamically set this in the future
257
- const ftHeaderHeight = ReactDOM.findDOMNode(this.flexibleTableHeader).getBoundingClientRect().height;
258
+ const ftHeaderHeight = (typeof this.flexibleTableHeader !== "undefined") ? ReactDOM.findDOMNode(this.flexibleTableHeader).getBoundingClientRect().height : 0;
258
259
  const flyoutHeight = this.findPropertyNodeHeight(this.flexibleTable, "properties-wf-children");
259
260
  if (flyoutHeight === 0) {
260
261
  newHeight = "100vh"; // set full window height if flyout height not found
@@ -320,6 +321,30 @@ class FlexibleTable extends React.Component {
320
321
  this.setState({ checkedAllRows: checked });
321
322
  }
322
323
 
324
+ /**
325
+ * This method is called when user wants to select multiple rows using shift key
326
+ * Select/deselect all rows between lastCheckedRow and existingRow
327
+ * @param lastCheckedRow (integer) - index of last selected row
328
+ * @param existingRow (integer) - index of row where shift key is clicked
329
+ * @param checked (boolean) - rows are to be selected or deselected
330
+ */
331
+ handleCheckedMultipleRows(lastCheckedRow, existingRow, checked) {
332
+ let selectedRows = this.props.selectedRows ? this.props.selectedRows : [];
333
+ // Calculate rows between lastChecked row and existingRow
334
+ let inBetweenRows;
335
+ if (lastCheckedRow < existingRow) {
336
+ inBetweenRows = Array.from({ length: (existingRow - lastCheckedRow) + 1 }, (_, i) => lastCheckedRow + i);
337
+ } else {
338
+ inBetweenRows = Array.from({ length: (lastCheckedRow - existingRow) + 1 }, (_, i) => existingRow + i);
339
+ }
340
+ // if selectedRows already has inBetweenRows, remove them first
341
+ selectedRows = selectedRows.filter((row) => !inBetweenRows.includes(row)); // Deselecting inBetweenRows using shift key
342
+ if (checked) {
343
+ selectedRows = selectedRows.concat(inBetweenRows); // Selecting inBetweenRows using shift key
344
+ }
345
+ return selectedRows;
346
+ }
347
+
323
348
  handleCheckedRow(data, evt) {
324
349
  const dataRowIndex = data.originalRowIndex; // Use the originalRowIndex for selection in case rows are filtered.
325
350
  const displayedRowIndex = data.index;
@@ -329,15 +354,20 @@ class FlexibleTable extends React.Component {
329
354
  if (!this.props.data[displayedRowIndex].disabled) {
330
355
  if (overSelectOption) { // Checkbox is clicked
331
356
  let current = this.props.selectedRows ? this.props.selectedRows : [];
332
- if (checked) {
357
+ if (data.selectMultipleRows) { // multiple rows selected/deselected using shift key
358
+ current = this.handleCheckedMultipleRows(data.lastCheckedRow, displayedRowIndex, checked);
359
+ this.setCheckedAll(current);
360
+ } else if (checked) { // single row selected
333
361
  current = current.concat(dataRowIndex);
334
362
  this.setCheckedAll(current);
335
- } else if (current) {
363
+ } else if (current) { // single row deselected
336
364
  current = current.filter(function(element) {
337
365
  return element !== dataRowIndex;
338
366
  });
339
367
  this.setState({ checkedAllRows: false });
340
368
  }
369
+ // Sort ascending because we want to add selected rows in the same order as they're displayed in the table
370
+ current.sort((a, b) => a - b);
341
371
  this.props.updateRowSelections(current);
342
372
  } else if (this.props.rowSelection === ROW_SELECTION.SINGLE && typeof this.props.updateRowSelections !== "undefined") { // Table row is clicked
343
373
  this.props.updateRowSelections(data.index, evt, this.props.data[data.index].rowKey);
@@ -355,7 +385,8 @@ class FlexibleTable extends React.Component {
355
385
  * "label": string,
356
386
  * "width": integer or string if containts 'px',
357
387
  * "description": optional string,
358
- * "resizable": optional string
388
+ * "resizable": optional boolean,
389
+ * "staticWidth": optional boolean - This is a special property added only for SPSS modeler which directly calls FlexibleTable. This property is NOT a part of uiHints.
359
390
  * }
360
391
  * ]
361
392
  * @param columnWidths
@@ -382,7 +413,8 @@ class FlexibleTable extends React.Component {
382
413
  description: columnDef.description,
383
414
  headerLabel: headerLabel,
384
415
  resizable: columnDef.resizable,
385
- operation: columnDef.operation
416
+ operation: columnDef.operation,
417
+ staticWidth: columnDef.staticWidth ? columnDef.staticWidth : false // Used to exclude a column from resizing. If true, "resizable" value will be ignored.
386
418
  });
387
419
  }
388
420
  return {
@@ -467,13 +499,16 @@ class FlexibleTable extends React.Component {
467
499
 
468
500
  const containerClass = this.props.showHeader ? "properties-ft-container-absolute " : "properties-ft-container-absolute-noheader ";
469
501
  const messageClass = (!this.props.messageInfo) ? containerClass + STATES.INFO : containerClass + this.props.messageInfo.type;
502
+ const ftHeader = (searchBar || this.props.topRightPanel)
503
+ ? (<div className="properties-ft-table-header" ref={ (ref) => (this.flexibleTableHeader = ref) }>
504
+ {searchBar}
505
+ {this.props.topRightPanel}
506
+ </div>)
507
+ : null;
470
508
 
471
509
  return (
472
510
  <div data-id={"properties-ft-" + this.props.scrollKey} className="properties-ft-control-container" ref={ (ref) => (this.flexibleTable = ref) }>
473
- <div className="properties-ft-table-header" ref={ (ref) => (this.flexibleTableHeader = ref) }>
474
- {searchBar}
475
- {this.props.topRightPanel}
476
- </div>
511
+ {ftHeader}
477
512
  <div className="properties-ft-container-panel">
478
513
  <ReactResizeDetector handleWidth onResize={this._updateTableWidth}>
479
514
  <div className="properties-ft-container-wrapper" style={ heightStyle }>
@@ -23,7 +23,7 @@ import { SORT_DIRECTION, STATES, ROW_SELECTION, MINIMUM_COLUMN_WIDTH, MINIMUM_CO
23
23
  import { injectIntl } from "react-intl";
24
24
  import defaultMessages from "../../../../locales/common-properties/locales/en.json";
25
25
 
26
- import { isEmpty, differenceBy } from "lodash";
26
+ import { isEmpty, differenceBy, mapValues } from "lodash";
27
27
  import { v4 as uuid4 } from "uuid";
28
28
  import classNames from "classnames";
29
29
 
@@ -54,6 +54,7 @@ class VirtualizedTable extends React.Component {
54
54
  columnResized: false
55
55
  };
56
56
  this.virtualizedTableRef = React.createRef();
57
+ this.lastChecked = isEmpty(props.rowsSelected) ? null : props.rowsSelected.slice(-1).pop();
57
58
 
58
59
  this.isOverSelectOption = false;
59
60
  this.mouseEventCalled = false;
@@ -88,7 +89,12 @@ class VirtualizedTable extends React.Component {
88
89
  "index": index,
89
90
  "originalRowIndex": rowData.originalRowIndex,
90
91
  "selected": selected,
91
- "isOverSelectOption": this.isOverSelectOption }, evt);
92
+ "isOverSelectOption": this.isOverSelectOption,
93
+ "selectMultipleRows": evt.shiftKey ? evt.shiftKey : false,
94
+ "lastCheckedRow": this.lastChecked === null ? 0 : this.lastChecked }, evt);
95
+
96
+ // Track lastChecked row for shift key selection
97
+ this.lastChecked = rowData.index;
92
98
  }
93
99
  }
94
100
  }
@@ -115,6 +121,37 @@ class VirtualizedTable extends React.Component {
115
121
  return index;
116
122
  }
117
123
 
124
+ // Returns an object of deltas for every column - {columnKey: individualDelta}
125
+ getColumnWiseDeltas(columns, deltaX) {
126
+ const columnWiseDeltas = {};
127
+ if (columns.length > 0) {
128
+ // sort columns in ascending order of widths because smallest column will reach MINIMUM_COLUMN_WIDTH first
129
+ columns.sort((a, b) => a.width - b.width);
130
+ let totalDelta = deltaX;
131
+ // Finalize individualDelta for 1 column at a time starting from smallest column
132
+ // If individualDelta is greater than maximum allowed delta for the column, set individualDelta = maximum allowed delta until column reaches MINIMUM_COLUMN_WIDTH
133
+ // Total delta will reduce after every iteration
134
+ for (let i = 0; i < columns.length; i++) {
135
+ const widthOfAllColumns = columns.slice(i).reduce((prev, current) => prev + current.width, 0);
136
+ let individualDelta = Math.round((columns[i].width * totalDelta) / widthOfAllColumns);
137
+ // check if individualDelta is greater than the maximum allowed delta for this column
138
+ if (columns[i].headerLabel.length > 0 && columns[i].width - individualDelta < MINIMUM_COLUMN_WIDTH) {
139
+ individualDelta = columns[i].width - MINIMUM_COLUMN_WIDTH;
140
+ } else if (columns[i].width - individualDelta < MINIMUM_COLUMN_WIDTH_WITHOUT_LABEL) {
141
+ individualDelta = columns[i].width - MINIMUM_COLUMN_WIDTH_WITHOUT_LABEL;
142
+ }
143
+ totalDelta -= individualDelta;
144
+ columnWiseDeltas[columns[i].key] = individualDelta;
145
+ }
146
+ if (totalDelta > 0) {
147
+ // deltaX is greater than maximum allowed delta for all columns.
148
+ // Don't allow resizing by setting individualDelta = 0 for ALL columns
149
+ return mapValues(columnWiseDeltas, () => 0);
150
+ }
151
+ }
152
+ return columnWiseDeltas;
153
+ }
154
+
118
155
  isRowSelected(index) {
119
156
  if (this.props.rowsSelected) {
120
157
  return this.props.rowsSelected.indexOf(index) > -1;
@@ -265,35 +302,50 @@ class VirtualizedTable extends React.Component {
265
302
 
266
303
  /* Columns are not resizable by default. Host application specifies resizable columns in parameter definition.
267
304
  * When a column is resized, width of ALL the columns to the right of resized column is adjusted.
268
- * Example: If a column width is reduced by 10px and there are 5 columns on the right of resized column. Each of the 5 columns width is increased by 2px (10px/number of columns)
269
- * When any column's width reaches MINIMUM_COLUMN_WIDTH (56px), resizing is stopped.
305
+ * Every column grows/shrinks directly proportional to column width.
306
+ * Example: If a column width is reduced by 10px and there are 4 columns on the right of resized column having widths [40, 30, 20, 10],
307
+ * Then 10px will be adjusted in 4 columns as - [4px, 3px, 2px, 1px]
308
+ * When every column's width reaches MINIMUM_COLUMN_WIDTH (56px), resizing is stopped.
270
309
  * Special case - For columns without labels, when their width reaches MINIMUM_COLUMN_WIDTH_WITHOUT_LABEL (32px), resizing is stopped.
271
310
  */
272
311
  resizeColumn({ dataKey, deltaX }) {
273
312
  this.setState((prevState) => {
274
313
 
275
314
  const columns = prevState.columns;
276
- // Calculate number of columns on the right of resized column
315
+ // Calculate number of resizable columns on the right of resized column
277
316
  const resizedColumnIndex = this.getColumnIndex(columns, dataKey);
278
- const numberOfColumnsOnTheRight = columns.length - 1 - resizedColumnIndex;
279
- const rightColumnsDelta = deltaX / numberOfColumnsOnTheRight;
280
-
281
- // Verify adjusted width of every column on the right is greater than minimum width
282
- const everyColumnGreaterThanMinWidth = columns.slice(resizedColumnIndex + 1).every((col) => {
283
- if (col.headerLabel.length > 0) {
284
- // Column with label has min width 56px
285
- return (col.width - rightColumnsDelta > MINIMUM_COLUMN_WIDTH);
317
+ const allColumnsOnRight = columns.slice(resizedColumnIndex + 1);
318
+ // Exclude columns having staticWidth: true
319
+ const nonStaticColumns = allColumnsOnRight.filter((column) => !column.staticWidth);
320
+
321
+ const resizableColumns = nonStaticColumns.filter((column) => {
322
+ // When shrinking, get columns having width greater than MINIMUM_COLUMN_WIDTH
323
+ if (deltaX >= 0) {
324
+ if (column.headerLabel.length > 0) {
325
+ // Column with label has min width 56px
326
+ return (column.width > MINIMUM_COLUMN_WIDTH);
327
+ }
328
+ // Column without label has min width 32px
329
+ return (column.width > MINIMUM_COLUMN_WIDTH_WITHOUT_LABEL);
286
330
  }
287
- // Column without label has min width 32px
288
- return (col.width - rightColumnsDelta > MINIMUM_COLUMN_WIDTH_WITHOUT_LABEL);
331
+ // When expanding, get all columns
332
+ return true;
289
333
  });
290
334
 
291
- if ((columns[resizedColumnIndex].width + deltaX) > MINIMUM_COLUMN_WIDTH && everyColumnGreaterThanMinWidth) {
335
+ // Get column wise delta for resizableColumns
336
+ const columnWiseDeltas = this.getColumnWiseDeltas(resizableColumns, deltaX);
337
+ const columnsToBeResized = Object.keys(columnWiseDeltas);
338
+
339
+ // check if all column wise deltas are 0. This happens when deltaX is more than maximum allowed delta for all columns
340
+ const everyColumnHasZeroDelta = Object.values(columnWiseDeltas).every((delta) => delta === 0);
341
+
342
+ if ((columns[resizedColumnIndex].width + deltaX) > MINIMUM_COLUMN_WIDTH && !isEmpty(columnWiseDeltas) && !everyColumnHasZeroDelta) {
292
343
  columns[resizedColumnIndex].width += deltaX;
293
- // Adjust width of all columns on the right
294
- for (let i = resizedColumnIndex + 1; i < columns.length; i++) {
295
- columns[i].width -= rightColumnsDelta;
296
- }
344
+ // Adjust width of all resizable columns
345
+ columnsToBeResized.forEach((columnKey) => {
346
+ const idx = columns.findIndex((col) => col.key === columnKey);
347
+ columns[idx].width -= columnWiseDeltas[columnKey];
348
+ });
297
349
  }
298
350
  return {
299
351
  columnResized: true,
@@ -229,3 +229,21 @@ export const CARBON_MODAL_SIZE_LARGE = "lg";
229
229
 
230
230
  export const MINIMUM_COLUMN_WIDTH = 56; // 16px padding on both sides + 24px label
231
231
  export const MINIMUM_COLUMN_WIDTH_WITHOUT_LABEL = 32; // 16px padding on both sides
232
+
233
+ export const CARBON_BUTTON_KIND = {
234
+ PRIMARY: "primary",
235
+ SECONDARY: "secondary",
236
+ TERTIARY: "tertiary",
237
+ GHOST: "ghost",
238
+ DANGER: "danger",
239
+ DANGER_TERTIARY: "danger--tertiary",
240
+ DANGER_GHOST: "danger--ghost"
241
+ };
242
+
243
+ export const CARBON_BUTTON_SIZE = {
244
+ SMALL: "sm",
245
+ MEDIUM: "md",
246
+ LARGE: "lg",
247
+ EXTRA_LARGE: "xl",
248
+ DEFAULT: "default" // TODO: remove this after upgrading to carbon 11.x
249
+ };
@@ -630,7 +630,7 @@ export default class AbstractTable extends React.Component {
630
630
  const selectedEditRow = this.props.control.rowSelection === ROW_SELECTION.MULTIPLE
631
631
  ? this.makeSelectedEditRow(this.props.selectedRows)
632
632
  : null;
633
- let topRightPanel = <div />;
633
+ let topRightPanel = null;
634
634
  if (customButtons) {
635
635
  topRightPanel = this.makeCustomButtonsPanel(tableState, customButtons);
636
636
  } else if (this.isReadonlyTable()) {
@@ -720,8 +720,8 @@ export default class AbstractTable extends React.Component {
720
720
  }
721
721
  // subpanel column will always be empty for ReadonlyTable control based on condition in makeCells()
722
722
  if (this.props.control.childItem && !this.isReadonlyTable()) {
723
- // set to specific size
724
- headers.push({ "key": "subpanel", "label": "", "width": TABLE_SUBPANEL_BUTTON_WIDTH });
723
+ // set to specific size. Exclude this column from resizing.
724
+ headers.push({ "key": "subpanel", "label": "", "width": TABLE_SUBPANEL_BUTTON_WIDTH, "staticWidth": true });
725
725
  }
726
726
  return headers;
727
727
  }
@@ -46,11 +46,17 @@ class CheckboxControl extends React.Component {
46
46
  tooltip = (
47
47
  <span >{this.props.control.description.text}</span>
48
48
  );
49
+ // If tooltip has a link, add propertyId in the link object
50
+ if (this.props.control.description.link) {
51
+ this.props.control.description.link.propertyId = this.props.propertyId;
52
+ }
49
53
  }
50
54
  const tooltipIcon = isEmpty(tooltip) ? "" : (
51
55
  <Tooltip
52
56
  id={tooltipId}
53
57
  tip={tooltip}
58
+ link={this.props.control.description.link ? this.props.control.description.link : null}
59
+ tooltipLinkHandler={this.props.controller.getHandlers().tooltipLinkHandler}
54
60
  direction="bottom"
55
61
  className="properties-tooltips"
56
62
  showToolTipOnClick