From 1bfdc83fff4277c33cb73ea7fecba9c84c8cf772 Mon Sep 17 00:00:00 2001 From: Pawan Kumar Date: Wed, 18 Dec 2024 13:26:57 +0530 Subject: [PATCH 1/3] fix menu widget bugs --- .../propertyPaneConfig/contentConfig.ts | 25 --------------- .../wds/WDSMenuButtonWidget/widget/index.tsx | 28 +++++++++------- .../wds/WDSMenuButtonWidget/widget/types.ts | 32 +++---------------- 3 files changed, 21 insertions(+), 64 deletions(-) diff --git a/app/client/src/modules/ui-builder/ui/wds/WDSMenuButtonWidget/config/propertyPaneConfig/contentConfig.ts b/app/client/src/modules/ui-builder/ui/wds/WDSMenuButtonWidget/config/propertyPaneConfig/contentConfig.ts index 52525d150834..e68fdbe7ea64 100644 --- a/app/client/src/modules/ui-builder/ui/wds/WDSMenuButtonWidget/config/propertyPaneConfig/contentConfig.ts +++ b/app/client/src/modules/ui-builder/ui/wds/WDSMenuButtonWidget/config/propertyPaneConfig/contentConfig.ts @@ -3,7 +3,6 @@ import { AutocompleteDataType } from "utils/autocomplete/AutocompleteDataType"; import { EvaluationSubstitutionType } from "entities/DataTree/dataTreeFactory"; import { sourceDataArrayValidation } from "./validations"; import { configureMenuItemsConfig, menuItemsConfig } from "./childPanels"; -import { updateMenuItemsSource } from "../helper"; import type { MenuButtonWidgetProps } from "../../widget/types"; import type { PropertyPaneConfig } from "constants/PropertyControlConstants"; @@ -21,30 +20,6 @@ export const propertyPaneContentConfig = [ isTriggerProperty: false, validation: { type: ValidationTypes.TEXT }, }, - { - propertyName: "menuItemsSource", - helpText: "Sets the source for the menu items", - label: "Menu items source", - controlType: "ICON_TABS", - defaultValue: "static", - fullWidth: true, - options: [ - { - label: "Static", - value: "static", - }, - { - label: "Dynamic", - value: "dynamic", - }, - ], - isJSConvertible: false, - isBindProperty: false, - isTriggerProperty: false, - validation: { type: ValidationTypes.TEXT }, - updateHook: updateMenuItemsSource, - dependencies: ["sourceData", "configureMenuItems"], - }, { helpText: "Menu items", propertyName: "menuItems", diff --git a/app/client/src/modules/ui-builder/ui/wds/WDSMenuButtonWidget/widget/index.tsx b/app/client/src/modules/ui-builder/ui/wds/WDSMenuButtonWidget/widget/index.tsx index f0708c9ece4d..8cf2bb806f14 100644 --- a/app/client/src/modules/ui-builder/ui/wds/WDSMenuButtonWidget/widget/index.tsx +++ b/app/client/src/modules/ui-builder/ui/wds/WDSMenuButtonWidget/widget/index.tsx @@ -1,4 +1,4 @@ -import React from "react"; +import React, { type Key } from "react"; import type { SetterConfig } from "entities/AppTheming"; import type { WidgetState } from "widgets/BaseWidget"; import BaseWidget from "widgets/BaseWidget"; @@ -12,9 +12,9 @@ import { methodsConfig, } from "../config"; import type { AnvilConfig } from "WidgetProvider/constants"; -import { Button, MenuTrigger, Menu } from "@appsmith/wds"; +import { Button, MenuTrigger, Menu, MenuItem } from "@appsmith/wds"; import { isArray, orderBy } from "lodash"; -import type { MenuButtonWidgetProps, MenuItem } from "./types"; +import type { MenuButtonWidgetProps } from "./types"; import { EventType, type ExecuteTriggerPayload, @@ -116,7 +116,7 @@ class WDSMenuButtonWidget extends BaseWidget< ) { const { config } = configureMenuItems; - const getValue = (propertyName: keyof MenuItem, index: number) => { + const getValue = (propertyName: keyof typeof config, index: number) => { const value = config[propertyName]; if (isArray(value)) { @@ -136,9 +136,6 @@ class WDSMenuButtonWidget extends BaseWidget< widgetId: "", label: getValue("label", index), onClick: config?.onClick, - iconAlign: getValue("iconAlign", index), - iconName: getValue("iconName", index), - textColor: getValue("textColor", index), })) .filter((item) => item.isVisible === true); @@ -159,7 +156,7 @@ class WDSMenuButtonWidget extends BaseWidget< triggerButtonVariant, } = this.props; - const visibleItems: MenuItem[] = this.getVisibleItems(); + const visibleItems = this.getVisibleItems(); const disabledKeys = visibleItems .filter((item) => item.isDisabled === true) .map((item) => item.id); @@ -178,8 +175,7 @@ class WDSMenuButtonWidget extends BaseWidget< } onAction={(key) => { const clickedItemIndex = visibleItems.findIndex( (item) => item.id === key, @@ -192,7 +188,17 @@ class WDSMenuButtonWidget extends BaseWidget< ); } }} - /> + > + {visibleItems.map((item) => ( + + {item.label} + + ))} + ); } diff --git a/app/client/src/modules/ui-builder/ui/wds/WDSMenuButtonWidget/widget/types.ts b/app/client/src/modules/ui-builder/ui/wds/WDSMenuButtonWidget/widget/types.ts index bcd7daac9820..57e8e9e1088f 100644 --- a/app/client/src/modules/ui-builder/ui/wds/WDSMenuButtonWidget/widget/types.ts +++ b/app/client/src/modules/ui-builder/ui/wds/WDSMenuButtonWidget/widget/types.ts @@ -1,45 +1,21 @@ -import type { ButtonProps, COLORS, IconProps } from "@appsmith/wds"; +import type { ButtonProps, IconProps } from "@appsmith/wds"; import type { WidgetProps } from "widgets/BaseWidget"; -import type { IconName } from "@blueprintjs/icons"; - -export interface MenuItem { - // Meta - id: string; - index?: number; - widgetId?: string; - - // General - label?: string; - isVisible?: boolean; - isDisabled?: boolean; - onClick?: string; - - // Style - iconName?: IconName; - iconAlign?: "start" | "end"; - textColor?: keyof typeof COLORS; -} export interface ConfigureMenuItems { label: string; id: string; - config: MenuItem; + config: Record; } export interface MenuButtonWidgetProps extends WidgetProps { - // General label?: string; isDisabled?: boolean; isVisible?: boolean; - - // Source data and menu items sourceData?: Array>; menuItemsSource: "static" | "dynamic"; configureMenuItems: ConfigureMenuItems; - menuItems: Record; - getVisibleItems: () => Array; - - // Trigger button style + menuItems: Record>; + getVisibleItems: () => Array>; triggerButtonIconName?: IconProps["name"]; triggerButtonIconAlign?: ButtonProps["iconPosition"]; triggerButtonVariant?: ButtonProps["variant"]; From abe56a0aab48af8c3dc8113d12f27d141b16c5fc Mon Sep 17 00:00:00 2001 From: Pawan Kumar Date: Wed, 18 Dec 2024 15:59:12 +0530 Subject: [PATCH 2/3] fix menu widget bugs --- .../ui-builder/ui/wds/WDSMenuButtonWidget/widget/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/client/src/modules/ui-builder/ui/wds/WDSMenuButtonWidget/widget/index.tsx b/app/client/src/modules/ui-builder/ui/wds/WDSMenuButtonWidget/widget/index.tsx index 8cf2bb806f14..6b8cfa966494 100644 --- a/app/client/src/modules/ui-builder/ui/wds/WDSMenuButtonWidget/widget/index.tsx +++ b/app/client/src/modules/ui-builder/ui/wds/WDSMenuButtonWidget/widget/index.tsx @@ -183,7 +183,7 @@ class WDSMenuButtonWidget extends BaseWidget< if (clickedItemIndex > -1) { this.menuItemClickHandler( - visibleItems[clickedItemIndex]?.onClick, + visibleItems[clickedItemIndex]?.onClick as string, clickedItemIndex, ); } From ade8c87e56c003a3d5c733f9c66a2ac4345f7158 Mon Sep 17 00:00:00 2001 From: Pawan Kumar Date: Wed, 18 Dec 2024 16:36:25 +0530 Subject: [PATCH 3/3] minor refactor --- .../WDSMenuButtonWidget/config/anvilConfig.ts | 10 +++ .../wds/WDSMenuButtonWidget/config/index.ts | 5 +- .../propertyPaneConfig/contentConfig.ts | 26 +++++++ .../wds/WDSMenuButtonWidget/widget/index.tsx | 76 ++++++++----------- .../wds/WDSMenuButtonWidget/widget/types.ts | 13 +++- 5 files changed, 80 insertions(+), 50 deletions(-) create mode 100644 app/client/src/modules/ui-builder/ui/wds/WDSMenuButtonWidget/config/anvilConfig.ts diff --git a/app/client/src/modules/ui-builder/ui/wds/WDSMenuButtonWidget/config/anvilConfig.ts b/app/client/src/modules/ui-builder/ui/wds/WDSMenuButtonWidget/config/anvilConfig.ts new file mode 100644 index 000000000000..169db7b31b60 --- /dev/null +++ b/app/client/src/modules/ui-builder/ui/wds/WDSMenuButtonWidget/config/anvilConfig.ts @@ -0,0 +1,10 @@ +export const anvilConfig = { + isLargeWidget: false, + widgetSize: { + maxWidth: { + base: "100%", + "280px": "sizing-70", + }, + minWidth: "sizing-14", + }, +}; diff --git a/app/client/src/modules/ui-builder/ui/wds/WDSMenuButtonWidget/config/index.ts b/app/client/src/modules/ui-builder/ui/wds/WDSMenuButtonWidget/config/index.ts index ab36e7a74f4d..fa4caee3937f 100644 --- a/app/client/src/modules/ui-builder/ui/wds/WDSMenuButtonWidget/config/index.ts +++ b/app/client/src/modules/ui-builder/ui/wds/WDSMenuButtonWidget/config/index.ts @@ -1,6 +1,7 @@ export * from "./propertyPaneConfig"; -export { autocompleteConfig } from "./autocompleteConfig"; -export { defaultsConfig } from "./defaultsConfig"; export { metaConfig } from "./metaConfig"; +export { anvilConfig } from "./anvilConfig"; export { settersConfig } from "./settersConfig"; export { methodsConfig } from "./methodsConfig"; +export { defaultsConfig } from "./defaultsConfig"; +export { autocompleteConfig } from "./autocompleteConfig"; diff --git a/app/client/src/modules/ui-builder/ui/wds/WDSMenuButtonWidget/config/propertyPaneConfig/contentConfig.ts b/app/client/src/modules/ui-builder/ui/wds/WDSMenuButtonWidget/config/propertyPaneConfig/contentConfig.ts index e68fdbe7ea64..633649ebabb7 100644 --- a/app/client/src/modules/ui-builder/ui/wds/WDSMenuButtonWidget/config/propertyPaneConfig/contentConfig.ts +++ b/app/client/src/modules/ui-builder/ui/wds/WDSMenuButtonWidget/config/propertyPaneConfig/contentConfig.ts @@ -5,6 +5,7 @@ import { sourceDataArrayValidation } from "./validations"; import { configureMenuItemsConfig, menuItemsConfig } from "./childPanels"; import type { MenuButtonWidgetProps } from "../../widget/types"; import type { PropertyPaneConfig } from "constants/PropertyControlConstants"; +import { updateMenuItemsSource } from "../helper"; export const propertyPaneContentConfig = [ { @@ -20,6 +21,31 @@ export const propertyPaneContentConfig = [ isTriggerProperty: false, validation: { type: ValidationTypes.TEXT }, }, + { + propertyName: "menuItemsSource", + helpText: "Sets the source for the menu items", + label: "Menu items source", + controlType: "ICON_TABS", + defaultValue: "static", + fullWidth: true, + options: [ + { + label: "Static", + value: "static", + }, + { + label: "Dynamic", + value: "dynamic", + }, + ], + isJSConvertible: false, + isBindProperty: false, + isTriggerProperty: false, + validation: { type: ValidationTypes.TEXT }, + updateHook: updateMenuItemsSource, + hidden: () => true, + dependencies: ["sourceData", "configureMenuItems"], + }, { helpText: "Menu items", propertyName: "menuItems", diff --git a/app/client/src/modules/ui-builder/ui/wds/WDSMenuButtonWidget/widget/index.tsx b/app/client/src/modules/ui-builder/ui/wds/WDSMenuButtonWidget/widget/index.tsx index 6b8cfa966494..a564912ab2fa 100644 --- a/app/client/src/modules/ui-builder/ui/wds/WDSMenuButtonWidget/widget/index.tsx +++ b/app/client/src/modules/ui-builder/ui/wds/WDSMenuButtonWidget/widget/index.tsx @@ -1,24 +1,17 @@ import React, { type Key } from "react"; -import type { SetterConfig } from "entities/AppTheming"; -import type { WidgetState } from "widgets/BaseWidget"; -import BaseWidget from "widgets/BaseWidget"; -import { - metaConfig, - defaultsConfig, - autocompleteConfig, - propertyPaneContentConfig, - propertyPaneStyleConfig, - settersConfig, - methodsConfig, -} from "../config"; -import type { AnvilConfig } from "WidgetProvider/constants"; -import { Button, MenuTrigger, Menu, MenuItem } from "@appsmith/wds"; import { isArray, orderBy } from "lodash"; -import type { MenuButtonWidgetProps } from "./types"; +import BaseWidget from "widgets/BaseWidget"; +import type { WidgetState } from "widgets/BaseWidget"; +import type { SetterConfig } from "entities/AppTheming"; import { EventType, type ExecuteTriggerPayload, } from "constants/AppsmithActionConstants/ActionConstants"; +import type { AnvilConfig } from "WidgetProvider/constants"; +import { Button, MenuTrigger, Menu, MenuItem } from "@appsmith/wds"; + +import * as config from "../config"; +import type { MenuButtonWidgetProps } from "./types"; class WDSMenuButtonWidget extends BaseWidget< MenuButtonWidgetProps, @@ -26,56 +19,43 @@ class WDSMenuButtonWidget extends BaseWidget< > { constructor(props: MenuButtonWidgetProps) { super(props); - - this.state = { - isLoading: false, - }; } static type = "WDS_MENU_BUTTON_WIDGET"; static getConfig() { - return metaConfig; + return config.metaConfig; } static getDefaults() { - return defaultsConfig; + return config.defaultsConfig; } static getAnvilConfig(): AnvilConfig | null { - return { - isLargeWidget: false, - widgetSize: { - maxWidth: { - base: "100%", - "280px": "sizing-70", - }, - minWidth: "sizing-14", - }, - }; + return config.anvilConfig; } static getAutocompleteDefinitions() { - return autocompleteConfig; + return config.autocompleteConfig; } static getPropertyPaneContentConfig() { - return propertyPaneContentConfig; + return config.propertyPaneContentConfig; } static getPropertyPaneStyleConfig() { - return propertyPaneStyleConfig; + return config.propertyPaneStyleConfig; } static getSetterConfig(): SetterConfig { - return settersConfig; + return config.settersConfig; } static getMethods() { - return methodsConfig; + return config.methodsConfig; } - menuItemClickHandler = (onClick: string | undefined, index: number) => { + onMenuItemClick = (onClick: string | undefined, index: number) => { if (onClick) { const config: ExecuteTriggerPayload = { triggerPropertyName: "onClick", @@ -85,6 +65,9 @@ class WDSMenuButtonWidget extends BaseWidget< }, }; + // in case when the menu items source is dynamic, we need to pass the current item to the global context + // the reason is in onClick, we can access the current item and current index by writing `{{currentItem}}` and `{{currentIndex}}`, + // so we need to pass the current item to the global context if (this.props.menuItemsSource === "dynamic") { config.globalContext = { currentItem: this.props.sourceData @@ -108,7 +91,9 @@ class WDSMenuButtonWidget extends BaseWidget< .filter((item) => item.isVisible === true); return orderBy(visibleItems, ["index"], ["asc"]); - } else if ( + } + + if ( menuItemsSource === "dynamic" && isArray(sourceData) && sourceData?.length && @@ -116,7 +101,10 @@ class WDSMenuButtonWidget extends BaseWidget< ) { const { config } = configureMenuItems; - const getValue = (propertyName: keyof typeof config, index: number) => { + const getDynamicMenuItemValue = ( + propertyName: keyof typeof config, + index: number, + ) => { const value = config[propertyName]; if (isArray(value)) { @@ -130,11 +118,11 @@ class WDSMenuButtonWidget extends BaseWidget< .map((item, index) => ({ ...item, id: index.toString(), - isVisible: getValue("isVisible", index), - isDisabled: getValue("isDisabled", index), + isVisible: getDynamicMenuItemValue("isVisible", index), + isDisabled: getDynamicMenuItemValue("isDisabled", index), index: index, widgetId: "", - label: getValue("label", index), + label: getDynamicMenuItemValue("label", index), onClick: config?.onClick, })) .filter((item) => item.isVisible === true); @@ -182,8 +170,8 @@ class WDSMenuButtonWidget extends BaseWidget< ); if (clickedItemIndex > -1) { - this.menuItemClickHandler( - visibleItems[clickedItemIndex]?.onClick as string, + this.onMenuItemClick( + visibleItems[clickedItemIndex]?.onClick, clickedItemIndex, ); } diff --git a/app/client/src/modules/ui-builder/ui/wds/WDSMenuButtonWidget/widget/types.ts b/app/client/src/modules/ui-builder/ui/wds/WDSMenuButtonWidget/widget/types.ts index 57e8e9e1088f..b06e1bafc055 100644 --- a/app/client/src/modules/ui-builder/ui/wds/WDSMenuButtonWidget/widget/types.ts +++ b/app/client/src/modules/ui-builder/ui/wds/WDSMenuButtonWidget/widget/types.ts @@ -4,18 +4,23 @@ import type { WidgetProps } from "widgets/BaseWidget"; export interface ConfigureMenuItems { label: string; id: string; - config: Record; + config: { + id: string; + label: string; + isVisible: boolean; + isDisabled: boolean; + onClick: string; + }; } export interface MenuButtonWidgetProps extends WidgetProps { label?: string; isDisabled?: boolean; isVisible?: boolean; - sourceData?: Array>; + sourceData?: Array; menuItemsSource: "static" | "dynamic"; configureMenuItems: ConfigureMenuItems; - menuItems: Record>; - getVisibleItems: () => Array>; + menuItems: Record; triggerButtonIconName?: IconProps["name"]; triggerButtonIconAlign?: ButtonProps["iconPosition"]; triggerButtonVariant?: ButtonProps["variant"];