chore: add empty state for list and spreadsheet layouts (#2531)

* chore: add empty state for list and spreadsheet layouts

* fix: build errors
This commit is contained in:
Aaryan Khandelwal 2023-10-30 20:09:04 +05:30 committed by GitHub
parent 8eaac60aa5
commit 050406b8a4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
22 changed files with 417 additions and 105 deletions

View File

@ -0,0 +1,25 @@
import { PlusIcon } from "lucide-react";
// components
import { EmptyState } from "components/common";
// assets
import emptyIssue from "public/empty-state/issue.svg";
export const CycleEmptyState: React.FC = () => (
<div className="h-full w-full grid place-items-center">
<EmptyState
title="Cycle issues will appear here"
description="Issues help you track individual pieces of work. With Issues, keep track of what's going on, who is working on it, and what's done."
image={emptyIssue}
primaryButton={{
text: "New issue",
icon: <PlusIcon className="h-3 w-3" strokeWidth={2} />,
onClick: () => {
const e = new KeyboardEvent("keydown", {
key: "c",
});
document.dispatchEvent(e);
},
}}
/>
</div>
);

View File

@ -0,0 +1,25 @@
import { PlusIcon } from "lucide-react";
// components
import { EmptyState } from "components/common";
// assets
import emptyIssue from "public/empty-state/issue.svg";
export const GlobalViewEmptyState: React.FC = () => (
<div className="h-full w-full grid place-items-center">
<EmptyState
title="View issues will appear here"
description="Issues help you track individual pieces of work. With Issues, keep track of what's going on, who is working on it, and what's done."
image={emptyIssue}
primaryButton={{
text: "New issue",
icon: <PlusIcon className="h-3 w-3" strokeWidth={2} />,
onClick: () => {
const e = new KeyboardEvent("keydown", {
key: "c",
});
document.dispatchEvent(e);
},
}}
/>
</div>
);

View File

@ -0,0 +1,5 @@
export * from "./cycle";
export * from "./global-view";
export * from "./module";
export * from "./project-view";
export * from "./project";

View File

@ -0,0 +1,25 @@
import { PlusIcon } from "lucide-react";
// components
import { EmptyState } from "components/common";
// assets
import emptyIssue from "public/empty-state/issue.svg";
export const ModuleEmptyState: React.FC = () => (
<div className="h-full w-full grid place-items-center">
<EmptyState
title="Module issues will appear here"
description="Issues help you track individual pieces of work. With Issues, keep track of what's going on, who is working on it, and what's done."
image={emptyIssue}
primaryButton={{
text: "New issue",
icon: <PlusIcon className="h-3 w-3" strokeWidth={2} />,
onClick: () => {
const e = new KeyboardEvent("keydown", {
key: "c",
});
document.dispatchEvent(e);
},
}}
/>
</div>
);

View File

@ -0,0 +1,25 @@
import { PlusIcon } from "lucide-react";
// components
import { EmptyState } from "components/common";
// assets
import emptyIssue from "public/empty-state/issue.svg";
export const ProjectViewEmptyState: React.FC = () => (
<div className="h-full w-full grid place-items-center">
<EmptyState
title="View issues will appear here"
description="Issues help you track individual pieces of work. With Issues, keep track of what's going on, who is working on it, and what's done."
image={emptyIssue}
primaryButton={{
text: "New issue",
icon: <PlusIcon className="h-3 w-3" strokeWidth={2} />,
onClick: () => {
const e = new KeyboardEvent("keydown", {
key: "c",
});
document.dispatchEvent(e);
},
}}
/>
</div>
);

View File

@ -0,0 +1,25 @@
import { PlusIcon } from "lucide-react";
// components
import { EmptyState } from "components/common";
// assets
import emptyIssue from "public/empty-state/issue.svg";
export const ProjectEmptyState: React.FC = () => (
<div className="h-full w-full grid place-items-center">
<EmptyState
title="Project issues will appear here"
description="Issues help you track individual pieces of work. With Issues, keep track of what's going on, who is working on it, and what's done."
image={emptyIssue}
primaryButton={{
text: "New issue",
icon: <PlusIcon className="h-3 w-3" strokeWidth={2} />,
onClick: () => {
const e = new KeyboardEvent("keydown", {
key: "c",
});
document.dispatchEvent(e);
},
}}
/>
</div>
);

View File

@ -1,5 +1,6 @@
// filters // filters
export * from "./filters"; export * from "./filters";
export * from "./empty-states";
export * from "./quick-action-dropdowns"; export * from "./quick-action-dropdowns";
// layouts // layouts

View File

@ -1,4 +1,5 @@
export * from "./roots"; export * from "./roots";
export * from "./block"; export * from "./block";
export * from "./roots";
export * from "./blocks-list"; export * from "./blocks-list";
export * from "./inline-create-issue-form"; export * from "./inline-create-issue-form";

View File

@ -68,7 +68,7 @@ export const ModuleListLayout: React.FC = observer(() => {
: null; : null;
return ( return (
<div className={`relative w-full h-full bg-custom-background-90`}> <div className="relative w-full h-full bg-custom-background-90">
<List <List
issues={issues} issues={issues}
group_by={group_by} group_by={group_by}

View File

@ -8,6 +8,7 @@ import { useMobxStore } from "lib/mobx/store-provider";
import { import {
CycleAppliedFiltersRoot, CycleAppliedFiltersRoot,
CycleCalendarLayout, CycleCalendarLayout,
CycleEmptyState,
CycleGanttLayout, CycleGanttLayout,
CycleKanBanLayout, CycleKanBanLayout,
CycleListLayout, CycleListLayout,
@ -50,25 +51,31 @@ export const CycleLayoutRoot: React.FC = observer(() => {
? getDateRangeStatus(cycleDetails?.start_date, cycleDetails?.end_date) ? getDateRangeStatus(cycleDetails?.start_date, cycleDetails?.end_date)
: "draft"; : "draft";
const issueCount = cycleIssueStore.getIssuesCount;
return ( return (
<> <>
<TransferIssuesModal handleClose={() => setTransferIssuesModal(false)} isOpen={transferIssuesModal} /> <TransferIssuesModal handleClose={() => setTransferIssuesModal(false)} isOpen={transferIssuesModal} />
<div className="relative w-full h-full flex flex-col overflow-hidden"> <div className="relative w-full h-full flex flex-col overflow-hidden">
{cycleStatus === "completed" && <TransferIssues handleClick={() => setTransferIssuesModal(true)} />} {cycleStatus === "completed" && <TransferIssues handleClick={() => setTransferIssuesModal(true)} />}
<CycleAppliedFiltersRoot /> <CycleAppliedFiltersRoot />
<div className="w-full h-full overflow-auto"> {(activeLayout === "list" || activeLayout === "spreadsheet") && issueCount === 0 ? (
{activeLayout === "list" ? ( <CycleEmptyState />
<CycleListLayout /> ) : (
) : activeLayout === "kanban" ? ( <div className="w-full h-full overflow-auto">
<CycleKanBanLayout /> {activeLayout === "list" ? (
) : activeLayout === "calendar" ? ( <CycleListLayout />
<CycleCalendarLayout /> ) : activeLayout === "kanban" ? (
) : activeLayout === "gantt_chart" ? ( <CycleKanBanLayout />
<CycleGanttLayout /> ) : activeLayout === "calendar" ? (
) : activeLayout === "spreadsheet" ? ( <CycleCalendarLayout />
<CycleSpreadsheetLayout /> ) : activeLayout === "gantt_chart" ? (
) : null} <CycleGanttLayout />
</div> ) : activeLayout === "spreadsheet" ? (
<CycleSpreadsheetLayout />
) : null}
</div>
)}
</div> </div>
</> </>
); );

View File

@ -5,7 +5,7 @@ import useSWR from "swr";
// mobx store // mobx store
import { useMobxStore } from "lib/mobx/store-provider"; import { useMobxStore } from "lib/mobx/store-provider";
// components // components
import { GlobalViewsAppliedFiltersRoot, SpreadsheetView } from "components/issues"; import { GlobalViewEmptyState, GlobalViewsAppliedFiltersRoot, SpreadsheetView } from "components/issues";
// types // types
import { IIssue, IIssueDisplayFilterOptions, TStaticViewTypes } from "types"; import { IIssue, IIssueDisplayFilterOptions, TStaticViewTypes } from "types";
@ -81,19 +81,23 @@ export const GlobalViewLayoutRoot: React.FC<Props> = observer((props) => {
return ( return (
<div className="relative w-full h-full flex flex-col overflow-hidden"> <div className="relative w-full h-full flex flex-col overflow-hidden">
<GlobalViewsAppliedFiltersRoot /> <GlobalViewsAppliedFiltersRoot />
<div className="h-full w-full overflow-auto"> {issues?.length === 0 ? (
<SpreadsheetView <GlobalViewEmptyState />
displayProperties={workspaceFilterStore.workspaceDisplayProperties} ) : (
displayFilters={workspaceFilterStore.workspaceDisplayFilters} <div className="h-full w-full overflow-auto">
handleDisplayFilterUpdate={handleDisplayFiltersUpdate} <SpreadsheetView
issues={issues} displayProperties={workspaceFilterStore.workspaceDisplayProperties}
members={workspaceStore.workspaceMembers ? workspaceStore.workspaceMembers.map((m) => m.member) : undefined} displayFilters={workspaceFilterStore.workspaceDisplayFilters}
labels={workspaceStore.workspaceLabels ? workspaceStore.workspaceLabels : undefined} handleDisplayFilterUpdate={handleDisplayFiltersUpdate}
handleIssueAction={() => {}} issues={issues}
handleUpdateIssue={handleUpdateIssue} members={workspaceStore.workspaceMembers ? workspaceStore.workspaceMembers.map((m) => m.member) : undefined}
disableUserActions={false} labels={workspaceStore.workspaceLabels ? workspaceStore.workspaceLabels : undefined}
/> handleIssueAction={() => {}}
</div> handleUpdateIssue={handleUpdateIssue}
disableUserActions={false}
/>
</div>
)}
</div> </div>
); );
}); });

View File

@ -9,6 +9,7 @@ import { useMobxStore } from "lib/mobx/store-provider";
import { import {
ModuleAppliedFiltersRoot, ModuleAppliedFiltersRoot,
ModuleCalendarLayout, ModuleCalendarLayout,
ModuleEmptyState,
ModuleGanttLayout, ModuleGanttLayout,
ModuleKanBanLayout, ModuleKanBanLayout,
ModuleListLayout, ModuleListLayout,
@ -46,22 +47,28 @@ export const ModuleLayoutRoot: React.FC = observer(() => {
const activeLayout = issueFilterStore.userDisplayFilters.layout; const activeLayout = issueFilterStore.userDisplayFilters.layout;
const issueCount = moduleIssueStore.getIssuesCount;
return ( return (
<div className="relative w-full h-full flex flex-col overflow-hidden"> <div className="relative w-full h-full flex flex-col overflow-hidden">
<ModuleAppliedFiltersRoot /> <ModuleAppliedFiltersRoot />
<div className="h-full w-full overflow-auto"> {(activeLayout === "list" || activeLayout === "spreadsheet") && issueCount === 0 ? (
{activeLayout === "list" ? ( <ModuleEmptyState />
<ModuleListLayout /> ) : (
) : activeLayout === "kanban" ? ( <div className="h-full w-full overflow-auto">
<ModuleKanBanLayout /> {activeLayout === "list" ? (
) : activeLayout === "calendar" ? ( <ModuleListLayout />
<ModuleCalendarLayout /> ) : activeLayout === "kanban" ? (
) : activeLayout === "gantt_chart" ? ( <ModuleKanBanLayout />
<ModuleGanttLayout /> ) : activeLayout === "calendar" ? (
) : activeLayout === "spreadsheet" ? ( <ModuleCalendarLayout />
<ModuleSpreadsheetLayout /> ) : activeLayout === "gantt_chart" ? (
) : null} <ModuleGanttLayout />
</div> ) : activeLayout === "spreadsheet" ? (
<ModuleSpreadsheetLayout />
) : null}
</div>
)}
</div> </div>
); );
}); });

View File

@ -12,6 +12,7 @@ import {
KanBanLayout, KanBanLayout,
ProjectAppliedFiltersRoot, ProjectAppliedFiltersRoot,
ProjectSpreadsheetLayout, ProjectSpreadsheetLayout,
ProjectEmptyState,
} from "components/issues"; } from "components/issues";
export const ProjectLayoutRoot: React.FC = observer(() => { export const ProjectLayoutRoot: React.FC = observer(() => {
@ -30,22 +31,28 @@ export const ProjectLayoutRoot: React.FC = observer(() => {
const activeLayout = issueFilterStore.userDisplayFilters.layout; const activeLayout = issueFilterStore.userDisplayFilters.layout;
const issueCount = issueStore.getIssuesCount;
return ( return (
<div className="relative w-full h-full flex flex-col overflow-hidden"> <div className="relative w-full h-full flex flex-col overflow-hidden">
<ProjectAppliedFiltersRoot /> <ProjectAppliedFiltersRoot />
<div className="w-full h-full overflow-auto"> {(activeLayout === "list" || activeLayout === "spreadsheet") && issueCount === 0 ? (
{activeLayout === "list" ? ( <ProjectEmptyState />
<ListLayout /> ) : (
) : activeLayout === "kanban" ? ( <div className="w-full h-full overflow-auto">
<KanBanLayout /> {activeLayout === "list" ? (
) : activeLayout === "calendar" ? ( <ListLayout />
<CalendarLayout /> ) : activeLayout === "kanban" ? (
) : activeLayout === "gantt_chart" ? ( <KanBanLayout />
<GanttLayout /> ) : activeLayout === "calendar" ? (
) : activeLayout === "spreadsheet" ? ( <CalendarLayout />
<ProjectSpreadsheetLayout /> ) : activeLayout === "gantt_chart" ? (
) : null} <GanttLayout />
</div> ) : activeLayout === "spreadsheet" ? (
<ProjectSpreadsheetLayout />
) : null}
</div>
)}
</div> </div>
); );
}); });

View File

@ -11,6 +11,7 @@ import {
ModuleListLayout, ModuleListLayout,
ProjectViewAppliedFiltersRoot, ProjectViewAppliedFiltersRoot,
ProjectViewCalendarLayout, ProjectViewCalendarLayout,
ProjectViewEmptyState,
ProjectViewGanttLayout, ProjectViewGanttLayout,
ProjectViewSpreadsheetLayout, ProjectViewSpreadsheetLayout,
} from "components/issues"; } from "components/issues";
@ -48,22 +49,28 @@ export const ProjectViewLayoutRoot: React.FC = observer(() => {
const activeLayout = issueFilterStore.userDisplayFilters.layout; const activeLayout = issueFilterStore.userDisplayFilters.layout;
const issueCount = projectViewIssuesStore.getIssuesCount;
return ( return (
<div className="relative h-full w-full flex flex-col overflow-hidden"> <div className="relative h-full w-full flex flex-col overflow-hidden">
<ProjectViewAppliedFiltersRoot /> <ProjectViewAppliedFiltersRoot />
<div className="h-full w-full overflow-y-auto"> {(activeLayout === "list" || activeLayout === "spreadsheet") && issueCount === 0 ? (
{activeLayout === "list" ? ( <ProjectViewEmptyState />
<ModuleListLayout /> ) : (
) : activeLayout === "kanban" ? ( <div className="h-full w-full overflow-y-auto">
<ModuleKanBanLayout /> {activeLayout === "list" ? (
) : activeLayout === "calendar" ? ( <ModuleListLayout />
<ProjectViewCalendarLayout /> ) : activeLayout === "kanban" ? (
) : activeLayout === "gantt_chart" ? ( <ModuleKanBanLayout />
<ProjectViewGanttLayout /> ) : activeLayout === "calendar" ? (
) : activeLayout === "spreadsheet" ? ( <ProjectViewCalendarLayout />
<ProjectViewSpreadsheetLayout /> ) : activeLayout === "gantt_chart" ? (
) : null} <ProjectViewGanttLayout />
</div> ) : activeLayout === "spreadsheet" ? (
<ProjectViewSpreadsheetLayout />
) : null}
</div>
)}
</div> </div>
); );
}); });

View File

@ -6,15 +6,12 @@ import { IIssue } from "types";
// services // services
import { IssueService } from "services/issue"; import { IssueService } from "services/issue";
import { sortArrayByDate, sortArrayByPriority } from "constants/kanban-helpers"; import { sortArrayByDate, sortArrayByPriority } from "constants/kanban-helpers";
import {
export type IIssueType = "grouped" | "groupWithSubGroups" | "ungrouped"; IIssueGroupWithSubGroupsStructure,
export type IIssueGroupedStructure = { [group_id: string]: IIssue[] }; IIssueGroupedStructure,
export type IIssueGroupWithSubGroupsStructure = { IIssueType,
[group_id: string]: { IIssueUnGroupedStructure,
[sub_group_id: string]: IIssue[]; } from "store/issue";
};
};
export type IIssueUnGroupedStructure = IIssue[];
export interface IArchivedIssueStore { export interface IArchivedIssueStore {
loader: boolean; loader: boolean;

View File

@ -9,15 +9,12 @@ import { sortArrayByDate, sortArrayByPriority } from "constants/kanban-helpers";
// types // types
import { IIssue } from "types"; import { IIssue } from "types";
import { IBlockUpdateData } from "components/gantt-chart"; import { IBlockUpdateData } from "components/gantt-chart";
import {
export type IIssueType = "grouped" | "groupWithSubGroups" | "ungrouped"; IIssueGroupWithSubGroupsStructure,
export type IIssueGroupedStructure = { [group_id: string]: IIssue[] }; IIssueGroupedStructure,
export type IIssueGroupWithSubGroupsStructure = { IIssueType,
[group_id: string]: { IIssueUnGroupedStructure,
[sub_group_id: string]: IIssue[]; } from "store/issue";
};
};
export type IIssueUnGroupedStructure = IIssue[];
export interface ICycleIssueStore { export interface ICycleIssueStore {
loader: boolean; loader: boolean;
@ -33,6 +30,7 @@ export interface ICycleIssueStore {
// computed // computed
getIssueType: IIssueType | null; getIssueType: IIssueType | null;
getIssues: IIssueGroupedStructure | IIssueGroupWithSubGroupsStructure | IIssueUnGroupedStructure | null; getIssues: IIssueGroupedStructure | IIssueGroupWithSubGroupsStructure | IIssueUnGroupedStructure | null;
getIssuesCount: number;
// action // action
fetchIssues: (workspaceSlug: string, projectId: string, cycleId: string) => Promise<any>; fetchIssues: (workspaceSlug: string, projectId: string, cycleId: string) => Promise<any>;
updateIssueStructure: (group_id: string | null, sub_group_id: string | null, issue: IIssue) => void; updateIssueStructure: (group_id: string | null, sub_group_id: string | null, issue: IIssue) => void;
@ -73,6 +71,7 @@ export class CycleIssueStore implements ICycleIssueStore {
// computed // computed
getIssueType: computed, getIssueType: computed,
getIssues: computed, getIssues: computed,
getIssuesCount: computed,
// actions // actions
fetchIssues: action, fetchIssues: action,
updateIssueStructure: action, updateIssueStructure: action,
@ -130,6 +129,44 @@ export class CycleIssueStore implements ICycleIssueStore {
return this.issues?.[cycleId]?.[issueType] || null; return this.issues?.[cycleId]?.[issueType] || null;
} }
get getIssuesCount() {
const issueType = this.getIssueType;
let issuesCount = 0;
if (issueType === "grouped") {
const issues = this.getIssues as IIssueGroupedStructure;
if (!issues) return 0;
Object.keys(issues).map((group_id) => {
issuesCount += issues[group_id].length;
});
}
if (issueType === "groupWithSubGroups") {
const issues = this.getIssues as IIssueGroupWithSubGroupsStructure;
if (!issues) return 0;
Object.keys(issues).map((sub_group_id) => {
Object.keys(issues[sub_group_id]).map((group_id) => {
issuesCount += issues[sub_group_id][group_id].length;
});
});
}
if (issueType === "ungrouped") {
const issues = this.getIssues as IIssueUnGroupedStructure;
if (!issues) return 0;
issuesCount = issues.length;
}
return issuesCount;
}
updateIssueStructure = async (group_id: string | null, sub_group_id: string | null, issue: IIssue) => { updateIssueStructure = async (group_id: string | null, sub_group_id: string | null, issue: IIssue) => {
const cycleId: string | null = this.rootStore?.cycle?.cycleId || null; const cycleId: string | null = this.rootStore?.cycle?.cycleId || null;
const issueType = this.getIssueType; const issueType = this.getIssueType;

View File

@ -1,7 +1,7 @@
import { action, makeObservable, runInAction } from "mobx"; import { action, makeObservable, runInAction } from "mobx";
// types // types
import { RootStore } from "../root"; import { RootStore } from "../root";
import { IIssueType } from "./cycle_issue.store"; import { IIssueType } from "store/issue";
export interface ICycleIssueCalendarViewStore { export interface ICycleIssueCalendarViewStore {
// actions // actions

View File

@ -6,15 +6,12 @@ import { IIssue } from "types";
// services // services
import { IssueService } from "services/issue"; import { IssueService } from "services/issue";
import { sortArrayByDate, sortArrayByPriority } from "constants/kanban-helpers"; import { sortArrayByDate, sortArrayByPriority } from "constants/kanban-helpers";
import {
export type IIssueType = "grouped" | "groupWithSubGroups" | "ungrouped"; IIssueGroupWithSubGroupsStructure,
export type IIssueGroupedStructure = { [group_id: string]: IIssue[] }; IIssueGroupedStructure,
export type IIssueGroupWithSubGroupsStructure = { IIssueType,
[group_id: string]: { IIssueUnGroupedStructure,
[sub_group_id: string]: IIssue[]; } from "store/issue";
};
};
export type IIssueUnGroupedStructure = IIssue[];
export interface IDraftIssueStore { export interface IDraftIssueStore {
loader: boolean; loader: boolean;

View File

@ -31,6 +31,7 @@ export interface IIssueStore {
// computed // computed
getIssueType: IIssueType | null; getIssueType: IIssueType | null;
getIssues: IIssueGroupedStructure | IIssueGroupWithSubGroupsStructure | IIssueUnGroupedStructure | null; getIssues: IIssueGroupedStructure | IIssueGroupWithSubGroupsStructure | IIssueUnGroupedStructure | null;
getIssuesCount: number;
// action // action
fetchIssues: (workspaceSlug: string, projectId: string) => Promise<any>; fetchIssues: (workspaceSlug: string, projectId: string) => Promise<any>;
updateIssueStructure: (group_id: string | null, sub_group_id: string | null, issue: IIssue) => void; updateIssueStructure: (group_id: string | null, sub_group_id: string | null, issue: IIssue) => void;
@ -68,6 +69,7 @@ export class IssueStore implements IIssueStore {
// computed // computed
getIssueType: computed, getIssueType: computed,
getIssues: computed, getIssues: computed,
getIssuesCount: computed,
// actions // actions
fetchIssues: action, fetchIssues: action,
updateIssueStructure: action, updateIssueStructure: action,
@ -120,6 +122,44 @@ export class IssueStore implements IIssueStore {
return this.issues?.[projectId]?.[issueType] || null; return this.issues?.[projectId]?.[issueType] || null;
} }
get getIssuesCount() {
const issueType = this.getIssueType;
let issuesCount = 0;
if (issueType === "grouped") {
const issues = this.getIssues as IIssueGroupedStructure;
if (!issues) return 0;
Object.keys(issues).map((group_id) => {
issuesCount += issues[group_id].length;
});
}
if (issueType === "groupWithSubGroups") {
const issues = this.getIssues as IIssueGroupWithSubGroupsStructure;
if (!issues) return 0;
Object.keys(issues).map((sub_group_id) => {
Object.keys(issues[sub_group_id]).map((group_id) => {
issuesCount += issues[sub_group_id][group_id].length;
});
});
}
if (issueType === "ungrouped") {
const issues = this.getIssues as IIssueUnGroupedStructure;
if (!issues) return 0;
issuesCount = issues.length;
}
return issuesCount;
}
updateIssueStructure = async (group_id: string | null, sub_group_id: string | null, issue: IIssue) => { updateIssueStructure = async (group_id: string | null, sub_group_id: string | null, issue: IIssue) => {
const projectId: string | null = issue?.project; const projectId: string | null = issue?.project;
const issueType = this.getIssueType; const issueType = this.getIssueType;

View File

@ -8,15 +8,12 @@ import { sortArrayByDate, sortArrayByPriority } from "constants/kanban-helpers";
// types // types
import { IIssue } from "types"; import { IIssue } from "types";
import { IBlockUpdateData } from "components/gantt-chart"; import { IBlockUpdateData } from "components/gantt-chart";
import {
export type IIssueType = "grouped" | "groupWithSubGroups" | "ungrouped"; IIssueGroupWithSubGroupsStructure,
export type IIssueGroupedStructure = { [group_id: string]: IIssue[] }; IIssueGroupedStructure,
export type IIssueGroupWithSubGroupsStructure = { IIssueType,
[group_id: string]: { IIssueUnGroupedStructure,
[sub_group_id: string]: IIssue[]; } from "store/issue";
};
};
export type IIssueUnGroupedStructure = IIssue[];
export interface IModuleIssueStore { export interface IModuleIssueStore {
loader: boolean; loader: boolean;
@ -32,6 +29,7 @@ export interface IModuleIssueStore {
// computed // computed
getIssueType: IIssueType | null; getIssueType: IIssueType | null;
getIssues: IIssueGroupedStructure | IIssueGroupWithSubGroupsStructure | IIssueUnGroupedStructure | null; getIssues: IIssueGroupedStructure | IIssueGroupWithSubGroupsStructure | IIssueUnGroupedStructure | null;
getIssuesCount: number;
// action // action
fetchIssues: (workspaceSlug: string, projectId: string, moduleId: string) => Promise<any>; fetchIssues: (workspaceSlug: string, projectId: string, moduleId: string) => Promise<any>;
updateIssueStructure: (group_id: string | null, sub_group_id: string | null, issue: IIssue) => void; updateIssueStructure: (group_id: string | null, sub_group_id: string | null, issue: IIssue) => void;
@ -76,6 +74,7 @@ export class ModuleIssueStore implements IModuleIssueStore {
// computed // computed
getIssueType: computed, getIssueType: computed,
getIssues: computed, getIssues: computed,
getIssuesCount: computed,
// actions // actions
fetchIssues: action, fetchIssues: action,
updateIssueStructure: action, updateIssueStructure: action,
@ -132,6 +131,44 @@ export class ModuleIssueStore implements IModuleIssueStore {
return this.issues?.[moduleId]?.[issueType] || null; return this.issues?.[moduleId]?.[issueType] || null;
} }
get getIssuesCount() {
const issueType = this.getIssueType;
let issuesCount = 0;
if (issueType === "grouped") {
const issues = this.getIssues as IIssueGroupedStructure;
if (!issues) return 0;
Object.keys(issues).map((group_id) => {
issuesCount += issues[group_id].length;
});
}
if (issueType === "groupWithSubGroups") {
const issues = this.getIssues as IIssueGroupWithSubGroupsStructure;
if (!issues) return 0;
Object.keys(issues).map((sub_group_id) => {
Object.keys(issues[sub_group_id]).map((group_id) => {
issuesCount += issues[sub_group_id][group_id].length;
});
});
}
if (issueType === "ungrouped") {
const issues = this.getIssues as IIssueUnGroupedStructure;
if (!issues) return 0;
issuesCount = issues.length;
}
return issuesCount;
}
updateIssueStructure = async (group_id: string | null, sub_group_id: string | null, issue: IIssue) => { updateIssueStructure = async (group_id: string | null, sub_group_id: string | null, issue: IIssue) => {
const moduleId: string | null = this.rootStore?.module?.moduleId; const moduleId: string | null = this.rootStore?.module?.moduleId;
const issueType = this.getIssueType; const issueType = this.getIssueType;

View File

@ -1,7 +1,7 @@
import { action, makeObservable, runInAction } from "mobx"; import { action, makeObservable, runInAction } from "mobx";
// types // types
import { RootStore } from "../root"; import { RootStore } from "../root";
import { IIssueType } from "./module_issue.store"; import { IIssueType } from "store/issue";
export interface IModuleIssueCalendarViewStore { export interface IModuleIssueCalendarViewStore {
// actions // actions

View File

@ -45,6 +45,7 @@ export interface IProjectViewIssuesStore {
// computed // computed
getIssues: IIssueGroupedStructure | IIssueGroupWithSubGroupsStructure | IIssueUnGroupedStructure | null; getIssues: IIssueGroupedStructure | IIssueGroupWithSubGroupsStructure | IIssueUnGroupedStructure | null;
getIssuesCount: number;
getIssueType: IIssueType | null; getIssueType: IIssueType | null;
} }
@ -86,6 +87,7 @@ export class ProjectViewIssuesStore implements IProjectViewIssuesStore {
// computed // computed
getIssueType: computed, getIssueType: computed,
getIssues: computed, getIssues: computed,
getIssuesCount: computed,
}); });
this.rootStore = _rootStore; this.rootStore = _rootStore;
@ -147,6 +149,44 @@ export class ProjectViewIssuesStore implements IProjectViewIssuesStore {
return this.viewIssues?.[viewId]?.[issueType] || null; return this.viewIssues?.[viewId]?.[issueType] || null;
} }
get getIssuesCount() {
const issueType = this.rootStore.issue.getIssueType;
let issuesCount = 0;
if (issueType === "grouped") {
const issues = this.getIssues as IIssueGroupedStructure;
if (!issues) return 0;
Object.keys(issues).map((group_id) => {
issuesCount += issues[group_id].length;
});
}
if (issueType === "groupWithSubGroups") {
const issues = this.getIssues as IIssueGroupWithSubGroupsStructure;
if (!issues) return 0;
Object.keys(issues).map((sub_group_id) => {
Object.keys(issues[sub_group_id]).map((group_id) => {
issuesCount += issues[sub_group_id][group_id].length;
});
});
}
if (issueType === "ungrouped") {
const issues = this.getIssues as IIssueUnGroupedStructure;
if (!issues) return 0;
issuesCount = issues.length;
}
return issuesCount;
}
updateIssueStructure = async (group_id: string | null, sub_group_id: string | null, issue: IIssue) => { updateIssueStructure = async (group_id: string | null, sub_group_id: string | null, issue: IIssue) => {
const viewId: string | null = this.rootStore.projectViews.viewId; const viewId: string | null = this.rootStore.projectViews.viewId;
const issueType = this.rootStore.issue.getIssueType; const issueType = this.rootStore.issue.getIssueType;