PromucFlow_constructor/app/client/src/utils/hooks/useDynamicAppLayout.tsx
Pawan Kumar 809a633306
feat: App Theming (#9714)
* fix style bugs

* fix select styles

* test: fix font size issue for cypress tests

* incorporate ashit feedback

* test: addresed review comments for cypress tests

* add analytics events

* height issue in view mode

* incorporate code review feedbacks

* incorporate code review feedbacks

* refactor: addressed review comments; removed border radius and box shadow for text widget; Updated migrations

* feat: Makes shadow and radius controls keyboard accessible (#11547)

* makes shadow and radius controls keyboard accessible

* removes unused imports

* moves options out of render method

* fix: changed the misnomer background property name to the relevant property name

* fix: border radius issue for the map widget

* address qa bugs

* address qa bugs

* fix ux of theming pane when widget is selected

* fix:
* added backgroundColor to the video widget
* restricted pop-over border radius to 0.375rem
* added box shadow for the input group for select widget

* fix: added delete icon in the delete theme modal

* address qa bugs

* change checkbox column size in config

* add js convertible to button color

* remove unused imports

* test: fixed jest tests

* fix primary color typo

* fix: migrations for the theming

* fix:
* Removed background color from MultiTreeSelect and TreeSelect component.
* grouped button's menu button pop over border radius restricting to 0.375rem.

* test: updated Dsl migration UT

* address qa bugs

* address qa bugs

* fix: address qa comments

* address qa bugs

* fix:
* migration issue;
* unit test cases;

* fix rating widget scroll issue

* fix youtube video border radius bug

* fix select widget

* fix select widgets styles

* address qa bugs

* merge conflicts

* makes the reset button keyboard accessible (#12134)

* -resolved merge conflicts

* address qa bugs

* fix: labelTextSize migration fixes

* refactor:
* made changes to the fontSizeUtils function
* fixed the issue related to unit tests

* fix button group widget

* remove unused imports

* fix: fixed the text size migration for the table widget

* refactor: addressed review comments for the table widget theming migration

* fix button group widget

* add init calls for view mode

* json form init theme changes

* fix: added migration for boxShadow, borderRadius and textSizes for table widget

* fix broken fields

* test: fixed unit tests

* wip

* inconsistancy fixes and schemaItem update in updateHook/fieldConfiguration

* feat: init json form migration theming

* json form primaryColor -> accentColor

* update table widget

* update table widget

* object field label styling

* fix: migration related to the JSON form

* fix: fixed labelTextSize migration for JSON form nested widgets

* property control nested stylesheet lookup

* JSONForm label styles form array items

* show label for checkbox field array item

* fix button group widget

* wip

* refactor: addressed table widget review comments

* refactor: addressed ashit review comments;
* added childStylesheet for widgets

* feat: Keyboard navigable Color Picker control (#11797)

* Makes ColorPicker keyboard accessible

* seperate out keyboard and mouse interactions

* fix issue with not focusing back to input

* Adds test for Color picker

* chore: added comment for the boxShadow property

* fix:
* added unit test cases for the widget and property utils
* resolved warning messages

* wip

* theme config update

* fix merge conflicts

* refactor: moved theming migration inside the migrations folder

* fix qa bugs

* fix jest test

* fix: unit test cases

* fix table column creation logic

* refactor: addressed review comments for migrations

* fix: Overriding margin and padding for custom render in the dropdown component (#12875)

* * fix for custom render padding and margin in ADS dropdown

* * fix for removing padding from normal render options

* refactor: moved the boxShadow condition to the variable

* fix qa bugs

* fix: migration QA callouts for audio recorder widget

* refactor: added updated comments for boxShadow migration for table widget

* fix theme binfings for JSONForm fields under Object

* fix table widget theming bug

* fix: addressed code review comments

* fix: unit test cases

* fix: qa migration callouts

* fix table widget theming bug

* fix JSONForm currency input dropdown not submit form

* Added new tests - AppThemingSpec

* fix qa bugs

* fix unit test

* fix JSONForm cellBorderWidth to have default value post migration

* fix unit test

* fix qa bugs

* remove unused imports

* fix qa bugs

* fix JSONForm input height issue

* fix qa bugs

* Updating Theming spec

* * dropdown color fixes (#13249)

* fix caching issue
;

* Fixed Theming tests

* fix tests

* fix tab widget tests

* fix: json form children level migration issue

* fix table widget tests

* Updated test

* updated tests

* updated test

* updated tests

* updated tests

* updated pageload

* fix cypress tests

* remove cypress created files

* fix color picker issues

* Failure fixes

* Fixed some more tests

* fix: cypress test failures

* fix tests

* remove consoles

* fix table tests

* fix qa bugs

* updating snapshots for AppPageLayout_spec as per new UI

* fix rating widget bug

* fix qa bugs

* fix:
* cypress failing tests
* Migration QA callouts
* Removed unused imports

* update constract check algo

* fix color contrast issue

* fix: cypress failure test cases

* update font sizes labels

* fix regression bugs

* fix:
* JSON form labelTextSize issue fix
* Updated comment for the fontSizeUtility function
* migrations issues related to table widget borderRadius and boxShadow

* fix: default labelTextSize issue for the Input and Select families

* fix regression bugs

* fix regression bugs

* PassingParams spec - added wait time

* fix: font family default value issue on JS toggle

* fix js toggle issue in text widget

* fix tests

* fix tests

* fix tests

* fix cypress tests

* fix regression bugs

* fix regression bugs

* fix:
* refactored table widget migration function as per review comments,
* added default value to the widget

* fix: failing unit test cases

* fix theming spec

* fix cypress tests

* test: fixed failed cypress test

* incorporate ashit feedback

* fix cypress tests

* fix: addressed review comments

* comment out table cypress test

* fix merge conflicts

* comment out color picker tests

Co-authored-by: Pawan Kumar <pawankumar@Pawans-MacBook-Pro.local>
Co-authored-by: keyurparalkar <keyur@appsmith.com>
Co-authored-by: Aswath K <aswath@appsmith.com>
Co-authored-by: Nayan <nayan@appsmith.com>
Co-authored-by: Ashit Rath <ashit@appsmith.com>
Co-authored-by: balajisoundar <balaji@appsmith.com>
Co-authored-by: albinAppsmith <87797149+albinAppsmith@users.noreply.github.com>
Co-authored-by: Aishwarya UR <aishwarya@appsmith.com>
Co-authored-by: apple <nandan@thinkify.io>
Co-authored-by: Parthvi Goswami <parthvigoswami@Parthvis-MacBook-Pro.local>
2022-05-04 15:15:57 +05:30

194 lines
5.7 KiB
TypeScript

import { debounce, get } from "lodash";
import { useDispatch, useSelector } from "react-redux";
import { useCallback, useEffect, useMemo, useState } from "react";
import { getWidgets } from "sagas/selectors";
import {
DefaultLayoutType,
layoutConfigurations,
} from "constants/WidgetConstants";
import {
getExplorerPinned,
getExplorerWidth,
} from "selectors/explorerSelector";
import {
getCurrentApplicationLayout,
getCurrentPageId,
getMainCanvasProps,
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 mainCanvasProps = useSelector(getMainCanvasProps);
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, mainCanvasProps?.height);
}, [mainCanvasProps]);
/**
* 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 closed or its preview mode, we don't need to subtract the EE width
if (isExplorerPinned === true && !isPreviewMode) {
const explorerWidth = domEntityExplorer?.clientWidth || 0;
calculatedWidth -= explorerWidth;
}
switch (true) {
case maxWidth < 0:
case appLayout?.type === "FLUID":
case calculatedWidth < maxWidth && calculatedWidth > minWidth:
const totalWidthToSubtract = BORDERS_WIDTH + GUTTER_WIDTH;
// NOTE: gutter + border width will be only substracted when theme mode and preview mode are off
return (
calculatedWidth -
(appMode === APP_MODE.EDIT && !isPreviewMode
? totalWidthToSubtract
: 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 { width: rightColumn } = mainCanvasProps || {};
if (rightColumn !== calculatedWidth) {
dispatch(
updateCanvasLayoutAction(calculatedWidth, mainCanvasProps?.height),
);
}
};
const debouncedResize = useCallback(debounce(resizeToLayout, 250), [
mainCanvasProps,
screenWidth,
]);
/**
* when screen height is changed, update canvas layout
*/
useEffect(() => {
if (calculatedMinHeight !== mainCanvasProps?.height) {
dispatch(
updateCanvasLayoutAction(mainCanvasProps?.width, calculatedMinHeight),
);
}
}, [screenHeight, mainCanvasProps?.height]);
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
* - theme mode is turned on
*/
useEffect(() => {
resizeToLayout();
}, [
appLayout,
currentPageId,
mainCanvasProps?.width,
isPreviewMode,
explorerWidth,
isExplorerPinned,
initialized,
]);
/**
* calling the setInitialized here so that property pane width is initialized
*/
useEffect(() => {
setInitialized(true);
});
};