refactor: enhance workspace and project wrapper modularity (#6207)
This commit is contained in:
parent
438cc33046
commit
4507802aba
10 changed files with 62 additions and 30 deletions
|
|
@ -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",
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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 }) {
|
||||||
|
|
|
||||||
|
|
@ -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>
|
||||||
|
|
|
||||||
15
web/ce/layouts/project-wrapper.tsx
Normal file
15
web/ce/layouts/project-wrapper.tsx
Normal 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>;
|
||||||
|
});
|
||||||
15
web/ce/layouts/workspace-wrapper.tsx
Normal file
15
web/ce/layouts/workspace-wrapper.tsx
Normal 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>;
|
||||||
|
});
|
||||||
|
|
@ -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.",
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}}
|
}}
|
||||||
|
|
|
||||||
|
|
@ -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">
|
||||||
|
|
|
||||||
|
|
@ -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">
|
||||||
|
|
|
||||||
1
web/ee/layouts/project-wrapper.tsx
Normal file
1
web/ee/layouts/project-wrapper.tsx
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
export * from "ce/layouts/project-wrapper";
|
||||||
1
web/ee/layouts/workspace-wrapper.tsx
Normal file
1
web/ee/layouts/workspace-wrapper.tsx
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
export * from "ce/layouts/workspace-wrapper";
|
||||||
Loading…
Add table
Add a link
Reference in a new issue