fixed mentions not showing in modals

This commit is contained in:
Palanikannan1437 2024-03-04 13:20:44 +05:30
parent a3033203af
commit 43fd94827f
22 changed files with 253 additions and 167 deletions

View File

@ -5,7 +5,7 @@ import { CoreEditorExtensions } from "src/ui/extensions";
import { EditorProps } from "@tiptap/pm/view";
import { getTrimmedHTML } from "src/lib/utils";
import { DeleteImage } from "src/types/delete-image";
import { IMentionSuggestion } from "src/types/mention-suggestion";
import { IMentionHighlight, IMentionSuggestion } from "src/types/mention-suggestion";
import { RestoreImage } from "src/types/restore-image";
import { UploadImage } from "src/types/upload-image";
@ -27,8 +27,8 @@ interface CustomEditorProps {
extensions?: any;
editorProps?: EditorProps;
forwardedRef?: any;
mentionHighlights?: string[];
mentionSuggestions?: IMentionSuggestion[];
mentionHighlights?: () => Promise<IMentionHighlight[]>;
mentionSuggestions?: () => Promise<IMentionSuggestion[]>;
}
export const useEditor = ({
@ -48,6 +48,7 @@ export const useEditor = ({
mentionHighlights,
mentionSuggestions,
}: CustomEditorProps) => {
console.log("the mentions", mentionHighlights);
const editor = useCustomEditor(
{
editorProps: {
@ -57,8 +58,8 @@ export const useEditor = ({
extensions: [
...CoreEditorExtensions(
{
mentionSuggestions: mentionSuggestions ?? [],
mentionHighlights: mentionHighlights ?? [],
mentionSuggestions: mentionSuggestions,
mentionHighlights: mentionHighlights,
},
deleteFile,
restoreFile,

View File

@ -68,7 +68,7 @@
top: 0;
bottom: -2px;
width: 4px;
z-index: 99;
z-index: 5;
background-color: rgba(var(--color-primary-400));
pointer-events: none;
}
@ -81,7 +81,7 @@
.tableWrapper .tableControls .rowsControl {
transition: opacity ease-in 100ms;
position: absolute;
z-index: 99;
z-index: 5;
display: flex;
justify-content: center;
align-items: center;

View File

@ -22,94 +22,92 @@ import { CustomKeymap } from "src/ui/extensions/keymap";
import { CustomQuoteExtension } from "src/ui/extensions/quote";
import { DeleteImage } from "src/types/delete-image";
import { IMentionSuggestion } from "src/types/mention-suggestion";
import { IMentionHighlight, IMentionSuggestion } from "src/types/mention-suggestion";
import { RestoreImage } from "src/types/restore-image";
import { CustomLinkExtension } from "src/ui/extensions/custom-link";
import { CustomCodeInlineExtension } from "./code-inline";
export const CoreEditorExtensions = (
mentionConfig: {
mentionSuggestions: IMentionSuggestion[];
mentionHighlights: string[];
mentionSuggestions?: () => Promise<IMentionSuggestion[]>;
mentionHighlights?: () => Promise<IMentionHighlight[]>;
},
deleteFile: DeleteImage,
restoreFile: RestoreImage,
cancelUploadImage?: () => any
) => {
return [
StarterKit.configure({
bulletList: {
HTMLAttributes: {
class: "list-disc list-outside leading-3 -mt-2",
},
},
orderedList: {
HTMLAttributes: {
class: "list-decimal list-outside leading-3 -mt-2",
},
},
listItem: {
HTMLAttributes: {
class: "leading-normal -mb-2",
},
},
code: false,
codeBlock: false,
horizontalRule: {
HTMLAttributes: { class: "mt-4 mb-4" },
},
blockquote: false,
dropcursor: {
color: "rgba(var(--color-text-100))",
width: 2,
},
}),
CustomQuoteExtension.configure({
HTMLAttributes: { className: "border-l-4 border-custom-border-300" },
}),
CustomKeymap,
ListKeymap,
CustomLinkExtension.configure({
openOnClick: true,
autolink: true,
linkOnPaste: true,
protocols: ["http", "https"],
validate: (url: string) => isValidHttpUrl(url),
) => [
StarterKit.configure({
bulletList: {
HTMLAttributes: {
class:
"text-custom-primary-300 underline underline-offset-[3px] hover:text-custom-primary-500 transition-colors cursor-pointer",
class: "list-disc list-outside leading-3 -mt-2",
},
}),
ImageExtension(deleteFile, restoreFile, cancelUploadImage).configure({
},
orderedList: {
HTMLAttributes: {
class: "rounded-lg border border-custom-border-300",
class: "list-decimal list-outside leading-3 -mt-2",
},
}),
TiptapUnderline,
TextStyle,
Color,
TaskList.configure({
},
listItem: {
HTMLAttributes: {
class: "not-prose pl-2",
class: "leading-normal -mb-2",
},
}),
TaskItem.configure({
HTMLAttributes: {
class: "flex items-start my-4",
},
nested: true,
}),
CustomCodeBlockExtension,
CustomCodeInlineExtension,
Markdown.configure({
html: true,
transformCopiedText: true,
transformPastedText: true,
}),
Table,
TableHeader,
TableCell,
TableRow,
Mentions(mentionConfig.mentionSuggestions, mentionConfig.mentionHighlights, false),
];
};
},
code: false,
codeBlock: false,
horizontalRule: {
HTMLAttributes: { class: "mt-4 mb-4" },
},
blockquote: false,
dropcursor: {
color: "rgba(var(--color-text-100))",
width: 2,
},
}),
CustomQuoteExtension.configure({
HTMLAttributes: { className: "border-l-4 border-custom-border-300" },
}),
CustomKeymap,
ListKeymap,
CustomLinkExtension.configure({
openOnClick: true,
autolink: true,
linkOnPaste: true,
protocols: ["http", "https"],
validate: (url: string) => isValidHttpUrl(url),
HTMLAttributes: {
class:
"text-custom-primary-300 underline underline-offset-[3px] hover:text-custom-primary-500 transition-colors cursor-pointer",
},
}),
ImageExtension(deleteFile, restoreFile, cancelUploadImage).configure({
HTMLAttributes: {
class: "rounded-lg border border-custom-border-300",
},
}),
TiptapUnderline,
TextStyle,
Color,
TaskList.configure({
HTMLAttributes: {
class: "not-prose pl-2",
},
}),
TaskItem.configure({
HTMLAttributes: {
class: "flex items-start my-4",
},
nested: true,
}),
CustomCodeBlockExtension,
CustomCodeInlineExtension,
Markdown.configure({
html: true,
transformCopiedText: true,
transformPastedText: true,
}),
Table,
TableHeader,
TableCell,
TableRow,
Mentions(mentionConfig.mentionSuggestions, mentionConfig.mentionHighlights, false),
];

View File

@ -5,7 +5,7 @@ import { MentionNodeView } from "src/ui/mentions/mention-node-view";
import { IMentionHighlight } from "src/types/mention-suggestion";
export interface CustomMentionOptions extends MentionOptions {
mentionHighlights: IMentionHighlight[];
mentionHighlights: () => Promise<IMentionHighlight[]>;
readonly?: boolean;
}

View File

@ -7,29 +7,9 @@ import tippy from "tippy.js";
import { v4 as uuidv4 } from "uuid";
import { MentionList } from "src/ui/mentions/mention-list";
export const getSuggestionItems =
(getSuggestions: () => Promise<IMentionSuggestion[]>) =>
async ({ query }: { query: string }) => {
console.log("yaa");
const suggestions = await getSuggestions();
const mappedSuggestions: IMentionSuggestion[] = suggestions.map((suggestion): IMentionSuggestion => {
const transactionId = uuidv4();
return {
...suggestion,
id: transactionId,
};
});
const filteredSuggestions = mappedSuggestions
.filter((suggestion) => suggestion.title.toLowerCase().startsWith(query.toLowerCase()))
.slice(0, 5);
console.log("yoo", filteredSuggestions);
return filteredSuggestions;
};
export const Mentions = (
mentionSuggestions: () => Promise<IMentionSuggestion[]>,
mentionHighlights: IMentionHighlight[],
mentionHighlights: () => Promise<IMentionHighlight[]>,
readonly: boolean
) =>
CustomMention.configure({
@ -39,8 +19,8 @@ export const Mentions = (
readonly: readonly,
mentionHighlights: mentionHighlights,
suggestion: {
items: ({ query }) => {
const suggestions = mentionSuggestions();
items: async ({ query }) => {
const suggestions = await mentionSuggestions();
const mappedSuggestions: IMentionSuggestion[] = suggestions.map((suggestion): IMentionSuggestion => {
const transactionId = uuidv4();
return {
@ -48,11 +28,11 @@ export const Mentions = (
id: transactionId,
};
});
const filteredSuggestions = mappedSuggestions
.filter((suggestion) => suggestion.title.toLowerCase().startsWith(query.toLowerCase()))
.slice(0, 5);
console.log("yoo", filteredSuggestions);
return filteredSuggestions;
},
// @ts-ignore
@ -60,33 +40,44 @@ export const Mentions = (
let reactRenderer: ReactRenderer | null = null;
let popup: any | null = null;
const hidePopup = () => {
popup?.[0].hide();
};
return {
onStart: (props: { editor: Editor; clientRect: DOMRect }) => {
props.editor.storage.mentionsOpen = true;
if (!props.clientRect) {
return;
}
reactRenderer = new ReactRenderer(MentionList, {
props,
editor: props.editor,
});
props.editor.storage.mentionsOpen = true;
// @ts-ignore
popup = tippy("body", {
getReferenceClientRect: props.clientRect,
appendTo: () => document.querySelector("#editor-container"),
appendTo: () => document.body,
content: reactRenderer.element,
showOnCreate: true,
interactive: true,
trigger: "manual",
placement: "bottom-start",
});
// document.addEventListener("scroll", hidePopup, true);
},
onUpdate: (props: { editor: Editor; clientRect: DOMRect }) => {
reactRenderer?.updateProps(props);
if (!props.clientRect) {
return;
}
popup &&
popup[0].setProps({
getReferenceClientRect: props.clientRect,
});
},
onKeyDown: (props: { event: KeyboardEvent }) => {
if (props.event.key === "Escape") {
popup?.[0].hide();
@ -108,6 +99,8 @@ export const Mentions = (
props.editor.storage.mentionsOpen = false;
popup?.[0].destroy();
reactRenderer?.destroy();
// document.removeEventListener("scroll", hidePopup, true);
},
};
},

View File

@ -12,6 +12,7 @@ interface MentionListProps {
export const MentionList = forwardRef((props: MentionListProps, ref) => {
const [selectedIndex, setSelectedIndex] = useState(0);
console.log("props", props);
const selectItem = (index: number) => {
const item = props.items[index];

View File

@ -4,11 +4,22 @@ import { NodeViewWrapper } from "@tiptap/react";
import { cn } from "src/lib/utils";
import { useRouter } from "next/router";
import { IMentionHighlight } from "src/types/mention-suggestion";
import { useEffect, useState } from "react";
// eslint-disable-next-line import/no-anonymous-default-export
export const MentionNodeView = (props) => {
const router = useRouter();
const highlights = props.extension.options.mentionHighlights as IMentionHighlight[];
// const highlights = props.extension.options.mentionHighlights as IMentionHighlight[];
const [highlightsState, setHighlightsState] = useState();
useEffect(() => {
console.log("hightlights type", props.extension.options.mentionHighlights);
const hightlights = async () => {
const userId = await props.extension.options.mentionHighlights();
setHighlightsState(userId);
};
hightlights();
}, []);
const handleClick = () => {
if (!props.extension.options.readonly) {
@ -16,12 +27,13 @@ export const MentionNodeView = (props) => {
}
};
console.log("state of highlight", highlightsState);
return (
<NodeViewWrapper className="mention-component inline w-fit">
<span
className={cn("mention rounded bg-custom-primary-100/20 px-1 py-0.5 font-medium text-custom-primary-100", {
"bg-yellow-500/20 text-yellow-500": highlights
? highlights.includes(props.node.attrs.entity_identifier)
"bg-yellow-500/20 text-yellow-500": highlightsState
? highlightsState.includes(props.node.attrs.entity_identifier)
: false,
"cursor-pointer": !props.extension.options.readonly,
// "hover:bg-custom-primary-300" : !props.extension.options.readonly && !highlights.includes(props.node.attrs.id)

View File

@ -126,6 +126,7 @@ const DocumentEditor = ({
extensions: DocumentEditorExtensions(uploadFile, setHideDragHandleFunction, setIsSubmitting),
});
console.log("in document editor", mentionHighlights);
if (!editor) {
return null;
}

View File

@ -327,10 +327,10 @@ const renderItems = () => {
// @ts-ignore
popup = tippy("body", {
getReferenceClientRect: props.clientRect,
appendTo: () => document.querySelector("#editor-container"),
appendTo: () => document.body,
content: component.element,
showOnCreate: true,
interactive: true,
// interactive: true,
trigger: "manual",
placement: "bottom-start",
});

View File

@ -15,7 +15,6 @@ export interface IUser {
is_email_verified: boolean;
is_managed: boolean;
is_onboarded: boolean;
is_password_autoset: boolean;
is_tour_completed: boolean;
is_password_autoset: boolean;
mobile_number: string | null;

View File

@ -48,7 +48,7 @@ export const CreateInboxIssueModal: React.FC<Props> = observer((props) => {
const editorRef = useRef<any>(null);
// toast alert
const { setToastAlert } = useToast();
const { mentionHighlights, mentionSuggestions } = useMention();
// router
const router = useRouter();
const { workspaceSlug, projectId, inboxId } = router.query as {
@ -59,6 +59,13 @@ export const CreateInboxIssueModal: React.FC<Props> = observer((props) => {
const workspaceStore = useWorkspace();
const workspaceId = workspaceStore.getWorkspaceBySlug(workspaceSlug as string)?.id as string;
console.log("in create issue modal", workspaceSlug, projectId);
const { mentionHighlights, mentionSuggestions } = useMention({
workspaceSlug: workspaceSlug as string,
projectId: projectId as string,
});
// store hooks
const {
issues: { createInboxIssue },

View File

@ -48,7 +48,11 @@ export const IssueDescriptionForm: FC<IssueDetailsProps> = observer((props) => {
const { setShowAlert } = useReloadConfirmations();
// store hooks
const { mentionHighlights, mentionSuggestions } = useMention();
const { mentionHighlights, mentionSuggestions } = useMention({
workspaceSlug: workspaceSlug as string,
projectId: projectId as string,
});
// form info
const {
handleSubmit,

View File

@ -106,10 +106,6 @@ export const DraftIssueForm: FC<IssueFormProps> = observer((props) => {
const [iAmFeelingLucky, setIAmFeelingLucky] = useState(false);
// store hooks
const { areEstimatesEnabledForProject } = useEstimate();
const { mentionHighlights, mentionSuggestions } = useMention();
// hooks
const { setValue: setLocalStorageValue } = useLocalStorage("draftedIssue", {});
const { setToastAlert } = useToast();
// refs
const editorRef = useRef<any>(null);
// router
@ -118,6 +114,14 @@ export const DraftIssueForm: FC<IssueFormProps> = observer((props) => {
const workspaceStore = useWorkspace();
const workspaceId = workspaceStore.getWorkspaceBySlug(workspaceSlug as string)?.id as string;
// hooks
const { setValue: setLocalStorageValue } = useLocalStorage("draftedIssue", {});
const { setToastAlert } = useToast();
const { mentionHighlights, mentionSuggestions } = useMention({
workspaceSlug: workspaceSlug as string,
projectId: projectId as string,
});
// store
const {
config: { envConfig },

View File

@ -10,13 +10,14 @@ import { TActivityOperations } from "./root";
type TIssueActivityCommentRoot = {
workspaceSlug: string;
projectId: string;
issueId: string;
activityOperations: TActivityOperations;
showAccessSpecifier?: boolean;
};
export const IssueActivityCommentRoot: FC<TIssueActivityCommentRoot> = observer((props) => {
const { workspaceSlug, issueId, activityOperations, showAccessSpecifier } = props;
const { workspaceSlug, issueId, activityOperations, showAccessSpecifier, projectId } = props;
// hooks
const {
activity: { getActivityCommentByIssueId },
@ -31,6 +32,7 @@ export const IssueActivityCommentRoot: FC<TIssueActivityCommentRoot> = observer(
{activityComments.map((activityComment, index) =>
activityComment.activity_type === "COMMENT" ? (
<IssueCommentCard
projectId={projectId}
workspaceSlug={workspaceSlug}
commentId={activityComment.id}
activityOperations={activityOperations}

View File

@ -18,6 +18,7 @@ import { TActivityOperations } from "../root";
const fileService = new FileService();
type TIssueCommentCard = {
projectId: string;
workspaceSlug: string;
commentId: string;
activityOperations: TActivityOperations;
@ -26,13 +27,16 @@ type TIssueCommentCard = {
};
export const IssueCommentCard: FC<TIssueCommentCard> = (props) => {
const { workspaceSlug, commentId, activityOperations, ends, showAccessSpecifier = false } = props;
const { workspaceSlug, projectId, commentId, activityOperations, ends, showAccessSpecifier = false } = props;
// hooks
const {
comment: { getCommentById },
} = useIssueDetail();
const { currentUser } = useUser();
const { mentionHighlights, mentionSuggestions } = useMention();
const { mentionHighlights, mentionSuggestions } = useMention({
workspaceSlug: workspaceSlug as string,
projectId: projectId as string,
});
// refs
const editorRef = useRef<any>(null);
const showEditorRef = useRef<any>(null);

View File

@ -15,6 +15,7 @@ import { useMention, useWorkspace } from "hooks/store";
const fileService = new FileService();
type TIssueCommentCreate = {
projectId: string;
workspaceSlug: string;
activityOperations: TActivityOperations;
showAccessSpecifier?: boolean;
@ -39,11 +40,14 @@ const commentAccess: commentAccessType[] = [
];
export const IssueCommentCreate: FC<TIssueCommentCreate> = (props) => {
const { workspaceSlug, activityOperations, showAccessSpecifier = false } = props;
const { workspaceSlug, projectId, activityOperations, showAccessSpecifier = false } = props;
const workspaceStore = useWorkspace();
const workspaceId = workspaceStore.getWorkspaceBySlug(workspaceSlug as string)?.id as string;
const { mentionHighlights, mentionSuggestions } = useMention();
const { mentionHighlights, mentionSuggestions } = useMention({
workspaceSlug: workspaceSlug as string,
projectId: projectId as string,
});
// refs
const editorRef = useRef<any>(null);

View File

@ -8,6 +8,7 @@ import { IssueCommentCard } from "./comment-card";
import { TActivityOperations } from "../root";
type TIssueCommentRoot = {
projectId: string;
workspaceSlug: string;
issueId: string;
activityOperations: TActivityOperations;
@ -15,7 +16,7 @@ type TIssueCommentRoot = {
};
export const IssueCommentRoot: FC<TIssueCommentRoot> = observer((props) => {
const { workspaceSlug, issueId, activityOperations, showAccessSpecifier } = props;
const { workspaceSlug, projectId, issueId, activityOperations, showAccessSpecifier } = props;
// hooks
const {
comment: { getCommentsByIssueId },
@ -28,6 +29,7 @@ export const IssueCommentRoot: FC<TIssueCommentRoot> = observer((props) => {
<div>
{commentIds.map((commentId, index) => (
<IssueCommentCard
projectId={projectId}
workspaceSlug={workspaceSlug}
commentId={commentId}
ends={index === 0 ? "top" : index === commentIds.length - 1 ? "bottom" : undefined}

View File

@ -141,12 +141,14 @@ export const IssueActivity: FC<TIssueActivity> = observer((props) => {
{activityTab === "all" ? (
<div className="space-y-3">
<IssueActivityCommentRoot
projectId={projectId}
workspaceSlug={workspaceSlug}
issueId={issueId}
activityOperations={activityOperations}
showAccessSpecifier={project.is_deployed}
/>
<IssueCommentCreate
projectId={projectId}
workspaceSlug={workspaceSlug}
activityOperations={activityOperations}
showAccessSpecifier={project.is_deployed}
@ -157,12 +159,14 @@ export const IssueActivity: FC<TIssueActivity> = observer((props) => {
) : (
<div className="space-y-3">
<IssueCommentRoot
projectId={projectId}
workspaceSlug={workspaceSlug}
issueId={issueId}
activityOperations={activityOperations}
showAccessSpecifier={project.is_deployed}
/>
<IssueCommentCreate
projectId={projectId}
workspaceSlug={workspaceSlug}
activityOperations={activityOperations}
showAccessSpecifier={project.is_deployed}

View File

@ -96,7 +96,11 @@ export const IssueFormRoot: FC<IssueFormProps> = observer((props) => {
} = useApplication();
const { getProjectById } = useProject();
const { areEstimatesEnabledForProject } = useEstimate();
const { mentionHighlights, mentionSuggestions } = useMention();
const { mentionHighlights, mentionSuggestions } = useMention({
workspaceSlug: workspaceSlug as string,
projectId: defaultProjectId,
});
const {
issue: { getIssueById },
} = useIssueDetail();

View File

@ -1,23 +1,27 @@
import useSWR from "swr";
import { ProjectMemberService } from "services/project";
import { IProjectMember } from "@plane/types";
import { UserService } from "services/user.service";
import { useRef, useEffect } from "react";
import { ProjectMemberService } from "services/project";
import { IProjectMember, IUser } from "@plane/types";
import { UserService } from "services/user.service";
export const useMention = ({ workspaceSlug, projectId }: { workspaceSlug: string; projectId: string }) => {
const userService = new UserService();
const projectMemberService = new ProjectMemberService();
const { data: projectMembers } = useSWR(["projectMembers", workspaceSlug, projectId], async () => {
const members = await projectMemberService.fetchProjectMembers(workspaceSlug, projectId);
const detailedMembers = await Promise.all(
members.map(async (member) => projectMemberService.getProjectMember(workspaceSlug, projectId, member.id))
);
return detailedMembers;
});
const { data: projectMembers, isLoading: projectMembersLoading } = useSWR(
["projectMembers", workspaceSlug, projectId],
async () => {
const members = await projectMemberService.fetchProjectMembers(workspaceSlug, projectId);
const detailedMembers = await Promise.all(
members.map(async (member) => projectMemberService.getProjectMember(workspaceSlug, projectId, member.id))
);
return detailedMembers;
}
);
const { data: user, isLoading: userDataLoading } = useSWR("currentUser", async () => userService.currentUser());
const projectMembersRef = useRef<IProjectMember[] | undefined>();
const userRef = useRef<IUser | undefined>();
useEffect(() => {
if (projectMembers) {
@ -25,13 +29,51 @@ export const useMention = ({ workspaceSlug, projectId }: { workspaceSlug: string
}
}, [projectMembers]);
const { data: user } = useSWR("currentUser", async () => userService.currentUser());
useEffect(() => {
if (userRef) {
userRef.current = user;
}
}, [user]);
const mentionHighlights = user ? [user.id] : [];
const waitForUserDate = async () =>
new Promise<IUser>((resolve) => {
const checkData = () => {
if (userRef.current) {
resolve(userRef.current);
} else {
setTimeout(checkData, 100);
}
};
checkData();
});
const getMentionSuggestions = () => () => {
const mentionSuggestions =
projectMembersRef.current?.map((memberDetails) => ({
const mentionHighlights = async () => {
console.log("isme aaya highlights");
if (!userDataLoading && userRef.current) {
return [userRef.current.id];
} else {
const user = await waitForUserDate();
return [user.id];
}
};
// Polling function to wait for projectMembersRef.current to be populated
const waitForData = async () =>
new Promise<IProjectMember[]>((resolve) => {
const checkData = () => {
if (projectMembersRef.current && projectMembersRef.current.length > 0) {
resolve(projectMembersRef.current);
} else {
setTimeout(checkData, 100); // Check every 100ms
}
};
checkData();
});
const mentionSuggestions = async () => {
if (!projectMembersLoading && projectMembersRef.current && projectMembersRef.current.length > 0) {
// If data is already available, return it immediately
return projectMembersRef.current.map((memberDetails) => ({
entity_name: "user_mention",
entity_identifier: `${memberDetails?.member?.id}`,
type: "User",
@ -39,12 +81,25 @@ export const useMention = ({ workspaceSlug, projectId }: { workspaceSlug: string
subtitle: memberDetails?.member?.email ?? "",
avatar: `${memberDetails?.member?.avatar}`,
redirect_uri: `/${workspaceSlug}/profile/${memberDetails?.member?.id}`,
})) || [];
return mentionSuggestions;
}));
} else {
// Wait for data to be available
const members = await waitForData();
console.log("isme aaya", members);
return members.map((memberDetails) => ({
entity_name: "user_mention",
entity_identifier: `${memberDetails?.member?.id}`,
type: "User",
title: `${memberDetails?.member?.display_name}`,
subtitle: memberDetails?.member?.email ?? "",
avatar: `${memberDetails?.member?.avatar}`,
redirect_uri: `/${workspaceSlug}/profile/${memberDetails?.member?.id}`,
}));
}
};
return {
getMentionSuggestions,
mentionSuggestions,
mentionHighlights,
};
};

View File

@ -1,9 +1,9 @@
import { Sparkle } from "lucide-react";
import { observer } from "mobx-react-lite";
import useSWR from "swr";
import { useRouter } from "next/router";
import { ReactElement, useEffect, useRef, useState } from "react";
import { Controller, useForm } from "react-hook-form";
import useSWR from "swr";
// hooks
import { useApplication, useMention, usePage, useUser, useWorkspace } from "hooks/store";
@ -26,11 +26,9 @@ import { IPage } from "@plane/types";
import { NextPageWithLayout } from "lib/types";
// fetch-keys
// constants
import { IssuePeekOverview } from "components/issues";
import { EUserProjectRoles } from "constants/project";
import { useProjectPages } from "hooks/store/use-project-specific-pages";
import { IssuePeekOverview } from "components/issues";
import { ProjectMemberService } from "services/project";
import { UserService } from "services/user.service";
// services
const fileService = new FileService();
@ -78,6 +76,7 @@ const PageDetailsPage: NextPageWithLayout = observer(() => {
? () => fetchProjectPages(workspaceSlug.toString(), projectId.toString())
: null
);
// fetching archived pages from API
useSWR(
workspaceSlug && projectId ? `ALL_ARCHIVED_PAGES_LIST_${projectId}` : null,
@ -86,21 +85,12 @@ const PageDetailsPage: NextPageWithLayout = observer(() => {
: null
);
const projectMemberService = new ProjectMemberService();
const { data: projectMembers } = useSWR(["projectMembers", workspaceSlug, projectId], async () => {
const members = await projectMemberService.fetchProjectMembers(workspaceSlug, projectId);
const detailedMembers = await Promise.all(
members.map(async (member) => projectMemberService.getProjectMember(workspaceSlug, projectId, member.id))
);
console.log("ye toh chal", detailedMembers);
return detailedMembers;
});
const pageStore = usePage(pageId as string);
// store hooks
const { getMentionSuggestions, mentionHighlights, mentionSuggestions } = useMention({ workspaceSlug, projectId });
const { mentionHighlights, mentionSuggestions } = useMention({
workspaceSlug: workspaceSlug as string,
projectId: projectId as string,
});
const { setShowAlert } = useReloadConfirmations(pageStore?.isSubmitting === "submitting");
@ -317,7 +307,7 @@ const PageDetailsPage: NextPageWithLayout = observer(() => {
last_updated_at: updated_at,
last_updated_by: updated_by,
}}
mentionSuggestions={getMentionSuggestions(projectMembers)}
mentionSuggestions={mentionSuggestions}
mentionHighlights={mentionHighlights}
uploadFile={fileService.getUploadFileFunction(workspaceSlug as string)}
deleteFile={fileService.getDeleteImageFunction(workspaceId)}

View File

@ -6,6 +6,7 @@ import "styles/globals.css";
import "styles/command-pallette.css";
import "styles/nprogress.css";
import "styles/react-datepicker.css";
// constants
import { SITE_TITLE } from "constants/seo-variables";
// mobx store provider