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

114 lines
4.4 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 { 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<TNameDescriptionLoader>("saved");
const [isDetailResolved, setIsDetailResolved] = useState(false);
const { data: currentUser } = useUser();
const { currentTab, 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?currentTab=${currentTab}`);
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [contourRequest, currentTab, 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 (
<ExternalContoursPeekShell
workspaceSlug={workspaceSlug}
projectId={projectId}
contourRequest={contourRequest}
hasDirectTargetAccess={hasDirectTargetAccess}
isSubmitting={isSubmitting}
embedIssue={embedIssue}
embedRemoveCurrentNotification={embedRemoveCurrentNotification}
onClose={() => router.replace(`/${workspaceSlug}/projects/${projectId}/external-contours?currentTab=${currentTab}`)}
>
<ExternalContoursIssueMainContent
workspaceSlug={workspaceSlug}
sourceProjectId={projectId}
contourRequest={contourRequest}
hasDirectTargetAccess={hasDirectTargetAccess}
isEditable={!!isEditable && !readOnly}
isSourceEditable={isSourceEditable}
isSubmitting={isSubmitting}
setIsSubmitting={setIsSubmitting}
/>
</ExternalContoursPeekShell>
);
});