PromucFlow_constructor/app/client/src/selectors/commentsSelectors.ts
2021-05-20 17:33:08 +05:30

150 lines
4.4 KiB
TypeScript

import { AppState } from "reducers";
import { get } from "lodash";
import { CommentThread, Comment } from "entities/Comments/CommentsInterfaces";
import { options as filterOptions } from "comments/AppComments/AppCommentsFilterPopover";
import moment from "moment";
export const refCommentThreadsSelector = (
refId: string,
applicationId?: string,
) => (state: AppState) =>
get(
state.ui.comments.applicationCommentThreadsByRef,
`${applicationId}.${refId}`,
[],
);
export const commentThreadsSelector = (commentThreadId: string) => (
state: AppState,
) => state.ui.comments.commentThreadsMap[commentThreadId];
export const unpublishedCommentThreadSelector = (refId: string) => (
state: AppState,
) => state.ui.comments.unpublishedCommentThreads[refId];
export const commentModeSelector = (state: AppState) =>
state.ui.comments?.isCommentMode;
export const applicationCommentsSelector = (applicationId: string) => (
state: AppState,
) => state.ui.comments.applicationCommentThreadsByRef[applicationId];
export const areCommentsEnabledForUserAndApp = (state: AppState) =>
state.ui.comments?.areCommentsEnabled;
/**
* Comments are stored as a map of refs (for example widgetIds)
* Flatten to fetch all application comment threads
*/
export const getAppCommentThreads = (
threadsByRefMap: Record<string, Array<string>>,
): Array<string> => {
if (!threadsByRefMap) return [];
return Object.entries(threadsByRefMap).reduce(
(res: Array<string>, [, threadIds]) => {
return [...res, ...threadIds];
},
[],
);
};
export const allCommentThreadsMap = (state: AppState) =>
state.ui.comments.commentThreadsMap;
const getSortIndexBool = (a: boolean, b: boolean) => {
if (a && b) return 0;
if (a) return -1;
if (b) return 1;
else return 0;
};
const getSortIndexTime = (
a: string | number = new Date().toISOString(),
b: string | number = new Date().toISOString(),
) => {
if (moment(a).isSame(moment(b))) return 0;
if (moment(a).isAfter(moment(b))) return -1;
else return 1;
};
const getContainsMyComment = (
thread: CommentThread,
currentUserUsername?: string,
) =>
thread.comments.some(
(comment: Comment) => comment.authorUsername === currentUserUsername,
);
export const getSortedAndFilteredAppCommentThreadIds = (
applicationThreadIds: Array<string>,
commentThreadsMap: Record<string, CommentThread>,
shouldShowResolved: boolean,
appCommentsFilter: typeof filterOptions[number]["value"],
currentUserUsername?: string,
): Array<string> => {
if (!applicationThreadIds) return [];
return applicationThreadIds
.sort((a, b) => {
const {
pinnedState: isAPinned,
updationTime: updationTimeA,
} = commentThreadsMap[a];
const {
pinnedState: isBPinned,
updationTime: updationTimeB,
} = commentThreadsMap[b];
let sortIdx = getSortIndexBool(!!isAPinned?.active, !!isBPinned?.active);
if (sortIdx !== 0) return sortIdx;
sortIdx = getSortIndexTime(
isAPinned?.updationTime?.epochSecond,
isBPinned?.updationTime?.epochSecond,
);
if (sortIdx !== 0) return sortIdx;
return getSortIndexTime(updationTimeA, updationTimeB);
})
.filter((threadId: string) => {
const thread = commentThreadsMap[threadId];
// Happens during delete thread
if (!thread) return false;
const isResolved = thread.resolvedState?.active;
const isPinned = thread.pinnedState?.active;
switch (appCommentsFilter) {
case "show-only-yours": {
const containsMyComment = getContainsMyComment(
thread,
currentUserUsername,
);
return containsMyComment;
}
case "show-only-pinned": {
return isPinned && (!isResolved || shouldShowResolved);
}
default: {
return shouldShowResolved || !isResolved;
}
}
});
};
export const shouldShowResolved = (state: AppState) =>
state.ui.comments.shouldShowResolvedAppCommentThreads;
export const appCommentsFilter = (state: AppState) =>
state.ui.comments.appCommentsFilter;
export const showUnreadIndicator = (state: AppState) =>
state.ui.comments.showUnreadIndicator;
export const visibleCommentThread = (state: AppState) =>
state.ui.comments.visibleCommentThreadId;
export const isIntroCarouselVisibleSelector = (state: AppState) =>
state.ui.comments.isIntroCarouselVisible;