diff --git a/web/components/issues/issue-layouts/spreadsheet/columns/attachment-column.tsx b/web/components/issues/issue-layouts/spreadsheet/columns/attachment-column.tsx new file mode 100644 index 000000000..475161eeb --- /dev/null +++ b/web/components/issues/issue-layouts/spreadsheet/columns/attachment-column.tsx @@ -0,0 +1,34 @@ +import React from "react"; +// hooks +import useSubIssue from "hooks/use-sub-issue"; +// types +import { IIssue } from "types"; + +type Props = { + issue: IIssue; + expandedIssues: string[]; +}; + +export const SpreadsheetAttachmentColumn: React.FC = (props) => { + const { issue, expandedIssues } = props; + + const isExpanded = expandedIssues.indexOf(issue.id) > -1; + + const { subIssues, isLoading } = useSubIssue(issue.project_detail.id, issue.id, isExpanded); + + return ( + <> +
+ {issue.attachment_count} {issue.attachment_count === 1 ? "attachment" : "attachments"} +
+ + {isExpanded && + !isLoading && + subIssues && + subIssues.length > 0 && + subIssues.map((subIssue: IIssue) => ( + + ))} + + ); +}; diff --git a/web/components/issues/issue-layouts/spreadsheet/columns/columns-list.tsx b/web/components/issues/issue-layouts/spreadsheet/columns/columns-list.tsx index bd1712cdd..90ad56d12 100644 --- a/web/components/issues/issue-layouts/spreadsheet/columns/columns-list.tsx +++ b/web/components/issues/issue-layouts/spreadsheet/columns/columns-list.tsx @@ -142,6 +142,39 @@ export const SpreadsheetColumnsList: React.FC = observer((props) => { property="updated_on" /> )} + {displayProperties.link && ( + + )} + {displayProperties.attachment_count && ( + + )} + {displayProperties.sub_issue_count && ( + + )} ); }); diff --git a/web/components/issues/issue-layouts/spreadsheet/columns/index.ts b/web/components/issues/issue-layouts/spreadsheet/columns/index.ts index a1c4959ab..a6c4979b3 100644 --- a/web/components/issues/issue-layouts/spreadsheet/columns/index.ts +++ b/web/components/issues/issue-layouts/spreadsheet/columns/index.ts @@ -1,11 +1,14 @@ export * from "./issue"; export * from "./assignee-column"; +export * from "./attachment-column"; export * from "./columns-list"; export * from "./created-on-column"; export * from "./due-date-column"; export * from "./estimate-column"; export * from "./label-column"; +export * from "./link-column"; export * from "./priority-column"; export * from "./start-date-column"; export * from "./state-column"; +export * from "./sub-issue-column"; export * from "./updated-on-column"; diff --git a/web/components/issues/issue-layouts/spreadsheet/columns/link-column.tsx b/web/components/issues/issue-layouts/spreadsheet/columns/link-column.tsx new file mode 100644 index 000000000..90e71bcde --- /dev/null +++ b/web/components/issues/issue-layouts/spreadsheet/columns/link-column.tsx @@ -0,0 +1,34 @@ +import React from "react"; +// hooks +import useSubIssue from "hooks/use-sub-issue"; +// types +import { IIssue } from "types"; + +type Props = { + issue: IIssue; + expandedIssues: string[]; +}; + +export const SpreadsheetLinkColumn: React.FC = (props) => { + const { issue, expandedIssues } = props; + + const isExpanded = expandedIssues.indexOf(issue.id) > -1; + + const { subIssues, isLoading } = useSubIssue(issue.project_detail.id, issue.id, isExpanded); + + return ( + <> +
+ {issue.link_count} {issue.link_count === 1 ? "link" : "links"} +
+ + {isExpanded && + !isLoading && + subIssues && + subIssues.length > 0 && + subIssues.map((subIssue: IIssue) => ( + + ))} + + ); +}; diff --git a/web/components/issues/issue-layouts/spreadsheet/columns/sub-issue-column.tsx b/web/components/issues/issue-layouts/spreadsheet/columns/sub-issue-column.tsx new file mode 100644 index 000000000..8f5e6f125 --- /dev/null +++ b/web/components/issues/issue-layouts/spreadsheet/columns/sub-issue-column.tsx @@ -0,0 +1,34 @@ +import React from "react"; +// hooks +import useSubIssue from "hooks/use-sub-issue"; +// types +import { IIssue } from "types"; + +type Props = { + issue: IIssue; + expandedIssues: string[]; +}; + +export const SpreadsheetSubIssueColumn: React.FC = (props) => { + const { issue, expandedIssues } = props; + + const isExpanded = expandedIssues.indexOf(issue.id) > -1; + + const { subIssues, isLoading } = useSubIssue(issue.project_detail.id, issue.id, isExpanded); + + return ( + <> +
+ {issue.sub_issues_count} {issue.sub_issues_count === 1 ? "sub-issue" : "sub-issues"} +
+ + {isExpanded && + !isLoading && + subIssues && + subIssues.length > 0 && + subIssues.map((subIssue: IIssue) => ( + + ))} + + ); +}; diff --git a/web/components/issues/issue-layouts/spreadsheet/spreadsheet-column.tsx b/web/components/issues/issue-layouts/spreadsheet/spreadsheet-column.tsx index 4013c7737..006e91d50 100644 --- a/web/components/issues/issue-layouts/spreadsheet/spreadsheet-column.tsx +++ b/web/components/issues/issue-layouts/spreadsheet/spreadsheet-column.tsx @@ -12,13 +12,16 @@ import useLocalStorage from "hooks/use-local-storage"; // components import { SpreadsheetAssigneeColumn, + SpreadsheetAttachmentColumn, SpreadsheetCreatedOnColumn, SpreadsheetDueDateColumn, SpreadsheetEstimateColumn, SpreadsheetLabelColumn, + SpreadsheetLinkColumn, SpreadsheetPriorityColumn, SpreadsheetStartDateColumn, SpreadsheetStateColumn, + SpreadsheetSubIssueColumn, SpreadsheetUpdatedOnColumn, } from "components/issues"; // ui @@ -178,7 +181,6 @@ export const SpreadsheetColumn: React.FC = (props) => { /> ) : property === "priority" ? ( = (props) => { /> ) : property === "estimate" ? ( = (props) => { /> ) : property === "assignee" ? ( = (props) => { /> ) : property === "labels" ? ( = (props) => { /> ) : property === "start_date" ? ( = (props) => { /> ) : property === "due_date" ? ( ) => handleUpdateIssue(issue, data)} /> ) : property === "created_on" ? ( - + ) : property === "updated_on" ? ( - + + ) : property === "link" ? ( + + ) : property === "attachment_count" ? ( + + ) : property === "sub_issue_count" ? ( + ) : null} ))} diff --git a/web/constants/spreadsheet.ts b/web/constants/spreadsheet.ts index 1fe1f4e34..603e280f5 100644 --- a/web/constants/spreadsheet.ts +++ b/web/constants/spreadsheet.ts @@ -72,4 +72,25 @@ export const SPREADSHEET_PROPERTY_DETAILS: { descendingOrderKey: "updated_at", descendingOrderTitle: "Old", }, + link: { + title: "Link", + ascendingOrderKey: "-link_count", + ascendingOrderTitle: "Most", + descendingOrderKey: "link_count", + descendingOrderTitle: "Least", + }, + attachment_count: { + title: "Attachment", + ascendingOrderKey: "-attachment_count", + ascendingOrderTitle: "Most", + descendingOrderKey: "attachment_count", + descendingOrderTitle: "Least", + }, + sub_issue_count: { + title: "Sub-issue", + ascendingOrderKey: "-sub_issues_count", + ascendingOrderTitle: "Most", + descendingOrderKey: "sub_issues_count", + descendingOrderTitle: "Least", + }, }; diff --git a/web/types/view-props.d.ts b/web/types/view-props.d.ts index 67884e5e5..c8c47576b 100644 --- a/web/types/view-props.d.ts +++ b/web/types/view-props.d.ts @@ -30,7 +30,13 @@ export type TIssueOrderByOptions = | "estimate_point" | "-estimate_point" | "start_date" - | "-start_date"; + | "-start_date" + | "link_count" + | "-link_count" + | "attachment_count" + | "-attachment_count" + | "sub_issues_count" + | "-sub_issues_count"; export type TIssueTypeFilters = "active" | "backlog" | null;