From 0b87c7431bfc0166ff674235b12524e98bdf4cdf Mon Sep 17 00:00:00 2001 From: Abhinav Jha Date: Fri, 18 Sep 2020 10:52:54 +0530 Subject: [PATCH] Fix issue where tabs are lost when the user enters an invalid tabs value (#569) --- .../src/constants/FieldExpectedValue.ts | 3 +- app/client/src/utils/WidgetPropsUtils.tsx | 31 ++++++++------ app/client/src/widgets/TabsWidget.tsx | 41 ++++++++++--------- 3 files changed, 43 insertions(+), 32 deletions(-) diff --git a/app/client/src/constants/FieldExpectedValue.ts b/app/client/src/constants/FieldExpectedValue.ts index 7d13e27e89..c9ac6d44fc 100644 --- a/app/client/src/constants/FieldExpectedValue.ts +++ b/app/client/src/constants/FieldExpectedValue.ts @@ -46,7 +46,8 @@ const FIELD_VALUES: Record< // onSelectionChange: "Function Call", }, TABS_WIDGET: { - tabs: "Array<{ label: string, id: string }>", + tabs: + "Array<{ label: string, id: string(unique), widgetId: string(unique) }>", selectedTab: "string", isVisible: "boolean", }, diff --git a/app/client/src/utils/WidgetPropsUtils.tsx b/app/client/src/utils/WidgetPropsUtils.tsx index 38c33b9e02..afaa13f133 100644 --- a/app/client/src/utils/WidgetPropsUtils.tsx +++ b/app/client/src/utils/WidgetPropsUtils.tsx @@ -21,6 +21,7 @@ import { generateReactKey } from "./generators"; import { ChartDataPoint } from "widgets/ChartWidget"; import { FlattenedWidgetProps } from "reducers/entityReducers/canvasWidgetsReducer"; import { isString } from "lodash"; +import log from "loglevel"; export type WidgetOperationParams = { operation: WidgetOperation; @@ -200,18 +201,23 @@ const tabsWidgetTabsPropertyMigration = ( ?.filter(Boolean) .map((child: WidgetProps) => { if (child.type === WidgetTypes.TABS_WIDGET) { - const tabs = isString(child.tabs) ? JSON.parse(child.tabs) : child.tabs; - - const newTabs = tabs.map((tab: any) => { - const childForTab = child.children - ?.filter(Boolean) - .find((tabChild: WidgetProps) => tabChild.tabId === tab.id); - if (childForTab) { - tab.widgetId = childForTab.widgetId; - } - return tab; - }); - child.tabs = JSON.stringify(newTabs); + try { + const tabs = isString(child.tabs) + ? JSON.parse(child.tabs) + : child.tabs; + const newTabs = tabs.map((tab: any) => { + const childForTab = child.children + ?.filter(Boolean) + .find((tabChild: WidgetProps) => tabChild.tabId === tab.id); + if (childForTab) { + tab.widgetId = childForTab.widgetId; + } + return tab; + }); + child.tabs = JSON.stringify(newTabs); + } catch (migrationError) { + log.debug({ migrationError }); + } } if (child.children && child.children.length) { child = tabsWidgetTabsPropertyMigration(child); @@ -266,6 +272,7 @@ const transformDSL = (currentDSL: ContainerWidgetProps) => { } if (currentDSL.version === 5) { currentDSL = tabsWidgetTabsPropertyMigration(currentDSL); + currentDSL.version = 6; } return currentDSL; diff --git a/app/client/src/widgets/TabsWidget.tsx b/app/client/src/widgets/TabsWidget.tsx index 2e79893c26..e610437d47 100644 --- a/app/client/src/widgets/TabsWidget.tsx +++ b/app/client/src/widgets/TabsWidget.tsx @@ -143,26 +143,29 @@ class TabsWidget extends BaseWidget< .map(child => child.widgetId); // If the tabs and children are different, // add and/or remove tab container widgets - if (_.xor(childWidgetIds, tabWidgetIds).length > 0) { - const widgetIdsToRemove: string[] = _.without( - childWidgetIds, - ...tabWidgetIds, - ); - const widgetIdsToCreate: string[] = _.without( - tabWidgetIds, - ...childWidgetIds, - ); - this.addTabContainer(widgetIdsToCreate); - this.removeTabContainer(widgetIdsToRemove); - } - // If all tabs were removed. - if (tabWidgetIds.length === 0) { - const newTabContainerWidgetId = generateReactKey(); - const tabs = [ - { id: "tab1", widgetId: newTabContainerWidgetId, label: "Tab 1" }, - ]; - this.updateWidgetProperty("tabs", JSON.stringify(tabs)); + if (!this.props.invalidProps?.tabs) { + if (_.xor(childWidgetIds, tabWidgetIds).length > 0) { + const widgetIdsToRemove: string[] = _.without( + childWidgetIds, + ...tabWidgetIds, + ); + const widgetIdsToCreate: string[] = _.without( + tabWidgetIds, + ...childWidgetIds, + ); + this.addTabContainer(widgetIdsToCreate); + this.removeTabContainer(widgetIdsToRemove); + } + + // If all tabs were removed. + if (tabWidgetIds.length === 0) { + const newTabContainerWidgetId = generateReactKey(); + const tabs = [ + { id: "tab1", widgetId: newTabContainerWidgetId, label: "Tab 1" }, + ]; + this.updateWidgetProperty("tabs", JSON.stringify(tabs)); + } } } if (this.props.defaultTab) {