/** * 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 { useProjectExternalContours } from "@/hooks/store/use-project-external-contours"; import { useUser, useUserPermissions } from "@/hooks/store/user"; import { useAppRouter } from "@/hooks/use-app-router"; import { ExternalContoursPeekShell } from "./peek-shell"; import { ExternalContoursIssueMainContent } from "./issue-root"; type Props = { workspaceSlug: string; projectId: string; inboxIssueId: string; embedIssue?: boolean; embedRemoveCurrentNotification?: () => void; }; export const ExternalContoursContentRoot = observer(function ExternalContoursContentRoot(props: Props) { const { workspaceSlug, projectId, inboxIssueId, embedIssue = false, embedRemoveCurrentNotification, } = props; const router = useAppRouter(); const [isSubmitting, setIsSubmitting] = useState("saved"); const [isDetailResolved, setIsDetailResolved] = useState(false); const { data: currentUser } = useUser(); const { fetchRequestById, getRequestById } = 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 ); useEffect(() => { if (isDetailResolved && !contourRequest && inboxIssueId) { router.replace(`/${workspaceSlug}/projects/${projectId}/external-contours`); } // eslint-disable-next-line react-hooks/exhaustive-deps }, [contourRequest, inboxIssueId, isDetailResolved, projectId, router, workspaceSlug]); useSWR( workspaceSlug && projectId && inboxIssueId ? `PROJECT_EXTERNAL_CONTOUR_DETAIL_${workspaceSlug}_${projectId}_${inboxIssueId}` : null, workspaceSlug && projectId && inboxIssueId ? async () => { const request = await fetchRequestById(workspaceSlug, projectId, inboxIssueId); setIsDetailResolved(true); return request; } : 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 sourceRequesterId = contourRequest?.requested_by_id || issue?.created_by || contourRequest?.created_by; const isSourceEditable = !hasDirectTargetAccess && contourRequest?.status === "open" && !!currentUser?.id && String(sourceRequesterId) === String(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 ( router.replace(`/${workspaceSlug}/projects/${projectId}/external-contours`)} > ); });