Initialise comments (#3328)
* Initial scaffolding for comments CRUD APIs
* add actions
* add assets
* state management for existing comments and creating new
* add ui components
* add overlay comments wrapper to baseWidget
* add toggle comment mode button at editor header
* trigger tests
* Disallow commenting as someone else
* Add applicationId for comments
* lint
* Add overlay blacklist to prevent component interaction while adding comments
* Comment thread style updates
* Placeholder comment context menu
* Controlled comment thread visibility for making new comments visible by default
* Update comment type description
* Reset input on save
* Resolve comment thread button ui
* fix close on esc key, dont create new comment on outside click
* Submit on enter
* add emoji picker
* Attempt at adding a websocket server in Java
* CRUD APIs for comment threads
* Add API for getting all threads in application
* Move types to a separate file
* Initial commit for real time server (RTS)
* Add script to start RTS
* Fix position property
* Use create comment thread API
* Use add comment to thread API
* Add custom cursor
* Dispatch logout init on 401 errors
* Allow CORS for real time connection
* Add more logs to RTS
* Fix construction of MongoClient
* WIP: Real time comments
* Enable comments
* Minor updates
* Read backend API base URL from environment
* Escape to reset comments mode
* Set popover position as auto and boundary as scroll parent
* Disable warning
* Added permissions for comment threads
* Add resolved API for comment threads
* Migration to set commenting permission on existing apps
* Fix updates bringing the RTS down
* Show view latest button, scroll to bottom on creating a new comment
* Cleanup comment reducer
* Move to typescript for RTS
* Add missing server.ts and tsconfig files
* Resolve / unresolve comment
* Scaffold app comments
* Minor fixes: comment on top of all widgets, add toggle button at viewer header
* Reconnect socket on creating a new app, set connected status in store
* Retry socket connection flow
* Integration tests for comments with api mocks using msw
* Fix circular depependency
* rm file
* Minor cleanup and comments
* Minor refactors: move isScrolledToBottom to common hooks, decouple prevent interactions overlay from comments wrapper
* Use policies when pushing updates in RTS
* ENV var to set if comments are enabled
* Fix: check if editor/viewer is initialised before waiting for init action
* Add tests for comments reducer
* Revert "ENV var to set if comments are enabled"
This reverts commit 988efeaa69d378d943a387e1e73510334958adc5.
* Enable comments for users with appsmith email
* lint
* fix
* Try running a socket.io server inside backend
* Update comment reducer tests
* Init mentions within comments
* Fix comment thread updates with email rooms
* Minor fixes
* Refactors / review suggestions
* lint
* increase cache limit for builds
* Comment out tests for feature that's under development
* Add Dockerfile for RTS
* Fix policies missing for first comment in threads
* Use draftJS for comments input with mentions support
* fix fixtures
* Use thread's policies when querying for threads
* Update socket.io to v4
* Add support for richer body with mentions
* Update comment body type to RawDraftContentState
* fix stale method
* Fix mentions search
* Minor cleanups
* Comment context menu and thread UI updates
* revert: Scaffold app comments
* Yarn dependencies
* Delete comment using id api added
* Init app comments
* Add test for creating thread
* Api for delete comment with id
* Test comment creation response and policies
* Copy comment links
* Fix reset editor state
* Delete valid comment testcase added
* Delete comment TC : code refactor
* Don't allow creating comments with an empty body
* Pin comments WIP[]
* Ignore dependency-reduced-pom.xml files from VCS
* Cleanup of some dev-only files, for review
* Delete comment
* Update socket.io to v4 in RTS
* Pin and resolve comment thread object added in commentThread
* Pin and resolve comment thread object added in commentThread
* Update comment thread API
* Added creationTime and updationTime in comment thread response
* Added creationTime and updationTime in comment thread response
* Added human readable id to comment threads, fallback to username for null name in user document
* Refactor
* lint
* fix test, rm duplicate selector
* comment out saga used for dev
* CommentThread viewed status, username fallback for getName=null, username field added in pin & resolve status
* lint
* trigger tests
Co-authored-by: Shrikant Sharat Kandula <shrikant@appsmith.com>
Co-authored-by: Abhijeet <abhi.nagarnaik@gmail.com>
2021-04-29 10:33:51 +00:00
|
|
|
import { CommentThread } from "entities/Comments/CommentsInterfaces";
|
2021-06-17 07:37:27 +00:00
|
|
|
import {
|
|
|
|
|
BUILDER_PAGE_URL,
|
|
|
|
|
getApplicationViewerPageURL,
|
2021-11-18 06:48:52 +00:00
|
|
|
GIT_BRANCH_QUERY_KEY,
|
2021-06-17 07:37:27 +00:00
|
|
|
} from "constants/routes";
|
2021-08-06 09:17:56 +00:00
|
|
|
import { APP_MODE } from "entities/App";
|
2021-09-09 15:10:22 +00:00
|
|
|
import { MAIN_CONTAINER_WIDGET_ID } from "constants/WidgetConstants";
|
|
|
|
|
import WidgetFactory from "utils/WidgetFactory";
|
|
|
|
|
const WidgetTypes = WidgetFactory.widgetTypes;
|
Initialise comments (#3328)
* Initial scaffolding for comments CRUD APIs
* add actions
* add assets
* state management for existing comments and creating new
* add ui components
* add overlay comments wrapper to baseWidget
* add toggle comment mode button at editor header
* trigger tests
* Disallow commenting as someone else
* Add applicationId for comments
* lint
* Add overlay blacklist to prevent component interaction while adding comments
* Comment thread style updates
* Placeholder comment context menu
* Controlled comment thread visibility for making new comments visible by default
* Update comment type description
* Reset input on save
* Resolve comment thread button ui
* fix close on esc key, dont create new comment on outside click
* Submit on enter
* add emoji picker
* Attempt at adding a websocket server in Java
* CRUD APIs for comment threads
* Add API for getting all threads in application
* Move types to a separate file
* Initial commit for real time server (RTS)
* Add script to start RTS
* Fix position property
* Use create comment thread API
* Use add comment to thread API
* Add custom cursor
* Dispatch logout init on 401 errors
* Allow CORS for real time connection
* Add more logs to RTS
* Fix construction of MongoClient
* WIP: Real time comments
* Enable comments
* Minor updates
* Read backend API base URL from environment
* Escape to reset comments mode
* Set popover position as auto and boundary as scroll parent
* Disable warning
* Added permissions for comment threads
* Add resolved API for comment threads
* Migration to set commenting permission on existing apps
* Fix updates bringing the RTS down
* Show view latest button, scroll to bottom on creating a new comment
* Cleanup comment reducer
* Move to typescript for RTS
* Add missing server.ts and tsconfig files
* Resolve / unresolve comment
* Scaffold app comments
* Minor fixes: comment on top of all widgets, add toggle button at viewer header
* Reconnect socket on creating a new app, set connected status in store
* Retry socket connection flow
* Integration tests for comments with api mocks using msw
* Fix circular depependency
* rm file
* Minor cleanup and comments
* Minor refactors: move isScrolledToBottom to common hooks, decouple prevent interactions overlay from comments wrapper
* Use policies when pushing updates in RTS
* ENV var to set if comments are enabled
* Fix: check if editor/viewer is initialised before waiting for init action
* Add tests for comments reducer
* Revert "ENV var to set if comments are enabled"
This reverts commit 988efeaa69d378d943a387e1e73510334958adc5.
* Enable comments for users with appsmith email
* lint
* fix
* Try running a socket.io server inside backend
* Update comment reducer tests
* Init mentions within comments
* Fix comment thread updates with email rooms
* Minor fixes
* Refactors / review suggestions
* lint
* increase cache limit for builds
* Comment out tests for feature that's under development
* Add Dockerfile for RTS
* Fix policies missing for first comment in threads
* Use draftJS for comments input with mentions support
* fix fixtures
* Use thread's policies when querying for threads
* Update socket.io to v4
* Add support for richer body with mentions
* Update comment body type to RawDraftContentState
* fix stale method
* Fix mentions search
* Minor cleanups
* Comment context menu and thread UI updates
* revert: Scaffold app comments
* Yarn dependencies
* Delete comment using id api added
* Init app comments
* Add test for creating thread
* Api for delete comment with id
* Test comment creation response and policies
* Copy comment links
* Fix reset editor state
* Delete valid comment testcase added
* Delete comment TC : code refactor
* Don't allow creating comments with an empty body
* Pin comments WIP[]
* Ignore dependency-reduced-pom.xml files from VCS
* Cleanup of some dev-only files, for review
* Delete comment
* Update socket.io to v4 in RTS
* Pin and resolve comment thread object added in commentThread
* Pin and resolve comment thread object added in commentThread
* Update comment thread API
* Added creationTime and updationTime in comment thread response
* Added creationTime and updationTime in comment thread response
* Added human readable id to comment threads, fallback to username for null name in user document
* Refactor
* lint
* fix test, rm duplicate selector
* comment out saga used for dev
* CommentThread viewed status, username fallback for getName=null, username field added in pin & resolve status
* lint
* trigger tests
Co-authored-by: Shrikant Sharat Kandula <shrikant@appsmith.com>
Co-authored-by: Abhijeet <abhi.nagarnaik@gmail.com>
2021-04-29 10:33:51 +00:00
|
|
|
|
|
|
|
|
// 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 }],
|
|
|
|
|
};
|
|
|
|
|
};
|
2021-05-20 12:03:08 +00:00
|
|
|
|
2021-08-27 08:57:18 +00:00
|
|
|
const getRelativePos = (
|
|
|
|
|
absPosition: { x: number; y: number },
|
|
|
|
|
boundingRectSizePosition: {
|
|
|
|
|
top: number;
|
|
|
|
|
left: number;
|
|
|
|
|
width: number;
|
|
|
|
|
height: number;
|
|
|
|
|
},
|
2021-05-20 12:03:08 +00:00
|
|
|
) => {
|
|
|
|
|
const containerPosition = {
|
2021-08-27 08:57:18 +00:00
|
|
|
left: boundingRectSizePosition.left,
|
|
|
|
|
top: boundingRectSizePosition.top,
|
2021-05-20 12:03:08 +00:00
|
|
|
};
|
2021-08-27 08:57:18 +00:00
|
|
|
const offsetLeft = absPosition.x - containerPosition.left;
|
|
|
|
|
const offsetTop = absPosition.y - containerPosition.top;
|
2021-05-20 12:03:08 +00:00
|
|
|
|
|
|
|
|
const offsetLeftPercent = parseFloat(
|
2021-08-27 08:57:18 +00:00
|
|
|
`${(offsetLeft / boundingRectSizePosition.width) * 100}`,
|
2021-05-20 12:03:08 +00:00
|
|
|
);
|
|
|
|
|
const offsetTopPercent = parseFloat(
|
2021-08-27 08:57:18 +00:00
|
|
|
`${(offsetTop / boundingRectSizePosition.height) * 100}`,
|
2021-05-20 12:03:08 +00:00
|
|
|
);
|
|
|
|
|
|
|
|
|
|
return {
|
2021-07-19 15:28:41 +00:00
|
|
|
leftPercent: offsetLeftPercent,
|
|
|
|
|
topPercent: offsetTopPercent,
|
|
|
|
|
left: offsetLeft,
|
|
|
|
|
top: offsetTop,
|
2021-05-20 12:03:08 +00:00
|
|
|
};
|
|
|
|
|
};
|
2021-06-09 14:32:17 +00:00
|
|
|
|
2021-08-27 08:57:18 +00:00
|
|
|
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);
|
|
|
|
|
};
|
|
|
|
|
|
2021-06-09 14:32:17 +00:00
|
|
|
export const getCommentThreadURL = ({
|
|
|
|
|
applicationId,
|
2021-11-18 06:48:52 +00:00
|
|
|
branch,
|
2021-06-09 14:32:17 +00:00
|
|
|
commentThreadId,
|
|
|
|
|
isResolved,
|
|
|
|
|
pageId,
|
2021-06-17 07:37:27 +00:00
|
|
|
mode = APP_MODE.PUBLISHED,
|
2021-06-09 14:32:17 +00:00
|
|
|
}: {
|
2021-10-18 14:03:44 +00:00
|
|
|
applicationId: string;
|
2021-11-18 06:48:52 +00:00
|
|
|
branch?: string;
|
2021-06-09 14:32:17 +00:00
|
|
|
commentThreadId: string;
|
|
|
|
|
isResolved?: boolean;
|
2021-10-18 14:03:44 +00:00
|
|
|
pageId: string;
|
2021-06-17 07:37:27 +00:00
|
|
|
mode?: APP_MODE;
|
2021-06-09 14:32:17 +00:00
|
|
|
}) => {
|
|
|
|
|
const queryParams: Record<string, any> = {
|
|
|
|
|
commentThreadId,
|
|
|
|
|
isCommentMode: true,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
if (isResolved) {
|
|
|
|
|
queryParams.isResolved = true;
|
|
|
|
|
}
|
|
|
|
|
|
2021-11-18 06:48:52 +00:00
|
|
|
if (branch) {
|
|
|
|
|
queryParams[GIT_BRANCH_QUERY_KEY] = branch;
|
|
|
|
|
}
|
|
|
|
|
|
2021-06-17 07:37:27 +00:00
|
|
|
const urlBuilder =
|
|
|
|
|
mode === APP_MODE.PUBLISHED
|
|
|
|
|
? getApplicationViewerPageURL
|
|
|
|
|
: BUILDER_PAGE_URL;
|
|
|
|
|
|
2021-06-09 14:32:17 +00:00
|
|
|
const url = new URL(
|
2021-10-18 14:03:44 +00:00
|
|
|
`${window.location.origin}${urlBuilder({
|
|
|
|
|
applicationId: applicationId,
|
2021-06-09 14:32:17 +00:00
|
|
|
pageId,
|
2021-10-18 14:03:44 +00:00
|
|
|
params: queryParams,
|
|
|
|
|
})}`,
|
2021-06-09 14:32:17 +00:00
|
|
|
);
|
|
|
|
|
|
|
|
|
|
return url;
|
|
|
|
|
};
|
2021-07-19 15:28:41 +00:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Absolutely position the pins within the
|
|
|
|
|
* main container canvas since the height
|
|
|
|
|
* can change dynamically
|
|
|
|
|
*/
|
|
|
|
|
export const getPosition = (props: {
|
2021-11-02 07:33:12 +00:00
|
|
|
top?: number;
|
|
|
|
|
left?: number;
|
2021-07-19 15:28:41 +00:00
|
|
|
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;
|
2021-11-02 07:33:12 +00:00
|
|
|
const top = props.top || 0;
|
|
|
|
|
const left = props.left || 0;
|
2021-07-19 15:28:41 +00:00
|
|
|
if (props.positionAbsolutely) {
|
|
|
|
|
return `
|
2021-11-02 07:33:12 +00:00
|
|
|
top: ${top - 29}px;
|
|
|
|
|
left: ${left - 29}px;
|
2021-07-19 15:28:41 +00:00
|
|
|
`;
|
|
|
|
|
} 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
|
|
|
|
|
);
|
|
|
|
|
};
|