From 4507802abab2e99677b2fc18f225eec8d66e6dc7 Mon Sep 17 00:00:00 2001 From: Prateek Shourya Date: Mon, 16 Dec 2024 19:01:37 +0530 Subject: [PATCH] refactor: enhance workspace and project wrapper modularity (#6207) --- packages/ui/src/modals/constants.ts | 1 + web/app/[workspaceSlug]/(projects)/layout.tsx | 3 +- .../(projects)/projects/(detail)/layout.tsx | 4 +-- web/ce/layouts/project-wrapper.tsx | 15 +++++++++ web/ce/layouts/workspace-wrapper.tsx | 15 +++++++++ .../settings/invitations-list-item.tsx | 4 +-- .../layouts/auth-layout/project-wrapper.tsx | 31 +++++++++---------- .../layouts/auth-layout/workspace-wrapper.tsx | 17 +++++----- web/ee/layouts/project-wrapper.tsx | 1 + web/ee/layouts/workspace-wrapper.tsx | 1 + 10 files changed, 62 insertions(+), 30 deletions(-) create mode 100644 web/ce/layouts/project-wrapper.tsx create mode 100644 web/ce/layouts/workspace-wrapper.tsx create mode 100644 web/ee/layouts/project-wrapper.tsx create mode 100644 web/ee/layouts/workspace-wrapper.tsx diff --git a/packages/ui/src/modals/constants.ts b/packages/ui/src/modals/constants.ts index fe72ef7aea1..e1eccd94129 100644 --- a/packages/ui/src/modals/constants.ts +++ b/packages/ui/src/modals/constants.ts @@ -13,4 +13,5 @@ export enum EModalWidth { XXXXL = "sm:max-w-4xl", VXL = "sm:max-w-5xl", VIXL = "sm:max-w-6xl", + VIIXL = "sm:max-w-7xl", } diff --git a/web/app/[workspaceSlug]/(projects)/layout.tsx b/web/app/[workspaceSlug]/(projects)/layout.tsx index f8fe0f8f9e0..340ec57d0d0 100644 --- a/web/app/[workspaceSlug]/(projects)/layout.tsx +++ b/web/app/[workspaceSlug]/(projects)/layout.tsx @@ -1,8 +1,9 @@ "use client"; import { CommandPalette } from "@/components/command-palette"; -import { WorkspaceAuthWrapper } from "@/layouts/auth-layout"; import { AuthenticationWrapper } from "@/lib/wrappers"; +// plane web components +import { WorkspaceAuthWrapper } from "@/plane-web/layouts/workspace-wrapper"; import { AppSidebar } from "./sidebar"; export default function WorkspaceLayout({ children }: { children: React.ReactNode }) { diff --git a/web/app/[workspaceSlug]/(projects)/projects/(detail)/layout.tsx b/web/app/[workspaceSlug]/(projects)/projects/(detail)/layout.tsx index fc2ec0075f3..cdd4f708077 100644 --- a/web/app/[workspaceSlug]/(projects)/projects/(detail)/layout.tsx +++ b/web/app/[workspaceSlug]/(projects)/projects/(detail)/layout.tsx @@ -1,8 +1,8 @@ "use client"; import { ReactNode } from "react"; -// layouts -import { ProjectAuthWrapper } from "@/layouts/auth-layout"; +// plane web layouts +import { ProjectAuthWrapper } from "@/plane-web/layouts/project-wrapper"; const ProjectDetailLayout = ({ children }: { children: ReactNode }) => ( {children} diff --git a/web/ce/layouts/project-wrapper.tsx b/web/ce/layouts/project-wrapper.tsx new file mode 100644 index 00000000000..a9223210994 --- /dev/null +++ b/web/ce/layouts/project-wrapper.tsx @@ -0,0 +1,15 @@ +import { FC } from "react"; +import { observer } from "mobx-react"; +// layouts +import { ProjectAuthWrapper as CoreProjectAuthWrapper } from "@/layouts/auth-layout"; + +export type IProjectAuthWrapper = { + children: React.ReactNode; +}; + +export const ProjectAuthWrapper: FC = observer((props) => { + // props + const { children } = props; + + return {children}; +}); diff --git a/web/ce/layouts/workspace-wrapper.tsx b/web/ce/layouts/workspace-wrapper.tsx new file mode 100644 index 00000000000..fcde83e7f32 --- /dev/null +++ b/web/ce/layouts/workspace-wrapper.tsx @@ -0,0 +1,15 @@ +import { FC } from "react"; +import { observer } from "mobx-react"; +// layouts +import { WorkspaceAuthWrapper as CoreWorkspaceAuthWrapper } from "@/layouts/auth-layout"; + +export type IWorkspaceAuthWrapper = { + children: React.ReactNode; +}; + +export const WorkspaceAuthWrapper: FC = observer((props) => { + // props + const { children } = props; + + return {children}; +}); diff --git a/web/core/components/workspace/settings/invitations-list-item.tsx b/web/core/components/workspace/settings/invitations-list-item.tsx index 09ca653f349..bbbbcd2670f 100644 --- a/web/core/components/workspace/settings/invitations-list-item.tsx +++ b/web/core/components/workspace/settings/invitations-list-item.tsx @@ -120,11 +120,11 @@ export const WorkspaceInvitationsListItem: FC = observer((props) => { updateMemberInvitation(workspaceSlug.toString(), invitationDetails.id, { role: value, - }).catch(() => { + }).catch((error) => { setToast({ type: TOAST_TYPE.ERROR, title: "Error!", - message: "An error occurred while updating member role. Please try again.", + message: error?.error || "An error occurred while updating member role. Please try again.", }); }); }} diff --git a/web/core/layouts/auth-layout/project-wrapper.tsx b/web/core/layouts/auth-layout/project-wrapper.tsx index 4cca052573a..dcba2a8fef2 100644 --- a/web/core/layouts/auth-layout/project-wrapper.tsx +++ b/web/core/layouts/auth-layout/project-wrapper.tsx @@ -34,12 +34,14 @@ import { EUserPermissions, EUserPermissionsLevel } from "@/plane-web/constants/u interface IProjectAuthWrapper { children: ReactNode; + isLoading?: boolean; } export const ProjectAuthWrapper: FC = observer((props) => { - const { children } = props; - // store - // const { fetchInboxes } = useInbox(); + const { children, isLoading: isParentLoading = false } = props; + // router + const { workspaceSlug, projectId } = useParams(); + // store hooks const { toggleCreateProjectModal } = useCommandPalette(); const { setTrackElement } = useEventTracker(); const { fetchUserProjectInfo, allowPermissions, projectUserInfo } = useUserPermissions(); @@ -54,14 +56,20 @@ export const ProjectAuthWrapper: FC = observer((props) => { const { fetchProjectStates, fetchProjectStateTransitions } = useProjectState(); const { fetchProjectLabels } = useLabel(); const { getProjectEstimates } = useProjectEstimates(); - // router - const { workspaceSlug, projectId } = useParams(); - + // derived values + const projectExists = projectId ? getProjectById(projectId.toString()) : null; const projectMemberInfo = projectUserInfo?.[workspaceSlug?.toString()]?.[projectId?.toString()]; + const hasPermissionToCurrentProject = allowPermissions( + [EUserPermissions.ADMIN, EUserPermissions.MEMBER, EUserPermissions.GUEST], + EUserPermissionsLevel.PROJECT, + workspaceSlug.toString(), + projectId?.toString() + ); // Initialize module timeline chart useEffect(() => { initGantt(); + // eslint-disable-next-line react-hooks/exhaustive-deps }, []); useSWR( @@ -143,17 +151,8 @@ export const ProjectAuthWrapper: FC = observer((props) => { { revalidateIfStale: false, revalidateOnFocus: false } ); - // derived values - const projectExists = projectId ? getProjectById(projectId.toString()) : null; - const hasPermissionToCurrentProject = allowPermissions( - [EUserPermissions.ADMIN, EUserPermissions.MEMBER, EUserPermissions.GUEST], - EUserPermissionsLevel.PROJECT, - workspaceSlug.toString(), - projectId?.toString() - ); - // check if the project member apis is loading - if (!projectMemberInfo && projectId && hasPermissionToCurrentProject === null) + if (isParentLoading || (!projectMemberInfo && projectId && hasPermissionToCurrentProject === null)) return (
diff --git a/web/core/layouts/auth-layout/workspace-wrapper.tsx b/web/core/layouts/auth-layout/workspace-wrapper.tsx index 2dd658704e3..ab39dd76147 100644 --- a/web/core/layouts/auth-layout/workspace-wrapper.tsx +++ b/web/core/layouts/auth-layout/workspace-wrapper.tsx @@ -8,11 +8,12 @@ import { useParams } from "next/navigation"; import { useTheme } from "next-themes"; import useSWR from "swr"; import useSWRImmutable from "swr/immutable"; - +// ui import { LogOut } from "lucide-react"; -// hooks import { Button, setToast, TOAST_TYPE, Tooltip } from "@plane/ui"; +// components import { LogoSpinner } from "@/components/common"; +// hooks import { useMember, useProject, useUser, useUserPermissions, useWorkspace } from "@/hooks/store"; import { useFavorite } from "@/hooks/store/use-favorite"; import { usePlatformOS } from "@/hooks/use-platform-os"; @@ -25,12 +26,13 @@ import PlaneBlackLogo from "@/public/plane-logos/black-horizontal-with-blue-logo import PlaneWhiteLogo from "@/public/plane-logos/white-horizontal-with-blue-logo.png"; import WorkSpaceNotAvailable from "@/public/workspace/workspace-not-available.png"; -export interface IWorkspaceAuthWrapper { +interface IWorkspaceAuthWrapper { children: ReactNode; + isLoading?: boolean; } export const WorkspaceAuthWrapper: FC = observer((props) => { - const { children } = props; + const { children, isLoading: isParentLoading = false } = props; // router params const { workspaceSlug } = useParams(); // next themes @@ -51,11 +53,11 @@ export const WorkspaceAuthWrapper: FC = observer((props) [EUserPermissions.ADMIN, EUserPermissions.MEMBER], EUserPermissionsLevel.WORKSPACE ); - const planeLogo = resolvedTheme === "dark" ? PlaneWhiteLogo : PlaneBlackLogo; const allWorkspaces = workspaces ? Object.values(workspaces) : undefined; const currentWorkspace = (allWorkspaces && allWorkspaces.find((workspace) => workspace?.slug === workspaceSlug)) || undefined; + const currentWorkspaceInfo = workspaceSlug && workspaceInfoBySlug(workspaceSlug.toString()); // fetching user workspace information useSWR( @@ -116,11 +118,8 @@ export const WorkspaceAuthWrapper: FC = observer((props) ); }; - // derived values - const currentWorkspaceInfo = workspaceSlug && workspaceInfoBySlug(workspaceSlug.toString()); - // if list of workspaces are not there then we have to render the spinner - if (allWorkspaces === undefined || loader || isDBInitializing) { + if (isParentLoading || allWorkspaces === undefined || loader || isDBInitializing) { return (
diff --git a/web/ee/layouts/project-wrapper.tsx b/web/ee/layouts/project-wrapper.tsx new file mode 100644 index 00000000000..911665c9786 --- /dev/null +++ b/web/ee/layouts/project-wrapper.tsx @@ -0,0 +1 @@ +export * from "ce/layouts/project-wrapper"; diff --git a/web/ee/layouts/workspace-wrapper.tsx b/web/ee/layouts/workspace-wrapper.tsx new file mode 100644 index 00000000000..186266fc1ad --- /dev/null +++ b/web/ee/layouts/workspace-wrapper.tsx @@ -0,0 +1 @@ +export * from "ce/layouts/workspace-wrapper";