PromucFlow_constructor/app/client/src/utils/hooks/useDynamicAppLayout.tsx
Pawan Kumar 8395f5e18f
feat: property pane docking (#7361)
* add tailwindcss

* docked property pane

* uncomment a line

* make entity explorer as drawer on unpin

* remove unused imports

* add pin state in  reducer

* add menu icon in header

* fix widget sidebar

* fix widgets sidebar

* style property pane

* update property pane css

* update icons in property pane

* update property pane header styles

* update spacing

* fix few ui issues

* wip: preview mode

* wip:preview mode

* remove unused import

* comments sidebar in app and edit mode

* fix order of import

* use selected state for property pane

* update scrollbar style

* add classes to sidebar and property pane

* make widgets editor fluid

* make widgets editor fluid and refactor logic

* resize the widgets editor if explorer is pinned

* add shortcut for preview mode

* fix link for tabs in edit mode

* zoom in/zoom out for 0.75

* fix chart widget + table widget crashing

* allow zooming of canvas

* fix weird canvas draw issue + update container for handling zoom

* add actions for is panning

* allow panning with grab cursor

* reset panning + zooming when entering preview mode

* add grabbing cursor when grabbing

* only prevent default when space key is pressed

* dont allow zoom in preview mode

* remove unused imports

* fix dont allow zoom in preview mode

* fix ux of panning on space hit

* make fluid as the default app layout

* chart spec

* fix dropdown_on change spec

* fix add widget table and bind spec

* remove draggable property pane spec

* fix container spec

* fix form widget spec

* fix jest test

* fix the function typo

* remove clicking of close button for property pane in cypress tests

* remove property pane actions test

* fix drag and drop test failing

* add cypress selector id to back button in property pane

* fix toggle js spec

* fix merge conflicts from new design system

* editor header

* fix product updates styles + widget card

* remove all unused imports

* fix dynamic layout spec

* fix entity explorer tab rename test failing

* fix table spec

* fix bind tabletextpagination spec

* fix js object spec

* fix entity explorer rename issue

* fix cypress test

* fix cypress command wrong commit

* fix tab spec

* fix property pane copy tests

* add zoom header

* zoom levels

* make property pane sidebar resizable

* add multi select property pane

* fix widget search bug

* update property pane width in state on drag end

* fix viewer header

* fix editor header

* update editor header + remove zooming

* update small style

* dont allow closing of explorer when resizing

* fix jest test

* fix dropdown widget jest test

* preview test case wip

* add entity explorer pinning tests + preview mode tests

* add tooltip in layout control + add padding bottom in property pane view

* incorporate aakash feedbacks

* fix preview mode margin issue

* remove panning code

* fix cypress failing test

* uncomment jest test

* remove redundant code

* fix maincontainer test

* incorporate review feedbacks

* incorporate aakash feedbacks

* review feedbacks

* incorporate review feedbacks

* incorporate qa feedbacks

* fix dynamic layout spec

* updated test based on latest change

* dsl updated

* Updated dsl

* Updated dsl

* resize deselects widget issue.

* fix canvas height issue

* fix typo

* incorporate qa feedbacks

* incorporate qa feedbacks

* incorporate qa feedbacks

* update color for setting control for widget name

* fix onboarding styles conflicts

* Updated tests

* fix application overflow issue

* updated test method

Co-authored-by: root <root@DESKTOP-9GENCK0.localdomain>
Co-authored-by: Pawan Kumar <pawankumar@Pawans-MacBook-Pro.local>
Co-authored-by: Ashok Kumar M <35134347+marks0351@users.noreply.github.com>
Co-authored-by: Apple <nandan@thinkify.io>
2021-11-23 13:31:46 +05:30

194 lines
5.6 KiB
TypeScript

import { debounce, get } from "lodash";
import { useDispatch, useSelector } from "react-redux";
import { useCallback, useEffect, useMemo, useState } from "react";
import { getWidgetByID, getWidgets } from "sagas/selectors";
import {
DefaultLayoutType,
layoutConfigurations,
MAIN_CONTAINER_WIDGET_ID,
} from "constants/WidgetConstants";
import {
getExplorerPinned,
getExplorerWidth,
} from "selectors/explorerSelector";
import {
getCurrentApplicationLayout,
getCurrentPageId,
previewModeSelector,
} from "selectors/editorSelectors";
import { APP_MODE } from "entities/App";
import { scrollbarWidth } from "utils/helpers";
import { useWindowSizeHooks } from "./dragResizeHooks";
import { getAppMode } from "selectors/entitiesSelector";
import { updateCanvasLayoutAction } from "actions/editorActions";
import { calculateDynamicHeight } from "utils/DSLMigrations";
const BORDERS_WIDTH = 2;
const GUTTER_WIDTH = 72;
export const useDynamicAppLayout = () => {
const dispatch = useDispatch();
const [initialized, setInitialized] = useState(false);
const explorerWidth = useSelector(getExplorerWidth);
const isExplorerPinned = useSelector(getExplorerPinned);
const appMode: APP_MODE | undefined = useSelector(getAppMode);
const domEntityExplorer = document.querySelector(".js-entity-explorer");
const domPropertyPane = document.querySelector(".js-property-pane-sidebar");
const { height: screenHeight, width: screenWidth } = useWindowSizeHooks();
const mainContainer = useSelector(getWidgetByID(MAIN_CONTAINER_WIDGET_ID));
const isPreviewMode = useSelector(previewModeSelector);
const currentPageId = useSelector(getCurrentPageId);
const canvasWidgets = useSelector(getWidgets);
const appLayout = useSelector(getCurrentApplicationLayout);
/**
* calculates min height
*/
const calculatedMinHeight = useMemo(() => {
return calculateDynamicHeight(canvasWidgets, mainContainer?.minHeight);
}, [mainContainer]);
/**
* app layout range i.e minWidth and maxWidth for the current layout
* if there is no config for the current layout, use default layout i.e desktop
*/
const layoutWidthRange = useMemo(() => {
let minWidth = -1;
let maxWidth = -1;
if (appLayout) {
const { type } = appLayout;
const currentLayoutConfig = get(
layoutConfigurations,
type,
layoutConfigurations[DefaultLayoutType],
);
if (currentLayoutConfig.minWidth) minWidth = currentLayoutConfig.minWidth;
if (currentLayoutConfig.maxWidth) maxWidth = currentLayoutConfig.maxWidth;
}
return { minWidth, maxWidth };
}, [appLayout]);
/**
* calculate the width for the canvas
*
* cases:
* - if max width is negative, use calculated width
* - if calculated width is in range of min/max widths of layout, use calculated width
* - if calculated width is less then min width, use min Width
* - if calculated width is larger than max width, use max width
* - by default use min width
*
* @param screenWidth
* @param layoutMaxWidth
* @returns
*/
const calculateCanvasWidth = () => {
const { maxWidth, minWidth } = layoutWidthRange;
let calculatedWidth = screenWidth - scrollbarWidth();
// if preview mode is on, we don't need to subtract the Property Pane width
if (isPreviewMode === false) {
const propertyPaneWidth = domPropertyPane?.clientWidth || 0;
calculatedWidth -= propertyPaneWidth;
}
// if explorer is unpinned or its preview mode, we don't need to subtract the EE width
if (isExplorerPinned === true && isPreviewMode === false) {
const explorerWidth = domEntityExplorer?.clientWidth || 0;
calculatedWidth -= explorerWidth;
}
switch (true) {
case maxWidth < 0:
case appLayout?.type === "FLUID":
case calculatedWidth < maxWidth && calculatedWidth > minWidth:
return (
calculatedWidth -
(appMode === APP_MODE.EDIT && !isPreviewMode
? BORDERS_WIDTH + GUTTER_WIDTH
: 0)
);
case calculatedWidth < minWidth:
return minWidth;
case calculatedWidth > maxWidth:
return maxWidth;
default:
return minWidth;
}
};
/**
* resizes the layout based on the layout type
*
* @param screenWidth
* @param appLayout
*/
const resizeToLayout = () => {
const calculatedWidth = calculateCanvasWidth();
const { rightColumn } = mainContainer || {};
if (rightColumn !== calculatedWidth) {
dispatch(
updateCanvasLayoutAction(calculatedWidth, mainContainer?.minHeight),
);
}
};
const debouncedResize = useCallback(debounce(resizeToLayout, 250), [
mainContainer,
screenWidth,
]);
/**
* when screen height is changed, update canvas layout
*/
useEffect(() => {
if (calculatedMinHeight !== mainContainer?.minHeight) {
dispatch(
updateCanvasLayoutAction(
mainContainer?.rightColumn,
calculatedMinHeight,
),
);
}
}, [screenHeight, mainContainer?.minHeight]);
useEffect(() => {
debouncedResize();
}, [screenWidth]);
/**
* resize the layout if any of the following thing changes:
* - app layout
* - page
* - container right column
* - preview mode
* - explorer width
* - explorer is pinned
*/
useEffect(() => {
resizeToLayout();
}, [
appLayout,
currentPageId,
mainContainer?.rightColumn,
isPreviewMode,
explorerWidth,
isExplorerPinned,
initialized,
]);
/**
* calling the setInitialized here so that property pane width is initialized
*/
useEffect(() => {
setInitialized(true);
});
};