2023-10-06 10:07:43 +00:00
|
|
|
import type { AppState } from "@appsmith/reducers";
|
|
|
|
|
import { createSelector } from "reselect";
|
|
|
|
|
import { getFocusedWidget, getSelectedWidgets } from "selectors/ui";
|
|
|
|
|
import { getDataTree } from "selectors/dataTreeSelectors";
|
|
|
|
|
import { getWidgets } from "sagas/selectors";
|
|
|
|
|
import { getShouldShowWidgetName } from "@appsmith/selectors/entitiesSelector";
|
|
|
|
|
import { WidgetNameState } from "./WidgetNamesCanvas/WidgetNameConstants";
|
|
|
|
|
import { MAIN_CONTAINER_WIDGET_ID } from "constants/WidgetConstants";
|
|
|
|
|
import { EVAL_ERROR_PATH } from "utils/DynamicBindingUtils";
|
|
|
|
|
import get from "lodash/get";
|
|
|
|
|
import { getErrorCount } from "layoutSystems/common/widgetName/utils";
|
2023-10-18 13:39:07 +00:00
|
|
|
import type { LayoutElementPositions } from "./types";
|
2023-10-06 10:07:43 +00:00
|
|
|
import type { WidgetProps } from "widgets/BaseWidget";
|
|
|
|
|
import type { WidgetNameData } from "./WidgetNamesCanvas/WidgetNameTypes";
|
2023-10-10 12:32:17 +00:00
|
|
|
import type { DataTree } from "entities/DataTree/dataTreeTypes";
|
2023-10-06 10:07:43 +00:00
|
|
|
|
2023-10-18 13:39:07 +00:00
|
|
|
export const getLayoutElementPositions = (state: AppState) =>
|
|
|
|
|
state.entities.layoutElementPositions;
|
2023-10-06 10:07:43 +00:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* method to get the widget data required to draw widget name component on canvas
|
|
|
|
|
* @param widget widget whose widget name will be drawn on canvas
|
|
|
|
|
* @param dataTree contains evaluated widget information that is used to check of the widget has any errors
|
|
|
|
|
* @param positions positions of all the widgets in pixels
|
|
|
|
|
* @param isFocused boolean to indicate if the widget is focused
|
|
|
|
|
* @returns WidgetNameData object which contains information regarding the widget to draw it's widget name on canvas
|
|
|
|
|
*/
|
|
|
|
|
const getWidgetNameState = (
|
|
|
|
|
widget: WidgetProps,
|
|
|
|
|
dataTree: DataTree,
|
2023-10-18 13:39:07 +00:00
|
|
|
positions: LayoutElementPositions,
|
2023-10-06 10:07:43 +00:00
|
|
|
isFocused = false,
|
|
|
|
|
): WidgetNameData => {
|
|
|
|
|
let nameState = isFocused
|
|
|
|
|
? WidgetNameState.FOCUSED
|
|
|
|
|
: WidgetNameState.SELECTED;
|
|
|
|
|
|
|
|
|
|
const widgetName = widget.widgetName;
|
|
|
|
|
|
|
|
|
|
const widgetEntity = dataTree[widgetName];
|
|
|
|
|
|
|
|
|
|
const parentId = widget.parentId || MAIN_CONTAINER_WIDGET_ID;
|
|
|
|
|
|
|
|
|
|
if (widgetEntity) {
|
|
|
|
|
const errorObj = get(widgetEntity, EVAL_ERROR_PATH, {});
|
|
|
|
|
const errorCount = getErrorCount(errorObj);
|
|
|
|
|
|
|
|
|
|
if (errorCount > 0) {
|
|
|
|
|
nameState = WidgetNameState.ERROR;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const widgetNameData = {
|
|
|
|
|
id: widget.widgetId,
|
|
|
|
|
position: positions[widget.widgetId],
|
|
|
|
|
widgetName: widgetName,
|
|
|
|
|
parentId,
|
|
|
|
|
dragDisabled: widget.dragDisabled,
|
|
|
|
|
nameState,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
return widgetNameData;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* selector to get information regarding the selected widget to draw it's widget name on canvas
|
|
|
|
|
*/
|
|
|
|
|
export const getSelectedWidgetNameData = createSelector(
|
2023-10-18 13:39:07 +00:00
|
|
|
getLayoutElementPositions,
|
2023-10-06 10:07:43 +00:00
|
|
|
getSelectedWidgets,
|
|
|
|
|
getWidgets,
|
|
|
|
|
getDataTree,
|
|
|
|
|
getShouldShowWidgetName,
|
|
|
|
|
(
|
|
|
|
|
positions,
|
|
|
|
|
selectedWidgets,
|
|
|
|
|
widgets,
|
|
|
|
|
dataTree,
|
|
|
|
|
shouldShowWidgetName,
|
2023-10-20 06:15:16 +00:00
|
|
|
): WidgetNameData[] | undefined => {
|
2023-10-25 05:40:43 +00:00
|
|
|
// This way, we know that we're dragging so we'll clear the canvas, but keep existing references
|
|
|
|
|
// Then, we can prevent a redraw until the widget positions change
|
|
|
|
|
if (!shouldShowWidgetName) return [];
|
|
|
|
|
// This way, we know that we're supposed to clear all the widget names
|
|
|
|
|
// This would happen if there are no selected widgets and we need to clear the canvas
|
|
|
|
|
if (!selectedWidgets || selectedWidgets.length === 0) return;
|
|
|
|
|
|
2023-10-20 06:15:16 +00:00
|
|
|
const result: WidgetNameData[] = [];
|
|
|
|
|
for (const selectedWidgetId of selectedWidgets) {
|
|
|
|
|
const selectedWidget = widgets[selectedWidgetId];
|
|
|
|
|
if (!selectedWidget) continue;
|
|
|
|
|
result.push(getWidgetNameState(selectedWidget, dataTree, positions));
|
|
|
|
|
}
|
|
|
|
|
if (result.length > 0) return result;
|
|
|
|
|
else return;
|
2023-10-06 10:07:43 +00:00
|
|
|
},
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* selector to get information regarding the focused widget to draw it's widget name on canvas
|
|
|
|
|
*/
|
|
|
|
|
export const getFocusedWidgetNameData = createSelector(
|
2023-10-18 13:39:07 +00:00
|
|
|
getLayoutElementPositions,
|
2023-10-06 10:07:43 +00:00
|
|
|
getFocusedWidget,
|
|
|
|
|
getSelectedWidgets,
|
|
|
|
|
getWidgets,
|
|
|
|
|
getDataTree,
|
|
|
|
|
getShouldShowWidgetName,
|
|
|
|
|
(
|
|
|
|
|
positions,
|
|
|
|
|
focusedWidgetId,
|
|
|
|
|
selectedWidgets,
|
|
|
|
|
widgets,
|
|
|
|
|
dataTree,
|
|
|
|
|
shouldShowWidgetName,
|
|
|
|
|
): WidgetNameData | undefined => {
|
|
|
|
|
if (!focusedWidgetId || !widgets || !shouldShowWidgetName) return;
|
|
|
|
|
|
|
|
|
|
const focusedWidget = widgets[focusedWidgetId];
|
|
|
|
|
|
|
|
|
|
if (!focusedWidget || selectedWidgets.indexOf(focusedWidgetId) > -1) return;
|
|
|
|
|
|
|
|
|
|
return getWidgetNameState(focusedWidget, dataTree, positions, true);
|
|
|
|
|
},
|
|
|
|
|
);
|