forked from github/plane
dev: implemented the new project issues store with grouped, subGrouped and unGrouped issue computed functions
This commit is contained in:
parent
a6567bbce4
commit
e5343595f6
@ -1,4 +1,4 @@
|
||||
import { useState } from "react";
|
||||
import { useEffect, useState } from "react";
|
||||
import Image from "next/image";
|
||||
import { useRouter } from "next/router";
|
||||
import useSWR from "swr";
|
||||
@ -19,7 +19,6 @@ export const WorkspaceDashboardView = observer(() => {
|
||||
const { workspaceSlug } = router.query;
|
||||
// store
|
||||
const { user: userStore, project: projectStore, commandPalette: commandPaletteStore } = useMobxStore();
|
||||
|
||||
const user = userStore.currentUser;
|
||||
const projects = workspaceSlug ? projectStore.projects[workspaceSlug.toString()] : null;
|
||||
const workspaceDashboardInfo = userStore.dashboardInfo;
|
||||
|
@ -3,6 +3,7 @@ import { APIService } from "services/api.service";
|
||||
import { TrackEventService } from "services/track_event.service";
|
||||
// type
|
||||
import type { IUser, IIssue, IIssueActivity, ISubIssueResponse, IIssueDisplayProperties } from "types";
|
||||
import type { IIssueResponse } from "store/project-issues";
|
||||
// helper
|
||||
import { API_BASE_URL } from "helpers/common.helper";
|
||||
|
||||
@ -32,6 +33,16 @@ export class IssueService extends APIService {
|
||||
});
|
||||
}
|
||||
|
||||
async getV3Issues(workspaceSlug: string, projectId: string, queries?: any): Promise<IIssueResponse> {
|
||||
return this.get(`/api/v3/workspaces/${workspaceSlug}/projects/${projectId}/issues/`, {
|
||||
params: queries,
|
||||
})
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async getIssuesWithParams(
|
||||
workspaceSlug: string,
|
||||
projectId: string,
|
||||
|
209
web/store/project-issues.ts
Normal file
209
web/store/project-issues.ts
Normal file
@ -0,0 +1,209 @@
|
||||
import { action, observable, makeObservable, computed, runInAction } from "mobx";
|
||||
// services
|
||||
import { IssueService } from "services/issue/issue.service";
|
||||
// constants
|
||||
import { ISSUE_PRIORITIES, ISSUE_STATE_GROUPS } from "constants/issue";
|
||||
// types
|
||||
import { IIssue, IState, TIssueGroupByOptions } from "types";
|
||||
import { RootStore } from "store/root";
|
||||
|
||||
export interface IGroupedIssues {
|
||||
[group_id: string]: string[];
|
||||
}
|
||||
|
||||
export interface ISubGroupedIssues {
|
||||
[sub_grouped_id: string]: {
|
||||
[group_id: string]: string[];
|
||||
};
|
||||
}
|
||||
|
||||
export type TUnGroupedIssues = string[];
|
||||
|
||||
export interface IIssueResponse {
|
||||
[issue_id: string]: IIssue;
|
||||
}
|
||||
|
||||
enum issueGroupByKeys {
|
||||
state = "state",
|
||||
"state_detail.group" = "state_detail.group",
|
||||
priority = "priority",
|
||||
labels = "labels",
|
||||
created_by = "created_by",
|
||||
project = "project",
|
||||
assignees = "assignees",
|
||||
mentions = "assignees",
|
||||
}
|
||||
|
||||
export interface IProjectIssueStore {
|
||||
loader: "init-loader" | "mutation" | null;
|
||||
projectId: string | undefined;
|
||||
issues:
|
||||
| {
|
||||
[project_id: string]: {
|
||||
[issue_id: string]: IIssue;
|
||||
};
|
||||
}
|
||||
| undefined;
|
||||
|
||||
// computed
|
||||
groupedIssues: IGroupedIssues | undefined;
|
||||
subGroupedIssues: ISubGroupedIssues | undefined;
|
||||
unGroupedIssues: TUnGroupedIssues | undefined;
|
||||
|
||||
// actions
|
||||
fetchProjectIssues: (workspaceSlug: string, projectId: string) => Promise<IIssueResponse> | undefined;
|
||||
}
|
||||
|
||||
export class ProjectIssueStore implements IProjectIssueStore {
|
||||
loader: "init-loader" | "mutation" | null = null;
|
||||
projectId: string | undefined = undefined;
|
||||
issues:
|
||||
| {
|
||||
[project_id: string]: {
|
||||
[issue_id: string]: IIssue;
|
||||
};
|
||||
}
|
||||
| undefined = undefined;
|
||||
// root store
|
||||
rootStore;
|
||||
// service
|
||||
issueService;
|
||||
|
||||
constructor(_rootStore: RootStore | null = null) {
|
||||
makeObservable(this, {
|
||||
// observable
|
||||
loader: observable.ref,
|
||||
projectId: observable.ref,
|
||||
issues: observable.ref,
|
||||
// computed
|
||||
groupedIssues: computed,
|
||||
subGroupedIssues: computed,
|
||||
unGroupedIssues: computed,
|
||||
// action
|
||||
fetchProjectIssues: action,
|
||||
});
|
||||
|
||||
this.rootStore = _rootStore;
|
||||
this.issueService = new IssueService();
|
||||
}
|
||||
|
||||
get groupedIssues() {
|
||||
const groupBy: TIssueGroupByOptions | undefined = this.rootStore?.issueFilter.userDisplayFilters.group_by;
|
||||
const projectId: string | undefined | null = this.rootStore?.project.projectId;
|
||||
|
||||
if (!groupBy || !projectId || !this.issues || !this.issues[projectId]) return undefined;
|
||||
|
||||
const displayFiltersDefaultData: { [filter_key: string]: string[] } = {
|
||||
state: (this.rootStore?.projectState?.states?.[projectId] ?? []).map((i: IState) => i.id),
|
||||
"state_detail.group": ISSUE_STATE_GROUPS.map((i) => i.key),
|
||||
priority: ISSUE_PRIORITIES.map((i) => i.key),
|
||||
labels: [...(this.rootStore?.project?.projectLabels ?? []).map((i) => i.id), "None"],
|
||||
created_by: (this.rootStore?.project?.projectMembers ?? []).map((i) => i.member.id),
|
||||
project: (this.rootStore?.project.workspaceProjects ?? []).map((i) => i.id),
|
||||
assignees: [...(this.rootStore?.project?.projectMembers ?? []).map((i) => i.member.id), "None"],
|
||||
};
|
||||
|
||||
const issues: { [group_id: string]: string[] } = {};
|
||||
displayFiltersDefaultData[groupBy].forEach((group) => {
|
||||
issues[group] = [];
|
||||
});
|
||||
|
||||
const projectIssues = this.issues[projectId];
|
||||
|
||||
for (const issue in projectIssues) {
|
||||
const _issue = projectIssues[issue];
|
||||
const groupArray = this.getGroupArray(_issue[issueGroupByKeys[groupBy] as keyof IIssue]);
|
||||
|
||||
for (const group of groupArray) {
|
||||
if (group && issues[group]) {
|
||||
issues[group].push(_issue.id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return issues;
|
||||
}
|
||||
|
||||
get subGroupedIssues() {
|
||||
const subGroupBy: TIssueGroupByOptions | undefined = this.rootStore?.issueFilter.userDisplayFilters.sub_group_by;
|
||||
const groupBy: TIssueGroupByOptions | undefined = this.rootStore?.issueFilter.userDisplayFilters.group_by;
|
||||
const projectId: string | undefined | null = this.rootStore?.project.projectId;
|
||||
|
||||
if (!subGroupBy || !groupBy || !projectId || !this.issues || !this.issues[projectId]) return undefined;
|
||||
|
||||
const displayFiltersDefaultData: { [filter_key: string]: string[] } = {
|
||||
state: (this.rootStore?.projectState?.states?.[projectId] ?? []).map((i: IState) => i.id),
|
||||
"state_detail.group": ISSUE_STATE_GROUPS.map((i) => i.key),
|
||||
priority: ISSUE_PRIORITIES.map((i) => i.key),
|
||||
labels: [...(this.rootStore?.project?.projectLabels ?? []).map((i) => i.id), "None"],
|
||||
created_by: (this.rootStore?.project?.projectMembers ?? []).map((i) => i.member.id),
|
||||
project: (this.rootStore?.project.workspaceProjects ?? []).map((i) => i.id),
|
||||
assignees: [...(this.rootStore?.project?.projectMembers ?? []).map((i) => i.member.id), "None"],
|
||||
};
|
||||
|
||||
const issues: { [sub_group_id: string]: { [group_id: string]: string[] } } = {};
|
||||
displayFiltersDefaultData[subGroupBy].forEach((sub_group: any) => {
|
||||
const groupByIssues: { [group_id: string]: string[] } = {};
|
||||
displayFiltersDefaultData[groupBy].forEach((group) => {
|
||||
groupByIssues[group] = [];
|
||||
});
|
||||
issues[sub_group] = groupByIssues;
|
||||
});
|
||||
|
||||
const projectIssues = this.issues[projectId];
|
||||
|
||||
for (const issue in projectIssues) {
|
||||
const _issue = projectIssues[issue];
|
||||
const subGroupArray = this.getGroupArray(_issue[issueGroupByKeys[subGroupBy] as keyof IIssue]);
|
||||
const groupArray = this.getGroupArray(_issue[issueGroupByKeys[groupBy] as keyof IIssue]);
|
||||
|
||||
for (const subGroup of subGroupArray) {
|
||||
for (const group of groupArray) {
|
||||
if (subGroup && group && issues[subGroup]) {
|
||||
issues[subGroup][group].push(_issue.id);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return issues;
|
||||
}
|
||||
|
||||
get unGroupedIssues() {
|
||||
if (!this.projectId || !this.issues || !this.issues[this.projectId]) return undefined;
|
||||
return Object.keys(this.issues[this.projectId]);
|
||||
}
|
||||
|
||||
fetchProjectIssues = async (workspaceSlug: string, projectId: string) => {
|
||||
try {
|
||||
this.projectId = projectId;
|
||||
this.rootStore?.project.setProjectId(projectId);
|
||||
|
||||
const response = await this.issueService.getV3Issues(workspaceSlug, projectId);
|
||||
const _issues = {
|
||||
...this.issues,
|
||||
[projectId]: { ...response },
|
||||
};
|
||||
|
||||
runInAction(() => {
|
||||
this.issues = _issues;
|
||||
});
|
||||
|
||||
return response;
|
||||
} catch (error) {
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
* @description this function helps to convert the typeof value (array | string | null) to array and returns an array
|
||||
*/
|
||||
getGroupArray(value: string[] | string | null) {
|
||||
if (Array.isArray(value)) {
|
||||
return value;
|
||||
} else {
|
||||
return [value || "None"];
|
||||
}
|
||||
}
|
||||
}
|
@ -108,6 +108,9 @@ import {
|
||||
InboxStore,
|
||||
} from "store/inbox";
|
||||
|
||||
// v3
|
||||
import { ProjectIssueStore, IProjectIssueStore } from "store/project-issues";
|
||||
|
||||
import { IMentionsStore, MentionsStore } from "store/editor";
|
||||
|
||||
enableStaticRendering(typeof window === "undefined");
|
||||
@ -176,6 +179,8 @@ export class RootStore {
|
||||
|
||||
mentionsStore: IMentionsStore;
|
||||
|
||||
projectIssues: IProjectIssueStore;
|
||||
|
||||
constructor() {
|
||||
this.appConfig = new AppConfigStore(this);
|
||||
this.commandPalette = new CommandPaletteStore(this);
|
||||
@ -239,5 +244,7 @@ export class RootStore {
|
||||
this.inboxFilters = new InboxFiltersStore(this);
|
||||
|
||||
this.mentionsStore = new MentionsStore(this);
|
||||
|
||||
this.projectIssues = new ProjectIssueStore(this);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user