NODEDC_TASKMANAGER/plane-src/apps/web/ce/components/projects/external-contours/content-root.tsx

101 lines
4.0 KiB
TypeScript

/**
* Copyright (c) 2023-present Plane Software, Inc. and contributors
* SPDX-License-Identifier: AGPL-3.0-only
* See the LICENSE file for details.
*/
import { useEffect, useState } from "react";
import { observer } from "mobx-react";
import useSWR from "swr";
import { EUserPermissions, EUserPermissionsLevel } from "@plane/constants";
import type { TNameDescriptionLoader } from "@plane/types";
import { ContentWrapper } from "@plane/ui";
import { useProjectExternalContours } from "@/hooks/store/use-project-external-contours";
import { useUser, useUserPermissions } from "@/hooks/store/user";
import { useAppRouter } from "@/hooks/use-app-router";
import { ExternalContoursIssueActionsHeader } from "./issue-header";
import { ExternalContoursIssueMainContent } from "./issue-root";
type Props = {
workspaceSlug: string;
projectId: string;
inboxIssueId: string;
isMobileSidebar: boolean;
setIsMobileSidebar: (value: boolean) => void;
};
export const ExternalContoursContentRoot = observer(function ExternalContoursContentRoot(props: Props) {
const { workspaceSlug, projectId, inboxIssueId, isMobileSidebar, setIsMobileSidebar } = props;
const router = useAppRouter();
const [isSubmitting, setIsSubmitting] = useState<TNameDescriptionLoader>("saved");
const { data: currentUser } = useUser();
const { currentTab, fetchRequestById, getRequestById, getIsRequestAvailable } = useProjectExternalContours();
const contourRequest = getRequestById(inboxIssueId);
const issue = contourRequest?.issue;
const targetProjectId = issue?.project_id || projectId;
const { allowPermissions, getProjectRoleByWorkspaceSlugAndProjectId } = useUserPermissions();
const hasDirectTargetAccess = !!(
targetProjectId && getProjectRoleByWorkspaceSlugAndProjectId(workspaceSlug, targetProjectId) !== undefined
);
const isIssueAvailable = getIsRequestAvailable(inboxIssueId?.toString() || "");
useEffect(() => {
if (!isIssueAvailable && inboxIssueId) {
router.replace(`/${workspaceSlug}/projects/${projectId}/external-contours?currentTab=${currentTab}`);
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [isIssueAvailable]);
useSWR(
workspaceSlug && projectId && inboxIssueId
? `PROJECT_EXTERNAL_CONTOUR_DETAIL_${workspaceSlug}_${projectId}_${inboxIssueId}`
: null,
workspaceSlug && projectId && inboxIssueId ? () => fetchRequestById(workspaceSlug, projectId, inboxIssueId) : null,
{
revalidateOnFocus: !hasDirectTargetAccess,
revalidateIfStale: !hasDirectTargetAccess,
refreshInterval: hasDirectTargetAccess ? 0 : 15000,
}
);
const isEditable =
hasDirectTargetAccess &&
(allowPermissions([EUserPermissions.ADMIN], EUserPermissionsLevel.PROJECT, workspaceSlug, targetProjectId) ||
issue?.created_by === currentUser?.id);
const isGuest =
!!targetProjectId && getProjectRoleByWorkspaceSlugAndProjectId(workspaceSlug, targetProjectId) === EUserPermissions.GUEST;
const isOwner = issue?.created_by === currentUser?.id;
const readOnly = !isOwner && isGuest;
if (!contourRequest || !issue) return <></>;
return (
<div className="relative flex h-full w-full flex-col overflow-hidden">
<div className="z-[11] min-h-[52px] flex-shrink-0">
<ExternalContoursIssueActionsHeader
setIsMobileSidebar={setIsMobileSidebar}
isMobileSidebar={isMobileSidebar}
workspaceSlug={workspaceSlug}
sourceProjectId={projectId}
contourRequest={contourRequest}
isSubmitting={isSubmitting}
hasDirectTargetAccess={hasDirectTargetAccess}
/>
</div>
<ContentWrapper className="divide-y-2 divide-subtle-1">
<ExternalContoursIssueMainContent
workspaceSlug={workspaceSlug}
sourceProjectId={projectId}
contourRequest={contourRequest}
hasDirectTargetAccess={hasDirectTargetAccess}
isEditable={!!isEditable && !readOnly}
isSubmitting={isSubmitting}
setIsSubmitting={setIsSubmitting}
/>
</ContentWrapper>
</div>
);
});