PromucFlow_constructor/app/client/src/widgets/CanvasWidget.tsx
balajisoundar 2608e3dbd3
chore: Move the widget config to widget class (#26073)
## Description
- Remove the config objects from widget and config maps from the widget
factory.
- Introduce methods in widget development API to dynamically fetch this
items.
- freeze the widget configuration.

#### PR fixes following issue(s)
Fixes https://github.com/appsmithorg/appsmith/issues/26008
> if no issue exists, please create an issue and ask the maintainers
about this first
>
>
#### 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.
- Bug fix (non-breaking change which fixes an issue)
- New feature (non-breaking change which adds functionality)
- Breaking change (fix or feature that would cause existing
functionality to not work as expected)
- Chore (housekeeping or task changes that don't impact user perception)
- This change requires a documentation update
>
>
>
## 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
- [x] Manual
- [ ] 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
- [x] 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
- [x] 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
2023-09-06 17:45:04 +05:30

248 lines
7.7 KiB
TypeScript

import {
LayoutDirection,
Positioning,
ResponsiveBehavior,
} from "utils/autoLayout/constants";
import FlexBoxComponent from "components/designSystems/appsmith/autoLayout/FlexBoxComponent";
import DropTargetComponent from "components/editorComponents/DropTargetComponent";
import { CANVAS_DEFAULT_MIN_HEIGHT_PX } from "constants/AppConstants";
import { FILL_WIDGET_MIN_WIDTH } from "constants/minWidthConstants";
import { GridDefaults, RenderModes } from "constants/WidgetConstants";
import { CanvasDraggingArena } from "pages/common/CanvasArenas/CanvasDraggingArena";
import { CanvasSelectionArena } from "pages/common/CanvasArenas/CanvasSelectionArena";
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 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 type {
CanvasWidgetStructure,
DSLWidget,
WidgetDefaultProps,
} from "../WidgetProvider/constants";
import ContainerComponent from "./ContainerWidget/component";
import { AppPositioningTypes } from "reducers/entityReducers/pageListReducer";
import type { AutocompletionDefinitions } from "WidgetProvider/constants";
import type { SetterConfig } from "entities/AppTheming";
class CanvasWidget extends ContainerWidget {
static type = "CANVAS_WIDGET";
static getConfig() {
return {
name: "Canvas",
hideCard: true,
eagerRender: true,
};
}
static getDefaults(): WidgetDefaultProps {
return {
rows: 0,
columns: 0,
widgetName: "Canvas",
version: 1,
detachFromLayout: true,
flexLayers: [],
responsiveBehavior: ResponsiveBehavior.Fill,
minWidth: FILL_WIDGET_MIN_WIDTH,
};
}
static getPropertyPaneConfig() {
return [];
}
static getAutocompleteDefinitions(): AutocompletionDefinitions {
return {};
}
static getSetterConfig(): SetterConfig | 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.appPositioningType === AppPositioningTypes.AUTO,
);
return (
<ContainerComponent {...props}>
{props.renderMode === RenderModes.CANVAS && (
<>
<CanvasDraggingArena
{...this.getSnapSpaces()}
alignItems={props.alignItems}
canExtend={props.canExtend}
direction={direction}
dropDisabled={!!props.dropDisabled}
noPad={this.props.noPad}
parentId={props.parentId}
snapRows={snapRows}
useAutoLayout={this.props.useAutoLayout}
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.appPositioningType === AppPositioningTypes.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>
);
}
getCanvasView() {
if (!this.props.dropDisabled) {
return this.renderAsDropTarget();
}
return this.getPageView();
}
static getDerivedPropertiesMap(): DerivedPropertiesMap {
return {};
}
static getDefaultPropertiesMap(): Record<string, string> {
return {};
}
// TODO Find a way to enforce this, (dont let it be set)
static getMetaPropertiesMap(): Record<string, any> {
return {};
}
}
export default CanvasWidget;