[WEB-419] feat: manual issue archival (#3801)
* fix: issue archive without automation * fix: unarchive issue endpoint change * chore: archiving logic implemented in the quick-actions dropdowns * chore: peek overview archive button * chore: issue archive completed at state * chore: updated archiving icon and added archive option everywhere * chore: all issues quick actions dropdown * chore: archive and unarchive response * fix: archival mutation * fix: restore issue from peek overview * chore: update notification content for archive/restore * refactor: activity user name * fix: all issues mutation * fix: restore issue auth * chore: close peek overview on archival --------- Co-authored-by: NarayanBavisetti <narayan3119@gmail.com> Co-authored-by: gurusainath <gurusainath007@gmail.com>
This commit is contained in:
parent
b1520783cf
commit
30cc923fdb
77 changed files with 1402 additions and 691 deletions
|
|
@ -1,5 +1,6 @@
|
|||
import { action, observable, makeObservable, computed, runInAction } from "mobx";
|
||||
import set from "lodash/set";
|
||||
import pull from "lodash/pull";
|
||||
// base class
|
||||
import { IssueHelperStore } from "../helpers/issue-helper.store";
|
||||
// services
|
||||
|
|
@ -18,7 +19,7 @@ export interface IArchivedIssues {
|
|||
// actions
|
||||
fetchIssues: (workspaceSlug: string, projectId: string, loadType: TLoader) => Promise<TIssue>;
|
||||
removeIssue: (workspaceSlug: string, projectId: string, issueId: string) => Promise<void>;
|
||||
removeIssueFromArchived: (workspaceSlug: string, projectId: string, issueId: string) => Promise<void>;
|
||||
restoreIssue: (workspaceSlug: string, projectId: string, issueId: string) => Promise<void>;
|
||||
quickAddIssue: undefined;
|
||||
}
|
||||
|
||||
|
|
@ -48,7 +49,7 @@ export class ArchivedIssues extends IssueHelperStore implements IArchivedIssues
|
|||
// action
|
||||
fetchIssues: action,
|
||||
removeIssue: action,
|
||||
removeIssueFromArchived: action,
|
||||
restoreIssue: action,
|
||||
});
|
||||
// root store
|
||||
this.rootIssueStore = _rootStore;
|
||||
|
|
@ -70,7 +71,7 @@ export class ArchivedIssues extends IssueHelperStore implements IArchivedIssues
|
|||
const archivedIssueIds = this.issues[projectId];
|
||||
if (!archivedIssueIds) return undefined;
|
||||
|
||||
const _issues = this.rootIssueStore.issues.getIssuesByIds(archivedIssueIds);
|
||||
const _issues = this.rootIssueStore.issues.getIssuesByIds(archivedIssueIds, "archived");
|
||||
if (!_issues) return [];
|
||||
|
||||
let issues: TGroupedIssues | TSubGroupedIssues | TUnGroupedIssues | undefined = undefined;
|
||||
|
|
@ -113,25 +114,24 @@ export class ArchivedIssues extends IssueHelperStore implements IArchivedIssues
|
|||
try {
|
||||
await this.rootIssueStore.projectIssues.removeIssue(workspaceSlug, projectId, issueId);
|
||||
|
||||
const issueIndex = this.issues[projectId].findIndex((_issueId) => _issueId === issueId);
|
||||
if (issueIndex >= 0)
|
||||
runInAction(() => {
|
||||
this.issues[projectId].splice(issueIndex, 1);
|
||||
});
|
||||
runInAction(() => {
|
||||
pull(this.issues[projectId], issueId);
|
||||
});
|
||||
} catch (error) {
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
removeIssueFromArchived = async (workspaceSlug: string, projectId: string, issueId: string) => {
|
||||
restoreIssue = async (workspaceSlug: string, projectId: string, issueId: string) => {
|
||||
try {
|
||||
const response = await this.archivedIssueService.unarchiveIssue(workspaceSlug, projectId, issueId);
|
||||
const response = await this.archivedIssueService.restoreIssue(workspaceSlug, projectId, issueId);
|
||||
|
||||
const issueIndex = this.issues[projectId]?.findIndex((_issueId) => _issueId === issueId);
|
||||
if (issueIndex && issueIndex >= 0)
|
||||
runInAction(() => {
|
||||
this.issues[projectId].splice(issueIndex, 1);
|
||||
runInAction(() => {
|
||||
this.rootStore.issues.updateIssue(issueId, {
|
||||
archived_at: null,
|
||||
});
|
||||
pull(this.issues[projectId], issueId);
|
||||
});
|
||||
|
||||
return response;
|
||||
} catch (error) {
|
||||
|
|
|
|||
|
|
@ -48,6 +48,12 @@ export interface ICycleIssues {
|
|||
issueId: string,
|
||||
cycleId?: string | undefined
|
||||
) => Promise<void>;
|
||||
archiveIssue: (
|
||||
workspaceSlug: string,
|
||||
projectId: string,
|
||||
issueId: string,
|
||||
cycleId?: string | undefined
|
||||
) => Promise<void>;
|
||||
quickAddIssue: (
|
||||
workspaceSlug: string,
|
||||
projectId: string,
|
||||
|
|
@ -100,6 +106,7 @@ export class CycleIssues extends IssueHelperStore implements ICycleIssues {
|
|||
createIssue: action,
|
||||
updateIssue: action,
|
||||
removeIssue: action,
|
||||
archiveIssue: action,
|
||||
quickAddIssue: action,
|
||||
addIssueToCycle: action,
|
||||
removeIssueFromCycle: action,
|
||||
|
|
@ -127,7 +134,7 @@ export class CycleIssues extends IssueHelperStore implements ICycleIssues {
|
|||
const cycleIssueIds = this.issues[cycleId];
|
||||
if (!cycleIssueIds) return;
|
||||
|
||||
const _issues = this.rootIssueStore.issues.getIssuesByIds(cycleIssueIds);
|
||||
const _issues = this.rootIssueStore.issues.getIssuesByIds(cycleIssueIds, "un-archived");
|
||||
if (!_issues) return [];
|
||||
|
||||
let issues: TGroupedIssues | TSubGroupedIssues | TUnGroupedIssues = [];
|
||||
|
|
@ -237,6 +244,26 @@ export class CycleIssues extends IssueHelperStore implements ICycleIssues {
|
|||
}
|
||||
};
|
||||
|
||||
archiveIssue = async (
|
||||
workspaceSlug: string,
|
||||
projectId: string,
|
||||
issueId: string,
|
||||
cycleId: string | undefined = undefined
|
||||
) => {
|
||||
try {
|
||||
if (!cycleId) throw new Error("Cycle Id is required");
|
||||
|
||||
await this.rootIssueStore.projectIssues.archiveIssue(workspaceSlug, projectId, issueId);
|
||||
this.rootIssueStore.rootStore.cycle.fetchCycleDetails(workspaceSlug, projectId, cycleId);
|
||||
|
||||
runInAction(() => {
|
||||
pull(this.issues[cycleId], issueId);
|
||||
});
|
||||
} catch (error) {
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
quickAddIssue = async (
|
||||
workspaceSlug: string,
|
||||
projectId: string,
|
||||
|
|
|
|||
|
|
@ -81,7 +81,7 @@ export class DraftIssues extends IssueHelperStore implements IDraftIssues {
|
|||
const draftIssueIds = this.issues[projectId];
|
||||
if (!draftIssueIds) return undefined;
|
||||
|
||||
const _issues = this.rootIssueStore.issues.getIssuesByIds(draftIssueIds);
|
||||
const _issues = this.rootIssueStore.issues.getIssuesByIds(draftIssueIds, "un-archived");
|
||||
if (!_issues) return [];
|
||||
|
||||
let issues: TGroupedIssues | TSubGroupedIssues | TUnGroupedIssues | undefined = undefined;
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ export interface IIssueStoreActions {
|
|||
) => Promise<TIssue>;
|
||||
updateIssue: (workspaceSlug: string, projectId: string, issueId: string, data: Partial<TIssue>) => Promise<void>;
|
||||
removeIssue: (workspaceSlug: string, projectId: string, issueId: string) => Promise<void>;
|
||||
archiveIssue: (workspaceSlug: string, projectId: string, issueId: string) => Promise<void>;
|
||||
addIssueToCycle: (workspaceSlug: string, projectId: string, cycleId: string, issueIds: string[]) => Promise<void>;
|
||||
removeIssueFromCycle: (workspaceSlug: string, projectId: string, cycleId: string, issueId: string) => Promise<TIssue>;
|
||||
addModulesToIssue: (workspaceSlug: string, projectId: string, issueId: string, moduleIds: string[]) => Promise<any>;
|
||||
|
|
@ -156,6 +157,9 @@ export class IssueStore implements IIssueStore {
|
|||
removeIssue = async (workspaceSlug: string, projectId: string, issueId: string) =>
|
||||
this.rootIssueDetailStore.rootIssueStore.projectIssues.removeIssue(workspaceSlug, projectId, issueId);
|
||||
|
||||
archiveIssue = async (workspaceSlug: string, projectId: string, issueId: string) =>
|
||||
this.rootIssueDetailStore.rootIssueStore.projectIssues.archiveIssue(workspaceSlug, projectId, issueId);
|
||||
|
||||
addIssueToCycle = async (workspaceSlug: string, projectId: string, cycleId: string, issueIds: string[]) => {
|
||||
await this.rootIssueDetailStore.rootIssueStore.cycleIssues.addIssueToCycle(
|
||||
workspaceSlug,
|
||||
|
|
|
|||
|
|
@ -47,6 +47,7 @@ export interface IIssueDetail
|
|||
isIssueLinkModalOpen: boolean;
|
||||
isParentIssueModalOpen: boolean;
|
||||
isDeleteIssueModalOpen: boolean;
|
||||
isArchiveIssueModalOpen: boolean;
|
||||
isRelationModalOpen: TIssueRelationTypes | null;
|
||||
// computed
|
||||
isAnyModalOpen: boolean;
|
||||
|
|
@ -55,6 +56,7 @@ export interface IIssueDetail
|
|||
toggleIssueLinkModal: (value: boolean) => void;
|
||||
toggleParentIssueModal: (value: boolean) => void;
|
||||
toggleDeleteIssueModal: (value: boolean) => void;
|
||||
toggleArchiveIssueModal: (value: boolean) => void;
|
||||
toggleRelationModal: (value: TIssueRelationTypes | null) => void;
|
||||
// store
|
||||
rootIssueStore: IIssueRootStore;
|
||||
|
|
@ -76,6 +78,7 @@ export class IssueDetail implements IIssueDetail {
|
|||
isIssueLinkModalOpen: boolean = false;
|
||||
isParentIssueModalOpen: boolean = false;
|
||||
isDeleteIssueModalOpen: boolean = false;
|
||||
isArchiveIssueModalOpen: boolean = false;
|
||||
isRelationModalOpen: TIssueRelationTypes | null = null;
|
||||
// store
|
||||
rootIssueStore: IIssueRootStore;
|
||||
|
|
@ -97,6 +100,7 @@ export class IssueDetail implements IIssueDetail {
|
|||
isIssueLinkModalOpen: observable.ref,
|
||||
isParentIssueModalOpen: observable.ref,
|
||||
isDeleteIssueModalOpen: observable.ref,
|
||||
isArchiveIssueModalOpen: observable.ref,
|
||||
isRelationModalOpen: observable.ref,
|
||||
// computed
|
||||
isAnyModalOpen: computed,
|
||||
|
|
@ -105,6 +109,7 @@ export class IssueDetail implements IIssueDetail {
|
|||
toggleIssueLinkModal: action,
|
||||
toggleParentIssueModal: action,
|
||||
toggleDeleteIssueModal: action,
|
||||
toggleArchiveIssueModal: action,
|
||||
toggleRelationModal: action,
|
||||
});
|
||||
|
||||
|
|
@ -128,6 +133,7 @@ export class IssueDetail implements IIssueDetail {
|
|||
this.isIssueLinkModalOpen ||
|
||||
this.isParentIssueModalOpen ||
|
||||
this.isDeleteIssueModalOpen ||
|
||||
this.isArchiveIssueModalOpen ||
|
||||
Boolean(this.isRelationModalOpen)
|
||||
);
|
||||
}
|
||||
|
|
@ -137,6 +143,7 @@ export class IssueDetail implements IIssueDetail {
|
|||
toggleIssueLinkModal = (value: boolean) => (this.isIssueLinkModalOpen = value);
|
||||
toggleParentIssueModal = (value: boolean) => (this.isParentIssueModalOpen = value);
|
||||
toggleDeleteIssueModal = (value: boolean) => (this.isDeleteIssueModalOpen = value);
|
||||
toggleArchiveIssueModal = (value: boolean) => (this.isArchiveIssueModalOpen = value);
|
||||
toggleRelationModal = (value: TIssueRelationTypes | null) => (this.isRelationModalOpen = value);
|
||||
|
||||
// issue
|
||||
|
|
@ -150,6 +157,8 @@ export class IssueDetail implements IIssueDetail {
|
|||
this.issue.updateIssue(workspaceSlug, projectId, issueId, data);
|
||||
removeIssue = async (workspaceSlug: string, projectId: string, issueId: string) =>
|
||||
this.issue.removeIssue(workspaceSlug, projectId, issueId);
|
||||
archiveIssue = async (workspaceSlug: string, projectId: string, issueId: string) =>
|
||||
this.issue.archiveIssue(workspaceSlug, projectId, issueId);
|
||||
addIssueToCycle = async (workspaceSlug: string, projectId: string, cycleId: string, issueIds: string[]) =>
|
||||
this.issue.addIssueToCycle(workspaceSlug, projectId, cycleId, issueIds);
|
||||
removeIssueFromCycle = async (workspaceSlug: string, projectId: string, cycleId: string, issueId: string) =>
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ export type IIssueStore = {
|
|||
removeIssue(issueId: string): void;
|
||||
// helper methods
|
||||
getIssueById(issueId: string): undefined | TIssue;
|
||||
getIssuesByIds(issueIds: string[]): undefined | Record<string, TIssue>; // Record defines issue_id as key and TIssue as value
|
||||
getIssuesByIds(issueIds: string[], type: "archived" | "un-archived"): undefined | Record<string, TIssue>; // Record defines issue_id as key and TIssue as value
|
||||
};
|
||||
|
||||
export class IssueStore implements IIssueStore {
|
||||
|
|
@ -108,14 +108,17 @@ export class IssueStore implements IIssueStore {
|
|||
/**
|
||||
* @description This method will return the issues from the issuesMap
|
||||
* @param {string[]} issueIds
|
||||
* @param {boolean} archivedIssues
|
||||
* @returns {Record<string, TIssue> | undefined}
|
||||
*/
|
||||
getIssuesByIds = computedFn((issueIds: string[]) => {
|
||||
getIssuesByIds = computedFn((issueIds: string[], type: "archived" | "un-archived") => {
|
||||
if (!issueIds || issueIds.length <= 0 || isEmpty(this.issuesMap)) return undefined;
|
||||
const filteredIssues: { [key: string]: TIssue } = {};
|
||||
Object.values(this.issuesMap).forEach((issue) => {
|
||||
if (issueIds.includes(issue.id)) {
|
||||
filteredIssues[issue.id] = issue;
|
||||
// if type is archived then check archived_at is not null
|
||||
// if type is un-archived then check archived_at is null
|
||||
if ((type === "archived" && issue.archived_at) || (type === "un-archived" && !issue.archived_at)) {
|
||||
if (issueIds.includes(issue.id)) filteredIssues[issue.id] = issue;
|
||||
}
|
||||
});
|
||||
return isEmpty(filteredIssues) ? undefined : filteredIssues;
|
||||
|
|
|
|||
|
|
@ -46,6 +46,12 @@ export interface IModuleIssues {
|
|||
issueId: string,
|
||||
moduleId?: string | undefined
|
||||
) => Promise<void>;
|
||||
archiveIssue: (
|
||||
workspaceSlug: string,
|
||||
projectId: string,
|
||||
issueId: string,
|
||||
moduleId?: string | undefined
|
||||
) => Promise<void>;
|
||||
quickAddIssue: (
|
||||
workspaceSlug: string,
|
||||
projectId: string,
|
||||
|
|
@ -103,6 +109,7 @@ export class ModuleIssues extends IssueHelperStore implements IModuleIssues {
|
|||
createIssue: action,
|
||||
updateIssue: action,
|
||||
removeIssue: action,
|
||||
archiveIssue: action,
|
||||
quickAddIssue: action,
|
||||
addIssuesToModule: action,
|
||||
removeIssuesFromModule: action,
|
||||
|
|
@ -131,7 +138,7 @@ export class ModuleIssues extends IssueHelperStore implements IModuleIssues {
|
|||
const moduleIssueIds = this.issues[moduleId];
|
||||
if (!moduleIssueIds) return;
|
||||
|
||||
const _issues = this.rootIssueStore.issues.getIssuesByIds(moduleIssueIds);
|
||||
const _issues = this.rootIssueStore.issues.getIssuesByIds(moduleIssueIds, "un-archived");
|
||||
if (!_issues) return [];
|
||||
|
||||
let issues: TGroupedIssues | TSubGroupedIssues | TUnGroupedIssues = [];
|
||||
|
|
@ -242,6 +249,26 @@ export class ModuleIssues extends IssueHelperStore implements IModuleIssues {
|
|||
}
|
||||
};
|
||||
|
||||
archiveIssue = async (
|
||||
workspaceSlug: string,
|
||||
projectId: string,
|
||||
issueId: string,
|
||||
moduleId: string | undefined = undefined
|
||||
) => {
|
||||
try {
|
||||
if (!moduleId) throw new Error("Module Id is required");
|
||||
|
||||
await this.rootIssueStore.projectIssues.archiveIssue(workspaceSlug, projectId, issueId);
|
||||
this.rootIssueStore.rootStore.module.fetchModuleDetails(workspaceSlug, projectId, moduleId);
|
||||
|
||||
runInAction(() => {
|
||||
pull(this.issues[moduleId], issueId);
|
||||
});
|
||||
} catch (error) {
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
quickAddIssue = async (
|
||||
workspaceSlug: string,
|
||||
projectId: string,
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import { action, observable, makeObservable, computed, runInAction } from "mobx";
|
||||
import set from "lodash/set";
|
||||
import pull from "lodash/pull";
|
||||
// base class
|
||||
import { IssueHelperStore } from "../helpers/issue-helper.store";
|
||||
// services
|
||||
|
|
@ -48,6 +49,12 @@ export interface IProfileIssues {
|
|||
issueId: string,
|
||||
userId?: string | undefined
|
||||
) => Promise<void>;
|
||||
archiveIssue: (
|
||||
workspaceSlug: string,
|
||||
projectId: string,
|
||||
issueId: string,
|
||||
userId?: string | undefined
|
||||
) => Promise<void>;
|
||||
quickAddIssue: undefined;
|
||||
}
|
||||
|
||||
|
|
@ -77,6 +84,7 @@ export class ProfileIssues extends IssueHelperStore implements IProfileIssues {
|
|||
createIssue: action,
|
||||
updateIssue: action,
|
||||
removeIssue: action,
|
||||
archiveIssue: action,
|
||||
});
|
||||
// root store
|
||||
this.rootIssueStore = _rootStore;
|
||||
|
|
@ -104,7 +112,7 @@ export class ProfileIssues extends IssueHelperStore implements IProfileIssues {
|
|||
|
||||
if (!userIssueIds) return;
|
||||
|
||||
const _issues = this.rootStore.issues.getIssuesByIds(userIssueIds);
|
||||
const _issues = this.rootStore.issues.getIssuesByIds(userIssueIds, "un-archived");
|
||||
if (!_issues) return [];
|
||||
|
||||
let issues: TGroupedIssues | TSubGroupedIssues | TUnGroupedIssues | undefined = undefined;
|
||||
|
|
@ -249,4 +257,24 @@ export class ProfileIssues extends IssueHelperStore implements IProfileIssues {
|
|||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
archiveIssue = async (
|
||||
workspaceSlug: string,
|
||||
projectId: string,
|
||||
issueId: string,
|
||||
userId: string | undefined = undefined
|
||||
) => {
|
||||
if (!userId) return;
|
||||
try {
|
||||
await this.rootIssueStore.projectIssues.archiveIssue(workspaceSlug, projectId, issueId);
|
||||
|
||||
const uniqueViewId = `${workspaceSlug}_${this.currentView}`;
|
||||
|
||||
runInAction(() => {
|
||||
pull(this.issues[userId][uniqueViewId], issueId);
|
||||
});
|
||||
} catch (error) {
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import { action, observable, makeObservable, computed, runInAction } from "mobx";
|
||||
import set from "lodash/set";
|
||||
import pull from "lodash/pull";
|
||||
// base class
|
||||
import { IssueHelperStore } from "../helpers/issue-helper.store";
|
||||
// services
|
||||
|
|
@ -41,6 +42,12 @@ export interface IProjectViewIssues {
|
|||
issueId: string,
|
||||
viewId?: string | undefined
|
||||
) => Promise<void>;
|
||||
archiveIssue: (
|
||||
workspaceSlug: string,
|
||||
projectId: string,
|
||||
issueId: string,
|
||||
viewId?: string | undefined
|
||||
) => Promise<void>;
|
||||
quickAddIssue: (
|
||||
workspaceSlug: string,
|
||||
projectId: string,
|
||||
|
|
@ -75,6 +82,7 @@ export class ProjectViewIssues extends IssueHelperStore implements IProjectViewI
|
|||
createIssue: action,
|
||||
updateIssue: action,
|
||||
removeIssue: action,
|
||||
archiveIssue: action,
|
||||
quickAddIssue: action,
|
||||
});
|
||||
// root store
|
||||
|
|
@ -98,7 +106,7 @@ export class ProjectViewIssues extends IssueHelperStore implements IProjectViewI
|
|||
const viewIssueIds = this.issues[viewId];
|
||||
if (!viewIssueIds) return;
|
||||
|
||||
const _issues = this.rootStore.issues.getIssuesByIds(viewIssueIds);
|
||||
const _issues = this.rootStore.issues.getIssuesByIds(viewIssueIds, "un-archived");
|
||||
if (!_issues) return [];
|
||||
|
||||
let issues: TGroupedIssues | TSubGroupedIssues | TUnGroupedIssues = [];
|
||||
|
|
@ -210,6 +218,26 @@ export class ProjectViewIssues extends IssueHelperStore implements IProjectViewI
|
|||
}
|
||||
};
|
||||
|
||||
archiveIssue = async (
|
||||
workspaceSlug: string,
|
||||
projectId: string,
|
||||
issueId: string,
|
||||
viewId: string | undefined = undefined
|
||||
) => {
|
||||
try {
|
||||
if (!viewId) throw new Error("View Id is required");
|
||||
|
||||
await this.rootIssueStore.projectIssues.archiveIssue(workspaceSlug, projectId, issueId);
|
||||
|
||||
runInAction(() => {
|
||||
pull(this.issues[viewId], issueId);
|
||||
});
|
||||
} catch (error) {
|
||||
this.fetchIssues(workspaceSlug, projectId, "mutation");
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
quickAddIssue = async (
|
||||
workspaceSlug: string,
|
||||
projectId: string,
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ import concat from "lodash/concat";
|
|||
// base class
|
||||
import { IssueHelperStore } from "../helpers/issue-helper.store";
|
||||
// services
|
||||
import { IssueService } from "services/issue/issue.service";
|
||||
import { IssueService, IssueArchiveService } from "services/issue";
|
||||
// types
|
||||
import { IIssueRootStore } from "../root.store";
|
||||
import { TIssue, TGroupedIssues, TSubGroupedIssues, TLoader, TUnGroupedIssues, ViewFlags } from "@plane/types";
|
||||
|
|
@ -23,6 +23,7 @@ export interface IProjectIssues {
|
|||
createIssue: (workspaceSlug: string, projectId: string, data: Partial<TIssue>) => Promise<TIssue>;
|
||||
updateIssue: (workspaceSlug: string, projectId: string, issueId: string, data: Partial<TIssue>) => Promise<void>;
|
||||
removeIssue: (workspaceSlug: string, projectId: string, issueId: string) => Promise<void>;
|
||||
archiveIssue: (workspaceSlug: string, projectId: string, issueId: string) => Promise<void>;
|
||||
quickAddIssue: (workspaceSlug: string, projectId: string, data: TIssue) => Promise<TIssue>;
|
||||
removeBulkIssues: (workspaceSlug: string, projectId: string, issueIds: string[]) => Promise<void>;
|
||||
}
|
||||
|
|
@ -40,6 +41,7 @@ export class ProjectIssues extends IssueHelperStore implements IProjectIssues {
|
|||
rootIssueStore: IIssueRootStore;
|
||||
// services
|
||||
issueService;
|
||||
issueArchiveService;
|
||||
|
||||
constructor(_rootStore: IIssueRootStore) {
|
||||
super(_rootStore);
|
||||
|
|
@ -54,6 +56,7 @@ export class ProjectIssues extends IssueHelperStore implements IProjectIssues {
|
|||
createIssue: action,
|
||||
updateIssue: action,
|
||||
removeIssue: action,
|
||||
archiveIssue: action,
|
||||
removeBulkIssues: action,
|
||||
quickAddIssue: action,
|
||||
});
|
||||
|
|
@ -61,6 +64,7 @@ export class ProjectIssues extends IssueHelperStore implements IProjectIssues {
|
|||
this.rootIssueStore = _rootStore;
|
||||
// services
|
||||
this.issueService = new IssueService();
|
||||
this.issueArchiveService = new IssueArchiveService();
|
||||
}
|
||||
|
||||
get groupedIssueIds() {
|
||||
|
|
@ -78,7 +82,7 @@ export class ProjectIssues extends IssueHelperStore implements IProjectIssues {
|
|||
const projectIssueIds = this.issues[projectId];
|
||||
if (!projectIssueIds) return;
|
||||
|
||||
const _issues = this.rootStore.issues.getIssuesByIds(projectIssueIds);
|
||||
const _issues = this.rootStore.issues.getIssuesByIds(projectIssueIds, "un-archived");
|
||||
if (!_issues) return [];
|
||||
|
||||
let issues: TGroupedIssues | TSubGroupedIssues | TUnGroupedIssues = [];
|
||||
|
|
@ -165,6 +169,21 @@ export class ProjectIssues extends IssueHelperStore implements IProjectIssues {
|
|||
}
|
||||
};
|
||||
|
||||
archiveIssue = async (workspaceSlug: string, projectId: string, issueId: string) => {
|
||||
try {
|
||||
const response = await this.issueArchiveService.archiveIssue(workspaceSlug, projectId, issueId);
|
||||
|
||||
runInAction(() => {
|
||||
this.rootStore.issues.updateIssue(issueId, {
|
||||
archived_at: response.archived_at,
|
||||
});
|
||||
pull(this.issues[projectId], issueId);
|
||||
});
|
||||
} catch (error) {
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
quickAddIssue = async (workspaceSlug: string, projectId: string, data: TIssue) => {
|
||||
try {
|
||||
runInAction(() => {
|
||||
|
|
|
|||
|
|
@ -1,10 +1,11 @@
|
|||
import { action, observable, makeObservable, computed, runInAction } from "mobx";
|
||||
import set from "lodash/set";
|
||||
import pull from "lodash/pull";
|
||||
// base class
|
||||
import { IssueHelperStore } from "../helpers/issue-helper.store";
|
||||
// services
|
||||
import { WorkspaceService } from "services/workspace.service";
|
||||
import { IssueService } from "services/issue";
|
||||
import { IssueService, IssueArchiveService } from "services/issue";
|
||||
// types
|
||||
import { IIssueRootStore } from "../root.store";
|
||||
import { TIssue, TLoader, TUnGroupedIssues, ViewFlags } from "@plane/types";
|
||||
|
|
@ -37,6 +38,12 @@ export interface IWorkspaceIssues {
|
|||
issueId: string,
|
||||
viewId?: string | undefined
|
||||
) => Promise<void>;
|
||||
archiveIssue: (
|
||||
workspaceSlug: string,
|
||||
projectId: string,
|
||||
issueId: string,
|
||||
viewId?: string | undefined
|
||||
) => Promise<void>;
|
||||
}
|
||||
|
||||
export class WorkspaceIssues extends IssueHelperStore implements IWorkspaceIssues {
|
||||
|
|
@ -52,6 +59,7 @@ export class WorkspaceIssues extends IssueHelperStore implements IWorkspaceIssue
|
|||
// service
|
||||
workspaceService;
|
||||
issueService;
|
||||
issueArchiveService;
|
||||
|
||||
constructor(_rootStore: IIssueRootStore) {
|
||||
super(_rootStore);
|
||||
|
|
@ -67,12 +75,14 @@ export class WorkspaceIssues extends IssueHelperStore implements IWorkspaceIssue
|
|||
createIssue: action,
|
||||
updateIssue: action,
|
||||
removeIssue: action,
|
||||
archiveIssue: action,
|
||||
});
|
||||
// root store
|
||||
this.rootIssueStore = _rootStore;
|
||||
// services
|
||||
this.workspaceService = new WorkspaceService();
|
||||
this.issueService = new IssueService();
|
||||
this.issueArchiveService = new IssueArchiveService();
|
||||
}
|
||||
|
||||
get groupedIssueIds() {
|
||||
|
|
@ -91,7 +101,7 @@ export class WorkspaceIssues extends IssueHelperStore implements IWorkspaceIssue
|
|||
|
||||
if (!viewIssueIds) return { dataViewId: viewId, issueIds: undefined };
|
||||
|
||||
const _issues = this.rootStore.issues.getIssuesByIds(viewIssueIds);
|
||||
const _issues = this.rootStore.issues.getIssuesByIds(viewIssueIds, "un-archived");
|
||||
if (!_issues) return { dataViewId: viewId, issueIds: [] };
|
||||
|
||||
let issueIds: TIssue | TUnGroupedIssues | undefined = undefined;
|
||||
|
|
@ -196,4 +206,28 @@ export class WorkspaceIssues extends IssueHelperStore implements IWorkspaceIssue
|
|||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
archiveIssue = async (
|
||||
workspaceSlug: string,
|
||||
projectId: string,
|
||||
issueId: string,
|
||||
viewId: string | undefined = undefined
|
||||
) => {
|
||||
try {
|
||||
if (!viewId) throw new Error("View id is required");
|
||||
|
||||
const uniqueViewId = `${workspaceSlug}_${viewId}`;
|
||||
|
||||
const response = await this.issueArchiveService.archiveIssue(workspaceSlug, projectId, issueId);
|
||||
|
||||
runInAction(() => {
|
||||
this.rootStore.issues.updateIssue(issueId, {
|
||||
archived_at: response.archived_at,
|
||||
});
|
||||
pull(this.issues[uniqueViewId], issueId);
|
||||
});
|
||||
} catch (error) {
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue