[](https://workerb.linearb.io/v2/badge/collaboration-page?magicLinkId=MdeCkAG) ## Description In this PR, - we are refactoring Anvil DnD to use dom elements to render highlights instead of canvas. Why? - Doesn't have the ability to overflow a widget and still allow dnd events(section widget use case) - limitations with respect to being testable - we are adding compensators to dnd layers, so that DnD is not just for layout but for the entire widget. Widget is the appsmith entity. layout is something present in container like widgets like Section and Zone which allow you to contain children widgets based on a the layout structure. What are compensators? - additional padding for DnD layers in a widget - additional position offsets for highlights in a widget so that they don't stick to the layout. Why compensators? - Section widget can be activated to show highlights in areas overlapping with main canvas - DnD should be possible even at spacings created by parent widget like in Zone widget - we are also removing canvas activation logic and moving to using mouse move event to activate a canvas for DnD. Fixes #32016 _or_ Fixes `Issue URL` > [!WARNING] > _If no issue exists, please create an issue first, and check with the maintainers if the issue is valid._ ## Automation /ok-to-test tags="@tag.Anvil" ### 🔍 Cypress test results <!-- This is an auto-generated comment: Cypress test results --> > [!TIP] > 🟢 🟢 🟢 All cypress tests have passed! 🎉 🎉 🎉 > Workflow run: <https://github.com/appsmithorg/appsmith/actions/runs/8872919856> > Commit: 3f6603bf8480a99437552ac73764c9de1d6f7f95 > Cypress dashboard url: <a href="https://internal.appsmith.com/app/cypress-dashboard/rundetails-65890b3c81d7400d08fa9ee5?branch=master&workflowId=8872919856&attempt=1" target="_blank">Click here!</a> <!-- end of auto-generated comment: Cypress test results --> ## Communication Should the DevRel and Marketing teams inform users about this change? - [ ] Yes - [x] No <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit ## Summary by CodeRabbit - **New Features** - Introduced a new layout property for widgets, enhancing customization options. - Added a custom error boundary component to handle and display errors elegantly. - New drag-and-drop components and utilities to improve interaction within the editor canvas. - Adjusted component hierarchies in Anvil editor and viewer for better performance and structure. - **Refactor** - Simplified rendering logic in `AnvilWidgetComponent` by removing conditional boundaries. - Updated the hierarchy within the Anvil editor, enhancing component nesting and interaction. - **Bug Fixes** - Adjusted padding values and added new constants for better UI alignment and interaction feedback. - **Chores** - Renamed and reorganized Cypress locators and methods for clearer and more efficient testing automation. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
118 lines
3.3 KiB
TypeScript
118 lines
3.3 KiB
TypeScript
import { drop } from "lodash";
|
|
import { getWidgetSelector } from "../../locators/WidgetLocators";
|
|
import { ObjectsRegistry } from "../Objects/Registry";
|
|
import {
|
|
AppSidebar,
|
|
AppSidebarButton,
|
|
PageLeftPane,
|
|
PagePaneSegment,
|
|
} from "./EditorNavigation";
|
|
|
|
interface DropTargetDetails {
|
|
id?: string;
|
|
name?: string;
|
|
}
|
|
|
|
interface DragDropWidgetOptions {
|
|
skipWidgetSearch?: boolean;
|
|
dropTargetDetails?: DropTargetDetails;
|
|
}
|
|
|
|
export class AnvilLayout {
|
|
private entityExplorer = ObjectsRegistry.EntityExplorer;
|
|
private locator = ObjectsRegistry.CommonLocators;
|
|
private agHelper = ObjectsRegistry.AggregateHelper;
|
|
public mainCanvasSelector = "#anvil-canvas-0";
|
|
private getAnvilDropTargetSelectorFromOptions = (
|
|
dropTarget?: DropTargetDetails,
|
|
) => {
|
|
if (dropTarget) {
|
|
if (dropTarget.id) {
|
|
return `#${dropTarget.id}`;
|
|
}
|
|
if (dropTarget.name) {
|
|
return `${getWidgetSelector(dropTarget.name.toLowerCase() as any)} ${
|
|
this.locator._anvilDnDListener
|
|
}`;
|
|
}
|
|
}
|
|
return this.locator._anvilDnDListener;
|
|
};
|
|
|
|
private performDnDInAnvil(
|
|
xPos: number,
|
|
yPos: number,
|
|
options = {} as DragDropWidgetOptions,
|
|
) {
|
|
const dropAreaSelector = this.getAnvilDropTargetSelectorFromOptions(
|
|
options.dropTargetDetails,
|
|
);
|
|
cy.document()
|
|
// to activate ANVIL canvas
|
|
.trigger("mousemove", xPos, yPos, {
|
|
eventConstructor: "MouseEvent",
|
|
force: true,
|
|
});
|
|
this.agHelper.Sleep(200);
|
|
cy.get(dropAreaSelector).first().trigger("mouseover", xPos, yPos, {
|
|
eventConstructor: "MouseEvent",
|
|
force: true,
|
|
});
|
|
cy.get(dropAreaSelector).first().trigger("mousemove", xPos, yPos, {
|
|
eventConstructor: "MouseEvent",
|
|
force: true,
|
|
});
|
|
cy.get(dropAreaSelector).first().trigger("mousemove", xPos, yPos, {
|
|
eventConstructor: "MouseEvent",
|
|
force: true,
|
|
});
|
|
cy.get(this.locator._anvilDnDHighlight);
|
|
cy.get(dropAreaSelector).first().trigger("mouseup", xPos, yPos, {
|
|
eventConstructor: "MouseEvent",
|
|
force: true,
|
|
});
|
|
}
|
|
|
|
private startDraggingWidgetFromPane(widgetType: string) {
|
|
cy.get(this.locator._widgetPageIcon(widgetType))
|
|
.first()
|
|
.trigger("dragstart", { force: true });
|
|
}
|
|
|
|
private setupWidgetPane(skipWidgetSearch: boolean, widgetType: string) {
|
|
if (!skipWidgetSearch) {
|
|
this.entityExplorer.SearchWidgetPane(widgetType);
|
|
} else {
|
|
AppSidebar.navigate(AppSidebarButton.Editor);
|
|
PageLeftPane.switchSegment(PagePaneSegment.UI);
|
|
PageLeftPane.switchToAddNew();
|
|
}
|
|
}
|
|
|
|
private DragNDropAnvilWidget(
|
|
widgetType: string,
|
|
x = 300,
|
|
y = 100,
|
|
options = {} as DragDropWidgetOptions,
|
|
) {
|
|
const { skipWidgetSearch = false } = options;
|
|
this.setupWidgetPane(skipWidgetSearch, widgetType);
|
|
this.startDraggingWidgetFromPane(widgetType);
|
|
this.performDnDInAnvil(x, y, options);
|
|
}
|
|
|
|
public DragDropAnvilWidgetNVerify(
|
|
widgetType: string,
|
|
x = 300,
|
|
y = 100,
|
|
options = {} as DragDropWidgetOptions,
|
|
) {
|
|
this.DragNDropAnvilWidget(widgetType, x, y, options);
|
|
this.agHelper.AssertAutoSave(); //settling time for widget on canvas!
|
|
this.agHelper.AssertElementExist(
|
|
this.locator._anvilWidgetInCanvas(widgetType),
|
|
);
|
|
this.agHelper.Sleep(200); //waiting a bit for widget properties to open
|
|
}
|
|
}
|