PromucFlow_constructor/app/client/src/widgets/MenuButtonWidget/widget/index.tsx
Dhruvik Neharia 1a7b4c6725
feat: Dynamic Menu Items - Menu Button Widget (#17652)
* faet: Add menu items source for menu widget

* feat: Add configuration panel for dynamic menu items

* feat: Pass down items from sourceData to menu items widget

* feat: Take menu items config from property pane for dynamic menu items

* fix: Change all onMenuItemClick to onClick for dynamic menu items

* feat: Create MenuComputeValue property control to add support for {{currentItem}} binding in menu widget

* feat: Add JS toggles for style properties for menu widget

* feat: onClick now supports currentItem for menu button widget

* feat: Add currentItem autocomplete, move property pane config to separate files for menu button widget

* feat: WIP - Add Dynamic Menu Items for Table Widget

* Revert "feat: WIP - Add Dynamic Menu Items for Table Widget"

This reverts commit 271f96211c8612bc6f073a1aab7467993b9d7e36.

* fix: remove current item label by default for dynamic menu items in menu button

* feat: Add source data max length 10 validation for dynamic menu items in menu button

* feat: Add migrations for Dynamic Menu Items for Menu Button Widget

* feat: Add cypress test for dynamic menu items for menu button

* test: Update DSLMigration test with menu button widget tests

* fix: Update MenuButtonWidget migration

* fix: DSL migrations for menu button dynmaic items

* fix: Style validations for menu widget

* feat: Add more descriptive help text for configure menu items in menu button widget

* feat: Change menu items source property type from dropdown to icon tabs

* fix: Cy test for menu button widget to select menu items source from button tabs instead of dropdown

* feat: Make ConfigureMenuItemsControl a Generic/reusable OpenNextPanelWithButtonControl

* refactor: Change MenuComputeValue to MenuButtonDynamicItemsControl

* refactor: Merge TABLE_PROPERTY and MENU_PROPERTY into one ARRAY_AND_ANY_PROPERTY

* fix: Don't polute Menu Button DSL with properties for dynamic menu items until the source is static

* style: Change color of curly braces hint in currentItem autocomplete to make it more readable

* fix: remove unused import

* refactor: Move child config panels to a different file, style: Change help text and placeholder for a few properties for Dynamic menu items - menu button

* refactor: Change event autocomplete function name, use fast equal

* refactor: Change source data validation function name and use camelCase throughout

* refactor: Validation function for source data

* refactor: Create different type for menuItems and configureMenuItems and reuse them property config

* feat: refactor: move get items to widget instead of component

* pref: Visible items to be calculated when menu button is clicked

* refactor: replace !("menuItemsSource" in child) with in migration

* refactor: Change controlType name from OPEN_NEXT_PANEL_WITH_BUTTON to OPEN_CONFIG_PANEL, use generic names inside OpenNextPanelWithButtonControl.tsx

* refactor: Minor cleanup at MenuButtonDynamicItemsControl.tsx

* refactor: Minor cleanup at MenuButtonDynamicItemsControl.tsx

* fix: Change constant used in migration to a static value

* test: Add tests for validations and helper for menu button

* test: Add more Cypress tests for dynamic-menu-items

* fix: Minor refactor at onclick handler and MenuButtonDynamicItemsControl

* refactor: Rename ARRAY_AND_ANY_PROPERTY to ARRAY_TYPE_OR_TYPE

* feat: Move initial source data and keys generation inside an update hook

* refactor: Rename ARRAY_TYPE_OR_TYPE to ARRAY_OF_TYPE_OR_TYPE

* refactor: Minor code refactor in MenuButtonWidget/widget/index.tsx

* refactor: Change OpenNextPanelWithButtonControl with OpenConfigPanelControl

* feat: Use traverseDSLAndMigrate for dynamic menu items migration

* style: Minor code hygiene changes here and there for dynamic menu items

* style: Minor code hygiene changes here and there for dynamic menu items

* style: remove any type for visible items inside dynamic menu items

* refactor: Change type MenuItems to MenuItem

* feat: Add support for dynamic menu items (menu button) inside list widget

* fix: updateMenuItemsSource hook not working when changing from DYNAMIC to STATIC menu items source

* fix: Avoid empty icon name from rendering inside button and menu item

* style: Fix a couple of code callouts

* fix: Update import from TernServer to CodemirrorTernService

* style: fix minor code callouts here and there

* fix: Add check for configureMenuItems.config

* fix: Add wait time after addOption click for DynamicHeight_Auto_Height_spec.js

* fix: Increase the wait time for DynamicHeight_Auto_Height_spec.js to 200ms

Co-authored-by: Aishwarya UR <aishwarya@appsmith.com>
2022-12-01 10:25:57 +05:30

146 lines
4.1 KiB
TypeScript

import React from "react";
import BaseWidget, { WidgetState } from "widgets/BaseWidget";
import {
EventType,
ExecuteTriggerPayload,
} from "constants/AppsmithActionConstants/ActionConstants";
import MenuButtonComponent from "../component";
import { MinimumPopupRows } from "widgets/constants";
import { MenuButtonWidgetProps, MenuItem, MenuItemsSource } from "../constants";
import contentConfig from "./propertyConfig/contentConfig";
import styleConfig from "./propertyConfig/styleConfig";
import equal from "fast-deep-equal/es6";
import { isArray, orderBy } from "lodash";
import { getSourceDataKeys } from "./helper";
import { Stylesheet } from "entities/AppTheming";
class MenuButtonWidget extends BaseWidget<MenuButtonWidgetProps, WidgetState> {
static getPropertyPaneContentConfig() {
return contentConfig;
}
static getPropertyPaneStyleConfig() {
return styleConfig;
}
static getStylesheetConfig(): Stylesheet {
return {
menuColor: "{{appsmith.theme.colors.primaryColor}}",
borderRadius: "{{appsmith.theme.borderRadius.appBorderRadius}}",
boxShadow: "none",
};
}
menuItemClickHandler = (onClick: string | undefined, index: number) => {
if (onClick) {
const config: ExecuteTriggerPayload = {
triggerPropertyName: "onClick",
dynamicString: onClick,
event: {
type: EventType.ON_CLICK,
},
};
if (this.props.menuItemsSource === MenuItemsSource.DYNAMIC) {
config.globalContext = {
currentItem: this.props.sourceData
? this.props.sourceData[index]
: {},
currentIndex: index,
};
}
super.executeAction(config);
}
};
getVisibleItems = () => {
const {
configureMenuItems,
menuItems,
menuItemsSource,
sourceData,
} = this.props;
if (menuItemsSource === MenuItemsSource.STATIC) {
const visibleItems = Object.keys(menuItems)
.map((itemKey) => menuItems[itemKey])
.filter((item) => item.isVisible === true);
return orderBy(visibleItems, ["index"], ["asc"]);
} else if (
menuItemsSource === MenuItemsSource.DYNAMIC &&
isArray(sourceData) &&
sourceData?.length &&
configureMenuItems?.config
) {
const { config } = configureMenuItems;
const getValue = (propertyName: keyof MenuItem, index: number) => {
const value = config[propertyName];
if (isArray(value)) {
return value[index];
}
return value ?? null;
};
const visibleItems = sourceData
.map((item, index) => ({
...item,
id: index.toString(),
isVisible: getValue("isVisible", index),
isDisabled: getValue("isDisabled", index),
index: index,
widgetId: "",
label: getValue("label", index),
onClick: config?.onClick,
textColor: getValue("textColor", index),
backgroundColor: getValue("backgroundColor", index),
iconAlign: getValue("iconAlign", index),
iconColor: getValue("iconColor", index),
iconName: getValue("iconName", index),
}))
.filter((item) => item.isVisible === true);
return visibleItems;
}
return [];
};
componentDidMount = () => {
super.updateWidgetProperty("sourceDataKeys", getSourceDataKeys(this.props));
};
componentDidUpdate = (prevProps: MenuButtonWidgetProps) => {
if (!equal(prevProps.sourceData, this.props.sourceData)) {
super.updateWidgetProperty(
"sourceDataKeys",
getSourceDataKeys(this.props),
);
}
};
getPageView() {
const { componentWidth } = this.getComponentDimensions();
const menuDropDownWidth = MinimumPopupRows * this.props.parentColumnSpace;
return (
<MenuButtonComponent
{...this.props}
getVisibleItems={this.getVisibleItems}
menuDropDownWidth={menuDropDownWidth}
onItemClicked={this.menuItemClickHandler}
renderMode={this.props.renderMode}
width={componentWidth}
/>
);
}
static getWidgetType() {
return "MENU_BUTTON_WIDGET";
}
}
export default MenuButtonWidget;