2021-08-24 11:38:20 +00:00
|
|
|
import {
|
|
|
|
|
ReduxAction,
|
|
|
|
|
ReduxActionErrorTypes,
|
|
|
|
|
ReduxActionTypes,
|
2022-04-12 10:50:01 +00:00
|
|
|
} from "@appsmith/constants/ReduxActionConstants";
|
2021-09-09 15:10:22 +00:00
|
|
|
import { MAIN_CONTAINER_WIDGET_ID } from "constants/WidgetConstants";
|
2021-08-24 11:38:20 +00:00
|
|
|
import { all, call, fork, put, select, takeLatest } from "redux-saga/effects";
|
|
|
|
|
import {
|
2022-12-08 12:16:41 +00:00
|
|
|
getWidgetIdsByType,
|
2021-08-24 11:38:20 +00:00
|
|
|
getWidgetImmediateChildren,
|
|
|
|
|
getWidgetMetaProps,
|
|
|
|
|
getWidgets,
|
|
|
|
|
} from "./selectors";
|
2021-06-17 13:26:54 +00:00
|
|
|
import log from "loglevel";
|
|
|
|
|
import {
|
|
|
|
|
deselectMultipleWidgetsAction,
|
|
|
|
|
selectMultipleWidgetsAction,
|
|
|
|
|
selectWidgetAction,
|
|
|
|
|
selectWidgetInitAction,
|
2021-06-28 07:11:47 +00:00
|
|
|
silentAddSelectionsAction,
|
2021-06-17 13:26:54 +00:00
|
|
|
} from "actions/widgetSelectionActions";
|
2023-01-23 03:50:47 +00:00
|
|
|
import { Toaster, Variant } from "design-system-old";
|
2022-02-11 18:08:46 +00:00
|
|
|
import {
|
|
|
|
|
createMessage,
|
|
|
|
|
SELECT_ALL_WIDGETS_MSG,
|
|
|
|
|
} from "@appsmith/constants/messages";
|
2022-09-15 05:44:11 +00:00
|
|
|
import { getLastSelectedWidget, getSelectedWidgets } from "selectors/ui";
|
2021-08-24 11:38:20 +00:00
|
|
|
import {
|
|
|
|
|
CanvasWidgetsReduxState,
|
|
|
|
|
FlattenedWidgetProps,
|
|
|
|
|
} from "reducers/entityReducers/canvasWidgetsReducer";
|
2022-06-25 05:30:54 +00:00
|
|
|
import { getWidgetChildrenIds } from "./WidgetOperationUtils";
|
2022-08-24 12:16:32 +00:00
|
|
|
import { AppState } from "@appsmith/reducers";
|
2021-09-09 15:10:22 +00:00
|
|
|
import { checkIsDropTarget } from "components/designSystems/appsmith/PositionedContainer";
|
|
|
|
|
import WidgetFactory from "utils/WidgetFactory";
|
2022-12-08 12:16:41 +00:00
|
|
|
import { closeAllModals, showModal } from "actions/widgetActions";
|
2022-10-17 15:16:38 +00:00
|
|
|
import history from "utils/history";
|
|
|
|
|
import { getCurrentPageId } from "selectors/editorSelectors";
|
|
|
|
|
import { builderURL } from "RouteBuilder";
|
|
|
|
|
import { CanvasWidgetsStructureReduxState } from "reducers/entityReducers/canvasWidgetsStructureReducer";
|
2022-12-08 12:16:41 +00:00
|
|
|
import {
|
|
|
|
|
getCanvasWidgetsWithParentId,
|
2022-12-15 02:32:03 +00:00
|
|
|
getParentModalId,
|
2022-12-08 12:16:41 +00:00
|
|
|
} from "selectors/entitiesSelector";
|
2021-09-09 15:10:22 +00:00
|
|
|
const WidgetTypes = WidgetFactory.widgetTypes;
|
2021-06-17 13:26:54 +00:00
|
|
|
// The following is computed to be used in the entity explorer
|
|
|
|
|
// Every time a widget is selected, we need to expand widget entities
|
|
|
|
|
// in the entity explorer so that the selected widget is visible
|
|
|
|
|
function* selectedWidgetAncestrySaga(
|
|
|
|
|
action: ReduxAction<{ widgetId: string; isMultiSelect: boolean }>,
|
|
|
|
|
) {
|
|
|
|
|
try {
|
2021-08-24 11:38:20 +00:00
|
|
|
const canvasWidgets: CanvasWidgetsReduxState = yield select(getWidgets);
|
2021-06-17 13:26:54 +00:00
|
|
|
const widgetIdsExpandList = [];
|
|
|
|
|
const { isMultiSelect, widgetId: selectedWidget } = action.payload;
|
|
|
|
|
|
|
|
|
|
// Make sure that the selected widget exists in canvasWidgets
|
|
|
|
|
let widgetId = canvasWidgets[selectedWidget]
|
|
|
|
|
? canvasWidgets[selectedWidget].parentId
|
|
|
|
|
: undefined;
|
|
|
|
|
// If there is a parentId for the selectedWidget
|
|
|
|
|
if (widgetId) {
|
|
|
|
|
// Keep including the parent until we reach the main container
|
2021-08-24 11:38:20 +00:00
|
|
|
while (widgetId && widgetId !== MAIN_CONTAINER_WIDGET_ID) {
|
2021-06-17 13:26:54 +00:00
|
|
|
widgetIdsExpandList.push(widgetId);
|
|
|
|
|
if (canvasWidgets[widgetId] && canvasWidgets[widgetId].parentId)
|
|
|
|
|
widgetId = canvasWidgets[widgetId].parentId;
|
|
|
|
|
else break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (isMultiSelect) {
|
|
|
|
|
// Deselect the parents if this is a Multi select.
|
|
|
|
|
const parentsToDeselect = widgetIdsExpandList.filter(
|
|
|
|
|
(each) => each !== selectedWidget,
|
|
|
|
|
);
|
|
|
|
|
if (parentsToDeselect && parentsToDeselect.length) {
|
|
|
|
|
yield put(deselectMultipleWidgetsAction(parentsToDeselect));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
yield put({
|
|
|
|
|
type: ReduxActionTypes.SET_SELECTED_WIDGET_ANCESTORY,
|
|
|
|
|
payload: widgetIdsExpandList,
|
|
|
|
|
});
|
|
|
|
|
} catch (error) {
|
|
|
|
|
log.debug("Could not compute selected widget's ancestry", error);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-08-24 11:38:20 +00:00
|
|
|
function* getDroppingCanvasOfWidget(widgetLastSelected: FlattenedWidgetProps) {
|
2021-09-09 15:10:22 +00:00
|
|
|
if (checkIsDropTarget(widgetLastSelected.type)) {
|
2021-08-24 11:38:20 +00:00
|
|
|
const canvasWidgets: CanvasWidgetsReduxState = yield select(getWidgets);
|
|
|
|
|
const childWidgets: string[] = yield select(
|
|
|
|
|
getWidgetImmediateChildren,
|
|
|
|
|
widgetLastSelected.widgetId,
|
|
|
|
|
);
|
|
|
|
|
const firstCanvas = childWidgets.find((each) => {
|
|
|
|
|
const widget = canvasWidgets[each];
|
|
|
|
|
return widget.type === WidgetTypes.CANVAS_WIDGET;
|
|
|
|
|
});
|
|
|
|
|
if (widgetLastSelected.type === WidgetTypes.TABS_WIDGET) {
|
|
|
|
|
const tabMetaProps: Record<string, unknown> = yield select(
|
|
|
|
|
getWidgetMetaProps,
|
|
|
|
|
widgetLastSelected.widgetId,
|
|
|
|
|
);
|
|
|
|
|
return tabMetaProps.selectedTabWidgetId;
|
|
|
|
|
}
|
|
|
|
|
if (firstCanvas) {
|
|
|
|
|
return firstCanvas;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return widgetLastSelected.parentId;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function* getLastSelectedCanvas() {
|
2022-09-15 05:44:11 +00:00
|
|
|
const lastSelectedWidget: string = yield select(getLastSelectedWidget);
|
2021-08-24 11:38:20 +00:00
|
|
|
const canvasWidgets: CanvasWidgetsReduxState = yield select(getWidgets);
|
|
|
|
|
const widgetLastSelected =
|
|
|
|
|
lastSelectedWidget && canvasWidgets[lastSelectedWidget];
|
|
|
|
|
if (widgetLastSelected) {
|
|
|
|
|
const canvasToSelect: string = yield call(
|
|
|
|
|
getDroppingCanvasOfWidget,
|
|
|
|
|
widgetLastSelected,
|
|
|
|
|
);
|
|
|
|
|
return canvasToSelect ? canvasToSelect : MAIN_CONTAINER_WIDGET_ID;
|
|
|
|
|
}
|
|
|
|
|
return MAIN_CONTAINER_WIDGET_ID;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// used for List widget cases
|
|
|
|
|
const isChildOfDropDisabledCanvas = (
|
|
|
|
|
canvasWidgets: CanvasWidgetsReduxState,
|
|
|
|
|
widgetId: string,
|
|
|
|
|
) => {
|
|
|
|
|
const widget = canvasWidgets[widgetId];
|
|
|
|
|
const parentId = widget.parentId || MAIN_CONTAINER_WIDGET_ID;
|
|
|
|
|
const parent = canvasWidgets[parentId];
|
|
|
|
|
return !!parent?.dropDisabled;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
function* getAllSelectableChildren() {
|
2022-09-15 05:44:11 +00:00
|
|
|
const lastSelectedWidget: string = yield select(getLastSelectedWidget);
|
2021-08-24 11:38:20 +00:00
|
|
|
const canvasWidgets: CanvasWidgetsReduxState = yield select(getWidgets);
|
|
|
|
|
const widgetLastSelected = canvasWidgets[lastSelectedWidget];
|
|
|
|
|
const canvasId: string = yield call(getLastSelectedCanvas);
|
|
|
|
|
let allChildren: string[] = [];
|
|
|
|
|
const selectGrandChildren: boolean = lastSelectedWidget
|
2021-11-19 09:54:46 +00:00
|
|
|
? widgetLastSelected && widgetLastSelected.type === WidgetTypes.LIST_WIDGET
|
2021-08-24 11:38:20 +00:00
|
|
|
: false;
|
|
|
|
|
if (selectGrandChildren) {
|
|
|
|
|
allChildren = yield call(
|
2022-06-25 05:30:54 +00:00
|
|
|
getWidgetChildrenIds,
|
2021-08-24 11:38:20 +00:00
|
|
|
canvasWidgets,
|
|
|
|
|
lastSelectedWidget,
|
|
|
|
|
);
|
|
|
|
|
} else {
|
|
|
|
|
allChildren = yield select(getWidgetImmediateChildren, canvasId);
|
|
|
|
|
}
|
|
|
|
|
if (allChildren && allChildren.length) {
|
|
|
|
|
const selectableChildren = allChildren.filter((each) => {
|
|
|
|
|
const isCanvasWidget =
|
|
|
|
|
each &&
|
|
|
|
|
canvasWidgets[each] &&
|
|
|
|
|
canvasWidgets[each].type === WidgetTypes.CANVAS_WIDGET;
|
|
|
|
|
const isImmovableWidget = isChildOfDropDisabledCanvas(
|
|
|
|
|
canvasWidgets,
|
|
|
|
|
each,
|
|
|
|
|
);
|
|
|
|
|
return !(isCanvasWidget || isImmovableWidget);
|
|
|
|
|
});
|
|
|
|
|
return selectableChildren;
|
|
|
|
|
}
|
|
|
|
|
return [];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function* selectAllWidgetsInCanvasSaga() {
|
|
|
|
|
try {
|
|
|
|
|
const canvasWidgets: CanvasWidgetsReduxState = yield select(getWidgets);
|
|
|
|
|
const allSelectableChildren: string[] = yield call(
|
|
|
|
|
getAllSelectableChildren,
|
|
|
|
|
);
|
|
|
|
|
if (allSelectableChildren && allSelectableChildren.length) {
|
|
|
|
|
yield put(selectMultipleWidgetsAction(allSelectableChildren));
|
|
|
|
|
const isAnyModalSelected = allSelectableChildren.some((each) => {
|
|
|
|
|
return (
|
|
|
|
|
each &&
|
|
|
|
|
canvasWidgets[each] &&
|
|
|
|
|
canvasWidgets[each].type === WidgetTypes.MODAL_WIDGET
|
|
|
|
|
);
|
|
|
|
|
});
|
|
|
|
|
if (isAnyModalSelected) {
|
|
|
|
|
Toaster.show({
|
|
|
|
|
text: createMessage(SELECT_ALL_WIDGETS_MSG),
|
|
|
|
|
variant: Variant.info,
|
|
|
|
|
duration: 3000,
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} catch (error) {
|
|
|
|
|
yield put({
|
|
|
|
|
type: ReduxActionErrorTypes.WIDGET_SELECTION_ERROR,
|
|
|
|
|
payload: {
|
|
|
|
|
action: ReduxActionTypes.SELECT_ALL_WIDGETS_IN_CANVAS_INIT,
|
|
|
|
|
error,
|
|
|
|
|
},
|
2021-06-17 13:26:54 +00:00
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function* deselectNonSiblingsOfWidgetSaga(
|
|
|
|
|
action: ReduxAction<{ widgetId: string; isMultiSelect: boolean }>,
|
|
|
|
|
) {
|
2021-08-24 11:38:20 +00:00
|
|
|
try {
|
|
|
|
|
const { isMultiSelect, widgetId } = action.payload;
|
|
|
|
|
if (isMultiSelect) {
|
|
|
|
|
const allWidgets: CanvasWidgetsReduxState = yield select(getWidgets);
|
|
|
|
|
const parentId: any = allWidgets[widgetId].parentId;
|
|
|
|
|
const childWidgets: string[] = yield select(
|
|
|
|
|
getWidgetImmediateChildren,
|
|
|
|
|
parentId,
|
|
|
|
|
);
|
|
|
|
|
const currentSelectedWidgets: string[] = yield select(getSelectedWidgets);
|
2021-06-17 13:26:54 +00:00
|
|
|
|
2021-08-24 11:38:20 +00:00
|
|
|
const nonSiblings = currentSelectedWidgets.filter(
|
|
|
|
|
(each) => !childWidgets.includes(each),
|
2021-06-17 13:26:54 +00:00
|
|
|
);
|
2021-08-24 11:38:20 +00:00
|
|
|
if (nonSiblings && nonSiblings.length) {
|
|
|
|
|
yield put(
|
|
|
|
|
deselectMultipleWidgetsAction(
|
|
|
|
|
nonSiblings.filter((each) => each !== widgetId),
|
|
|
|
|
),
|
|
|
|
|
);
|
|
|
|
|
}
|
2021-06-17 13:26:54 +00:00
|
|
|
}
|
2021-08-24 11:38:20 +00:00
|
|
|
} catch (error) {
|
|
|
|
|
yield put({
|
|
|
|
|
type: ReduxActionErrorTypes.WIDGET_SELECTION_ERROR,
|
|
|
|
|
payload: {
|
|
|
|
|
action: ReduxActionTypes.SELECT_WIDGET_INIT,
|
|
|
|
|
error,
|
|
|
|
|
},
|
|
|
|
|
});
|
2021-06-17 13:26:54 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function* selectWidgetSaga(
|
|
|
|
|
action: ReduxAction<{ widgetId: string; isMultiSelect: boolean }>,
|
|
|
|
|
) {
|
2021-08-24 11:38:20 +00:00
|
|
|
try {
|
|
|
|
|
const { isMultiSelect, widgetId } = action.payload;
|
|
|
|
|
yield put(selectWidgetAction(widgetId, isMultiSelect));
|
|
|
|
|
} catch (error) {
|
|
|
|
|
yield put({
|
|
|
|
|
type: ReduxActionErrorTypes.WIDGET_SELECTION_ERROR,
|
|
|
|
|
payload: {
|
|
|
|
|
action: ReduxActionTypes.SELECT_WIDGET_INIT,
|
|
|
|
|
error,
|
|
|
|
|
},
|
|
|
|
|
});
|
|
|
|
|
}
|
2021-06-17 13:26:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function* shiftSelectWidgetsSaga(
|
|
|
|
|
action: ReduxAction<{ widgetId: string; siblingWidgets: string[] }>,
|
|
|
|
|
) {
|
2021-08-24 11:38:20 +00:00
|
|
|
try {
|
|
|
|
|
const { siblingWidgets, widgetId } = action.payload;
|
|
|
|
|
const selectedWidgets: string[] = yield select(getSelectedWidgets);
|
2022-09-15 05:44:11 +00:00
|
|
|
const lastSelectedWidget: string = yield select(getLastSelectedWidget);
|
2021-08-24 11:38:20 +00:00
|
|
|
const lastSelectedWidgetIndex = siblingWidgets.indexOf(lastSelectedWidget);
|
|
|
|
|
const isWidgetSelected = selectedWidgets.includes(widgetId);
|
|
|
|
|
if (!isWidgetSelected && lastSelectedWidgetIndex > -1) {
|
|
|
|
|
const selectedWidgetIndex = siblingWidgets.indexOf(widgetId);
|
|
|
|
|
const start =
|
|
|
|
|
lastSelectedWidgetIndex < selectedWidgetIndex
|
|
|
|
|
? lastSelectedWidgetIndex
|
|
|
|
|
: selectedWidgetIndex;
|
|
|
|
|
const end =
|
|
|
|
|
lastSelectedWidgetIndex < selectedWidgetIndex
|
|
|
|
|
? selectedWidgetIndex
|
|
|
|
|
: lastSelectedWidgetIndex;
|
|
|
|
|
const unSelectedSiblings = siblingWidgets.slice(start + 1, end);
|
|
|
|
|
if (unSelectedSiblings && unSelectedSiblings.length) {
|
|
|
|
|
yield put(silentAddSelectionsAction(unSelectedSiblings));
|
|
|
|
|
}
|
2021-06-17 13:26:54 +00:00
|
|
|
}
|
2021-08-24 11:38:20 +00:00
|
|
|
yield put(selectWidgetInitAction(widgetId, true));
|
|
|
|
|
} catch (error) {
|
|
|
|
|
yield put({
|
|
|
|
|
type: ReduxActionErrorTypes.WIDGET_SELECTION_ERROR,
|
|
|
|
|
payload: {
|
|
|
|
|
action: ReduxActionTypes.SHIFT_SELECT_WIDGET_INIT,
|
|
|
|
|
error,
|
|
|
|
|
},
|
|
|
|
|
});
|
2021-06-17 13:26:54 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-06-28 07:11:47 +00:00
|
|
|
function* selectMultipleWidgetsSaga(
|
|
|
|
|
action: ReduxAction<{ widgetIds: string[] }>,
|
|
|
|
|
) {
|
2021-08-24 11:38:20 +00:00
|
|
|
try {
|
|
|
|
|
const { widgetIds } = action.payload;
|
2022-10-17 15:16:38 +00:00
|
|
|
if (!widgetIds) {
|
2021-08-24 11:38:20 +00:00
|
|
|
return;
|
|
|
|
|
}
|
2022-10-17 15:16:38 +00:00
|
|
|
const allWidgets: CanvasWidgetsReduxState = yield select(
|
|
|
|
|
getCanvasWidgetsWithParentId,
|
|
|
|
|
);
|
|
|
|
|
const parentToMatch = allWidgets[widgetIds[0]]?.parentId;
|
2021-08-24 11:38:20 +00:00
|
|
|
const doesNotMatchParent = widgetIds.some((each) => {
|
2022-10-17 15:16:38 +00:00
|
|
|
return allWidgets[each]?.parentId !== parentToMatch;
|
2021-08-24 11:38:20 +00:00
|
|
|
});
|
|
|
|
|
if (doesNotMatchParent) {
|
|
|
|
|
return;
|
2022-12-08 12:16:41 +00:00
|
|
|
} else if (widgetIds.length === 1) {
|
|
|
|
|
yield put(selectWidgetInitAction(widgetIds[0]));
|
2021-08-24 11:38:20 +00:00
|
|
|
} else {
|
|
|
|
|
yield put(selectWidgetAction());
|
|
|
|
|
yield put(selectMultipleWidgetsAction(widgetIds));
|
|
|
|
|
}
|
|
|
|
|
} catch (error) {
|
|
|
|
|
yield put({
|
|
|
|
|
type: ReduxActionErrorTypes.WIDGET_SELECTION_ERROR,
|
|
|
|
|
payload: {
|
|
|
|
|
action: ReduxActionTypes.SELECT_MULTIPLE_WIDGETS_INIT,
|
|
|
|
|
error,
|
|
|
|
|
},
|
|
|
|
|
});
|
2021-06-28 07:11:47 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-10-17 15:16:38 +00:00
|
|
|
/**
|
|
|
|
|
* Append Selected widgetId as hash to the url path
|
|
|
|
|
* @param action
|
|
|
|
|
*/
|
|
|
|
|
function* appendSelectedWidgetToUrlSaga(
|
|
|
|
|
action: ReduxAction<{ selectedWidgets: string[] }>,
|
|
|
|
|
) {
|
|
|
|
|
const { hash, pathname } = window.location;
|
|
|
|
|
const { selectedWidgets } = action.payload;
|
|
|
|
|
const currentPageId: string = yield select(getCurrentPageId);
|
|
|
|
|
|
|
|
|
|
const currentURL = hash ? `${pathname}${hash}` : pathname;
|
|
|
|
|
let canvasEditorURL;
|
|
|
|
|
if (selectedWidgets.length === 1) {
|
|
|
|
|
canvasEditorURL = `${builderURL({
|
|
|
|
|
pageId: currentPageId,
|
|
|
|
|
hash: selectedWidgets[0],
|
2022-11-28 05:44:31 +00:00
|
|
|
persistExistingParams: true,
|
2022-10-17 15:16:38 +00:00
|
|
|
})}`;
|
|
|
|
|
} else {
|
|
|
|
|
canvasEditorURL = `${builderURL({
|
|
|
|
|
pageId: currentPageId,
|
2022-11-28 05:44:31 +00:00
|
|
|
persistExistingParams: true,
|
2022-10-17 15:16:38 +00:00
|
|
|
})}`;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (currentURL !== canvasEditorURL) {
|
2022-11-28 05:44:31 +00:00
|
|
|
history.replace(canvasEditorURL);
|
2022-10-17 15:16:38 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-08-16 09:24:42 +00:00
|
|
|
function* canPerformSelectionSaga(saga: any, action: any) {
|
|
|
|
|
const isDragging: boolean = yield select(
|
|
|
|
|
(state: AppState) => state.ui.widgetDragResize.isDragging,
|
|
|
|
|
);
|
|
|
|
|
if (!isDragging) {
|
|
|
|
|
yield fork(saga, action);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function* deselectAllWidgetsSaga() {
|
|
|
|
|
yield put(selectMultipleWidgetsAction([]));
|
|
|
|
|
}
|
|
|
|
|
|
2022-10-17 15:16:38 +00:00
|
|
|
/**
|
|
|
|
|
* Deselect widgets only if it is or inside the modal. Otherwise will not deselect any widgets.
|
|
|
|
|
* @param action
|
|
|
|
|
* @returns
|
|
|
|
|
*/
|
|
|
|
|
function* deselectModalWidgetSaga(
|
|
|
|
|
action: ReduxAction<{
|
|
|
|
|
modalId: string;
|
|
|
|
|
modalWidgetChildren?: CanvasWidgetsStructureReduxState[];
|
|
|
|
|
}>,
|
|
|
|
|
) {
|
|
|
|
|
const { modalId, modalWidgetChildren } = action.payload;
|
|
|
|
|
const selectedWidgets: string[] = yield select(getSelectedWidgets);
|
|
|
|
|
if (selectedWidgets.length == 0) return;
|
|
|
|
|
|
|
|
|
|
if (
|
|
|
|
|
(selectedWidgets.length === 1 && selectedWidgets[0] === modalId) ||
|
|
|
|
|
isWidgetPartOfChildren(selectedWidgets[0], modalWidgetChildren)
|
|
|
|
|
)
|
|
|
|
|
yield put(selectMultipleWidgetsAction([]));
|
|
|
|
|
}
|
|
|
|
|
|
2022-12-08 12:16:41 +00:00
|
|
|
function* openOrCloseModalSaga(
|
|
|
|
|
action: ReduxAction<{ widgetId: string; isMultiSelect: boolean }>,
|
|
|
|
|
) {
|
|
|
|
|
if (!action.payload.widgetId) return;
|
|
|
|
|
if (action.payload.isMultiSelect) return;
|
|
|
|
|
|
|
|
|
|
const modalWidgetIds: string[] = yield select(
|
|
|
|
|
getWidgetIdsByType,
|
|
|
|
|
"MODAL_WIDGET",
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
const widgetIsModal = modalWidgetIds.includes(action.payload.widgetId);
|
|
|
|
|
|
|
|
|
|
if (widgetIsModal) {
|
|
|
|
|
yield put(showModal(action.payload.widgetId));
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2022-12-15 02:32:03 +00:00
|
|
|
const widgetMap: CanvasWidgetsReduxState = yield select(getWidgets);
|
2022-12-08 12:16:41 +00:00
|
|
|
const widget = widgetMap[action.payload.widgetId];
|
|
|
|
|
|
2022-12-13 10:04:32 +00:00
|
|
|
if (widget && widget.parentId) {
|
2022-12-15 02:32:03 +00:00
|
|
|
const parentModalId = getParentModalId(widget, widgetMap);
|
|
|
|
|
const widgetInModal = modalWidgetIds.includes(parentModalId);
|
2022-12-08 12:16:41 +00:00
|
|
|
if (widgetInModal) {
|
2022-12-15 02:32:03 +00:00
|
|
|
yield put(showModal(parentModalId));
|
2022-12-08 12:16:41 +00:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
yield put(closeAllModals());
|
|
|
|
|
}
|
|
|
|
|
|
2022-10-17 15:16:38 +00:00
|
|
|
/**
|
|
|
|
|
* Checks if the given widgetId is part of the children recursively
|
|
|
|
|
* @param widgetId
|
|
|
|
|
* @param children
|
|
|
|
|
* @returns
|
|
|
|
|
*/
|
|
|
|
|
function isWidgetPartOfChildren(
|
|
|
|
|
widgetId: string,
|
|
|
|
|
children?: CanvasWidgetsStructureReduxState[],
|
|
|
|
|
) {
|
|
|
|
|
if (!children) return false;
|
|
|
|
|
|
|
|
|
|
for (const child of children) {
|
|
|
|
|
if (
|
|
|
|
|
child.widgetId === widgetId ||
|
|
|
|
|
isWidgetPartOfChildren(widgetId, child.children)
|
|
|
|
|
) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2021-06-17 13:26:54 +00:00
|
|
|
export function* widgetSelectionSagas() {
|
|
|
|
|
yield all([
|
|
|
|
|
takeLatest(
|
|
|
|
|
ReduxActionTypes.SHIFT_SELECT_WIDGET_INIT,
|
2021-08-16 09:24:42 +00:00
|
|
|
canPerformSelectionSaga,
|
2021-06-17 13:26:54 +00:00
|
|
|
shiftSelectWidgetsSaga,
|
|
|
|
|
),
|
|
|
|
|
takeLatest(
|
|
|
|
|
ReduxActionTypes.SELECT_WIDGET_INIT,
|
2021-08-16 09:24:42 +00:00
|
|
|
canPerformSelectionSaga,
|
|
|
|
|
selectWidgetSaga,
|
|
|
|
|
),
|
|
|
|
|
takeLatest(
|
|
|
|
|
ReduxActionTypes.SELECT_WIDGET_INIT,
|
|
|
|
|
canPerformSelectionSaga,
|
|
|
|
|
selectedWidgetAncestrySaga,
|
|
|
|
|
),
|
|
|
|
|
takeLatest(
|
|
|
|
|
ReduxActionTypes.SELECT_WIDGET_INIT,
|
|
|
|
|
canPerformSelectionSaga,
|
2021-06-17 13:26:54 +00:00
|
|
|
deselectNonSiblingsOfWidgetSaga,
|
|
|
|
|
),
|
2022-12-08 12:16:41 +00:00
|
|
|
takeLatest(
|
|
|
|
|
ReduxActionTypes.SELECT_WIDGET_INIT,
|
|
|
|
|
canPerformSelectionSaga,
|
|
|
|
|
openOrCloseModalSaga,
|
|
|
|
|
),
|
2021-06-28 07:11:47 +00:00
|
|
|
takeLatest(
|
|
|
|
|
ReduxActionTypes.SELECT_ALL_WIDGETS_IN_CANVAS_INIT,
|
2021-08-16 09:24:42 +00:00
|
|
|
canPerformSelectionSaga,
|
2021-06-28 07:11:47 +00:00
|
|
|
selectAllWidgetsInCanvasSaga,
|
|
|
|
|
),
|
2021-06-17 13:26:54 +00:00
|
|
|
takeLatest(
|
|
|
|
|
ReduxActionTypes.SELECT_MULTIPLE_WIDGETS_INIT,
|
2021-08-16 09:24:42 +00:00
|
|
|
canPerformSelectionSaga,
|
2021-06-28 07:11:47 +00:00
|
|
|
selectMultipleWidgetsSaga,
|
2021-06-17 13:26:54 +00:00
|
|
|
),
|
2021-08-16 09:24:42 +00:00
|
|
|
takeLatest(
|
|
|
|
|
ReduxActionTypes.DESELECT_MULTIPLE_WIDGETS_INIT,
|
|
|
|
|
canPerformSelectionSaga,
|
|
|
|
|
deselectAllWidgetsSaga,
|
|
|
|
|
),
|
2022-10-17 15:16:38 +00:00
|
|
|
takeLatest(
|
|
|
|
|
ReduxActionTypes.DESELECT_MODAL_WIDGETS,
|
|
|
|
|
deselectModalWidgetSaga,
|
|
|
|
|
),
|
|
|
|
|
takeLatest(
|
|
|
|
|
ReduxActionTypes.APPEND_SELECTED_WIDGET_TO_URL,
|
|
|
|
|
appendSelectedWidgetToUrlSaga,
|
|
|
|
|
),
|
2021-06-17 13:26:54 +00:00
|
|
|
]);
|
|
|
|
|
}
|