chore: Layout system wise restructuring of Canvas Widget (#27496)

> Pull Request Template
>
> Use this template to quickly create a well written pull request.
Delete all quotes before creating the pull request.
>
## Description

In This PR, we are cleaning up Canvas Widget implementation and taking
measures to remove it from the widget suite.
more detailed explanation of Why and How of the solution
[here](https://www.notion.so/Canvas-Widget-73776a3364ba42eb8f783c79046777d0)

In this solution we are going to remove implementation of Editing and
Layouting Specific implementation from Canvas Widget and create a new
view component which is Layout system specific.

#### PR fixes following issue(s)
Fixes #27003
#### Media
> A video or a GIF is preferred. when using Loom, don’t embed because it
looks like it’s a GIF. instead, just link to the video
>
>
#### Type of change
> Please delete options that are not relevant.
- Chore (housekeeping or task changes that don't impact user perception)
>
>
>
## Testing
>
#### How Has This Been Tested?
> Please describe the tests that you ran to verify your changes. Also
list any relevant details for your test configuration.
> Delete anything that is not relevant
- [ ] Manual
- [ ] JUnit
- [X] Jest
- [ ] Cypress
>
>
#### Test Plan
> Add Testsmith test cases links that relate to this PR
>
>
#### Issues raised during DP testing
> Link issues raised during DP testing for better visiblity and tracking
(copy link from comments dropped on this PR)
>
>
>
## Checklist:
#### Dev activity
- [ ] My code follows the style guidelines of this project
- [ ] I have performed a self-review of my own code
- [ ] I have commented my code, particularly in hard-to-understand areas
- [ ] I have made corresponding changes to the documentation
- [ ] My changes generate no new warnings
- [ ] I have added tests that prove my fix is effective or that my
feature works
- [ ] New and existing unit tests pass locally with my changes
- [ ] PR is being merged under a feature flag


#### QA activity:
- [ ] [Speedbreak
features](https://github.com/appsmithorg/TestSmith/wiki/Guidelines-for-test-plans#speedbreakers-)
have been covered
- [ ] Test plan covers all impacted features and [areas of
interest](https://github.com/appsmithorg/TestSmith/wiki/Guidelines-for-test-plans#areas-of-interest-)
- [ ] Test plan has been peer reviewed by project stakeholders and other
QA members
- [ ] Manually tested functionality on DP
- [ ] We had an implementation alignment call with stakeholders post QA
Round 2
- [ ] Cypress test cases have been added and approved by SDET/manual QA
- [ ] Added `Test Plan Approved` label after Cypress tests were reviewed
- [ ] Added `Test Plan Approved` label after JUnit tests were reviewed
This commit is contained in:
Ashok Kumar M 2023-10-04 17:23:29 +05:30 committed by GitHub
parent 62813928b5
commit 703048b7b5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
71 changed files with 1239 additions and 894 deletions

View File

@ -69,13 +69,10 @@ app/client/src/normalizers/CanvasWidgetsNormalizer.tsx @appsmithorg/ui-builders
app/client/src/pages/Editor/Canvas.tsx @appsmithorg/ui-builders app/client/src/pages/Editor/Canvas.tsx @appsmithorg/ui-builders
app/client/src/pages/Editor/CanvasLayoutConversion/* @appsmithorg/ui-builders app/client/src/pages/Editor/CanvasLayoutConversion/* @appsmithorg/ui-builders
app/client/src/pages/Editor/PropertyPane/* @appsmithorg/ui-builders app/client/src/pages/Editor/PropertyPane/* @appsmithorg/ui-builders
app/client/src/pages/Editor/WidgetsMultiSelectBox.tsx @appsmithorg/ui-builders
app/client/src/pages/common/CanvasArenas/* @appsmithorg/ui-builders
app/client/src/reducers/entityReducers/autoHeightReducers/* @appsmithorg/ui-builders app/client/src/reducers/entityReducers/autoHeightReducers/* @appsmithorg/ui-builders
app/client/src/reducers/entityReducers/canvasWidgetsReducer.ts @appsmithorg/ui-builders app/client/src/reducers/entityReducers/canvasWidgetsReducer.ts @appsmithorg/ui-builders
app/client/src/reducers/entityReducers/widgetConfigReducer.ts @appsmithorg/ui-builders app/client/src/reducers/entityReducers/widgetConfigReducer.ts @appsmithorg/ui-builders
app/client/src/reflow/* @appsmithorg/ui-builders app/client/src/reflow/* @appsmithorg/ui-builders
app/client/src/resizable/* @appsmithorg/ui-builders
app/client/src/sagas/AutoLayoutUpdateSagas.tsx @appsmithorg/ui-builders app/client/src/sagas/AutoLayoutUpdateSagas.tsx @appsmithorg/ui-builders
app/client/src/sagas/CanvasSagas/* @appsmithorg/ui-builders app/client/src/sagas/CanvasSagas/* @appsmithorg/ui-builders
app/client/src/sagas/ReplaySaga.ts @appsmithorg/ui-builders app/client/src/sagas/ReplaySaga.ts @appsmithorg/ui-builders

View File

@ -1,6 +1,6 @@
import type { ReduxAction } from "@appsmith/constants/ReduxActionConstants"; import type { ReduxAction } from "@appsmith/constants/ReduxActionConstants";
import { ReduxActionTypes } from "@appsmith/constants/ReduxActionConstants"; import { ReduxActionTypes } from "@appsmith/constants/ReduxActionConstants";
import type { XYCord } from "layoutSystems/common/CanvasArenas/ArenaTypes"; import type { XYCord } from "layoutSystems/common/canvasArenas/ArenaTypes";
import type { SelectedArenaDimensions } from "layoutSystems/fixedlayout/editor/FixedLayoutCanvasArenas/CanvasSelectionArena"; import type { SelectedArenaDimensions } from "layoutSystems/fixedlayout/editor/FixedLayoutCanvasArenas/CanvasSelectionArena";
export const setCanvasSelectionFromEditor = ( export const setCanvasSelectionFromEditor = (

View File

@ -0,0 +1,105 @@
import { RenderModes } from "constants/WidgetConstants";
import * as editorSelectors from "selectors/editorSelectors";
import { buildChildren } from "test/factories/WidgetFactoryUtils";
import { renderAppsmithCanvas } from "./CanvasFactory";
import { render } from "test/testUtils";
import React from "react";
import store from "store";
import type { WidgetProps } from "widgets/BaseWidget";
import { LayoutSystemTypes } from "./types";
import * as layoutSystemSelectors from "selectors/layoutSystemSelectors";
describe("Layout Based Canvas aka Canvas Widget Test cases", () => {
it("Render Fixed Layout Editor Canvas when layoutSystemType/appPositioningType is FIXED and render mode is CANVAS/PAGE", () => {
const children = buildChildren([
{
type: "CANVAS_WIDGET",
parentId: "xxxxxx",
children: [],
widgetId: "yyyyyy",
dynamicHeight: "FIXED",
},
]);
if (children) {
const canvasProps = children[0];
jest
.spyOn(editorSelectors, "getRenderMode")
.mockImplementation(() => RenderModes.CANVAS);
jest
.spyOn(layoutSystemSelectors, "getLayoutSystemType")
.mockImplementation(() => LayoutSystemTypes.FIXED);
const state = store.getState();
const customState = {
...state,
entities: {
...state.entities,
canvasWidgets: {
xxxxxx: {} as WidgetProps,
yyyyyy: {} as WidgetProps,
},
},
};
const editorCanvas = render(<>{renderAppsmithCanvas(canvasProps)}</>, {
initialState: customState,
});
const editorDropTarget =
editorCanvas.container.getElementsByClassName("t--drop-target")[0];
expect(editorDropTarget).toBeTruthy();
jest
.spyOn(editorSelectors, "getRenderMode")
.mockImplementation(() => RenderModes.PAGE);
const viewerCanvas = render(<>{renderAppsmithCanvas(canvasProps)}</>, {
initialState: customState,
});
const viewerDropTarget =
viewerCanvas.container.getElementsByClassName("t--drop-target")[0];
expect(viewerDropTarget).toBeFalsy();
}
});
it("Render Auto Layout Editor Canvas when layoutSystemType/appPositioningType is AUTO and render mode is CANVAS/PAGE", () => {
const children = buildChildren([
{
type: "CANVAS_WIDGET",
parentId: "xxxxxx",
children: [],
widgetId: "yyyyyy",
dynamicHeight: "FIXED",
},
]);
if (children) {
const canvasProps = children[0];
jest
.spyOn(editorSelectors, "getRenderMode")
.mockImplementation(() => RenderModes.CANVAS);
jest
.spyOn(layoutSystemSelectors, "getLayoutSystemType")
.mockImplementation(() => LayoutSystemTypes.AUTO);
const state = store.getState();
const customState = {
...state,
entities: {
...state.entities,
canvasWidgets: {
xxxxxx: {} as WidgetProps,
yyyyyy: {} as WidgetProps,
},
},
};
const editorCanvas = render(<>{renderAppsmithCanvas(canvasProps)}</>, {
initialState: customState,
});
const editorDropTarget =
editorCanvas.container.getElementsByClassName("t--drop-target")[0];
expect(editorDropTarget).toBeTruthy();
jest
.spyOn(editorSelectors, "getRenderMode")
.mockImplementation(() => RenderModes.PAGE);
const viewerCanvas = render(<>{renderAppsmithCanvas(canvasProps)}</>, {
initialState: customState,
});
const viewerDropTarget =
viewerCanvas.container.getElementsByClassName("t--drop-target")[0];
expect(viewerDropTarget).toBeFalsy();
}
});
});

View File

@ -0,0 +1,39 @@
import React, { memo, useMemo } from "react";
import { useSelector } from "react-redux";
import { getRenderMode } from "selectors/editorSelectors";
import { getLayoutSystemType } from "selectors/layoutSystemSelectors";
import type { WidgetProps } from "widgets/BaseWidget";
import withWidgetProps from "widgets/withWidgetProps";
import { getLayoutSystem } from "./withLayoutSystemWidgetHOC";
// ToDo(#27615): destructure withWidgetProps to withCanvasProps by picking only necessary props of a canvas.
/**
* Canvas of a Layout System is the module that provides necessary utilities to position and order widgets.
* Canvas also provides editing layout system specific editing experiences like Drag and Drop, Drag to Select, Widget Grouping, etc.
* This Component Hydrates canvas with enhanced properties from withWidgetProps and picks the layout system specific Canvas Implementation.
*/
const LayoutSystemBasedCanvas = memo((props: WidgetProps) => {
const renderMode = useSelector(getRenderMode);
const layoutSystemType = useSelector(getLayoutSystemType);
const { canvasSystem } = useMemo(
() => getLayoutSystem(renderMode, layoutSystemType),
[
{
renderMode,
layoutSystemType,
},
],
);
const { Canvas, propertyEnhancer } = canvasSystem;
return <Canvas {...propertyEnhancer(props)} />;
});
const HydratedLayoutSystemBasedCanvas = withWidgetProps(
LayoutSystemBasedCanvas as any,
);
export const renderAppsmithCanvas = (props: WidgetProps) => {
return <HydratedLayoutSystemBasedCanvas {...props} />;
};

View File

@ -20,10 +20,5 @@ export const AnvilEditorWrapper = (props: WidgetProps) => {
: AnvilEditorWidgetOnion; : AnvilEditorWidgetOnion;
}, [props.type]); }, [props.type]);
//Canvas_Onion
if (props.type === "CANVAS_WIDGET") {
return props.children;
}
return <WidgetOnion {...props}>{props.children}</WidgetOnion>; return <WidgetOnion {...props}>{props.children}</WidgetOnion>;
}; };

View File

@ -52,7 +52,7 @@ const getAnvilSystemWrapper = (renderMode: RenderModes) => {
return AnvilViewerWrapper; return AnvilViewerWrapper;
}; };
export function getAnvilSystem(renderMode: RenderModes) { export function getAnvilLayoutSystem(renderMode: RenderModes) {
return { return {
LayoutSystemWrapper: getAnvilSystemWrapper(renderMode), LayoutSystemWrapper: getAnvilSystemWrapper(renderMode),
propertyEnhancer: getAnvilSystemPropsEnhancer, propertyEnhancer: getAnvilSystemPropsEnhancer,

View File

@ -19,9 +19,5 @@ export const AnvilViewerWrapper = (props: WidgetProps) => {
: AnvilViewerWidgetOnion; : AnvilViewerWidgetOnion;
}, [props.type]); }, [props.type]);
if (props.type === "CANVAS_WIDGET") {
return props.children;
}
return <WidgetOnion {...props}>{props.children}</WidgetOnion>; return <WidgetOnion {...props}>{props.children}</WidgetOnion>;
}; };

View File

@ -1,187 +0,0 @@
import { layoutConfigurations } from "constants/WidgetConstants";
import React, { useEffect, useRef } from "react";
import { useDispatch, useSelector } from "react-redux";
import { getCurrentApplicationLayout } from "selectors/editorSelectors";
import { setAutoCanvasResizing } from "actions/autoLayoutActions";
import styled from "styled-components";
import { AUTOLAYOUT_RESIZER_WIDTH_BUFFER } from "utils/hooks/useDynamicAppLayout";
import { importSvg } from "design-system-old";
import { CANVAS_VIEWPORT } from "constants/componentClassNameConstants";
const CanvasResizerIcon = importSvg(
() => import("assets/icons/ads/app-icons/canvas-resizer.svg"),
);
const AutoLayoutCanvasResizer = styled.div`
position: sticky;
cursor: col-resize;
width: 2px;
height: 100%;
display: flex;
background: var(--ads-v2-color-border);
align-items: center;
justify-content: flex-start;
margin-left: 2px;
transition: width 300ms ease;
transition: background 300ms ease;
.canvas-resizer-icon {
border-left: 2px solid;
border-color: var(--ads-v2-color-border);
transition: border 300ms ease;
margin-left: 2px;
& > svg {
fill: var(--ads-v2-color-border);
transition: fill 300ms ease;
}
}
&:hover,
&:active {
width: 3px;
transition: width 300ms ease;
background: #ff9b4e;
transition: background 300ms ease;
.canvas-resizer-icon {
border-color: #ff9b4e;
transition: border 300ms ease;
& > svg {
fill: #ff9b4e;
transition: fill 300ms ease;
}
}
}
`;
/**
* OldName: CanvasResizer
*/
export function MainContainerResizer({
currentPageId,
enableMainCanvasResizer,
heightWithTopMargin,
isPageInitiated,
isPreviewMode,
shouldHaveTopMargin,
}: {
heightWithTopMargin: string;
isPageInitiated: boolean;
shouldHaveTopMargin: boolean;
isPreviewMode: boolean;
currentPageId: string;
enableMainCanvasResizer: boolean;
}) {
const appLayout = useSelector(getCurrentApplicationLayout);
const ref = useRef(null);
const dispatch = useDispatch();
useEffect(() => {
const ele: any = document.getElementById(CANVAS_VIEWPORT);
if (isPageInitiated && enableMainCanvasResizer) {
const buffer = isPreviewMode ? AUTOLAYOUT_RESIZER_WIDTH_BUFFER : 0;
const fullWidthCSS = `calc(100% - ${AUTOLAYOUT_RESIZER_WIDTH_BUFFER}px)`;
const wrapperElement: any = document.getElementById("widgets-editor");
let maxWidth =
wrapperElement.offsetWidth - AUTOLAYOUT_RESIZER_WIDTH_BUFFER;
if (ele && ele.offsetWidth >= maxWidth) {
ele.style.width = fullWidthCSS;
}
if (appLayout?.type === "FLUID") {
const smallestWidth = layoutConfigurations.MOBILE.minWidth;
// The current position of mouse
let x = 0;
// let y = 0;
// The dimension of the element
let w = 0;
// let h = 0;
let events: any = [];
// Handle the mousedown event
// that's triggered when user drags the resizer
const mouseDownHandler = function (e: any) {
maxWidth =
wrapperElement.offsetWidth - AUTOLAYOUT_RESIZER_WIDTH_BUFFER;
// Get the current mouse position
x = e.clientX;
// y = e.clientY;
// Calculate the dimension of element
const styles = window.getComputedStyle(ele);
dispatch(setAutoCanvasResizing(true));
w = parseInt(styles.width, 10) + buffer;
// h = parseInt(styles.height, 10);
const mouseMove = (e: any) => mouseMoveHandler(e);
events.push(mouseMove);
// Attach the listeners to `document`
document.addEventListener("mousemove", mouseMove);
document.addEventListener("mouseup", mouseUpHandler);
// e.stopPropagation();
};
const mouseMoveHandler = function (e: any) {
// How far the mouse has been moved
// const multiplier = rightHandle ? 2 : -2;
const multiplier = 2;
const dx = (e.clientX - x) * multiplier;
if (maxWidth >= w + dx && smallestWidth <= w + dx) {
// Adjust the dimension of element
ele.style.width = `${w + dx}px`;
}
if (maxWidth < w + dx) {
ele.style.width = fullWidthCSS;
}
if (smallestWidth > w + dx) {
ele.style.width = `${smallestWidth}px`;
}
// e.stopPropagation();
};
const mouseUpHandler = function (e: any) {
// Remove the handlers of `mousemove` and `mouseup`
mouseMoveHandler(e);
dispatch(setAutoCanvasResizing(false));
document.removeEventListener("mousemove", events[0] as any);
document.removeEventListener("mouseup", mouseUpHandler);
events = [];
};
const rightResizer: any = ref.current;
const rightMove = (e: any) => mouseDownHandler(e);
rightResizer && rightResizer.addEventListener("mousedown", rightMove);
return () => {
rightResizer &&
rightResizer.removeEventListener("mousedown", rightMove);
};
}
} else {
ele.style.removeProperty("width");
}
}, [
appLayout,
isPreviewMode,
currentPageId,
enableMainCanvasResizer,
isPageInitiated,
]);
return enableMainCanvasResizer ? (
<AutoLayoutCanvasResizer
className="resizer-right"
draggable
onDragStart={(e) => {
e.preventDefault();
e.stopPropagation();
}}
ref={ref}
style={{
top: "100%",
height: shouldHaveTopMargin ? heightWithTopMargin : "100vh",
}}
>
<div className="canvas-resizer-icon">
<CanvasResizerIcon />
</div>
</AutoLayoutCanvasResizer>
) : null;
}

View File

@ -0,0 +1,68 @@
import { GridDefaults } from "constants/WidgetConstants";
import type { RenderModes } from "constants/WidgetConstants";
import { renderChildren } from "layoutSystems/common/utils/canvasUtils";
import React, { useMemo } from "react";
import type { BaseWidgetProps } from "widgets/BaseWidgetHOC/withBaseWidgetHOC";
import FlexBoxComponent from "../common/flexCanvas/FlexBoxComponent";
import type { AdditionalAutoLayoutProperties } from "./types";
import type { WidgetProps } from "widgets/BaseWidget";
import type { LayoutDirection } from "layoutSystems/common/utils/constants";
/**
* This is the view component used by Canvas of Auto Layout both in Edit/View mode.
* This component is responsible for rendering the children of a canvas.
* It also adds additional layout specific properties to the children like parentColumnSpace, parentRowSpace, isFlexChild, etc.
*/
export const AutoLayoutCanvasView = ({
direction,
renderMode,
snapColumnSpace,
widgetProps,
}: {
widgetProps: BaseWidgetProps;
renderMode: RenderModes;
snapColumnSpace: number;
direction: LayoutDirection;
}) => {
// setting stretchFlexBox to true would stretch the canvas to 100% of the container widgets height when there are no children in it.
// else its set to auto height.
const stretchFlexBox = !widgetProps.children || !widgetProps.children?.length;
const layoutSystemProps: AdditionalAutoLayoutProperties = {
parentColumnSpace: snapColumnSpace,
parentRowSpace: GridDefaults.DEFAULT_GRID_ROW_HEIGHT,
};
const defaultWidgetProps: Partial<WidgetProps> = {
isFlexChild: true,
direction,
};
const canvasChildren = useMemo(
() =>
renderChildren(
widgetProps.children,
widgetProps.widgetId,
renderMode,
defaultWidgetProps,
layoutSystemProps,
),
[
widgetProps.children,
widgetProps.widgetId,
renderMode,
snapColumnSpace,
direction,
],
);
return (
<FlexBoxComponent
direction={direction}
flexLayers={widgetProps.flexLayers || []}
isMobile={widgetProps.isMobile || false}
stretchHeight={stretchFlexBox}
useAutoLayout={widgetProps.useAutoLayout || false}
widgetId={widgetProps.widgetId}
>
{canvasChildren}
</FlexBoxComponent>
);
};

View File

@ -0,0 +1,92 @@
import { CANVAS_DEFAULT_MIN_HEIGHT_PX } from "constants/AppConstants";
import { RenderModes } from "constants/WidgetConstants";
import { DropTargetComponentWrapper } from "layoutSystems/common/dropTarget/DropTargetComponentWrapper";
import { CanvasSelectionArena } from "layoutSystems/fixedlayout/editor/FixedLayoutCanvasArenas/CanvasSelectionArena";
import React, { useMemo } from "react";
import { getSnappedGrid } from "sagas/WidgetOperationUtils";
import { getCanvasSnapRows } from "utils/WidgetPropsUtils";
import type { BaseWidgetProps } from "widgets/BaseWidgetHOC/withBaseWidgetHOC";
import ContainerComponent from "widgets/ContainerWidget/component";
import { AutoCanvasDraggingArena } from "../editor/AutoLayoutCanvasArenas/AutoCanvasDraggingArena";
import { AutoLayoutCanvasView } from "./AutoLayoutCanvasView";
import { getDirection } from "./utils";
/**
* This component implements the Canvas for Auto Layout System in Edit mode.
* It renders layers like CanvasDraggingArena, CanvasSelectionArena, etc which are responsible for
* drag and drop, scrolling, etc.
*/
export const AutoLayoutEditorCanvas = (props: BaseWidgetProps) => {
const { snapGrid } = getSnappedGrid(props, props.componentWidth);
const { snapColumnSpace } = snapGrid;
const direction = getDirection(props.positioning);
const snapRows = getCanvasSnapRows(
props.bottomRow,
props.mobileBottomRow,
props.isMobile,
true,
);
const autoLayoutDropTargetProps = useMemo(
() => ({
bottomRow: props.bottomRow,
isListWidgetCanvas: props.isListWidgetCanvas,
isMobile: props.isMobile,
minHeight: props.minHeight || CANVAS_DEFAULT_MIN_HEIGHT_PX,
mobileBottomRow: props.mobileBottomRow,
noPad: props.noPad,
parentId: props.parentId,
snapColumnSpace: snapColumnSpace,
useAutoLayout: props.useAutoLayout,
widgetId: props.widgetId,
}),
[
props.bottomRow,
props.isListWidgetCanvas,
props.isMobile,
props.minHeight,
props.mobileBottomRow,
props.noPad,
props.parentId,
snapColumnSpace,
props.useAutoLayout,
props.widgetId,
],
);
return (
<DropTargetComponentWrapper
dropDisabled={props.dropDisabled}
dropTargetProps={autoLayoutDropTargetProps}
snapColumnSpace={snapColumnSpace}
>
<ContainerComponent {...props}>
<AutoCanvasDraggingArena
{...snapGrid}
alignItems={props.alignItems}
canExtend={props.canExtend}
direction={direction}
dropDisabled={!!props.dropDisabled}
noPad={props.noPad}
parentId={props.parentId}
snapRows={snapRows}
widgetId={props.widgetId}
widgetName={props.widgetName}
/>
<CanvasSelectionArena
{...snapGrid}
canExtend={props.canExtend}
dropDisabled={!!props.dropDisabled}
parentId={props.parentId}
snapRows={snapRows}
widgetId={props.widgetId}
/>
<AutoLayoutCanvasView
direction={direction}
renderMode={RenderModes.CANVAS}
snapColumnSpace={snapColumnSpace}
widgetProps={props}
/>
</ContainerComponent>
</DropTargetComponentWrapper>
);
};

View File

@ -0,0 +1,40 @@
import { RenderModes } from "constants/WidgetConstants";
import { CanvasViewerWrapper } from "layoutSystems/common/canvasViewer/CanvasViewerWrapper";
import React from "react";
import { getSnappedGrid } from "sagas/WidgetOperationUtils";
import { getCanvasSnapRows } from "utils/WidgetPropsUtils";
import type { BaseWidgetProps } from "widgets/BaseWidgetHOC/withBaseWidgetHOC";
import ContainerComponent from "widgets/ContainerWidget/component";
import { AutoLayoutCanvasView } from "./AutoLayoutCanvasView";
import { getDirection } from "./utils";
/**
* This component implements the Canvas for Auto Layout System in View mode.
*/
export const AutoLayoutViewerCanvas = (props: BaseWidgetProps) => {
const { snapGrid } = getSnappedGrid(props, props.componentWidth);
const { snapColumnSpace } = snapGrid;
const direction = getDirection(props.positioning);
const snapRows = getCanvasSnapRows(
props.bottomRow,
props.mobileBottomRow,
props.isMobile,
true,
);
return (
<CanvasViewerWrapper
isListWidgetCanvas={props.isListWidgetCanvas}
snapRows={snapRows}
>
<ContainerComponent {...props}>
<AutoLayoutCanvasView
direction={direction}
renderMode={RenderModes.PAGE}
snapColumnSpace={snapColumnSpace}
widgetProps={props}
/>
</ContainerComponent>
</CanvasViewerWrapper>
);
};

View File

@ -0,0 +1,4 @@
export type AdditionalAutoLayoutProperties = {
parentColumnSpace: number;
parentRowSpace: number;
};

View File

@ -0,0 +1,16 @@
import {
LayoutDirection,
Positioning,
} from "layoutSystems/common/utils/constants";
/**
* This utility function returns the direction of the layout based on the positioning
* @param positioning
* @returns
*/
export const getDirection = (positioning?: Positioning): LayoutDirection => {
return positioning === Positioning.Vertical
? LayoutDirection.Vertical
: LayoutDirection.Horizontal;
};

View File

@ -3,8 +3,8 @@ import React from "react";
import { useSelector } from "react-redux"; import { useSelector } from "react-redux";
import { getNearestParentCanvas } from "utils/generators"; import { getNearestParentCanvas } from "utils/generators";
import { useCanvasDragging } from "./hooks/useCanvasDragging"; import { useCanvasDragging } from "./hooks/useCanvasDragging";
import { StickyCanvasArena } from "layoutSystems/common/canvasArenas/StickyCanvasArena";
import type { LayoutDirection } from "layoutSystems/common/utils/constants"; import type { LayoutDirection } from "layoutSystems/common/utils/constants";
import { StickyCanvasArena } from "layoutSystems/common/CanvasArenas/StickyCanvasArena";
export interface AutoCanvasDraggingArenaProps { export interface AutoCanvasDraggingArenaProps {
alignItems?: string; alignItems?: string;

View File

@ -5,7 +5,7 @@ import WidgetFactory from "WidgetProvider/factory";
import type { HighlightInfo } from "layoutSystems/common/utils/types"; import type { HighlightInfo } from "layoutSystems/common/utils/types";
import { useRef } from "react"; import { useRef } from "react";
import { getIsAutoLayoutMobileBreakPoint } from "selectors/editorSelectors"; import { getIsAutoLayoutMobileBreakPoint } from "selectors/editorSelectors";
import type { WidgetDraggingBlock } from "layoutSystems/common/CanvasArenas/ArenaTypes"; import type { WidgetDraggingBlock } from "layoutSystems/common/canvasArenas/ArenaTypes";
import { deriveHighlightsFromLayers } from "layoutSystems/autolayout/utils/highlightUtils"; import { deriveHighlightsFromLayers } from "layoutSystems/autolayout/utils/highlightUtils";
import type { Point } from "layoutSystems/autolayout/utils/highlightSelectionUtils"; import type { Point } from "layoutSystems/autolayout/utils/highlightSelectionUtils";
import { getHighlightPayload } from "layoutSystems/autolayout/utils/highlightSelectionUtils"; import { getHighlightPayload } from "layoutSystems/autolayout/utils/highlightSelectionUtils";

View File

@ -8,7 +8,7 @@ import { getOccupiedSpacesWhileMoving } from "selectors/editorSelectors";
import type { WidgetSpace } from "constants/CanvasEditorConstants"; import type { WidgetSpace } from "constants/CanvasEditorConstants";
import { getDragDetails, getWidgetByID, getWidgets } from "sagas/selectors"; import { getDragDetails, getWidgetByID, getWidgets } from "sagas/selectors";
import { widgetOperationParams } from "utils/WidgetPropsUtils"; import { widgetOperationParams } from "utils/WidgetPropsUtils";
import { DropTargetContext } from "components/editorComponents/DropTargetComponent"; import { DropTargetContext } from "layoutSystems/common/dropTarget/DropTargetComponent";
import equal from "fast-deep-equal/es6"; import equal from "fast-deep-equal/es6";
import { useDispatch, useSelector } from "react-redux"; import { useDispatch, useSelector } from "react-redux";
import { ReduxActionTypes } from "@appsmith/constants/ReduxActionConstants"; import { ReduxActionTypes } from "@appsmith/constants/ReduxActionConstants";
@ -17,7 +17,7 @@ import type { DragDetails } from "reducers/uiReducers/dragResizeReducer";
import { SelectionRequestType } from "sagas/WidgetSelectUtils"; import { SelectionRequestType } from "sagas/WidgetSelectUtils";
import { useContext, useEffect, useRef } from "react"; import { useContext, useEffect, useRef } from "react";
import type { AutoCanvasDraggingArenaProps } from "../AutoCanvasDraggingArena"; import type { AutoCanvasDraggingArenaProps } from "../AutoCanvasDraggingArena";
import type { WidgetDraggingBlock } from "../../../../common/CanvasArenas/ArenaTypes"; import type { WidgetDraggingBlock } from "../../../../common/canvasArenas/ArenaTypes";
import type { HighlightInfo } from "layoutSystems/common/utils/types"; import type { HighlightInfo } from "layoutSystems/common/utils/types";
import { import {
LayoutDirection, LayoutDirection,

View File

@ -7,12 +7,12 @@ import { getTotalTopOffset } from "selectors/autoLayoutSelectors";
import { getNearestParentCanvas } from "utils/generators"; import { getNearestParentCanvas } from "utils/generators";
import { useWidgetDragResize } from "utils/hooks/dragResizeHooks"; import { useWidgetDragResize } from "utils/hooks/dragResizeHooks";
import { useAutoLayoutHighlights } from "./useAutoLayoutHighlights"; import { useAutoLayoutHighlights } from "./useAutoLayoutHighlights";
import type { WidgetDraggingBlock } from "../../../../common/CanvasArenas/ArenaTypes"; import type { WidgetDraggingBlock } from "../../../../common/canvasArenas/ArenaTypes";
import { useBlocksToBeDraggedOnCanvas } from "./useBlocksToBeDraggedOnCanvas"; import { useBlocksToBeDraggedOnCanvas } from "./useBlocksToBeDraggedOnCanvas";
import { useRenderBlocksOnCanvas } from "./useRenderBlocksOnCanvas"; import { useRenderBlocksOnCanvas } from "./useRenderBlocksOnCanvas";
import type { HighlightInfo } from "layoutSystems/common/utils/types"; import type { HighlightInfo } from "layoutSystems/common/utils/types";
import type { AutoCanvasDraggingArenaProps } from "../AutoCanvasDraggingArena"; import type { AutoCanvasDraggingArenaProps } from "../AutoCanvasDraggingArena";
import { useCanvasDragToScroll } from "layoutSystems/common/CanvasArenas/useCanvasDragToScroll"; import { useCanvasDragToScroll } from "layoutSystems/common/canvasArenas/useCanvasDragToScroll";
import { modifyBlockDimension } from "layoutSystems/common/utils/canvasDraggingUtils"; import { modifyBlockDimension } from "layoutSystems/common/utils/canvasDraggingUtils";
import { CANVAS_VIEWPORT } from "constants/componentClassNameConstants"; import { CANVAS_VIEWPORT } from "constants/componentClassNameConstants";

View File

@ -4,7 +4,7 @@ import { useSelector } from "react-redux";
import { getZoomLevel } from "selectors/editorSelectors"; import { getZoomLevel } from "selectors/editorSelectors";
import type { HighlightInfo } from "layoutSystems/common/utils/types"; import type { HighlightInfo } from "layoutSystems/common/utils/types";
import { getAbsolutePixels } from "utils/helpers"; import { getAbsolutePixels } from "utils/helpers";
import type { WidgetDraggingBlock } from "../../../../common/CanvasArenas/ArenaTypes"; import type { WidgetDraggingBlock } from "../../../../common/canvasArenas/ArenaTypes";
import { modifyDrawingRectangles } from "layoutSystems/common/utils/canvasDraggingUtils"; import { modifyDrawingRectangles } from "layoutSystems/common/utils/canvasDraggingUtils";
/** /**

View File

@ -24,11 +24,6 @@ export const AutoLayoutEditorWrapper = (props: WidgetProps) => {
? AutoLayoutEditorModalOnion ? AutoLayoutEditorModalOnion
: AutoLayoutEditorWidgetOnion; : AutoLayoutEditorWidgetOnion;
}, [props.type]); }, [props.type]);
const canvasWidget = props.type === "CANVAS_WIDGET";
if (canvasWidget) {
return props.children;
}
return <WidgetOnion {...props}>{props.children}</WidgetOnion>; return <WidgetOnion {...props}>{props.children}</WidgetOnion>;
}; };

View File

@ -1,8 +1,13 @@
import type { BaseWidgetProps } from "widgets/BaseWidgetHOC/withBaseWidgetHOC"; import type { BaseWidgetProps } from "widgets/BaseWidgetHOC/withBaseWidgetHOC";
import { RenderModes } from "../../constants/WidgetConstants"; import { RenderModes } from "../../constants/WidgetConstants";
import { AutoLayoutEditorCanvas } from "./canvas/AutoLayoutEditorCanvas";
import { AutoLayoutViewerCanvas } from "./canvas/AutoLayoutViewerCanvas";
import { AutoLayoutEditorWrapper } from "./editor/AutoLayoutEditorWrapper"; import { AutoLayoutEditorWrapper } from "./editor/AutoLayoutEditorWrapper";
import { AutoLayoutViewerWrapper } from "./viewer/AutoLayoutViewerWrapper"; import { AutoLayoutViewerWrapper } from "./viewer/AutoLayoutViewerWrapper";
import { getAutoLayoutComponentDimensions } from "layoutSystems/common/utils/ComponentSizeUtils"; import { getAutoLayoutComponentDimensions } from "layoutSystems/common/utils/ComponentSizeUtils";
import type { LayoutSystem } from "layoutSystems/types";
import { CANVAS_DEFAULT_MIN_HEIGHT_PX } from "constants/AppConstants";
import type { CanvasProps } from "layoutSystems/fixedlayout/canvas/FixedLayoutEditorCanvas";
import { import {
getAutoDimensionsConfig, getAutoDimensionsConfig,
getAutoLayoutWidgetConfig, getAutoLayoutWidgetConfig,
@ -24,7 +29,7 @@ export const getAutoLayoutDimensionsConfig = (
}; };
/** /**
* getAutoLayoutSystemPropsEnhancer * getAutoLayoutSystemWidgetPropsEnhancer
* *
* utility function to enhance BaseWidgetProps with Auto Layout system specific props * utility function to enhance BaseWidgetProps with Auto Layout system specific props
* *
@ -35,7 +40,7 @@ export const getAutoLayoutDimensionsConfig = (
* *
*/ */
const getAutoLayoutSystemPropsEnhancer = (props: BaseWidgetProps) => { const getAutoLayoutSystemWidgetPropsEnhancer = (props: BaseWidgetProps) => {
const autoDimensionConfig = getAutoLayoutDimensionsConfig(props); const autoDimensionConfig = getAutoLayoutDimensionsConfig(props);
const { componentHeight, componentWidth } = const { componentHeight, componentWidth } =
getAutoLayoutComponentDimensions(props); getAutoLayoutComponentDimensions(props);
@ -47,6 +52,45 @@ const getAutoLayoutSystemPropsEnhancer = (props: BaseWidgetProps) => {
}; };
}; };
const defaultAutoLayoutCanvasProps: Partial<CanvasProps> = {
parentRowSpace: 1,
parentColumnSpace: 1,
topRow: 0,
leftColumn: 0,
containerStyle: "none",
detachFromLayout: true,
shouldScrollContents: false,
};
/**
* getAutoLayoutSystemCanvasPropsEnhancer
*
* utility function to enhance BaseWidgetProps of canvas with Auto Layout system specific props
*
* @returns EnhancedBaseWidgetProps
* @property {AutoDimensionValues | undefined} autoDimensionConfig The auto dimension configuration of a widget.
* @property {number} componentHeight The calculated height of a widget in pixels.
* @property {number} componentWidth The calculated width of a widget in pixels.
*
*/
const getAutoLayoutSystemCanvasPropsEnhancer = (props: BaseWidgetProps) => {
const enhancedProps = {
minHeight: CANVAS_DEFAULT_MIN_HEIGHT_PX,
...props,
...defaultAutoLayoutCanvasProps,
};
const autoDimensionConfig = getAutoLayoutDimensionsConfig(enhancedProps);
const { componentHeight, componentWidth } =
getAutoLayoutComponentDimensions(enhancedProps);
return {
...enhancedProps,
autoDimensionConfig,
componentHeight,
componentWidth,
};
};
/** /**
* getAutoLayoutSystemWrapper * getAutoLayoutSystemWrapper
* *
@ -64,6 +108,22 @@ const getAutoLayoutSystemWrapper = (renderMode: RenderModes) => {
} }
}; };
/**
* getAutoLayoutSystemCanvasWrapper
*
* utility function to return the auto layout system canvas implementation based on render mode.
*
* @returns current render mode specific canvas component.
*/
function getAutoLayoutSystemCanvasWrapper(renderMode: RenderModes) {
if (renderMode === RenderModes.CANVAS) {
return AutoLayoutEditorCanvas;
} else {
return AutoLayoutViewerCanvas;
}
}
/** /**
* getAutoLayoutSystem * getAutoLayoutSystem
* *
@ -71,15 +131,19 @@ const getAutoLayoutSystemWrapper = (renderMode: RenderModes) => {
* wrapper based on render mode and property enhancer function * wrapper based on render mode and property enhancer function
* *
* @returns * @returns
* @function LayoutSystemWrapper - layout and render mode specific component which is wrapped around a widget * @property widgetSystem - widget specific wrappers and enhancers of a layout system
* pls check getAutoLayoutSystemWrapper for more details. * @property canvasSystem - canvas specific implementation and enhancers of a layout system
* @function propertyEnhancer - layout specific enhancer function which adds more properties generated/used by the layout system.
* pls check getAutoLayoutSystemPropsEnhancer for more details.
*/ */
export function getAutoLayoutSystem(renderMode: RenderModes) { export function getAutoLayoutSystem(renderMode: RenderModes): LayoutSystem {
return { return {
LayoutSystemWrapper: getAutoLayoutSystemWrapper(renderMode), widgetSystem: {
propertyEnhancer: getAutoLayoutSystemPropsEnhancer, WidgetWrapper: getAutoLayoutSystemWrapper(renderMode),
propertyEnhancer: getAutoLayoutSystemWidgetPropsEnhancer,
},
canvasSystem: {
Canvas: getAutoLayoutSystemCanvasWrapper(renderMode),
propertyEnhancer: getAutoLayoutSystemCanvasPropsEnhancer,
},
}; };
} }

View File

@ -24,10 +24,6 @@ export const AutoLayoutViewerWrapper = (props: WidgetProps) => {
? AutoLayoutViewerModalOnion ? AutoLayoutViewerModalOnion
: AutoLayoutViewerWidgetOnion; : AutoLayoutViewerWidgetOnion;
}, [props.type]); }, [props.type]);
const canvasWidget = props.type === "CANVAS_WIDGET";
if (canvasWidget) {
return props.children;
}
return <WidgetOnion {...props}>{props.children}</WidgetOnion>; return <WidgetOnion {...props}>{props.children}</WidgetOnion>;
}; };

View File

@ -0,0 +1,33 @@
import { GridDefaults } from "constants/WidgetConstants";
import type { CSSProperties, ReactNode } from "react";
import React from "react";
import { getCanvasClassName } from "utils/generators";
type CanvasViewerWrapperProps = {
snapRows: number;
isListWidgetCanvas: boolean;
children: ReactNode;
};
/**
* This component is a wrapper for the canvas in the viewer.
* It is responsible for setting the height of the canvas in view mode.
*/
export const CanvasViewerWrapper = ({
children,
isListWidgetCanvas,
snapRows,
}: CanvasViewerWrapperProps) => {
const height = snapRows * GridDefaults.DEFAULT_GRID_ROW_HEIGHT;
const style: CSSProperties = {
width: "100%",
height: isListWidgetCanvas ? "auto" : `${height}px`,
background: "none",
position: "relative",
};
return (
<div className={getCanvasClassName()} style={style}>
{children}
</div>
);
};

View File

@ -17,7 +17,6 @@ import styled from "styled-components";
import { getCanvasSnapRows } from "utils/WidgetPropsUtils"; import { getCanvasSnapRows } from "utils/WidgetPropsUtils";
import { calculateDropTargetRows } from "./DropTargetUtils"; import { calculateDropTargetRows } from "./DropTargetUtils";
import DragLayerComponent from "./DragLayerComponent";
import { useDispatch } from "react-redux"; import { useDispatch } from "react-redux";
import { useShowPropertyPane } from "utils/hooks/dragResizeHooks"; import { useShowPropertyPane } from "utils/hooks/dragResizeHooks";
import { import {
@ -37,10 +36,11 @@ import {
isAutoHeightEnabledForWidgetWithLimits, isAutoHeightEnabledForWidgetWithLimits,
} from "widgets/WidgetUtils"; } from "widgets/WidgetUtils";
import { getIsAppSettingsPaneWithNavigationTabOpen } from "selectors/appSettingsPaneSelectors"; import { getIsAppSettingsPaneWithNavigationTabOpen } from "selectors/appSettingsPaneSelectors";
import { LayoutSystemTypes } from "layoutSystems/types"; import DragLayerComponent from "./DragLayerComponent";
import { getLayoutSystemType } from "selectors/layoutSystemSelectors"; import { getLayoutSystemType } from "selectors/layoutSystemSelectors";
import { LayoutSystemTypes } from "layoutSystems/types";
type DropTargetComponentProps = PropsWithChildren<{ export type DropTargetComponentProps = PropsWithChildren<{
snapColumnSpace: number; snapColumnSpace: number;
widgetId: string; widgetId: string;
parentId?: string; parentId?: string;

View File

@ -0,0 +1,33 @@
import DropTargetComponent from "layoutSystems/common/dropTarget/DropTargetComponent";
import type { DropTargetComponentProps } from "layoutSystems/common/dropTarget/DropTargetComponent";
import type { ReactNode } from "react";
import { memo } from "react";
import React from "react";
type DropTargetComponentWrapperProps = {
dropTargetProps: DropTargetComponentProps;
dropDisabled: boolean;
children: ReactNode;
snapColumnSpace: number;
};
/**
* This component is a wrapper for the DropTargetComponent.
* It decides whether to render the DropTargetComponent or not based on the dropDisabled prop.
*/
export const DropTargetComponentWrapper = memo(
({
children,
dropDisabled,
dropTargetProps,
}: DropTargetComponentWrapperProps) => {
if (dropDisabled) {
//eslint-disable-next-line
return <>{children}</>;
}
return (
<DropTargetComponent {...dropTargetProps}>{children}</DropTargetComponent>
);
},
);

View File

@ -9,7 +9,7 @@ import {
WidgetHeightLimits, WidgetHeightLimits,
} from "constants/WidgetConstants"; } from "constants/WidgetConstants";
import { get, omit } from "lodash"; import { get, omit } from "lodash";
import type { XYCord } from "layoutSystems/common/CanvasArenas/ArenaTypes"; import type { XYCord } from "layoutSystems/common/canvasArenas/ArenaTypes";
import React, { memo, useContext, useMemo } from "react"; import React, { memo, useContext, useMemo } from "react";
import { useDispatch, useSelector } from "react-redux"; import { useDispatch, useSelector } from "react-redux";
import { AutoLayoutResizable } from "layoutSystems/autolayout/common/resizer/AutoLayoutResizable"; import { AutoLayoutResizable } from "layoutSystems/autolayout/common/resizer/AutoLayoutResizable";
@ -47,7 +47,7 @@ import {
isAutoHeightEnabledForWidget, isAutoHeightEnabledForWidget,
isAutoHeightEnabledForWidgetWithLimits, isAutoHeightEnabledForWidgetWithLimits,
} from "widgets/WidgetUtils"; } from "widgets/WidgetUtils";
import { DropTargetContext } from "../../../components/editorComponents/DropTargetComponent"; import { DropTargetContext } from "../dropTarget/DropTargetComponent";
import { import {
BottomHandleStyles, BottomHandleStyles,
BottomLeftHandleStyles, BottomLeftHandleStyles,

View File

@ -1,6 +1,6 @@
import type { WidgetRowCols } from "widgets/BaseWidget"; import type { WidgetRowCols } from "widgets/BaseWidget";
import { GridDefaults } from "constants/WidgetConstants"; import { GridDefaults } from "constants/WidgetConstants";
import type { XYCord } from "layoutSystems/common/CanvasArenas/ArenaTypes"; import type { XYCord } from "layoutSystems/common/canvasArenas/ArenaTypes";
import { ReflowDirection } from "reflow/reflowTypes"; import { ReflowDirection } from "reflow/reflowTypes";
import { ResponsiveBehavior } from "layoutSystems/common/utils/constants"; import { ResponsiveBehavior } from "layoutSystems/common/utils/constants";

View File

@ -110,12 +110,14 @@ export const getComponentDimensions = memo(
( (
props: BaseWidgetProps, props: BaseWidgetProps,
layoutSystemType: LayoutSystemTypes, layoutSystemType: LayoutSystemTypes,
isMobile: boolean, isMobile = false,
): { ): {
componentHeight: number; componentHeight: number;
componentWidth: number; componentWidth: number;
} => { } => {
switch (layoutSystemType) { switch (layoutSystemType) {
case LayoutSystemTypes.ANVIL:
return getAnvilComponentDimensions(props);
case LayoutSystemTypes.AUTO: case LayoutSystemTypes.AUTO:
return getAutoLayoutComponentDimensions({ ...props, isMobile }); return getAutoLayoutComponentDimensions({ ...props, isMobile });
default: default:

View File

@ -22,7 +22,7 @@ import {
getDropZoneOffsets, getDropZoneOffsets,
noCollision, noCollision,
} from "utils/WidgetPropsUtils"; } from "utils/WidgetPropsUtils";
import type { WidgetDraggingBlock, XYCord } from "../CanvasArenas/ArenaTypes"; import type { WidgetDraggingBlock, XYCord } from "../canvasArenas/ArenaTypes";
/** /**
* Method to get the Direction appropriate to closest edge of the canvas * Method to get the Direction appropriate to closest edge of the canvas

View File

@ -0,0 +1,79 @@
import type { RenderModes } from "constants/WidgetConstants";
import type { AdditionalAutoLayoutProperties } from "layoutSystems/autolayout/canvas/types";
import type { AdditionalFixedLayoutProperties } from "layoutSystems/fixedlayout/canvas/types";
import { map } from "lodash";
import WidgetFactory from "WidgetProvider/factory";
import type { WidgetProps } from "widgets/BaseWidget";
type LayoutSystemProps =
| AdditionalFixedLayoutProperties
| AdditionalAutoLayoutProperties;
/**
* This utility function renders a child widget based on the widget data passed to it.
* when enhancing a child widget properties
* layoutSystemProps override childWidgetData and defaultWidgetProps,
* childWidgetData override defaultWidgetProps.
*
* @returns
*/
function renderChildWidget({
childWidgetData,
defaultWidgetProps,
layoutSystemProps,
noPad,
renderMode,
widgetId,
}: {
childWidgetData: WidgetProps;
widgetId: string;
renderMode: RenderModes;
layoutSystemProps: LayoutSystemProps;
defaultWidgetProps: Record<string, any>;
noPad: boolean;
}): React.ReactNode {
const childWidget = {
...defaultWidgetProps,
...childWidgetData,
...layoutSystemProps,
};
if (!childWidgetData) return null;
if (noPad) childWidget.noContainerOffset = true;
childWidget.parentId = widgetId;
return WidgetFactory.createWidget(childWidget, renderMode);
}
/**
*
* @param children - array of props of the children.
* @param widgetId - id of the parent canvas.
* @param renderMode - current render mode.
* @param defaultWidgetProps - default props of the child widget.
* @param layoutSystemProps - props of the layout system.
* @param noPad - if true, noContainerOffset is set to true to the child widget.
*
* children is an array of childWidgetData
* childWidgetData is props of each individual child widget.
* layoutSystemProps override childWidgetData, childWidgetData override defaultWidgetProps.
*
* @returns array of child widgets.
*/
export const renderChildren = (
children: WidgetProps[],
widgetId: string,
renderMode: RenderModes,
defaultWidgetProps: Partial<WidgetProps> = {},
layoutSystemProps: LayoutSystemProps,
noPad = false,
): React.ReactNode[] => {
return map(children, (childWidgetData: WidgetProps) =>
renderChildWidget({
childWidgetData,
layoutSystemProps,
defaultWidgetProps,
noPad,
renderMode,
widgetId,
}),
);
};

View File

@ -0,0 +1,119 @@
import { CANVAS_DEFAULT_MIN_HEIGHT_PX } from "constants/AppConstants";
import { GridDefaults, RenderModes } from "constants/WidgetConstants";
import { renderChildren } from "layoutSystems/common/utils/canvasUtils";
import { CanvasSelectionArena } from "layoutSystems/fixedlayout/editor/FixedLayoutCanvasArenas/CanvasSelectionArena";
import WidgetsMultiSelectBox from "layoutSystems/fixedlayout/common/widgetGrouping/WidgetsMultiSelectBox";
import React, { useMemo } from "react";
import { getSnappedGrid } from "sagas/WidgetOperationUtils";
import { getCanvasSnapRows } from "utils/WidgetPropsUtils";
import type { WidgetProps } from "widgets/BaseWidget";
import type { BaseWidgetProps } from "widgets/BaseWidgetHOC/withBaseWidgetHOC";
import ContainerComponent from "widgets/ContainerWidget/component";
import { DropTargetComponentWrapper } from "../../common/dropTarget/DropTargetComponentWrapper";
import { FixedCanvasDraggingArena } from "../editor/FixedLayoutCanvasArenas/FixedCanvasDraggingArena";
import { compact, sortBy } from "lodash";
import { Positioning } from "layoutSystems/common/utils/constants";
import type { DSLWidget } from "WidgetProvider/constants";
export type CanvasProps = DSLWidget;
/**
* This component implements the Canvas for Fixed Layout System in Edit mode.
* This component adds layers like CanvasDraggingArena, CanvasSelectionArena, etc which are responsible for
* drag and drop, selection, etc.
* This component also renders the children of the canvas with additional layout specific properties like
* parentColumnSpace, parentRowSpace, etc.
*/
export const FixedLayoutEditorCanvas = (props: BaseWidgetProps) => {
const { snapGrid } = getSnappedGrid(props, props.componentWidth);
const { snapColumnSpace } = snapGrid;
const snapRows = getCanvasSnapRows(props.bottomRow);
const fixedLayoutDropTargetProps = useMemo(
() => ({
bottomRow: props.bottomRow,
isListWidgetCanvas: props.isListWidgetCanvas,
minHeight: props.minHeight || CANVAS_DEFAULT_MIN_HEIGHT_PX,
noPad: props.noPad,
parentId: props.parentId,
snapColumnSpace: snapColumnSpace,
widgetId: props.widgetId,
}),
[
props.bottomRow,
props.isListWidgetCanvas,
props.minHeight,
props.noPad,
props.parentId,
snapColumnSpace,
props.widgetId,
],
);
const layoutSystemProps = {
parentColumnSpace: snapColumnSpace,
parentRowSpace: GridDefaults.DEFAULT_GRID_ROW_HEIGHT,
};
const defaultWidgetProps: Partial<WidgetProps> = {
positioning: props.positioning,
};
// ToDO(#27617): Remove sorting of children on the view, ideally the model should be sorted, coz they are less frequently happening
// operations. leaving it as is for now, coz it multiple cypress tests are dependent on this.
const canvasChildren = useMemo(
() =>
renderChildren(
props.positioning !== Positioning.Fixed
? props.children
: sortBy(
compact(props.children),
(child: WidgetProps) => child.topRow,
),
props.widgetId,
RenderModes.CANVAS,
defaultWidgetProps,
layoutSystemProps,
!!props.noPad,
),
[
props.children,
props.shouldScrollContents,
props.widgetId,
props.componentHeight,
props.componentWidth,
snapColumnSpace,
],
);
return (
<DropTargetComponentWrapper
dropDisabled={!!props.dropDisabled}
dropTargetProps={fixedLayoutDropTargetProps}
snapColumnSpace={snapColumnSpace}
>
<ContainerComponent {...props}>
<FixedCanvasDraggingArena
{...snapGrid}
canExtend={props.canExtend}
dropDisabled={!!props.dropDisabled}
noPad={props.noPad}
parentId={props.parentId}
snapRows={snapRows}
widgetId={props.widgetId}
widgetName={props.widgetName}
/>
<CanvasSelectionArena
{...snapGrid}
canExtend={props.canExtend}
dropDisabled={!!props.dropDisabled}
parentId={props.parentId}
snapRows={snapRows}
widgetId={props.widgetId}
/>
<WidgetsMultiSelectBox
{...snapGrid}
noContainerOffset={!!props.noContainerOffset}
widgetId={props.widgetId}
widgetType={props.type}
/>
{canvasChildren}
</ContainerComponent>
</DropTargetComponentWrapper>
);
};

View File

@ -0,0 +1,69 @@
import { GridDefaults, RenderModes } from "constants/WidgetConstants";
import { Positioning } from "layoutSystems/common/utils/constants";
import { CanvasViewerWrapper } from "layoutSystems/common/canvasViewer/CanvasViewerWrapper";
import { renderChildren } from "layoutSystems/common/utils/canvasUtils";
import { compact, sortBy } from "lodash";
import React, { useMemo } from "react";
import { getSnappedGrid } from "sagas/WidgetOperationUtils";
import { getCanvasSnapRows } from "utils/WidgetPropsUtils";
import type { WidgetProps } from "widgets/BaseWidget";
import type { BaseWidgetProps } from "widgets/BaseWidgetHOC/withBaseWidgetHOC";
import ContainerComponent from "widgets/ContainerWidget/component";
import type { ContainerWidgetProps } from "widgets/ContainerWidget/widget";
import type { AdditionalFixedLayoutProperties } from "./types";
export type CanvasProps = ContainerWidgetProps<WidgetProps>;
/**
* This component implements the Canvas for Fixed Layout System in View mode.
* This component also renders the children of the canvas with additional layout specific properties like
* parentColumnSpace, parentRowSpace, etc.
*/
export const FixedLayoutViewerCanvas = (props: BaseWidgetProps) => {
const { snapGrid } = getSnappedGrid(props, props.componentWidth);
const { snapColumnSpace } = snapGrid;
const layoutSystemProps: AdditionalFixedLayoutProperties = {
parentColumnSpace: snapColumnSpace,
parentRowSpace: GridDefaults.DEFAULT_GRID_ROW_HEIGHT,
};
const defaultWidgetProps: Partial<WidgetProps> = {
positioning: props.positioning,
};
// ToDO(#27617): Remove sorting of children on the view, ideally the model should be sorted, coz they are less frequently happening
// operations. leaving it as is for now, coz it multiple cypress tests are dependent on this.
const canvasChildren = useMemo(
() =>
renderChildren(
props.positioning !== Positioning.Fixed
? props.children
: sortBy(
compact(props.children),
(child: WidgetProps) => child.topRow,
),
props.widgetId,
RenderModes.PAGE,
defaultWidgetProps,
layoutSystemProps,
!!props.noPad,
),
[
props.children,
props.shouldScrollContents,
props.widgetId,
props.componentHeight,
props.componentWidth,
snapColumnSpace,
],
);
const snapRows = getCanvasSnapRows(props.bottomRow);
return (
<CanvasViewerWrapper
isListWidgetCanvas={props.isListWidgetCanvas}
snapRows={snapRows}
>
<ContainerComponent {...props}>{canvasChildren}</ContainerComponent>
</CanvasViewerWrapper>
);
};

View File

@ -0,0 +1,4 @@
export type AdditionalFixedLayoutProperties = {
parentRowSpace: number;
parentColumnSpace: number;
};

View File

@ -1,9 +1,9 @@
import { WIDGET_PADDING } from "constants/WidgetConstants"; import { WIDGET_PADDING } from "constants/WidgetConstants";
import React from "react"; import React, { memo } from "react";
import type { BaseWidgetProps } from "widgets/BaseWidgetHOC/withBaseWidgetHOC"; import type { BaseWidgetProps } from "widgets/BaseWidgetHOC/withBaseWidgetHOC";
import { ResizableComponent } from "layoutSystems/common/resizer/ResizableComponent"; import { ResizableComponent } from "layoutSystems/common/resizer/ResizableComponent";
export const FixedResizableLayer = (props: BaseWidgetProps) => { export const FixedResizableLayer = memo((props: BaseWidgetProps) => {
if (props.resizeDisabled || props.type === "SKELETON_WIDGET") { if (props.resizeDisabled || props.type === "SKELETON_WIDGET") {
return props.children; return props.children;
} }
@ -12,4 +12,4 @@ export const FixedResizableLayer = (props: BaseWidgetProps) => {
{props.children} {props.children}
</ResizableComponent> </ResizableComponent>
); );
}; });

View File

@ -27,9 +27,9 @@ import {
} from "selectors/editorSelectors"; } from "selectors/editorSelectors";
import { getNearestParentCanvas } from "utils/generators"; import { getNearestParentCanvas } from "utils/generators";
import { getAbsolutePixels } from "utils/helpers"; import { getAbsolutePixels } from "utils/helpers";
import type { XYCord } from "layoutSystems/common/CanvasArenas/ArenaTypes"; import type { XYCord } from "layoutSystems/common/canvasArenas/ArenaTypes";
import { useCanvasDragToScroll } from "layoutSystems/common/CanvasArenas/useCanvasDragToScroll"; import { useCanvasDragToScroll } from "layoutSystems/common/canvasArenas/useCanvasDragToScroll";
import { StickyCanvasArena } from "layoutSystems/common/CanvasArenas/StickyCanvasArena"; import { StickyCanvasArena } from "layoutSystems/common/canvasArenas/StickyCanvasArena";
export interface SelectedArenaDimensions { export interface SelectedArenaDimensions {
top: number; top: number;

View File

@ -1,7 +1,7 @@
import type { AppState } from "@appsmith/reducers"; import type { AppState } from "@appsmith/reducers";
import { theme } from "constants/DefaultTheme"; import { theme } from "constants/DefaultTheme";
import { MAIN_CONTAINER_WIDGET_ID } from "constants/WidgetConstants"; import { MAIN_CONTAINER_WIDGET_ID } from "constants/WidgetConstants";
import { StickyCanvasArena } from "layoutSystems/common/CanvasArenas/StickyCanvasArena"; import { StickyCanvasArena } from "layoutSystems/common/canvasArenas/StickyCanvasArena";
import React from "react"; import React from "react";
import { useSelector } from "react-redux"; import { useSelector } from "react-redux";
import { getNearestParentCanvas } from "utils/generators"; import { getNearestParentCanvas } from "utils/generators";

View File

@ -12,7 +12,7 @@ import type {
} from "constants/CanvasEditorConstants"; } from "constants/CanvasEditorConstants";
import { getDragDetails, getWidgetByID, getWidgets } from "sagas/selectors"; import { getDragDetails, getWidgetByID, getWidgets } from "sagas/selectors";
import { widgetOperationParams } from "utils/WidgetPropsUtils"; import { widgetOperationParams } from "utils/WidgetPropsUtils";
import { DropTargetContext } from "components/editorComponents/DropTargetComponent"; import { DropTargetContext } from "layoutSystems/common/dropTarget/DropTargetComponent";
import equal from "fast-deep-equal/es6"; import equal from "fast-deep-equal/es6";
import type { FixedCanvasDraggingArenaProps } from "../FixedCanvasDraggingArena"; import type { FixedCanvasDraggingArenaProps } from "../FixedCanvasDraggingArena";
import { useDispatch, useSelector } from "react-redux"; import { useDispatch, useSelector } from "react-redux";
@ -30,7 +30,7 @@ import type {
WidgetDraggingBlock, WidgetDraggingBlock,
WidgetDraggingUpdateParams, WidgetDraggingUpdateParams,
XYCord, XYCord,
} from "../../../../common/CanvasArenas/ArenaTypes"; } from "../../../../common/canvasArenas/ArenaTypes";
import { import {
getBlocksToDraw, getBlocksToDraw,
getParentDiff, getParentDiff,

View File

@ -29,10 +29,10 @@ import {
modifyDrawingRectangles, modifyDrawingRectangles,
updateRectanglesPostReflow, updateRectanglesPostReflow,
} from "layoutSystems/common/utils/canvasDraggingUtils"; } from "layoutSystems/common/utils/canvasDraggingUtils";
import type { WidgetDraggingBlock } from "../../../../common/CanvasArenas/ArenaTypes"; import type { WidgetDraggingBlock } from "../../../../common/canvasArenas/ArenaTypes";
import { useBlocksToBeDraggedOnCanvas } from "./useBlocksToBeDraggedOnCanvas"; import { useBlocksToBeDraggedOnCanvas } from "./useBlocksToBeDraggedOnCanvas";
import { useRenderBlocksOnCanvas } from "./useRenderBlocksOnCanvas"; import { useRenderBlocksOnCanvas } from "./useRenderBlocksOnCanvas";
import { useCanvasDragToScroll } from "layoutSystems/common/CanvasArenas/useCanvasDragToScroll"; import { useCanvasDragToScroll } from "layoutSystems/common/canvasArenas/useCanvasDragToScroll";
import type { FixedCanvasDraggingArenaProps } from "../FixedCanvasDraggingArena"; import type { FixedCanvasDraggingArenaProps } from "../FixedCanvasDraggingArena";
/** /**

View File

@ -4,8 +4,8 @@ import { useSelector } from "react-redux";
import type { SpaceMap } from "reflow/reflowTypes"; import type { SpaceMap } from "reflow/reflowTypes";
import { getZoomLevel } from "selectors/editorSelectors"; import { getZoomLevel } from "selectors/editorSelectors";
import { getAbsolutePixels } from "utils/helpers"; import { getAbsolutePixels } from "utils/helpers";
import type { XYCord } from "../../../../common/CanvasArenas/ArenaTypes"; import type { XYCord } from "../../../../common/canvasArenas/ArenaTypes";
import type { WidgetDraggingBlock } from "../../../../common/CanvasArenas/ArenaTypes"; import type { WidgetDraggingBlock } from "../../../../common/canvasArenas/ArenaTypes";
/** /**
* returns a method that renders dragging blocks on canvas * returns a method that renders dragging blocks on canvas

View File

@ -24,10 +24,6 @@ export const FixedLayoutEditorWrapper = (props: WidgetProps) => {
? FixedLayoutEditorModalOnion ? FixedLayoutEditorModalOnion
: FixedLayoutEditorWidgetOnion; : FixedLayoutEditorWidgetOnion;
}, [props.type]); }, [props.type]);
const canvasWidget = props.type === "CANVAS_WIDGET";
if (canvasWidget) {
return props.children;
}
return <WidgetOnion {...props}>{props.children}</WidgetOnion>; return <WidgetOnion {...props}>{props.children}</WidgetOnion>;
}; };

View File

@ -3,10 +3,15 @@ import { FixedLayoutEditorWrapper } from "./editor/FixedLayoutEditorWrapper";
import { FixedLayoutViewerWrapper } from "./viewer/FixedLayoutViewerWrapper"; import { FixedLayoutViewerWrapper } from "./viewer/FixedLayoutViewerWrapper";
import type { BaseWidgetProps } from "widgets/BaseWidgetHOC/withBaseWidgetHOC"; import type { BaseWidgetProps } from "widgets/BaseWidgetHOC/withBaseWidgetHOC";
import { getFixedLayoutComponentDimensions } from "layoutSystems/common/utils/ComponentSizeUtils"; import { getFixedLayoutComponentDimensions } from "layoutSystems/common/utils/ComponentSizeUtils";
import { FixedLayoutEditorCanvas } from "./canvas/FixedLayoutEditorCanvas";
import type { CanvasProps } from "./canvas/FixedLayoutEditorCanvas";
import { FixedLayoutViewerCanvas } from "./canvas/FixedLayoutViewerCanvas";
import { CANVAS_DEFAULT_MIN_HEIGHT_PX } from "constants/AppConstants";
import type { LayoutSystem } from "layoutSystems/types";
/** /**
* getLabelWidth * getLabelWidth
* utiltiy function to compute a widgets label width in Fixed layout system * utility function to compute a widgets label width in Fixed layout system
* *
*/ */
const getLabelWidth = (props: BaseWidgetProps) => { const getLabelWidth = (props: BaseWidgetProps) => {
@ -19,7 +24,7 @@ const getLabelWidth = (props: BaseWidgetProps) => {
* utility function to enhance BaseWidgetProps with Fixed Layout system specific props * utility function to enhance BaseWidgetProps with Fixed Layout system specific props
* *
*/ */
const getFixedLayoutSystemPropsEnhancer = (props: BaseWidgetProps) => { const getFixedLayoutSystemWidgetPropsEnhancer = (props: BaseWidgetProps) => {
const { componentHeight, componentWidth } = const { componentHeight, componentWidth } =
getFixedLayoutComponentDimensions(props); getFixedLayoutComponentDimensions(props);
const labelComponentWidth = getLabelWidth(props); const labelComponentWidth = getLabelWidth(props);
@ -32,6 +37,42 @@ const getFixedLayoutSystemPropsEnhancer = (props: BaseWidgetProps) => {
}; };
}; };
const defaultFixedCanvasProps: Partial<CanvasProps> = {
parentRowSpace: 1,
parentColumnSpace: 1,
topRow: 0,
leftColumn: 0,
containerStyle: "none",
detachFromLayout: true,
shouldScrollContents: false,
};
/**
* getFixedLayoutSystemCanvasPropsEnhancer
*
* utility function to enhance BaseWidgetProps of canvas with Auto Layout system specific props
*
* @returns EnhancedBaseWidgetProps
* @property {number} componentHeight The calculated height of a widget in pixels.
* @property {number} componentWidth The calculated width of a widget in pixels.
*
*/
const getFixedLayoutSystemCanvasPropsEnhancer = (props: BaseWidgetProps) => {
const enhancedProps = {
minHeight: CANVAS_DEFAULT_MIN_HEIGHT_PX,
...props,
...defaultFixedCanvasProps,
};
const { componentHeight, componentWidth } =
getFixedLayoutComponentDimensions(enhancedProps);
return {
...enhancedProps,
componentHeight,
componentWidth,
};
};
/** /**
* getFixedLayoutSystemWrapper * getFixedLayoutSystemWrapper
* *
@ -47,16 +88,41 @@ const getFixedLayoutSystemWrapper = (renderMode: RenderModes) => {
} }
}; };
/**
*
* utility function to return the fixed layout system canvas implementation based on render mode.
*
* @returns current render mode specific canvas component.
*/
function getFixedLayoutSystemCanvasWrapper(renderMode: RenderModes) {
if (renderMode === RenderModes.CANVAS) {
return FixedLayoutEditorCanvas;
} else {
return FixedLayoutViewerCanvas;
}
}
/** /**
* getFixedLayoutSystem * getFixedLayoutSystem
* *
* utility function to return the fixed layout system config for * utility function to return the fixed layout system config for
* wrapper based on render mode and property enhancer function * wrapper based on render mode and property enhancer function
* *
* @returns
* @property widgetSystem - widget specific wrappers and enhancers of a layout system
* @property canvasSystem - canvas specific implementation and enhancers of a layout system
*/ */
export function getFixedLayoutSystem(renderMode: RenderModes) {
export function getFixedLayoutSystem(renderMode: RenderModes): LayoutSystem {
return { return {
LayoutSystemWrapper: getFixedLayoutSystemWrapper(renderMode), widgetSystem: {
propertyEnhancer: getFixedLayoutSystemPropsEnhancer, WidgetWrapper: getFixedLayoutSystemWrapper(renderMode),
propertyEnhancer: getFixedLayoutSystemWidgetPropsEnhancer,
},
canvasSystem: {
Canvas: getFixedLayoutSystemCanvasWrapper(renderMode) as any,
propertyEnhancer: getFixedLayoutSystemCanvasPropsEnhancer,
},
}; };
} }

View File

@ -24,9 +24,5 @@ export const FixedLayoutViewerWrapper = (props: WidgetProps) => {
? FixedLayoutViewerModalOnion ? FixedLayoutViewerModalOnion
: FixedLayoutViewerWidgetOnion; : FixedLayoutViewerWidgetOnion;
}, [props.type]); }, [props.type]);
const canvasWidget = props.type === "CANVAS_WIDGET";
if (canvasWidget) {
return props.children;
}
return <WidgetOnion {...props}>{props.children}</WidgetOnion>; return <WidgetOnion {...props}>{props.children}</WidgetOnion>;
}; };

View File

@ -1,3 +1,5 @@
import type { WidgetProps } from "widgets/BaseWidget";
// Layout system types that Appsmith provides // Layout system types that Appsmith provides
export enum LayoutSystemTypes { export enum LayoutSystemTypes {
FIXED = "FIXED", FIXED = "FIXED",
@ -8,6 +10,48 @@ export enum LayoutSystemTypes {
// interface for appPositioning(aka layoutStystem) details. // interface for appPositioning(aka layoutStystem) details.
// It is part of applicationDetails Record of an Application // It is part of applicationDetails Record of an Application
// Refer to ApplicationPayload // Refer to ApplicationPayload
export interface LayoutSystemTypeConfig { export type LayoutSystemTypeConfig = {
type: LayoutSystemTypes; type: LayoutSystemTypes;
} };
/**
* @type WidgetLayoutSystem
*
* type to define the structure of widget based entities on a specific layout system.
*
* @property WidgetWrapper - component that wraps around a widget
* @property propertyEnhancer - function that is used to enhance/modify widget properties as per the layout system
*/
export type WidgetLayoutSystem = {
WidgetWrapper: (props: WidgetProps) => JSX.Element;
propertyEnhancer: (props: WidgetProps) => WidgetProps;
};
/**
* @type CanvasLayoutSystem
*
* type to define the structure of canvas based entities on a specific layout system.
* @property Canvas - component that renders/positions children as per the layout system.
* @property propertyEnhancer - function that is used to enhance/modify canvas properties as per the layout system
*/
export type CanvasLayoutSystem = {
Canvas: (props: WidgetProps) => JSX.Element;
propertyEnhancer: (props: WidgetProps) => WidgetProps;
};
/**
* @type LayoutSystem
*
* Layout System is the high level system that provides set of wrappers/implementations needed for widgets to function and
* render on both Editor and Viewer of Appsmith.
*
* @property widgetSystem - provides widget specific entities
* @property canvasSystem - provides canvas specific entities
*/
export type LayoutSystem = {
widgetSystem: WidgetLayoutSystem;
canvasSystem: CanvasLayoutSystem;
};

View File

@ -1,370 +0,0 @@
import { RenderModes } from "constants/WidgetConstants";
import React from "react";
import { LayoutSystemTypes } from "layoutSystems/types";
import * as editorSelectors from "selectors/editorSelectors";
import * as layoutSystemSelectors from "selectors/layoutSystemSelectors";
import { WidgetTypeFactories } from "test/factories/Widgets/WidgetTypeFactories";
import { render } from "test/testUtils";
import CanvasWidget from "widgets/CanvasWidget";
import InputWidget from "widgets/InputWidgetV2/widget";
import { ModalWidget } from "widgets/ModalWidget/widget";
import { withLayoutSystemHOC } from "./withLayoutSystemHOC";
describe("Layout System HOC's Tests", () => {
describe("Fixed Layout Layers", () => {
it("Layout system hoc should return Fixed Editor for FIXED positioning and CANVAS render mode", () => {
const widget = InputWidget;
const HOC = withLayoutSystemHOC(widget);
const widgetProps = WidgetTypeFactories[InputWidget.type].build();
jest
.spyOn(editorSelectors, "getRenderMode")
.mockImplementation(() => RenderModes.CANVAS);
jest
.spyOn(layoutSystemSelectors, "getLayoutSystemType")
.mockImplementation(() => LayoutSystemTypes.FIXED);
const component = render(<HOC {...widgetProps} />);
const positionedLayer =
component.container.getElementsByClassName("positioned-widget")[0];
const resizerLayer =
component.container.getElementsByClassName("resize-wrapper")[0];
expect(positionedLayer).toBeTruthy();
expect(resizerLayer).toBeTruthy();
});
it("Layout system hoc should return Fixed Modal Editor for FIXED positioning and CANVAS render mode", () => {
const widget = ModalWidget;
const HOC = withLayoutSystemHOC(widget);
const widgetProps = WidgetTypeFactories[ModalWidget.type].build({
isVisible: true,
});
jest
.spyOn(editorSelectors, "getRenderMode")
.mockImplementation(() => RenderModes.CANVAS);
jest
.spyOn(layoutSystemSelectors, "getLayoutSystemType")
.mockImplementation(() => LayoutSystemTypes.FIXED);
const component = render(<HOC {...widgetProps} />);
const positionedLayer =
component.container.getElementsByClassName("positioned-widget")[0];
const resizerLayer =
component.container.getElementsByClassName("resize-wrapper")[0];
const overlayLayer =
component.container.getElementsByClassName("bp3-overlay")[0];
expect(positionedLayer).toBeFalsy();
expect(overlayLayer).toBeTruthy();
expect(resizerLayer).toBeTruthy();
});
it("Layout system hoc should return no wrapper for CANVAS WIDGET for FIXED positioning and CANVAS render mode", () => {
const widget = CanvasWidget;
const HOC = withLayoutSystemHOC(widget);
const widgetProps = WidgetTypeFactories[CanvasWidget.type].build();
jest
.spyOn(editorSelectors, "getRenderMode")
.mockImplementation(() => RenderModes.CANVAS);
jest
.spyOn(layoutSystemSelectors, "getLayoutSystemType")
.mockImplementation(() => LayoutSystemTypes.FIXED);
const component = render(<HOC {...widgetProps} />);
const positionedLayer =
component.container.getElementsByClassName("positioned-widget")[0];
const resizerLayer =
component.container.getElementsByClassName("resize-wrapper")[0];
expect(positionedLayer).toBeFalsy();
expect(resizerLayer).toBeFalsy();
});
it("Layout system hoc should return Fixed Modal Viewer for FIXED positioning and PAGE render mode", () => {
const widget = ModalWidget;
const HOC = withLayoutSystemHOC(widget);
const widgetProps = WidgetTypeFactories[ModalWidget.type].build({
isVisible: true,
});
jest
.spyOn(editorSelectors, "getRenderMode")
.mockImplementation(() => RenderModes.PAGE);
jest
.spyOn(layoutSystemSelectors, "getLayoutSystemType")
.mockImplementation(() => LayoutSystemTypes.FIXED);
const component = render(<HOC {...widgetProps} />);
const positionedLayer =
component.container.getElementsByClassName("positioned-widget")[0];
const resizerLayer =
component.container.getElementsByClassName("resize-wrapper")[0];
const overlayLayer =
component.container.getElementsByClassName("bp3-overlay")[0];
expect(positionedLayer).toBeFalsy();
expect(overlayLayer).toBeTruthy();
expect(resizerLayer).toBeFalsy();
});
it("Layout system hoc should return Fixed Viewer for FIXED positioning and PAGE render mode", () => {
const widget = InputWidget;
const HOC = withLayoutSystemHOC(widget);
const widgetProps = WidgetTypeFactories[InputWidget.type].build();
jest
.spyOn(editorSelectors, "getRenderMode")
.mockImplementation(() => RenderModes.PAGE);
jest
.spyOn(layoutSystemSelectors, "getLayoutSystemType")
.mockImplementation(() => LayoutSystemTypes.FIXED);
const component = render(<HOC {...widgetProps} />);
const positionedLayer =
component.container.getElementsByClassName("positioned-widget")[0];
const resizerLayer =
component.container.getElementsByClassName("resize-wrapper")[0];
expect(positionedLayer).toBeTruthy();
expect(resizerLayer).toBeFalsy();
});
it("Layout system hoc should return no wrapper for CANVAS WIDGET for FIXED positioning and PAGE render mode", () => {
const widget = CanvasWidget;
const HOC = withLayoutSystemHOC(widget);
const widgetProps = WidgetTypeFactories[CanvasWidget.type].build();
jest
.spyOn(editorSelectors, "getRenderMode")
.mockImplementation(() => RenderModes.PAGE);
jest
.spyOn(layoutSystemSelectors, "getLayoutSystemType")
.mockImplementation(() => LayoutSystemTypes.FIXED);
const component = render(<HOC {...widgetProps} />);
const positionedLayer =
component.container.getElementsByClassName("positioned-widget")[0];
const resizerLayer =
component.container.getElementsByClassName("resize-wrapper")[0];
expect(positionedLayer).toBeFalsy();
expect(resizerLayer).toBeFalsy();
});
});
describe("Auto Layout Layers", () => {
it("Layout system hoc should return Auto Layout Editor for AUTO positioning and CANVAS render mode", () => {
const widget = InputWidget;
const HOC = withLayoutSystemHOC(widget);
const widgetProps = WidgetTypeFactories[InputWidget.type].build();
jest
.spyOn(editorSelectors, "getRenderMode")
.mockImplementation(() => RenderModes.CANVAS);
jest
.spyOn(layoutSystemSelectors, "getLayoutSystemType")
.mockImplementation(() => LayoutSystemTypes.AUTO);
const component = render(<HOC {...widgetProps} />);
const flexPositionedLayer = component.container.getElementsByClassName(
"auto-layout-child-" + widgetProps.widgetId,
)[0];
const resizerLayer =
component.container.getElementsByClassName("resize-wrapper")[0];
expect(flexPositionedLayer).toBeTruthy();
expect(resizerLayer).toBeTruthy();
});
it("Layout system hoc should return Auto Modal Editor for AUTO positioning and CANVAS render mode", () => {
const widget = ModalWidget;
const HOC = withLayoutSystemHOC(widget);
const widgetProps = WidgetTypeFactories[ModalWidget.type].build({
isVisible: true,
});
jest
.spyOn(editorSelectors, "getRenderMode")
.mockImplementation(() => RenderModes.CANVAS);
jest
.spyOn(layoutSystemSelectors, "getLayoutSystemType")
.mockImplementation(() => LayoutSystemTypes.AUTO);
const component = render(<HOC {...widgetProps} />);
const flexPositionedLayer = component.container.getElementsByClassName(
"auto-layout-child-" + widgetProps.widgetId,
)[0];
const resizerLayer =
component.container.getElementsByClassName("resize-wrapper")[0];
const overlayLayer =
component.container.getElementsByClassName("bp3-overlay")[0];
expect(flexPositionedLayer).toBeFalsy();
expect(overlayLayer).toBeTruthy();
expect(resizerLayer).toBeTruthy();
});
it("Layout system hoc should return no wrapper for CANVAS WIDGET for AUTO positioning and CANVAS render mode", () => {
const widget = CanvasWidget;
const HOC = withLayoutSystemHOC(widget);
const widgetProps = WidgetTypeFactories[CanvasWidget.type].build();
jest
.spyOn(editorSelectors, "getRenderMode")
.mockImplementation(() => RenderModes.CANVAS);
jest
.spyOn(layoutSystemSelectors, "getLayoutSystemType")
.mockImplementation(() => LayoutSystemTypes.AUTO);
const component = render(<HOC {...widgetProps} />);
const flexPositionedLayer = component.container.getElementsByClassName(
"auto-layout-child-" + widgetProps.widgetId,
)[0];
const resizerLayer =
component.container.getElementsByClassName("resize-wrapper")[0];
expect(flexPositionedLayer).toBeFalsy();
expect(resizerLayer).toBeFalsy();
});
it("Layout system hoc should return Auto Modal Viewer for AUTO positioning and PAGE render mode", () => {
const widget = ModalWidget;
const HOC = withLayoutSystemHOC(widget);
const widgetProps = WidgetTypeFactories[ModalWidget.type].build({
isVisible: true,
});
jest
.spyOn(editorSelectors, "getRenderMode")
.mockImplementation(() => RenderModes.PAGE);
jest
.spyOn(layoutSystemSelectors, "getLayoutSystemType")
.mockImplementation(() => LayoutSystemTypes.AUTO);
const component = render(<HOC {...widgetProps} />);
const flexPositionedLayer = component.container.getElementsByClassName(
"auto-layout-child-" + widgetProps.widgetId,
)[0];
const resizerLayer =
component.container.getElementsByClassName("resize-wrapper")[0];
const overlayLayer =
component.container.getElementsByClassName("bp3-overlay")[0];
expect(flexPositionedLayer).toBeFalsy();
expect(overlayLayer).toBeTruthy();
expect(resizerLayer).toBeFalsy();
});
it("Layout system hoc should return Auto Viewer for Auto positioning and PAGE render mode", () => {
const widget = InputWidget;
const HOC = withLayoutSystemHOC(widget);
const widgetProps = WidgetTypeFactories[InputWidget.type].build();
jest
.spyOn(editorSelectors, "getRenderMode")
.mockImplementation(() => RenderModes.PAGE);
jest
.spyOn(layoutSystemSelectors, "getLayoutSystemType")
.mockImplementation(() => LayoutSystemTypes.AUTO);
const component = render(<HOC {...widgetProps} />);
const flexPositionedLayer = component.container.getElementsByClassName(
"auto-layout-child-" + widgetProps.widgetId,
)[0];
const resizerLayer =
component.container.getElementsByClassName("resize-wrapper")[0];
expect(flexPositionedLayer).toBeTruthy();
expect(resizerLayer).toBeFalsy();
});
it("Layout system hoc should return no wrapper for CANVAS WIDGET for Auto positioning and PAGE render mode", () => {
const widget = CanvasWidget;
const HOC = withLayoutSystemHOC(widget);
const widgetProps = WidgetTypeFactories[CanvasWidget.type].build();
jest
.spyOn(editorSelectors, "getRenderMode")
.mockImplementation(() => RenderModes.PAGE);
jest
.spyOn(layoutSystemSelectors, "getLayoutSystemType")
.mockImplementation(() => LayoutSystemTypes.AUTO);
const component = render(<HOC {...widgetProps} />);
const flexPositionedLayer = component.container.getElementsByClassName(
"auto-layout-child-" + widgetProps.widgetId,
)[0];
const resizerLayer =
component.container.getElementsByClassName("resize-wrapper")[0];
expect(flexPositionedLayer).toBeFalsy();
expect(resizerLayer).toBeFalsy();
});
});
describe("Anvil Layers", () => {
it("Layout system hoc should return Anvil Editor for ANVIL positioning and CANVAS render mode", () => {
const widget = InputWidget;
const HOC = withLayoutSystemHOC(widget);
const widgetProps = WidgetTypeFactories[InputWidget.type].build();
jest
.spyOn(editorSelectors, "getRenderMode")
.mockImplementation(() => RenderModes.CANVAS);
jest
.spyOn(layoutSystemSelectors, "getLayoutSystemType")
.mockImplementation(() => LayoutSystemTypes.ANVIL);
const component = render(<HOC {...widgetProps} />);
const flexPositionedLayer = component.container.getElementsByClassName(
"anvil-layout-child-" + widgetProps.widgetId,
)[0];
expect(flexPositionedLayer).toBeTruthy();
});
it("should return Auto Modal Editor for ANVIL positioning and CANVAS render mode", () => {
const widget = ModalWidget;
const HOC = withLayoutSystemHOC(widget);
const widgetProps = WidgetTypeFactories[ModalWidget.type].build({
isVisible: true,
});
jest
.spyOn(editorSelectors, "getRenderMode")
.mockImplementation(() => RenderModes.CANVAS);
jest
.spyOn(layoutSystemSelectors, "getLayoutSystemType")
.mockImplementation(() => LayoutSystemTypes.ANVIL);
const component = render(<HOC {...widgetProps} />);
const flexPositionedLayer = component.container.getElementsByClassName(
"anvil-layout-child-" + widgetProps.widgetId,
)[0];
const overlayLayer =
component.container.getElementsByClassName("bp3-overlay")[0];
expect(flexPositionedLayer).toBeFalsy();
expect(overlayLayer).toBeTruthy();
});
it("should return no wrapper for CANVAS WIDGET for ANVIL positioning and CANVAS render mode", () => {
const widget = CanvasWidget;
const HOC = withLayoutSystemHOC(widget);
const widgetProps = WidgetTypeFactories[CanvasWidget.type].build();
jest
.spyOn(editorSelectors, "getRenderMode")
.mockImplementation(() => RenderModes.CANVAS);
jest
.spyOn(layoutSystemSelectors, "getLayoutSystemType")
.mockImplementation(() => LayoutSystemTypes.ANVIL);
const component = render(<HOC {...widgetProps} />);
const flexPositionedLayer = component.container.getElementsByClassName(
"anvil-layout-child-" + widgetProps.widgetId,
)[0];
expect(flexPositionedLayer).toBeFalsy();
});
it("should return Auto Modal Viewer for ANVIL positioning and PAGE render mode", () => {
const widget = ModalWidget;
const HOC = withLayoutSystemHOC(widget);
const widgetProps = WidgetTypeFactories[ModalWidget.type].build({
isVisible: true,
});
jest
.spyOn(editorSelectors, "getRenderMode")
.mockImplementation(() => RenderModes.PAGE);
jest
.spyOn(layoutSystemSelectors, "getLayoutSystemType")
.mockImplementation(() => LayoutSystemTypes.ANVIL);
const component = render(<HOC {...widgetProps} />);
const flexPositionedLayer = component.container.getElementsByClassName(
"anvil-layout-child-" + widgetProps.widgetId,
)[0];
const overlayLayer =
component.container.getElementsByClassName("bp3-overlay")[0];
expect(flexPositionedLayer).toBeFalsy();
expect(overlayLayer).toBeTruthy();
});
it("should return Anvil Viewer for ANVIL positioning and PAGE render mode", () => {
const widget = InputWidget;
const HOC = withLayoutSystemHOC(widget);
const widgetProps = WidgetTypeFactories[InputWidget.type].build();
jest
.spyOn(editorSelectors, "getRenderMode")
.mockImplementation(() => RenderModes.PAGE);
jest
.spyOn(layoutSystemSelectors, "getLayoutSystemType")
.mockImplementation(() => LayoutSystemTypes.ANVIL);
const component = render(<HOC {...widgetProps} />);
const flexPositionedLayer = component.container.getElementsByClassName(
"anvil-layout-child-" + widgetProps.widgetId,
)[0];
expect(flexPositionedLayer).toBeTruthy();
});
it("should return no wrapper for CANVAS WIDGET for ANVIL positioning and PAGE render mode", () => {
const widget = CanvasWidget;
const HOC = withLayoutSystemHOC(widget);
const widgetProps = WidgetTypeFactories[CanvasWidget.type].build();
jest
.spyOn(editorSelectors, "getRenderMode")
.mockImplementation(() => RenderModes.PAGE);
jest
.spyOn(layoutSystemSelectors, "getLayoutSystemType")
.mockImplementation(() => LayoutSystemTypes.ANVIL);
const component = render(<HOC {...widgetProps} />);
const flexPositionedLayer = component.container.getElementsByClassName(
"anvil-layout-child-" + widgetProps.widgetId,
)[0];
expect(flexPositionedLayer).toBeFalsy();
});
});
});

View File

@ -0,0 +1,261 @@
import { RenderModes } from "constants/WidgetConstants";
import React from "react";
import * as editorSelectors from "selectors/editorSelectors";
import { WidgetTypeFactories } from "test/factories/Widgets/WidgetTypeFactories";
import { render } from "test/testUtils";
import InputWidget from "widgets/InputWidgetV2/widget";
import { ModalWidget } from "widgets/ModalWidget/widget";
import { withLayoutSystemWidgetHOC } from "./withLayoutSystemWidgetHOC";
import { LayoutSystemTypes } from "./types";
import * as layoutSystemSelectors from "selectors/layoutSystemSelectors";
describe("Layout System HOC's Tests", () => {
describe("Fixed Layout Layers", () => {
it("Layout system hoc should return Fixed Editor for FIXED positioning and CANVAS render mode", () => {
const widget = InputWidget;
const HOC = withLayoutSystemWidgetHOC(widget);
const widgetProps = WidgetTypeFactories[InputWidget.type].build();
jest
.spyOn(editorSelectors, "getRenderMode")
.mockImplementation(() => RenderModes.CANVAS);
jest
.spyOn(layoutSystemSelectors, "getLayoutSystemType")
.mockImplementation(() => LayoutSystemTypes.FIXED);
const component = render(<HOC {...widgetProps} />);
const positionedLayer =
component.container.getElementsByClassName("positioned-widget")[0];
const resizerLayer =
component.container.getElementsByClassName("resize-wrapper")[0];
expect(positionedLayer).toBeTruthy();
expect(resizerLayer).toBeTruthy();
});
it("Layout system hoc should return Fixed Modal Editor for FIXED positioning and CANVAS render mode", () => {
const widget = ModalWidget;
const HOC = withLayoutSystemWidgetHOC(widget);
const widgetProps = WidgetTypeFactories[ModalWidget.type].build({
isVisible: true,
});
jest
.spyOn(editorSelectors, "getRenderMode")
.mockImplementation(() => RenderModes.CANVAS);
jest
.spyOn(layoutSystemSelectors, "getLayoutSystemType")
.mockImplementation(() => LayoutSystemTypes.FIXED);
const component = render(<HOC {...widgetProps} />);
const positionedLayer =
component.container.getElementsByClassName("positioned-widget")[0];
const resizerLayer =
component.container.getElementsByClassName("resize-wrapper")[0];
const overlayLayer =
component.container.getElementsByClassName("bp3-overlay")[0];
expect(positionedLayer).toBeFalsy();
expect(overlayLayer).toBeTruthy();
expect(resizerLayer).toBeTruthy();
});
it("Layout system hoc should return Fixed Modal Viewer for FIXED positioning and PAGE render mode", () => {
const widget = ModalWidget;
const HOC = withLayoutSystemWidgetHOC(widget);
const widgetProps = WidgetTypeFactories[ModalWidget.type].build({
isVisible: true,
});
jest
.spyOn(editorSelectors, "getRenderMode")
.mockImplementation(() => RenderModes.PAGE);
jest
.spyOn(layoutSystemSelectors, "getLayoutSystemType")
.mockImplementation(() => LayoutSystemTypes.FIXED);
const component = render(<HOC {...widgetProps} />);
const positionedLayer =
component.container.getElementsByClassName("positioned-widget")[0];
const resizerLayer =
component.container.getElementsByClassName("resize-wrapper")[0];
const overlayLayer =
component.container.getElementsByClassName("bp3-overlay")[0];
expect(positionedLayer).toBeFalsy();
expect(overlayLayer).toBeTruthy();
expect(resizerLayer).toBeFalsy();
});
it("Layout system hoc should return Fixed Viewer for FIXED positioning and PAGE render mode", () => {
const widget = InputWidget;
const HOC = withLayoutSystemWidgetHOC(widget);
const widgetProps = WidgetTypeFactories[InputWidget.type].build();
jest
.spyOn(editorSelectors, "getRenderMode")
.mockImplementation(() => RenderModes.PAGE);
jest
.spyOn(layoutSystemSelectors, "getLayoutSystemType")
.mockImplementation(() => LayoutSystemTypes.FIXED);
const component = render(<HOC {...widgetProps} />);
const positionedLayer =
component.container.getElementsByClassName("positioned-widget")[0];
const resizerLayer =
component.container.getElementsByClassName("resize-wrapper")[0];
expect(positionedLayer).toBeTruthy();
expect(resizerLayer).toBeFalsy();
});
});
describe("Auto Layout Layers", () => {
it("Layout system hoc should return Auto Layout Editor for AUTO positioning and CANVAS render mode", () => {
const widget = InputWidget;
const HOC = withLayoutSystemWidgetHOC(widget);
const widgetProps = WidgetTypeFactories[InputWidget.type].build();
jest
.spyOn(editorSelectors, "getRenderMode")
.mockImplementation(() => RenderModes.CANVAS);
jest
.spyOn(layoutSystemSelectors, "getLayoutSystemType")
.mockImplementation(() => LayoutSystemTypes.AUTO);
const component = render(<HOC {...widgetProps} />);
const flexPositionedLayer = component.container.getElementsByClassName(
"auto-layout-child-" + widgetProps.widgetId,
)[0];
const resizerLayer =
component.container.getElementsByClassName("resize-wrapper")[0];
expect(flexPositionedLayer).toBeTruthy();
expect(resizerLayer).toBeTruthy();
});
it("Layout system hoc should return Auto Modal Editor for AUTO positioning and CANVAS render mode", () => {
const widget = ModalWidget;
const HOC = withLayoutSystemWidgetHOC(widget);
const widgetProps = WidgetTypeFactories[ModalWidget.type].build({
isVisible: true,
});
jest
.spyOn(editorSelectors, "getRenderMode")
.mockImplementation(() => RenderModes.CANVAS);
jest
.spyOn(layoutSystemSelectors, "getLayoutSystemType")
.mockImplementation(() => LayoutSystemTypes.AUTO);
const component = render(<HOC {...widgetProps} />);
const flexPositionedLayer = component.container.getElementsByClassName(
"auto-layout-child-" + widgetProps.widgetId,
)[0];
const resizerLayer =
component.container.getElementsByClassName("resize-wrapper")[0];
const overlayLayer =
component.container.getElementsByClassName("bp3-overlay")[0];
expect(flexPositionedLayer).toBeFalsy();
expect(overlayLayer).toBeTruthy();
expect(resizerLayer).toBeTruthy();
});
it("Layout system hoc should return Auto Modal Viewer for AUTO positioning and PAGE render mode", () => {
const widget = ModalWidget;
const HOC = withLayoutSystemWidgetHOC(widget);
const widgetProps = WidgetTypeFactories[ModalWidget.type].build({
isVisible: true,
});
jest
.spyOn(editorSelectors, "getRenderMode")
.mockImplementation(() => RenderModes.PAGE);
jest
.spyOn(layoutSystemSelectors, "getLayoutSystemType")
.mockImplementation(() => LayoutSystemTypes.AUTO);
const component = render(<HOC {...widgetProps} />);
const flexPositionedLayer = component.container.getElementsByClassName(
"auto-layout-child-" + widgetProps.widgetId,
)[0];
const resizerLayer =
component.container.getElementsByClassName("resize-wrapper")[0];
const overlayLayer =
component.container.getElementsByClassName("bp3-overlay")[0];
expect(flexPositionedLayer).toBeFalsy();
expect(overlayLayer).toBeTruthy();
expect(resizerLayer).toBeFalsy();
});
it("Layout system hoc should return Auto Viewer for Auto positioning and PAGE render mode", () => {
const widget = InputWidget;
const HOC = withLayoutSystemWidgetHOC(widget);
const widgetProps = WidgetTypeFactories[InputWidget.type].build();
jest
.spyOn(editorSelectors, "getRenderMode")
.mockImplementation(() => RenderModes.PAGE);
jest
.spyOn(layoutSystemSelectors, "getLayoutSystemType")
.mockImplementation(() => LayoutSystemTypes.AUTO);
const component = render(<HOC {...widgetProps} />);
const flexPositionedLayer = component.container.getElementsByClassName(
"auto-layout-child-" + widgetProps.widgetId,
)[0];
const resizerLayer =
component.container.getElementsByClassName("resize-wrapper")[0];
expect(flexPositionedLayer).toBeTruthy();
expect(resizerLayer).toBeFalsy();
});
});
// describe("Anvil Layout Layers", () => {
// it("Layout system hoc should return Anvil Editor for ANVIL positioning and CANVAS render mode", () => {
// const widget = InputWidget;
// const HOC = withLayoutSystemWidgetHOC(widget);
// const widgetProps = WidgetTypeFactories[InputWidget.type].build();
// jest
// .spyOn(editorSelectors, "getRenderMode")
// .mockImplementation(() => RenderModes.CANVAS);
// jest
// .spyOn(layoutSystemSelectors, "getLayoutSystemType")
// .mockImplementation(() => LayoutSystemTypes.ANVIL);
// const component = render(<HOC {...widgetProps} />);
// const flexPositionedLayer = component.container.getElementsByClassName(
// "anvil-layout-child-" + widgetProps.widgetId,
// )[0];
// expect(flexPositionedLayer).toBeTruthy();
// });
// it("should return Auto Modal Editor for ANVIL positioning and CANVAS render mode", () => {
// const widget = ModalWidget;
// const HOC = withLayoutSystemWidgetHOC(widget);
// const widgetProps = WidgetTypeFactories[ModalWidget.type].build({
// isVisible: true,
// });
// jest
// .spyOn(editorSelectors, "getRenderMode")
// .mockImplementation(() => RenderModes.CANVAS);
// jest
// .spyOn(layoutSystemSelectors, "getLayoutSystemType")
// .mockImplementation(() => LayoutSystemTypes.ANVIL);
// const component = render(<HOC {...widgetProps} />);
// const flexPositionedLayer = component.container.getElementsByClassName(
// "anvil-layout-child-" + widgetProps.widgetId,
// )[0];
// const overlayLayer =
// component.container.getElementsByClassName("bp3-overlay")[0];
// expect(flexPositionedLayer).toBeFalsy();
// expect(overlayLayer).toBeTruthy();
// });
// it("should return Auto Modal Viewer for ANVIL positioning and PAGE render mode", () => {
// const widget = ModalWidget;
// const HOC = withLayoutSystemWidgetHOC(widget);
// const widgetProps = WidgetTypeFactories[ModalWidget.type].build({
// isVisible: true,
// });
// jest
// .spyOn(editorSelectors, "getRenderMode")
// .mockImplementation(() => RenderModes.PAGE);
// jest
// .spyOn(layoutSystemSelectors, "getLayoutSystemType")
// .mockImplementation(() => LayoutSystemTypes.ANVIL);
// const component = render(<HOC {...widgetProps} />);
// const flexPositionedLayer = component.container.getElementsByClassName(
// "anvil-layout-child-" + widgetProps.widgetId,
// )[0];
// const overlayLayer =
// component.container.getElementsByClassName("bp3-overlay")[0];
// expect(flexPositionedLayer).toBeFalsy();
// expect(overlayLayer).toBeTruthy();
// });
// it("should return Anvil Viewer for ANVIL positioning and PAGE render mode", () => {
// const widget = InputWidget;
// const HOC = withLayoutSystemWidgetHOC(widget);
// const widgetProps = WidgetTypeFactories[InputWidget.type].build();
// jest
// .spyOn(editorSelectors, "getRenderMode")
// .mockImplementation(() => RenderModes.PAGE);
// jest
// .spyOn(layoutSystemSelectors, "getLayoutSystemType")
// .mockImplementation(() => LayoutSystemTypes.ANVIL);
// const component = render(<HOC {...widgetProps} />);
// const flexPositionedLayer = component.container.getElementsByClassName(
// "anvil-layout-child-" + widgetProps.widgetId,
// )[0];
// expect(flexPositionedLayer).toBeTruthy();
// });
// });
});

View File

@ -6,21 +6,27 @@ import { getLayoutSystemType } from "selectors/layoutSystemSelectors";
import type { WidgetProps } from "widgets/BaseWidget"; import type { WidgetProps } from "widgets/BaseWidget";
import { getAutoLayoutSystem } from "./autolayout"; import { getAutoLayoutSystem } from "./autolayout";
import { getFixedLayoutSystem } from "./fixedlayout"; import { getFixedLayoutSystem } from "./fixedlayout";
import type { LayoutSystem } from "./types";
import { LayoutSystemTypes } from "./types"; import { LayoutSystemTypes } from "./types";
import { getAnvilSystem } from "./anvil";
export type LayoutSystem = { /**
LayoutSystemWrapper: (props: WidgetProps) => any; *
propertyEnhancer: (props: WidgetProps) => WidgetProps; * @param renderMode - render mode specifies whether the application is in edit/deploy mode.
}; * @param appPositioningType - layout system of the application.
* @returns
* @property widgetSystem - widget specific wrappers and enhancers of a layout system
* @property canvasSystem - canvas specific implementation and enhancers of a layout system
*/
export const getLayoutSystem = ( export const getLayoutSystem = (
renderMode: RenderModes, renderMode: RenderModes,
layoutSystemType: LayoutSystemTypes, layoutSystemType: LayoutSystemTypes,
): LayoutSystem => { ): LayoutSystem => {
switch (layoutSystemType) { switch (layoutSystemType) {
case LayoutSystemTypes.ANVIL: // Removing Anvil system until canvas system of Anvil is Implemented.
return getAnvilSystem(renderMode); // when re-introducing pls make sure to uncomment anvil based test cases in withLayoutSystemWidgetHOC.test
// case LayoutSystemTypes.ANVIL:
// return getAnvilLayoutSystem(renderMode);
case LayoutSystemTypes.AUTO: case LayoutSystemTypes.AUTO:
return getAutoLayoutSystem(renderMode); return getAutoLayoutSystem(renderMode);
default: default:
@ -33,26 +39,24 @@ const LayoutSystemWrapper = ({
widgetProps, widgetProps,
}: { }: {
widgetProps: WidgetProps; widgetProps: WidgetProps;
Widget: (props: WidgetProps) => any; Widget: (props: WidgetProps) => JSX.Element;
}) => { }) => {
const renderMode = useSelector(getRenderMode); const renderMode = useSelector(getRenderMode);
const layoutSystemType = useSelector(getLayoutSystemType); const layoutSystemType = useSelector(getLayoutSystemType);
// based on layoutSystemType and renderMode // based on layoutSystemType and renderMode
// get the layout system wrapper(adds layout system specific functionality) and // get the layout system wrapper(adds layout system specific functionality) and
// properties enhancer(adds/modifies properties of a widget based on layout system) // properties enhancer(adds/modifies properties of a widget based on layout system)
const { LayoutSystemWrapper, propertyEnhancer } = getLayoutSystem( const { widgetSystem } = getLayoutSystem(renderMode, layoutSystemType);
renderMode, const { propertyEnhancer, WidgetWrapper } = widgetSystem;
layoutSystemType,
);
const enhancedProperties = propertyEnhancer(widgetProps); const enhancedProperties = propertyEnhancer(widgetProps);
return ( return (
<LayoutSystemWrapper {...enhancedProperties}> <WidgetWrapper {...enhancedProperties}>
<Widget {...enhancedProperties} /> <Widget {...enhancedProperties} />
</LayoutSystemWrapper> </WidgetWrapper>
); );
}; };
export const withLayoutSystemHOC = (Widget: any) => { export const withLayoutSystemWidgetHOC = (Widget: any) => {
return function LayoutWrappedWidget(props: WidgetProps) { return function LayoutWrappedWidget(props: WidgetProps) {
return <LayoutSystemWrapper Widget={Widget} widgetProps={props} />; return <LayoutSystemWrapper Widget={Widget} widgetProps={props} />;
}; };

View File

@ -1,9 +1,7 @@
import React, { useEffect } from "react"; import React, { useEffect } from "react";
import WidgetFactory from "WidgetProvider/factory";
import AnalyticsUtil from "utils/AnalyticsUtil"; import AnalyticsUtil from "utils/AnalyticsUtil";
import { useDynamicAppLayout } from "utils/hooks/useDynamicAppLayout"; import { useDynamicAppLayout } from "utils/hooks/useDynamicAppLayout";
import type { CanvasWidgetStructure } from "WidgetProvider/constants"; import type { CanvasWidgetStructure } from "WidgetProvider/constants";
import { RenderModes } from "constants/WidgetConstants";
import { useSelector } from "react-redux"; import { useSelector } from "react-redux";
import { import {
getCurrentApplication, getCurrentApplication,
@ -16,6 +14,8 @@ import { PageView, PageViewWrapper } from "./AppPage.styled";
import { useIsMobileDevice } from "utils/hooks/useDeviceDetect"; import { useIsMobileDevice } from "utils/hooks/useDeviceDetect";
import { APP_MODE } from "entities/App"; import { APP_MODE } from "entities/App";
import { useLocation } from "react-router"; import { useLocation } from "react-router";
import { renderAppsmithCanvas } from "layoutSystems/CanvasFactory";
import type { WidgetProps } from "widgets/BaseWidget";
type AppPageProps = { type AppPageProps = {
appName?: string; appName?: string;
@ -63,7 +63,7 @@ export function AppPage(props: AppPageProps) {
> >
<PageView className="t--app-viewer-page" width={props.canvasWidth}> <PageView className="t--app-viewer-page" width={props.canvasWidth}>
{props.widgetsStructure.widgetId && {props.widgetsStructure.widgetId &&
WidgetFactory.createWidget(props.widgetsStructure, RenderModes.PAGE)} renderAppsmithCanvas(props.widgetsStructure as WidgetProps)}
</PageView> </PageView>
</PageViewWrapper> </PageViewWrapper>
); );

View File

@ -3,10 +3,7 @@ import React from "react";
import styled from "styled-components"; import styled from "styled-components";
import * as Sentry from "@sentry/react"; import * as Sentry from "@sentry/react";
import { useSelector } from "react-redux"; import { useSelector } from "react-redux";
import WidgetFactory from "WidgetProvider/factory";
import type { CanvasWidgetStructure } from "WidgetProvider/constants"; import type { CanvasWidgetStructure } from "WidgetProvider/constants";
import { RenderModes } from "constants/WidgetConstants";
import useWidgetFocus from "utils/hooks/useWidgetFocus"; import useWidgetFocus from "utils/hooks/useWidgetFocus";
import { useFeatureFlag } from "utils/hooks/useFeatureFlag"; import { useFeatureFlag } from "utils/hooks/useFeatureFlag";
import { previewModeSelector } from "selectors/editorSelectors"; import { previewModeSelector } from "selectors/editorSelectors";
@ -18,6 +15,8 @@ import {
useTheme, useTheme,
} from "@design-system/theming"; } from "@design-system/theming";
import { getIsAppSettingsPaneWithNavigationTabOpen } from "selectors/appSettingsPaneSelectors"; import { getIsAppSettingsPaneWithNavigationTabOpen } from "selectors/appSettingsPaneSelectors";
import { renderAppsmithCanvas } from "layoutSystems/CanvasFactory";
import type { WidgetProps } from "widgets/BaseWidget";
interface CanvasProps { interface CanvasProps {
widgetsStructure: CanvasWidgetStructure; widgetsStructure: CanvasWidgetStructure;
@ -90,10 +89,7 @@ const Canvas = (props: CanvasProps) => {
width={canvasWidth} width={canvasWidth}
> >
{props.widgetsStructure.widgetId && {props.widgetsStructure.widgetId &&
WidgetFactory.createWidget( renderAppsmithCanvas(props.widgetsStructure as WidgetProps)}
props.widgetsStructure,
RenderModes.CANVAS,
)}
</Wrapper> </Wrapper>
</WDSThemeProvider> </WDSThemeProvider>
); );

View File

@ -31,7 +31,6 @@ import {
} from "utils/hooks/useDynamicAppLayout"; } from "utils/hooks/useDynamicAppLayout";
import Canvas from "../Canvas"; import Canvas from "../Canvas";
import type { AppState } from "@appsmith/reducers"; import type { AppState } from "@appsmith/reducers";
import { MainContainerResizer } from "layoutSystems/autolayout/MainContainerResizer/MainContainerResizer";
import { useFeatureFlag } from "utils/hooks/useFeatureFlag"; import { useFeatureFlag } from "utils/hooks/useFeatureFlag";
import { getIsAnonymousDataPopupVisible } from "selectors/onboardingSelectors"; import { getIsAnonymousDataPopupVisible } from "selectors/onboardingSelectors";
import { import {
@ -39,6 +38,7 @@ import {
useLayoutSystemFeatures, useLayoutSystemFeatures,
} from "../../../layoutSystems/common/useLayoutSystemFeatures"; } from "../../../layoutSystems/common/useLayoutSystemFeatures";
import { CANVAS_VIEWPORT } from "constants/componentClassNameConstants"; import { CANVAS_VIEWPORT } from "constants/componentClassNameConstants";
import { MainContainerResizer } from "layoutSystems/common/mainContainerResizer/MainContainerResizer";
type MainCanvasWrapperProps = { type MainCanvasWrapperProps = {
isPreviewMode: boolean; isPreviewMode: boolean;

View File

@ -2,7 +2,7 @@ import { createImmerReducer } from "utils/ReducerUtils";
import type { ReduxAction } from "@appsmith/constants/ReduxActionConstants"; import type { ReduxAction } from "@appsmith/constants/ReduxActionConstants";
import { ReduxActionTypes } from "@appsmith/constants/ReduxActionConstants"; import { ReduxActionTypes } from "@appsmith/constants/ReduxActionConstants";
import { MAIN_CONTAINER_WIDGET_ID } from "constants/WidgetConstants"; import { MAIN_CONTAINER_WIDGET_ID } from "constants/WidgetConstants";
import type { XYCord } from "layoutSystems/common/CanvasArenas/ArenaTypes"; import type { XYCord } from "layoutSystems/common/canvasArenas/ArenaTypes";
const initialState: CanvasSelectionState = { const initialState: CanvasSelectionState = {
isDraggingForSelection: false, isDraggingForSelection: false,

View File

@ -6,7 +6,7 @@ import {
import { generateAutoHeightLayoutTreeAction } from "actions/autoHeightActions"; import { generateAutoHeightLayoutTreeAction } from "actions/autoHeightActions";
import type { WidgetAddChild } from "actions/pageActions"; import type { WidgetAddChild } from "actions/pageActions";
import { updateAndSaveLayout } from "actions/pageActions"; import { updateAndSaveLayout } from "actions/pageActions";
import { calculateDropTargetRows } from "components/editorComponents/DropTargetUtils"; import { calculateDropTargetRows } from "layoutSystems/common/dropTarget/DropTargetUtils";
import { CANVAS_DEFAULT_MIN_HEIGHT_PX } from "constants/AppConstants"; import { CANVAS_DEFAULT_MIN_HEIGHT_PX } from "constants/AppConstants";
import type { OccupiedSpace } from "constants/CanvasEditorConstants"; import type { OccupiedSpace } from "constants/CanvasEditorConstants";
import { import {
@ -40,7 +40,7 @@ import { collisionCheckPostReflow } from "utils/reflowHookUtils";
import type { WidgetProps } from "widgets/BaseWidget"; import type { WidgetProps } from "widgets/BaseWidget";
import { BlueprintOperationTypes } from "WidgetProvider/constants"; import { BlueprintOperationTypes } from "WidgetProvider/constants";
import { toast } from "design-system"; import { toast } from "design-system";
import type { WidgetDraggingUpdateParams } from "layoutSystems/common/CanvasArenas/ArenaTypes"; import type { WidgetDraggingUpdateParams } from "layoutSystems/common/canvasArenas/ArenaTypes";
import { getLayoutSystemType } from "selectors/layoutSystemSelectors"; import { getLayoutSystemType } from "selectors/layoutSystemSelectors";
export type WidgetMoveParams = { export type WidgetMoveParams = {

View File

@ -1,6 +1,6 @@
import { getCanvasWidgets } from "@appsmith/selectors/entitiesSelector"; import { getCanvasWidgets } from "@appsmith/selectors/entitiesSelector";
import { GridDefaults, type RenderModes } from "constants/WidgetConstants"; import { GridDefaults, type RenderModes } from "constants/WidgetConstants";
import { getLayoutSystem } from "layoutSystems/withLayoutSystemHOC"; import { getLayoutSystem } from "layoutSystems/withLayoutSystemWidgetHOC";
import type { import type {
CanvasWidgetsReduxState, CanvasWidgetsReduxState,
FlattenedWidgetProps, FlattenedWidgetProps,
@ -21,7 +21,9 @@ function buildFlattenedChildCanvasWidgets(
flattenedChildCanvasWidgets: Record<string, FlattenedWidgetProps> = {}, flattenedChildCanvasWidgets: Record<string, FlattenedWidgetProps> = {},
) { ) {
const parentWidget = canvasWidgets[parentWidgetId]; const parentWidget = canvasWidgets[parentWidgetId];
const { propertyEnhancer } = getLayoutSystem(renderMode, layoutSystemType); const {
widgetSystem: { propertyEnhancer },
} = getLayoutSystem(renderMode, layoutSystemType);
parentWidget?.children?.forEach((childId) => { parentWidget?.children?.forEach((childId) => {
const childWidget = canvasWidgets[childId]; const childWidget = canvasWidgets[childId];
let parentRowSpace = let parentRowSpace =

View File

@ -18,7 +18,7 @@ import {
getDraggingSpacesFromBlocks, getDraggingSpacesFromBlocks,
getMousePositionsOnCanvas, getMousePositionsOnCanvas,
} from "./WidgetPropsUtils"; } from "./WidgetPropsUtils";
import type { WidgetDraggingBlock } from "layoutSystems/common/CanvasArenas/ArenaTypes"; import type { WidgetDraggingBlock } from "layoutSystems/common/canvasArenas/ArenaTypes";
import { ASSETS_CDN_URL } from "constants/ThirdPartyConstants"; import { ASSETS_CDN_URL } from "constants/ThirdPartyConstants";
describe("WidgetProps tests", () => { describe("WidgetProps tests", () => {

View File

@ -24,7 +24,7 @@ import { checkIsDSLAutoLayout } from "../layoutSystems/autolayout/utils/AutoLayo
import type { import type {
WidgetDraggingBlock, WidgetDraggingBlock,
XYCord, XYCord,
} from "layoutSystems/common/CanvasArenas/ArenaTypes"; } from "layoutSystems/common/canvasArenas/ArenaTypes";
export type WidgetOperationParams = { export type WidgetOperationParams = {
operation: WidgetOperation; operation: WidgetOperation;

View File

@ -4,7 +4,7 @@ import { withLazyRender } from "widgets/withLazyRender";
import type BaseWidget from "widgets/BaseWidget"; import type BaseWidget from "widgets/BaseWidget";
import withWidgetProps from "widgets/withWidgetProps"; import withWidgetProps from "widgets/withWidgetProps";
import * as Sentry from "@sentry/react"; import * as Sentry from "@sentry/react";
import { withLayoutSystemHOC } from "../../layoutSystems/withLayoutSystemHOC"; import { withLayoutSystemWidgetHOC } from "../../layoutSystems/withLayoutSystemWidgetHOC";
export interface BaseWidgetProps extends WidgetProps, WidgetState {} export interface BaseWidgetProps extends WidgetProps, WidgetState {}
@ -20,7 +20,7 @@ export const withBaseWidgetHOC = (
? MetaWidget ? MetaWidget
: withLazyRender(MetaWidget as any); : withLazyRender(MetaWidget as any);
// Adds respective layout specific layers to a widget // Adds respective layout specific layers to a widget
const LayoutWrappedWidget = withLayoutSystemHOC(LazyRenderedWidget); const LayoutWrappedWidget = withLayoutSystemWidgetHOC(LazyRenderedWidget);
// Adds/Enhances widget props // Adds/Enhances widget props
const HydratedWidget = withWidgetProps(LayoutWrappedWidget as any); const HydratedWidget = withWidgetProps(LayoutWrappedWidget as any);
// Wraps the widget to be profiled via sentry // Wraps the widget to be profiled via sentry

View File

@ -1,36 +1,15 @@
import { import { ResponsiveBehavior } from "layoutSystems/common/utils/constants";
LayoutDirection,
Positioning,
ResponsiveBehavior,
} from "layoutSystems/common/utils/constants";
import DropTargetComponent from "components/editorComponents/DropTargetComponent";
import { CANVAS_DEFAULT_MIN_HEIGHT_PX } from "constants/AppConstants";
import { FILL_WIDGET_MIN_WIDTH } from "constants/minWidthConstants"; import { FILL_WIDGET_MIN_WIDTH } from "constants/minWidthConstants";
import { GridDefaults, RenderModes } from "constants/WidgetConstants";
import WidgetsMultiSelectBox from "pages/Editor/WidgetsMultiSelectBox";
import type { CSSProperties } from "react";
import React from "react";
import { getCanvasClassName } from "utils/generators";
import type { DerivedPropertiesMap } from "WidgetProvider/factory"; import type { DerivedPropertiesMap } from "WidgetProvider/factory";
import WidgetFactory from "WidgetProvider/factory";
import { getCanvasSnapRows } from "utils/WidgetPropsUtils";
import type { WidgetProps } from "widgets/BaseWidget";
import type { ContainerWidgetProps } from "widgets/ContainerWidget/widget";
import ContainerWidget from "widgets/ContainerWidget/widget"; import ContainerWidget from "widgets/ContainerWidget/widget";
import type { import type { WidgetDefaultProps } from "../WidgetProvider/constants";
CanvasWidgetStructure,
DSLWidget,
WidgetDefaultProps,
} from "../WidgetProvider/constants";
import ContainerComponent from "./ContainerWidget/component";
import { LayoutSystemTypes } from "layoutSystems/types";
import FlexBoxComponent from "../layoutSystems/autolayout/common/flexCanvas/FlexBoxComponent";
import { AutoCanvasDraggingArena } from "layoutSystems/autolayout/editor/AutoLayoutCanvasArenas/AutoCanvasDraggingArena";
import { FixedCanvasDraggingArena } from "layoutSystems/fixedlayout/editor/FixedLayoutCanvasArenas/FixedCanvasDraggingArena";
import { CanvasSelectionArena } from "layoutSystems/fixedlayout/editor/FixedLayoutCanvasArenas/CanvasSelectionArena";
import type { AutocompletionDefinitions } from "WidgetProvider/constants"; import type { AutocompletionDefinitions } from "WidgetProvider/constants";
import type { SetterConfig } from "entities/AppTheming"; import type { SetterConfig } from "entities/AppTheming";
/**
* Please refer to renderAppsmithCanvas in CanvasFactory to see current version of How CanvasWidget is rendered.
*/
class CanvasWidget extends ContainerWidget { class CanvasWidget extends ContainerWidget {
static type = "CANVAS_WIDGET"; static type = "CANVAS_WIDGET";
@ -67,188 +46,6 @@ class CanvasWidget extends ContainerWidget {
return null; return null;
} }
getCanvasProps(): DSLWidget & { minHeight: number } {
return {
...this.props,
parentRowSpace: 1,
parentColumnSpace: 1,
topRow: 0,
leftColumn: 0,
containerStyle: "none",
detachFromLayout: true,
minHeight: this.props.minHeight || CANVAS_DEFAULT_MIN_HEIGHT_PX,
shouldScrollContents: false,
};
}
renderAsDropTarget() {
const canvasProps = this.getCanvasProps();
const { snapColumnSpace } = this.getSnapSpaces();
return (
<DropTargetComponent
bottomRow={this.props.bottomRow}
isListWidgetCanvas={this.props.isListWidgetCanvas}
isMobile={this.props.isMobile}
minHeight={this.props.minHeight || CANVAS_DEFAULT_MIN_HEIGHT_PX}
mobileBottomRow={this.props.mobileBottomRow}
noPad={this.props.noPad}
parentId={this.props.parentId}
snapColumnSpace={snapColumnSpace}
useAutoLayout={this.props.useAutoLayout}
widgetId={this.props.widgetId}
>
{this.renderAsContainerComponent(canvasProps)}
</DropTargetComponent>
);
}
renderChildWidget(childWidgetData: CanvasWidgetStructure): React.ReactNode {
if (!childWidgetData) return null;
const childWidget = { ...childWidgetData };
const snapSpaces = this.getSnapSpaces();
childWidget.parentColumnSpace = snapSpaces.snapColumnSpace;
childWidget.parentRowSpace = snapSpaces.snapRowSpace;
if (this.props.noPad) childWidget.noContainerOffset = true;
childWidget.parentId = this.props.widgetId;
// Pass layout controls to children
childWidget.positioning =
childWidget?.positioning || this.props.positioning;
childWidget.isFlexChild = this.props.useAutoLayout;
childWidget.direction = this.getDirection();
return WidgetFactory.createWidget(childWidget, this.props.renderMode);
}
renderAsContainerComponent(
props: ContainerWidgetProps<WidgetProps>,
): JSX.Element {
const direction = this.getDirection();
const snapRows = getCanvasSnapRows(
this.props.bottomRow,
this.props.mobileBottomRow,
this.props.isMobile,
this.props.layoutSystemType === LayoutSystemTypes.AUTO,
);
return (
<ContainerComponent {...props}>
{props.renderMode === RenderModes.CANVAS && (
<>
{
//Temporary change, will have better separation logic with Canvas onion implementation
!this.props.useAutoLayout ? (
<FixedCanvasDraggingArena
{...this.getSnapSpaces()}
canExtend={props.canExtend}
dropDisabled={!!props.dropDisabled}
noPad={this.props.noPad}
parentId={props.parentId}
snapRows={snapRows}
widgetId={props.widgetId}
widgetName={props.widgetName}
/>
) : (
<AutoCanvasDraggingArena
{...this.getSnapSpaces()}
alignItems={props.alignItems}
canExtend={props.canExtend}
direction={direction}
dropDisabled={!!props.dropDisabled}
noPad={this.props.noPad}
parentId={props.parentId}
snapRows={snapRows}
widgetId={props.widgetId}
widgetName={props.widgetName}
/>
)
}
<CanvasSelectionArena
{...this.getSnapSpaces()}
canExtend={props.canExtend}
dropDisabled={!!props.dropDisabled}
parentId={props.parentId}
snapRows={snapRows}
widgetId={props.widgetId}
/>
</>
)}
{this.props.useAutoLayout
? this.renderFlexCanvas(direction)
: this.renderFixedCanvas(props)}
</ContainerComponent>
);
}
renderFlexCanvas(direction: LayoutDirection) {
const stretchFlexBox = !this.props.children || !this.props.children?.length;
return (
<FlexBoxComponent
direction={direction}
flexLayers={this.props.flexLayers || []}
isMobile={this.props.isMobile || false}
stretchHeight={stretchFlexBox}
useAutoLayout={this.props.useAutoLayout || false}
widgetId={this.props.widgetId}
>
{this.renderChildren()}
</FlexBoxComponent>
);
}
renderFixedCanvas(props: ContainerWidgetProps<WidgetProps>) {
return (
<>
<WidgetsMultiSelectBox
{...this.getSnapSpaces()}
noContainerOffset={!!props.noContainerOffset}
widgetId={this.props.widgetId}
widgetType={this.props.type}
/>
{this.renderChildren()}
</>
);
}
getDirection(): LayoutDirection {
return this.props.positioning === Positioning.Vertical
? LayoutDirection.Vertical
: LayoutDirection.Horizontal;
}
getPageView() {
let height = 0;
const snapRows = getCanvasSnapRows(
this.props.bottomRow,
this.props.mobileBottomRow,
this.props.isMobile,
this.props.layoutSystemType === LayoutSystemTypes.AUTO,
);
height = snapRows * GridDefaults.DEFAULT_GRID_ROW_HEIGHT;
const style: CSSProperties = {
width: "100%",
height: this.props.isListWidgetCanvas ? "auto" : `${height}px`,
background: "none",
position: "relative",
};
// This div is the DropTargetComponent alternative for the page view
// DropTargetComponent and this div are responsible for the canvas height
return (
<div className={getCanvasClassName()} style={style}>
{this.renderAsContainerComponent(this.getCanvasProps())}
</div>
);
}
getWidgetView() {
//ToDo(Ashok): Make sure Layout Factory takes care of render mode based widget view.
// untill then this part of the widget will have a abstraction leak.
if (!this.props.dropDisabled && this.props.renderMode === "CANVAS") {
return this.renderAsDropTarget();
}
return this.getPageView();
}
static getDerivedPropertiesMap(): DerivedPropertiesMap { static getDerivedPropertiesMap(): DerivedPropertiesMap {
return {}; return {};
} }

View File

@ -131,7 +131,6 @@ function ContainerComponentWrapper(
? "auto-layout" ? "auto-layout"
: "" : ""
}`} }`}
data-widgetId={props.widgetId}
dropDisabled={props.dropDisabled} dropDisabled={props.dropDisabled}
onClick={props.onClick} onClick={props.onClick}
onClickCapture={props.onClickCapture} onClickCapture={props.onClickCapture}

View File

@ -1,18 +1,13 @@
import type { MouseEventHandler } from "react"; import type { MouseEventHandler } from "react";
import React from "react"; import React from "react";
import type { DerivedPropertiesMap } from "WidgetProvider/factory"; import type { DerivedPropertiesMap } from "WidgetProvider/factory";
import WidgetFactory from "WidgetProvider/factory";
import type { ContainerStyle } from "../component"; import type { ContainerStyle } from "../component";
import ContainerComponent from "../component"; import ContainerComponent from "../component";
import type { WidgetProps, WidgetState } from "widgets/BaseWidget"; import type { WidgetProps, WidgetState } from "widgets/BaseWidget";
import BaseWidget from "widgets/BaseWidget"; import BaseWidget from "widgets/BaseWidget";
import { ValidationTypes } from "constants/WidgetValidation"; import { ValidationTypes } from "constants/WidgetValidation";
import { compact, map, sortBy } from "lodash"; import { compact, map, sortBy } from "lodash";
import WidgetsMultiSelectBox from "pages/Editor/WidgetsMultiSelectBox"; import WidgetsMultiSelectBox from "layoutSystems/fixedlayout/common/widgetGrouping/WidgetsMultiSelectBox";
import type { SetterConfig, Stylesheet } from "entities/AppTheming"; import type { SetterConfig, Stylesheet } from "entities/AppTheming";
import { getSnappedGrid } from "sagas/WidgetOperationUtils"; import { getSnappedGrid } from "sagas/WidgetOperationUtils";
import { ReduxActionTypes } from "@appsmith/constants/ReduxActionConstants"; import { ReduxActionTypes } from "@appsmith/constants/ReduxActionConstants";
@ -38,6 +33,7 @@ import {
Positioning, Positioning,
ResponsiveBehavior, ResponsiveBehavior,
} from "layoutSystems/common/utils/constants"; } from "layoutSystems/common/utils/constants";
import { renderAppsmithCanvas } from "layoutSystems/CanvasFactory";
export class ContainerWidget extends BaseWidget< export class ContainerWidget extends BaseWidget<
ContainerWidgetProps<WidgetProps>, ContainerWidgetProps<WidgetProps>,
@ -314,7 +310,7 @@ export class ContainerWidget extends BaseWidget<
childWidget.useAutoLayout = this.props.positioning childWidget.useAutoLayout = this.props.positioning
? this.props.positioning === Positioning.Vertical ? this.props.positioning === Positioning.Vertical
: false; : false;
return WidgetFactory.createWidget(childWidget, this.props.renderMode); return renderAppsmithCanvas(childWidget as WidgetProps);
} }
renderChildren = () => { renderChildren = () => {

View File

@ -65,6 +65,7 @@ import { getAssetUrl } from "@appsmith/utils/airgapHelpers";
import { ASSETS_CDN_URL } from "constants/ThirdPartyConstants"; import { ASSETS_CDN_URL } from "constants/ThirdPartyConstants";
import { FILL_WIDGET_MIN_WIDTH } from "constants/minWidthConstants"; import { FILL_WIDGET_MIN_WIDTH } from "constants/minWidthConstants";
import IconSVG from "../icon.svg"; import IconSVG from "../icon.svg";
import { renderAppsmithCanvas } from "layoutSystems/CanvasFactory";
const LIST_WIDGET_PAGINATION_HEIGHT = 36; const LIST_WIDGET_PAGINATION_HEIGHT = 36;
@ -865,8 +866,7 @@ class ListWidget extends BaseWidget<ListWidgetProps<WidgetProps>, WidgetState> {
this.props.positioning || childWidgetData.positioning; this.props.positioning || childWidgetData.positioning;
childWidgetData.positioning = positioning; childWidgetData.positioning = positioning;
childWidgetData.useAutoLayout = positioning === Positioning.Vertical; childWidgetData.useAutoLayout = positioning === Positioning.Vertical;
return renderAppsmithCanvas(childWidgetData as WidgetProps);
return WidgetFactory.createWidget(childWidgetData, this.props.renderMode);
}; };
getGridGap = () => getGridGap = () =>

View File

@ -17,7 +17,6 @@ import Loader from "../component/Loader";
import MetaWidgetContextProvider from "../../MetaWidgetContextProvider"; import MetaWidgetContextProvider from "../../MetaWidgetContextProvider";
import type { GeneratorOptions, HookOptions } from "../MetaWidgetGenerator"; import type { GeneratorOptions, HookOptions } from "../MetaWidgetGenerator";
import MetaWidgetGenerator from "../MetaWidgetGenerator"; import MetaWidgetGenerator from "../MetaWidgetGenerator";
import WidgetFactory from "WidgetProvider/factory";
import type { BatchPropertyUpdatePayload } from "actions/controlActions"; import type { BatchPropertyUpdatePayload } from "actions/controlActions";
import type { import type {
AutocompletionDefinitions, AutocompletionDefinitions,
@ -52,6 +51,7 @@ import { generateTypeDef } from "utils/autocomplete/dataTreeTypeDefCreator";
import defaultProps from "./defaultProps"; import defaultProps from "./defaultProps";
import IconSVG from "../icon.svg"; import IconSVG from "../icon.svg";
import { renderAppsmithCanvas } from "layoutSystems/CanvasFactory";
const getCurrentItemsViewBindingTemplate = () => ({ const getCurrentItemsViewBindingTemplate = () => ({
prefix: "{{[", prefix: "{{[",
@ -1217,7 +1217,7 @@ class ListWidget extends BaseWidget<
}, },
}; };
}); });
return WidgetFactory.createWidget(child, this.props.renderMode); return renderAppsmithCanvas(child as WidgetProps);
}, },
); );

View File

@ -1,6 +1,5 @@
import React from "react"; import React from "react";
import type { WidgetProps } from "./BaseWidget"; import type { WidgetProps } from "./BaseWidget";
import type BaseWidget from "./BaseWidget";
import { debounce, fromPairs, isEmpty } from "lodash"; import { debounce, fromPairs, isEmpty } from "lodash";
import { EditorContext } from "components/editorComponents/EditorContextProvider"; import { EditorContext } from "components/editorComponents/EditorContextProvider";
import AppsmithConsole from "utils/AppsmithConsole"; import AppsmithConsole from "utils/AppsmithConsole";
@ -12,6 +11,7 @@ import { getWidgetMetaProps } from "sagas/selectors";
import type { AppState } from "@appsmith/reducers"; import type { AppState } from "@appsmith/reducers";
import { error } from "loglevel"; import { error } from "loglevel";
import WidgetFactory from "WidgetProvider/factory"; import WidgetFactory from "WidgetProvider/factory";
import type BaseWidget from "./BaseWidget";
export type pushAction = ( export type pushAction = (
propertyName: string | batchUpdateWidgetMetaPropertyType, propertyName: string | batchUpdateWidgetMetaPropertyType,
propertyValue?: unknown, propertyValue?: unknown,

View File

@ -10,13 +10,13 @@ import { scrollCSS } from "widgets/WidgetUtils";
import type { WidgetProps } from "widgets/BaseWidget"; import type { WidgetProps } from "widgets/BaseWidget";
import type { RenderMode } from "constants/WidgetConstants"; import type { RenderMode } from "constants/WidgetConstants";
import { WIDGET_PADDING } from "constants/WidgetConstants"; import { WIDGET_PADDING } from "constants/WidgetConstants";
import WidgetFactory from "WidgetProvider/factory";
import { useModalWidth } from "./useModalWidth"; import { useModalWidth } from "./useModalWidth";
import type { import type {
Alignment, Alignment,
Positioning, Positioning,
Spacing, Spacing,
} from "layoutSystems/common/utils/constants"; } from "layoutSystems/common/utils/constants";
import { renderAppsmithCanvas } from "layoutSystems/CanvasFactory";
const Content = styled.div<{ $scroll: boolean }>` const Content = styled.div<{ $scroll: boolean }>`
overflow-x: hidden; overflow-x: hidden;
@ -113,7 +113,7 @@ export default function ModalComponent(props: ModalComponentProps) {
childData.positioning = props.positioning; childData.positioning = props.positioning;
childData.alignment = props.alignment; childData.alignment = props.alignment;
childData.spacing = props.spacing; childData.spacing = props.spacing;
return WidgetFactory.createWidget(childData, props.renderMode); return renderAppsmithCanvas(childData as WidgetProps);
}; };
const getChildren = (): ReactNode => { const getChildren = (): ReactNode => {
if ( if (

View File

@ -12,7 +12,6 @@ import React from "react";
import { LayoutSystemTypes } from "layoutSystems/types"; import { LayoutSystemTypes } from "layoutSystems/types";
import type { WidgetProperties } from "selectors/propertyPaneSelectors"; import type { WidgetProperties } from "selectors/propertyPaneSelectors";
import { AutocompleteDataType } from "utils/autocomplete/AutocompleteDataType"; import { AutocompleteDataType } from "utils/autocomplete/AutocompleteDataType";
import WidgetFactory from "WidgetProvider/factory";
import type { WidgetState } from "../../BaseWidget"; import type { WidgetState } from "../../BaseWidget";
import BaseWidget from "../../BaseWidget"; import BaseWidget from "../../BaseWidget";
import TabsComponent from "../component"; import TabsComponent from "../component";
@ -36,6 +35,7 @@ import {
import type { WidgetProps } from "widgets/BaseWidget"; import type { WidgetProps } from "widgets/BaseWidget";
import { BlueprintOperationTypes } from "WidgetProvider/constants"; import { BlueprintOperationTypes } from "WidgetProvider/constants";
import IconSVG from "../icon.svg"; import IconSVG from "../icon.svg";
import { renderAppsmithCanvas } from "layoutSystems/CanvasFactory";
export function selectedTabValidation( export function selectedTabValidation(
value: unknown, value: unknown,
@ -588,8 +588,7 @@ class TabsWidget extends BaseWidget<
: LayoutDirection.Horizontal; : LayoutDirection.Horizontal;
childWidgetData.alignment = selectedTabProps?.alignment; childWidgetData.alignment = selectedTabProps?.alignment;
childWidgetData.spacing = selectedTabProps?.spacing; childWidgetData.spacing = selectedTabProps?.spacing;
return renderAppsmithCanvas(childWidgetData as WidgetProps);
return WidgetFactory.createWidget(childWidgetData, this.props.renderMode);
}; };
private getSelectedTabWidgetId() { private getSelectedTabWidgetId() {