From 9108aff55c0c6aaf67a12be4b5baf69e87ceb5ad Mon Sep 17 00:00:00 2001 From: Matt Howard Date: Mon, 5 Aug 2024 14:17:35 -0500 Subject: [PATCH 001/110] Add test coverage for Sonar Signed-off-by: Matt Howard --- .github/workflows/build.yml | 4 ++++ sonar-project.properties | 8 ++++++++ 2 files changed, 12 insertions(+) create mode 100644 sonar-project.properties diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 4dc84eb703..22a0a3275f 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -39,6 +39,10 @@ jobs: - run: ./canvas_modules/common-canvas/build.sh - run: ./canvas_modules/harness/build.sh test - run: ./canvas_modules/harness/functional_test.sh + - name: SonarCloud Scan + uses: SonarSource/sonarcloud-github-action@master + env: + SONAR_TOKEN: ${{ secrets. SONAR_TOKEN }} tag: runs-on: ubuntu-latest diff --git a/sonar-project.properties b/sonar-project.properties new file mode 100644 index 0000000000..4f86c70dd6 --- /dev/null +++ b/sonar-project.properties @@ -0,0 +1,8 @@ +sonar.projectKey=elyra-ai_canvas + +# relative paths to source directories. More details and properties are described +# in https://sonarcloud.io/documentation/project-administration/narrowing-the-focus/ +sonar.sources=canvas_modules/common-canvas/src,canvas_modules/common-canvas/utils +sonar.tests=canvas_modules/common-canvas/__tests__ +sonar.javascript.lcov.reportPaths=canvas_modules/common-canvas/coverage/lcov.info +sonar.verbose=true \ No newline at end of file From 587bc77ae2b8d9d1adcc1f21eb8058bba994123f Mon Sep 17 00:00:00 2001 From: srikant Date: Tue, 16 Apr 2024 02:01:21 +0530 Subject: [PATCH 002/110] #1872 Use React Testing Library for Toolbar Tests (#1873) Signed-off-by: Matt Howard --- .../__tests__/toolbar/toolbar-test.js | 91 ++++++++++--------- 1 file changed, 50 insertions(+), 41 deletions(-) diff --git a/canvas_modules/common-canvas/__tests__/toolbar/toolbar-test.js b/canvas_modules/common-canvas/__tests__/toolbar/toolbar-test.js index 9ad78c1ca7..17dd601dca 100644 --- a/canvas_modules/common-canvas/__tests__/toolbar/toolbar-test.js +++ b/canvas_modules/common-canvas/__tests__/toolbar/toolbar-test.js @@ -15,10 +15,11 @@ */ import React from "react"; -import { mountWithIntl } from "../_utils_/intl-utils"; +import { renderWithIntl } from "../_utils_/intl-utils"; import { expect } from "chai"; import Toolbar from "../../src/toolbar/toolbar.jsx"; import sinon from "sinon"; +import { fireEvent } from "@testing-library/react"; describe("Toolbar renders correctly", () => { @@ -39,13 +40,12 @@ describe("Toolbar renders correctly", () => { { action: "deleteSelectedObjects", label: "Delete", enable: true } ] }; - const canvasToolbar = createToolbar(toolbarConfig); - expect(canvasToolbar.find(".toolbar-div")).to.have.length(1); - expect(canvasToolbar.find(".toolbar-left-bar")).to.have.length(1); - expect(canvasToolbar.find(".toolbar-right-bar")).to.have.length(1); - expect(canvasToolbar.find(".toolbar-item")).to.have.length(10); - expect(canvasToolbar.find(".toolbar-divider")).to.have.length(2); - expect(canvasToolbar.find(".toolbar-overflow-container")).to.have.length(10); + const { container } = createToolbar(toolbarConfig); + expect(container.getElementsByClassName("toolbar-div")).to.have.length(1); + expect(container.getElementsByClassName("toolbar-left-bar")).to.have.length(1); + expect(container.getElementsByClassName("toolbar-item")).to.have.length(10); + expect(container.getElementsByClassName("toolbar-divider")).to.have.length(2); + expect(container.getElementsByClassName("toolbar-overflow-container")).to.have.length(10); }); it("should render a Toolbar with just a right bar defined", () => { @@ -59,14 +59,14 @@ describe("Toolbar renders correctly", () => { ] }; - const canvasToolbar = createToolbar(toolbarConfig); - expect(canvasToolbar.find(".toolbar-div")).to.have.length(1); - expect(canvasToolbar.find(".toolbar-left-bar")).to.have.length(1); - expect(canvasToolbar.find(".toolbar-right-bar")).to.have.length(1); - expect(canvasToolbar.find(".toolbar-item")).to.have.length(4); - expect(canvasToolbar.find(".toolbar-divider")).to.have.length(1); + const { container } = createToolbar(toolbarConfig); + + expect(container.getElementsByClassName("toolbar-left-bar")).to.have.length(1); + expect(container.getElementsByClassName("toolbar-right-bar")).to.have.length(1); + expect(container.getElementsByClassName("toolbar-item")).to.have.length(4); + expect(container.getElementsByClassName("toolbar-divider")).to.have.length(1); // No toolbar-overflow-container created for the right bar - expect(canvasToolbar.find(".toolbar-overflow-container")).to.have.length(0); + expect(container.getElementsByClassName("toolbar-overflow-container")).to.have.length(0); }); it("should register a click when clicked on an enabled toolbar item", () => { @@ -80,12 +80,11 @@ describe("Toolbar renders correctly", () => { ] }; const toolbarActionHandler = sinon.spy(); - const canvasToolbar = createToolbar(toolbarConfig, toolbarActionHandler); + const { container } = createToolbar(toolbarConfig, toolbarActionHandler); - canvasToolbar.find(".zoomIn-action button") - .at(0) - .simulate("click"); - expect(toolbarActionHandler.calledOnce).to.equal(true); + const el = container.querySelector(".zoomIn-action button"); + fireEvent.click(el); + expect(toolbarActionHandler.calledOnce).to.be.true; }); @@ -100,12 +99,11 @@ describe("Toolbar renders correctly", () => { ] }; const toolbarActionHandler = sinon.spy(); - const canvasToolbar = createToolbar(toolbarConfig, toolbarActionHandler); + const { container } = createToolbar(toolbarConfig, toolbarActionHandler); - canvasToolbar.find(".zoomToFit-action button") - .at(0) - .simulate("click"); - expect(toolbarActionHandler.calledOnce).to.equal(false); + const el = container.querySelector(".zoomToFit-action button"); + fireEvent.click(el); + expect(toolbarActionHandler.calledOnce).to.be.false; }); it("should render a Toolbar with medium size buttons", () => { @@ -117,17 +115,21 @@ describe("Toolbar renders correctly", () => { { action: "run", label: "Run Pipeline", enable: false }, ] }; - const canvasToolbar = createToolbar(toolbarConfig, sinon.spy(), "md"); + const { container } = createToolbar(toolbarConfig, sinon.spy(), "md"); // Select the toolbar medium buttons - const overflowButtons = canvasToolbar.find(".toolbar-overflow-item button"); - const defaultButtons = canvasToolbar.find(".toolbar-item.default button"); + const overflowButtons = container.querySelectorAll(".toolbar-overflow-item button"); + const defaultButtons = container.querySelectorAll(".toolbar-item.default button"); expect(overflowButtons).to.have.length(3); expect(defaultButtons).to.have.length(3); // Verify if the buttons show up with medium size - expect(overflowButtons.find(".cds--btn--md")).to.have.length(3); - expect(defaultButtons.find(".cds--btn--md")).to.have.length(3); + overflowButtons.forEach((button) => { + expect(button.classList.contains("cds--btn--md")).to.be.true; + }); + defaultButtons.forEach((button) => { + expect(button.classList.contains("cds--btn--md")).to.be.true; + }); }); it("should render a Toolbar with small size buttons", () => { @@ -139,17 +141,21 @@ describe("Toolbar renders correctly", () => { { action: "run", label: "Run Pipeline", enable: false }, ] }; - const canvasToolbar = createToolbar(toolbarConfig, sinon.spy(), "sm"); + const { container } = createToolbar(toolbarConfig, sinon.spy(), "sm"); // Select the toolbar small buttons - const overflowButtons = canvasToolbar.find(".toolbar-overflow-item button"); - const defaultButtons = canvasToolbar.find(".toolbar-item.default button"); + const overflowButtons = container.querySelectorAll(".toolbar-overflow-item button"); + const defaultButtons = container.querySelectorAll(".toolbar-item.default button"); expect(overflowButtons).to.have.length(3); expect(defaultButtons).to.have.length(3); // Verify if the buttons show up with small size - expect(overflowButtons.find(".cds--btn--sm")).to.have.length(3); - expect(defaultButtons.find(".cds--btn--sm")).to.have.length(3); + overflowButtons.forEach((button) => { + expect(button.classList.contains("cds--btn--sm")).to.be.true; + }); + defaultButtons.forEach((button) => { + expect(button.classList.contains("cds--btn--sm")).to.be.true; + }); }); it("should render a Toolbar buttons with only icons ", () => { @@ -158,9 +164,9 @@ describe("Toolbar renders correctly", () => { { action: "cut", enable: true, incLabelWithIcon: "no" }, ] }; - const canvasToolbar = createToolbar(toolbarConfig); + const { container } = createToolbar(toolbarConfig); // Select the toolbar only icons buttons - const defaultButtons = canvasToolbar.find(".toolbar-item.default button"); + const defaultButtons = container.querySelectorAll(".toolbar-item.default button"); expect(defaultButtons).to.have.length(1); }); @@ -171,18 +177,21 @@ describe("Toolbar renders correctly", () => { { action: "run", label: "Before - enabled", enable: true, incLabelWithIcon: "before" }, ] }; - const canvasToolbar = createToolbar(toolbarConfig); + const { container } = createToolbar(toolbarConfig); // Select the toolbar only icons buttons - const defaultButtons = canvasToolbar.find(".toolbar-item.default button"); + const defaultButtons = container.querySelectorAll(".toolbar-item.default button"); expect(defaultButtons).to.have.length(1); - expect(defaultButtons.find(".cds--btn--icon-only")).to.have.length(0); + + defaultButtons.forEach((button) => { + expect(button.classList.contains(".cds--btn--icon-only")).to.be.false; + }); }); }); function createToolbar(config, actionHandler, size) { const toolbarActionHandler = actionHandler || sinon.spy(); - const canvasToolbar = mountWithIntl( + const canvasToolbar = renderWithIntl( Date: Mon, 15 Apr 2024 14:24:56 -0700 Subject: [PATCH 003/110] More docs changes (#1871) Signed-off-by: Matt Howard --- docs/pages/03.03-callbacks.md | 6 +- docs/pages/03.03.01-context-menu-handler.md | 84 +++++++++++---------- docs/pages/index.md | 24 +++--- 3 files changed, 60 insertions(+), 54 deletions(-) diff --git a/docs/pages/03.03-callbacks.md b/docs/pages/03.03-callbacks.md index 4758ec416a..af1384ff7a 100644 --- a/docs/pages/03.03-callbacks.md +++ b/docs/pages/03.03-callbacks.md @@ -1,7 +1,7 @@ # Callbacks Overview You can *optionally* provide callback listeners. These will be called when the user interacts with the canvas and allows -your application to perform processing specific to your application's needs based on user interactions. +your application to perform processing specific to your application's needs based on user interactions. If you don't implement any of the callbacks, common-canvas will perform appropriate actions if necessary. These listeners are as follows: @@ -9,10 +9,10 @@ These listeners are as follows: _Overrides or adds to the default context menu (or context toolbar) displayed for nodes, links, comments, etc._ ### Before Edit Action Handler -_Called for each edit action on the canvas. For example, when a node it created or a link is deleted or a comment is moved. It is called **before** the internal object model has been updated and the edit action has completed, so this can be used to cancel user actions if necessary._ +_Called for each edit action on the canvas. It is called **before** the internal object model has been updated and the edit action has completed, so this can be used to cancel user actions if necessary._ ### Edit Action Handler -_Called for each edit action on the canvas. For example, when a node it created or a link is deleted or a comment is moved. It is called **after** the internal object model has been updated and the edit action has completed._ +_Called for each edit action on the canvas. It is called **after** the internal object model has been updated and the edit action has completed._ ### Layout Handler _Allows the application to override layout settings for nodes on a node-by-node basis._ diff --git a/docs/pages/03.03.01-context-menu-handler.md b/docs/pages/03.03.01-context-menu-handler.md index 8b1a679003..61ee03b3a1 100644 --- a/docs/pages/03.03.01-context-menu-handler.md +++ b/docs/pages/03.03.01-context-menu-handler.md @@ -1,27 +1,31 @@ # Context Menu Handler -This callback is optional. You don't need to implement anything for it. If implemented it must return an array of actions that describe what options are displayed on the [context menu](01.03-context-menu.md) or [context toolbar](01.04-context-toolbar.md). +This callback is optional. You don't need to implement anything for it. If implemented, it must return an array of actions that describe what options are displayed in the [Context Menu](01.03-context-menu.md) or [Context Toolbar](01.04-context-toolbar.md). -## contextMenuHandler -```js - contextMenuHandler(source, defaultMenu) -``` -This callback is used for both 'context menus' and, if the [`enableContextToolbar`](03.02.01-canvas-config.md#enablecontexttoolbar) canvas config option is set to `true`, for 'context toolbars'. - -If this callback is not provided common canvas will handle context menu/toolbars, and their actions, internally. You only need to implement this callback if you want to add or remove options to/from the context menu/toolbar or provide your own menus in place of the default ones. +If this callback is not provided common-canvas will handle context menu/toolbars, and their actions, internally. You only need to implement this callback if you want to add or remove options to/from the context menu/toolbar or provide your own menus in place of the default ones. -## For Context Menu +## When is it called -For context menus, this will be dependent on what object or set of objects the context menu was requested for by the user. +### For Context Menu -This callback will be called if the user performs a context menu gesture (such as mouse 'right click' or clicking an ellipsis icon) on a: +This callback will be called if the [`enableContextToolbar`](03.02.01-canvas-config.md#enablecontexttoolbar) canvas config option is set to `false` (which is the default) and when the user performs a **context menu gesture**, such as mouse 'right click' or clicking an ellipsis icon, on a: * Node * Link * Comment * Port -* On the canvas background or +* The canvas background or * Combination of objects - if a number of objects are selected + - Note: With multiple selected objects, the convention is that a context menu/toolbar should display actions that are applicable to all the objects that are selected, rather than just the object for which the menu was requested. + +### For Context Toolbar + +This callback will be called if the [`enableContextToolbar`](03.02.01-canvas-config.md#enablecontexttoolbar) canvas config option is set to `true` and when the mouse cursor is **hovered over** any of the objects mentioend above. + +## contextMenuHandler +```js + contextMenuHandler(source, defaultMenu) +``` #### 'source' parameter @@ -44,13 +48,13 @@ The source object passed in looks like this: #### 'defaultMenu' parameter -This is an array describing the default menu that common-canvas would usually display. If necessary, you can modify this array with your own elements or remove elements and then return the modified array. +This is an array describing the default menu that common-canvas would usually display. If necessary, you can modify this array with your own elements or remove elements and then return the modified array. Alternatively, you can ignore this parameter and just return your own array. -### Return +## Return array for Context Menus -The callback must return an array, that describes the context menu to be displayed. If the callback returns a null, then no menu will be displayed. +The callback must return an array, that describes the context menu to be displayed. If the callback returns a null, then no menu/toolbar will be displayed. -There is one element in the array for each entry in the context menu. An entry can be either a context menu item, which consists of a label and an action, or a divider, whose field would need to be set to true. An action can be disabled by setting the 'enable' field to false. +There is one element in the array for each entry in the context menu. An entry can be either a context menu item, which consists of a label and an action, or a divider. An action can be disabled by setting the 'enable' field to false. Here's an example of a contextMenuHandler: @@ -60,7 +64,7 @@ Here's an example of a contextMenuHandler: return [ { action: "deleteSelectedObjects", label: "Delete" }, { divider: true}, - { action: "myAction", label: "My Action" }, + { action: "myApp_Action1", label: "My Action" }, { action: "paste", label: "Paste from clipboard", enable: false } ]; } @@ -72,25 +76,9 @@ The above array will produce a context menu like this: -When the user clicks an action in the menu the action is executed either internally or externally. - -### Internal acitons - -Internal actions are implemented inside the common canvas, like "deleteSelectedObjects" in the example above. Common-canvas supports a large number of [internal actions](03.11-internal-actions.md). - -### External actions - -External actions are custom actions you want common canvas to display for your application like "myAction", in the example above. -Tip: To avoid any future name clashes with internal actions that might be added it is recommended you should make sure you action names are unique. For example, by adding a prefix to your application specfic actions. - -### Handling actions - -When the user clicks an option in the context menu (or context toolbar) it causes the [Before Edit Action Handler](03.03.02-before-edit-action-handler.md) and then the [Edit Action Handler](03.03.03-edit-action-handler.md) callbacks to be called. - - ### Customizing the default context menu - If you want to simply add your action to the default context menu provided by common canvas you can take the defaultMenu parameter provided to the callback, and add your menu item to it. Alternatively, you can provide a complete new context menu of your own. + If you want to simply add your action to the default context menu provided by common-canvas you can take the defaultMenu parameter provided to the callback, and add your menu item to it. Alternatively, you can provide a complete new context menu of your own. Here is a sample implementation of contextMenuHandler, which takes a source object (described above) and the defaultMenu as parameters, and adds a custom action to the default menu when the user 'right clicks' the canvas background. @@ -98,18 +86,19 @@ Here is a sample implementation of contextMenuHandler, which takes a source obje contextMenuHandler(source, defaultMenu) { let customMenu = defaultMenu; if (source.type === "canvas") { - customMenu = customMenu.concat({ action: "myAction", label: "My Action" }); + customMenu = customMenu.concat({ action: "myApp_Action1", label: "My Action" }); } return customMenu; } ``` -## For Context Toolbar +## Return array for Context Toolbar To display a context toolbar the same type of array is returned as described above for context menu. However, there are some extra fields for the action elements in the array. These are -* isToolbarItem: This is a boolean. The default is false. If set to true the action will be added to the toolbar and if set to false the action will be displayed in the overflow menu. -* icon: This is the icon to display for the action. If `isToolbarItem` is set to true you must provide an icon otherwise the action will show as an empty space in the toolbar. If an icon is specified and `isToolbarItem` is set to false, the icon will be displayed next to the action in the overflow menu. For many internal actions, common canvas will automatically display an appropriate carbon icon. See the [Internal Actions page](03.11-internal-actions.md/#action-names-with-built-in-icons) for a list of actions that have associated icons. +**isToolbarItem** - This is a boolean. The default is false. If set to true the action will be added to the toolbar and if set to false the action will be displayed in the overflow menu. + +**icon** - This is the icon to display for the action. If `isToolbarItem` is set to true you must provide an icon otherwise the action will show as an empty space in the toolbar. If an icon is specified and `isToolbarItem` is set to false, the icon will be displayed next to the action in the overflow menu. For many internal actions, common-canvas will automatically display an appropriate Carbon icon. See the [Internal Actions page](03.11-internal-actions.md/#action-names-with-built-in-icons) for a list of actions that have associated icons. Dividers can also be added to the context toolbar by specifying 'toolbarItem: true' @@ -142,9 +131,26 @@ And when the overflow icon is clicked, like this: #### Warning -The contents of the context toolbar is dependent on which object the mouse cursor is currently **hovering** over (which may be different to any of the **currently selected** objects). You should make sure the actions you return in the array are applicable to the object the mouse cursor is hovering over or, if it is hovering over a selected object and other objects are alos selected, to the set of selected objects. +The contents of the context toolbar is dependent on which object the mouse cursor is currently **hovering** over (which may be different to any of the **currently selected** objects). You should make sure the actions you return in the array are applicable to the object the mouse cursor is hovering over or, if it is hovering over a selected object and other objects are also selected, to the set of selected objects. To help decide whether the mouse cursor is hovering over a selected object or not, the application can call the canvas controller's helper function: 'isContextToolbarForNonSelectedObj(source)'. This will return true if the mouse cursor is over a non-selected object. +## Actions + +When the user clicks an action in the menu the action is executed either internally or externally. + +### Internal acitons + +Internal actions are implemented inside common-canvas, like "deleteSelectedObjects" in the example above. Common-canvas supports a large number of [internal actions](03.11-internal-actions.md). + +### External actions + +External actions are custom actions you want common-canvas to display for your application like "myApp_Action1", in the example above. +Tip: To avoid any future name clashes with internal actions that might be added it is recommended you should make sure you action names are unique. For example, by adding a prefix to your application specfic actions. + +### Handling actions + +When the user clicks an option in the context menu (or context toolbar) it causes the [Before Edit Action Handler](03.03.02-before-edit-action-handler.md) and then the [Edit Action Handler](03.03.03-edit-action-handler.md) callbacks to be called. + diff --git a/docs/pages/index.md b/docs/pages/index.md index 01079f4a0a..6303f4cb5b 100644 --- a/docs/pages/index.md +++ b/docs/pages/index.md @@ -14,30 +14,30 @@ flows of linked nodes. Elyra Canvas: -* Provides a comprehensive set of out-of-the-box UI components needed to build +* Provides a **comprehensive set of out-of-the-box UI components** needed to build an application such as: flow editor, palette, toolbar, context menu, tooltips, command stack, clipboard support, notifications area, side panels and more! -* Is a UI-centric library and is therefore back-end and run-time agnositc, meaning the flow can +* Is a UI-centric library and is therefore **back-end and run-time agnositc**, meaning the flow can display connected nodes representing any kind of operations. -* Is fast to get running - and easy to customize - with extensive customization capability. -* Is delivered as a package from the [NPM registry](https://www.npmjs.com/package/@elyra/canvas) +* Is fast to get running - and **easy to customize** - with extensive customization capability. +* Is delivered as a package from the [**NPM registry**](https://www.npmjs.com/package/@elyra/canvas) * Delivers a JSON powered properties management component to allow easy, no-code handling of mulltiple properties windows - for when you have a multitude of node types each with their own range of properties. -* Conforms to the [IBM Carbon](https://carbondesignsystem.com/all-about-carbon/what-is-carbon/) visual design language - and therefore plugs in easily to any application wishing to follow the Carbon standards including dark mode and light mode themes. -* Delivers built-in accessibility so there's no need to worry about keyboard +* Conforms to the [**IBM Carbon**](https://carbondesignsystem.com/all-about-carbon/what-is-carbon/) visual design language - and therefore plugs in easily to any application wishing to follow the Carbon standards including dark mode and light mode themes. +* Delivers built-in **accessibility** so there's no need to worry about keyboard navigation, accessible color themes, screen reader integration, etc. -* Is translated into 12 languages. -* Is the mainstay of several IBM products/applications across multiple divisions. +* Is translated into **12 languages**. +* Is the mainstay of several IBM products/applications. -## Elyra Canvas Components +## Elyra Canvas Modules -The elyra-ai/canvas repo contains three main components: +The elyra-ai/canvas repo contains three main modules: -* [Common Canvas](03-common-canvas.md) - This contains canvas functionality which is packaged into the [elyra/canvas NPM module](https://www.npmjs.com/package/@elyra/canvas) and deployed to the NPM registry. It provides a way for an application to display a flow of data operations (shown as a set of nodes connected with links) to the user and to allows the user to interact with the display to modify the flow. Common canvas is a react component which can be imported, and is assisted by a regular JavaScript class called `CanvasController` which provides an API and handles the internal data model of the flow. Common canvas is highly customizable where node shape and appearance, colors, styles layout etc can all be customized by your application code. Common canvas handles flows parsed from, and serialized into, a pipeline flow JSON document. It's palette of available nodes is also +* [Common-Canvas](03-common-canvas.md) - This contains canvas functionality which is packaged into the [elyra/canvas NPM module](https://www.npmjs.com/package/@elyra/canvas) and deployed to the NPM registry. It provides a way for an application to display a flow of data operations (shown as a set of nodes connected with links) to the user and to allows the user to interact with the display to modify the flow. Common canvas is a react component which can be imported, and is assisted by a regular JavaScript class called `CanvasController` which provides an API and handles the internal data model of the flow. Common canvas is highly customizable where node shape and appearance, colors, styles layout etc can all be customized by your application code. Common canvas handles flows parsed from, and serialized into, a pipeline flow JSON document. It's palette of available nodes is also customized usging a JSON document -* [Common Properties](04-common-properties.md) - This contains properties functionality which is packaged into the [elyra/canvas NPM module](https://www.npmjs.com/package/@elyra/canvas) and deployed to the NPM registry. It provides a way to translate a JSON document, which describes a set of properties with UI hints, into a working properties dialog panel. Common properties is a React component and has an associated properties controller object. +* [Common-Properties](04-common-properties.md) - This contains properties functionality which is packaged into the [elyra/canvas NPM module](https://www.npmjs.com/package/@elyra/canvas) and deployed to the NPM registry. It provides a way to translate a JSON document, which describes a set of properties with UI hints, into a working properties dialog panel. Common properties is a React component and has an associated properties controller object. * [Test Harness](https://github.com/elyra-ai/canvas/tree/master/canvas_modules/harness#test-harness) - This provides a node.js app which displays a UI which allows you to try out some sample applications and various features of the common canvas and common properties components. Bear in mind this is not supposed to be a fully functional app but is, as the name suggests, a framework for testing. In the test harness, you can select one of the sample applications or select `None` as the sample app and then select a test canvas file from the `Canvas Diagram` drop down list and a test palette from the `Canvas palette` drop down list. From 57b74b75c9d5c7278dec5895dacedaf7d3707621 Mon Sep 17 00:00:00 2001 From: Neha Gokhale Date: Tue, 16 Apr 2024 13:32:14 -0700 Subject: [PATCH 004/110] #1867 Fixed left nav subtabs CSS in tearsheet (#1875) Signed-off-by: Matt Howard --- .../src/common-properties/panels/subtabs/subtabs.scss | 8 ++++---- canvas_modules/harness/assets/styles/harness.scss | 3 +-- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/canvas_modules/common-canvas/src/common-properties/panels/subtabs/subtabs.scss b/canvas_modules/common-canvas/src/common-properties/panels/subtabs/subtabs.scss index 5e94574311..20408a6390 100644 --- a/canvas_modules/common-canvas/src/common-properties/panels/subtabs/subtabs.scss +++ b/canvas_modules/common-canvas/src/common-properties/panels/subtabs/subtabs.scss @@ -32,34 +32,34 @@ $selected-tab-width: 3px; .properties-leftnav-container { display: flex; - border-top: px solid $layer-accent-01; height: calc(100% + #{$parent-padding}); // Include padding from parent margin-top: -$spacing-05; margin-left: -$spacing-05; margin-bottom: calc(-1 * #{$parent-padding}); - // TODO: Height of this class will be fixed in issue https://github.ibm.com/NGP-TWC/wdp-abstract-canvas/issues/3699 .properties-leftnav-subtabs { width: 282px; background-color: $layer-01; border-right: 1px solid $layer-accent-01; padding-top: $spacing-02; height: 100%; + max-block-size: none; // To make the height same as parent div .cds--tab--list { flex-direction: column; width: 282px; - height: fit-content; } button.properties-leftnav-subtab-item { &:hover { - border-bottom: 0; + background-color: $layer-hover-01; + border-block-end: none !important; // Added !important to override carbon CSS which showed bottom border } border-left: $selected-tab-width solid transparent; border-bottom: 0; transition: none; // Prevent border/outline from flickering + max-block-size: $spacing-08; &:focus, &:active { outline: 0; diff --git a/canvas_modules/harness/assets/styles/harness.scss b/canvas_modules/harness/assets/styles/harness.scss index 1aab5d357d..af95029414 100644 --- a/canvas_modules/harness/assets/styles/harness.scss +++ b/canvas_modules/harness/assets/styles/harness.scss @@ -15,7 +15,7 @@ */ @use "@carbon/react/scss/themes" as *; -@use "./carbon.scss" as *; +@import "./carbon.scss"; // Switch the theme's below to change light <-> dark theme for harness // Modify common-canvas/src/themes/light.scss to switch common-canvas. @@ -32,7 +32,6 @@ $harness-sidepanel-width: 320px; $harness-sidepanel-transition-time: 0.3s; $harness-console-height: 200px; -@import "./carbon.scss"; @import "../../src/client/components/console/console.scss"; @import "../../src/styles/custom-canvases.scss"; @import "../../src/styles/canvas-customization.scss"; From 811438d96556e52b0da5e53d398cbbca2f39e8a0 Mon Sep 17 00:00:00 2001 From: CTomlyn Date: Wed, 17 Apr 2024 11:29:09 -0700 Subject: [PATCH 005/110] 1878 Don't createRoot every time node data changes in SvgCanvasExternal (#1879) Signed-off-by: Matt Howard --- .../src/common-canvas/svg-canvas-renderer.js | 10 +++++- .../svg-canvas-utils-external.js | 31 +++++++++++++------ 2 files changed, 30 insertions(+), 11 deletions(-) diff --git a/canvas_modules/common-canvas/src/common-canvas/svg-canvas-renderer.js b/canvas_modules/common-canvas/src/common-canvas/svg-canvas-renderer.js index 5ac319eab4..db7e6f759a 100644 --- a/canvas_modules/common-canvas/src/common-canvas/svg-canvas-renderer.js +++ b/canvas_modules/common-canvas/src/common-canvas/svg-canvas-renderer.js @@ -1765,7 +1765,15 @@ export default class SVGCanvasRenderer { } removeNodes(removeSel) { - // Remove any foreign objects for react nodes, if necessary. + // Remove any JSX decorations for the nodes being removed to + // unmount their React objects. + removeSel + .selectAll(".d3-foreign-object-dec-jsx") + .each((d, idx, exts) => + this.externalUtils.removeExternalObject(d, idx, exts)); + + // Remove any foreign objects for React nodes to + // unmount their React objects. removeSel .selectChildren(".d3-foreign-object-external-node") .each((d, idx, exts) => diff --git a/canvas_modules/common-canvas/src/common-canvas/svg-canvas-utils-external.js b/canvas_modules/common-canvas/src/common-canvas/svg-canvas-utils-external.js index d0e9f58d28..aa10fdf56e 100644 --- a/canvas_modules/common-canvas/src/common-canvas/svg-canvas-utils-external.js +++ b/canvas_modules/common-canvas/src/common-canvas/svg-canvas-utils-external.js @@ -1,5 +1,5 @@ /* - * Copyright 2023 Elyra Authors + * Copyright 2023-2024 Elyra Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -25,28 +25,39 @@ export default class SvgCanvasExternal { } addNodeExternalObject(node, i, foreignObjects) { - const container = foreignObjects[i]; - const root = createRoot(container); - - root.render( + const jsx = ( ); + this.renderExternalObject(jsx, foreignObjects[i]); } addDecExternalObject(dec, i, foreignObjects) { - const container = foreignObjects[i]; - const root = createRoot(container); - root.render(dec.jsx); + this.renderExternalObject(dec.jsx, foreignObjects[i]); + } + + renderExternalObject(jsx, container) { + if (!container.root) { + container.root = createRoot(container); + } + container.root.render(jsx); } removeExternalObject(obj, i, foreignObjects) { const container = foreignObjects[i]; - const root = createRoot(container); - root.unmount(); + if (!container.root) { + container.root = createRoot(container); + } + // Unmount in Timeout to stop this warning from appearing: + // "Warning: Attempted to synchronously unmount a root while + // React was already rendering." + setTimeout(() => { + container.root.unmount(); + container.root = null; + }); } getActiveNodes() { From 90a01565384e92b52936dd577d9fd7c801abb2c3 Mon Sep 17 00:00:00 2001 From: CTomlyn Date: Wed, 17 Apr 2024 11:42:38 -0700 Subject: [PATCH 006/110] =?UTF-8?q?#1876=20'Cannot=20read=20properties=20o?= =?UTF-8?q?f=20null'=20errors=20in=20console=20using=20contex=E2=80=A6=20(?= =?UTF-8?q?#1877)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Matt Howard --- .../common-canvas/src/toolbar/toolbar.jsx | 44 +++++++++---------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/canvas_modules/common-canvas/src/toolbar/toolbar.jsx b/canvas_modules/common-canvas/src/toolbar/toolbar.jsx index 489f3d7130..15db792a6f 100644 --- a/canvas_modules/common-canvas/src/toolbar/toolbar.jsx +++ b/canvas_modules/common-canvas/src/toolbar/toolbar.jsx @@ -152,11 +152,11 @@ class Toolbar extends React.Component { const refWithOpenSubArea = this.getRefWithOpenSubArea(); if (refWithOpenSubArea) { - const action = refWithOpenSubArea.current.getAction(); + const action = refWithOpenSubArea.current?.getAction(); const isFocusActionWithOpenSubAreaFocusable = this.isFocusActionFocusable(action, focusableItemRefs); if (!isFocusActionWithOpenSubAreaFocusable) { - refWithOpenSubArea.current.closeSubArea(); + refWithOpenSubArea.current?.closeSubArea(); } else { // This forces a refresh that will cause the position of any @@ -175,12 +175,12 @@ class Toolbar extends React.Component { // Returns the ref to any item that currently has an open sub-area or null // if no item has an open sub-area. getRefWithOpenSubArea() { - let subAreaOpenRef = this.leftItemRefs.find((ref) => ref.current.isSubAreaDisplayed()); + let subAreaOpenRef = this.leftItemRefs.find((ref) => ref.current?.isSubAreaDisplayed()); if (!subAreaOpenRef) { - subAreaOpenRef = this.rightItemRefs.find((ref) => ref.current.isSubAreaDisplayed()); + subAreaOpenRef = this.rightItemRefs.find((ref) => ref.current?.isSubAreaDisplayed()); } if (!subAreaOpenRef) { - subAreaOpenRef = this.overflowItemRefs.find((ref) => ref.current.isSubAreaDisplayed()); + subAreaOpenRef = this.overflowItemRefs.find((ref) => ref.current?.isSubAreaDisplayed()); } return subAreaOpenRef; } @@ -245,7 +245,7 @@ class Toolbar extends React.Component { } getRefAction(ref) { - return ref.current.getAction(); + return ref.current?.getAction(); } // Returns an array of references to focusable (that is enabled) @@ -270,17 +270,17 @@ class Toolbar extends React.Component { let overflowItemRef = null; for (let i = 0; i < this.leftItemRefs.length; i++) { - const itemRect = this.leftItemRefs[i].current.getBoundingRect(); + const itemRect = this.leftItemRefs[i].current?.getBoundingRect(); - if (itemRect.top === topRowY) { - if (this.leftItemRefs[i].current.isEnabled()) { + if (itemRect?.top === topRowY) { + if (this.leftItemRefs[i].current?.isEnabled()) { focusableItemRefs.push(this.leftItemRefs[i]); } } else if (!overflowItemRef) { const leftRefAction = this.getRefAction(this.leftItemRefs[i]); const overflowAction = this.getOverflowAction(leftRefAction); - overflowItemRef = this.overflowItemRefs.find((oRef) => oRef.current.getAction() === overflowAction); + overflowItemRef = this.overflowItemRefs.find((oRef) => oRef.current?.getAction() === overflowAction); if (overflowItemRef) { focusableItemRefs.push(overflowItemRef); } @@ -303,8 +303,8 @@ class Toolbar extends React.Component { const topRowY = this.findToolbarTopYCoordinate(); for (let i = 0; i < this.rightItemRefs.length; i++) { - if (this.rightItemRefs[i].current.isEnabled()) { - const refRect = this.rightItemRefs[i].current.getBoundingRect(); + if (this.rightItemRefs[i].current?.isEnabled()) { + const refRect = this.rightItemRefs[i].current?.getBoundingRect(); if (refRect.top === topRowY) { focusableItemRefs.push(this.rightItemRefs[i]); @@ -355,7 +355,7 @@ class Toolbar extends React.Component { // items. (It may not be if it has been placed in the overflow menu). isFocusActionFocusable(focusAction, focusableItemRefs) { const indexFocusAction = focusableItemRefs.findIndex((ref) => - ref.current.props.actionObj?.action === focusAction); + ref.current?.props.actionObj?.action === focusAction); return indexFocusAction > -1; } @@ -367,7 +367,7 @@ class Toolbar extends React.Component { let rightItemRef = null; for (let i = 0; i < this.rightItemRefs.length; i++) { - const itemRect = this.rightItemRefs[i].current.getBoundingRect(); + const itemRect = this.rightItemRefs[i].current?.getBoundingRect(); if (itemRect.top !== topRowY && rightItemRef === null) { rightItemRef = this.rightItemRefs[i]; } @@ -379,8 +379,8 @@ class Toolbar extends React.Component { // used to detecg which toolbar items are on the top (visible) // row and which are wrapped onto other rows. findToolbarTopYCoordinate() { - const rect = this.toolbarRef.current.getBoundingClientRect(); - return rect.top; + const rect = this.toolbarRef.current?.getBoundingClientRect(); + return rect?.top; } // Generates an array of toolbar items from the toolbarActions array passed in. When @@ -495,17 +495,17 @@ class Toolbar extends React.Component { } closeSubAreaOnRef(ref) { - if (ref.current.props.actionObj.setExtIsSubAreaDisplayed) { - ref.current.props.actionObj.setExtIsSubAreaDisplayed(false); + if (ref.current?.props.actionObj.setExtIsSubAreaDisplayed) { + ref.current?.props.actionObj.setExtIsSubAreaDisplayed(false); - } else if (ref.current.state.subAreaDisplayed) { - ref.current.closeSubArea(); + } else if (ref.current?.state.subAreaDisplayed) { + ref.current?.closeSubArea(); } } closeOverflowMenuOnRef(ref) { - if (ref.current.state.showExtendedMenu) { - ref.current.closeSubArea(); + if (ref.current?.state.showExtendedMenu) { + ref.current?.closeSubArea(); } } From 5dd3935eb5bf3a57c885c5c9097d62c3d07a1a22 Mon Sep 17 00:00:00 2001 From: Neha Gokhale Date: Thu, 18 Apr 2024 09:35:10 -0700 Subject: [PATCH 007/110] #1881 Added Layer component at control level (#1882) Signed-off-by: Neha Gokhale Signed-off-by: Matt Howard --- .../controls/datefield-test.js | 22 ++--- .../controls/control-factory.js | 11 ++- .../controls/datefield/datefield.jsx | 26 +++--- .../datepicker-range/datepicker-range.jsx | 68 ++++++++-------- .../controls/datepicker/datepicker.jsx | 44 +++++----- .../controls/dropdown/dropdown.jsx | 80 +++++++++---------- .../controls/dropdown/dropdown.scss | 2 +- .../controls/multiselect/multiselect.jsx | 50 ++++++------ .../controls/numberfield/numberfield.jsx | 34 ++++---- .../controls/passwordfield/passwordfield.jsx | 32 ++++---- .../controls/slider/slider.jsx | 34 ++++---- .../controls/textarea/textarea.jsx | 44 +++++----- .../controls/textfield/textfield.jsx | 28 +++---- .../controls/timefield/timefield.jsx | 26 +++--- 14 files changed, 234 insertions(+), 267 deletions(-) diff --git a/canvas_modules/common-canvas/__tests__/common-properties/controls/datefield-test.js b/canvas_modules/common-canvas/__tests__/common-properties/controls/datefield-test.js index 9a61f65df5..e26e8c4dab 100644 --- a/canvas_modules/common-canvas/__tests__/common-properties/controls/datefield-test.js +++ b/canvas_modules/common-canvas/__tests__/common-properties/controls/datefield-test.js @@ -163,22 +163,6 @@ describe("datefield-control renders correctly", () => { expect(input.getDOMNode().placeholder).to.equal(control.additionalText); }); - it("should render `DatefieldControl` with light mode enabled", () => { - controller.setLight(true); - const wrapper = mount( - - ); - const dateWrapper = wrapper.find("div[data-id='properties-test-datefield']"); - expect(dateWrapper.find(".cds--layer-two")).to.have.length(1); // light enabled - expect(dateWrapper.find(".cds--layer-one")).to.have.length(0); // light disabled - }); - it("should render `DatefieldControl` with light mode disabled", () => { controller.setLight(false); const wrapper = mount( @@ -341,6 +325,12 @@ describe("error messages renders correctly for datefield controls", () => { dateWrapper = wrapper.find("div[data-id='properties-disabled_date']"); expect(dateWrapper.find("input").prop("disabled")).to.equal(false); }); + + it("should render `DatefieldControl` with light mode enabled", () => { + const dateWrapper = wrapper.find("div[data-id='properties-ctrl-date_mdy']"); + expect(dateWrapper.find(".cds--layer-two")).to.have.length(1); // light enabled + expect(dateWrapper.find(".cds--layer-one")).to.have.length(0); // light disabled + }); }); describe("datefield classnames appear correctly", () => { diff --git a/canvas_modules/common-canvas/src/common-properties/controls/control-factory.js b/canvas_modules/common-canvas/src/common-properties/controls/control-factory.js index 1ef2ef8a76..03a9856b6e 100644 --- a/canvas_modules/common-canvas/src/common-properties/controls/control-factory.js +++ b/canvas_modules/common-canvas/src/common-properties/controls/control-factory.js @@ -23,6 +23,7 @@ import { PropertyDef } from "./../form/PropertyDef"; import { makeControl } from "./../form/EditorForm"; import { L10nProvider } from "./../util/L10nProvider"; import * as ControlUtils from "./../util/control-utils"; +import { Layer } from "@carbon/react"; import TextfieldControl from "./textfield"; import ReadonlyControl from "./readonly"; @@ -346,6 +347,12 @@ export default class ControlFactory { createdControl = (); } + const createdControlLayered = ( + + {createdControl} + + ); + /* * should be called from every control. * Adding this temporary condition so that we can change one control at a time. @@ -366,12 +373,12 @@ export default class ControlFactory { className )} > - {createdControl} + {createdControlLayered} {action} ); } - return createdControl; + return createdControlLayered; } /** diff --git a/canvas_modules/common-canvas/src/common-properties/controls/datefield/datefield.jsx b/canvas_modules/common-canvas/src/common-properties/controls/datefield/datefield.jsx index 43a152dcb1..a27ffb5d87 100644 --- a/canvas_modules/common-canvas/src/common-properties/controls/datefield/datefield.jsx +++ b/canvas_modules/common-canvas/src/common-properties/controls/datefield/datefield.jsx @@ -17,7 +17,7 @@ import React from "react"; import PropTypes from "prop-types"; import { connect } from "react-redux"; -import { TextInput, Layer } from "@carbon/react"; +import { TextInput } from "@carbon/react"; import ValidationMessage from "./../../components/validation-message"; import * as ControlUtils from "./../../util/control-utils"; import { parse, format, isValid } from "date-fns"; @@ -73,19 +73,17 @@ class DatefieldControl extends React.Component { const validationProps = ControlUtils.getValidationProps(this.props.messageInfo, this.props.tableControl); return (
- - - +
); diff --git a/canvas_modules/common-canvas/src/common-properties/controls/datepicker-range/datepicker-range.jsx b/canvas_modules/common-canvas/src/common-properties/controls/datepicker-range/datepicker-range.jsx index 774aa09215..721bb4d33d 100644 --- a/canvas_modules/common-canvas/src/common-properties/controls/datepicker-range/datepicker-range.jsx +++ b/canvas_modules/common-canvas/src/common-properties/controls/datepicker-range/datepicker-range.jsx @@ -17,7 +17,7 @@ import React from "react"; import PropTypes from "prop-types"; import { connect } from "react-redux"; -import { DatePicker, DatePickerInput, Layer } from "@carbon/react"; +import { DatePicker, DatePickerInput } from "@carbon/react"; import classNames from "classnames"; import { v4 as uuid4 } from "uuid"; @@ -135,40 +135,38 @@ class DatepickerRangeControl extends React.Component { return (
- - - - - - + + + +
); diff --git a/canvas_modules/common-canvas/src/common-properties/controls/datepicker/datepicker.jsx b/canvas_modules/common-canvas/src/common-properties/controls/datepicker/datepicker.jsx index bdf0e6cb85..507fdca20c 100644 --- a/canvas_modules/common-canvas/src/common-properties/controls/datepicker/datepicker.jsx +++ b/canvas_modules/common-canvas/src/common-properties/controls/datepicker/datepicker.jsx @@ -17,7 +17,7 @@ import React from "react"; import PropTypes from "prop-types"; import { connect } from "react-redux"; -import { DatePicker, DatePickerInput, Layer } from "@carbon/react"; +import { DatePicker, DatePickerInput } from "@carbon/react"; import classNames from "classnames"; import ValidationMessage from "../../components/validation-message"; @@ -71,28 +71,26 @@ class DatepickerControl extends React.Component { return (
- - - - - + + +
); diff --git a/canvas_modules/common-canvas/src/common-properties/controls/dropdown/dropdown.jsx b/canvas_modules/common-canvas/src/common-properties/controls/dropdown/dropdown.jsx index 63625ac6d5..2a3a2ba275 100644 --- a/canvas_modules/common-canvas/src/common-properties/controls/dropdown/dropdown.jsx +++ b/canvas_modules/common-canvas/src/common-properties/controls/dropdown/dropdown.jsx @@ -17,7 +17,7 @@ import React from "react"; import PropTypes from "prop-types"; import { connect } from "react-redux"; -import { SelectItem, Select, Dropdown, ComboBox, Layer } from "@carbon/react"; +import { SelectItem, Select, Dropdown, ComboBox } from "@carbon/react"; import { isEqual, isEmpty } from "lodash"; import * as ControlUtils from "./../../util/control-utils"; import ValidationMessage from "./../../components/validation-message"; @@ -220,54 +220,48 @@ class DropDown extends React.Component { options.push(); } dropdownComponent = ( - - - + ); } else if (this.props.control.customValueAllowed) { // combobox dropdown not allowed in tables dropdownComponent = ( - - listBoxMenuIconTranslationIds[id]} - titleText={this.props.controlItem} - /> - + listBoxMenuIconTranslationIds[id]} + titleText={this.props.controlItem} + /> ); } else { dropdownComponent = ( - - listBoxMenuIconTranslationIds[id]} - titleText={this.props.controlItem} - /> - + listBoxMenuIconTranslationIds[id]} + titleText={this.props.controlItem} + /> ); } diff --git a/canvas_modules/common-canvas/src/common-properties/controls/dropdown/dropdown.scss b/canvas_modules/common-canvas/src/common-properties/controls/dropdown/dropdown.scss index cc154de790..57b40fd563 100644 --- a/canvas_modules/common-canvas/src/common-properties/controls/dropdown/dropdown.scss +++ b/canvas_modules/common-canvas/src/common-properties/controls/dropdown/dropdown.scss @@ -24,7 +24,7 @@ } .properties-table-cell-control { - >.properties-dropdown { + .properties-dropdown { .cds--select.cds--select--inline { .cds--select-input--inline__wrapper { width: 100%; diff --git a/canvas_modules/common-canvas/src/common-properties/controls/multiselect/multiselect.jsx b/canvas_modules/common-canvas/src/common-properties/controls/multiselect/multiselect.jsx index b321d2e65b..a4a24602c2 100644 --- a/canvas_modules/common-canvas/src/common-properties/controls/multiselect/multiselect.jsx +++ b/canvas_modules/common-canvas/src/common-properties/controls/multiselect/multiselect.jsx @@ -17,7 +17,7 @@ import React from "react"; import PropTypes from "prop-types"; import { connect } from "react-redux"; -import { MultiSelect, FilterableMultiSelect, Layer } from "@carbon/react"; +import { MultiSelect, FilterableMultiSelect } from "@carbon/react"; import * as ControlUtils from "./../../util/control-utils"; import ValidationMessage from "./../../components/validation-message"; import classNames from "classnames"; @@ -145,35 +145,31 @@ class MultiSelectControl extends React.Component { let dropdownComponent = null; if (this.props.control.filterable) { dropdownComponent = ( - - listBoxMenuIconTranslationIds[id]} - items={multiSelectDropdown.options} - initialSelectedItems={multiSelectDropdown.selectedOptions} - onChange={this.handleOnChange} - placeholder={label} - titleText={this.props.tableControl ? null : this.props.controlItem} - /> - + listBoxMenuIconTranslationIds[id]} + items={multiSelectDropdown.options} + initialSelectedItems={multiSelectDropdown.selectedOptions} + onChange={this.handleOnChange} + placeholder={label} + titleText={this.props.tableControl ? null : this.props.controlItem} + /> ); } else { dropdownComponent = ( - - listBoxMenuIconTranslationIds[id]} - items={multiSelectDropdown.options} - selectedItems={multiSelectDropdown.selectedOptions} - onChange={this.handleOnChange} - label={label} - titleText={this.props.tableControl ? null : this.props.controlItem} - /> - + listBoxMenuIconTranslationIds[id]} + items={multiSelectDropdown.options} + selectedItems={multiSelectDropdown.selectedOptions} + onChange={this.handleOnChange} + label={label} + titleText={this.props.tableControl ? null : this.props.controlItem} + /> ); } diff --git a/canvas_modules/common-canvas/src/common-properties/controls/numberfield/numberfield.jsx b/canvas_modules/common-canvas/src/common-properties/controls/numberfield/numberfield.jsx index 857ab76868..0ebab116ca 100755 --- a/canvas_modules/common-canvas/src/common-properties/controls/numberfield/numberfield.jsx +++ b/canvas_modules/common-canvas/src/common-properties/controls/numberfield/numberfield.jsx @@ -17,7 +17,7 @@ import React from "react"; import PropTypes from "prop-types"; import { connect } from "react-redux"; -import { NumberInput, Button, Layer } from "@carbon/react"; +import { NumberInput, Button } from "@carbon/react"; import ValidationMessage from "./../../components/validation-message"; import * as ControlUtils from "./../../util/control-utils"; import { formatMessage } from "./../../util/property-utils"; @@ -158,23 +158,21 @@ class NumberfieldControl extends React.Component { const validationProps = ControlUtils.getValidationProps(this.props.messageInfo, this.props.tableControl); return (
- - (this.numberInput = ref)} - id={this.id} - onChange={this.handleChange.bind(this)} - disabled={disabled} - step={this.props.control.increment} - value={controlValue} - placeholder={this.props.control.additionalText} - label={this.props.controlItem} - hideLabel={this.props.tableControl} - allowEmpty - hideSteppers={this.props.tableControl || (this.props.control.controlType === ControlType.NUMBERFIELD)} - onInput={this.onInput.bind(this)} - /> - + (this.numberInput = ref)} + id={this.id} + onChange={this.handleChange.bind(this)} + disabled={disabled} + step={this.props.control.increment} + value={controlValue} + placeholder={this.props.control.additionalText} + label={this.props.controlItem} + hideLabel={this.props.tableControl} + allowEmpty + hideSteppers={this.props.tableControl || (this.props.control.controlType === ControlType.NUMBERFIELD)} + onInput={this.onInput.bind(this)} + /> {numberGenerator}
diff --git a/canvas_modules/common-canvas/src/common-properties/controls/passwordfield/passwordfield.jsx b/canvas_modules/common-canvas/src/common-properties/controls/passwordfield/passwordfield.jsx index f573307dfc..496de24210 100644 --- a/canvas_modules/common-canvas/src/common-properties/controls/passwordfield/passwordfield.jsx +++ b/canvas_modules/common-canvas/src/common-properties/controls/passwordfield/passwordfield.jsx @@ -17,7 +17,7 @@ import React from "react"; import PropTypes from "prop-types"; import { connect } from "react-redux"; -import { TextInput, Layer } from "@carbon/react"; +import { TextInput } from "@carbon/react"; import ValidationMessage from "./../../components/validation-message"; import * as ControlUtils from "./../../util/control-utils"; import { STATES, MESSAGE_KEYS } from "./../../constants/constants.js"; @@ -49,22 +49,20 @@ class PasswordControl extends React.Component { const validationProps = ControlUtils.getValidationProps(this.props.messageInfo, this.props.tableControl); return (
- - - +
); } diff --git a/canvas_modules/common-canvas/src/common-properties/controls/slider/slider.jsx b/canvas_modules/common-canvas/src/common-properties/controls/slider/slider.jsx index fd61c05d2c..fefa124b07 100644 --- a/canvas_modules/common-canvas/src/common-properties/controls/slider/slider.jsx +++ b/canvas_modules/common-canvas/src/common-properties/controls/slider/slider.jsx @@ -16,7 +16,7 @@ import React from "react"; import PropTypes from "prop-types"; -import { Slider, Layer } from "@carbon/react"; +import { Slider } from "@carbon/react"; import { connect } from "react-redux"; import classNames from "classnames"; import { v4 as uuid4 } from "uuid"; @@ -50,23 +50,21 @@ class SliderControl extends React.Component {
- - label || val - } - /> - + label || val + } + />
); diff --git a/canvas_modules/common-canvas/src/common-properties/controls/textarea/textarea.jsx b/canvas_modules/common-canvas/src/common-properties/controls/textarea/textarea.jsx index 29f3a84b04..581a5e75e6 100644 --- a/canvas_modules/common-canvas/src/common-properties/controls/textarea/textarea.jsx +++ b/canvas_modules/common-canvas/src/common-properties/controls/textarea/textarea.jsx @@ -17,7 +17,7 @@ import React from "react"; import PropTypes from "prop-types"; import { connect } from "react-redux"; -import { TextArea, Layer } from "@carbon/react"; +import { TextArea } from "@carbon/react"; import ValidationMessage from "./../../components/validation-message"; import * as ControlUtils from "./../../util/control-utils"; import { formatMessage } from "./../../util/property-utils"; @@ -71,33 +71,29 @@ class TextareaControl extends React.Component { }; validationProps = ControlUtils.getValidationProps(errorMessage, this.props.tableControl); textArea = (
- -