* add tailwindcss * docked property pane * uncomment a line * make entity explorer as drawer on unpin * remove unused imports * add pin state in reducer * add menu icon in header * fix widget sidebar * fix widgets sidebar * style property pane * update property pane css * update icons in property pane * update property pane header styles * update spacing * fix few ui issues * wip: preview mode * wip:preview mode * remove unused import * comments sidebar in app and edit mode * fix order of import * use selected state for property pane * update scrollbar style * add classes to sidebar and property pane * make widgets editor fluid * make widgets editor fluid and refactor logic * resize the widgets editor if explorer is pinned * add shortcut for preview mode * fix link for tabs in edit mode * zoom in/zoom out for 0.75 * fix chart widget + table widget crashing * allow zooming of canvas * fix weird canvas draw issue + update container for handling zoom * add actions for is panning * allow panning with grab cursor * reset panning + zooming when entering preview mode * add grabbing cursor when grabbing * only prevent default when space key is pressed * dont allow zoom in preview mode * remove unused imports * fix dont allow zoom in preview mode * fix ux of panning on space hit * make fluid as the default app layout * chart spec * fix dropdown_on change spec * fix add widget table and bind spec * remove draggable property pane spec * fix container spec * fix form widget spec * fix jest test * fix the function typo * remove clicking of close button for property pane in cypress tests * remove property pane actions test * fix drag and drop test failing * add cypress selector id to back button in property pane * fix toggle js spec * fix merge conflicts from new design system * editor header * fix product updates styles + widget card * remove all unused imports * fix dynamic layout spec * fix entity explorer tab rename test failing * fix table spec * fix bind tabletextpagination spec * fix js object spec * fix entity explorer rename issue * fix cypress test * fix cypress command wrong commit * fix tab spec * fix property pane copy tests * add zoom header * zoom levels * make property pane sidebar resizable * add multi select property pane * fix widget search bug * update property pane width in state on drag end * fix viewer header * fix editor header * update editor header + remove zooming * update small style * dont allow closing of explorer when resizing * fix jest test * fix dropdown widget jest test * preview test case wip * add entity explorer pinning tests + preview mode tests * add tooltip in layout control + add padding bottom in property pane view * incorporate aakash feedbacks * fix preview mode margin issue * remove panning code * fix cypress failing test * uncomment jest test * remove redundant code * fix maincontainer test * incorporate review feedbacks * incorporate aakash feedbacks * review feedbacks * incorporate review feedbacks * incorporate qa feedbacks * fix dynamic layout spec * updated test based on latest change * dsl updated * Updated dsl * Updated dsl * resize deselects widget issue. * fix canvas height issue * fix typo * incorporate qa feedbacks * incorporate qa feedbacks * incorporate qa feedbacks * update color for setting control for widget name * fix onboarding styles conflicts * Updated tests * fix application overflow issue * updated test method Co-authored-by: root <root@DESKTOP-9GENCK0.localdomain> Co-authored-by: Pawan Kumar <pawankumar@Pawans-MacBook-Pro.local> Co-authored-by: Ashok Kumar M <35134347+marks0351@users.noreply.github.com> Co-authored-by: Apple <nandan@thinkify.io>
291 lines
7.0 KiB
TypeScript
291 lines
7.0 KiB
TypeScript
import { FetchPageResponse } from "api/PageApi";
|
|
import { XYCord } from "utils/hooks/useCanvasDragging";
|
|
import { WidgetConfigProps } from "reducers/entityReducers/widgetConfigReducer";
|
|
import {
|
|
WidgetOperation,
|
|
WidgetOperations,
|
|
WidgetProps,
|
|
} from "widgets/BaseWidget";
|
|
import { GridDefaults, RenderMode } from "constants/WidgetConstants";
|
|
import { snapToGrid } from "./helpers";
|
|
import { OccupiedSpace } from "constants/CanvasEditorConstants";
|
|
import defaultTemplate from "templates/default";
|
|
import { FlattenedWidgetProps } from "reducers/entityReducers/canvasWidgetsReducer";
|
|
import { transformDSL } from "./DSLMigrations";
|
|
import { WidgetType } from "./WidgetFactory";
|
|
import { DSLWidget } from "widgets/constants";
|
|
|
|
export type WidgetOperationParams = {
|
|
operation: WidgetOperation;
|
|
widgetId: string;
|
|
payload: any;
|
|
};
|
|
|
|
type Rect = {
|
|
top: number;
|
|
left: number;
|
|
right: number;
|
|
bottom: number;
|
|
};
|
|
|
|
const defaultDSL = defaultTemplate;
|
|
|
|
export const extractCurrentDSL = (
|
|
fetchPageResponse?: FetchPageResponse,
|
|
): DSLWidget => {
|
|
const newPage = !fetchPageResponse;
|
|
const currentDSL = fetchPageResponse?.data.layouts[0].dsl || {
|
|
...defaultDSL,
|
|
};
|
|
return transformDSL(currentDSL, newPage);
|
|
};
|
|
|
|
export const getDropZoneOffsets = (
|
|
colWidth: number,
|
|
rowHeight: number,
|
|
dragOffset: XYCord,
|
|
parentOffset: XYCord,
|
|
) => {
|
|
// Calculate actual drop position by snapping based on x, y and grid cell size
|
|
return snapToGrid(
|
|
colWidth,
|
|
rowHeight,
|
|
dragOffset.x - parentOffset.x,
|
|
dragOffset.y - parentOffset.y,
|
|
);
|
|
};
|
|
|
|
export const areIntersecting = (r1: Rect, r2: Rect) => {
|
|
return !(
|
|
r2.left >= r1.right ||
|
|
r2.right <= r1.left ||
|
|
r2.top >= r1.bottom ||
|
|
r2.bottom <= r1.top
|
|
);
|
|
};
|
|
|
|
export const isDropZoneOccupied = (
|
|
offset: Rect,
|
|
widgetId: string,
|
|
occupied?: OccupiedSpace[],
|
|
) => {
|
|
if (occupied) {
|
|
occupied = occupied.filter((widgetDetails) => {
|
|
return (
|
|
widgetDetails.id !== widgetId && widgetDetails.parentId !== widgetId
|
|
);
|
|
});
|
|
for (let i = 0; i < occupied.length; i++) {
|
|
if (areIntersecting(occupied[i], offset)) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
return false;
|
|
};
|
|
|
|
export const isWidgetOverflowingParentBounds = (
|
|
parentRowCols: { rows?: number; cols?: number },
|
|
offset: Rect,
|
|
): boolean => {
|
|
return (
|
|
offset.right < 0 ||
|
|
offset.top < 0 ||
|
|
(parentRowCols.cols || GridDefaults.DEFAULT_GRID_COLUMNS) < offset.right ||
|
|
(parentRowCols.rows || 0) < offset.bottom
|
|
);
|
|
};
|
|
|
|
export const noCollision = (
|
|
clientOffset: XYCord,
|
|
colWidth: number,
|
|
rowHeight: number,
|
|
dropTargetOffset: XYCord,
|
|
widgetWidth: number,
|
|
widgetHeight: number,
|
|
widgetId: string,
|
|
occupiedSpaces?: OccupiedSpace[],
|
|
rows?: number,
|
|
cols?: number,
|
|
detachFromLayout = false,
|
|
): boolean => {
|
|
if (detachFromLayout) {
|
|
return true;
|
|
}
|
|
if (clientOffset && dropTargetOffset) {
|
|
const [left, top] = getDropZoneOffsets(
|
|
colWidth,
|
|
rowHeight,
|
|
clientOffset as XYCord,
|
|
dropTargetOffset,
|
|
);
|
|
if (left < 0 || top < 0) {
|
|
return false;
|
|
}
|
|
const currentOffset = {
|
|
left,
|
|
right: left + widgetWidth,
|
|
top,
|
|
bottom: top + widgetHeight,
|
|
};
|
|
return (
|
|
!isDropZoneOccupied(currentOffset, widgetId, occupiedSpaces) &&
|
|
!isWidgetOverflowingParentBounds({ rows, cols }, currentOffset)
|
|
);
|
|
}
|
|
return false;
|
|
};
|
|
|
|
export const currentDropRow = (
|
|
dropTargetRowSpace: number,
|
|
dropTargetVerticalOffset: number,
|
|
draggableItemVerticalOffset: number,
|
|
widget: WidgetProps & Partial<WidgetConfigProps>,
|
|
) => {
|
|
const widgetHeight = widget.rows
|
|
? widget.rows
|
|
: widget.bottomRow - widget.topRow;
|
|
const top = Math.round(
|
|
(draggableItemVerticalOffset - dropTargetVerticalOffset) /
|
|
dropTargetRowSpace,
|
|
);
|
|
const currentBottomOffset = top + widgetHeight;
|
|
return currentBottomOffset;
|
|
};
|
|
|
|
export const widgetOperationParams = (
|
|
widget: WidgetProps & Partial<WidgetConfigProps>,
|
|
widgetOffset: XYCord,
|
|
parentOffset: XYCord,
|
|
parentColumnSpace: number,
|
|
parentRowSpace: number,
|
|
parentWidgetId: string, // parentWidget
|
|
): WidgetOperationParams => {
|
|
const [leftColumn, topRow] = getDropZoneOffsets(
|
|
parentColumnSpace,
|
|
parentRowSpace,
|
|
widgetOffset,
|
|
parentOffset,
|
|
);
|
|
// If this is an existing widget, we'll have the widgetId
|
|
// Therefore, this is a move operation on drop of the widget
|
|
if (widget.widgetName) {
|
|
return {
|
|
operation: WidgetOperations.MOVE,
|
|
widgetId: widget.widgetId,
|
|
payload: {
|
|
leftColumn,
|
|
topRow,
|
|
parentId: widget.parentId,
|
|
newParentId: parentWidgetId,
|
|
},
|
|
};
|
|
// If this is not an existing widget, we'll not have the widgetId
|
|
// Therefore, this is an operation to add child to this container
|
|
}
|
|
const widgetDimensions = {
|
|
columns: widget.columns,
|
|
rows: widget.rows,
|
|
};
|
|
|
|
return {
|
|
operation: WidgetOperations.ADD_CHILD,
|
|
widgetId: parentWidgetId,
|
|
payload: {
|
|
type: widget.type,
|
|
leftColumn,
|
|
topRow,
|
|
...widgetDimensions,
|
|
parentRowSpace,
|
|
parentColumnSpace,
|
|
newWidgetId: widget.widgetId,
|
|
},
|
|
};
|
|
};
|
|
|
|
export const updateWidgetPosition = (
|
|
widget: WidgetProps,
|
|
leftColumn: number,
|
|
topRow: number,
|
|
) => {
|
|
const newPositions = {
|
|
leftColumn,
|
|
topRow,
|
|
rightColumn: leftColumn + (widget.rightColumn - widget.leftColumn),
|
|
bottomRow: topRow + (widget.bottomRow - widget.topRow),
|
|
};
|
|
|
|
return {
|
|
...newPositions,
|
|
};
|
|
};
|
|
|
|
export const getCanvasSnapRows = (
|
|
bottomRow: number,
|
|
canExtend: boolean,
|
|
): number => {
|
|
const totalRows = Math.floor(
|
|
bottomRow / GridDefaults.DEFAULT_GRID_ROW_HEIGHT,
|
|
);
|
|
|
|
// Canvas Widgets do not need to accommodate for widget and container padding.
|
|
// Only when they're extensible
|
|
if (canExtend) {
|
|
return totalRows;
|
|
}
|
|
// When Canvas widgets are not extensible
|
|
return totalRows - 1;
|
|
};
|
|
|
|
export const getSnapColumns = (): number => {
|
|
return GridDefaults.DEFAULT_GRID_COLUMNS;
|
|
};
|
|
|
|
export const generateWidgetProps = (
|
|
parent: FlattenedWidgetProps,
|
|
type: WidgetType,
|
|
leftColumn: number,
|
|
topRow: number,
|
|
parentRowSpace: number,
|
|
parentColumnSpace: number,
|
|
widgetName: string,
|
|
widgetConfig: {
|
|
widgetId: string;
|
|
renderMode: RenderMode;
|
|
} & Partial<WidgetProps>,
|
|
version: number,
|
|
): DSLWidget => {
|
|
if (parent) {
|
|
const sizes = {
|
|
leftColumn,
|
|
rightColumn: leftColumn + widgetConfig.columns,
|
|
topRow,
|
|
bottomRow: topRow + widgetConfig.rows,
|
|
};
|
|
|
|
const others = {};
|
|
const props: DSLWidget = {
|
|
// Todo(abhinav): abstraction leak
|
|
isVisible: "MODAL_WIDGET" === type ? undefined : true,
|
|
...widgetConfig,
|
|
type,
|
|
widgetName,
|
|
isLoading: false,
|
|
parentColumnSpace,
|
|
parentRowSpace,
|
|
...sizes,
|
|
...others,
|
|
parentId: parent.widgetId,
|
|
version,
|
|
};
|
|
delete props.rows;
|
|
delete props.columns;
|
|
return props;
|
|
} else {
|
|
if (parent) {
|
|
throw Error("Failed to create widget: Parent's size cannot be calculate");
|
|
} else throw Error("Failed to create widget: Parent was not provided ");
|
|
}
|
|
};
|