* made inline comment pins draggable and added wrapper around overlay comments wrapper * moved drag hook to pin * can drag on canvas * Properly updating the thread to be able to properly move the pin * always passing the ref to container * updating BE to save the new pins position * minor fix * changed a file name * minor improvement to fix unit test * fix, updated dragging reducer function to not expect appId * removing unrelated change * added drag and drop for comment pins without react dnd * updated unit tests * minor fix * added a grab pointer and minor offset when user moves the pin * removed unnecessary store states * moved drop from onDragEnd to onDrop to reset everything. * using state selector and dispatch hook * removed use of anchor widget * removed pointer change from comments wrapper * verifying if current pin is being dragged * updated action creator name * moved dragging in comments reducer. * using dragging thread id from store itself * using relative positioning of pointer to predict the location of pin * unit test cases fixed * minor fix * removed the dependency of off set from callback
196 lines
4.5 KiB
TypeScript
196 lines
4.5 KiB
TypeScript
import { CommentThread } from "entities/Comments/CommentsInterfaces";
|
|
import {
|
|
BUILDER_PAGE_URL,
|
|
getApplicationViewerPageURL,
|
|
} from "constants/routes";
|
|
import { APP_MODE } from "entities/App";
|
|
import {
|
|
MAIN_CONTAINER_WIDGET_ID,
|
|
WidgetTypes,
|
|
} from "constants/WidgetConstants";
|
|
|
|
// used for dev
|
|
export const reduceCommentsByRef = (comments: any[]) => {
|
|
return comments.reduce((res, curr) => {
|
|
return {
|
|
commentThreadsMap: {
|
|
...res.commentThreadsMap,
|
|
[curr.id]: curr,
|
|
},
|
|
refCommentThreads: {
|
|
...(res.refCommentThreads ? res.refCommentThreads : {}),
|
|
[curr.refId]: [
|
|
...(res.refCommentThreads && res.refCommentThreads[curr.refId]
|
|
? res.refCommentThreads[curr.refId]
|
|
: []),
|
|
curr.id,
|
|
],
|
|
},
|
|
};
|
|
}, {});
|
|
};
|
|
|
|
export const transformPublishedCommentActionPayload = (
|
|
payload: any,
|
|
): Record<string, CommentThread> => {
|
|
return {
|
|
[payload.refId]: {
|
|
...payload,
|
|
position: payload.position,
|
|
id: "UNPUBLISHED",
|
|
},
|
|
};
|
|
};
|
|
|
|
export const transformUnpublishCommentThreadToCreateNew = (payload: any) => {
|
|
const { commentBody, commentThread } = payload;
|
|
// eslint-disable-next-line
|
|
const { id, ...rest } = commentThread;
|
|
return {
|
|
...rest,
|
|
comments: [{ body: commentBody }],
|
|
};
|
|
};
|
|
|
|
const getRelativePos = (
|
|
absPosition: { x: number; y: number },
|
|
boundingRectSizePosition: {
|
|
top: number;
|
|
left: number;
|
|
width: number;
|
|
height: number;
|
|
},
|
|
) => {
|
|
const containerPosition = {
|
|
left: boundingRectSizePosition.left,
|
|
top: boundingRectSizePosition.top,
|
|
};
|
|
const offsetLeft = absPosition.x - containerPosition.left;
|
|
const offsetTop = absPosition.y - containerPosition.top;
|
|
|
|
const offsetLeftPercent = parseFloat(
|
|
`${(offsetLeft / boundingRectSizePosition.width) * 100}`,
|
|
);
|
|
const offsetTopPercent = parseFloat(
|
|
`${(offsetTop / boundingRectSizePosition.height) * 100}`,
|
|
);
|
|
|
|
return {
|
|
leftPercent: offsetLeftPercent,
|
|
topPercent: offsetTopPercent,
|
|
left: offsetLeft,
|
|
top: offsetTop,
|
|
};
|
|
};
|
|
|
|
export const getNewDragPos = (
|
|
absolutePos: {
|
|
x: number;
|
|
y: number;
|
|
},
|
|
boundingRectSizePosition: {
|
|
top: number;
|
|
left: number;
|
|
width: number;
|
|
height: number;
|
|
},
|
|
) => {
|
|
return getRelativePos(absolutePos, boundingRectSizePosition);
|
|
};
|
|
|
|
/**
|
|
* Returns the offset position relative to the container
|
|
* using the coordinates from the click event
|
|
* @param clickEvent
|
|
* @param containerRef
|
|
*/
|
|
export const getOffsetPos = (
|
|
clickEvent: React.MouseEvent,
|
|
containerRef: HTMLDivElement,
|
|
) => {
|
|
const clickPosition = {
|
|
x: clickEvent.clientX,
|
|
y: clickEvent.clientY,
|
|
};
|
|
const boundingClientRect = containerRef.getBoundingClientRect();
|
|
return getRelativePos(clickPosition, boundingClientRect);
|
|
};
|
|
|
|
export const getCommentThreadURL = ({
|
|
applicationId,
|
|
commentThreadId,
|
|
isResolved,
|
|
pageId,
|
|
mode = APP_MODE.PUBLISHED,
|
|
}: {
|
|
applicationId?: string;
|
|
commentThreadId: string;
|
|
isResolved?: boolean;
|
|
pageId?: string;
|
|
mode?: APP_MODE;
|
|
}) => {
|
|
const queryParams: Record<string, any> = {
|
|
commentThreadId,
|
|
isCommentMode: true,
|
|
};
|
|
|
|
if (isResolved) {
|
|
queryParams.isResolved = true;
|
|
}
|
|
|
|
const urlBuilder =
|
|
mode === APP_MODE.PUBLISHED
|
|
? getApplicationViewerPageURL
|
|
: BUILDER_PAGE_URL;
|
|
|
|
const url = new URL(
|
|
`${window.location.origin}${urlBuilder(
|
|
applicationId,
|
|
pageId,
|
|
queryParams,
|
|
)}`,
|
|
);
|
|
|
|
return url;
|
|
};
|
|
|
|
/**
|
|
* Absolutely position the pins within the
|
|
* main container canvas since the height
|
|
* can change dynamically
|
|
*/
|
|
export const getPosition = (props: {
|
|
top: number;
|
|
left: number;
|
|
leftPercent: number;
|
|
topPercent: number;
|
|
positionAbsolutely: boolean;
|
|
xOffset?: number;
|
|
yOffset?: number;
|
|
offset?: number;
|
|
}) => {
|
|
const xOffset = props.xOffset || props.offset || 0;
|
|
const yOffset = props.yOffset || props.offset || 0;
|
|
if (props.positionAbsolutely) {
|
|
return `
|
|
top: ${props.top - 29}px;
|
|
left: ${props.left - 29}px;
|
|
`;
|
|
} else {
|
|
// The folling syntax is supported: bottom: calc(50% + -6px);
|
|
// so we can work with both +ve and -ve offset values as
|
|
// `calc(${100 - props.topPercent}% + ${yOffset}px);`
|
|
return `
|
|
bottom: calc(${100 - props.topPercent}% + ${yOffset}px);
|
|
right: calc(${100 - props.leftPercent}% + ${xOffset}px);
|
|
`;
|
|
}
|
|
};
|
|
|
|
export const getShouldPositionAbsolutely = (commentThread: CommentThread) => {
|
|
return (
|
|
commentThread?.refId === MAIN_CONTAINER_WIDGET_ID &&
|
|
commentThread?.widgetType === WidgetTypes.CANVAS_WIDGET
|
|
);
|
|
};
|