From 3bebb81f637be7fb4e5a72d97546762c2ee015f5 Mon Sep 17 00:00:00 2001 From: mikieyx <103902194+mikieyx@users.noreply.github.com> Date: Wed, 13 Nov 2024 12:35:15 -0800 Subject: [PATCH] #2213 Table toolbar should not be shown for single select tables (#2214) --- .../controls/structurelisteditor-test.js | 63 ++++++++++++++++--- .../common-properties/panels/summary-test.js | 27 ++++---- .../structurelisteditor_paramDef.json | 2 +- .../locales/common-properties/locales/en.json | 3 +- .../locales/common-properties/locales/eo.json | 3 +- .../flexible-table/flexible-table.jsx | 3 +- .../flexible-table/flexible-table.scss | 5 ++ .../virtualized-table/virtualized-table.jsx | 1 - .../common-properties/constants/constants.js | 1 + .../controls/abstract-table.jsx | 37 ++++++++++- .../e2e/properties/properties-tooltips.cy.js | 4 +- .../support/properties/properties-cmds.js | 16 +++++ .../structurelisteditor_paramDef.json | 2 +- 13 files changed, 133 insertions(+), 34 deletions(-) diff --git a/canvas_modules/common-canvas/__tests__/common-properties/controls/structurelisteditor-test.js b/canvas_modules/common-canvas/__tests__/common-properties/controls/structurelisteditor-test.js index 637ab46c62..929a4044ff 100644 --- a/canvas_modules/common-canvas/__tests__/common-properties/controls/structurelisteditor-test.js +++ b/canvas_modules/common-canvas/__tests__/common-properties/controls/structurelisteditor-test.js @@ -498,7 +498,7 @@ describe("StructureListEditor render from paramdef", () => { expect(tableUtilsRTL.getTableRows(container)).to.have.length(2); // select the first row in the table - tableUtilsRTL.clickTableRows(container, [0]); + tableUtilsRTL.selectCheckboxes(container, [0]); // ensure table toolbar has Delete button and select it const tableToolbar = container.querySelector("div.properties-table-toolbar"); @@ -525,7 +525,7 @@ describe("StructureListEditor render from paramdef", () => { expect(tableData).to.have.length(3); // set the error in the last row - const checkboxCell = summaryPanel.querySelectorAll("input[type='checkbox']")[3]; + const checkboxCell = summaryPanel.querySelectorAll("input[type='checkbox']")[7]; checkboxCell.setAttribute("checked", false); fireEvent.click(checkboxCell); @@ -544,10 +544,10 @@ describe("StructureListEditor render from paramdef", () => { expect(errorMessage).to.eql(actual); // remove the first row and ensure the error message is associated with the correct row. - tableUtilsRTL.clickTableRows(summaryPanel, [0]); + tableUtilsRTL.selectCheckboxes(container, [0]); const tableToolbar = container.querySelector("div.properties-table-toolbar"); - let deleteButton = tableToolbar.querySelector("button.properties-action-delete"); - fireEvent.click(deleteButton); + let deleteButton = tableToolbar.querySelectorAll("button.properties-action-delete"); + fireEvent.click(deleteButton[0]); const messages = renderedController.getAllErrorMessages(); const rowErrorMsg = { "1": { "3": { propertyId: { @@ -561,9 +561,9 @@ describe("StructureListEditor render from paramdef", () => { summaryPanel = container.querySelector("div.properties-wf-content.show"); tableData = tableUtilsRTL.getTableRows(summaryPanel); expect(tableData).to.have.length(2); - tableUtilsRTL.clickTableRows(summaryPanel, [1]); - deleteButton = container.querySelector("div.properties-table-toolbar").querySelector("button.properties-action-delete"); - fireEvent.click(deleteButton); + tableUtilsRTL.selectCheckboxes(container, [1]); + deleteButton = container.querySelectorAll("button.properties-action-delete"); + fireEvent.click(deleteButton[0]); actual = renderedController.getErrorMessage({ name: "inlineEditingTableError" }); expect(actual).to.equal(null); }); @@ -630,7 +630,7 @@ describe("StructureListEditor render from paramdef", () => { expect(errorMessage).to.eql(actual); // select the first row and move it to the bottom and make sure the error messages stay aligned. - tableUtilsRTL.clickTableRows(summaryPanel, [0]); + tableUtilsRTL.selectCheckboxes(summaryPanel, [0]); summaryPanel = container.querySelector("div.properties-wf-content.show"); const moveRowBottom = container.querySelector("div.properties-table-toolbar").querySelector("button.table-row-move-bottom-button"); fireEvent.click(moveRowBottom); @@ -656,7 +656,7 @@ describe("StructureListEditor render from paramdef", () => { // select the second from the last row and move it to the top and make sure the error messages stay aligned. tableData = tableUtilsRTL.getTableRows(summaryPanel); expect(tableData).to.have.length(5); - tableUtilsRTL.clickTableRows(summaryPanel, [3]); + tableUtilsRTL.selectCheckboxes(summaryPanel, [3]); summaryPanel = container.querySelector("div.properties-wf-content.show"); const moveRowTop = container.querySelector("div.properties-table-toolbar").querySelector("button.table-row-move-top-button"); fireEvent.click(moveRowTop); @@ -780,6 +780,49 @@ describe("StructureListEditor render from paramdef", () => { }); }); +describe("StructureListEditor single select table renders and functions correctly", () => { + let wrapper; + + beforeEach(() => { + const renderedObject = propertyUtilsRTL.flyoutEditorForm(structureListEditorParamDef); + wrapper = renderedObject.wrapper; + }); + + afterEach(() => { + wrapper.unmount(); + }); + + // Removed table toolbar from single select tables. + it("Should not render table toolbar", () => { + const { container } = wrapper; + propertyUtilsRTL.openSummaryPanel(wrapper, "inlineEditingTableWarning-summary-panel"); + tableUtilsRTL.clickTableRows(container, [0]); + const tableToolbar = container.querySelectorAll("div.properties-table-toolbar"); + expect(tableToolbar).to.have.length(0); + }); + + // Testing delete icons for single select table + it("should delete rows correctly", async() => { + const { container } = wrapper; + const summaryPanel = propertyUtilsRTL.openSummaryPanel(wrapper, "inlineEditingTableWarning-summary-panel"); + + // Adding a row + const addColumnButton = summaryPanel.querySelectorAll("button.properties-add-fields-button"); + expect(addColumnButton).to.have.length(1); + fireEvent.click(addColumnButton[0]); + + expect(tableUtilsRTL.getTableRows(container)).to.have.length(2); + + // Testing delete row icon + const deleteButtons = container.querySelectorAll(".delete-button"); + expect(deleteButtons).to.have.length(2); + tableUtilsRTL.clickTableRows(container, [0]); // need to click on the table that we want to delete + fireEvent.click(deleteButtons[0]); + + expect(tableUtilsRTL.getTableRows(container)).to.have.length(1); + }); +}); + describe("StructureListEditor renders correctly with nested controls", () => { let wrapper; let renderedController; diff --git a/canvas_modules/common-canvas/__tests__/common-properties/panels/summary-test.js b/canvas_modules/common-canvas/__tests__/common-properties/panels/summary-test.js index 57a57bdcc6..2e0d1bfcab 100644 --- a/canvas_modules/common-canvas/__tests__/common-properties/panels/summary-test.js +++ b/canvas_modules/common-canvas/__tests__/common-properties/panels/summary-test.js @@ -106,19 +106,18 @@ describe("summary panel renders error/warning status correctly", () => { // ensure table toolbar has Delete button and click it wideflyout = wrapper.find("div.properties-wf-content.show"); let tableWrapper = wideflyout.find("div[data-id='properties-expressionCellTable']"); - let tableToolbar = tableWrapper.find("div.properties-table-toolbar"); - let deleteButton = tableToolbar.find("button.properties-action-delete"); - expect(deleteButton).to.have.length(1); - deleteButton.simulate("click"); + let deleteButtons = tableWrapper.find("button.delete-button"); + expect(deleteButtons).to.have.length(2); + deleteButtons.at(0).simulate("click"); // remove second row tableUtils.clickTableRows(wideflyout, [0]); wideflyout = wrapper.find("div.properties-wf-content.show"); tableWrapper = wideflyout.find("div[data-id='properties-expressionCellTable']"); - tableToolbar = tableWrapper.find("div.properties-table-toolbar"); - deleteButton = tableToolbar.find("button.properties-action-delete"); - expect(deleteButton).to.have.length(1); - deleteButton.simulate("click"); + deleteButtons = tableWrapper.find("button.delete-button"); + expect(deleteButtons).to.have.length(1); + deleteButtons.at(0).simulate("click"); + // close fly-out wideflyout.find("button.properties-apply-button").simulate("click"); @@ -162,18 +161,16 @@ describe("summary panel renders error/warning status correctly", () => { wideflyout = wrapper.find("div.properties-wf-content.show"); // ensure table toolbar has Delete button and click it let tableWrapper = wideflyout.find("div[data-id='properties-expressionCellTable']"); - const tableToolbar = tableWrapper.find("div.properties-table-toolbar"); - let deleteButton = tableToolbar.find("button.properties-action-delete"); - expect(deleteButton).to.have.length(1); - deleteButton.simulate("click"); + let deleteButtons = tableWrapper.find("button.delete-button"); + deleteButtons.at(0).simulate("click"); // remove second row tableUtils.clickTableRows(wideflyout, [0]); wideflyout = wrapper.find("div.properties-wf-content.show"); tableWrapper = wideflyout.find("div[data-id='properties-expressionCellTable']"); - deleteButton = tableWrapper.find("div.properties-table-toolbar").find("button.properties-action-delete"); - expect(deleteButton).to.have.length(1); - deleteButton.simulate("click"); + deleteButtons = tableWrapper.find("button.delete-button"); + deleteButtons.at(0).simulate("click"); + // check that all rows were removed wideflyout = wrapper.find("div.properties-wf-content.show"); diff --git a/canvas_modules/common-canvas/__tests__/test_resources/paramDefs/structurelisteditor_paramDef.json b/canvas_modules/common-canvas/__tests__/test_resources/paramDefs/structurelisteditor_paramDef.json index 73fcfc1abc..20f80d50cc 100644 --- a/canvas_modules/common-canvas/__tests__/test_resources/paramDefs/structurelisteditor_paramDef.json +++ b/canvas_modules/common-canvas/__tests__/test_resources/paramDefs/structurelisteditor_paramDef.json @@ -1216,7 +1216,7 @@ }, { "complex_type_ref": "inlineEditingTableError", - "row_selection": "single", + "row_selection": "multiple-edit", "moveable_rows": true, "parameters": [ { diff --git a/canvas_modules/common-canvas/locales/common-properties/locales/en.json b/canvas_modules/common-canvas/locales/common-properties/locales/en.json index 96081ecffb..644fe60889 100644 --- a/canvas_modules/common-canvas/locales/common-properties/locales/en.json +++ b/canvas_modules/common-canvas/locales/common-properties/locales/en.json @@ -114,5 +114,6 @@ "label.indicator.optional": "(optional)", "slider.numberInput.label": "Slider number input", "editorForm.tabList.label": "Primary Tabs", - "subTabs.tabList.label": "Tab List" + "subTabs.tabList.label": "Tab List", + "table.deleteIcon.tooltip": "Delete" } diff --git a/canvas_modules/common-canvas/locales/common-properties/locales/eo.json b/canvas_modules/common-canvas/locales/common-properties/locales/eo.json index 22449a7e90..fc4af3eb85 100644 --- a/canvas_modules/common-canvas/locales/common-properties/locales/eo.json +++ b/canvas_modules/common-canvas/locales/common-properties/locales/eo.json @@ -112,5 +112,6 @@ "label.indicator.optional": "[Esperanto~(optional)~~~~~~eo]", "slider.numberInput.label": "[Esperanto~Slider number input~~~~~eo]", "editorForm.tabList.label": "[Esperanto~Primary Tabs~~~~eo]", - "subTabs.tabList.label": "[Esperanto~Tab List~~~~eo]" + "subTabs.tabList.label": "[Esperanto~Tab List~~~~eo]", + "table.deleteIcon.tooltip": "[Esperanto~Delete~~~~eo]" } diff --git a/canvas_modules/common-canvas/src/common-properties/components/flexible-table/flexible-table.jsx b/canvas_modules/common-canvas/src/common-properties/components/flexible-table/flexible-table.jsx index b7edb83a91..237d7b3d04 100644 --- a/canvas_modules/common-canvas/src/common-properties/components/flexible-table/flexible-table.jsx +++ b/canvas_modules/common-canvas/src/common-properties/components/flexible-table/flexible-table.jsx @@ -523,7 +523,8 @@ class FlexibleTable extends React.Component { const containerClass = this.props.showHeader ? "properties-ft-container-absolute " : "properties-ft-container-absolute-noheader "; const messageClass = (!this.props.messageInfo) ? containerClass + STATES.INFO : containerClass; - const ftHeaderClassname = "properties-ft-table-header"; + const ftHeaderClassname = classNames("properties-ft-table-header", + { "single-row-selection-table": this.props.rowSelection === ROW_SELECTION.SINGLE }); // When topRightPanel has Add button, it has this.props.topRightPanel.props.className = "properties-at-buttons-container" const topRightPanelHasTableToolbar = (typeof this.props.topRightPanel !== "undefined" && this.props.topRightPanel !== null && typeof this.props.topRightPanel.props.className === "undefined"); diff --git a/canvas_modules/common-canvas/src/common-properties/components/flexible-table/flexible-table.scss b/canvas_modules/common-canvas/src/common-properties/components/flexible-table/flexible-table.scss index f09700bbf7..8a46af3912 100644 --- a/canvas_modules/common-canvas/src/common-properties/components/flexible-table/flexible-table.scss +++ b/canvas_modules/common-canvas/src/common-properties/components/flexible-table/flexible-table.scss @@ -39,6 +39,11 @@ $row-left-padding: $spacing-02; height: $spacing-07; } +.single-row-selection-table { + display: flex; + justify-content: right; +} + .properties-ft-container-panel { height: calc(100% - #{$spacing-07}); // adjust height for table header } diff --git a/canvas_modules/common-canvas/src/common-properties/components/virtualized-table/virtualized-table.jsx b/canvas_modules/common-canvas/src/common-properties/components/virtualized-table/virtualized-table.jsx index d38252cfc4..cdd7e22ae2 100644 --- a/canvas_modules/common-canvas/src/common-properties/components/virtualized-table/virtualized-table.jsx +++ b/canvas_modules/common-canvas/src/common-properties/components/virtualized-table/virtualized-table.jsx @@ -378,7 +378,6 @@ class VirtualizedTable extends React.Component { let selectOption = ""; let selectedRow = false; const rowDisabled = typeof rowData.disabled === "boolean" ? rowData.disabled : false; - if (typeof this.props.rowHeight === "function" && this.props.rowHeight({ index }) === 0) { return null; } diff --git a/canvas_modules/common-canvas/src/common-properties/constants/constants.js b/canvas_modules/common-canvas/src/common-properties/constants/constants.js index 44cc39bd6e..45305b6cbc 100644 --- a/canvas_modules/common-canvas/src/common-properties/constants/constants.js +++ b/canvas_modules/common-canvas/src/common-properties/constants/constants.js @@ -127,6 +127,7 @@ export const MESSAGE_KEYS = { TABLE_TOOLBAR_BUTTON_DELETE: "table.toolbar.button.delete", TABLE_TOOLBAR_BUTTON_EDIT: "table.toolbar.button.edit", TABLE_TOOLBAR_BUTTON_CANCEL: "table.toolbar.button.cancel", + TABLE_DELETEICON_TOOLTIP: "table.deleteIcon.tooltip" }; diff --git a/canvas_modules/common-canvas/src/common-properties/controls/abstract-table.jsx b/canvas_modules/common-canvas/src/common-properties/controls/abstract-table.jsx index 4982014155..0681b3c04d 100644 --- a/canvas_modules/common-canvas/src/common-properties/controls/abstract-table.jsx +++ b/canvas_modules/common-canvas/src/common-properties/controls/abstract-table.jsx @@ -18,9 +18,11 @@ import React from "react"; import PropTypes from "prop-types"; import { Button, Checkbox } from "@carbon/react"; +import { TrashCan } from "@carbon/react/icons"; import FlexibleTable from "./../components/flexible-table"; import TableButtons from "./../components/table-buttons"; import SubPanelCell from "./../panels/sub-panel/cell.jsx"; +import Tooltip from "../../tooltip/tooltip.jsx"; import ReadonlyControl from "./readonly"; import * as PropertyUtils from "./../util/property-utils"; import classNames from "classnames"; @@ -429,7 +431,9 @@ export default class AbstractTable extends React.Component { } makeTableToolbar(selectedRows) { - if ((this.props.addRemoveRows || this.props.control?.moveableRows || this.isSelectSummaryEdit(selectedRows)) && selectedRows?.length > 0) { + if ((this.props.addRemoveRows || this.props.control?.moveableRows || this.isSelectSummaryEdit(selectedRows)) && + selectedRows?.length > 0 && + this.props.control.rowSelection !== ROW_SELECTION.SINGLE) { const multiSelectEditRowPropertyId = { name: this.selectSummaryPropertyName, row: 0 @@ -704,6 +708,9 @@ export default class AbstractTable extends React.Component { // set to specific size. Exclude this column from resizing. headers.push({ "key": "subpanel", "label": "", "width": TABLE_SUBPANEL_BUTTON_WIDTH, "staticWidth": true }); } + if (this.props.control.rowSelection === ROW_SELECTION.SINGLE) { + headers.push({ "key": "deleteRow", "label": "", "width": TABLE_SUBPANEL_BUTTON_WIDTH, "staticWidth": true }); + } return headers; } @@ -733,6 +740,34 @@ export default class AbstractTable extends React.Component { const cell = this.buildChildItem(propertyName, rowIndex, tableState); columns.push(cell); } + if (this.props.control.rowSelection === ROW_SELECTION.SINGLE) { + const toolTip = PropertyUtils.formatMessage(this.reactIntl, MESSAGE_KEYS.TABLE_DELETEICON_TOOLTIP); + const tooltipId = "tooltip-delete-row"; + const deleteOption = ( + +