From 992cf790316ca3f3253ea78df706a34c31f4ebd7 Mon Sep 17 00:00:00 2001 From: Aaryan Khandelwal <65252264+aaryan610@users.noreply.github.com> Date: Fri, 3 Nov 2023 19:13:10 +0530 Subject: [PATCH] chore: peek overview authorization (#2632) * chore: peek overview authorization * chore: comment access specifier validation --- .../core/src/ui/menus/menu-items/index.tsx | 78 ++++++--- .../src/ui/menus/fixed-menu/index.tsx | 162 ++++++++++-------- web/components/issues/comment/add-comment.tsx | 58 ++++--- .../issues/issue-layouts/list/properties.tsx | 1 + .../activity/comment-editor.tsx | 46 ++--- .../issue-peek-overview/activity/view.tsx | 7 +- .../issues/issue-peek-overview/properties.tsx | 53 ++++-- .../issues/issue-peek-overview/root.tsx | 7 +- .../issues/issue-peek-overview/view.tsx | 31 +++- web/components/project/join-project-modal.tsx | 9 +- web/layouts/auth-layout/user-wrapper.tsx | 12 +- web/types/projects.d.ts | 1 - 12 files changed, 270 insertions(+), 195 deletions(-) diff --git a/packages/editor/core/src/ui/menus/menu-items/index.tsx b/packages/editor/core/src/ui/menus/menu-items/index.tsx index f31b6601e..8a2651d1e 100644 --- a/packages/editor/core/src/ui/menus/menu-items/index.tsx +++ b/packages/editor/core/src/ui/menus/menu-items/index.tsx @@ -1,7 +1,37 @@ -import { BoldIcon, Heading1, CheckSquare, Heading2, Heading3, QuoteIcon, ImageIcon, TableIcon, ListIcon, ListOrderedIcon, ItalicIcon, UnderlineIcon, StrikethroughIcon, CodeIcon } from "lucide-react"; +import { + BoldIcon, + Heading1, + CheckSquare, + Heading2, + Heading3, + QuoteIcon, + ImageIcon, + TableIcon, + ListIcon, + ListOrderedIcon, + ItalicIcon, + UnderlineIcon, + StrikethroughIcon, + CodeIcon, +} from "lucide-react"; import { Editor } from "@tiptap/react"; import { UploadImage } from "../../../types/upload-image"; -import { insertImageCommand, insertTableCommand, toggleBlockquote, toggleBold, toggleBulletList, toggleCode, toggleHeadingOne, toggleHeadingThree, toggleHeadingTwo, toggleItalic, toggleOrderedList, toggleStrike, toggleTaskList, toggleUnderline, } from "../../../lib/editor-commands"; +import { + insertImageCommand, + insertTableCommand, + toggleBlockquote, + toggleBold, + toggleBulletList, + toggleCode, + toggleHeadingOne, + toggleHeadingThree, + toggleHeadingTwo, + toggleItalic, + toggleOrderedList, + toggleStrike, + toggleTaskList, + toggleUnderline, +} from "../../../lib/editor-commands"; export interface EditorMenuItem { name: string; @@ -15,95 +45,101 @@ export const HeadingOneItem = (editor: Editor): EditorMenuItem => ({ isActive: () => editor.isActive("heading", { level: 1 }), command: () => toggleHeadingOne(editor), icon: Heading1, -}) +}); export const HeadingTwoItem = (editor: Editor): EditorMenuItem => ({ name: "H2", isActive: () => editor.isActive("heading", { level: 2 }), command: () => toggleHeadingTwo(editor), icon: Heading2, -}) +}); export const HeadingThreeItem = (editor: Editor): EditorMenuItem => ({ name: "H3", isActive: () => editor.isActive("heading", { level: 3 }), command: () => toggleHeadingThree(editor), icon: Heading3, -}) +}); export const BoldItem = (editor: Editor): EditorMenuItem => ({ name: "bold", isActive: () => editor?.isActive("bold"), command: () => toggleBold(editor), icon: BoldIcon, -}) +}); export const ItalicItem = (editor: Editor): EditorMenuItem => ({ name: "italic", isActive: () => editor?.isActive("italic"), command: () => toggleItalic(editor), icon: ItalicIcon, -}) +}); export const UnderLineItem = (editor: Editor): EditorMenuItem => ({ name: "underline", isActive: () => editor?.isActive("underline"), command: () => toggleUnderline(editor), icon: UnderlineIcon, -}) +}); export const StrikeThroughItem = (editor: Editor): EditorMenuItem => ({ name: "strike", isActive: () => editor?.isActive("strike"), command: () => toggleStrike(editor), icon: StrikethroughIcon, -}) +}); export const CodeItem = (editor: Editor): EditorMenuItem => ({ name: "code", isActive: () => editor?.isActive("code"), command: () => toggleCode(editor), icon: CodeIcon, -}) +}); export const BulletListItem = (editor: Editor): EditorMenuItem => ({ name: "bullet-list", isActive: () => editor?.isActive("bulletList"), command: () => toggleBulletList(editor), icon: ListIcon, -}) +}); export const TodoListItem = (editor: Editor): EditorMenuItem => ({ name: "To-do List", isActive: () => editor.isActive("taskItem"), command: () => toggleTaskList(editor), icon: CheckSquare, -}) +}); export const NumberedListItem = (editor: Editor): EditorMenuItem => ({ name: "ordered-list", isActive: () => editor?.isActive("orderedList"), command: () => toggleOrderedList(editor), - icon: ListOrderedIcon -}) + icon: ListOrderedIcon, +}); export const QuoteItem = (editor: Editor): EditorMenuItem => ({ name: "quote", isActive: () => editor?.isActive("quote"), command: () => toggleBlockquote(editor), - icon: QuoteIcon -}) + icon: QuoteIcon, +}); export const TableItem = (editor: Editor): EditorMenuItem => ({ - name: "quote", + name: "table", isActive: () => editor?.isActive("table"), command: () => insertTableCommand(editor), - icon: TableIcon -}) + icon: TableIcon, +}); -export const ImageItem = (editor: Editor, uploadFile: UploadImage, setIsSubmitting?: (isSubmitting: "submitting" | "submitted" | "saved") => void): EditorMenuItem => ({ +export const ImageItem = ( + editor: Editor, + uploadFile: UploadImage, + setIsSubmitting?: ( + isSubmitting: "submitting" | "submitted" | "saved", + ) => void, +): EditorMenuItem => ({ name: "image", isActive: () => editor?.isActive("image"), command: () => insertImageCommand(editor, uploadFile, setIsSubmitting), icon: ImageIcon, -}) +}); diff --git a/packages/editor/lite-text-editor/src/ui/menus/fixed-menu/index.tsx b/packages/editor/lite-text-editor/src/ui/menus/fixed-menu/index.tsx index 62957a769..cf0d78688 100644 --- a/packages/editor/lite-text-editor/src/ui/menus/fixed-menu/index.tsx +++ b/packages/editor/lite-text-editor/src/ui/menus/fixed-menu/index.tsx @@ -72,12 +72,10 @@ export const FixedMenu = (props: EditorBubbleMenuProps) => { props.commentAccessSpecifier?.onAccessChange(accessKey); }; - console.log(complexItems); - return ( -
+
{props.commentAccessSpecifier && ( -
+
{props?.commentAccessSpecifier.commentAccess?.map((access) => (
)} -
+
{basicMarkItems.map((item, index) => ( - + + ))}
{listItems.map((item, index) => ( - + + ))}
{userActionItems.map((item, index) => ( - + + ))}
{complexItems.map((item, index) => ( - + + ))}
- {props.submitButton} +
{props.submitButton}
); diff --git a/web/components/issues/comment/add-comment.tsx b/web/components/issues/comment/add-comment.tsx index 9b1f49f46..71294b8c5 100644 --- a/web/components/issues/comment/add-comment.tsx +++ b/web/components/issues/comment/add-comment.tsx @@ -52,7 +52,7 @@ export const AddComment: React.FC = ({ disabled = false, onSubmit, showAc const router = useRouter(); const { workspaceSlug, projectId } = router.query; - const editorSuggestions = useEditorSuggestions(workspaceSlug as string | undefined, projectId as string | undefined) + const editorSuggestions = useEditorSuggestions(workspaceSlug as string | undefined, projectId as string | undefined); const { control, @@ -74,33 +74,35 @@ export const AddComment: React.FC = ({ disabled = false, onSubmit, showAc
-
- ( - ( -

" : commentValue} - customClassName="p-3 min-h-[100px] shadow-sm" - debouncedUpdatesEnabled={false} - onChange={(comment_json: Object, comment_html: string) => onCommentChange(comment_html)} - commentAccessSpecifier={{ accessValue, onAccessChange, showAccessSpecifier, commentAccess }} - mentionSuggestions={editorSuggestions.mentionSuggestions} - mentionHighlights={editorSuggestions.mentionHighlights} - /> - )} - /> - )} - /> -
+ ( + ( +

" : commentValue} + customClassName="p-3 min-h-[100px] shadow-sm" + debouncedUpdatesEnabled={false} + onChange={(comment_json: Object, comment_html: string) => onCommentChange(comment_html)} + commentAccessSpecifier={ + showAccessSpecifier + ? { accessValue, onAccessChange, showAccessSpecifier, commentAccess } + : undefined + } + mentionSuggestions={editorSuggestions.mentionSuggestions} + mentionHighlights={editorSuggestions.mentionHighlights} + /> + )} + /> + )} + /> - - ))} -
- )} - /> -
- )} +
= (props) => { mentionSuggestions={editorSuggestions.mentionSuggestions} mentionHighlights={editorSuggestions.mentionHighlights} onChange={(comment_json: Object, comment_html: string) => onCommentChange(comment_html)} - commentAccessSpecifier={{ accessValue, onAccessChange, showAccessSpecifier, commentAccess }} + commentAccessSpecifier={ + showAccessSpecifier + ? { accessValue, onAccessChange, showAccessSpecifier, commentAccess } + : undefined + } submitButton={
@@ -207,7 +206,11 @@ export const PeekOverviewProperties: FC = observer((pro

Assignees

- +
@@ -218,7 +221,11 @@ export const PeekOverviewProperties: FC = observer((pro

Priority

- +
@@ -229,7 +236,11 @@ export const PeekOverviewProperties: FC = observer((pro

Estimate

- +
@@ -246,7 +257,7 @@ export const PeekOverviewProperties: FC = observer((pro onChange={handleStartDate} className="bg-custom-background-80 border-none !px-2.5 !py-0.5" maxDate={maxDate ?? undefined} - disabled={isNotAllowed} + disabled={disableUserActions} /> @@ -264,7 +275,7 @@ export const PeekOverviewProperties: FC = observer((pro onChange={handleTargetDate} className="bg-custom-background-80 border-none !px-2.5 !py-0.5" minDate={minDate ?? undefined} - disabled={isNotAllowed} + disabled={disableUserActions} /> @@ -276,7 +287,7 @@ export const PeekOverviewProperties: FC = observer((pro

Parent

- +
@@ -290,7 +301,11 @@ export const PeekOverviewProperties: FC = observer((pro

Cycle

- +
@@ -300,7 +315,11 @@ export const PeekOverviewProperties: FC = observer((pro

Module

- +
@@ -313,8 +332,8 @@ export const PeekOverviewProperties: FC = observer((pro issueDetails={issue} labelList={issue.labels} submitChanges={handleLabels} - isNotAllowed={isNotAllowed} - uneditable={isNotAllowed} + isNotAllowed={disableUserActions} + uneditable={disableUserActions} />
@@ -330,11 +349,11 @@ export const PeekOverviewProperties: FC = observer((pro

Links

- {!isNotAllowed && ( + {!disableUserActions && ( - + {!disableUserActions && ( + + )}
@@ -264,7 +271,11 @@ export const IssueView: FC = observer((props) => { issueReactionRemove={issueReactionRemove} /> - + = observer((props) => { issueCommentRemove={issueCommentRemove} issueCommentReactionCreate={issueCommentReactionCreate} issueCommentReactionRemove={issueCommentReactionRemove} + showCommentAccessSpecifier={showCommentAccessSpecifier} /> ) : ( @@ -305,10 +317,15 @@ export const IssueView: FC = observer((props) => { issueCommentRemove={issueCommentRemove} issueCommentReactionCreate={issueCommentReactionCreate} issueCommentReactionRemove={issueCommentReactionRemove} + showCommentAccessSpecifier={showCommentAccessSpecifier} />
- +
)} diff --git a/web/components/project/join-project-modal.tsx b/web/components/project/join-project-modal.tsx index b6a212eb7..9debb0d83 100644 --- a/web/components/project/join-project-modal.tsx +++ b/web/components/project/join-project-modal.tsx @@ -1,4 +1,5 @@ import { useState, Fragment } from "react"; +import { useRouter } from "next/router"; import { Transition, Dialog } from "@headlessui/react"; // ui import { Button } from "@plane/ui"; @@ -17,10 +18,12 @@ type TJoinProjectModalProps = { export const JoinProjectModal: React.FC = (props) => { const { handleClose, isOpen, project, workspaceSlug } = props; - // store - const { project: projectStore } = useMobxStore(); // states const [isJoiningLoading, setIsJoiningLoading] = useState(false); + // store + const { project: projectStore } = useMobxStore(); + // router + const router = useRouter(); const handleJoin = () => { setIsJoiningLoading(true); @@ -29,6 +32,8 @@ export const JoinProjectModal: React.FC = (props) => { .joinProject(workspaceSlug, [project.id]) .then(() => { setIsJoiningLoading(false); + + router.push(`/${workspaceSlug}/projects/${project.id}/issues`); handleClose(); }) .catch(() => { diff --git a/web/layouts/auth-layout/user-wrapper.tsx b/web/layouts/auth-layout/user-wrapper.tsx index 7e4f51fb7..321e43888 100644 --- a/web/layouts/auth-layout/user-wrapper.tsx +++ b/web/layouts/auth-layout/user-wrapper.tsx @@ -17,11 +17,17 @@ export const UserAuthWrapper: FC = (props) => { // router const router = useRouter(); // fetching user information - const { data: currentUser, error } = useSWR("CURRENT_USER_DETAILS", () => userStore.fetchCurrentUser()); + const { data: currentUser, error } = useSWR("CURRENT_USER_DETAILS", () => userStore.fetchCurrentUser(), { + shouldRetryOnError: false, + }); // fetching user settings - useSWR("CURRENT_USER_SETTINGS", () => userStore.fetchCurrentUserSettings()); + useSWR("CURRENT_USER_SETTINGS", () => userStore.fetchCurrentUserSettings(), { + shouldRetryOnError: false, + }); // fetching all workspaces - useSWR(`USER_WORKSPACES_LIST`, () => workspaceStore.fetchWorkspaces()); + useSWR(`USER_WORKSPACES_LIST`, () => workspaceStore.fetchWorkspaces(), { + shouldRetryOnError: false, + }); if (!currentUser && !error) { return ( diff --git a/web/types/projects.d.ts b/web/types/projects.d.ts index 2ee0fc43a..129b0bb3b 100644 --- a/web/types/projects.d.ts +++ b/web/types/projects.d.ts @@ -43,7 +43,6 @@ export interface IProject { page_view: boolean; project_lead: IUserLite | string | null; sort_order: number | null; - slug: string; total_cycles: number; total_members: number; total_modules: number;