refactor: enhance workspace and project wrapper modularity (#6207)

This commit is contained in:
Prateek Shourya 2024-12-16 19:01:37 +05:30 committed by GitHub
parent 438cc33046
commit 4507802aba
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
10 changed files with 62 additions and 30 deletions

View file

@ -13,4 +13,5 @@ export enum EModalWidth {
XXXXL = "sm:max-w-4xl", XXXXL = "sm:max-w-4xl",
VXL = "sm:max-w-5xl", VXL = "sm:max-w-5xl",
VIXL = "sm:max-w-6xl", VIXL = "sm:max-w-6xl",
VIIXL = "sm:max-w-7xl",
} }

View file

@ -1,8 +1,9 @@
"use client"; "use client";
import { CommandPalette } from "@/components/command-palette"; import { CommandPalette } from "@/components/command-palette";
import { WorkspaceAuthWrapper } from "@/layouts/auth-layout";
import { AuthenticationWrapper } from "@/lib/wrappers"; import { AuthenticationWrapper } from "@/lib/wrappers";
// plane web components
import { WorkspaceAuthWrapper } from "@/plane-web/layouts/workspace-wrapper";
import { AppSidebar } from "./sidebar"; import { AppSidebar } from "./sidebar";
export default function WorkspaceLayout({ children }: { children: React.ReactNode }) { export default function WorkspaceLayout({ children }: { children: React.ReactNode }) {

View file

@ -1,8 +1,8 @@
"use client"; "use client";
import { ReactNode } from "react"; import { ReactNode } from "react";
// layouts // plane web layouts
import { ProjectAuthWrapper } from "@/layouts/auth-layout"; import { ProjectAuthWrapper } from "@/plane-web/layouts/project-wrapper";
const ProjectDetailLayout = ({ children }: { children: ReactNode }) => ( const ProjectDetailLayout = ({ children }: { children: ReactNode }) => (
<ProjectAuthWrapper>{children}</ProjectAuthWrapper> <ProjectAuthWrapper>{children}</ProjectAuthWrapper>

View file

@ -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<IProjectAuthWrapper> = observer((props) => {
// props
const { children } = props;
return <CoreProjectAuthWrapper>{children}</CoreProjectAuthWrapper>;
});

View file

@ -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<IWorkspaceAuthWrapper> = observer((props) => {
// props
const { children } = props;
return <CoreWorkspaceAuthWrapper>{children}</CoreWorkspaceAuthWrapper>;
});

View file

@ -120,11 +120,11 @@ export const WorkspaceInvitationsListItem: FC<Props> = observer((props) => {
updateMemberInvitation(workspaceSlug.toString(), invitationDetails.id, { updateMemberInvitation(workspaceSlug.toString(), invitationDetails.id, {
role: value, role: value,
}).catch(() => { }).catch((error) => {
setToast({ setToast({
type: TOAST_TYPE.ERROR, type: TOAST_TYPE.ERROR,
title: "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.",
}); });
}); });
}} }}

View file

@ -34,12 +34,14 @@ import { EUserPermissions, EUserPermissionsLevel } from "@/plane-web/constants/u
interface IProjectAuthWrapper { interface IProjectAuthWrapper {
children: ReactNode; children: ReactNode;
isLoading?: boolean;
} }
export const ProjectAuthWrapper: FC<IProjectAuthWrapper> = observer((props) => { export const ProjectAuthWrapper: FC<IProjectAuthWrapper> = observer((props) => {
const { children } = props; const { children, isLoading: isParentLoading = false } = props;
// store // router
// const { fetchInboxes } = useInbox(); const { workspaceSlug, projectId } = useParams();
// store hooks
const { toggleCreateProjectModal } = useCommandPalette(); const { toggleCreateProjectModal } = useCommandPalette();
const { setTrackElement } = useEventTracker(); const { setTrackElement } = useEventTracker();
const { fetchUserProjectInfo, allowPermissions, projectUserInfo } = useUserPermissions(); const { fetchUserProjectInfo, allowPermissions, projectUserInfo } = useUserPermissions();
@ -54,14 +56,20 @@ export const ProjectAuthWrapper: FC<IProjectAuthWrapper> = observer((props) => {
const { fetchProjectStates, fetchProjectStateTransitions } = useProjectState(); const { fetchProjectStates, fetchProjectStateTransitions } = useProjectState();
const { fetchProjectLabels } = useLabel(); const { fetchProjectLabels } = useLabel();
const { getProjectEstimates } = useProjectEstimates(); const { getProjectEstimates } = useProjectEstimates();
// router // derived values
const { workspaceSlug, projectId } = useParams(); const projectExists = projectId ? getProjectById(projectId.toString()) : null;
const projectMemberInfo = projectUserInfo?.[workspaceSlug?.toString()]?.[projectId?.toString()]; 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 // Initialize module timeline chart
useEffect(() => { useEffect(() => {
initGantt(); initGantt();
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []); }, []);
useSWR( useSWR(
@ -143,17 +151,8 @@ export const ProjectAuthWrapper: FC<IProjectAuthWrapper> = observer((props) => {
{ revalidateIfStale: false, revalidateOnFocus: false } { 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 // check if the project member apis is loading
if (!projectMemberInfo && projectId && hasPermissionToCurrentProject === null) if (isParentLoading || (!projectMemberInfo && projectId && hasPermissionToCurrentProject === null))
return ( return (
<div className="grid h-screen place-items-center bg-custom-background-100 p-4"> <div className="grid h-screen place-items-center bg-custom-background-100 p-4">
<div className="flex flex-col items-center gap-3 text-center"> <div className="flex flex-col items-center gap-3 text-center">

View file

@ -8,11 +8,12 @@ import { useParams } from "next/navigation";
import { useTheme } from "next-themes"; import { useTheme } from "next-themes";
import useSWR from "swr"; import useSWR from "swr";
import useSWRImmutable from "swr/immutable"; import useSWRImmutable from "swr/immutable";
// ui
import { LogOut } from "lucide-react"; import { LogOut } from "lucide-react";
// hooks
import { Button, setToast, TOAST_TYPE, Tooltip } from "@plane/ui"; import { Button, setToast, TOAST_TYPE, Tooltip } from "@plane/ui";
// components
import { LogoSpinner } from "@/components/common"; import { LogoSpinner } from "@/components/common";
// hooks
import { useMember, useProject, useUser, useUserPermissions, useWorkspace } from "@/hooks/store"; import { useMember, useProject, useUser, useUserPermissions, useWorkspace } from "@/hooks/store";
import { useFavorite } from "@/hooks/store/use-favorite"; import { useFavorite } from "@/hooks/store/use-favorite";
import { usePlatformOS } from "@/hooks/use-platform-os"; 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 PlaneWhiteLogo from "@/public/plane-logos/white-horizontal-with-blue-logo.png";
import WorkSpaceNotAvailable from "@/public/workspace/workspace-not-available.png"; import WorkSpaceNotAvailable from "@/public/workspace/workspace-not-available.png";
export interface IWorkspaceAuthWrapper { interface IWorkspaceAuthWrapper {
children: ReactNode; children: ReactNode;
isLoading?: boolean;
} }
export const WorkspaceAuthWrapper: FC<IWorkspaceAuthWrapper> = observer((props) => { export const WorkspaceAuthWrapper: FC<IWorkspaceAuthWrapper> = observer((props) => {
const { children } = props; const { children, isLoading: isParentLoading = false } = props;
// router params // router params
const { workspaceSlug } = useParams(); const { workspaceSlug } = useParams();
// next themes // next themes
@ -51,11 +53,11 @@ export const WorkspaceAuthWrapper: FC<IWorkspaceAuthWrapper> = observer((props)
[EUserPermissions.ADMIN, EUserPermissions.MEMBER], [EUserPermissions.ADMIN, EUserPermissions.MEMBER],
EUserPermissionsLevel.WORKSPACE EUserPermissionsLevel.WORKSPACE
); );
const planeLogo = resolvedTheme === "dark" ? PlaneWhiteLogo : PlaneBlackLogo; const planeLogo = resolvedTheme === "dark" ? PlaneWhiteLogo : PlaneBlackLogo;
const allWorkspaces = workspaces ? Object.values(workspaces) : undefined; const allWorkspaces = workspaces ? Object.values(workspaces) : undefined;
const currentWorkspace = const currentWorkspace =
(allWorkspaces && allWorkspaces.find((workspace) => workspace?.slug === workspaceSlug)) || undefined; (allWorkspaces && allWorkspaces.find((workspace) => workspace?.slug === workspaceSlug)) || undefined;
const currentWorkspaceInfo = workspaceSlug && workspaceInfoBySlug(workspaceSlug.toString());
// fetching user workspace information // fetching user workspace information
useSWR( useSWR(
@ -116,11 +118,8 @@ export const WorkspaceAuthWrapper: FC<IWorkspaceAuthWrapper> = 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 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 ( return (
<div className="grid h-screen place-items-center bg-custom-background-100 p-4"> <div className="grid h-screen place-items-center bg-custom-background-100 p-4">
<div className="flex flex-col items-center gap-3 text-center"> <div className="flex flex-col items-center gap-3 text-center">

View file

@ -0,0 +1 @@
export * from "ce/layouts/project-wrapper";

View file

@ -0,0 +1 @@
export * from "ce/layouts/workspace-wrapper";