diff --git a/canvas_modules/common-canvas/__tests__/common-properties/controls/multiselect-test.js b/canvas_modules/common-canvas/__tests__/common-properties/controls/multiselect-test.js new file mode 100644 index 0000000000..e4c06ca0ec --- /dev/null +++ b/canvas_modules/common-canvas/__tests__/common-properties/controls/multiselect-test.js @@ -0,0 +1,352 @@ +/* + * Copyright 2017-2021 Elyra Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import React from "react"; +import MultiSelectControl from "../../../src/common-properties/controls/multiselect"; +import propertyUtils from "../../_utils_/property-utils"; +import tableUtils from "./../../_utils_/table-utils"; +import { mount } from "enzyme"; +import { expect } from "chai"; +import Controller from "../../../src/common-properties/properties-controller"; + +import multiselectParamDef from "../../test_resources/paramDefs/multiselect_paramDef.json"; + + +describe("multiselect renders correctly", () => { + + const propertyName = "test-multiselect"; + const propertyId = { name: propertyName }; + const emptyValueIndicator = "None selected"; + + let controller; + const control = { + "name": "test-multiselect", + "label": { + "text": "multiselect" + }, + "description": { + "text": "multiselect description" + }, + "controlType": "multiselect", + "role": "enum", + "valueDef": { + "propType": "string", + "isList": false, + "isMap": false + }, + "values": [ + "Order", + "Keys", + "Condition", + "Gtt" + ], + "valueLabels": [ + "Order", + "Keys", + "Condition", + "Ranked condition" + ] + }; + + beforeEach(() => { + controller = new Controller(); + propertyUtils.setControls(controller, [control]); + }); + + afterEach(() => { + controller.setErrorMessages({}); + controller.setControlStates({}); + }); + it("props should have been defined", () => { + const wrapper = mount( + + ); + expect(wrapper.prop("control")).to.equal(control); + expect(wrapper.prop("controller")).to.equal(controller); + expect(wrapper.prop("propertyId")).to.equal(propertyId); + }); + + it("should render a multiselect with empty value label", () => { + const wrapper = mount( + + ); + + const multiselectWrapper = wrapper.find("div[data-id='properties-test-multiselect']"); + expect(multiselectWrapper.find("button > span").text()).to.equal(emptyValueIndicator); + }); + + it("multiselect handles null correctly", () => { + controller.setPropertyValues( + { propertyName: null } + ); + const wrapper = mount( + + ); + let multiselectWrapper = wrapper.find("div[data-id='properties-test-multiselect']"); + expect(multiselectWrapper.find("button > span").text()).to.equal(emptyValueIndicator); + const multiselectButton = multiselectWrapper.find("button"); + multiselectButton.simulate("click"); + + // select the first item + multiselectWrapper = wrapper.find("div[data-id='properties-test-multiselect']"); + const multiselectList = multiselectWrapper.find("div.bx--list-box__menu-item"); + expect(multiselectList).to.be.length(4); + multiselectList.at(0).simulate("click"); + const expectedValue = [multiselectList.at(0).text()]; + expect(controller.getPropertyValue(propertyId)).to.eql(expectedValue); + }); + + it("multiselect handles undefined correctly", () => { + controller.setPropertyValues( + { } + ); + const wrapper = mount( + + ); + let multiselectWrapper = wrapper.find("div[data-id='properties-test-multiselect']"); + expect(multiselectWrapper.find("button > span").text()).to.equal(emptyValueIndicator); + // open the multiselect + const multiselectButton = multiselectWrapper.find("button"); + multiselectButton.simulate("click"); + // select the first item + multiselectWrapper = wrapper.find("div[data-id='properties-test-multiselect']"); + const multiselectList = multiselectWrapper.find("div.bx--list-box__menu-item"); + expect(multiselectList).to.be.length(4); + multiselectList.at(0).simulate("click"); + const expectedValue = [multiselectList.at(0).text()]; + expect(controller.getPropertyValue(propertyId)).to.eql(expectedValue); + }); + + it("multiselect renders when disabled", () => { + controller.updateControlState(propertyId, "disabled"); + const wrapper = mount( + + ); + const multiselectWrapper = wrapper.find("div[data-id='properties-test-multiselect']"); + expect(multiselectWrapper.find("MultiSelect").prop("disabled")).to.equal(true); + }); + + it("multiselect renders when hidden", () => { + controller.updateControlState(propertyId, "hidden"); + const wrapper = mount( + + ); + const multiselectWrapper = wrapper.find("div[data-id='properties-test-multiselect']"); + expect(multiselectWrapper.hasClass("hide")).to.equal(true); + }); + + it("Validate multiselect filtered correctly", () => { + controller.setControlStates({ "test-multiselect": { "enumFilter": ["order", "gtt"] } }); + const wrapper = mount( + + ); + let multiselectWrapper = wrapper.find("div[data-id='properties-test-multiselect']"); + // open the multiselect + const multiselectButton = multiselectWrapper.find("button"); + multiselectButton.simulate("click"); + multiselectWrapper = wrapper.find("div[data-id='properties-test-multiselect']"); + // select the first item + const multiselectList = multiselectWrapper.find("div.bx--list-box__menu-item"); + expect(multiselectList).to.be.length(2); + }); + + it("multiselect renders messages correctly", () => { + controller.updateErrorMessage(propertyId, { + validation_id: propertyId.name, + type: "warning", + text: "bad multiselect value" + }); + const wrapper = mount( + + ); + const multiselectWrapper = wrapper.find("div[data-id='properties-test-multiselect']"); + const messageWrapper = multiselectWrapper.find("div.properties-validation-message"); + expect(messageWrapper).to.have.length(1); + }); +}); + +describe("multiselect paramDef works correctly", () => { + let wrapper; + let renderedController; + beforeEach(() => { + const renderedObject = propertyUtils.flyoutEditorForm(multiselectParamDef); + wrapper = renderedObject.wrapper; + renderedController = renderedObject.controller; + }); + afterEach(() => { + wrapper.unmount(); + }); + + it("multiselect placeholder custom label rendered correctly", () => { + let multiselectWrapper = wrapper.find("div[data-id='properties-multiselect_custom_labels']"); + const expectedEmptyLabel = multiselectParamDef.resources["multiselect_custom_labels.multiselect.dropdown.empty.label"]; + expect(multiselectWrapper.find("button > span").text()).to.equal(expectedEmptyLabel); + + const propertyId = { name: "multiselect_custom_labels" }; + const multiselectButton = multiselectWrapper.find("button"); + multiselectButton.simulate("click"); + + multiselectWrapper.update(); + multiselectWrapper = wrapper.find("div[data-id='properties-multiselect_custom_labels']"); + const multiselectList = multiselectWrapper.find("div.bx--list-box__menu-item"); + expect(multiselectList).to.have.length(6); + + multiselectList.at(0).simulate("click"); + const expectedValue = [multiselectList.at(0).text()]; + expect(renderedController.getPropertyValue(propertyId)).to.eql(expectedValue); + + const expectedSelectedLabel = multiselectParamDef.resources["multiselect_custom_labels.multiselect.dropdown.options.selected.label"]; + expect(multiselectWrapper.find("button > span").text()).to.equal(expectedSelectedLabel); + }); + + it("multiselect allows enum label different from enum value", () => { + let multiselectWrapper = wrapper.find("div[data-id='properties-multiselect_multiple_selected']"); + const multiselectButton = multiselectWrapper.find("button"); + multiselectButton.simulate("click"); + + multiselectWrapper.update(); + multiselectWrapper = wrapper.find("div[data-id='properties-multiselect_multiple_selected']"); + const multiselectList = multiselectWrapper.find("div.bx--list-box__menu-item"); + expect(multiselectList).to.have.length(6); + + // The options are not in the order they are defined. Test to verify "Custom" is in the text + expect(multiselectList.at(0).text() + .indexOf("Custom") > -1).to.equal(true); + expect(multiselectList.at(1).text() + .indexOf("Custom") > -1).to.equal(true); + expect(multiselectList.at(2).text() + .indexOf("Custom") > -1).to.equal(true); + expect(multiselectList.at(3).text() + .indexOf("Custom") > -1).to.equal(true); + expect(multiselectList.at(4).text() + .indexOf("Custom") > -1).to.equal(true); + expect(multiselectList.at(5).text() + .indexOf("Custom") > -1).to.equal(true); + }); + + it("multiselect renders correctly in a table - subpanel", () => { + const propertyId02 = { name: "multiselect_table", row: 0, col: 2 }; + propertyUtils.openSummaryPanel(wrapper, "multiselect-table-panel"); + let table = wrapper.find("div[data-id='properties-ci-multiselect_table']"); + + // Verify initial value + const rowOneColTwoInitValue = ["blue"]; + expect(renderedController.getPropertyValue(propertyId02)).to.be.eql(rowOneColTwoInitValue); + + // verify able to select a new option subPanel + const editButtons = table.find("button.properties-subpanel-button"); + expect(editButtons).to.have.length(2); + editButtons.at(0).simulate("click"); + const subPanel = wrapper.find(".properties-editstyle-sub-panel"); + const subPanelMultiselect = subPanel.find("div[data-id='properties-multiselect_table_0_2']"); + + const subPanelMultiselectButton = subPanelMultiselect.find("input"); // filterable multiselect + subPanelMultiselectButton.simulate("click"); + + table.update(); + table = wrapper.find("div[data-id='properties-ci-multiselect_table']"); + const subPanelMultiselectList = table.find("div.bx--list-box__menu-item"); + expect(subPanelMultiselectList).to.have.length(6); + + subPanelMultiselectList.at(1).simulate("click"); + const expectedSubPanelValue = rowOneColTwoInitValue.concat(subPanelMultiselectList.at(1).text()); + expect(JSON.stringify(renderedController.getPropertyValue(propertyId02))).to.equal(JSON.stringify(expectedSubPanelValue)); + }); + + it("multiselect renders correctly in a table - onpanel", () => { + const propertyId11 = { name: "multiselect_table", row: 1, col: 1 }; + propertyUtils.openSummaryPanel(wrapper, "multiselect-table-panel"); + let table = wrapper.find("div[data-id='properties-ci-multiselect_table']"); + + // Verify initial value + expect(renderedController.getPropertyValue(propertyId11)).to.be.eql([]); + + tableUtils.selectCheckboxes(table, [1]); // Select second row for onPanel edit + table = wrapper.find("div[data-id='properties-ci-multiselect_table']"); + + // verify able to select a new option + const multiselectOnPanel = table.find(".properties-onpanel-container"); + const multiselectButton = multiselectOnPanel.find("button"); + multiselectButton.simulate("click"); + + table.update(); + table = wrapper.find("div[data-id='properties-ci-multiselect_table']"); + const multiselectList = table.find("div.bx--list-box__menu-item"); + expect(multiselectList).to.have.length(4); + + multiselectList.at(0).simulate("click"); + const expectedValue = [multiselectList.at(0).text()]; + expect(renderedController.getPropertyValue(propertyId11)).to.eql(expectedValue); + }); +}); + +describe("multiselect classnames appear correctly", () => { + let wrapper; + beforeEach(() => { + const renderedObject = propertyUtils.flyoutEditorForm(multiselectParamDef); + wrapper = renderedObject.wrapper; + }); + + it("multiselect should have custom classname defined", () => { + expect(wrapper.find(".multiselect-control-class")).to.have.length(1); + }); + + it("multiselect should have custom classname defined in table cells", () => { + propertyUtils.openSummaryPanel(wrapper, "multiselect-table-panel"); + expect(wrapper.find(".table-on-panel-multiselect-control-class")).to.have.length(2); + expect(wrapper.find(".table-subpanel-multiselect-control-class")).to.have.length(2); + }); +}); diff --git a/canvas_modules/common-canvas/__tests__/test_resources/paramDefs/multiselect_paramDef.json b/canvas_modules/common-canvas/__tests__/test_resources/paramDefs/multiselect_paramDef.json new file mode 100644 index 0000000000..55987e669f --- /dev/null +++ b/canvas_modules/common-canvas/__tests__/test_resources/paramDefs/multiselect_paramDef.json @@ -0,0 +1,544 @@ +{ + "titleDefinition": { + "title": "MultiSelect" + }, + "current_parameters": { + "multiselect_empty": [], + "multiselect": ["blue"], + "multiselect_multiple_selected": ["orange", "yellow"], + "multiselect_filterable": [], + "multiselect_filterable_single": ["green"], + "multiselect_filterable_multiple_selected": ["orange", "yellow"], + "multiselect_custom_labels": [], + "multiselect_error": [], + "multiselect_warning": [], + "hide": true, + "multiselect_hidden": [], + "disabled": true, + "multiselect_disabled": [], + "multiselect_table": [ + [ + ["cat"], + ["pear"], + ["blue"] + ], + [ + [], + [], + ["red"] + ] + ] + }, + "parameters": [ + { + "id": "multiselect_empty", + "enum": [ + "red", + "orange", + "yellow", + "green", + "blue", + "purple" + ] + }, + { + "id": "multiselect", + "enum": [ + "red", + "orange", + "yellow", + "green", + "blue", + "purple" + ], + "required": true + }, + { + "id": "multiselect_multiple_selected", + "enum": [ + "red", + "orange", + "yellow", + "green", + "blue", + "purple" + ], + "required": true + }, + { + "id": "multiselect_filterable", + "enum": [ + "red", + "orange", + "yellow", + "green", + "blue", + "purple" + ], + "required": true + }, + { + "id": "multiselect_filterable_single", + "enum": [ + "red", + "orange", + "yellow", + "green", + "blue", + "purple" + ], + "required": true + }, + { + "id": "multiselect_filterable_multiple_selected", + "enum": [ + "red", + "orange", + "yellow", + "green", + "blue", + "purple" + ], + "required": true + }, + { + "id": "multiselect_custom_labels", + "enum": [ + "red", + "orange", + "yellow", + "green", + "blue", + "purple" + ], + "required": true + }, + { + "id": "multiselect_error", + "enum": [ + "red", + "orange", + "yellow", + "green", + "blue", + "purple" + ], + "required": true + }, + { + "id": "multiselect_warning", + "enum": [ + "red", + "orange", + "yellow", + "green", + "blue", + "purple" + ] + }, + { + "id": "hide", + "type": "boolean" + }, + { + "id": "multiselect_hidden", + "enum": [ + "red", + "orange", + "yellow", + "green", + "blue", + "purple" + ], + "required": true + }, + { + "id": "disabled", + "type": "boolean" + }, + { + "id": "multiselect_disabled", + "enum": [ + "red", + "orange", + "yellow", + "green", + "blue", + "purple" + ], + "required": true + }, + { + "id": "multiselect_table", + "type": "array[multiselect_table_struct]", + "default": [] + } + ], + "complex_types": [ + { + "id": "multiselect_table_struct", + "parameters": [ + { + "id": "animal", + "enum": [ + "dog", + "cat", + "pig", + "horse", + "all of the above animals" + ], + "default": ["horse"] + }, + { + "id": "fruit", + "enum": [ + "apple", + "orange", + "pear", + "strawberry" + ] + }, + { + "id": "color", + "enum": [ + "red", + "green", + "blue", + "purple", + "orange", + "brown" + ], + "default": ["red"] + } + ] + } +], + "uihints": { + "id": "multiselect", + "icon": "images/default.svg", + "label": { + "default": "MultiSelect" + }, + "parameter_info": [ + { + "parameter_ref": "multiselect_empty", + "label": { + "default": "multiselect" + }, + "description": { + "default": "multiselect no options selected" + }, + "class_name": "multiselect-control-class", + "control": "multiselect" + }, + { + "parameter_ref": "multiselect", + "label": { + "default": "multiselect one option selected" + }, + "description": { + "default": "multiselect with parameter value set to 'blue'" + }, + "control": "multiselect" + }, + { + "parameter_ref": "multiselect_multiple_selected", + "label": { + "default": "multiselect multiple options selected" + }, + "description": { + "default": "multiselect with multiple options selected with custom labels" + }, + "control": "multiselect" + }, + { + "parameter_ref": "multiselect_filterable", + "label": { + "default": "multiselect filterable no options selected" + }, + "description": { + "default": "multiselect dropdown with filter enabled" + }, + "control": "multiselect", + "filterable": true + }, + { + "parameter_ref": "multiselect_filterable_single", + "label": { + "default": "multiselect filterable one option selected" + }, + "description": { + "default": "multiselect dropdown with filter enabled and one option selected" + }, + "control": "multiselect", + "filterable": true + }, + { + "parameter_ref": "multiselect_filterable_multiple_selected", + "label": { + "default": "multiselect filterable multiple options selected" + }, + "description": { + "default": "multiselect dropdown with filter enabled and multiple options selected" + }, + "control": "multiselect", + "filterable": true + }, + { + "parameter_ref": "multiselect_custom_labels", + "label": { + "default": "multiselect custom labels" + }, + "description": { + "default": "multiselect dropdown with custom labels set in resources" + }, + "control": "multiselect" + }, + { + "parameter_ref": "multiselect_error", + "label": { + "default": "multiselect error" + }, + "description": { + "default": "multiselect dropdown with error when set to 'red'", + "placement": "on_panel" + }, + "control": "multiselect" + }, + { + "parameter_ref": "multiselect_warning", + "label": { + "default": "multiselect warning" + }, + "description": { + "default": "Shouldn't be empty, cannot equal []", + "placement": "on_panel" + }, + "control": "multiselect", + "filterable": true + }, + { + "parameter_ref": "hide", + "label": { + "default": "hide 'multiselect hidden'" + } + }, + { + "parameter_ref": "multiselect_hidden", + "label": { + "default": "multiselect hidden" + }, + "description": { + "default": "multiselect dropdown hidden" + }, + "control": "multiselect" + }, + { + "parameter_ref": "disabled", + "label": { + "default": "disable 'multiselect disabled'" + } + }, + { + "parameter_ref": "multiselect_disabled", + "label": { + "default": "multiselect disabled" + }, + "description": { + "default": "multiselect dropdown disabled" + }, + "control": "multiselect" + }, + { + "parameter_ref": "multiselect_table", + "label": { + "default": "multiselect table" + }, + "description": { + "default": "A multiselect should not be displayed in the table 'inline'. This control is best used 'on_panel' or in a 'subpanel'. As shown below, if 'inline', the select options will be clipped within the row.", + "placement": "on_panel" + } + } + ], + "complex_type_info": [ + { + "complex_type_ref": "multiselect_table_struct", + "parameters": [ + { + "parameter_ref": "animal", + "label": { + "default": "Pet inline" + }, + "description": { + "default": "Pet" + }, + "width": 10, + "edit_style": "inline", + "control": "multiselect", + "class_name": "table-multiselect-control-class" + }, + { + "parameter_ref": "fruit", + "label": { + "default": "Fruit on-panel" + }, + "description": { + "default": "Fruit" + }, + "width": 10, + "edit_style": "on_panel", + "control": "multiselect", + "class_name": "table-on-panel-multiselect-control-class" + }, + { + "parameter_ref": "color", + "label": { + "default": "color" + }, + "description": { + "default": "color subpanel" + }, + "width": 10, + "edit_style": "subpanel", + "control": "multiselect", + "filterable": true, + "class_name": "table-subpanel-multiselect-control-class" + } + ] + } + ], + "group_info": [ + { + "id": "multiselect-values", + "label": { + "default": "Values" + }, + "type": "controls", + "parameter_refs": [ + "multiselect_empty", + "multiselect", + "multiselect_multiple_selected", + "multiselect_filterable", + "multiselect_filterable_single", + "multiselect_filterable_multiple_selected", + "multiselect_custom_labels" + ] + }, + { + "id": "multiselect-conditions", + "label": { + "default": "Conditions" + }, + "type": "controls", + "parameter_refs": [ + "multiselect_error", + "multiselect_warning", + "hide", + "multiselect_hidden", + "disabled", + "multiselect_disabled" + ] + }, + { + "id": "multiselect-tables", + "label": { + "default": "Table" + }, + "type": "panels", + "group_info": [ + { + "id": "multiselect-table-panel", + "type": "summaryPanel", + "label": { + "default": "multiselect in a table" + }, + "group_info": [ + { + "id": "multiselect-table-controls", + "parameter_refs": [ + "multiselect_table" + ] + } + ] + } + ] + } + ] + }, + "conditions": [ + { + "validation": { + "fail_message": { + "type": "error", + "focus_parameter_ref": "multiselect_error", + "message": { + "default": "Don't select 'red'" + } + }, + "evaluate": { + "condition": { + "parameter_ref": "multiselect_error", + "op": "notContains", + "value": "red" + } + } + } + }, + { + "validation": { + "fail_message": { + "type": "warning", + "focus_parameter_ref": "multiselect_warning", + "message": { + "default": "Shouldn't be empty, cannot equal []" + } + }, + "evaluate": { + "condition": { + "parameter_ref": "multiselect_warning", + "op": "notEquals", + "value": [] + } + } + } + }, + { + "visible": { + "parameter_refs": [ + "multiselect_hidden" + ], + "evaluate": { + "condition": { + "parameter_ref": "hide", + "op": "equals", + "value": false + } + } + } + }, + { + "enabled": { + "parameter_refs": [ + "multiselect_disabled" + ], + "evaluate": { + "condition": { + "parameter_ref": "disabled", + "op": "equals", + "value": false + } + } + } + } + ], + "resources": { + "multiselect_multiple_selected.red.label": "Custom red", + "multiselect_multiple_selected.orange.label": "Custom orange", + "multiselect_multiple_selected.yellow.label": "Custom yellow", + "multiselect_multiple_selected.green.label": "Custom green", + "multiselect_multiple_selected.blue.label": "Custom blue", + "multiselect_multiple_selected.purple.label": "Custom purple", + "multiselect_custom_labels.multiselect.dropdown.empty.label": "nothing selected yet", + "multiselect_custom_labels.multiselect.dropdown.options.selected.label": "options are selected" + } +} 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 fb3ab8dd09..3a4d065eaf 100644 --- a/canvas_modules/common-canvas/locales/common-properties/locales/en.json +++ b/canvas_modules/common-canvas/locales/common-properties/locales/en.json @@ -70,8 +70,12 @@ "list.table.label": "Values", "dropdown.tooltip.openMenu": "Open menu", "dropdown.tooltip.closeMenu": "Close menu", + "dropdown.tooltip.clear.all": "Clear all", + "dropdown.tooltip.clear.selection": "Clear selection", "truncate.long.string.error": "These values exceed the display limit of {truncate_limit} characters and can't be edited.", "properties.label": "Properties", "readonlytable.edit.button.label": "Edit", - "toggletext.icon.description": "{toggletext_label} Icon" + "toggletext.icon.description": "{toggletext_label} Icon", + "multiselect.dropdown.empty.label": "None selected", + "multiselect.dropdown.options.selected.label": "options selected" } 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 8ad8d34f38..12050d5aa3 100644 --- a/canvas_modules/common-canvas/locales/common-properties/locales/eo.json +++ b/canvas_modules/common-canvas/locales/common-properties/locales/eo.json @@ -71,8 +71,12 @@ "list.table.label": "[Esperanto~Values~~~~eo]", "dropdown.tooltip.openMenu": "[Esperanto~Open menu~~~~eo]", "dropdown.tooltip.closeMenu": "[Esperanto~Close menu~~~~~~eo]", + "dropdown.tooltip.clear.all": "[Esperanto~Clear all~~~~~~eo]", + "dropdown.tooltip.clear.selection": "[Esperanto~Clear selection~~~~~~eo]", "truncate.long.string.error": "[Esperanto~These values exceed the display limit of {truncate_limit} characters and can't be edited.~~~~~~~~~~~~eo]", "properties.label": "[Esperanto~Properties~~~~~~eo]", "readonlytable.edit.button.label": "[Esperanto~Edit~eo]", - "toggletext.icon.description": "[Esperanto~{toggletext_label} Icon~~~~eo]" + "toggletext.icon.description": "[Esperanto~{toggletext_label} Icon~~~~eo]", + "multiselect.dropdown.empty.label": "[Esperanto~None selected~~~~~~eo]", + "multiselect.dropdown.options.selected.label": "[Esperanto~options selected~~~~~~eo]" } 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 98768f2b68..6df483ae9a 100644 --- a/canvas_modules/common-canvas/src/common-properties/constants/constants.js +++ b/canvas_modules/common-canvas/src/common-properties/constants/constants.js @@ -1,5 +1,5 @@ /* - * Copyright 2017-2020 Elyra Authors + * Copyright 2017-2021 Elyra Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -92,10 +92,14 @@ _defineConstant("MESSAGE_KEYS", { LIST_TABLE_LABEL: "list.table.label", DROPDOWN_TOOLTIP_OPENMENU: "dropdown.tooltip.openMenu", DROPDOWN_TOOLTIP_CLOSEMENU: "dropdown.tooltip.closeMenu", + DROPDOWN_TOOLTIP_CLEARALL: "dropdown.tooltip.clear.all", + DROPDOWN_TOOLTIP_CLEARSELECTION: "dropdown.tooltip.clear.selection", TRUNCATE_LONG_STRING_ERROR: "truncate.long.string.error", PROPERTIES_LABEL: "properties.label", READONLYTABLE_EDIT_BUTTON_LABEL: "readonlytable.edit.button.label", - TOGGLETEXT_ICON_DESCRIPTION: "toggletext.icon.description" + TOGGLETEXT_ICON_DESCRIPTION: "toggletext.icon.description", + MULTISELECT_DROPDOWN_EMPTY_LABEL: "multiselect.dropdown.empty.label", + MULTISELECT_DROPDOWN_OPTIONS_SELECTED_LABEL: "multiselect.dropdown.options.selected.label" }); _defineConstant("CHARACTER_LIMITS", { diff --git a/canvas_modules/common-canvas/src/common-properties/constants/form-constants.js b/canvas_modules/common-canvas/src/common-properties/constants/form-constants.js index 9bb82b854d..7c716cdd82 100644 --- a/canvas_modules/common-canvas/src/common-properties/constants/form-constants.js +++ b/canvas_modules/common-canvas/src/common-properties/constants/form-constants.js @@ -1,5 +1,5 @@ /* - * Copyright 2017-2020 Elyra Authors + * Copyright 2017-2021 Elyra Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -81,6 +81,7 @@ const ControlType = { RADIOSET: "radioset", CHECKBOXSET: "checkboxset", ONEOFSELECT: "oneofselect", + MULTISELECT: "multiselect", SOMEOFSELECT: "someofselect", SELECTCOLUMN: "selectcolumn", SELECTCOLUMNS: "selectcolumns", 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 22a28b3307..92d72ede35 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 @@ -1,5 +1,5 @@ /* - * Copyright 2017-2020 Elyra Authors + * Copyright 2017-2021 Elyra Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -38,6 +38,7 @@ import CheckboxControl from "./checkbox"; import CheckboxsetControl from "./checkboxset"; import RadiosetControl from "./radioset"; import Dropdown from "./dropdown"; +import MultiSelectControl from "./multiselect"; import SomeofselectControl from "./someofselect"; import SelectColumnsControl from "./selectcolumns"; import StructureEditorControl from "./structureeditor"; @@ -211,6 +212,9 @@ export default class ControlFactory { rightFlyout={this.rightFlyout} />); break; + case (ControlType.MULTISELECT): + createdControl = (); + break; case (ControlType.SELECTCOLUMN): if (!tableInfo || (tableInfo && tableInfo.allowColumnControls)) { createdControl = ( selectedOptions.push(options.find(function(option) { + return option.value === value; + }))); + } + return selectedOptions; + } + + genSelectOptions(selectedValues) { + const options = []; + for (let j = 0; j < this.props.controlOpts.values.length; j++) { + options.push({ + value: this.props.controlOpts.values[j], + label: this.props.controlOpts.valueLabels[j] + }); + } + const selectedOptions = this.getSelectedOption(options, selectedValues); + return { + options: options, + selectedOptions: selectedOptions + }; + } + + handleOnChange(evt) { + const controlValues = []; + for (let i = 0; i < evt.selectedItems.length; i++) { + controlValues.push(evt.selectedItems[i].value); + } + this.props.controller.updatePropertyValue(this.props.propertyId, controlValues); + } + + render() { + const multiSelectDropdown = this.genSelectOptions(this.props.value); + + const listBoxMenuIconTranslationIds = { + "close.menu": formatMessage(this.reactIntl, MESSAGE_KEYS.DROPDOWN_TOOLTIP_CLOSEMENU), + "open.menu": formatMessage(this.reactIntl, MESSAGE_KEYS.DROPDOWN_TOOLTIP_OPENMENU), + "clear.all": formatMessage(this.reactIntl, MESSAGE_KEYS.DROPDOWN_TOOLTIP_CLEARALL), + "clear.selection": formatMessage(this.reactIntl, MESSAGE_KEYS.DROPDOWN_TOOLTIP_CLEARSELECTION) + }; + + const overrideEmptyLabelKey = `${this.props.control.name}.multiselect.dropdown.empty.label`; + const defaultEmptyLabel = formatMessage(this.reactIntl, MESSAGE_KEYS.MULTISELECT_DROPDOWN_EMPTY_LABEL); + const overrideOptionsSelectedLabelKey = `${this.props.control.name}.multiselect.dropdown.options.selected.label`; + const defaultOptionsSelectedLabel = formatMessage(this.reactIntl, MESSAGE_KEYS.MULTISELECT_DROPDOWN_OPTIONS_SELECTED_LABEL); + + let label = ""; + if (multiSelectDropdown.selectedOptions.length === 0) { // Display message for no options selected + label = this.props.controller.getResource(overrideEmptyLabelKey, defaultEmptyLabel); + } else { // Display message for multiple options selected + label = this.props.controller.getResource(overrideOptionsSelectedLabelKey, defaultOptionsSelectedLabel); + } + + let dropdownComponent = null; + if (this.props.control.filterable) { + dropdownComponent = ( listBoxMenuIconTranslationIds[id]} + items={multiSelectDropdown.options} + initialSelectedItems={multiSelectDropdown.selectedOptions} + onChange={this.handleOnChange} + placeholder={label} + light + />); + } else { + dropdownComponent = ( listBoxMenuIconTranslationIds[id]} + items={multiSelectDropdown.options} + initialSelectedItems={multiSelectDropdown.selectedOptions} + onChange={this.handleOnChange} + label={label} + light + />); + } + + return ( +
+ {dropdownComponent} + +
+ ); + } +} + +MultiSelectControl.propTypes = { + control: PropTypes.object.isRequired, + propertyId: PropTypes.object.isRequired, + controller: PropTypes.object.isRequired, + tableControl: PropTypes.bool, + controlOpts: PropTypes.object, // pass in by redux + state: PropTypes.string, // pass in by redux + value: PropTypes.array, // pass in by redux + messageInfo: PropTypes.object // pass in by redux +}; + +const mapStateToProps = (state, ownProps) => { + const props = { + value: ownProps.controller.getPropertyValue(ownProps.propertyId), + state: ownProps.controller.getControlState(ownProps.propertyId), + messageInfo: ownProps.controller.getErrorMessage(ownProps.propertyId), + controlOpts: ownProps.controller.getFilteredEnumItems(ownProps.propertyId, ownProps.control) + }; + return props; +}; + +export default connect(mapStateToProps, null)(MultiSelectControl); diff --git a/canvas_modules/common-canvas/src/common-properties/form/EditorForm.js b/canvas_modules/common-canvas/src/common-properties/form/EditorForm.js index 169c0050ff..af6626b7ab 100644 --- a/canvas_modules/common-canvas/src/common-properties/form/EditorForm.js +++ b/canvas_modules/common-canvas/src/common-properties/form/EditorForm.js @@ -1,5 +1,5 @@ /* - * Copyright 2017-2020 Elyra Authors + * Copyright 2017-2021 Elyra Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,8 +18,7 @@ import { Control } from "./ControlInfo"; import { UIItem } from "./UIItem"; -import { GroupType, PanelType, Type, ControlType, ParamRole } from "../constants/form-constants"; -import { ORIENTATIONS } from "../constants/form-constants.js"; +import { GroupType, PanelType, Type, ControlType, ParamRole, ORIENTATIONS } from "../constants/form-constants"; import logger from "../../../utils/logger"; import { StructureDef } from "./StructureInfo"; import { Action } from "./ActionInfo"; diff --git a/canvas_modules/harness/src/client/components/common-properties-components.jsx b/canvas_modules/harness/src/client/components/common-properties-components.jsx index 62d538d1bf..085aad1baf 100644 --- a/canvas_modules/harness/src/client/components/common-properties-components.jsx +++ b/canvas_modules/harness/src/client/components/common-properties-components.jsx @@ -1,5 +1,5 @@ /* - * Copyright 2017-2020 Elyra Authors + * Copyright 2017-2021 Elyra Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -57,6 +57,8 @@ import { ONEOFSELECT_PROPS_INFO, ONEOFSELECT_CUSTOM_VALUE_PROPS_INFO, FORCED_RADIOSET_PROPS_INFO, + MULTISELECT_PROPS_INFO, + MULTISELECT_FILTERABLE_PROPS_INFO, SOMEOFSELECT_PROPS_INFO, FORCED_CHECKBOX_SET_PROPS_INFO, SELECTSCHEMA_PROPS_INFO, @@ -251,7 +253,7 @@ class CommonPropertiesComponents extends React.Component { "id", "type", "role", "enum", "required", "default", "uihints", "parameter_info", - "parameter_ref", "control", "label", "moveable_rows", "rows", + "parameter_ref", "control", "label", "moveable_rows", "rows", "filterable", "description", "language", "orientation" @@ -366,6 +368,7 @@ class CommonPropertiesComponents extends React.Component { "--checkboxset", "--radioset", "--oneofselect", + "--multiselect", "--someofselect", "--selectschema", "--selectcolumn", @@ -1194,6 +1197,49 @@ class CommonPropertiesComponents extends React.Component { + +
+

multiselect

+

A multi-selection dropdown control is rendered when the control is + set to multiselect in the uihints section + of the parameter_info. +

+
+
+ + {this.renderRightFlyoutButton(MULTISELECT_PROPS_INFO)} +
+
+
+								{this.jsonReplacer(MULTISELECT_PROPS_INFO.parameterDef, "control")}
+							
+
+
+

If filterable is set to true, this dropdown selection can be filtered. +

+
+
+ + {this.renderRightFlyoutButton(MULTISELECT_FILTERABLE_PROPS_INFO)} +
+
+
+								{this.jsonReplacer(MULTISELECT_FILTERABLE_PROPS_INFO.parameterDef, "custom",
+									["uihints",
+										"id", "parameter_info",
+										"parameter_info", "label", "description", "default", "control", "filterable"
+									])}
+							
+
+
+
+

someofselect

A multi-selection control is rendered for a parameter with an enum list diff --git a/canvas_modules/harness/src/client/components/common-properties-conditions.jsx b/canvas_modules/harness/src/client/components/common-properties-conditions.jsx index 2278f2e94a..de07f2e53d 100644 --- a/canvas_modules/harness/src/client/components/common-properties-conditions.jsx +++ b/canvas_modules/harness/src/client/components/common-properties-conditions.jsx @@ -1,5 +1,5 @@ /* - * Copyright 2017-2020 Elyra Authors + * Copyright 2017-2021 Elyra Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -39,6 +39,7 @@ import { RADIOSET_HORIZONTAL_ERROR_PROPS_INFO, RADIOSET_VERTICAL_WARNING_PROPS_INFO, ONEOFSELECT_ERROR_PROPS_INFO, + MULTISELECT_ERROR_PROPS_INFO, SOMEOFSELECT_ERROR_PROPS_INFO, SELECTCOLUMN_ERROR_PROPS_INFO, SELECTCOLUMNS_ERROR_PROPS_INFO, @@ -328,6 +329,8 @@ class CommonPropertiesComponents extends React.Component { dmMeasurementEquals: "no", dmMeasurementNotEquals: "no", dmRoleEquals: "no", dmRoleNotEquals: "no", lengthEquals: "no", lengthGreaterThan: "no", lengthLessThan: "no" }, { Control: "oneofselect (string)", empty: "yes", greaterLessThan: "no", equals: "yes", contains: "yes", matches: "yes", colNotExists: "no", isDateTime: "no", dmTypeEquals: "no", dmTypeNotEquals: "no", dmMeasurementEquals: "no", dmMeasurementNotEquals: "no", dmRoleEquals: "no", dmRoleNotEquals: "no", lengthEquals: "yes", lengthGreaterThan: "yes", lengthLessThan: "yes" }, + { Control: "multiselect ([string])", empty: "yes", greaterLessThan: "no", equals: "yes", contains: "yes", matches: "no", colNotExists: "no", isDateTime: "no", dmTypeEquals: "no", dmTypeNotEquals: "no", + dmMeasurementEquals: "no", dmMeasurementNotEquals: "no", dmRoleEquals: "no", dmRoleNotEquals: "no", lengthEquals: "yes", lengthGreaterThan: "yes", lengthLessThan: "yes" }, { Control: "timeField (time)", empty: "yes", greaterLessThan: "no", equals: "yes", contains: "yes", matches: "no", colNotExists: "no", isDateTime: "yes", dmTypeEquals: "no", dmTypeNotEquals: "no", dmMeasurementEquals: "no", dmMeasurementNotEquals: "no", dmRoleEquals: "no", dmRoleNotEquals: "no", lengthEquals: "no", lengthGreaterThan: "no", lengthLessThan: "no" }, { Control: "dateField (date)", empty: "yes", greaterLessThan: "no", equals: "yes", contains: "yes", matches: "no", colNotExists: "no", isDateTime: "yes", dmTypeEquals: "no", dmTypeNotEquals: "no", @@ -779,6 +782,27 @@ class CommonPropertiesComponents extends React.Component {

+ +
+

multiselect

+

The multiselect control is of type [string]. + The below example shows an error if the option 'red' is selected. +

+
+
+ +
+
+
+								{this.jsonReplacer(MULTISELECT_ERROR_PROPS_INFO.parameterDef, "conditions")}
+							
+
+
+
+

someofselect

A someofselect control is of type [string]. @@ -1061,8 +1085,9 @@ class CommonPropertiesComponents extends React.Component {

Filtered Enumeration Conditions

The enum_filter condition operates upon controls whose parameter is backed by an enumerated list of options. This includes radioset, checkboxset, - and droplist controls. When the condition is true, enum_filter conditions allow authors - to dynamically filter the available enumeration options based upon the state of other parameters. + and droplist controls, but excluding multiselect. When + the condition is true, enum_filter conditions allow authors to dynamically filter the available + enumeration options based upon the state of other parameters.

diff --git a/canvas_modules/harness/src/client/constants/conditions-documentation-constants.js b/canvas_modules/harness/src/client/constants/conditions-documentation-constants.js index 327656b813..3a2217f137 100644 --- a/canvas_modules/harness/src/client/constants/conditions-documentation-constants.js +++ b/canvas_modules/harness/src/client/constants/conditions-documentation-constants.js @@ -1434,6 +1434,75 @@ _defineConstant("ONEOFSELECT_ERROR_PROPS_INFO", { } } }); +_defineConstant("MULTISELECT_ERROR_PROPS_INFO", { + "title": "Multiselect Title", + "parameterDef": { + "current_parameters": { + "multiselectList": [] + }, + "parameters": [ + { + "id": "multiselectList", + "enum": [ + "red", + "orange", + "yellow", + "green", + "blue", + "purple" + ] + } + ], + "uihints": { + "id": "multiselectList", + "parameter_info": [ + { + "parameter_ref": "multiselectList", + "label": { + "default": "Multiselect Control Name" + }, + "description": { + "default": "Select multiple options from the 'multiselect' dropdown, besides 'red'" + }, + "control": "multiselect" + } + ], + "group_info": [ + { + "id": "Multiselect Control", + "type": "controls", + "parameter_refs": [ + "multiselectList" + ] + } + ] + }, + "conditions": [ + { + "validation": { + "fail_message": { + "type": "error", + "message": { + "default": "an option must be selected.", + "resource_key": "multiselectList_invalid" + }, + "focus_parameter_ref": "multiselectList" + }, + "evaluate": { + "condition": { + "parameter_ref": "multiselectList", + "op": "notContains", + "value": "red" + } + } + } + } + ], + "resources": { + "multiselectList_invalid": "The option red should not be selected." + } + } +}); _defineConstant("SOMEOFSELECT_ERROR_PROPS_INFO", { "title": "Some of Select Title", "parameterDef": { diff --git a/canvas_modules/harness/src/client/constants/properties-documentation-constants.js b/canvas_modules/harness/src/client/constants/properties-documentation-constants.js index da979b1ffe..130e1bc6d2 100644 --- a/canvas_modules/harness/src/client/constants/properties-documentation-constants.js +++ b/canvas_modules/harness/src/client/constants/properties-documentation-constants.js @@ -2441,6 +2441,107 @@ _defineConstant("FORCED_RADIOSET_PROPS_INFO", { ] } }); +_defineConstant("MULTISELECT_PROPS_INFO", { + "title": "Multiselect Title", + "parameterDef": { + "titleDefinition": { + "title": "Control: multiselect", + "editable": false + }, + "current_parameters": { + "multiselectList": ["blue"] + }, + "parameters": [ + { + "id": "multiselectList", + "enum": [ + "red", + "orange", + "yellow", + "green", + "blue", + "purple" + ], + "default": ["yellow"] + } + ], + "uihints": { + "id": "multiselectList", + "parameter_info": [ + { + "parameter_ref": "multiselectList", + "label": { + "default": "Multiselect Control Name" + }, + "description": { + "default": "multiselect test" + }, + "control": "multiselect" + } + ], + "group_info": [ + { + "id": "Multiselect Control", + "type": "controls", + "parameter_refs": [ + "multiselectList" + ] + } + ] + } + } +}); +_defineConstant("MULTISELECT_FILTERABLE_PROPS_INFO", { + "title": "Multiselect Title", + "parameterDef": { + "titleDefinition": { + "title": "Control: multiselect", + "editable": false + }, + "current_parameters": { + "multiselectList": [] + }, + "parameters": [ + { + "id": "multiselectList", + "enum": [ + "red", + "orange", + "yellow", + "green", + "blue", + "purple" + ], + "default": ["yellow"] + } + ], + "uihints": { + "id": "multiselectList", + "parameter_info": [ + { + "parameter_ref": "multiselectList", + "label": { + "default": "Multiselect Control Name" + }, + "description": { + "default": "multiselect test" + }, + "control": "multiselect", + "filterable": true + } + ], + "group_info": [ + { + "id": "Multiselect Control", + "type": "controls", + "parameter_refs": [ + "multiselectList" + ] + } + ] + } + } +}); _defineConstant("SOMEOFSELECT_PROPS_INFO", { "title": "Some of Select Title", "parameterDef": { diff --git a/canvas_modules/harness/test_resources/parameterDefs/multiselect_paramDef.json b/canvas_modules/harness/test_resources/parameterDefs/multiselect_paramDef.json new file mode 100644 index 0000000000..55987e669f --- /dev/null +++ b/canvas_modules/harness/test_resources/parameterDefs/multiselect_paramDef.json @@ -0,0 +1,544 @@ +{ + "titleDefinition": { + "title": "MultiSelect" + }, + "current_parameters": { + "multiselect_empty": [], + "multiselect": ["blue"], + "multiselect_multiple_selected": ["orange", "yellow"], + "multiselect_filterable": [], + "multiselect_filterable_single": ["green"], + "multiselect_filterable_multiple_selected": ["orange", "yellow"], + "multiselect_custom_labels": [], + "multiselect_error": [], + "multiselect_warning": [], + "hide": true, + "multiselect_hidden": [], + "disabled": true, + "multiselect_disabled": [], + "multiselect_table": [ + [ + ["cat"], + ["pear"], + ["blue"] + ], + [ + [], + [], + ["red"] + ] + ] + }, + "parameters": [ + { + "id": "multiselect_empty", + "enum": [ + "red", + "orange", + "yellow", + "green", + "blue", + "purple" + ] + }, + { + "id": "multiselect", + "enum": [ + "red", + "orange", + "yellow", + "green", + "blue", + "purple" + ], + "required": true + }, + { + "id": "multiselect_multiple_selected", + "enum": [ + "red", + "orange", + "yellow", + "green", + "blue", + "purple" + ], + "required": true + }, + { + "id": "multiselect_filterable", + "enum": [ + "red", + "orange", + "yellow", + "green", + "blue", + "purple" + ], + "required": true + }, + { + "id": "multiselect_filterable_single", + "enum": [ + "red", + "orange", + "yellow", + "green", + "blue", + "purple" + ], + "required": true + }, + { + "id": "multiselect_filterable_multiple_selected", + "enum": [ + "red", + "orange", + "yellow", + "green", + "blue", + "purple" + ], + "required": true + }, + { + "id": "multiselect_custom_labels", + "enum": [ + "red", + "orange", + "yellow", + "green", + "blue", + "purple" + ], + "required": true + }, + { + "id": "multiselect_error", + "enum": [ + "red", + "orange", + "yellow", + "green", + "blue", + "purple" + ], + "required": true + }, + { + "id": "multiselect_warning", + "enum": [ + "red", + "orange", + "yellow", + "green", + "blue", + "purple" + ] + }, + { + "id": "hide", + "type": "boolean" + }, + { + "id": "multiselect_hidden", + "enum": [ + "red", + "orange", + "yellow", + "green", + "blue", + "purple" + ], + "required": true + }, + { + "id": "disabled", + "type": "boolean" + }, + { + "id": "multiselect_disabled", + "enum": [ + "red", + "orange", + "yellow", + "green", + "blue", + "purple" + ], + "required": true + }, + { + "id": "multiselect_table", + "type": "array[multiselect_table_struct]", + "default": [] + } + ], + "complex_types": [ + { + "id": "multiselect_table_struct", + "parameters": [ + { + "id": "animal", + "enum": [ + "dog", + "cat", + "pig", + "horse", + "all of the above animals" + ], + "default": ["horse"] + }, + { + "id": "fruit", + "enum": [ + "apple", + "orange", + "pear", + "strawberry" + ] + }, + { + "id": "color", + "enum": [ + "red", + "green", + "blue", + "purple", + "orange", + "brown" + ], + "default": ["red"] + } + ] + } +], + "uihints": { + "id": "multiselect", + "icon": "images/default.svg", + "label": { + "default": "MultiSelect" + }, + "parameter_info": [ + { + "parameter_ref": "multiselect_empty", + "label": { + "default": "multiselect" + }, + "description": { + "default": "multiselect no options selected" + }, + "class_name": "multiselect-control-class", + "control": "multiselect" + }, + { + "parameter_ref": "multiselect", + "label": { + "default": "multiselect one option selected" + }, + "description": { + "default": "multiselect with parameter value set to 'blue'" + }, + "control": "multiselect" + }, + { + "parameter_ref": "multiselect_multiple_selected", + "label": { + "default": "multiselect multiple options selected" + }, + "description": { + "default": "multiselect with multiple options selected with custom labels" + }, + "control": "multiselect" + }, + { + "parameter_ref": "multiselect_filterable", + "label": { + "default": "multiselect filterable no options selected" + }, + "description": { + "default": "multiselect dropdown with filter enabled" + }, + "control": "multiselect", + "filterable": true + }, + { + "parameter_ref": "multiselect_filterable_single", + "label": { + "default": "multiselect filterable one option selected" + }, + "description": { + "default": "multiselect dropdown with filter enabled and one option selected" + }, + "control": "multiselect", + "filterable": true + }, + { + "parameter_ref": "multiselect_filterable_multiple_selected", + "label": { + "default": "multiselect filterable multiple options selected" + }, + "description": { + "default": "multiselect dropdown with filter enabled and multiple options selected" + }, + "control": "multiselect", + "filterable": true + }, + { + "parameter_ref": "multiselect_custom_labels", + "label": { + "default": "multiselect custom labels" + }, + "description": { + "default": "multiselect dropdown with custom labels set in resources" + }, + "control": "multiselect" + }, + { + "parameter_ref": "multiselect_error", + "label": { + "default": "multiselect error" + }, + "description": { + "default": "multiselect dropdown with error when set to 'red'", + "placement": "on_panel" + }, + "control": "multiselect" + }, + { + "parameter_ref": "multiselect_warning", + "label": { + "default": "multiselect warning" + }, + "description": { + "default": "Shouldn't be empty, cannot equal []", + "placement": "on_panel" + }, + "control": "multiselect", + "filterable": true + }, + { + "parameter_ref": "hide", + "label": { + "default": "hide 'multiselect hidden'" + } + }, + { + "parameter_ref": "multiselect_hidden", + "label": { + "default": "multiselect hidden" + }, + "description": { + "default": "multiselect dropdown hidden" + }, + "control": "multiselect" + }, + { + "parameter_ref": "disabled", + "label": { + "default": "disable 'multiselect disabled'" + } + }, + { + "parameter_ref": "multiselect_disabled", + "label": { + "default": "multiselect disabled" + }, + "description": { + "default": "multiselect dropdown disabled" + }, + "control": "multiselect" + }, + { + "parameter_ref": "multiselect_table", + "label": { + "default": "multiselect table" + }, + "description": { + "default": "A multiselect should not be displayed in the table 'inline'. This control is best used 'on_panel' or in a 'subpanel'. As shown below, if 'inline', the select options will be clipped within the row.", + "placement": "on_panel" + } + } + ], + "complex_type_info": [ + { + "complex_type_ref": "multiselect_table_struct", + "parameters": [ + { + "parameter_ref": "animal", + "label": { + "default": "Pet inline" + }, + "description": { + "default": "Pet" + }, + "width": 10, + "edit_style": "inline", + "control": "multiselect", + "class_name": "table-multiselect-control-class" + }, + { + "parameter_ref": "fruit", + "label": { + "default": "Fruit on-panel" + }, + "description": { + "default": "Fruit" + }, + "width": 10, + "edit_style": "on_panel", + "control": "multiselect", + "class_name": "table-on-panel-multiselect-control-class" + }, + { + "parameter_ref": "color", + "label": { + "default": "color" + }, + "description": { + "default": "color subpanel" + }, + "width": 10, + "edit_style": "subpanel", + "control": "multiselect", + "filterable": true, + "class_name": "table-subpanel-multiselect-control-class" + } + ] + } + ], + "group_info": [ + { + "id": "multiselect-values", + "label": { + "default": "Values" + }, + "type": "controls", + "parameter_refs": [ + "multiselect_empty", + "multiselect", + "multiselect_multiple_selected", + "multiselect_filterable", + "multiselect_filterable_single", + "multiselect_filterable_multiple_selected", + "multiselect_custom_labels" + ] + }, + { + "id": "multiselect-conditions", + "label": { + "default": "Conditions" + }, + "type": "controls", + "parameter_refs": [ + "multiselect_error", + "multiselect_warning", + "hide", + "multiselect_hidden", + "disabled", + "multiselect_disabled" + ] + }, + { + "id": "multiselect-tables", + "label": { + "default": "Table" + }, + "type": "panels", + "group_info": [ + { + "id": "multiselect-table-panel", + "type": "summaryPanel", + "label": { + "default": "multiselect in a table" + }, + "group_info": [ + { + "id": "multiselect-table-controls", + "parameter_refs": [ + "multiselect_table" + ] + } + ] + } + ] + } + ] + }, + "conditions": [ + { + "validation": { + "fail_message": { + "type": "error", + "focus_parameter_ref": "multiselect_error", + "message": { + "default": "Don't select 'red'" + } + }, + "evaluate": { + "condition": { + "parameter_ref": "multiselect_error", + "op": "notContains", + "value": "red" + } + } + } + }, + { + "validation": { + "fail_message": { + "type": "warning", + "focus_parameter_ref": "multiselect_warning", + "message": { + "default": "Shouldn't be empty, cannot equal []" + } + }, + "evaluate": { + "condition": { + "parameter_ref": "multiselect_warning", + "op": "notEquals", + "value": [] + } + } + } + }, + { + "visible": { + "parameter_refs": [ + "multiselect_hidden" + ], + "evaluate": { + "condition": { + "parameter_ref": "hide", + "op": "equals", + "value": false + } + } + } + }, + { + "enabled": { + "parameter_refs": [ + "multiselect_disabled" + ], + "evaluate": { + "condition": { + "parameter_ref": "disabled", + "op": "equals", + "value": false + } + } + } + } + ], + "resources": { + "multiselect_multiple_selected.red.label": "Custom red", + "multiselect_multiple_selected.orange.label": "Custom orange", + "multiselect_multiple_selected.yellow.label": "Custom yellow", + "multiselect_multiple_selected.green.label": "Custom green", + "multiselect_multiple_selected.blue.label": "Custom blue", + "multiselect_multiple_selected.purple.label": "Custom purple", + "multiselect_custom_labels.multiselect.dropdown.empty.label": "nothing selected yet", + "multiselect_custom_labels.multiselect.dropdown.options.selected.label": "options are selected" + } +}