diff --git a/app/client/src/actions/pageActions.tsx b/app/client/src/actions/pageActions.tsx index 29d9137f59..248edb4d5f 100644 --- a/app/client/src/actions/pageActions.tsx +++ b/app/client/src/actions/pageActions.tsx @@ -92,12 +92,13 @@ export type WidgetMove = { widgetId: string; leftColumn: number; topRow: number; + parentId: string; /* - If parentWidgetId is different from what we have in redux store, + If newParentId is different from what we have in redux store, then we have to delete this, as it has been dropped in another container somewhere. */ - parentWidgetId: string; + newParentId: string; }; export type WidgetRemoveChild = { @@ -107,6 +108,7 @@ export type WidgetRemoveChild = { export type WidgetDelete = { widgetId: string; + parentId: string; }; export type WidgetResize = { diff --git a/app/client/src/editorComponents/DraggableComponent.tsx b/app/client/src/editorComponents/DraggableComponent.tsx index f45d20d5b6..11892cfbfb 100644 --- a/app/client/src/editorComponents/DraggableComponent.tsx +++ b/app/client/src/editorComponents/DraggableComponent.tsx @@ -60,7 +60,10 @@ const DraggableComponent = (props: DraggableComponentProps) => { const { updateWidget } = useContext(WidgetFunctionsContext); const [isResizing, setIsResizing] = useState(false); const deleteWidget = () => { - updateWidget && updateWidget(WidgetOperations.DELETE, props.widgetId); + updateWidget && + updateWidget(WidgetOperations.DELETE, props.widgetId, { + parentId: props.parentId, + }); }; const [{ isDragging }, drag, preview] = useDrag({ item: props, diff --git a/app/client/src/mockResponses/WidgetConfigResponse.tsx b/app/client/src/mockResponses/WidgetConfigResponse.tsx index efff9f0c9f..f63cf16dd6 100644 --- a/app/client/src/mockResponses/WidgetConfigResponse.tsx +++ b/app/client/src/mockResponses/WidgetConfigResponse.tsx @@ -7,12 +7,14 @@ const WidgetConfigResponse: WidgetConfigReducerState = { buttonStyle: "PRIMARY_BUTTON", rows: 1, columns: 2, + widgetName: "Button", }, TEXT_WIDGET: { text: "Not all labels are bad!", textStyle: "LABEL", rows: 1, columns: 3, + widgetName: "Text", }, IMAGE_WIDGET: { defaultImage: "", @@ -20,27 +22,32 @@ const WidgetConfigResponse: WidgetConfigReducerState = { image: "", rows: 3, columns: 3, + widgetName: "Image", }, INPUT_WIDGET: { inputType: "TEXT", label: "Label me", rows: 1, columns: 3, + widgetName: "Input", }, SWITCH_WIDGET: { isOn: false, label: "Turn me on", rows: 1, columns: 4, + widgetName: "Switch", }, CONTAINER_WIDGET: { backgroundColor: "#FFFFFF", rows: 1, columns: 4, + widgetName: "Container", }, SPINNER_WIDGET: { rows: 1, columns: 1, + widgetName: "Spinner", }, DATE_PICKER_WIDGET: { enableTime: false, @@ -48,23 +55,27 @@ const WidgetConfigResponse: WidgetConfigReducerState = { rows: 1, columns: 3, label: "Date", + widgetName: "Datepicker", }, TABLE_WIDGET: { rows: 5, columns: 7, label: "Don't table me!", + widgetName: "Table", }, DROP_DOWN_WIDGET: { rows: 1, columns: 3, selectionType: "SINGLE_SELECT", label: "Pick me!", + widgetName: "Dropdown", }, CHECKBOX_WIDGET: { rows: 1, columns: 3, label: "Label - CHECK!", defaultCheckedState: true, + widgetName: "Checkbox", }, RADIO_GROUP_WIDGET: { rows: 3, @@ -76,6 +87,7 @@ const WidgetConfigResponse: WidgetConfigReducerState = { { label: "Charlie", value: "3" }, ], defaultOptionValue: "1", + widgetName: "RadioGroup", }, ALERT_WIDGET: { alertType: "NOTIFICATION", @@ -84,6 +96,7 @@ const WidgetConfigResponse: WidgetConfigReducerState = { columns: 3, header: "", message: "", + widgetName: "Alert", }, }, configVersion: 1, diff --git a/app/client/src/sagas/WidgetOperationSagas.tsx b/app/client/src/sagas/WidgetOperationSagas.tsx index c5e856738c..d7c42a9c2d 100644 --- a/app/client/src/sagas/WidgetOperationSagas.tsx +++ b/app/client/src/sagas/WidgetOperationSagas.tsx @@ -10,12 +10,7 @@ import { WidgetDelete, } from "../actions/pageActions"; import { FlattenedWidgetProps } from "../reducers/entityReducers/canvasWidgetsReducer"; -import { - getWidgets, - getWidget, - getWidgetParent, - getDefaultWidgetConfig, -} from "./selectors"; +import { getWidgets, getWidget, getDefaultWidgetConfig } from "./selectors"; import { generateWidgetProps, updateWidgetPosition, @@ -47,7 +42,7 @@ export function* addChildSaga(addChildAction: ReduxAction) { rows, parentRowSpace, parentColumnSpace, - getNextWidgetName(type, widgets), + getNextWidgetName(defaultWidgetConfig.widgetName, widgets), defaultWidgetConfig, ); widgets[childWidget.widgetId] = childWidget; @@ -72,14 +67,14 @@ export function* addChildSaga(addChildAction: ReduxAction) { export function* deleteSaga(deleteAction: ReduxAction) { try { - const { widgetId } = deleteAction.payload; + const { widgetId, parentId } = deleteAction.payload; const widgets = yield select(getWidgets); - delete widgets[widgetId]; - const parent = yield select(getWidgetParent, widgetId); + const parent = yield select(getWidget, parentId); parent.children = parent.children.filter( (child: string) => child !== widgetId, ); - widgets[parent.widgetId] = parent; + delete widgets[widgetId]; + widgets[parentId] = parent; yield put({ type: ReduxActionTypes.UPDATE_LAYOUT, payload: { widgets }, @@ -97,25 +92,31 @@ export function* deleteSaga(deleteAction: ReduxAction) { export function* moveSaga(moveAction: ReduxAction) { try { - const { widgetId, leftColumn, topRow, parentWidgetId } = moveAction.payload; + const { + widgetId, + leftColumn, + topRow, + parentId, + newParentId, + } = moveAction.payload; let widget: FlattenedWidgetProps = yield select(getWidget, widgetId); // Get all widgets from DSL/Redux Store const widgets = yield select(getWidgets) as any; // Get parent from DSL/Redux Store - const parent = yield select(getWidgetParent, widgetId); + const parent = yield select(getWidget, parentId); // Update position of widget widget = updateWidgetPosition(widget, leftColumn, topRow, parent); // Replace widget with update widget props widgets[widgetId] = widget; // If the parent has changed i.e parentWidgetId is not parent.widgetId - if (parent.widgetId !== parentWidgetId && widgetId !== parentWidgetId) { + if (parent.widgetId !== newParentId && widgetId !== newParentId) { // Remove from the previous parent parent.children = parent.children.filter( (child: string) => child !== widgetId, ); widgets[parent.widgetId] = parent; // Add to new parent - widgets[parentWidgetId].children.push(widgetId); + widgets[newParentId].children.push(widgetId); } yield put({ type: ReduxActionTypes.UPDATE_LAYOUT, diff --git a/app/client/src/sagas/selectors.tsx b/app/client/src/sagas/selectors.tsx index fc1c5eacf8..86fa24db4c 100644 --- a/app/client/src/sagas/selectors.tsx +++ b/app/client/src/sagas/selectors.tsx @@ -22,20 +22,6 @@ export const getEditorConfigs = ( }; }; -export const getWidgetParent = ( - state: AppState, - widgetId: string, -): FlattenedWidgetProps | undefined => { - const widgets = state.entities.canvasWidgets; - return Object.values(widgets).find( - (widget: FlattenedWidgetProps) => - widget && - widget.children && - widget.children.length > 0 && - widget.children.indexOf(widgetId) > -1, - ); -}; - export const getDefaultWidgetConfig = ( state: AppState, type: WidgetType, diff --git a/app/client/src/utils/AppsmithUtils.tsx b/app/client/src/utils/AppsmithUtils.tsx index ba3636bba0..dbd83854b3 100644 --- a/app/client/src/utils/AppsmithUtils.tsx +++ b/app/client/src/utils/AppsmithUtils.tsx @@ -12,7 +12,6 @@ import FontFaceObserver from "fontfaceobserver"; import PropertyControlRegistry from "./PropertyControlRegistry"; import WidgetBuilderRegistry from "./WidgetRegistry"; import { Property } from "../api/ActionAPI"; -import { WidgetType } from "../constants/WidgetConstants"; import { FlattenedWidgetProps } from "../reducers/entityReducers/canvasWidgetsReducer"; import _ from "lodash"; @@ -64,21 +63,18 @@ export const mapToPropList = (map: Record): Property[] => { }; export const getNextWidgetName = ( - type: WidgetType, + prefix: string, widgets: { [id: string]: FlattenedWidgetProps; }, ) => { - const prefix = type - .split("_") - .filter(token => token !== "WIDGET") - .join("") - .toLowerCase(); + const regex = new RegExp(`^${prefix}(\\d+)$`); const usedIndices: number[] = Object.values(widgets).map(widget => { - if (widget.type === type) { - const ind = widget.widgetName - ? parseInt(widget.widgetName.split(prefix)[1], 10) - : 0; + if (widget && widget.widgetName && regex.test(widget.widgetName)) { + const name = widget.widgetName || ""; + const matches = name.match(regex); + const ind = + matches && Array.isArray(matches) ? parseInt(matches[1], 10) : 0; return Number.isNaN(ind) ? 0 : ind; } return 0; diff --git a/app/client/src/utils/WidgetPropsUtils.tsx b/app/client/src/utils/WidgetPropsUtils.tsx index 5395d90b88..3e974980f8 100644 --- a/app/client/src/utils/WidgetPropsUtils.tsx +++ b/app/client/src/utils/WidgetPropsUtils.tsx @@ -142,7 +142,8 @@ export const widgetOperationParams = ( { leftColumn, topRow, - parentWidgetId: widgetId, + parentId: widget.parentId, + newParentId: widgetId, }, ]; // If this is not an existing widget, we'll not have the widgetId