import concat from "lodash/concat"; import pull from "lodash/pull"; import uniq from "lodash/uniq"; import update from "lodash/update"; import { action, observable, makeObservable, computed, runInAction } from "mobx"; // base class import { BaseIssuesStore, IBaseIssuesStore } from "../helpers/base-issues.store"; // services import { ModuleService } from "services/module.service"; // types import { TIssue, TLoader, ViewFlags, IssuePaginationOptions, TIssuesResponse } from "@plane/types"; import { IIssueRootStore } from "../root.store"; import { IModuleIssuesFilter } from "./filter.store"; export interface IModuleIssues extends IBaseIssuesStore { viewFlags: ViewFlags; // actions fetchIssues: ( workspaceSlug: string, projectId: string, loadType: TLoader, options: IssuePaginationOptions, moduleId: string ) => Promise; fetchIssuesWithExistingPagination: ( workspaceSlug: string, projectId: string, loadType: TLoader, moduleId: string ) => Promise; fetchNextIssues: (workspaceSlug: string, projectId: string, moduleId: string) => Promise; createIssue: (workspaceSlug: string, projectId: string, data: Partial, moduleId: string) => Promise; updateIssue: (workspaceSlug: string, projectId: string, issueId: string, data: Partial) => Promise; archiveIssue: (workspaceSlug: string, projectId: string, issueId: string) => Promise; quickAddIssue: (workspaceSlug: string, projectId: string, data: TIssue) => Promise; removeBulkIssues: (workspaceSlug: string, projectId: string, issueIds: string[]) => Promise; addIssuesToModule: ( workspaceSlug: string, projectId: string, moduleId: string, issueIds: string[], fetchAddedIssues?: boolean ) => Promise; removeIssuesFromModule: ( workspaceSlug: string, projectId: string, moduleId: string, issueIds: string[] ) => Promise; addModulesToIssue: (workspaceSlug: string, projectId: string, issueId: string, moduleIds: string[]) => Promise; removeModulesFromIssue: ( workspaceSlug: string, projectId: string, issueId: string, moduleIds: string[] ) => Promise; removeIssueFromModule: (workspaceSlug: string, projectId: string, moduleId: string, issueId: string) => Promise; } export class ModuleIssues extends BaseIssuesStore implements IModuleIssues { moduleId: string | undefined = undefined; viewFlags = { enableQuickAdd: true, enableIssueCreation: true, enableInlineEditing: true, }; // service moduleService; // filter store issueFilterStore: IModuleIssuesFilter; constructor(_rootStore: IIssueRootStore, issueFilterStore: IModuleIssuesFilter) { super(_rootStore, issueFilterStore); makeObservable(this, { // observable moduleId: observable.ref, // action fetchIssues: action, fetchNextIssues: action, fetchIssuesWithExistingPagination: action, addIssuesToModule: action, removeIssuesFromModule: action, addModulesToIssue: action, removeModulesFromIssue: action, removeIssueFromModule: action, quickAddIssue: action, }); // filter store this.issueFilterStore = issueFilterStore; // service this.moduleService = new ModuleService(); } fetchIssues = async ( workspaceSlug: string, projectId: string, loadType: TLoader, options: IssuePaginationOptions, moduleId: string ) => { try { runInAction(() => { this.loader = loadType; }); this.clear(); this.moduleId = moduleId; const params = this.issueFilterStore?.getFilterParams(options, undefined); const response = await this.moduleService.getModuleIssues(workspaceSlug, projectId, moduleId, params); this.onfetchIssues(response, options); return response; } catch (error) { this.loader = undefined; throw error; } }; fetchNextIssues = async (workspaceSlug: string, projectId: string, moduleId: string) => { if (!this.paginationOptions || !this.next_page_results) return; try { this.loader = "pagination"; const params = this.issueFilterStore?.getFilterParams(this.paginationOptions, this.nextCursor); const response = await this.moduleService.getModuleIssues(workspaceSlug, projectId, moduleId, params); this.onfetchNexIssues(response); return response; } catch (error) { this.loader = undefined; throw error; } }; fetchIssuesWithExistingPagination = async ( workspaceSlug: string, projectId: string, loadType: TLoader, moduleId: string ) => { if (!this.paginationOptions) return; return await this.fetchIssues(workspaceSlug, projectId, loadType, this.paginationOptions, moduleId); }; override createIssue = async (workspaceSlug: string, projectId: string, data: Partial, moduleId: string) => { try { const response = await super.createIssue(workspaceSlug, projectId, data, moduleId, false); await this.addIssuesToModule(workspaceSlug, projectId, moduleId, [response.id], false); this.moduleId === moduleId && this.addIssue(response); this.rootIssueStore.rootStore.module.fetchModuleDetails(workspaceSlug, projectId, moduleId); return response; } catch (error) { throw error; } }; addIssuesToModule = async ( workspaceSlug: string, projectId: string, moduleId: string, issueIds: string[], fetchAddedIssues = true ) => { try { await this.moduleService.addIssuesToModule(workspaceSlug, projectId, moduleId, { issues: issueIds, }); if (fetchAddedIssues) await this.rootIssueStore.issues.getIssues(workspaceSlug, projectId, issueIds); runInAction(() => { this.moduleId === moduleId && update(this, "issues", (moduleIssueIds = []) => { if (!moduleIssueIds) return [...issueIds]; else return uniq(concat(moduleIssueIds, issueIds)); }); }); issueIds.forEach((issueId) => { update(this.rootIssueStore.issues.issuesMap, [issueId, "module_ids"], (issueModuleIds = []) => { if (issueModuleIds.includes(moduleId)) return issueModuleIds; else return uniq(concat(issueModuleIds, [moduleId])); }); }); this.rootIssueStore.rootStore.module.fetchModuleDetails(workspaceSlug, projectId, moduleId); } catch (error) { throw error; } }; removeIssuesFromModule = async (workspaceSlug: string, projectId: string, moduleId: string, issueIds: string[]) => { try { const response = await this.moduleService.removeIssuesFromModuleBulk( workspaceSlug, projectId, moduleId, issueIds ); runInAction(() => { this.moduleId === moduleId && issueIds.forEach((issueId) => { this.issues && pull(this.issues, issueId); }); }); runInAction(() => { issueIds.forEach((issueId) => { update(this.rootIssueStore.issues.issuesMap, [issueId, "module_ids"], (issueModuleIds = []) => { if (issueModuleIds.includes(moduleId)) return pull(issueModuleIds, moduleId); else return uniq(concat(issueModuleIds, [moduleId])); }); }); }); this.rootIssueStore.rootStore.module.fetchModuleDetails(workspaceSlug, projectId, moduleId); return response; } catch (error) { throw error; } }; addModulesToIssue = async (workspaceSlug: string, projectId: string, issueId: string, moduleIds: string[]) => { try { const issueToModule = await this.moduleService.addModulesToIssue(workspaceSlug, projectId, issueId, { modules: moduleIds, }); runInAction(() => { moduleIds.forEach((moduleId) => { this.moduleId === moduleId && update(this, "issues", (moduleIssueIds = []) => { if (moduleIssueIds.includes(issueId)) return moduleIssueIds; else return uniq(concat(moduleIssueIds, [issueId])); }); }); update(this.rootIssueStore.issues.issuesMap, [issueId, "module_ids"], (issueModuleIds = []) => uniq(concat(issueModuleIds, moduleIds)) ); }); return issueToModule; } catch (error) { throw error; } }; removeModulesFromIssue = async (workspaceSlug: string, projectId: string, issueId: string, moduleIds: string[]) => { try { runInAction(() => { moduleIds.forEach((moduleId) => { this.moduleId === moduleId && update(this, "issues", (moduleIssueIds = []) => { if (moduleIssueIds.includes(issueId)) return pull(moduleIssueIds, issueId); else return uniq(concat(moduleIssueIds, [issueId])); }); update(this.rootIssueStore.issues.issuesMap, [issueId, "module_ids"], (issueModuleIds = []) => pull(issueModuleIds, moduleId) ); }); }); const response = await this.moduleService.removeModulesFromIssueBulk( workspaceSlug, projectId, issueId, moduleIds ); return response; } catch (error) { throw error; } }; removeIssueFromModule = async (workspaceSlug: string, projectId: string, moduleId: string, issueId: string) => { try { runInAction(() => { this.issues && this.moduleId === this.moduleId && pull(this.issues, issueId); update(this.rootIssueStore.issues.issuesMap, [issueId, "module_ids"], (issueModuleIds = []) => pull(issueModuleIds, moduleId) ); }); const response = await this.moduleService.removeIssueFromModule(workspaceSlug, projectId, moduleId, issueId); return response; } catch (error) { throw error; } }; quickAddIssue = this.issueQuickAdd; }