import React from "react"; import { Alignment } from "@blueprintjs/core"; import { xor } from "lodash"; import BaseWidget, { WidgetProps, WidgetState } from "widgets/BaseWidget"; import { DerivedPropertiesMap } from "utils/WidgetFactory"; import { ValidationTypes } from "constants/WidgetValidation"; import { EventType } from "constants/AppsmithActionConstants/ActionConstants"; import { EvaluationSubstitutionType } from "entities/DataTree/dataTreeFactory"; import SwitchGroupComponent, { OptionProps } from "../component"; class SwitchGroupWidget extends BaseWidget< SwitchGroupWidgetProps, WidgetState > { static getPropertyPaneConfig() { return [ { sectionName: "General", children: [ { helpText: "Displays a list of options for a user to select. Values must be unique", propertyName: "options", label: "Options", controlType: "INPUT_TEXT", placeholderText: '[{ "label": "Option1", "value": "Option2" }]', isBindProperty: true, isTriggerProperty: false, validation: { type: ValidationTypes.ARRAY, params: { children: { type: ValidationTypes.OBJECT, params: { allowedKeys: [ { name: "label", type: ValidationTypes.TEXT, params: { default: "", required: true, unique: true, }, }, { name: "value", type: ValidationTypes.TEXT, params: { default: "", unique: true, }, }, ], }, }, }, }, evaluationSubstitutionType: EvaluationSubstitutionType.SMART_SUBSTITUTE, }, { helpText: "Selects values of the options checked by default. Enter comma separated values for multiple selected", propertyName: "defaultSelectedValues", label: "Default Selected Values", placeholderText: "Enter option values", controlType: "INPUT_TEXT", isBindProperty: true, isTriggerProperty: false, validation: { type: ValidationTypes.ARRAY, params: { default: [], children: { type: ValidationTypes.TEXT, }, strict: true, }, }, }, { propertyName: "isInline", helpText: "Whether switches are to be displayed inline horizontally", label: "Inline", controlType: "SWITCH", isJSConvertible: true, isBindProperty: true, isTriggerProperty: false, validation: { type: ValidationTypes.BOOLEAN }, }, { propertyName: "isRequired", label: "Required", helpText: "Makes input to the widget mandatory", controlType: "SWITCH", isJSConvertible: true, isBindProperty: true, isTriggerProperty: false, validation: { type: ValidationTypes.BOOLEAN }, }, { propertyName: "isVisible", helpText: "Controls the visibility of the widget", label: "Visible", controlType: "SWITCH", isJSConvertible: true, isBindProperty: true, isTriggerProperty: false, validation: { type: ValidationTypes.BOOLEAN }, }, { propertyName: "isDisabled", helpText: "Disables input to the widget", label: "Disabled", controlType: "SWITCH", isJSConvertible: true, isBindProperty: true, isTriggerProperty: false, validation: { type: ValidationTypes.BOOLEAN }, }, { propertyName: "animateLoading", label: "Animate Loading", controlType: "SWITCH", helpText: "Controls the loading of the widget", defaultValue: true, isJSConvertible: true, isBindProperty: true, isTriggerProperty: false, validation: { type: ValidationTypes.BOOLEAN }, }, { propertyName: "alignment", helpText: "Sets the alignment of the widget", label: "Alignment", controlType: "DROP_DOWN", isBindProperty: true, isTriggerProperty: false, options: [ { label: "Left", value: Alignment.LEFT, }, { label: "Right", value: Alignment.RIGHT, }, ], }, ], }, { sectionName: "Actions", children: [ { helpText: "Triggers an action when a switch state inside the group is changed", propertyName: "onSelectionChange", label: "onSelectionChange", controlType: "ACTION_SELECTOR", isJSConvertible: true, isBindProperty: true, isTriggerProperty: true, }, ], }, ]; } static getDefaultPropertiesMap(): Record { return { selectedValuesArray: "defaultSelectedValues", }; } static getMetaPropertiesMap(): Record { return { selectedValuesArray: undefined, isDirty: false, }; } static getDerivedPropertiesMap(): DerivedPropertiesMap { return { isValid: `{{ this.isRequired ? !!this.selectedValues.length : true }}`, selectedValues: `{{ this.selectedValuesArray.filter( selectedValue => this.options.map(option => option.value).includes(selectedValue) ) }}`, }; } static getWidgetType(): string { return "SWITCH_GROUP_WIDGET"; } componentDidUpdate(prevProps: SwitchGroupWidgetProps): void { if ( xor(this.props.defaultSelectedValues, prevProps.defaultSelectedValues) .length > 0 ) { if (this.props.isDirty) { this.props.updateWidgetMetaProperty("isDirty", false); } this.props.updateWidgetMetaProperty( "selectedValuesArray", this.props.defaultSelectedValues, ); } } getPageView() { const { alignment, isDisabled, isInline, isRequired, isValid, options, parentRowSpace, selectedValuesArray, } = this.props; return ( ); } private handleSwitchStateChange = (value: string) => { return (event: React.FormEvent) => { let { selectedValuesArray } = this.props; const isChecked = (event.target as HTMLInputElement).checked; if (isChecked) { selectedValuesArray = [...selectedValuesArray, value]; } else { selectedValuesArray = selectedValuesArray.filter( (item: string) => item !== value, ); } if (!this.props.isDirty) { this.props.updateWidgetMetaProperty("isDirty", true); } this.props.updateWidgetMetaProperty( "selectedValuesArray", selectedValuesArray, { triggerPropertyName: "onSelectionChange", dynamicString: this.props.onSelectionChange, event: { type: EventType.ON_SWITCH_GROUP_SELECTION_CHANGE, }, }, ); }; }; } export interface SwitchGroupWidgetProps extends WidgetProps { options: OptionProps[]; defaultSelectedValues: string[]; selectedValuesArray: string[]; isInline: boolean; isRequired?: boolean; isValid?: boolean; isDisabled?: boolean; alignment: Alignment; onSelectionChange?: boolean; } export default SwitchGroupWidget;