[WEB-763] fix: workspace remains listed after leaving the workspace in the user profile (#3993)
* chore: build error * fix: workspace not getting removed when user leaves the workspace
This commit is contained in:
parent
0f79c6d7d8
commit
7d3a96b3d0
8 changed files with 128 additions and 34 deletions
|
|
@ -1,11 +1,11 @@
|
|||
import { FC, ReactNode } from "react";
|
||||
// layouts
|
||||
import { observer } from "mobx-react-lite";
|
||||
import { CommandPalette } from "@/components/command-palette";
|
||||
import { UserAuthWrapper, WorkspaceAuthWrapper, ProjectAuthWrapper } from "@/layouts/auth-layout";
|
||||
// components
|
||||
import { AppSidebar } from "./sidebar";
|
||||
import { CommandPalette } from "@/components/command-palette";
|
||||
import { SidebarHamburgerToggle } from "@/components/core/sidebar/sidebar-menu-hamburger-toggle";
|
||||
// layouts
|
||||
import { UserAuthWrapper, WorkspaceAuthWrapper, ProjectAuthWrapper } from "@/layouts/auth-layout";
|
||||
import { AppSidebar } from "./sidebar";
|
||||
|
||||
export interface IAppLayout {
|
||||
children: ReactNode;
|
||||
|
|
@ -19,8 +19,8 @@ export const AppLayout: FC<IAppLayout> = observer((props) => {
|
|||
|
||||
return (
|
||||
<>
|
||||
<CommandPalette />
|
||||
<UserAuthWrapper>
|
||||
<CommandPalette />
|
||||
<WorkspaceAuthWrapper>
|
||||
<div className="relative flex h-screen w-full overflow-hidden">
|
||||
<AppSidebar />
|
||||
|
|
|
|||
|
|
@ -34,15 +34,15 @@ export const UserAuthWrapper: FC<IUserAuthWrapper> = observer((props) => {
|
|||
shouldRetryOnError: false,
|
||||
});
|
||||
// fetching user settings
|
||||
useSWR("CURRENT_USER_SETTINGS", () => fetchCurrentUserSettings(), {
|
||||
const { isLoading: userSettingsLoader } = useSWR("CURRENT_USER_SETTINGS", () => fetchCurrentUserSettings(), {
|
||||
shouldRetryOnError: false,
|
||||
});
|
||||
// fetching all workspaces
|
||||
useSWR("USER_WORKSPACES_LIST", () => fetchWorkspaces(), {
|
||||
const { isLoading: workspaceLoader } = useSWR("USER_WORKSPACES_LIST", () => fetchWorkspaces(), {
|
||||
shouldRetryOnError: false,
|
||||
});
|
||||
|
||||
if (!currentUser && !currentUserError) {
|
||||
if ((!currentUser && !currentUserError) || userSettingsLoader || workspaceLoader) {
|
||||
return (
|
||||
<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">
|
||||
|
|
|
|||
|
|
@ -1,12 +1,19 @@
|
|||
import { FC, ReactNode } from "react";
|
||||
import { observer } from "mobx-react-lite";
|
||||
import Image from "next/image";
|
||||
import Link from "next/link";
|
||||
import { useRouter } from "next/router";
|
||||
import useSWR from "swr";
|
||||
import { useTheme } from "next-themes";
|
||||
import useSWR, { mutate } from "swr";
|
||||
import { LogOut } from "lucide-react";
|
||||
// hooks
|
||||
import { Button, Spinner } from "@plane/ui";
|
||||
import { useLabel, useMember, useProject, useUser } from "@/hooks/store";
|
||||
// icons
|
||||
import { Button, Spinner, TOAST_TYPE, setToast, Tooltip } from "@plane/ui";
|
||||
import { useMember, useProject, useUser, useWorkspace } from "@/hooks/store";
|
||||
import { usePlatformOS } from "@/hooks/use-platform-os";
|
||||
// images
|
||||
import PlaneBlackLogo from "public/plane-logos/black-horizontal-with-blue-logo.svg";
|
||||
import PlaneWhiteLogo from "public/plane-logos/white-horizontal-with-blue-logo.svg";
|
||||
import WorkSpaceNotAvailable from "public/workspace/workspace-not-available.png";
|
||||
|
||||
export interface IWorkspaceAuthWrapper {
|
||||
children: ReactNode;
|
||||
|
|
@ -14,42 +21,70 @@ export interface IWorkspaceAuthWrapper {
|
|||
|
||||
export const WorkspaceAuthWrapper: FC<IWorkspaceAuthWrapper> = observer((props) => {
|
||||
const { children } = props;
|
||||
// router
|
||||
const router = useRouter();
|
||||
const { workspaceSlug } = router.query;
|
||||
// next themes
|
||||
const { resolvedTheme, setTheme } = useTheme();
|
||||
// store hooks
|
||||
const { membership } = useUser();
|
||||
const { membership, signOut, currentUser } = useUser();
|
||||
const { fetchProjects } = useProject();
|
||||
const {
|
||||
workspace: { fetchWorkspaceMembers },
|
||||
} = useMember();
|
||||
// router
|
||||
const router = useRouter();
|
||||
const { workspaceSlug } = router.query;
|
||||
const { workspaces } = useWorkspace();
|
||||
const { isMobile } = usePlatformOS();
|
||||
|
||||
const planeLogo = resolvedTheme === "dark" ? PlaneWhiteLogo : PlaneBlackLogo;
|
||||
const allWorkspaces = workspaces ? Object.values(workspaces) : undefined;
|
||||
const currentWorkspace =
|
||||
(allWorkspaces && allWorkspaces.find((workspace) => workspace?.slug === workspaceSlug)) || undefined;
|
||||
|
||||
// fetching user workspace information
|
||||
useSWR(
|
||||
workspaceSlug ? `WORKSPACE_MEMBERS_ME_${workspaceSlug}` : null,
|
||||
workspaceSlug ? () => membership.fetchUserWorkspaceInfo(workspaceSlug.toString()) : null,
|
||||
workspaceSlug && currentWorkspace ? `WORKSPACE_MEMBERS_ME_${workspaceSlug}` : null,
|
||||
workspaceSlug && currentWorkspace ? () => membership.fetchUserWorkspaceInfo(workspaceSlug.toString()) : null,
|
||||
{ revalidateIfStale: false, revalidateOnFocus: false }
|
||||
);
|
||||
// fetching workspace projects
|
||||
useSWR(
|
||||
workspaceSlug ? `WORKSPACE_PROJECTS_${workspaceSlug}` : null,
|
||||
workspaceSlug ? () => fetchProjects(workspaceSlug.toString()) : null,
|
||||
workspaceSlug && currentWorkspace ? `WORKSPACE_PROJECTS_${workspaceSlug}` : null,
|
||||
workspaceSlug && currentWorkspace ? () => fetchProjects(workspaceSlug.toString()) : null,
|
||||
{ revalidateIfStale: false, revalidateOnFocus: false }
|
||||
);
|
||||
// fetch workspace members
|
||||
useSWR(
|
||||
workspaceSlug ? `WORKSPACE_MEMBERS_${workspaceSlug}` : null,
|
||||
workspaceSlug ? () => fetchWorkspaceMembers(workspaceSlug.toString()) : null,
|
||||
workspaceSlug && currentWorkspace ? `WORKSPACE_MEMBERS_${workspaceSlug}` : null,
|
||||
workspaceSlug && currentWorkspace ? () => fetchWorkspaceMembers(workspaceSlug.toString()) : null,
|
||||
{ revalidateIfStale: false, revalidateOnFocus: false }
|
||||
);
|
||||
// fetch workspace user projects role
|
||||
useSWR(
|
||||
workspaceSlug ? `WORKSPACE_PROJECTS_ROLE_${workspaceSlug}` : null,
|
||||
workspaceSlug ? () => membership.fetchUserWorkspaceProjectsRole(workspaceSlug.toString()) : null,
|
||||
workspaceSlug && currentWorkspace ? `WORKSPACE_PROJECTS_ROLE_${workspaceSlug}` : null,
|
||||
workspaceSlug && currentWorkspace
|
||||
? () => membership.fetchUserWorkspaceProjectsRole(workspaceSlug.toString())
|
||||
: null,
|
||||
{ revalidateIfStale: false, revalidateOnFocus: false }
|
||||
);
|
||||
|
||||
// while data is being loaded
|
||||
if (!membership.currentWorkspaceMemberInfo && membership.hasPermissionToCurrentWorkspace === undefined) {
|
||||
const handleSignOut = async () => {
|
||||
await signOut()
|
||||
.then(() => {
|
||||
mutate("CURRENT_USER_DETAILS", null);
|
||||
setTheme("system");
|
||||
router.push("/");
|
||||
})
|
||||
.catch(() =>
|
||||
setToast({
|
||||
type: TOAST_TYPE.ERROR,
|
||||
title: "Error!",
|
||||
message: "Failed to sign out. Please try again.",
|
||||
})
|
||||
);
|
||||
};
|
||||
|
||||
// if list of workspaces are not there then we have to render the spinner
|
||||
if (allWorkspaces === undefined) {
|
||||
return (
|
||||
<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">
|
||||
|
|
@ -58,6 +93,58 @@ export const WorkspaceAuthWrapper: FC<IWorkspaceAuthWrapper> = observer((props)
|
|||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
// if workspaces are there and we are trying to access the workspace that we are not part of then show the existing workspaces
|
||||
if (
|
||||
currentWorkspace === undefined &&
|
||||
!membership.currentWorkspaceMemberInfo &&
|
||||
membership.hasPermissionToCurrentWorkspace === undefined
|
||||
) {
|
||||
return (
|
||||
<div className="relative w-full h-full flex flex-col justify-center items-center bg-custom-background-90">
|
||||
<div className="relative container px-5 md:px-0 w-full h-full mx-auto py-14 overflow-hidden overflow-y-auto flex flex-col">
|
||||
<div className="flex-shrink-0 relative flex justify-between items-center gap-4">
|
||||
<div className="flex-shrink-0 py-4 z-10 bg-custom-background-90">
|
||||
<Image src={planeLogo} className="h-[26px] w-full" alt="Plane logo" />
|
||||
</div>
|
||||
<div className="relative flex items-center gap-2">
|
||||
<div className="text-sm font-medium">{currentUser?.email}</div>
|
||||
<div
|
||||
className="relative flex-shrink-0 w-6 h-6 rounded overflow-hidden flex justify-center items-center cursor-pointer hover:bg-custom-background-80"
|
||||
onClick={handleSignOut}
|
||||
>
|
||||
<Tooltip tooltipContent={"Sign out"} position="top" className="ml-2" isMobile={isMobile}>
|
||||
<LogOut size={14} />
|
||||
</Tooltip>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="space-y-3 w-full h-full flex-grow relative flex flex-col justify-center items-center">
|
||||
<div className="flex-shrink-0 relative">
|
||||
<Image src={WorkSpaceNotAvailable} className="h-[220px] object-contain object-center" alt="Plane logo" />
|
||||
</div>
|
||||
<h3 className="text-lg font-semibold text-center">Workspace not found</h3>
|
||||
<p className="text-sm text-custom-text-200 text-center">
|
||||
No workspace found with the URL. It may not exist or you lack authorization to view it.
|
||||
</p>
|
||||
<div className="flex justify-center items-center gap-2 pt-4">
|
||||
{allWorkspaces && allWorkspaces.length > 1 && (
|
||||
<Link href="/">
|
||||
<Button>Go Home</Button>
|
||||
</Link>
|
||||
)}
|
||||
<Link href="/profile">
|
||||
<Button variant="neutral-primary">Visit Profile</Button>
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="absolute top-0 bottom-0 left-4 w-0 md:w-0.5 bg-custom-background-80" />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
// while user does not have access to view that workspace
|
||||
if (
|
||||
membership.hasPermissionToCurrentWorkspace !== undefined &&
|
||||
|
|
|
|||
|
|
@ -43,6 +43,7 @@ export const ProfileLayoutSidebar = observer(() => {
|
|||
const { currentUser, currentUserSettings, signOut } = useUser();
|
||||
const { workspaces } = useWorkspace();
|
||||
const { isMobile } = usePlatformOS();
|
||||
|
||||
const workspacesList = Object.values(workspaces ?? {});
|
||||
|
||||
// redirect url for normal mode
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue