PromucFlow_constructor/app/client/src/utils/WidgetPropsUtils.tsx

1527 lines
44 KiB
TypeScript
Raw Normal View History

2019-11-25 05:07:27 +00:00
import { FetchPageResponse } from "api/PageApi";
import { CANVAS_DEFAULT_HEIGHT_PX } from "constants/AppConstants";
import { XYCord } from "utils/hooks/useCanvasDragging";
2019-11-25 05:07:27 +00:00
import { ContainerWidgetProps } from "widgets/ContainerWidget";
import { WidgetConfigProps } from "reducers/entityReducers/widgetConfigReducer";
import {
WidgetOperation,
2020-03-06 09:45:21 +00:00
WidgetOperations,
WidgetProps,
2019-11-25 05:07:27 +00:00
} from "widgets/BaseWidget";
2020-01-16 11:46:21 +00:00
import {
GridDefaults,
LATEST_PAGE_VERSION,
MAIN_CONTAINER_WIDGET_ID,
2020-04-17 16:15:09 +00:00
RenderMode,
2020-03-06 09:45:21 +00:00
WidgetType,
2020-01-16 11:46:21 +00:00
WidgetTypes,
} from "constants/WidgetConstants";
List Widget Phase 2 (#4189) * update meta properties + default properties map * update widget registery * update get meta property * update metahoc + widgetfactory + data tree evaluator * try sending function as string to worker * revert data tree evaluator update * pass default props map from dataTreeWidget file * wip * save child meta properties * remove console.log * save meta and default map in list * update listwidget * remove console.log + unused variables * revert getMetaPropertiesMap function * fix data tree test * fix list widget test * fix entity definition test * fix overriting of item in updatedItems * remove todo comments * fix meta prop issue * revert making meta properties from undefiend to "" & fix filepicker bug * fix test case * change items to listData and updatedItems to items * remove console.log * fix test * extract derived properties to dervied.js * disabled top, left, right resize handler list widget container * add test for dervied js * add test for selectedItem * fix background color bug on hover * remove console.log * fix chart widget inside list widget * fix checkbox issue + points raised by yogesh * revert the createImmerReducer usage * fix parse derived properties * remove internal props object that fails the test * fix import typo * allow bottom resize handler * fix template height check * fix template height check * update template size check * fix the is visible invalid prop issue * fix migration of list widget phase 2 * fix migration * remove unused import * fix migration * fix migration * remove console.log * hide delete option for container in entity explorer * fix testcases * remove unused import * fix switch widget meta prop Co-authored-by: root <root@DESKTOP-9GENCK0.localdomain> Co-authored-by: Pawan Kumar <pawankumar@Pawans-MacBook-Pro.local>
2021-06-18 07:42:57 +00:00
import { renameKeyInObject, snapToGrid } from "./helpers";
import { OccupiedSpace } from "constants/editorConstants";
2020-02-13 09:32:24 +00:00
import defaultTemplate from "templates/default";
import { generateReactKey } from "./generators";
2020-04-15 15:26:36 +00:00
import { ChartDataPoint } from "widgets/ChartWidget";
import { FlattenedWidgetProps } from "reducers/entityReducers/canvasWidgetsReducer";
import { has, isString, set, isEmpty, omit, get } from "lodash";
import log from "loglevel";
import {
migrateTablePrimaryColumnsBindings,
tableWidgetPropertyPaneMigrations,
migrateTableWidgetParentRowSpaceProperty,
migrateTableWidgetHeaderVisibilityProperties,
migrateTablePrimaryColumnsComputedValue,
migrateTableWidgetDelimiterProperties,
} from "utils/migrations/TableWidget";
import { migrateIncorrectDynamicBindingPathLists } from "utils/migrations/IncorrectDynamicBindingPathLists";
import * as Sentry from "@sentry/react";
import { migrateTextStyleFromTextWidget } from "./migrations/TextWidgetReplaceTextStyle";
import { nextAvailableRowInContainer } from "entities/Widget/utils";
import { DATA_BIND_REGEX_GLOBAL } from "constants/BindingsConstants";
import { ColumnProperties } from "components/designSystems/appsmith/TableComponent/Constants";
import WidgetConfigResponse, {
GRID_DENSITY_MIGRATION_V1,
} from "mockResponses/WidgetConfigResponse";
import CanvasWidgetsNormalizer from "normalizers/CanvasWidgetsNormalizer";
import { theme } from "../../src/constants/DefaultTheme";
import { migrateMenuButtonWidgetButtonProperties } from "./migrations/MenuButtonWidget";
export type WidgetOperationParams = {
operation: WidgetOperation;
widgetId: string;
payload: any;
};
const { DEFAULT_GRID_ROW_HEIGHT } = GridDefaults;
2019-09-25 21:21:04 +00:00
type Rect = {
top: number;
left: number;
right: number;
bottom: number;
};
const defaultDSL = defaultTemplate;
2020-01-16 11:46:21 +00:00
const updateContainers = (dsl: ContainerWidgetProps<WidgetProps>) => {
if (
dsl.type === WidgetTypes.CONTAINER_WIDGET ||
dsl.type === WidgetTypes.FORM_WIDGET
) {
if (
!(
dsl.children &&
dsl.children.length > 0 &&
(dsl.children[0].type === WidgetTypes.CANVAS_WIDGET ||
dsl.children[0].type === WidgetTypes.FORM_WIDGET)
)
) {
const canvas = {
...dsl,
2020-04-29 10:09:27 +00:00
backgroundColor: "transparent",
type: WidgetTypes.CANVAS_WIDGET,
detachFromLayout: true,
topRow: 0,
leftColumn: 0,
rightColumn: dsl.parentColumnSpace * (dsl.rightColumn - dsl.leftColumn),
bottomRow: dsl.parentRowSpace * (dsl.bottomRow - dsl.topRow),
widgetName: generateReactKey(),
widgetId: generateReactKey(),
parentRowSpace: 1,
parentColumnSpace: 1,
containerStyle: "none",
canExtend: false,
isVisible: true,
};
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
delete canvas.dynamicBindings;
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
delete canvas.dynamicProperties;
if (canvas.children && canvas.children.length > 0)
canvas.children = canvas.children.map(updateContainers);
dsl.children = [{ ...canvas }];
}
}
return dsl;
};
2020-01-16 11:46:21 +00:00
2020-04-15 15:26:36 +00:00
//transform chart data, from old chart widget to new chart widget
//updatd chart widget has support for multiple series
const chartDataMigration = (currentDSL: ContainerWidgetProps<WidgetProps>) => {
currentDSL.children = currentDSL.children?.map((children: WidgetProps) => {
if (
children.type === WidgetTypes.CHART_WIDGET &&
children.chartData &&
children.chartData.length &&
!Array.isArray(children.chartData[0])
) {
children.chartData = [{ data: children.chartData as ChartDataPoint[] }];
} else if (
children.type === WidgetTypes.CONTAINER_WIDGET ||
children.type === WidgetTypes.FORM_WIDGET ||
children.type === WidgetTypes.CANVAS_WIDGET ||
children.type === WidgetTypes.TABS_WIDGET
) {
children = chartDataMigration(children);
}
return children;
});
return currentDSL;
};
const singleChartDataMigration = (
currentDSL: ContainerWidgetProps<WidgetProps>,
) => {
2020-12-24 04:32:25 +00:00
currentDSL.children = currentDSL.children?.map((child) => {
if (child.type === WidgetTypes.CHART_WIDGET) {
// Check if chart widget has the deprecated singleChartData property
if (child.hasOwnProperty("singleChartData")) {
// This is to make sure that the format of the chartData is accurate
if (
Array.isArray(child.singleChartData) &&
!child.singleChartData[0].hasOwnProperty("seriesName")
) {
child.singleChartData = {
seriesName: "Series 1",
data: child.singleChartData || [],
};
}
//TODO: other possibilities?
child.chartData = JSON.stringify([...child.singleChartData]);
delete child.singleChartData;
}
}
if (child.children && child.children.length > 0) {
child = singleChartDataMigration(child);
}
return child;
});
return currentDSL;
};
2020-05-07 10:51:37 +00:00
const mapDataMigration = (currentDSL: ContainerWidgetProps<WidgetProps>) => {
currentDSL.children = currentDSL.children?.map((children: WidgetProps) => {
if (children.type === WidgetTypes.MAP_WIDGET) {
if (children.markers) {
children.markers = children.markers.map(
(marker: { lat: any; lng: any; long: any; title: any }) => {
return {
lat: marker.lat,
long: marker.lng || marker.long,
title: marker.title,
};
},
);
}
if (children.defaultMarkers) {
const defaultMarkers = JSON.parse(children.defaultMarkers);
children.defaultMarkers = defaultMarkers.map(
(marker: {
lat: number;
lng: number;
long: number;
title: string;
}) => {
return {
lat: marker.lat,
long: marker.lng || marker.long,
title: marker.title,
};
},
);
}
if (children.selectedMarker) {
children.selectedMarker = {
lat: children.selectedMarker.lat,
long: children.selectedMarker.lng || children.selectedMarker.long,
title: children.selectedMarker.title,
};
}
if (children.mapCenter) {
children.mapCenter = {
lat: children.mapCenter.lat,
long: children.mapCenter.lng || children.mapCenter.long,
title: children.mapCenter.title,
};
}
if (children.center) {
children.center = {
lat: children.center.lat,
long: children.center.lng || children.center.long,
title: children.center.title,
};
}
} else if (children.children && children.children.length > 0) {
children = mapDataMigration(children);
}
return children;
});
return currentDSL;
};
const tabsWidgetTabsPropertyMigration = (
currentDSL: ContainerWidgetProps<WidgetProps>,
) => {
currentDSL.children = currentDSL.children
?.filter(Boolean)
.map((child: WidgetProps) => {
if (child.type === WidgetTypes.TABS_WIDGET) {
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);
}
return child;
});
return currentDSL;
};
const dynamicPathListMigration = (
currentDSL: ContainerWidgetProps<WidgetProps>,
) => {
if (currentDSL.children && currentDSL.children.length) {
currentDSL.children = currentDSL.children.map(dynamicPathListMigration);
}
if (currentDSL.dynamicBindings) {
currentDSL.dynamicBindingPathList = Object.keys(
currentDSL.dynamicBindings,
2020-12-24 04:32:25 +00:00
).map((path) => ({ key: path }));
delete currentDSL.dynamicBindings;
}
if (currentDSL.dynamicTriggers) {
currentDSL.dynamicTriggerPathList = Object.keys(
currentDSL.dynamicTriggers,
2020-12-24 04:32:25 +00:00
).map((path) => ({ key: path }));
delete currentDSL.dynamicTriggers;
}
if (currentDSL.dynamicProperties) {
currentDSL.dynamicPropertyPathList = Object.keys(
currentDSL.dynamicProperties,
2020-12-24 04:32:25 +00:00
).map((path) => ({ key: path }));
delete currentDSL.dynamicProperties;
}
return currentDSL;
};
const addVersionNumberMigration = (
currentDSL: ContainerWidgetProps<WidgetProps>,
) => {
if (currentDSL.children && currentDSL.children.length) {
currentDSL.children = currentDSL.children.map(addVersionNumberMigration);
}
if (currentDSL.version === undefined) {
currentDSL.version = 1;
}
return currentDSL;
};
const canvasNameConflictMigration = (
currentDSL: ContainerWidgetProps<WidgetProps>,
props = { counter: 1 },
): ContainerWidgetProps<WidgetProps> => {
if (
currentDSL.type === WidgetTypes.CANVAS_WIDGET &&
currentDSL.widgetName.startsWith("Canvas")
) {
currentDSL.widgetName = `Canvas${props.counter}`;
// Canvases inside tabs have `name` property as well
if (currentDSL.name) {
currentDSL.name = currentDSL.widgetName;
}
props.counter++;
}
currentDSL.children?.forEach((c) => canvasNameConflictMigration(c, props));
return currentDSL;
};
const renamedCanvasNameConflictMigration = (
currentDSL: ContainerWidgetProps<WidgetProps>,
props = { counter: 1 },
): ContainerWidgetProps<WidgetProps> => {
// Rename all canvas widgets except for MainContainer
if (
currentDSL.type === WidgetTypes.CANVAS_WIDGET &&
currentDSL.widgetName !== "MainContainer"
) {
currentDSL.widgetName = `Canvas${props.counter}`;
// Canvases inside tabs have `name` property as well
if (currentDSL.name) {
currentDSL.name = currentDSL.widgetName;
}
props.counter++;
}
currentDSL.children?.forEach((c) => canvasNameConflictMigration(c, props));
return currentDSL;
};
const rteDefaultValueMigration = (
currentDSL: ContainerWidgetProps<WidgetProps>,
): ContainerWidgetProps<WidgetProps> => {
if (currentDSL.type === WidgetTypes.RICH_TEXT_EDITOR_WIDGET) {
currentDSL.inputType = "html";
}
currentDSL.children?.forEach((children) =>
rteDefaultValueMigration(children),
);
return currentDSL;
};
function migrateTabsDataUsingMigrator(
currentDSL: ContainerWidgetProps<WidgetProps>,
) {
if (currentDSL.type === WidgetTypes.TABS_WIDGET && currentDSL.version === 1) {
try {
currentDSL.type = WidgetTypes.TABS_MIGRATOR_WIDGET;
currentDSL.version = 1;
} catch (error) {
Sentry.captureException({
message: "Tabs Migration Failed",
oldData: currentDSL.tabs,
});
currentDSL.tabsObj = {};
delete currentDSL.tabs;
}
}
if (currentDSL.children && currentDSL.children.length) {
currentDSL.children = currentDSL.children.map(migrateTabsDataUsingMigrator);
}
return currentDSL;
}
export function migrateTabsData(currentDSL: ContainerWidgetProps<WidgetProps>) {
if (
[WidgetTypes.TABS_WIDGET, WidgetTypes.TABS_MIGRATOR_WIDGET].includes(
currentDSL.type as any,
) &&
currentDSL.version === 1
) {
try {
currentDSL.type = WidgetTypes.TABS_WIDGET;
const isTabsDataBinded = isString(currentDSL.tabs);
currentDSL.dynamicPropertyPathList =
currentDSL.dynamicPropertyPathList || [];
currentDSL.dynamicBindingPathList =
currentDSL.dynamicBindingPathList || [];
if (isTabsDataBinded) {
const tabsString = currentDSL.tabs.replace(
DATA_BIND_REGEX_GLOBAL,
(word: any) => `"${word}"`,
);
try {
currentDSL.tabs = JSON.parse(tabsString);
} catch (error) {
return migrateTabsDataUsingMigrator(currentDSL);
}
const dynamicPropsList = currentDSL.tabs
.filter((each: any) => DATA_BIND_REGEX_GLOBAL.test(each.isVisible))
.map((each: any) => {
return { key: `tabsObj.${each.id}.isVisible` };
});
const dynamicBindablePropsList = currentDSL.tabs.map((each: any) => {
return { key: `tabsObj.${each.id}.isVisible` };
});
currentDSL.dynamicPropertyPathList = [
...currentDSL.dynamicPropertyPathList,
...dynamicPropsList,
];
currentDSL.dynamicBindingPathList = [
...currentDSL.dynamicBindingPathList,
...dynamicBindablePropsList,
];
}
currentDSL.dynamicPropertyPathList = currentDSL.dynamicPropertyPathList.filter(
(each) => {
return each.key !== "tabs";
},
);
currentDSL.dynamicBindingPathList = currentDSL.dynamicBindingPathList.filter(
(each) => {
return each.key !== "tabs";
},
);
currentDSL.tabsObj = currentDSL.tabs.reduce(
(obj: any, tab: any, index: number) => {
obj = {
...obj,
[tab.id]: {
...tab,
isVisible: tab.isVisible === undefined ? true : tab.isVisible,
index,
},
};
return obj;
},
{},
);
currentDSL.version = 2;
delete currentDSL.tabs;
} catch (error) {
Sentry.captureException({
message: "Tabs Migration Failed",
oldData: currentDSL.tabs,
});
currentDSL.tabsObj = {};
delete currentDSL.tabs;
}
}
if (currentDSL.children && currentDSL.children.length) {
currentDSL.children = currentDSL.children.map(migrateTabsData);
}
return currentDSL;
}
// A rudimentary transform function which updates the DSL based on its version.
function migrateOldChartData(currentDSL: ContainerWidgetProps<WidgetProps>) {
if (currentDSL.type === WidgetTypes.CHART_WIDGET) {
if (isString(currentDSL.chartData)) {
try {
currentDSL.chartData = JSON.parse(currentDSL.chartData);
} catch (error) {
Sentry.captureException({
message: "Chart Migration Failed",
oldData: currentDSL.chartData,
});
currentDSL.chartData = [];
}
}
}
if (currentDSL.children && currentDSL.children.length) {
currentDSL.children = currentDSL.children.map(migrateOldChartData);
}
return currentDSL;
}
/**
* changes chartData which we were using as array. now it will be a object
*
*
* @param currentDSL
* @returns
*/
export function migrateChartDataFromArrayToObject(
currentDSL: ContainerWidgetProps<WidgetProps>,
) {
currentDSL.children = currentDSL.children?.map((children: WidgetProps) => {
if (children.type === WidgetTypes.CHART_WIDGET) {
if (Array.isArray(children.chartData)) {
const newChartData = {};
const dynamicBindingPathList = children?.dynamicBindingPathList
? children?.dynamicBindingPathList.slice()
: [];
children.chartData.map((datum: any, index: number) => {
const generatedKey = generateReactKey();
set(newChartData, `${generatedKey}`, datum);
if (
Array.isArray(children.dynamicBindingPathList) &&
children.dynamicBindingPathList?.findIndex(
(path) => (path.key = `chartData[${index}].data`),
) > -1
) {
const foundIndex = children.dynamicBindingPathList.findIndex(
(path) => (path.key = `chartData[${index}].data`),
);
dynamicBindingPathList[foundIndex] = {
key: `chartData.${generatedKey}.data`,
};
}
});
children.dynamicBindingPathList = dynamicBindingPathList;
children.chartData = newChartData;
}
} else if (
children.type === WidgetTypes.CONTAINER_WIDGET ||
children.type === WidgetTypes.FORM_WIDGET ||
children.type === WidgetTypes.CANVAS_WIDGET ||
children.type === WidgetTypes.TABS_WIDGET
) {
children = migrateChartDataFromArrayToObject(children);
}
return children;
});
return currentDSL;
}
const pixelToNumber = (pixel: string) => {
if (pixel.includes("px")) {
return parseInt(pixel.split("px").join(""));
}
return 0;
};
export const calculateDynamicHeight = (
canvasWidgets: {
[widgetId: string]: FlattenedWidgetProps;
} = {},
presentMinimumHeight = CANVAS_DEFAULT_HEIGHT_PX,
) => {
let minimumHeight = presentMinimumHeight;
const nextAvailableRow = nextAvailableRowInContainer(
MAIN_CONTAINER_WIDGET_ID,
canvasWidgets,
);
const screenHeight = window.innerHeight;
const gridRowHeight = GridDefaults.DEFAULT_GRID_ROW_HEIGHT;
const calculatedCanvasHeight = nextAvailableRow * gridRowHeight;
// DGRH - DEFAULT_GRID_ROW_HEIGHT
// View Mode: Header height + Page Selection Tab = 8 * DGRH (approx)
// Edit Mode: Header height + Canvas control = 8 * DGRH (approx)
// buffer: ~8 grid row height
const buffer = gridRowHeight + 2 * pixelToNumber(theme.smallHeaderHeight);
const calculatedMinHeight =
Math.floor((screenHeight - buffer) / gridRowHeight) * gridRowHeight;
if (
calculatedCanvasHeight < screenHeight &&
calculatedMinHeight !== presentMinimumHeight
) {
minimumHeight = calculatedMinHeight;
}
return minimumHeight;
};
export const migrateInitialValues = (
currentDSL: ContainerWidgetProps<WidgetProps>,
) => {
currentDSL.children = currentDSL.children?.map((child: WidgetProps) => {
if (child.type === WidgetTypes.INPUT_WIDGET) {
child = {
isRequired: false,
isDisabled: false,
resetOnSubmit: false,
...child,
};
} else if (child.type === WidgetTypes.DROP_DOWN_WIDGET) {
child = {
isRequired: false,
isDisabled: false,
...child,
};
} else if (child.type === WidgetTypes.DATE_PICKER_WIDGET2) {
child = {
minDate: "2001-01-01 00:00",
maxDate: "2041-12-31 23:59",
isRequired: false,
...child,
};
} else if (child.type === WidgetTypes.SWITCH_WIDGET) {
child = {
isDisabled: false,
...child,
};
} else if (child.type === WidgetTypes.ICON_WIDGET) {
child = {
isRequired: false,
...child,
};
} else if (child.type === WidgetTypes.VIDEO_WIDGET) {
child = {
isRequired: false,
isDisabled: false,
...child,
};
} else if (child.type === WidgetTypes.CHECKBOX_WIDGET) {
child = {
isDisabled: false,
isRequired: false,
...child,
};
} else if (child.type === WidgetTypes.RADIO_GROUP_WIDGET) {
child = {
isDisabled: false,
isRequired: false,
...child,
};
} else if (child.type === WidgetTypes.FILE_PICKER_WIDGET) {
child = {
isDisabled: false,
isRequired: false,
allowedFileTypes: [],
...child,
};
} else if (child.children && child.children.length > 0) {
child = migrateInitialValues(child);
}
return child;
});
return currentDSL;
};
// A rudimentary transform function which updates the DSL based on its version.
// A more modular approach needs to be designed.
const transformDSL = (currentDSL: ContainerWidgetProps<WidgetProps>) => {
if (currentDSL.version === undefined) {
// Since this top level widget is a CANVAS_WIDGET,
// DropTargetComponent needs to know the minimum height the canvas can take
// See DropTargetUtils.ts
currentDSL.minHeight = calculateDynamicHeight();
// For the first time the DSL is created, remove one row from the total possible rows
// to adjust for padding and margins.
currentDSL.snapRows =
Math.floor(currentDSL.bottomRow / DEFAULT_GRID_ROW_HEIGHT) - 1;
2020-01-16 11:46:21 +00:00
// Force the width of the canvas to 1224 px
currentDSL.rightColumn = 1224;
// The canvas is a CANVAS_WIDGET whichdoesn't have a background or borders by default
currentDSL.backgroundColor = "none";
currentDSL.containerStyle = "none";
currentDSL.type = WidgetTypes.CANVAS_WIDGET;
currentDSL.detachFromLayout = true;
currentDSL.canExtend = true;
2020-02-13 09:32:24 +00:00
// Update version to make sure this doesn't run everytime.
currentDSL.version = 1;
}
if (currentDSL.version === 1) {
if (currentDSL.children && currentDSL.children.length > 0)
currentDSL.children = currentDSL.children.map(updateContainers);
currentDSL.version = 2;
}
2020-04-15 15:26:36 +00:00
if (currentDSL.version === 2) {
currentDSL = chartDataMigration(currentDSL);
currentDSL.version = 3;
}
2020-05-07 10:51:37 +00:00
if (currentDSL.version === 3) {
currentDSL = mapDataMigration(currentDSL);
currentDSL.version = 4;
}
if (currentDSL.version === 4) {
currentDSL = singleChartDataMigration(currentDSL);
currentDSL.version = 5;
}
if (currentDSL.version === 5) {
currentDSL = tabsWidgetTabsPropertyMigration(currentDSL);
currentDSL.version = 6;
}
if (currentDSL.version === 6) {
currentDSL = dynamicPathListMigration(currentDSL);
currentDSL.version = 7;
}
if (currentDSL.version === 7) {
currentDSL = canvasNameConflictMigration(currentDSL);
currentDSL.version = 8;
}
if (currentDSL.version === 8) {
currentDSL = renamedCanvasNameConflictMigration(currentDSL);
currentDSL.version = 9;
}
if (currentDSL.version === 9) {
currentDSL = tableWidgetPropertyPaneMigrations(currentDSL);
currentDSL.version = 10;
}
if (currentDSL.version === 10) {
currentDSL = addVersionNumberMigration(currentDSL);
currentDSL.version = 11;
}
if (currentDSL.version === 11) {
currentDSL = migrateTablePrimaryColumnsBindings(currentDSL);
currentDSL.version = 12;
}
if (currentDSL.version === 12) {
currentDSL = migrateIncorrectDynamicBindingPathLists(currentDSL);
currentDSL.version = 13;
}
if (currentDSL.version === 13) {
currentDSL = migrateOldChartData(currentDSL);
currentDSL.version = 14;
}
if (currentDSL.version === 14) {
currentDSL = rteDefaultValueMigration(currentDSL);
currentDSL.version = 15;
}
if (currentDSL.version === 15) {
currentDSL = migrateTextStyleFromTextWidget(currentDSL);
currentDSL.version = 16;
}
if (currentDSL.version === 16) {
currentDSL = migrateChartDataFromArrayToObject(currentDSL);
currentDSL.version = 17;
}
if (currentDSL.version === 17) {
currentDSL = migrateTabsData(currentDSL);
currentDSL.version = 18;
}
if (currentDSL.version === 18) {
currentDSL = migrateInitialValues(currentDSL);
currentDSL.version = 19;
}
if (currentDSL.version === 19) {
currentDSL.snapColumns = GridDefaults.DEFAULT_GRID_COLUMNS;
currentDSL.snapRows = getCanvasSnapRows(
currentDSL.bottomRow,
currentDSL.detachFromLayout || false,
);
currentDSL = migrateToNewLayout(currentDSL);
currentDSL.version = 20;
}
if (currentDSL.version === 20) {
currentDSL = migrateNewlyAddedTabsWidgetsMissingData(currentDSL);
currentDSL.version = 21;
}
if (currentDSL.version === 21) {
const {
entities: { canvasWidgets },
} = CanvasWidgetsNormalizer.normalize(currentDSL);
currentDSL = migrateWidgetsWithoutLeftRightColumns(
currentDSL,
canvasWidgets,
);
currentDSL = migrateOverFlowingTabsWidgets(currentDSL, canvasWidgets);
currentDSL.version = 22;
}
if (currentDSL.version === 22) {
currentDSL = migrateTableWidgetParentRowSpaceProperty(currentDSL);
currentDSL.version = 23;
}
if (currentDSL.version === 23) {
currentDSL = addLogBlackListToAllListWidgetChildren(currentDSL);
currentDSL.version = 24;
}
if (currentDSL.version === 24) {
currentDSL = migrateTableWidgetHeaderVisibilityProperties(currentDSL);
List Widget Phase 2 (#4189) * update meta properties + default properties map * update widget registery * update get meta property * update metahoc + widgetfactory + data tree evaluator * try sending function as string to worker * revert data tree evaluator update * pass default props map from dataTreeWidget file * wip * save child meta properties * remove console.log * save meta and default map in list * update listwidget * remove console.log + unused variables * revert getMetaPropertiesMap function * fix data tree test * fix list widget test * fix entity definition test * fix overriting of item in updatedItems * remove todo comments * fix meta prop issue * revert making meta properties from undefiend to "" & fix filepicker bug * fix test case * change items to listData and updatedItems to items * remove console.log * fix test * extract derived properties to dervied.js * disabled top, left, right resize handler list widget container * add test for dervied js * add test for selectedItem * fix background color bug on hover * remove console.log * fix chart widget inside list widget * fix checkbox issue + points raised by yogesh * revert the createImmerReducer usage * fix parse derived properties * remove internal props object that fails the test * fix import typo * allow bottom resize handler * fix template height check * fix template height check * update template size check * fix the is visible invalid prop issue * fix migration of list widget phase 2 * fix migration * remove unused import * fix migration * fix migration * remove console.log * hide delete option for container in entity explorer * fix testcases * remove unused import * fix switch widget meta prop Co-authored-by: root <root@DESKTOP-9GENCK0.localdomain> Co-authored-by: Pawan Kumar <pawankumar@Pawans-MacBook-Pro.local>
2021-06-18 07:42:57 +00:00
currentDSL.version = 25;
}
if (currentDSL.version === 25) {
currentDSL = migrateItemsToListDataInListWidget(currentDSL);
currentDSL.version = 26;
}
if (currentDSL.version === 26) {
currentDSL = migrateDatePickerMinMaxDate(currentDSL);
currentDSL.version = 27;
}
if (currentDSL.version === 27) {
currentDSL = migrateFilterValueForDropDownWidget(currentDSL);
currentDSL.version = 28;
}
if (currentDSL.version === 28) {
currentDSL = migrateTablePrimaryColumnsComputedValue(currentDSL);
currentDSL.version = 29;
}
if (currentDSL.version === 29) {
currentDSL = migrateToNewMultiSelect(currentDSL);
currentDSL.version = 30;
}
if (currentDSL.version === 30) {
currentDSL = migrateTableWidgetDelimiterProperties(currentDSL);
currentDSL.version = 31;
}
if (currentDSL.version === 31) {
currentDSL = migrateIsDisabledToButtonColumn(currentDSL);
currentDSL.version = 32;
}
if (currentDSL.version === 32) {
currentDSL = migrateTableVersion(currentDSL);
currentDSL.version = 33;
}
if (currentDSL.version === 33) {
currentDSL = migrateMenuButtonWidgetButtonProperties(currentDSL);
currentDSL.version = 34;
}
if (currentDSL.version === 34) {
currentDSL = migrateButtonWidgetValidation(currentDSL);
currentDSL.version = 35;
}
if (currentDSL.version === 35) {
currentDSL = migrateInputValidation(currentDSL);
currentDSL.version = 36;
}
if (currentDSL.version === 36) {
currentDSL = revertTableDefaultSelectedRow(currentDSL);
currentDSL.version = LATEST_PAGE_VERSION;
}
return currentDSL;
};
export const revertTableDefaultSelectedRow = (
currentDSL: ContainerWidgetProps<WidgetProps>,
) => {
if (currentDSL.type === WidgetTypes.TABLE_WIDGET) {
if (currentDSL.version === 1 && currentDSL.defaultSelectedRow === "0")
currentDSL.defaultSelectedRow = undefined;
// update version to 3 for all table dsl
currentDSL.version = 3;
}
if (currentDSL.children && currentDSL.children.length) {
currentDSL.children = currentDSL.children.map((child) =>
revertTableDefaultSelectedRow(child),
);
}
return currentDSL;
};
export const migrateTableVersion = (
currentDSL: ContainerWidgetProps<WidgetProps>,
) => {
// this is done to stop reverse migrations for apps that did not use migrateTableDefaultSelectedRow to migrate
if (currentDSL.type === WidgetTypes.TABLE_WIDGET) {
currentDSL.version = 2;
}
if (currentDSL.children && currentDSL.children.length) {
currentDSL.children = currentDSL.children.map((child) =>
migrateTableVersion(child),
);
}
return currentDSL;
};
const addIsDisabledToButtonColumn = (
currentDSL: ContainerWidgetProps<WidgetProps>,
) => {
if (currentDSL.type === "TABLE_WIDGET") {
if (!isEmpty(currentDSL.primaryColumns)) {
for (const key of Object.keys(
currentDSL.primaryColumns as Record<string, ColumnProperties>,
)) {
if (currentDSL.primaryColumns[key].columnType === "button") {
if (!currentDSL.primaryColumns[key].hasOwnProperty("isDisabled")) {
currentDSL.primaryColumns[key]["isDisabled"] = false;
}
}
if (!currentDSL.primaryColumns[key].hasOwnProperty("isCellVisible")) {
currentDSL.primaryColumns[key]["isCellVisible"] = true;
}
}
}
}
return currentDSL;
};
2019-09-26 11:11:28 +00:00
export const migrateInputValidation = (
currentDSL: ContainerWidgetProps<WidgetProps>,
) => {
if (currentDSL.type === WidgetTypes.INPUT_WIDGET) {
if (has(currentDSL, "validation")) {
// convert boolean to string expression
if (typeof currentDSL.validation === "boolean") {
currentDSL.validation = String(currentDSL.validation);
} else if (typeof currentDSL.validation !== "string") {
// for any other type of value set to default undefined
currentDSL.validation = undefined;
}
}
}
if (currentDSL.children && currentDSL.children.length) {
currentDSL.children = currentDSL.children.map((child) =>
migrateInputValidation(child),
);
}
return currentDSL;
};
const migrateIsDisabledToButtonColumn = (
currentDSL: ContainerWidgetProps<WidgetProps>,
) => {
const newDSL = addIsDisabledToButtonColumn(currentDSL);
newDSL.children = newDSL.children?.map((children: WidgetProps) => {
return migrateIsDisabledToButtonColumn(children);
});
return currentDSL;
};
export const migrateToNewMultiSelect = (
currentDSL: ContainerWidgetProps<WidgetProps>,
) => {
if (currentDSL.type === "DROP_DOWN_WIDGET") {
if (currentDSL.selectionType === "MULTI_SELECT") {
currentDSL.type = "MULTI_SELECT_WIDGET";
delete currentDSL.isFilterable;
}
delete currentDSL.selectionType;
}
if (currentDSL.children && currentDSL.children.length) {
currentDSL.children = currentDSL.children.map((child) =>
migrateToNewMultiSelect(child),
);
}
return currentDSL;
};
const migrateButtonWidgetValidation = (
currentDSL: ContainerWidgetProps<WidgetProps>,
) => {
if (currentDSL.type === WidgetTypes.INPUT_WIDGET) {
if (!has(currentDSL, "validation")) {
currentDSL.validation = true;
}
}
if (currentDSL.children && currentDSL.children.length) {
currentDSL.children.map(
(eachWidgetDSL: ContainerWidgetProps<WidgetProps>) => {
migrateButtonWidgetValidation(eachWidgetDSL);
},
);
}
return currentDSL;
};
const migrateDatePickerMinMaxDate = (
currentDSL: ContainerWidgetProps<WidgetProps>,
) => {
if (
currentDSL.type === WidgetTypes.DATE_PICKER_WIDGET2 &&
currentDSL.version === 2
) {
if (currentDSL.minDate === "2001-01-01 00:00") {
currentDSL.minDate = "1920-12-31T18:30:00.000Z";
}
if (currentDSL.maxDate === "2041-12-31 23:59") {
currentDSL.maxDate = "2121-12-31T18:29:00.000Z";
}
}
if (currentDSL.children && currentDSL.children.length) {
currentDSL.children.map(
(eachWidgetDSL: ContainerWidgetProps<WidgetProps>) => {
migrateDatePickerMinMaxDate(eachWidgetDSL);
},
);
}
return currentDSL;
};
const addFilterDefaultValue = (
currentDSL: ContainerWidgetProps<WidgetProps>,
) => {
if (currentDSL.type === WidgetTypes.DROP_DOWN_WIDGET) {
if (!currentDSL.hasOwnProperty("isFilterable")) {
currentDSL.isFilterable = true;
}
}
return currentDSL;
};
export const migrateFilterValueForDropDownWidget = (
currentDSL: ContainerWidgetProps<WidgetProps>,
) => {
const newDSL = addFilterDefaultValue(currentDSL);
newDSL.children = newDSL.children?.map((children: WidgetProps) => {
return migrateFilterValueForDropDownWidget(children);
});
return newDSL;
};
export const migrateObjectFitToImageWidget = (
dsl: ContainerWidgetProps<WidgetProps>,
) => {
const addObjectFitProperty = (widgetProps: WidgetProps) => {
widgetProps.objectFit = "cover";
if (widgetProps.children && widgetProps.children.length) {
widgetProps.children.forEach((eachWidgetProp: WidgetProps) => {
if (widgetProps.type === "IMAGE_WIDGET") {
addObjectFitProperty(eachWidgetProp);
}
});
}
};
addObjectFitProperty(dsl);
return dsl;
};
const migrateOverFlowingTabsWidgets = (
currentDSL: ContainerWidgetProps<WidgetProps>,
canvasWidgets: any,
) => {
if (
currentDSL.type === "TABS_WIDGET" &&
currentDSL.version === 3 &&
currentDSL.children &&
currentDSL.children.length
) {
const tabsWidgetHeight =
(currentDSL.bottomRow - currentDSL.topRow) * currentDSL.parentRowSpace;
const widgetHasOverflowingChildren = currentDSL.children.some((eachTab) => {
if (eachTab.children && eachTab.children.length) {
return eachTab.children.some((child: WidgetProps) => {
if (canvasWidgets[child.widgetId].repositioned) {
const tabHeight = child.bottomRow * child.parentRowSpace;
return tabsWidgetHeight < tabHeight;
}
return false;
});
}
return false;
});
if (widgetHasOverflowingChildren) {
currentDSL.shouldScrollContents = true;
}
}
if (currentDSL.children && currentDSL.children.length) {
currentDSL.children = currentDSL.children.map((eachChild) =>
migrateOverFlowingTabsWidgets(eachChild, canvasWidgets),
);
}
return currentDSL;
};
const migrateWidgetsWithoutLeftRightColumns = (
currentDSL: ContainerWidgetProps<WidgetProps>,
canvasWidgets: any,
) => {
if (
currentDSL.widgetId !== MAIN_CONTAINER_WIDGET_ID &&
!(
currentDSL.hasOwnProperty("leftColumn") &&
currentDSL.hasOwnProperty("rightColumn")
)
) {
try {
const nextRow = nextAvailableRowInContainer(
currentDSL.parentId || MAIN_CONTAINER_WIDGET_ID,
omit(canvasWidgets, [currentDSL.widgetId]),
);
canvasWidgets[currentDSL.widgetId].repositioned = true;
const leftColumn = 0;
const rightColumn = WidgetConfigResponse.config[currentDSL.type].rows;
const bottomRow = nextRow + (currentDSL.bottomRow - currentDSL.topRow);
const topRow = nextRow;
currentDSL = {
...currentDSL,
topRow,
bottomRow,
rightColumn,
leftColumn,
};
} catch (error) {
Sentry.captureException({
message: "Migrating position of widget on data loss failed",
oldData: currentDSL,
});
}
}
if (currentDSL.children && currentDSL.children.length) {
currentDSL.children = currentDSL.children.map((dsl) =>
migrateWidgetsWithoutLeftRightColumns(dsl, canvasWidgets),
);
}
return currentDSL;
};
const migrateNewlyAddedTabsWidgetsMissingData = (
currentDSL: ContainerWidgetProps<WidgetProps>,
) => {
if (currentDSL.type === WidgetTypes.TABS_WIDGET && currentDSL.version === 2) {
try {
if (currentDSL.children && currentDSL.children.length) {
currentDSL.children = currentDSL.children.map((each) => {
if (has(currentDSL, ["leftColumn", "rightColumn", "bottomRow"])) {
return each;
}
return {
...each,
leftColumn: 0,
rightColumn:
(currentDSL.rightColumn - currentDSL.leftColumn) *
currentDSL.parentColumnSpace,
bottomRow:
(currentDSL.bottomRow - currentDSL.topRow) *
currentDSL.parentRowSpace,
};
});
}
currentDSL.version = 3;
} catch (error) {
Sentry.captureException({
message: "Tabs Migration to add missing fields Failed",
oldData: currentDSL.children,
});
}
}
if (currentDSL.children && currentDSL.children.length) {
currentDSL.children = currentDSL.children.map(
migrateNewlyAddedTabsWidgetsMissingData,
);
}
return currentDSL;
};
export const migrateToNewLayout = (dsl: ContainerWidgetProps<WidgetProps>) => {
const scaleWidget = (widgetProps: WidgetProps) => {
widgetProps.bottomRow *= GRID_DENSITY_MIGRATION_V1;
widgetProps.topRow *= GRID_DENSITY_MIGRATION_V1;
widgetProps.leftColumn *= GRID_DENSITY_MIGRATION_V1;
widgetProps.rightColumn *= GRID_DENSITY_MIGRATION_V1;
if (widgetProps.children && widgetProps.children.length) {
widgetProps.children.forEach((eachWidgetProp: WidgetProps) => {
scaleWidget(eachWidgetProp);
});
}
};
scaleWidget(dsl);
return dsl;
};
export const checkIfMigrationIsNeeded = (
fetchPageResponse?: FetchPageResponse,
) => {
const currentDSL = fetchPageResponse?.data.layouts[0].dsl || defaultDSL;
return currentDSL.version !== LATEST_PAGE_VERSION;
};
export const extractCurrentDSL = (
fetchPageResponse?: FetchPageResponse,
): ContainerWidgetProps<WidgetProps> => {
const currentDSL = fetchPageResponse?.data.layouts[0].dsl || defaultDSL;
return transformDSL(currentDSL);
};
2019-09-25 21:21:04 +00:00
export const getDropZoneOffsets = (
colWidth: number,
rowHeight: number,
dragOffset: XYCord,
parentOffset: XYCord,
2019-09-25 21:21:04 +00:00
) => {
// Calculate actual drop position by snapping based on x, y and grid cell size
return snapToGrid(
colWidth,
rowHeight,
dragOffset.x - parentOffset.x,
dragOffset.y - parentOffset.y,
2019-09-25 21:21:04 +00:00
);
};
export const areIntersecting = (r1: Rect, r2: Rect) => {
2019-09-25 21:21:04 +00:00
return !(
r2.left >= r1.right ||
r2.right <= r1.left ||
r2.top >= r1.bottom ||
r2.bottom <= r1.top
2019-09-25 21:21:04 +00:00
);
};
export const isDropZoneOccupied = (
offset: Rect,
2019-10-08 06:19:10 +00:00
widgetId: string,
occupied?: OccupiedSpace[],
2019-09-25 21:21:04 +00:00
) => {
if (occupied) {
2020-12-24 04:32:25 +00:00
occupied = occupied.filter((widgetDetails) => {
2019-10-02 21:14:58 +00:00
return (
2019-10-08 06:19:10 +00:00
widgetDetails.id !== widgetId && widgetDetails.parentId !== widgetId
2019-10-02 21:14:58 +00:00
);
2019-09-25 21:21:04 +00:00
});
for (let i = 0; i < occupied.length; i++) {
if (areIntersecting(occupied[i], offset)) {
return true;
}
}
return false;
}
return false;
};
2019-10-08 06:19:10 +00:00
export const isWidgetOverflowingParentBounds = (
parentRowCols: { rows?: number; cols?: number },
offset: Rect,
2020-01-16 11:46:21 +00:00
): boolean => {
2020-03-06 09:45:21 +00:00
return (
2020-01-16 11:46:21 +00:00
offset.right < 0 ||
offset.top < 0 ||
2019-10-08 06:19:10 +00:00
(parentRowCols.cols || GridDefaults.DEFAULT_GRID_COLUMNS) < offset.right ||
2020-03-06 09:45:21 +00:00
(parentRowCols.rows || 0) < offset.bottom
);
2019-10-08 06:19:10 +00:00
};
2019-09-25 21:21:04 +00:00
export const noCollision = (
clientOffset: XYCord,
2019-09-25 21:21:04 +00:00
colWidth: number,
rowHeight: number,
dropTargetOffset: XYCord,
widgetWidth: number,
widgetHeight: number,
widgetId: string,
occupiedSpaces?: OccupiedSpace[],
2019-10-08 06:19:10 +00:00
rows?: number,
cols?: number,
detachFromLayout = false,
2019-09-25 21:21:04 +00:00
): boolean => {
if (detachFromLayout) {
return true;
}
if (clientOffset && dropTargetOffset) {
2019-09-25 21:21:04 +00:00
const [left, top] = getDropZoneOffsets(
colWidth,
rowHeight,
clientOffset as XYCord,
2019-09-25 21:21:04 +00:00
dropTargetOffset,
);
2020-01-16 11:46:21 +00:00
if (left < 0 || top < 0) {
return false;
}
2019-09-25 21:21:04 +00:00
const currentOffset = {
left,
right: left + widgetWidth,
top,
bottom: top + widgetHeight,
};
2019-10-08 06:19:10 +00:00
return (
!isDropZoneOccupied(currentOffset, widgetId, occupiedSpaces) &&
2019-10-08 06:19:10 +00:00
!isWidgetOverflowingParentBounds({ rows, cols }, currentOffset)
);
2019-09-25 21:21:04 +00:00
}
return false;
};
2020-01-16 11:46:21 +00:00
export const currentDropRow = (
dropTargetRowSpace: number,
dropTargetVerticalOffset: number,
draggableItemVerticalOffset: number,
widget: WidgetProps & Partial<WidgetConfigProps>,
) => {
const widgetHeight = widget.rows
? widget.rows
: widget.bottomRow - widget.topRow;
const top = Math.round(
(draggableItemVerticalOffset - dropTargetVerticalOffset) /
dropTargetRowSpace,
);
const currentBottomOffset = top + widgetHeight;
return currentBottomOffset;
};
export const widgetOperationParams = (
widget: WidgetProps & Partial<WidgetConfigProps>,
widgetOffset: XYCord,
parentOffset: XYCord,
parentColumnSpace: number,
parentRowSpace: number,
parentWidgetId: string, // parentWidget
): WidgetOperationParams => {
const [leftColumn, topRow] = getDropZoneOffsets(
parentColumnSpace,
parentRowSpace,
widgetOffset,
parentOffset,
);
// If this is an existing widget, we'll have the widgetId
// Therefore, this is a move operation on drop of the widget
if (widget.widgetName) {
return {
operation: WidgetOperations.MOVE,
widgetId: widget.widgetId,
payload: {
leftColumn,
topRow,
parentId: widget.parentId,
newParentId: parentWidgetId,
},
};
// If this is not an existing widget, we'll not have the widgetId
// Therefore, this is an operation to add child to this container
}
const widgetDimensions = {
columns: widget.columns,
rows: widget.rows,
};
[Feature] Grid Widget (#2389) * Updated test * updated assertions * Resizing image to take full width of table cell * updated assertion * Stop updating dynamicBindingPathList directly from widget * Fix selectedRow and selectedRows computations * Fix primaryColumns computations * Updated test for derived column * Added tests for computed value * Added check clear data * Reordering of test * updated common method * Made image size as 100% of table cell size * add templating logic * Updated flow and dsl * Clear old primary columns * Updated testname * updated assertion * use evaluated values for children * Fix primary columns update on component mount and component update * add isArray check * remove property pane enhancement reducer * add property pane enhancement reducer * disable items other than template + fix running property enchancment on drop of list widget * disbled drag, resize, settingsControl, drag for items other than template * add grid options * uncomment the widget operation for add child for grid children * handle delete scenario for child widget in list widget * WIP: Use the new delete and update property features * add listdsl.json for testcases * add test cases for correct no. of items being rendered * add test cases currentItem binding in list widget * change dragEnabled to dragDisabled * change resizeEnabled to resizeDisabled * change settingsControlEnabled to settingsControlDisabled * change dropEnabled to dropDisabled * update settingsControlDisabled default value * Use deleteProperties in propertyControls * Fix unsetting of array indices when deleting widget properties * remove old TableWidget.tsx file * Fix derived column property update on primary column property update * Handle undefined primary columns * Fix filepicker immutable prop issue * Fix object.freeze issue when adding ids to the property pane configuration * fix widget issue in grid * Fix column actions dynamicBindingPathList inclusion issue * remove consoles + fix typo around batch update * Remove redundant tests * js binding test for date picker * hydate enhancement map on copy list widget * check for dynamicleaf * fixes * improve check * fix getNextWidgetName * update template in list widget when copying * updating template copy logic when copying widget * update dynamicBindingPathList in copied widget * Add path parameter to hidden functions in property pane configs * fix copy bug when copying list widget * add computed list property control * Remove time column type Fix editor prompt for currentRow Fix undefined derivedColumns scenario Remove validations for primaryColums and derivedColumns Fix section toggle for video, image and button column types * Fix table widget actions and custom column migrations * Add logs for cyclical dependency map :recycle: * Process array differences * add property control for list widget * Fix onClick migrations * Property pane config parity * binding and trigger paths from the property pane config (#2920) * try react virtualized library * Fix unit test * Fix unit test :white_check_mark: * Fix minor issues in table widget * Add default meta props to binding paths to ensure eval and validation * Dummy commit :tada: * Remove unnecessary datepicker test Fix chart data as string issue * Achieve table column sorting and resizing parity with release * handle scenario where last column isn't available to access * Fix for panel config path not existing in the widget * Fix bindings in currentRow (default) Add dummy property pane config for canvas widget * Update canvas widgets with dynamicPathLists on delete of property paths * Add all diffs to change paths and trim later * Add back default properties 🚶🏻‍♂️ * Use object based paths instead of arrays for primaryColumns and derivedColumns * Fix issue in reordered columns * Fix inccorect update order * add virtualized list * Fix failing property pane tests * minor change * minor list widget change * Remove .vscode from git * Rename ads to alloy Fix isVisible in list widget * move grid component to widget folder * fix import in widget registry * add sticky row in virtualized list * add sticky container * Fix Height of grid widget items container * fix dragging of items in children other than template children * update list widget * update list widget * Fix padding in list widget * hide scrollbar in list widget list * fix copy bug in list widget * regenrate enhancement map on undo delete widget * Use enhancementmap for autocomplete in list widget Basic styles for list widget scrollbar * add custom control in widget config * minor commit * update scrollbar styles * remove unused variable * fix typo in custom control * comment out test cases * remove unused imports * remove unused imports * add JSON stringify in interweave * add noPad styling in dragLayer for noPad prop * implement grid gap * add list item background color prop * add white color in color picker control * fix gap in last list item * remove onBeforeParse in textcomponent * remove virtualization in grid widget * allow overflow-y * add onListItemClick action * add beta label * add pagination * fix actions in pagination in list widget * add list widget icon * add list background color default value * remove extra div * fix pagination issue * fix list widget crashing on perpage change * extract child operation function to widgetblueprint saga * refactor enhancements * add enhancement hook * refactor propertyUpdate hook enhancment * remove enhacement map * revert renaming ads to alloy * add autopagination * Cleanup unused vars Re-write loop using map Fix binding with external input widget * update default background color * remove unnessary scrol + fix pagination per page * remove console.log * use grid gap in pixel instead of snap * fix list widget tests for binding * add tests for on click action and pagination * remove unnecessary imports * remove overflow hidden in list component * Add feature to enable template actions * update property pane help text for list widget * disable pagination in editor view * update property pane options * add test case for action * uncomment tests * fix grid gap validation * update test cases * fix property pane opening issue for list tempalte * Disable form widgets in list widget * fix template issue for actions * add validation tests for list data * update starting template * add selectedRow + enable pagination in edit mode * remove extra padding in list widget + popper fix on settingDisabled * add stop propagation for button click * fix click event in edit mode * disallow filepicker widget for list widget * add test for list widget entity definition for selectItem * remove unused imports * fix test * remove evaluated value for list child widgets * add comment * remove log * fix copying bug in list widget * add check for not allowing template to copy * fix test * add test for property pane actions * remove unused import * add draglayercomponent test * add test for draggable component * add test for evaluatedvalue popup * add test for messages.ts * add test for widgeticons * add test for property pane selector * add test for widget config response * start testing widget configresponse * add test for enhancements in widget config * add test for codeeditor * add test for base widget + list widget * add test for executeWidgetBlueprintChildOperations * remove unused import * add test for widget operation utils * remove unused import * add test for handleSpecificCasesWhilePasting * remove unused function * remove unused import * add empty list styling * resolve all review comments * fix message test * add test for widget operation utils * fix merge conflicts * move validations in property config Co-authored-by: Abhinav Jha <abhinav@appsmith.com> Co-authored-by: nandan.anantharamu <nandan.anantharamu@thoughtspot.com> Co-authored-by: vicky-primathon.in <vicky.bansal@primathon.in> Co-authored-by: Pawan Kumar <pawankumar@Pawans-MacBook-Pro.local> Co-authored-by: Piyush <piyush@codeitout.com> Co-authored-by: hetunandu <hetu@appsmith.com> Co-authored-by: Hetu Nandu <hetunandu@gmail.com> Co-authored-by: root <root@DESKTOP-9GENCK0.localdomain>
2021-04-23 05:43:13 +00:00
return {
operation: WidgetOperations.ADD_CHILD,
widgetId: parentWidgetId,
payload: {
type: widget.type,
leftColumn,
topRow,
...widgetDimensions,
parentRowSpace,
parentColumnSpace,
newWidgetId: widget.widgetId,
},
};
};
export const updateWidgetPosition = (
widget: WidgetProps,
leftColumn: number,
topRow: number,
) => {
const newPositions = {
leftColumn,
topRow,
rightColumn: leftColumn + (widget.rightColumn - widget.leftColumn),
bottomRow: topRow + (widget.bottomRow - widget.topRow),
};
return {
2020-01-16 11:46:21 +00:00
...newPositions,
};
};
export const getCanvasSnapRows = (
bottomRow: number,
canExtend: boolean,
): number => {
const totalRows = Math.floor(
bottomRow / GridDefaults.DEFAULT_GRID_ROW_HEIGHT,
);
// Canvas Widgets do not need to accomodate for widget and container padding.
// Only when they're extensible
if (canExtend) {
return totalRows;
}
// When Canvas widgets are not extensible
return totalRows - 1;
};
export const getSnapColumns = (): number => {
return GridDefaults.DEFAULT_GRID_COLUMNS;
};
export const generateWidgetProps = (
parent: FlattenedWidgetProps,
type: WidgetType,
leftColumn: number,
topRow: number,
parentRowSpace: number,
parentColumnSpace: number,
widgetName: string,
widgetConfig: {
widgetId: string;
renderMode: RenderMode;
} & Partial<WidgetProps>,
version: number,
): ContainerWidgetProps<WidgetProps> => {
if (parent) {
const sizes = {
leftColumn,
rightColumn: leftColumn + widgetConfig.columns,
topRow,
bottomRow: topRow + widgetConfig.rows,
};
const others = {};
2020-04-17 16:15:09 +00:00
const props: ContainerWidgetProps<WidgetProps> = {
isVisible: WidgetTypes.MODAL_WIDGET === type ? undefined : true,
...widgetConfig,
type,
2020-01-17 09:28:26 +00:00
widgetName,
2019-11-20 08:10:01 +00:00
isLoading: false,
parentColumnSpace,
parentRowSpace,
...sizes,
...others,
parentId: parent.widgetId,
version,
};
delete props.rows;
delete props.columns;
return props;
} else {
2020-01-16 11:46:21 +00:00
if (parent) {
throw Error("Failed to create widget: Parent's size cannot be calculate");
2020-01-16 11:46:21 +00:00
} else throw Error("Failed to create widget: Parent was not provided ");
}
};
/**
* adds logBlackList key for all list widget children
*
* @param currentDSL
* @returns
*/
const addLogBlackListToAllListWidgetChildren = (
currentDSL: ContainerWidgetProps<WidgetProps>,
) => {
currentDSL.children = currentDSL.children?.map((children: WidgetProps) => {
if (children.type === WidgetTypes.LIST_WIDGET) {
const widgets = get(
children,
"children.0.children.0.children.0.children",
);
widgets.map((widget: any, index: number) => {
const logBlackList: { [key: string]: boolean } = {};
Object.keys(widget).map((key) => {
logBlackList[key] = true;
});
if (!widget.logBlackList) {
set(
children,
`children.0.children.0.children.0.children.${index}.logBlackList`,
logBlackList,
);
}
});
}
return children;
});
return currentDSL;
};
List Widget Phase 2 (#4189) * update meta properties + default properties map * update widget registery * update get meta property * update metahoc + widgetfactory + data tree evaluator * try sending function as string to worker * revert data tree evaluator update * pass default props map from dataTreeWidget file * wip * save child meta properties * remove console.log * save meta and default map in list * update listwidget * remove console.log + unused variables * revert getMetaPropertiesMap function * fix data tree test * fix list widget test * fix entity definition test * fix overriting of item in updatedItems * remove todo comments * fix meta prop issue * revert making meta properties from undefiend to "" & fix filepicker bug * fix test case * change items to listData and updatedItems to items * remove console.log * fix test * extract derived properties to dervied.js * disabled top, left, right resize handler list widget container * add test for dervied js * add test for selectedItem * fix background color bug on hover * remove console.log * fix chart widget inside list widget * fix checkbox issue + points raised by yogesh * revert the createImmerReducer usage * fix parse derived properties * remove internal props object that fails the test * fix import typo * allow bottom resize handler * fix template height check * fix template height check * update template size check * fix the is visible invalid prop issue * fix migration of list widget phase 2 * fix migration * remove unused import * fix migration * fix migration * remove console.log * hide delete option for container in entity explorer * fix testcases * remove unused import * fix switch widget meta prop Co-authored-by: root <root@DESKTOP-9GENCK0.localdomain> Co-authored-by: Pawan Kumar <pawankumar@Pawans-MacBook-Pro.local>
2021-06-18 07:42:57 +00:00
/**
* changes items -> listData
*
* @param currentDSL
* @returns
*/
const migrateItemsToListDataInListWidget = (
currentDSL: ContainerWidgetProps<WidgetProps>,
) => {
if (currentDSL.type === WidgetTypes.LIST_WIDGET) {
currentDSL = renameKeyInObject(currentDSL, "items", "listData");
currentDSL.dynamicBindingPathList = currentDSL.dynamicBindingPathList?.map(
(path: { key: string }) => {
if (path.key === "items") {
return { key: "listData" };
}
return path;
},
);
currentDSL.dynamicBindingPathList?.map((path: { key: string }) => {
if (
get(currentDSL, path.key) &&
path.key !== "items" &&
path.key !== "listData" &&
isString(get(currentDSL, path.key))
) {
set(
currentDSL,
path.key,
get(currentDSL, path.key, "").replace("items", "listData"),
);
}
});
Object.keys(currentDSL.template).map((widgetName) => {
const currentWidget = currentDSL.template[widgetName];
currentWidget.dynamicBindingPathList?.map((path: { key: string }) => {
set(
currentWidget,
path.key,
get(currentWidget, path.key).replace("items", "listData"),
);
});
});
}
if (currentDSL.children && currentDSL.children.length > 0) {
currentDSL.children = currentDSL.children.map(
migrateItemsToListDataInListWidget,
);
}
return currentDSL;
};