2021-04-23 05:43:13 +00:00
|
|
|
import {
|
|
|
|
|
MAIN_CONTAINER_WIDGET_ID,
|
|
|
|
|
WidgetTypes,
|
|
|
|
|
} from "constants/WidgetConstants";
|
2021-06-05 16:39:30 +00:00
|
|
|
import { cloneDeep, get, isString, filter, set } from "lodash";
|
2021-04-23 05:43:13 +00:00
|
|
|
import { FlattenedWidgetProps } from "reducers/entityReducers/canvasWidgetsReducer";
|
2021-06-17 13:26:54 +00:00
|
|
|
import { call, select } from "redux-saga/effects";
|
2021-04-23 05:43:13 +00:00
|
|
|
import { getDynamicBindings } from "utils/DynamicBindingUtils";
|
2021-06-17 13:26:54 +00:00
|
|
|
import { getWidget } from "./selectors";
|
2021-04-23 05:43:13 +00:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* checks if triggerpaths contains property path passed
|
|
|
|
|
*
|
|
|
|
|
* @param isTriggerProperty
|
|
|
|
|
* @param propertyPath
|
|
|
|
|
* @param triggerPaths
|
|
|
|
|
* @returns
|
|
|
|
|
*/
|
|
|
|
|
export const doesTriggerPathsContainPropertyPath = (
|
|
|
|
|
isTriggerProperty: boolean,
|
|
|
|
|
propertyPath: string,
|
|
|
|
|
triggerPaths?: string[],
|
|
|
|
|
) => {
|
|
|
|
|
if (!isTriggerProperty) {
|
|
|
|
|
if (
|
|
|
|
|
triggerPaths &&
|
|
|
|
|
triggerPaths.length &&
|
|
|
|
|
triggerPaths.includes(propertyPath)
|
|
|
|
|
) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return isTriggerProperty;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
*
|
|
|
|
|
* check if copied widget is being pasted in list widget,
|
|
|
|
|
* if yes, change all keys in template of list widget and
|
|
|
|
|
* update dynamicBindingPathList of ListWidget
|
|
|
|
|
*
|
|
|
|
|
* updates in list widget :
|
|
|
|
|
* 1. `dynamicBindingPathList`
|
|
|
|
|
* 2. `template`
|
|
|
|
|
*
|
|
|
|
|
* @param widget
|
|
|
|
|
* @param widgets
|
|
|
|
|
*/
|
|
|
|
|
export const handleIfParentIsListWidgetWhilePasting = (
|
|
|
|
|
widget: FlattenedWidgetProps,
|
|
|
|
|
widgets: { [widgetId: string]: FlattenedWidgetProps },
|
|
|
|
|
): { [widgetId: string]: FlattenedWidgetProps } => {
|
|
|
|
|
let root = get(widgets, `${widget.parentId}`);
|
|
|
|
|
|
2021-04-23 09:15:19 +00:00
|
|
|
while (root && root.parentId && root.widgetId !== MAIN_CONTAINER_WIDGET_ID) {
|
2021-04-23 05:43:13 +00:00
|
|
|
if (root.type === WidgetTypes.LIST_WIDGET) {
|
|
|
|
|
const listWidget = root;
|
|
|
|
|
const currentWidget = cloneDeep(widget);
|
|
|
|
|
let template = get(listWidget, "template", {});
|
|
|
|
|
const dynamicBindingPathList: any[] = get(
|
|
|
|
|
listWidget,
|
|
|
|
|
"dynamicBindingPathList",
|
|
|
|
|
[],
|
|
|
|
|
).slice();
|
|
|
|
|
|
|
|
|
|
// iterating over each keys of the new createdWidget checking if value contains currentItem
|
|
|
|
|
const keys = Object.keys(currentWidget);
|
|
|
|
|
|
|
|
|
|
for (let i = 0; i < keys.length; i++) {
|
|
|
|
|
const key = keys[i];
|
|
|
|
|
let value = currentWidget[key];
|
|
|
|
|
|
|
|
|
|
if (isString(value) && value.indexOf("currentItem") > -1) {
|
|
|
|
|
const { jsSnippets } = getDynamicBindings(value);
|
|
|
|
|
|
|
|
|
|
const modifiedAction = jsSnippets.reduce(
|
|
|
|
|
(prev: string, next: string) => {
|
|
|
|
|
return prev + `${next}`;
|
|
|
|
|
},
|
|
|
|
|
"",
|
|
|
|
|
);
|
|
|
|
|
|
2021-06-18 07:42:57 +00:00
|
|
|
value = `{{${listWidget.widgetName}.listData.map((currentItem) => ${modifiedAction})}}`;
|
2021-04-23 05:43:13 +00:00
|
|
|
|
|
|
|
|
currentWidget[key] = value;
|
|
|
|
|
|
|
|
|
|
dynamicBindingPathList.push({
|
|
|
|
|
key: `template.${currentWidget.widgetName}.${key}`,
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template = {
|
|
|
|
|
...template,
|
|
|
|
|
[currentWidget.widgetName]: currentWidget,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// now we have updated `dynamicBindingPathList` and updatedTemplate
|
|
|
|
|
// we need to update it the list widget
|
|
|
|
|
widgets[listWidget.widgetId] = {
|
|
|
|
|
...listWidget,
|
|
|
|
|
template,
|
|
|
|
|
dynamicBindingPathList,
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
root = widgets[root.parentId];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return widgets;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* this saga handles special cases when pasting the widget
|
|
|
|
|
*
|
|
|
|
|
* for e.g - when the list widget is being copied, we want to update template of list widget
|
|
|
|
|
* with new widgets name
|
|
|
|
|
*
|
|
|
|
|
* @param widget
|
|
|
|
|
* @param widgets
|
|
|
|
|
* @param widgetNameMap
|
|
|
|
|
* @param newWidgetList
|
|
|
|
|
* @returns
|
|
|
|
|
*/
|
|
|
|
|
export const handleSpecificCasesWhilePasting = (
|
|
|
|
|
widget: FlattenedWidgetProps,
|
|
|
|
|
widgets: { [widgetId: string]: FlattenedWidgetProps },
|
|
|
|
|
widgetNameMap: Record<string, string>,
|
|
|
|
|
newWidgetList: FlattenedWidgetProps[],
|
|
|
|
|
) => {
|
|
|
|
|
// this is the case when whole list widget is copied and pasted
|
|
|
|
|
if (widget.type === WidgetTypes.LIST_WIDGET) {
|
|
|
|
|
Object.keys(widget.template).map((widgetName) => {
|
|
|
|
|
const oldWidgetName = widgetName;
|
|
|
|
|
const newWidgetName = widgetNameMap[oldWidgetName];
|
|
|
|
|
|
|
|
|
|
const newWidget = newWidgetList.find(
|
|
|
|
|
(w: any) => w.widgetName === newWidgetName,
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
if (newWidget) {
|
|
|
|
|
newWidget.widgetName = newWidgetName;
|
|
|
|
|
|
|
|
|
|
if (widgetName === oldWidgetName) {
|
|
|
|
|
widget.template[newWidgetName] = {
|
|
|
|
|
...widget.template[oldWidgetName],
|
|
|
|
|
widgetId: newWidget.widgetId,
|
|
|
|
|
widgetName: newWidget.widgetName,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
delete widget.template[oldWidgetName];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// updating dynamicBindingPath in copied widget if the copied widge thas reference to oldWidgetNames
|
|
|
|
|
widget.dynamicBindingPathList = (widget.dynamicBindingPathList || []).map(
|
|
|
|
|
(path: any) => {
|
|
|
|
|
if (path.key.startsWith(`template.${oldWidgetName}`)) {
|
|
|
|
|
return {
|
|
|
|
|
key: path.key.replace(
|
|
|
|
|
`template.${oldWidgetName}`,
|
|
|
|
|
`template.${newWidgetName}`,
|
|
|
|
|
),
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return path;
|
|
|
|
|
},
|
|
|
|
|
);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
widgets[widget.widgetId] = widget;
|
2021-06-05 16:39:30 +00:00
|
|
|
} else if (widget.type === WidgetTypes.MODAL_WIDGET) {
|
|
|
|
|
// if Modal is being coppied handle all onClose action rename
|
|
|
|
|
const oldWidgetName = Object.keys(widgetNameMap).find(
|
|
|
|
|
(key) => widgetNameMap[key] === widget.widgetName,
|
|
|
|
|
);
|
|
|
|
|
// get all the button, icon widgets
|
|
|
|
|
const copiedBtnIcnWidgets = filter(
|
|
|
|
|
newWidgetList,
|
|
|
|
|
(copyWidget) =>
|
|
|
|
|
copyWidget.type === "BUTTON_WIDGET" ||
|
|
|
|
|
copyWidget.type === "ICON_WIDGET",
|
|
|
|
|
);
|
|
|
|
|
// replace oldName with new one if any of this widget have onClick action for old modal
|
|
|
|
|
copiedBtnIcnWidgets.map((copyWidget) => {
|
|
|
|
|
if (copyWidget.onClick) {
|
|
|
|
|
const newOnClick = widgets[copyWidget.widgetId].onClick.replace(
|
|
|
|
|
oldWidgetName,
|
|
|
|
|
widget.widgetName,
|
|
|
|
|
);
|
|
|
|
|
set(widgets[copyWidget.widgetId], "onClick", newOnClick);
|
|
|
|
|
}
|
|
|
|
|
});
|
2021-04-23 05:43:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
widgets = handleIfParentIsListWidgetWhilePasting(widget, widgets);
|
|
|
|
|
|
|
|
|
|
return widgets;
|
|
|
|
|
};
|
2021-06-17 13:26:54 +00:00
|
|
|
|
|
|
|
|
export function* getWidgetChildren(widgetId: string): any {
|
|
|
|
|
const childrenIds: string[] = [];
|
|
|
|
|
const widget = yield select(getWidget, widgetId);
|
|
|
|
|
// When a form widget tries to resetChildrenMetaProperties
|
|
|
|
|
// But one or more of its container like children
|
|
|
|
|
// have just been deleted, widget can be undefined
|
|
|
|
|
if (widget === undefined) {
|
|
|
|
|
return [];
|
|
|
|
|
}
|
|
|
|
|
const { children = [] } = widget;
|
|
|
|
|
if (children && children.length) {
|
|
|
|
|
for (const childIndex in children) {
|
|
|
|
|
if (children.hasOwnProperty(childIndex)) {
|
|
|
|
|
const child = children[childIndex];
|
|
|
|
|
childrenIds.push(child);
|
|
|
|
|
const grandChildren = yield call(getWidgetChildren, child);
|
|
|
|
|
if (grandChildren.length) {
|
|
|
|
|
childrenIds.push(...grandChildren);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return childrenIds;
|
|
|
|
|
}
|