modify adding issues to modules and cycles

This commit is contained in:
rahulramesha 2024-02-20 13:28:00 +05:30
parent 7078863189
commit fa085bd29f
9 changed files with 86 additions and 33 deletions

View File

@ -56,7 +56,7 @@ export const TransferIssuesModal: React.FC<Props> = observer((props) => {
const filteredOptions = currentProjectIncompleteCycleIds?.filter((optionId) => { const filteredOptions = currentProjectIncompleteCycleIds?.filter((optionId) => {
const cycleDetails = getCycleById(optionId); const cycleDetails = getCycleById(optionId);
return cycleDetails?.name.toLowerCase().includes(query.toLowerCase()); return cycleDetails?.name?.toLowerCase().includes(query?.toLowerCase());
}); });
// useEffect(() => { // useEffect(() => {

View File

@ -160,7 +160,7 @@ export const IssueDetailRoot: FC<TIssueDetailRoot> = observer((props) => {
}, },
addIssueToCycle: async (workspaceSlug: string, projectId: string, cycleId: string, issueIds: string[]) => { addIssueToCycle: async (workspaceSlug: string, projectId: string, cycleId: string, issueIds: string[]) => {
try { try {
const response = await addIssueToCycle(workspaceSlug, projectId, cycleId, issueIds); await addIssueToCycle(workspaceSlug, projectId, cycleId, issueIds);
setToastAlert({ setToastAlert({
title: "Cycle added to issue successfully", title: "Cycle added to issue successfully",
type: "success", type: "success",
@ -168,7 +168,7 @@ export const IssueDetailRoot: FC<TIssueDetailRoot> = observer((props) => {
}); });
captureIssueEvent({ captureIssueEvent({
eventName: ISSUE_UPDATED, eventName: ISSUE_UPDATED,
payload: { ...response, state: "SUCCESS", element: "Issue detail page" }, payload: { ...issueIds, state: "SUCCESS", element: "Issue detail page" },
updates: { updates: {
changed_property: "cycle_id", changed_property: "cycle_id",
change_details: cycleId, change_details: cycleId,

View File

@ -60,13 +60,7 @@ export const CycleEmptyState: React.FC<Props> = observer((props) => {
const issueIds = data.map((i) => i.id); const issueIds = data.map((i) => i.id);
await issues await issues.addIssueToCycle(workspaceSlug.toString(), projectId, cycleId.toString(), issueIds).catch(() => {
.addIssueToCycle(workspaceSlug.toString(), projectId, cycleId.toString(), issueIds)
.then((res) => {
updateIssue(workspaceSlug, projectId, res.id, res);
fetchIssue(workspaceSlug, projectId, res.id);
})
.catch(() => {
setToastAlert({ setToastAlert({
type: "error", type: "error",
title: "Error!", title: "Error!",

View File

@ -146,7 +146,7 @@ export const IssuePeekOverview: FC<IIssuePeekOverview> = observer((props) => {
}, },
addIssueToCycle: async (workspaceSlug: string, projectId: string, cycleId: string, issueIds: string[]) => { addIssueToCycle: async (workspaceSlug: string, projectId: string, cycleId: string, issueIds: string[]) => {
try { try {
const response = await addIssueToCycle(workspaceSlug, projectId, cycleId, issueIds); await addIssueToCycle(workspaceSlug, projectId, cycleId, issueIds);
setToastAlert({ setToastAlert({
title: "Cycle added to issue successfully", title: "Cycle added to issue successfully",
type: "success", type: "success",
@ -154,7 +154,7 @@ export const IssuePeekOverview: FC<IIssuePeekOverview> = observer((props) => {
}); });
captureIssueEvent({ captureIssueEvent({
eventName: ISSUE_UPDATED, eventName: ISSUE_UPDATED,
payload: { ...response, state: "SUCCESS", element: "Issue peek-overview" }, payload: { ...issueIds, state: "SUCCESS", element: "Issue peek-overview" },
updates: { updates: {
changed_property: "cycle_id", changed_property: "cycle_id",
change_details: cycleId, change_details: cycleId,

View File

@ -59,6 +59,16 @@ export class IssueService extends APIService {
}); });
} }
async retrieveIssues(workspaceSlug: string, projectId: string, issueIds: string[]): Promise<TIssue[]> {
return this.get(`/api/workspaces/${workspaceSlug}/projects/${projectId}/issues/list/`, {
params: { issues: issueIds.join(",") },
})
.then((response) => response?.data)
.catch((error) => {
throw error?.response?.data;
});
}
async getIssueActivities(workspaceSlug: string, projectId: string, issueId: string): Promise<TIssueActivity[]> { async getIssueActivities(workspaceSlug: string, projectId: string, issueId: string): Promise<TIssueActivity[]> {
return this.get(`/api/workspaces/${workspaceSlug}/projects/${projectId}/issues/${issueId}/history/`) return this.get(`/api/workspaces/${workspaceSlug}/projects/${projectId}/issues/${issueId}/history/`)
.then((response) => response?.data) .then((response) => response?.data)

View File

@ -54,7 +54,13 @@ export interface ICycleIssues {
data: TIssue, data: TIssue,
cycleId?: string | undefined cycleId?: string | undefined
) => Promise<TIssue>; ) => Promise<TIssue>;
addIssueToCycle: (workspaceSlug: string, projectId: string, cycleId: string, issueIds: string[]) => Promise<TIssue>; addIssueToCycle: (
workspaceSlug: string,
projectId: string,
cycleId: string,
issueIds: string[],
fetchAddedIssues?: boolean
) => Promise<void>;
removeIssueFromCycle: (workspaceSlug: string, projectId: string, cycleId: string, issueId: string) => Promise<TIssue>; removeIssueFromCycle: (workspaceSlug: string, projectId: string, cycleId: string, issueId: string) => Promise<TIssue>;
transferIssuesFromCycle: ( transferIssuesFromCycle: (
workspaceSlug: string, workspaceSlug: string,
@ -182,7 +188,7 @@ export class CycleIssues extends IssueHelperStore implements ICycleIssues {
if (!cycleId) throw new Error("Cycle Id is required"); if (!cycleId) throw new Error("Cycle Id is required");
const response = await this.rootIssueStore.projectIssues.createIssue(workspaceSlug, projectId, data); const response = await this.rootIssueStore.projectIssues.createIssue(workspaceSlug, projectId, data);
await this.addIssueToCycle(workspaceSlug, projectId, cycleId, [response.id]); await this.addIssueToCycle(workspaceSlug, projectId, cycleId, [response.id], false);
this.rootIssueStore.rootStore.cycle.fetchCycleDetails(workspaceSlug, projectId, cycleId); this.rootIssueStore.rootStore.cycle.fetchCycleDetails(workspaceSlug, projectId, cycleId);
return response; return response;
@ -265,21 +271,33 @@ export class CycleIssues extends IssueHelperStore implements ICycleIssues {
} }
}; };
addIssueToCycle = async (workspaceSlug: string, projectId: string, cycleId: string, issueIds: string[]) => { addIssueToCycle = async (
workspaceSlug: string,
projectId: string,
cycleId: string,
issueIds: string[],
fetchAddedIssues = true
) => {
try { try {
const issueToCycle = await this.issueService.addIssueToCycle(workspaceSlug, projectId, cycleId, { await this.issueService.addIssueToCycle(workspaceSlug, projectId, cycleId, {
issues: issueIds, issues: issueIds,
}); });
if (fetchAddedIssues) await this.rootIssueStore.issues.getIssues(workspaceSlug, projectId, issueIds);
runInAction(() => { runInAction(() => {
update(this.issues, cycleId, (cycleIssueIds = []) => uniq(concat(cycleIssueIds, issueIds))); update(this.issues, cycleId, (cycleIssueIds = []) => uniq(concat(cycleIssueIds, issueIds)));
}); });
issueIds.forEach((issueId) => { issueIds.forEach((issueId) => {
const issueCycleId = this.rootIssueStore.issues.getIssueById(issueId)?.cycle_id;
if (issueCycleId && issueCycleId !== cycleId) {
runInAction(() => {
pull(this.issues[issueCycleId], issueId);
});
}
this.rootStore.issues.updateIssue(issueId, { cycle_id: cycleId }); this.rootStore.issues.updateIssue(issueId, { cycle_id: cycleId });
}); });
this.rootIssueStore.rootStore.cycle.fetchCycleDetails(workspaceSlug, projectId, cycleId); this.rootIssueStore.rootStore.cycle.fetchCycleDetails(workspaceSlug, projectId, cycleId);
return issueToCycle;
} catch (error) { } catch (error) {
throw error; throw error;
} }

View File

@ -11,7 +11,7 @@ export interface IIssueStoreActions {
fetchIssue: (workspaceSlug: string, projectId: string, issueId: string, isArchived?: boolean) => Promise<TIssue>; fetchIssue: (workspaceSlug: string, projectId: string, issueId: string, isArchived?: boolean) => Promise<TIssue>;
updateIssue: (workspaceSlug: string, projectId: string, issueId: string, data: Partial<TIssue>) => Promise<TIssue>; updateIssue: (workspaceSlug: string, projectId: string, issueId: string, data: Partial<TIssue>) => Promise<TIssue>;
removeIssue: (workspaceSlug: string, projectId: string, issueId: string) => Promise<TIssue>; removeIssue: (workspaceSlug: string, projectId: string, issueId: string) => Promise<TIssue>;
addIssueToCycle: (workspaceSlug: string, projectId: string, cycleId: string, issueIds: string[]) => Promise<TIssue>; addIssueToCycle: (workspaceSlug: string, projectId: string, cycleId: string, issueIds: string[]) => Promise<void>;
removeIssueFromCycle: (workspaceSlug: string, projectId: string, cycleId: string, issueId: string) => Promise<TIssue>; removeIssueFromCycle: (workspaceSlug: string, projectId: string, cycleId: string, issueId: string) => Promise<TIssue>;
addModulesToIssue: (workspaceSlug: string, projectId: string, issueId: string, moduleIds: string[]) => Promise<any>; addModulesToIssue: (workspaceSlug: string, projectId: string, issueId: string, moduleIds: string[]) => Promise<any>;
removeModulesFromIssue: ( removeModulesFromIssue: (
@ -123,15 +123,15 @@ export class IssueStore implements IIssueStore {
this.rootIssueDetailStore.rootIssueStore.projectIssues.removeIssue(workspaceSlug, projectId, issueId); this.rootIssueDetailStore.rootIssueStore.projectIssues.removeIssue(workspaceSlug, projectId, issueId);
addIssueToCycle = async (workspaceSlug: string, projectId: string, cycleId: string, issueIds: string[]) => { addIssueToCycle = async (workspaceSlug: string, projectId: string, cycleId: string, issueIds: string[]) => {
const cycle = await this.rootIssueDetailStore.rootIssueStore.cycleIssues.addIssueToCycle( await this.rootIssueDetailStore.rootIssueStore.cycleIssues.addIssueToCycle(
workspaceSlug, workspaceSlug,
projectId, projectId,
cycleId, cycleId,
issueIds issueIds,
false
); );
if (issueIds && issueIds.length > 0) if (issueIds && issueIds.length > 0)
await this.rootIssueDetailStore.activity.fetchActivities(workspaceSlug, projectId, issueIds[0]); await this.rootIssueDetailStore.activity.fetchActivities(workspaceSlug, projectId, issueIds[0]);
return cycle;
}; };
removeIssueFromCycle = async (workspaceSlug: string, projectId: string, cycleId: string, issueId: string) => { removeIssueFromCycle = async (workspaceSlug: string, projectId: string, cycleId: string, issueId: string) => {

View File

@ -5,11 +5,14 @@ import { action, makeObservable, observable, runInAction } from "mobx";
import { computedFn } from "mobx-utils"; import { computedFn } from "mobx-utils";
// types // types
import { TIssue } from "@plane/types"; import { TIssue } from "@plane/types";
//services
import { IssueService } from "services/issue";
export type IIssueStore = { export type IIssueStore = {
// observables // observables
issuesMap: Record<string, TIssue>; // Record defines issue_id as key and TIssue as value issuesMap: Record<string, TIssue>; // Record defines issue_id as key and TIssue as value
// actions // actions
getIssues(workspaceSlug: string, projectId: string, issueIds: string[]): Promise<TIssue[]>;
addIssue(issues: TIssue[], shouldReplace?: boolean): void; addIssue(issues: TIssue[], shouldReplace?: boolean): void;
updateIssue(issueId: string, issue: Partial<TIssue>): void; updateIssue(issueId: string, issue: Partial<TIssue>): void;
removeIssue(issueId: string): void; removeIssue(issueId: string): void;
@ -21,6 +24,8 @@ export type IIssueStore = {
export class IssueStore implements IIssueStore { export class IssueStore implements IIssueStore {
// observables // observables
issuesMap: { [issue_id: string]: TIssue } = {}; issuesMap: { [issue_id: string]: TIssue } = {};
// service
issueService;
constructor() { constructor() {
makeObservable(this, { makeObservable(this, {
@ -31,6 +36,8 @@ export class IssueStore implements IIssueStore {
updateIssue: action, updateIssue: action,
removeIssue: action, removeIssue: action,
}); });
this.issueService = new IssueService();
} }
// actions // actions
@ -48,6 +55,18 @@ export class IssueStore implements IIssueStore {
}); });
}; };
getIssues = async (workspaceSlug: string, projectId: string, issueIds: string[]) => {
const issues = await this.issueService.retrieveIssues(workspaceSlug, projectId, issueIds);
runInAction(() => {
issues.forEach((issue) => {
if (!this.issuesMap[issue.id]) set(this.issuesMap, issue.id, issue);
});
});
return issues;
};
/** /**
* @description This method will update the issue in the issuesMap * @description This method will update the issue in the issuesMap
* @param {string} issueId * @param {string} issueId

View File

@ -52,7 +52,13 @@ export interface IModuleIssues {
data: TIssue, data: TIssue,
moduleId?: string | undefined moduleId?: string | undefined
) => Promise<TIssue | undefined>; ) => Promise<TIssue | undefined>;
addIssuesToModule: (workspaceSlug: string, projectId: string, moduleId: string, issueIds: string[]) => Promise<void>; addIssuesToModule: (
workspaceSlug: string,
projectId: string,
moduleId: string,
issueIds: string[],
fetchAddedIssues?: boolean
) => Promise<void>;
removeIssuesFromModule: ( removeIssuesFromModule: (
workspaceSlug: string, workspaceSlug: string,
projectId: string, projectId: string,
@ -187,7 +193,7 @@ export class ModuleIssues extends IssueHelperStore implements IModuleIssues {
if (!moduleId) throw new Error("Module Id is required"); if (!moduleId) throw new Error("Module Id is required");
const response = await this.rootIssueStore.projectIssues.createIssue(workspaceSlug, projectId, data); const response = await this.rootIssueStore.projectIssues.createIssue(workspaceSlug, projectId, data);
await this.addIssuesToModule(workspaceSlug, projectId, moduleId, [response.id]); await this.addIssuesToModule(workspaceSlug, projectId, moduleId, [response.id], false);
this.rootIssueStore.rootStore.module.fetchModuleDetails(workspaceSlug, projectId, moduleId); this.rootIssueStore.rootStore.module.fetchModuleDetails(workspaceSlug, projectId, moduleId);
return response; return response;
@ -269,12 +275,20 @@ export class ModuleIssues extends IssueHelperStore implements IModuleIssues {
} }
}; };
addIssuesToModule = async (workspaceSlug: string, projectId: string, moduleId: string, issueIds: string[]) => { addIssuesToModule = async (
workspaceSlug: string,
projectId: string,
moduleId: string,
issueIds: string[],
fetchAddedIssues = true
) => {
try { try {
const issueToModule = await this.moduleService.addIssuesToModule(workspaceSlug, projectId, moduleId, { await this.moduleService.addIssuesToModule(workspaceSlug, projectId, moduleId, {
issues: issueIds, issues: issueIds,
}); });
if (fetchAddedIssues) await this.rootIssueStore.issues.getIssues(workspaceSlug, projectId, issueIds);
runInAction(() => { runInAction(() => {
update(this.issues, moduleId, (moduleIssueIds = []) => { update(this.issues, moduleId, (moduleIssueIds = []) => {
if (!moduleIssueIds) return [...issueIds]; if (!moduleIssueIds) return [...issueIds];
@ -289,8 +303,6 @@ export class ModuleIssues extends IssueHelperStore implements IModuleIssues {
}); });
}); });
this.rootIssueStore.rootStore.module.fetchModuleDetails(workspaceSlug, projectId, moduleId); this.rootIssueStore.rootStore.module.fetchModuleDetails(workspaceSlug, projectId, moduleId);
return issueToModule;
} catch (error) { } catch (error) {
throw error; throw error;
} }