import React, { useCallback, useState } from "react"; // next import { useRouter } from "next/router"; import { KeyedMutator, mutate } from "swr"; // components import { ListInlineCreateIssueForm, SpreadsheetAssigneeColumn, SpreadsheetCreatedOnColumn, SpreadsheetDueDateColumn, SpreadsheetEstimateColumn, SpreadsheetIssuesColumn, SpreadsheetLabelColumn, SpreadsheetPriorityColumn, SpreadsheetStartDateColumn, SpreadsheetStateColumn, SpreadsheetUpdatedOnColumn, } from "components/core"; import { CustomMenu, Spinner } from "components/ui"; import { IssuePeekOverview } from "components/issues"; // hooks import useIssuesProperties from "hooks/use-issue-properties"; // types import { ICurrentUserResponse, IIssue, ISubIssueResponse, UserAuth } from "types"; import useWorkspaceIssuesFilters from "hooks/use-worskpace-issue-filter"; import { CYCLE_DETAILS, CYCLE_ISSUES_WITH_PARAMS, MODULE_DETAILS, MODULE_ISSUES_WITH_PARAMS, PROJECT_ISSUES_LIST_WITH_PARAMS, SUB_ISSUES, VIEW_ISSUES, WORKSPACE_VIEW_ISSUES, } from "constants/fetch-keys"; import useSpreadsheetIssuesView from "hooks/use-spreadsheet-issues-view"; import projectIssuesServices from "services/issues.service"; // icon import { PlusIcon } from "lucide-react"; type Props = { spreadsheetIssues: IIssue[]; mutateIssues: KeyedMutator< | IIssue[] | { [key: string]: IIssue[]; } >; handleIssueAction: (issue: IIssue, action: "copy" | "delete" | "edit") => void; openIssuesListModal?: (() => void) | null; disableUserActions: boolean; user: ICurrentUserResponse | undefined; userAuth: UserAuth; }; export const SpreadsheetView: React.FC = ({ spreadsheetIssues, mutateIssues, handleIssueAction, openIssuesListModal, disableUserActions, user, userAuth, }) => { const [expandedIssues, setExpandedIssues] = useState([]); const [currentProjectId, setCurrentProjectId] = useState(null); const [isInlineCreateIssueFormOpen, setIsInlineCreateIssueFormOpen] = useState(false); const router = useRouter(); const { workspaceSlug, projectId, cycleId, moduleId, viewId, workspaceViewId } = router.query; const type = cycleId ? "cycle" : moduleId ? "module" : "issue"; const [properties] = useIssuesProperties(workspaceSlug as string, projectId as string); const workspaceIssuesPath = [ { params: { sub_issue: false, }, path: "workspace-views/all-issues", }, { params: { assignees: user?.id ?? undefined, sub_issue: false, }, path: "workspace-views/assigned", }, { params: { created_by: user?.id ?? undefined, sub_issue: false, }, path: "workspace-views/created", }, { params: { subscriber: user?.id ?? undefined, sub_issue: false, }, path: "workspace-views/subscribed", }, ]; const currentWorkspaceIssuePath = workspaceIssuesPath.find((path) => router.pathname.includes(path.path) ); const { params: workspaceViewParams } = useWorkspaceIssuesFilters( workspaceSlug?.toString(), workspaceViewId?.toString() ); const { params } = useSpreadsheetIssuesView(); const partialUpdateIssue = useCallback( (formData: Partial, issue: IIssue) => { if (!workspaceSlug || !issue) return; const fetchKey = cycleId ? CYCLE_ISSUES_WITH_PARAMS(cycleId.toString(), params) : moduleId ? MODULE_ISSUES_WITH_PARAMS(moduleId.toString(), params) : viewId ? VIEW_ISSUES(viewId.toString(), params) : workspaceViewId ? WORKSPACE_VIEW_ISSUES(workspaceSlug.toString(), workspaceViewParams) : currentWorkspaceIssuePath ? WORKSPACE_VIEW_ISSUES(workspaceSlug.toString(), currentWorkspaceIssuePath?.params) : PROJECT_ISSUES_LIST_WITH_PARAMS(issue.project_detail.id, params); if (issue.parent) mutate( SUB_ISSUES(issue.parent.toString()), (prevData) => { if (!prevData) return prevData; return { ...prevData, sub_issues: (prevData.sub_issues ?? []).map((i) => { if (i.id === issue.id) { return { ...i, ...formData, }; } return i; }), }; }, false ); else mutate( fetchKey, (prevData) => (prevData ?? []).map((p) => { if (p.id === issue.id) { return { ...p, ...formData, }; } return p; }), false ); projectIssuesServices .patchIssue( workspaceSlug as string, issue.project_detail.id, issue.id as string, formData, user ) .then(() => { if (issue.parent) { mutate(SUB_ISSUES(issue.parent as string)); } else { mutate(fetchKey); if (cycleId) mutate(CYCLE_DETAILS(cycleId as string)); if (moduleId) mutate(MODULE_DETAILS(moduleId as string)); } }) .catch((error) => { console.log(error); }); }, [ workspaceSlug, cycleId, moduleId, viewId, workspaceViewId, currentWorkspaceIssuePath, workspaceViewParams, params, user, ] ); const isNotAllowed = userAuth.isGuest || userAuth.isViewer; const renderColumn = (header: string, Component: React.ComponentType) => (
{header}
{spreadsheetIssues.map((issue: IIssue, index) => ( ))}
); return ( <> mutateIssues()} projectId={currentProjectId ?? ""} workspaceSlug={workspaceSlug?.toString() ?? ""} readOnly={disableUserActions} />
{spreadsheetIssues ? ( <>
ID Issue
{spreadsheetIssues.map((issue: IIssue, index) => ( ))}
{renderColumn("State", SpreadsheetStateColumn)} {renderColumn("Priority", SpreadsheetPriorityColumn)} {renderColumn("Assignees", SpreadsheetAssigneeColumn)} {renderColumn("Label", SpreadsheetLabelColumn)} {renderColumn("Start Date", SpreadsheetStartDateColumn)} {renderColumn("Due Date", SpreadsheetDueDateColumn)} {renderColumn("Estimate", SpreadsheetEstimateColumn)} {renderColumn("Created On", SpreadsheetCreatedOnColumn)} {renderColumn("Updated On", SpreadsheetUpdatedOnColumn)} ) : (
)}
setIsInlineCreateIssueFormOpen(false)} prePopulatedData={{ ...(cycleId && { cycle: cycleId.toString() }), ...(moduleId && { module: moduleId.toString() }), }} /> {type === "issue" ? !disableUserActions && !isInlineCreateIssueFormOpen && ( ) : !disableUserActions && !isInlineCreateIssueFormOpen && ( Add Issue } position="left" verticalPosition="top" optionsClassName="left-5 !w-36" noBorder > setIsInlineCreateIssueFormOpen(true)}> Create new {openIssuesListModal && ( Add an existing issue )} )}
); };