PromucFlow_constructor/app/client/src/utils/hooks/useClickToSelectWidget.tsx
ashit-rath 893fd34cdd
perf: Widget re-rendering refactor (#14485)
* initial commit

* props hoc

* changes

* removed ignores and withWidgetProps

* added extra props to canvasStructure

* widget props changes

* list widget changes

* reintroduced widget props hook and other refactors

* remove warnings

* added deepequal for childWidgets selector

* fix global hotkeys and tabs widget jest test

* fix main container test fix

* fixed view mode width

* fix form widget values

* minor fix

* fix skeleton

* form widget validity fix

* jest test fix

* fixed tests: GlobalHotkeys, Tabs, CanvasSelectectionArena and fixed main container rendering

* minor fix

* minor comments

* reverted commented code

* simplified structure, selective redux state updates and other inconsistencies

* fix junit test cases

* stop form widget from force rendering children

* fix test case

* random commit to re run tests

* update isFormValid prop only if it exists

* detangling circular dependency

* fixing cypress tests

* cleaned up code

* clean up man cnavas props and fix jest cases

* fix rendering order of child widgets for canvas

* fix dropdown reset spec

* adding comments

* cleaning up unwanted code

* fix multiselect widget on deploy

* adressing review comments

* addressing minor review comment changes

* destructuring modal widget child and fix test case

* fix communityIssues cypress spec

* rewrite isVisible logic to match previous behaviour

* merging widget props with component props before checking isVisible

* adressing review comments for modal widget's isVisible

Co-authored-by: rahulramesha <rahul@appsmith.com>
2022-08-19 15:40:36 +05:30

154 lines
4.5 KiB
TypeScript

import { get } from "lodash";
import {
getCurrentWidgetId,
getIsPropertyPaneVisible,
} from "selectors/propertyPaneSelectors";
import { getIsTableFilterPaneVisible } from "selectors/tableFilterSelectors";
import { MAIN_CONTAINER_WIDGET_ID } from "constants/WidgetConstants";
import { useSelector } from "store";
import { AppState } from "reducers";
import { CanvasWidgetsReduxState } from "reducers/entityReducers/canvasWidgetsReducer";
import { APP_MODE } from "entities/App";
import { getAppMode } from "selectors/applicationSelectors";
import { useWidgetSelection } from "./useWidgetSelection";
import React, { ReactNode, useCallback } from "react";
import { stopEventPropagation } from "utils/AppsmithUtils";
import { getFocusedParentToOpen } from "selectors/widgetSelectors";
/**
*
* @param widgetId
* @param widgets
* @returns
*/
export function getParentToOpenIfAny(
widgetId: string | undefined,
widgets: CanvasWidgetsReduxState,
) {
if (widgetId) {
let widget = get(widgets, widgetId, undefined);
// While this widget has a openParentPropertyPane equql to true
while (widget?.openParentPropertyPane) {
// Get parent widget props
const parent = get(widgets, `${widget.parentId}`, undefined);
// If parent has openParentPropertyPane = false, return the currnet parent
if (!parent?.openParentPropertyPane) {
return parent;
}
if (parent?.parentId && parent.parentId !== MAIN_CONTAINER_WIDGET_ID) {
widget = get(widgets, `${widget.parentId}`, undefined);
continue;
}
}
}
return;
}
export function ClickContentToOpenPropPane({
children,
widgetId,
}: {
widgetId: string;
children?: ReactNode;
}) {
const { focusWidget } = useWidgetSelection();
const clickToSelectWidget = useClickToSelectWidget();
const clickToSelectFn = useCallback(
(e) => {
clickToSelectWidget(e, widgetId);
},
[widgetId, clickToSelectWidget],
);
const focusedWidget = useSelector(
(state: AppState) => state.ui.widgetDragResize.focusedWidget,
);
const isResizing = useSelector(
(state: AppState) => state.ui.widgetDragResize.isResizing,
);
const isDragging = useSelector(
(state: AppState) => state.ui.widgetDragResize.isDragging,
);
const isResizingOrDragging = !!isResizing || !!isDragging;
const handleMouseOver = (e: any) => {
focusWidget &&
!isResizingOrDragging &&
focusedWidget !== widgetId &&
focusWidget(widgetId);
e.stopPropagation();
};
return (
<div
onClick={stopEventPropagation}
onClickCapture={clickToSelectFn}
onMouseOver={handleMouseOver}
style={{
width: "100%",
height: "100%",
}}
>
{children}
</div>
);
}
export const useClickToSelectWidget = () => {
const { focusWidget, selectWidget } = useWidgetSelection();
const isPropPaneVisible = useSelector(getIsPropertyPaneVisible);
const isTableFilterPaneVisible = useSelector(getIsTableFilterPaneVisible);
const selectedWidgetId = useSelector(getCurrentWidgetId);
const focusedWidgetId = useSelector(
(state: AppState) => state.ui.widgetDragResize.focusedWidget,
);
// This state tells us whether a `ResizableComponent` is resizing
const isResizing = useSelector(
(state: AppState) => state.ui.widgetDragResize.isResizing,
);
const appMode = useSelector(getAppMode);
// This state tells us whether a `DraggableComponent` is dragging
const isDragging = useSelector(
(state: AppState) => state.ui.widgetDragResize.isDragging,
);
const parentWidgetToOpen = useSelector(getFocusedParentToOpen);
const clickToSelectWidget = (e: any, targetWidgetId: string) => {
// ignore click captures
// 1. if the component was resizing or dragging coz it is handled internally in draggable component
// 2. table filter property pane is open
if (
isResizing ||
isDragging ||
appMode !== APP_MODE.EDIT ||
targetWidgetId !== focusedWidgetId ||
isTableFilterPaneVisible
)
return;
if (
(!isPropPaneVisible && selectedWidgetId === focusedWidgetId) ||
selectedWidgetId !== focusedWidgetId
) {
const isMultiSelect = e.metaKey || e.ctrlKey || e.shiftKey;
if (parentWidgetToOpen) {
selectWidget(parentWidgetToOpen.widgetId, isMultiSelect);
} else {
selectWidget(focusedWidgetId, isMultiSelect);
focusWidget(focusedWidgetId);
}
if (isMultiSelect) {
e.stopPropagation();
}
}
};
return clickToSelectWidget;
};