Fix: Dynamic Canvas Height based on bottom most widget. (#3398)
* Fix: Dynamic Canvas Height based on bottom most widget. * Checking cytest failure reason. * Revert "Checking cytest failure reason." This reverts commit 2e3aaa882b282e10e1cf491633101293b72ffa89. * Using UPDATE_CANVAS_LAYOUT to update the layout. * Remove unwanted declarations. * Adding comments.
This commit is contained in:
parent
e1fb1203b5
commit
fc34901be8
|
|
@ -79,6 +79,7 @@ export interface UpdateWidgetPropertyPayload {
|
|||
|
||||
export interface UpdateCanvasLayout {
|
||||
width: number;
|
||||
height: number;
|
||||
}
|
||||
|
||||
export interface SetWidgetDynamicPropertyPayload {
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { FetchPageRequest, SavePageResponse } from "api/PageApi";
|
||||
import { FetchPageRequest, PageLayout, SavePageResponse } from "api/PageApi";
|
||||
import { WidgetOperation } from "widgets/BaseWidget";
|
||||
import { WidgetType } from "constants/WidgetConstants";
|
||||
import {
|
||||
|
|
@ -113,7 +113,11 @@ export const saveLayout = () => {
|
|||
};
|
||||
};
|
||||
|
||||
export const createPage = (applicationId: string, pageName: string) => {
|
||||
export const createPage = (
|
||||
applicationId: string,
|
||||
pageName: string,
|
||||
layouts: Partial<PageLayout>[],
|
||||
) => {
|
||||
AnalyticsUtil.logEvent("CREATE_PAGE", {
|
||||
pageName,
|
||||
});
|
||||
|
|
@ -122,6 +126,7 @@ export const createPage = (applicationId: string, pageName: string) => {
|
|||
payload: {
|
||||
applicationId,
|
||||
name: pageName,
|
||||
layouts,
|
||||
},
|
||||
};
|
||||
};
|
||||
|
|
|
|||
|
|
@ -61,6 +61,7 @@ export interface SavePageResponse extends ApiResponse {
|
|||
export interface CreatePageRequest {
|
||||
applicationId: string;
|
||||
name: string;
|
||||
layouts: Partial<PageLayout>[];
|
||||
}
|
||||
|
||||
export interface UpdatePageRequest {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import { WidgetProps } from "widgets/BaseWidget";
|
||||
import { PropertyPaneConfig } from "constants/PropertyControlConstants";
|
||||
import { get } from "lodash";
|
||||
import { FlattenedWidgetProps } from "reducers/entityReducers/canvasWidgetsReducer";
|
||||
|
||||
export const getAllPathsFromPropertyConfig = (
|
||||
widget: WidgetProps,
|
||||
|
|
@ -113,3 +114,18 @@ export const getAllPathsFromPropertyConfig = (
|
|||
|
||||
return { bindingPaths, triggerPaths };
|
||||
};
|
||||
|
||||
export const nextAvailableRowInContainer = (
|
||||
parenContainertId: string,
|
||||
canvasWidgets: { [widgetId: string]: FlattenedWidgetProps },
|
||||
) => {
|
||||
return (
|
||||
Object.values(canvasWidgets).reduce(
|
||||
(prev: number, next: any) =>
|
||||
next?.parentId === parenContainertId && next.bottomRow > prev
|
||||
? next.bottomRow
|
||||
: prev,
|
||||
0,
|
||||
) + 1
|
||||
);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ import { AppState } from "reducers";
|
|||
import { CanvasStructure } from "reducers/uiReducers/pageCanvasStructureReducer";
|
||||
import { Datasource } from "entities/Datasource";
|
||||
import { Plugin } from "api/PluginApi";
|
||||
import { extractCurrentDSL } from "utils/WidgetPropsUtils";
|
||||
|
||||
type ExplorerPageGroupProps = {
|
||||
searchKeyword?: string;
|
||||
|
|
@ -47,7 +48,11 @@ export const ExplorerPageGroup = memo((props: ExplorerPageGroupProps) => {
|
|||
"Page",
|
||||
pages.map((page: Page) => page.pageName),
|
||||
);
|
||||
dispatch(createPage(params.applicationId, name));
|
||||
// Default layout is extracted by adding dynamically computed properties like min-height.
|
||||
const defaultPageLayouts = [
|
||||
{ dsl: extractCurrentDSL(), layoutOnLoadActions: [] },
|
||||
];
|
||||
dispatch(createPage(params.applicationId, name, defaultPageLayouts));
|
||||
}, [dispatch, pages, params.applicationId]);
|
||||
|
||||
const pageEntities = pages.map((page) => {
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@ const canvasWidgetsReducer = createImmerReducer(initialState, {
|
|||
action: ReduxAction<UpdateCanvasLayout>,
|
||||
) => {
|
||||
set(state[MAIN_CONTAINER_WIDGET_ID], "rightColumn", action.payload.width);
|
||||
set(state[MAIN_CONTAINER_WIDGET_ID], "minHeight", action.payload.height);
|
||||
},
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -94,7 +94,10 @@ import { WidgetBlueprint } from "reducers/entityReducers/widgetConfigReducer";
|
|||
import { Toaster } from "components/ads/Toast";
|
||||
import { Variant } from "components/ads/common";
|
||||
import { ColumnProperties } from "components/designSystems/appsmith/TableComponent/Constants";
|
||||
import { getAllPathsFromPropertyConfig } from "entities/Widget/utils";
|
||||
import {
|
||||
getAllPathsFromPropertyConfig,
|
||||
nextAvailableRowInContainer,
|
||||
} from "entities/Widget/utils";
|
||||
import { getAllPaths } from "workers/evaluationUtils";
|
||||
import {
|
||||
createMessage,
|
||||
|
|
@ -1114,21 +1117,12 @@ function* copyWidgetSaga(action: ReduxAction<{ isShortcut: boolean }>) {
|
|||
export function calculateNewWidgetPosition(
|
||||
widget: WidgetProps,
|
||||
parentId: string,
|
||||
canvasWidgets: FlattenedWidgetProps[],
|
||||
canvasWidgets: { [widgetId: string]: FlattenedWidgetProps },
|
||||
) {
|
||||
// Note: This is a very simple algorithm.
|
||||
// We take the bottom most widget in the canvas, then calculate the top,left,right,bottom
|
||||
// co-ordinates for the new widget, such that it can be placed at the bottom of the canvas.
|
||||
const nextAvailableRow =
|
||||
Object.values(canvasWidgets).reduce(
|
||||
(prev: number, next: any) =>
|
||||
next.widgetId !== widget.parentId &&
|
||||
next.parentId === parentId &&
|
||||
next.bottomRow > prev
|
||||
? next.bottomRow
|
||||
: prev,
|
||||
0,
|
||||
) + 1;
|
||||
const nextAvailableRow = nextAvailableRowInContainer(parentId, canvasWidgets);
|
||||
return {
|
||||
leftColumn: 0,
|
||||
rightColumn: widget.rightColumn - widget.leftColumn,
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ import {
|
|||
} from "widgets/BaseWidget";
|
||||
import {
|
||||
GridDefaults,
|
||||
MAIN_CONTAINER_WIDGET_ID,
|
||||
RenderMode,
|
||||
WidgetType,
|
||||
WidgetTypes,
|
||||
|
|
@ -28,6 +29,7 @@ import {
|
|||
} from "utils/migrations/TableWidget";
|
||||
import { migrateIncorrectDynamicBindingPathLists } from "utils/migrations/IncorrectDynamicBindingPathLists";
|
||||
import * as Sentry from "@sentry/react";
|
||||
import { nextAvailableRowInContainer } from "entities/Widget/utils";
|
||||
|
||||
export type WidgetOperationParams = {
|
||||
operation: WidgetOperation;
|
||||
|
|
@ -351,13 +353,45 @@ function migrateOldChartData(currentDSL: ContainerWidgetProps<WidgetProps>) {
|
|||
return currentDSL;
|
||||
}
|
||||
|
||||
export const calculateDynamicHeight = (
|
||||
canvasWidgets: {
|
||||
[widgetId: string]: FlattenedWidgetProps;
|
||||
} = {},
|
||||
presentMinimumHeight = CANVAS_DEFAULT_HEIGHT_PX,
|
||||
) => {
|
||||
let minmumHeight = presentMinimumHeight;
|
||||
const nextAvailableRow = nextAvailableRowInContainer(
|
||||
MAIN_CONTAINER_WIDGET_ID,
|
||||
canvasWidgets,
|
||||
);
|
||||
const screenHeight = window.innerHeight;
|
||||
const gridRowHeight = GridDefaults.DEFAULT_GRID_ROW_HEIGHT;
|
||||
const calculatedCanvasHeight = nextAvailableRow * gridRowHeight;
|
||||
// DGRH - DEFAULT_GRID_ROW_HEIGHT
|
||||
// View Mode: Header height + Page Selection Tab = 2 * DGRH (approx)
|
||||
// Edit Mode: Header height + Canvas control = 2 * DGRH (approx)
|
||||
// buffer = DGRH, it's not 2 * DGRH coz we already add a buffer on the canvas which is also equal to DGRH.
|
||||
const buffer = gridRowHeight;
|
||||
const calculatedMinHeight =
|
||||
Math.floor((screenHeight - buffer) / gridRowHeight) * gridRowHeight;
|
||||
if (
|
||||
calculatedCanvasHeight < screenHeight &&
|
||||
calculatedMinHeight !== presentMinimumHeight
|
||||
) {
|
||||
minmumHeight = calculatedMinHeight;
|
||||
}
|
||||
return minmumHeight;
|
||||
};
|
||||
|
||||
// A rudimentary transform function which updates the DSL based on its version.
|
||||
// A more modular approach needs to be designed.
|
||||
const transformDSL = (currentDSL: ContainerWidgetProps<WidgetProps>) => {
|
||||
if (currentDSL.version === undefined) {
|
||||
// Since this top level widget is a CANVAS_WIDGET,
|
||||
// DropTargetComponent needs to know the minimum height the canvas can take
|
||||
// See DropTargetUtils.ts
|
||||
currentDSL.minHeight = CANVAS_DEFAULT_HEIGHT_PX;
|
||||
currentDSL.minHeight = calculateDynamicHeight();
|
||||
|
||||
// For the first time the DSL is created, remove one row from the total possible rows
|
||||
// to adjust for padding and margins.
|
||||
currentDSL.snapRows =
|
||||
|
|
@ -446,9 +480,9 @@ const transformDSL = (currentDSL: ContainerWidgetProps<WidgetProps>) => {
|
|||
};
|
||||
|
||||
export const extractCurrentDSL = (
|
||||
fetchPageResponse: FetchPageResponse,
|
||||
fetchPageResponse?: FetchPageResponse,
|
||||
): ContainerWidgetProps<WidgetProps> => {
|
||||
const currentDSL = fetchPageResponse.data.layouts[0].dsl || defaultDSL;
|
||||
const currentDSL = fetchPageResponse?.data.layouts[0].dsl || defaultDSL;
|
||||
return transformDSL(currentDSL);
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -3,25 +3,30 @@ import { ReduxActionTypes } from "constants/ReduxActionConstants";
|
|||
import {
|
||||
DefaultLayoutType,
|
||||
layoutConfigurations,
|
||||
MAIN_CONTAINER_WIDGET_ID,
|
||||
} from "constants/WidgetConstants";
|
||||
import { debounce } from "lodash";
|
||||
import { AppsmithDefaultLayout } from "pages/Editor/MainContainerLayoutControl";
|
||||
import { useCallback, useEffect } from "react";
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
import { AppState } from "reducers";
|
||||
import { getWidget } from "sagas/selectors";
|
||||
import { getWidget, getWidgets } from "sagas/selectors";
|
||||
import { getAppMode } from "selectors/applicationSelectors";
|
||||
import {
|
||||
getCurrentApplicationLayout,
|
||||
getCurrentPageId,
|
||||
} from "selectors/editorSelectors";
|
||||
import { calculateDynamicHeight } from "utils/WidgetPropsUtils";
|
||||
import { useWindowSizeHooks } from "./dragResizeHooks";
|
||||
|
||||
export const useDynamicAppLayout = () => {
|
||||
const { width: screenWidth } = useWindowSizeHooks();
|
||||
const mainContainer = useSelector((state: AppState) => getWidget(state, "0"));
|
||||
const { width: screenWidth, height: screenHeight } = useWindowSizeHooks();
|
||||
const mainContainer = useSelector((state: AppState) =>
|
||||
getWidget(state, MAIN_CONTAINER_WIDGET_ID),
|
||||
);
|
||||
const currentPageId = useSelector(getCurrentPageId);
|
||||
const appMode = useSelector(getAppMode);
|
||||
const canvasWidgets = useSelector(getWidgets);
|
||||
const appLayout = useSelector(getCurrentApplicationLayout);
|
||||
const dispatch = useDispatch();
|
||||
|
||||
|
|
@ -60,6 +65,7 @@ export const useDynamicAppLayout = () => {
|
|||
type: ReduxActionTypes.UPDATE_CANVAS_LAYOUT,
|
||||
payload: {
|
||||
width: layoutWidth,
|
||||
height: mainContainer.minHeight,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
|
@ -69,6 +75,22 @@ export const useDynamicAppLayout = () => {
|
|||
mainContainer,
|
||||
]);
|
||||
|
||||
useEffect(() => {
|
||||
const calculatedMinHeight = calculateDynamicHeight(
|
||||
canvasWidgets,
|
||||
mainContainer.minHeight,
|
||||
);
|
||||
if (calculatedMinHeight !== mainContainer.minHeight) {
|
||||
dispatch({
|
||||
type: ReduxActionTypes.UPDATE_CANVAS_LAYOUT,
|
||||
payload: {
|
||||
height: calculatedMinHeight,
|
||||
width: mainContainer.rightColumn,
|
||||
},
|
||||
});
|
||||
}
|
||||
}, [screenHeight, mainContainer.minHeight]);
|
||||
|
||||
useEffect(() => {
|
||||
debouncedResize(screenWidth, appLayout);
|
||||
}, [screenWidth]);
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user