PromucFlow_constructor/app/client/src/mockResponses/WidgetConfigResponse.tsx
Pawan Kumar 1717b0e392
[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 ♻️

* 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 

* Fix minor issues in table widget

* Add default meta props to binding paths to ensure eval and validation

* Dummy commit 🎉

* 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 11:13:13 +05:30

824 lines
25 KiB
TypeScript

import { WidgetConfigReducerState } from "reducers/entityReducers/widgetConfigReducer";
import { WidgetProps } from "widgets/BaseWidget";
import moment from "moment-timezone";
import { cloneDeep, get, indexOf, isString } from "lodash";
import { generateReactKey } from "utils/generators";
import { WidgetTypes } from "constants/WidgetConstants";
import { BlueprintOperationTypes } from "sagas/WidgetBlueprintSagasEnums";
import { FlattenedWidgetProps } from "reducers/entityReducers/canvasWidgetsReducer";
import { getDynamicBindings } from "utils/DynamicBindingUtils";
import { Colors } from "constants/Colors";
import FileDataTypes from "widgets/FileDataTypes";
/**
* this config sets the default values of properties being used in the widget
*/
const WidgetConfigResponse: WidgetConfigReducerState = {
config: {
BUTTON_WIDGET: {
text: "Submit",
buttonStyle: "PRIMARY_BUTTON",
rows: 1,
columns: 2,
widgetName: "Button",
isDisabled: false,
isVisible: true,
isDefaultClickDisabled: true,
version: 1,
},
TEXT_WIDGET: {
text: "Label",
fontSize: "PARAGRAPH",
fontStyle: "BOLD",
textAlign: "LEFT",
textColor: Colors.THUNDER,
rows: 1,
columns: 4,
widgetName: "Text",
version: 1,
},
RICH_TEXT_EDITOR_WIDGET: {
defaultText: "This is the initial <b>content</b> of the editor",
rows: 5,
columns: 8,
isDisabled: false,
isVisible: true,
widgetName: "RichTextEditor",
isDefaultClickDisabled: true,
inputType: "html",
version: 1,
},
IMAGE_WIDGET: {
defaultImage:
"https://res.cloudinary.com/drako999/image/upload/v1589196259/default.png",
imageShape: "RECTANGLE",
maxZoomLevel: 1,
image: "",
rows: 3,
columns: 4,
widgetName: "Image",
version: 1,
},
INPUT_WIDGET: {
inputType: "TEXT",
rows: 1,
label: "",
columns: 5,
widgetName: "Input",
version: 1,
resetOnSubmit: true,
},
SWITCH_WIDGET: {
label: "Label",
rows: 1,
columns: 2,
defaultSwitchState: true,
widgetName: "Switch",
alignWidget: "LEFT",
version: 1,
},
ICON_WIDGET: {
widgetName: "Icon",
rows: 1,
columns: 1,
version: 1,
},
CONTAINER_WIDGET: {
backgroundColor: "#FFFFFF",
rows: 10,
columns: 8,
widgetName: "Container",
containerStyle: "card",
children: [],
blueprint: {
view: [
{
type: "CANVAS_WIDGET",
position: { top: 0, left: 0 },
props: {
containerStyle: "none",
canExtend: false,
detachFromLayout: true,
children: [],
},
},
],
},
version: 1,
},
DATE_PICKER_WIDGET: {
isDisabled: false,
datePickerType: "DATE_PICKER",
rows: 1,
label: "",
dateFormat: "DD/MM/YYYY HH:mm",
columns: 5,
widgetName: "DatePicker",
defaultDate: moment().format("DD/MM/YYYY HH:mm"),
version: 1,
},
DATE_PICKER_WIDGET2: {
isDisabled: false,
datePickerType: "DATE_PICKER",
rows: 1,
label: "",
dateFormat: "DD/MM/YYYY HH:mm",
columns: 5,
widgetName: "DatePicker",
defaultDate: moment().toISOString(),
version: 2,
},
VIDEO_WIDGET: {
rows: 7,
columns: 7,
widgetName: "Video",
url: "https://www.youtube.com/watch?v=mzqK0QIZRLs",
autoPlay: false,
version: 1,
},
TABLE_WIDGET: {
rows: 7,
columns: 8,
label: "Data",
widgetName: "Table",
searchKey: "",
textSize: "PARAGRAPH",
horizontalAlignment: "LEFT",
verticalAlignment: "CENTER",
primaryColumns: {},
derivedColumns: {},
tableData: [
{
id: 2381224,
email: "michael.lawson@reqres.in",
userName: "Michael Lawson",
productName: "Chicken Sandwich",
orderAmount: 4.99,
},
{
id: 2736212,
email: "lindsay.ferguson@reqres.in",
userName: "Lindsay Ferguson",
productName: "Tuna Salad",
orderAmount: 9.99,
},
{
id: 6788734,
email: "tobias.funke@reqres.in",
userName: "Tobias Funke",
productName: "Beef steak",
orderAmount: 19.99,
},
],
version: 1,
},
DROP_DOWN_WIDGET: {
rows: 1,
columns: 5,
label: "",
selectionType: "SINGLE_SELECT",
options: [
{ label: "Vegetarian", value: "VEG" },
{ label: "Non-Vegetarian", value: "NON_VEG" },
{ label: "Vegan", value: "VEGAN" },
],
widgetName: "Dropdown",
defaultOptionValue: "VEG",
version: 1,
},
CHECKBOX_WIDGET: {
rows: 1,
columns: 3,
label: "Label",
defaultCheckedState: true,
widgetName: "Checkbox",
version: 1,
alignWidget: "LEFT",
},
RADIO_GROUP_WIDGET: {
rows: 2,
columns: 3,
label: "",
options: [
{ label: "Male", value: "M" },
{ label: "Female", value: "F" },
],
defaultOptionValue: "M",
widgetName: "RadioGroup",
version: 1,
},
FILE_PICKER_WIDGET: {
rows: 1,
files: [],
label: "Select Files",
columns: 4,
maxNumFiles: 1,
maxFileSize: 5,
fileDataType: FileDataTypes.Base64,
widgetName: "FilePicker",
isDefaultClickDisabled: true,
version: 1,
},
TABS_WIDGET: {
rows: 7,
columns: 8,
shouldScrollContents: false,
widgetName: "Tabs",
tabs: [
{ label: "Tab 1", id: "tab1", widgetId: "", isVisible: true },
{ label: "Tab 2", id: "tab2", widgetId: "", isVisible: true },
],
shouldShowTabs: true,
defaultTab: "Tab 1",
blueprint: {
operations: [
{
type: BlueprintOperationTypes.MODIFY_PROPS,
fn: (widget: WidgetProps & { children?: WidgetProps[] }) => {
const tabs = [...widget.tabs];
const newTabs = tabs.map((tab: any) => {
const newTab = { ...tab };
newTab.widgetId = generateReactKey();
return newTab;
});
const updatePropertyMap = [
{
widgetId: widget.widgetId,
propertyName: "tabs",
propertyValue: newTabs,
},
];
return updatePropertyMap;
},
},
],
},
version: 1,
},
MODAL_WIDGET: {
rows: 6,
columns: 6,
size: "MODAL_SMALL",
canEscapeKeyClose: true,
// detachFromLayout is set true for widgets that are not bound to the widgets within the layout.
// setting it to true will only render the widgets(from sidebar) on the main container without any collision check.
detachFromLayout: true,
canOutsideClickClose: true,
shouldScrollContents: true,
widgetName: "Modal",
children: [],
version: 1,
blueprint: {
view: [
{
type: "CANVAS_WIDGET",
position: { left: 0, top: 0 },
props: {
detachFromLayout: true,
canExtend: true,
isVisible: true,
isDisabled: false,
shouldScrollContents: false,
children: [],
version: 1,
blueprint: {
view: [
{
type: "ICON_WIDGET",
position: { left: 14, top: 0 },
size: { rows: 1, cols: 2 },
props: {
iconName: "cross",
iconSize: 24,
color: "#040627",
version: 1,
},
},
{
type: "TEXT_WIDGET",
position: { left: 0, top: 0 },
size: { rows: 1, cols: 10 },
props: {
text: "Modal Title",
textStyle: "HEADING",
version: 1,
},
},
{
type: "BUTTON_WIDGET",
position: { left: 9, top: 4 },
size: { rows: 1, cols: 3 },
props: {
text: "Cancel",
buttonStyle: "SECONDARY_BUTTON",
version: 1,
},
},
{
type: "BUTTON_WIDGET",
position: { left: 12, top: 4 },
size: { rows: 1, cols: 4 },
props: {
text: "Confirm",
buttonStyle: "PRIMARY_BUTTON",
version: 1,
},
},
],
operations: [
{
type: BlueprintOperationTypes.MODIFY_PROPS,
fn: (
widget: WidgetProps & { children?: WidgetProps[] },
widgets: { [widgetId: string]: FlattenedWidgetProps },
parent?: WidgetProps & { children?: WidgetProps[] },
) => {
const iconChild =
widget.children &&
widget.children.find(
(child) => child.type === "ICON_WIDGET",
);
if (iconChild && parent) {
return [
{
widgetId: iconChild.widgetId,
propertyName: "onClick",
propertyValue: `{{closeModal('${parent.widgetName}')}}`,
},
];
}
},
},
],
},
},
},
],
},
},
CANVAS_WIDGET: {
rows: 0,
columns: 0,
widgetName: "Canvas",
version: 1,
},
CHART_WIDGET: {
rows: 8,
columns: 6,
widgetName: "Chart",
chartType: "LINE_CHART",
chartName: "Sales on working days",
allowHorizontalScroll: false,
version: 1,
chartData: [
{
seriesName: "Sales",
data: [
{
x: "Mon",
y: 10000,
},
{
x: "Tue",
y: 12000,
},
{
x: "Wed",
y: 32000,
},
{
x: "Thu",
y: 28000,
},
{
x: "Fri",
y: 14000,
},
{
x: "Sat",
y: 19000,
},
{
x: "Sun",
y: 36000,
},
],
},
],
xAxisName: "Last Week",
yAxisName: "Total Order Revenue $",
},
FORM_BUTTON_WIDGET: {
rows: 1,
columns: 3,
widgetName: "FormButton",
text: "Submit",
isDefaultClickDisabled: true,
version: 1,
},
FORM_WIDGET: {
rows: 13,
columns: 7,
widgetName: "Form",
backgroundColor: "white",
children: [],
blueprint: {
view: [
{
type: "CANVAS_WIDGET",
position: { top: 0, left: 0 },
props: {
containerStyle: "none",
canExtend: false,
detachFromLayout: true,
children: [],
version: 1,
blueprint: {
view: [
{
type: "TEXT_WIDGET",
size: { rows: 1, cols: 12 },
position: { top: 0, left: 0 },
props: {
text: "Form",
textStyle: "HEADING",
version: 1,
},
},
{
type: "FORM_BUTTON_WIDGET",
size: { rows: 1, cols: 4 },
position: { top: 11, left: 12 },
props: {
text: "Submit",
buttonStyle: "PRIMARY_BUTTON",
disabledWhenInvalid: true,
resetFormOnClick: true,
version: 1,
},
},
{
type: "FORM_BUTTON_WIDGET",
size: { rows: 1, cols: 4 },
position: { top: 11, left: 8 },
props: {
text: "Reset",
buttonStyle: "SECONDARY_BUTTON",
disabledWhenInvalid: false,
resetFormOnClick: true,
version: 1,
},
},
],
},
},
},
],
},
},
MAP_WIDGET: {
rows: 12,
columns: 8,
isDisabled: false,
isVisible: true,
widgetName: "Map",
enableSearch: true,
zoomLevel: 50,
enablePickLocation: true,
allowZoom: true,
mapCenter: { lat: -34.397, long: 150.644 },
defaultMarkers: [{ lat: -34.397, long: 150.644, title: "Test A" }],
version: 1,
},
SKELETON_WIDGET: {
isLoading: true,
rows: 1,
columns: 1,
widgetName: "Skeleton",
version: 1,
},
[WidgetTypes.LIST_WIDGET]: {
backgroundColor: "",
itemBackgroundColor: "white",
rows: 10,
columns: 8,
gridType: "vertical",
enhancements: {
child: {
autocomplete: (parentProps: any) => {
return parentProps.childAutoComplete;
},
hideEvaluatedValue: () => true,
propertyUpdateHook: (
parentProps: any,
widgetName: string,
propertyPath: string, // onClick
propertyValue: string,
isTriggerProperty: boolean,
) => {
let value = propertyValue;
if (!parentProps.widgetId) return [];
const { jsSnippets } = getDynamicBindings(propertyValue);
const modifiedAction = jsSnippets.reduce(
(prev: string, next: string) => {
return `${prev}${next}`;
},
"",
);
value = `{{${parentProps.widgetName}.items.map((currentItem) => ${modifiedAction})}}`;
const path = `template.${widgetName}.${propertyPath}`;
return [
{
widgetId: parentProps.widgetId,
propertyPath: path,
propertyValue: isTriggerProperty ? propertyValue : value,
isDynamicTrigger: isTriggerProperty,
},
];
},
},
},
gridGap: 0,
items: [
{
id: 1,
num: "001",
name: "Bulbasaur",
img: "http://www.serebii.net/pokemongo/pokemon/001.png",
},
{
id: 2,
num: "002",
name: "Ivysaur",
img: "http://www.serebii.net/pokemongo/pokemon/002.png",
},
{
id: 3,
num: "003",
name: "Venusaur",
img: "http://www.serebii.net/pokemongo/pokemon/003.png",
},
{
id: 4,
num: "004",
name: "Charmander",
img: "http://www.serebii.net/pokemongo/pokemon/004.png",
},
{
id: 5,
num: "005",
name: "Charmeleon",
img: "http://www.serebii.net/pokemongo/pokemon/005.png",
},
{
id: 6,
num: "006",
name: "Charizard",
img: "http://www.serebii.net/pokemongo/pokemon/006.png",
},
],
widgetName: "List",
children: [],
blueprint: {
view: [
{
type: "CANVAS_WIDGET",
position: { top: 0, left: 0 },
props: {
containerStyle: "none",
canExtend: false,
detachFromLayout: true,
dropDisabled: true,
noPad: true,
children: [],
blueprint: {
view: [
{
type: "CONTAINER_WIDGET",
size: { rows: 4, cols: 16 },
position: { top: 0, left: 0 },
props: {
backgroundColor: "white",
containerStyle: "card",
dragDisabled: true,
isDeletable: false,
disallowCopy: true,
disablePropertyPane: true,
children: [],
blueprint: {
view: [
{
type: "CANVAS_WIDGET",
position: { top: 0, left: 0 },
props: {
containerStyle: "none",
canExtend: false,
detachFromLayout: true,
children: [],
version: 1,
blueprint: {
view: [
{
type: "IMAGE_WIDGET",
size: { rows: 3, cols: 4 },
position: { top: 0, left: 0 },
props: {
defaultImage:
"https://res.cloudinary.com/drako999/image/upload/v1589196259/default.png",
imageShape: "RECTANGLE",
maxZoomLevel: 1,
image: "{{currentItem.img}}",
dynamicBindingPathList: [
{
key: "image",
},
],
dynamicTriggerPathList: [],
},
},
{
type: "TEXT_WIDGET",
size: { rows: 1, cols: 6 },
position: { top: 0, left: 4 },
props: {
text: "{{currentItem.name}}",
textStyle: "HEADING",
textAlign: "LEFT",
dynamicBindingPathList: [
{
key: "text",
},
],
dynamicTriggerPathList: [],
},
},
{
type: "TEXT_WIDGET",
size: { rows: 1, cols: 6 },
position: { top: 1, left: 4 },
props: {
text: "{{currentItem.num}}",
textStyle: "BODY",
textAlign: "LEFT",
dynamicBindingPathList: [
{
key: "text",
},
],
dynamicTriggerPathList: [],
},
},
],
},
},
},
],
},
},
},
],
},
},
},
],
operations: [
{
type: BlueprintOperationTypes.MODIFY_PROPS,
fn: (
widget: WidgetProps & { children?: WidgetProps[] },
widgets: { [widgetId: string]: FlattenedWidgetProps },
) => {
let template = {};
const container = get(
widgets,
`${get(widget, "children.0.children.0")}`,
);
const canvas = get(widgets, `${get(container, "children.0")}`);
let updatePropertyMap: any = [];
const dynamicBindingPathList: any[] = get(
widget,
"dynamicBindingPathList",
[],
);
canvas.children &&
get(canvas, "children", []).forEach((child: string) => {
const childWidget = cloneDeep(get(widgets, `${child}`));
const keys = Object.keys(childWidget);
for (let i = 0; i < keys.length; i++) {
const key = keys[i];
let value = childWidget[key];
if (isString(value) && value.indexOf("currentItem") > -1) {
const { jsSnippets } = getDynamicBindings(value);
const modifiedAction = jsSnippets.reduce(
(prev: string, next: string) => {
return prev + `${next}`;
},
"",
);
value = `{{${widget.widgetName}.items.map((currentItem) => ${modifiedAction})}}`;
childWidget[key] = value;
dynamicBindingPathList.push({
key: `template.${childWidget.widgetName}.${key}`,
});
}
}
template = {
...template,
[childWidget.widgetName]: childWidget,
};
});
updatePropertyMap = [
{
widgetId: widget.widgetId,
propertyName: "dynamicBindingPathList",
propertyValue: dynamicBindingPathList,
},
{
widgetId: widget.widgetId,
propertyName: "template",
propertyValue: template,
},
];
return updatePropertyMap;
},
},
{
type: BlueprintOperationTypes.CHILD_OPERATIONS,
fn: (
widgets: { [widgetId: string]: FlattenedWidgetProps },
widgetId: string,
parentId: string,
widgetPropertyMaps: {
defaultPropertyMap: Record<string, string>;
},
) => {
if (!parentId) return { widgets };
const widget = { ...widgets[widgetId] };
const parent = { ...widgets[parentId] };
const disallowedWidgets = [WidgetTypes.FILE_PICKER_WIDGET];
if (
Object.keys(widgetPropertyMaps.defaultPropertyMap).length > 0 ||
indexOf(disallowedWidgets, widget.type) > -1
) {
const widget = widgets[widgetId];
if (widget.children && widget.children.length > 0) {
widget.children.forEach((childId: string) => {
delete widgets[childId];
});
}
if (widget.parentId) {
const _parent = { ...widgets[widget.parentId] };
_parent.children = _parent.children?.filter(
(id) => id !== widgetId,
);
widgets[widget.parentId] = _parent;
}
delete widgets[widgetId];
return {
widgets,
message: `${
WidgetConfigResponse.config[widget.type].widgetName
} widgets cannot be used inside the list widget right now.`,
};
}
const template = {
...get(parent, "template", {}),
[widget.widgetName]: widget,
};
parent.template = template;
widgets[parentId] = parent;
return { widgets };
},
},
],
},
},
},
configVersion: 1,
};
export default WidgetConfigResponse;