fix: spreadsheet layout sub-issues property update (#3110)

* fix: spreadsheet subissues property update

* fix: hover effect for sub-issues

* refactor: mutate sub-issues
This commit is contained in:
Lakhan Baheti 2023-12-13 23:07:26 +05:30 committed by GitHub
parent 4bb99d5fbf
commit 9d0056cfee
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 103 additions and 47 deletions

View File

@ -10,7 +10,7 @@ import { IIssue, IUserLite } from "types";
type Props = {
issue: IIssue;
members: IUserLite[] | undefined;
onChange: (data: Partial<IIssue>) => void;
onChange: (issue: IIssue, data: Partial<IIssue>) => void;
expandedIssues: string[];
disabled: boolean;
};
@ -18,7 +18,7 @@ type Props = {
export const SpreadsheetAssigneeColumn: React.FC<Props> = ({ issue, members, onChange, expandedIssues, disabled }) => {
const isExpanded = expandedIssues.indexOf(issue.id) > -1;
const { subIssues, isLoading } = useSubIssue(issue.project_detail?.id, issue.id, isExpanded);
const { subIssues, isLoading, mutateSubIssues } = useSubIssue(issue.project_detail?.id, issue.id, isExpanded);
return (
<>
@ -26,8 +26,13 @@ export const SpreadsheetAssigneeColumn: React.FC<Props> = ({ issue, members, onC
projectId={issue.project_detail?.id ?? null}
value={issue.assignees}
defaultOptions={issue?.assignee_details ? issue.assignee_details : []}
onChange={(data) => onChange({ assignees: data })}
className="h-11 w-full border-b-[0.5px] border-custom-border-200"
onChange={(data) => {
onChange(issue, { assignees: data });
if (issue.parent) {
mutateSubIssues(issue, { assignees: data });
}
}}
className="h-11 w-full border-b-[0.5px] border-custom-border-200 hover:bg-custom-background-80"
buttonClassName="!shadow-none !border-0 h-full w-full px-2.5 py-1 "
noLabelBorder
hideDropdownArrow

View File

@ -18,7 +18,7 @@ export const SpreadsheetAttachmentColumn: React.FC<Props> = (props) => {
return (
<>
<div className="flex h-11 w-full items-center px-2.5 py-1 text-xs border-b-[0.5px] border-custom-border-200">
<div className="flex h-11 w-full items-center px-2.5 py-1 text-xs border-b-[0.5px] border-custom-border-200 hover:bg-custom-background-80">
{issue.attachment_count} {issue.attachment_count === 1 ? "attachment" : "attachments"}
</div>

View File

@ -19,7 +19,7 @@ export const SpreadsheetCreatedOnColumn: React.FC<Props> = ({ issue, expandedIss
return (
<>
<div className="flex h-11 w-full items-center justify-center text-xs border-b-[0.5px] border-custom-border-200">
<div className="flex h-11 w-full items-center justify-center text-xs border-b-[0.5px] border-custom-border-200 hover:bg-custom-background-80">
{renderLongDetailDateFormat(issue.created_at)}
</div>

View File

@ -9,7 +9,7 @@ import { IIssue } from "types";
type Props = {
issue: IIssue;
onChange: (data: Partial<IIssue>) => void;
onChange: (issue: IIssue, data: Partial<IIssue>) => void;
expandedIssues: string[];
disabled: boolean;
};
@ -17,14 +17,19 @@ type Props = {
export const SpreadsheetDueDateColumn: React.FC<Props> = ({ issue, onChange, expandedIssues, disabled }) => {
const isExpanded = expandedIssues.indexOf(issue.id) > -1;
const { subIssues, isLoading } = useSubIssue(issue.project_detail?.id, issue.id, isExpanded);
const { subIssues, isLoading, mutateSubIssues } = useSubIssue(issue.project_detail?.id, issue.id, isExpanded);
return (
<>
<ViewDueDateSelect
issue={issue}
onChange={(val) => onChange({ target_date: val })}
className="flex !h-11 !w-full max-w-full items-center px-2.5 py-1 border-b-[0.5px] border-custom-border-200"
onChange={(val) => {
onChange(issue, { target_date: val });
if (issue.parent) {
mutateSubIssues(issue, { target_date: val });
}
}}
className="flex !h-11 !w-full max-w-full items-center px-2.5 py-1 border-b-[0.5px] border-custom-border-200 hover:bg-custom-background-80"
noBorder
disabled={disabled}
/>

View File

@ -7,7 +7,7 @@ import { IIssue } from "types";
type Props = {
issue: IIssue;
onChange: (formData: Partial<IIssue>) => void;
onChange: (issue: IIssue, formData: Partial<IIssue>) => void;
expandedIssues: string[];
disabled: boolean;
};
@ -17,15 +17,20 @@ export const SpreadsheetEstimateColumn: React.FC<Props> = (props) => {
const isExpanded = expandedIssues.indexOf(issue.id) > -1;
const { subIssues, isLoading } = useSubIssue(issue.project_detail?.id, issue.id, isExpanded);
const { subIssues, isLoading, mutateSubIssues } = useSubIssue(issue.project_detail?.id, issue.id, isExpanded);
return (
<>
<IssuePropertyEstimates
projectId={issue.project_detail?.id ?? null}
value={issue.estimate_point}
onChange={(data) => onChange({ estimate_point: data })}
className="h-11 w-full border-b-[0.5px] border-custom-border-200"
onChange={(data) => {
onChange(issue, { estimate_point: data });
if (issue.parent) {
mutateSubIssues(issue, { estimate_point: data });
}
}}
className="h-11 w-full border-b-[0.5px] border-custom-border-200 hover:bg-custom-background-80"
buttonClassName="h-full w-full px-2.5 py-1 !shadow-none !border-0"
hideDropdownArrow
disabled={disabled}

View File

@ -9,7 +9,7 @@ import { IIssue, IIssueLabel } from "types";
type Props = {
issue: IIssue;
onChange: (formData: Partial<IIssue>) => void;
onChange: (issue: IIssue, formData: Partial<IIssue>) => void;
labels: IIssueLabel[] | undefined;
expandedIssues: string[];
disabled: boolean;
@ -20,7 +20,7 @@ export const SpreadsheetLabelColumn: React.FC<Props> = (props) => {
const isExpanded = expandedIssues.indexOf(issue.id) > -1;
const { subIssues, isLoading } = useSubIssue(issue.project_detail?.id, issue.id, isExpanded);
const { subIssues, isLoading, mutateSubIssues } = useSubIssue(issue.project_detail?.id, issue.id, isExpanded);
return (
<>
@ -28,8 +28,13 @@ export const SpreadsheetLabelColumn: React.FC<Props> = (props) => {
projectId={issue.project_detail?.id ?? null}
value={issue.labels}
defaultOptions={issue?.label_details ? issue.label_details : []}
onChange={(data) => onChange({ labels: data })}
className="h-11 w-full border-b-[0.5px] border-custom-border-200"
onChange={(data) => {
onChange(issue, { labels: data });
if (issue.parent) {
mutateSubIssues(issue, { assignees: data });
}
}}
className="h-11 w-full border-b-[0.5px] border-custom-border-200 hover:bg-custom-background-80"
buttonClassName="px-2.5 h-full"
hideDropdownArrow
maxRender={1}

View File

@ -18,7 +18,7 @@ export const SpreadsheetLinkColumn: React.FC<Props> = (props) => {
return (
<>
<div className="flex h-11 w-full items-center px-2.5 py-1 text-xs border-b-[0.5px] border-custom-border-200">
<div className="flex h-11 w-full items-center px-2.5 py-1 text-xs border-b-[0.5px] border-custom-border-200 hover:bg-custom-background-80">
{issue.link_count} {issue.link_count === 1 ? "link" : "links"}
</div>

View File

@ -9,7 +9,7 @@ import { IIssue } from "types";
type Props = {
issue: IIssue;
onChange: (data: Partial<IIssue>) => void;
onChange: (issue: IIssue, data: Partial<IIssue>) => void;
expandedIssues: string[];
disabled: boolean;
};
@ -17,14 +17,19 @@ type Props = {
export const SpreadsheetPriorityColumn: React.FC<Props> = ({ issue, onChange, expandedIssues, disabled }) => {
const isExpanded = expandedIssues.indexOf(issue.id) > -1;
const { subIssues, isLoading } = useSubIssue(issue.project_detail?.id, issue.id, isExpanded);
const { subIssues, isLoading, mutateSubIssues } = useSubIssue(issue.project_detail?.id, issue.id, isExpanded);
return (
<>
<PrioritySelect
value={issue.priority}
onChange={(data) => onChange({ priority: data })}
className="h-11 w-full border-b-[0.5px] border-custom-border-200"
onChange={(data) => {
onChange(issue, { priority: data });
if (issue.parent) {
mutateSubIssues(issue, { priority: data });
}
}}
className="h-11 w-full border-b-[0.5px] border-custom-border-200 hover:bg-custom-background-80"
buttonClassName="!shadow-none !border-0 h-full w-full px-2.5 py-1"
showTitle
highlightUrgentPriority={false}

View File

@ -9,7 +9,7 @@ import { IIssue } from "types";
type Props = {
issue: IIssue;
onChange: (formData: Partial<IIssue>) => void;
onChange: (issue: IIssue, formData: Partial<IIssue>) => void;
expandedIssues: string[];
disabled: boolean;
};
@ -17,14 +17,19 @@ type Props = {
export const SpreadsheetStartDateColumn: React.FC<Props> = ({ issue, onChange, expandedIssues, disabled }) => {
const isExpanded = expandedIssues.indexOf(issue.id) > -1;
const { subIssues, isLoading } = useSubIssue(issue.project_detail?.id, issue.id, isExpanded);
const { subIssues, isLoading, mutateSubIssues } = useSubIssue(issue.project_detail?.id, issue.id, isExpanded);
return (
<>
<ViewStartDateSelect
issue={issue}
onChange={(val) => onChange({ start_date: val })}
className="flex !h-11 !w-full max-w-full items-center px-2.5 py-1 border-b-[0.5px] border-custom-border-200"
onChange={(val) => {
onChange(issue, { start_date: val });
if (issue.parent) {
mutateSubIssues(issue, { start_date: val });
}
}}
className="flex !h-11 !w-full max-w-full items-center px-2.5 py-1 border-b-[0.5px] border-custom-border-200 hover:bg-custom-background-80"
noBorder
disabled={disabled}
/>

View File

@ -6,10 +6,12 @@ import { IssuePropertyState } from "../../properties";
import useSubIssue from "hooks/use-sub-issue";
// types
import { IIssue, IState } from "types";
import { mutate } from "swr";
import { SUB_ISSUES } from "constants/fetch-keys";
type Props = {
issue: IIssue;
onChange: (data: Partial<IIssue>) => void;
onChange: (issue: IIssue, data: Partial<IIssue>) => void;
states: IState[] | undefined;
expandedIssues: string[];
disabled: boolean;
@ -20,7 +22,7 @@ export const SpreadsheetStateColumn: React.FC<Props> = (props) => {
const isExpanded = expandedIssues.indexOf(issue.id) > -1;
const { subIssues, isLoading } = useSubIssue(issue.project_detail?.id, issue.id, isExpanded);
const { subIssues, isLoading, mutateSubIssues } = useSubIssue(issue.project_detail?.id, issue.id, isExpanded);
return (
<>
@ -28,7 +30,12 @@ export const SpreadsheetStateColumn: React.FC<Props> = (props) => {
projectId={issue.project_detail?.id ?? null}
value={issue.state}
defaultOptions={issue?.state_detail ? [issue.state_detail] : []}
onChange={(data) => onChange({ state: data.id, state_detail: data })}
onChange={(data) => {
onChange(issue, { state: data.id, state_detail: data });
if (issue.parent) {
mutateSubIssues(issue, { state: data.id, state_detail: data });
}
}}
className="w-full !h-11 border-b-[0.5px] border-custom-border-200"
buttonClassName="!shadow-none !border-0 h-full w-full"
hideDropdownArrow

View File

@ -18,7 +18,7 @@ export const SpreadsheetSubIssueColumn: React.FC<Props> = (props) => {
return (
<>
<div className="flex h-11 w-full items-center px-2.5 py-1 text-xs border-b-[0.5px] border-custom-border-200">
<div className="flex h-11 w-full items-center px-2.5 py-1 text-xs border-b-[0.5px] border-custom-border-200 hover:bg-custom-background-80">
{issue.sub_issues_count} {issue.sub_issues_count === 1 ? "sub-issue" : "sub-issues"}
</div>

View File

@ -21,7 +21,7 @@ export const SpreadsheetUpdatedOnColumn: React.FC<Props> = (props) => {
return (
<>
<div className="flex h-11 w-full items-center justify-center text-xs border-b-[0.5px] border-custom-border-200">
<div className="flex h-11 w-full items-center justify-center text-xs border-b-[0.5px] border-custom-border-200 hover:bg-custom-background-80">
{renderLongDetailDateFormat(issue.updated_at)}
</div>

View File

@ -163,18 +163,13 @@ export const SpreadsheetColumn: React.FC<Props> = (props) => {
{issues?.map((issue) => {
const disableUserActions = !canEditProperties(issue.project);
return (
<div
key={`${property}-${issue.id}`}
className={`h-fit ${
disableUserActions ? "" : "cursor-pointer hover:bg-custom-background-80"
}`}
>
<div key={`${property}-${issue.id}`} className={`h-fit ${disableUserActions ? "" : "cursor-pointer"}`}>
{property === "state" ? (
<SpreadsheetStateColumn
disabled={disableUserActions}
expandedIssues={expandedIssues}
issue={issue}
onChange={(data: Partial<IIssue>) => handleUpdateIssue(issue, data)}
onChange={(issue: IIssue, data: Partial<IIssue>) => handleUpdateIssue(issue, data)}
states={states}
/>
) : property === "priority" ? (
@ -182,14 +177,14 @@ export const SpreadsheetColumn: React.FC<Props> = (props) => {
disabled={disableUserActions}
expandedIssues={expandedIssues}
issue={issue}
onChange={(data: Partial<IIssue>) => handleUpdateIssue(issue, data)}
onChange={(issue: IIssue, data: Partial<IIssue>) => handleUpdateIssue(issue, data)}
/>
) : property === "estimate" ? (
<SpreadsheetEstimateColumn
disabled={disableUserActions}
expandedIssues={expandedIssues}
issue={issue}
onChange={(data: Partial<IIssue>) => handleUpdateIssue(issue, data)}
onChange={(issue: IIssue, data: Partial<IIssue>) => handleUpdateIssue(issue, data)}
/>
) : property === "assignee" ? (
<SpreadsheetAssigneeColumn
@ -197,7 +192,7 @@ export const SpreadsheetColumn: React.FC<Props> = (props) => {
expandedIssues={expandedIssues}
issue={issue}
members={members}
onChange={(data: Partial<IIssue>) => handleUpdateIssue(issue, data)}
onChange={(issue: IIssue, data: Partial<IIssue>) => handleUpdateIssue(issue, data)}
/>
) : property === "labels" ? (
<SpreadsheetLabelColumn
@ -205,21 +200,21 @@ export const SpreadsheetColumn: React.FC<Props> = (props) => {
expandedIssues={expandedIssues}
issue={issue}
labels={labels}
onChange={(data: Partial<IIssue>) => handleUpdateIssue(issue, data)}
onChange={(issue: IIssue, data: Partial<IIssue>) => handleUpdateIssue(issue, data)}
/>
) : property === "start_date" ? (
<SpreadsheetStartDateColumn
disabled={disableUserActions}
expandedIssues={expandedIssues}
issue={issue}
onChange={(data: Partial<IIssue>) => handleUpdateIssue(issue, data)}
onChange={(issue: IIssue, data: Partial<IIssue>) => handleUpdateIssue(issue, data)}
/>
) : property === "due_date" ? (
<SpreadsheetDueDateColumn
disabled={disableUserActions}
expandedIssues={expandedIssues}
issue={issue}
onChange={(data: Partial<IIssue>) => handleUpdateIssue(issue, data)}
onChange={(issue: IIssue, data: Partial<IIssue>) => handleUpdateIssue(issue, data)}
/>
) : property === "created_on" ? (
<SpreadsheetCreatedOnColumn expandedIssues={expandedIssues} issue={issue} />

View File

@ -1,11 +1,11 @@
import { useRouter } from "next/router";
import useSWR from "swr";
import useSWR, { mutate } from "swr";
// services
import { IssueService } from "services/issue";
// types
import { ISubIssueResponse } from "types";
import { IIssue, ISubIssueResponse } from "types";
// fetch-keys
import { SUB_ISSUES } from "constants/fetch-keys";
@ -22,9 +22,33 @@ const useSubIssue = (projectId: string, issueId: string, isExpanded: boolean) =>
shouldFetch ? () => issueService.subIssues(workspaceSlug as string, projectId as string, issueId as string) : null
);
const mutateSubIssues = (issue: IIssue, data: Partial<IIssue>) => {
if (!issue.parent) return;
mutate(
SUB_ISSUES(issue.parent!),
(prev_data: any) => {
return {
...prev_data,
sub_issues: prev_data.sub_issues.map((sub_issue: any) => {
if (sub_issue.id === issue.id) {
return {
...sub_issue,
...data,
};
}
return sub_issue;
}),
};
},
false
);
};
return {
subIssues: subIssuesResponse?.sub_issues ?? [],
isLoading,
mutateSubIssues,
};
};