diff --git a/web/core/services/cycle.service.ts b/web/core/services/cycle.service.ts index 6681926fd2..9040b83407 100644 --- a/web/core/services/cycle.service.ts +++ b/web/core/services/cycle.service.ts @@ -2,7 +2,7 @@ import { API_BASE_URL } from "@/helpers/common.helper"; import { APIService } from "@/services/api.service"; // types -import type { CycleDateCheckData, ICycle, TIssue, TIssuesResponse } from "@plane/types"; +import type { CycleDateCheckData, ICycle, TIssuesResponse } from "@plane/types"; // helpers export class CycleService extends APIService { @@ -50,11 +50,16 @@ export class CycleService extends APIService { workspaceSlug: string, projectId: string, cycleId: string, - queries?: any + queries?: any, + config = {} ): Promise { - return this.get(`/api/workspaces/${workspaceSlug}/projects/${projectId}/cycles/${cycleId}/cycle-issues/`, { - params: queries, - }) + return this.get( + `/api/workspaces/${workspaceSlug}/projects/${projectId}/cycles/${cycleId}/cycle-issues/`, + { + params: queries, + }, + config + ) .then((response) => response?.data) .catch((error) => { throw error?.response?.data; diff --git a/web/core/services/issue/issue.service.ts b/web/core/services/issue/issue.service.ts index c9628840c6..7cded46330 100644 --- a/web/core/services/issue/issue.service.ts +++ b/web/core/services/issue/issue.service.ts @@ -18,10 +18,14 @@ export class IssueService extends APIService { }); } - async getIssues(workspaceSlug: string, projectId: string, queries?: any): Promise { - return this.get(`/api/workspaces/${workspaceSlug}/projects/${projectId}/issues/`, { - params: queries, - }) + async getIssues(workspaceSlug: string, projectId: string, queries?: any, config = {}): Promise { + return this.get( + `/api/workspaces/${workspaceSlug}/projects/${projectId}/issues/`, + { + params: queries, + }, + config + ) .then((response) => response?.data) .catch((error) => { throw error?.response?.data; diff --git a/web/core/services/issue/issue_archive.service.ts b/web/core/services/issue/issue_archive.service.ts index 6a55c3d7d6..5901daa5a9 100644 --- a/web/core/services/issue/issue_archive.service.ts +++ b/web/core/services/issue/issue_archive.service.ts @@ -9,10 +9,14 @@ export class IssueArchiveService extends APIService { super(API_BASE_URL); } - async getArchivedIssues(workspaceSlug: string, projectId: string, queries?: any): Promise { - return this.get(`/api/workspaces/${workspaceSlug}/projects/${projectId}/archived-issues/`, { - params: { ...queries }, - }) + async getArchivedIssues(workspaceSlug: string, projectId: string, queries?: any, config = {}): Promise { + return this.get( + `/api/workspaces/${workspaceSlug}/projects/${projectId}/archived-issues/`, + { + params: { ...queries }, + }, + config + ) .then((response) => response?.data) .catch((error) => { throw error?.response?.data; diff --git a/web/core/services/issue/issue_draft.service.ts b/web/core/services/issue/issue_draft.service.ts index 63cb2dda50..15152798d4 100644 --- a/web/core/services/issue/issue_draft.service.ts +++ b/web/core/services/issue/issue_draft.service.ts @@ -8,10 +8,14 @@ export class IssueDraftService extends APIService { super(API_BASE_URL); } - async getDraftIssues(workspaceSlug: string, projectId: string, query?: any): Promise { - return this.get(`/api/workspaces/${workspaceSlug}/projects/${projectId}/issue-drafts/`, { - params: { ...query }, - }) + async getDraftIssues(workspaceSlug: string, projectId: string, query?: any, config = {}): Promise { + return this.get( + `/api/workspaces/${workspaceSlug}/projects/${projectId}/issue-drafts/`, + { + params: { ...query }, + }, + config + ) .then((response) => response?.data) .catch((error) => { throw error?.response?.data; diff --git a/web/core/services/module.service.ts b/web/core/services/module.service.ts index d786453798..89ecc1726a 100644 --- a/web/core/services/module.service.ts +++ b/web/core/services/module.service.ts @@ -74,11 +74,16 @@ export class ModuleService extends APIService { workspaceSlug: string, projectId: string, moduleId: string, - queries?: any + queries?: any, + config = {} ): Promise { - return this.get(`/api/workspaces/${workspaceSlug}/projects/${projectId}/modules/${moduleId}/issues/`, { - params: queries, - }) + return this.get( + `/api/workspaces/${workspaceSlug}/projects/${projectId}/modules/${moduleId}/issues/`, + { + params: queries, + }, + config + ) .then((response) => response?.data) .catch((error) => { throw error?.response?.data; diff --git a/web/core/services/user.service.ts b/web/core/services/user.service.ts index adbae133c6..9202da9fe4 100644 --- a/web/core/services/user.service.ts +++ b/web/core/services/user.service.ts @@ -206,10 +206,19 @@ export class UserService extends APIService { }); } - async getUserProfileIssues(workspaceSlug: string, userId: string, params: any): Promise { - return this.get(`/api/workspaces/${workspaceSlug}/user-issues/${userId}/`, { - params, - }) + async getUserProfileIssues( + workspaceSlug: string, + userId: string, + params: any, + config = {} + ): Promise { + return this.get( + `/api/workspaces/${workspaceSlug}/user-issues/${userId}/`, + { + params, + }, + config + ) .then((response) => response?.data) .catch((error) => { throw error?.response?.data; diff --git a/web/core/services/workspace.service.ts b/web/core/services/workspace.service.ts index 4e8ee4bdf4..9ba8eedf10 100644 --- a/web/core/services/workspace.service.ts +++ b/web/core/services/workspace.service.ts @@ -257,10 +257,14 @@ export class WorkspaceService extends APIService { }); } - async getViewIssues(workspaceSlug: string, params: any): Promise { - return this.get(`/api/workspaces/${workspaceSlug}/issues/`, { - params, - }) + async getViewIssues(workspaceSlug: string, params: any, config = {}): Promise { + return this.get( + `/api/workspaces/${workspaceSlug}/issues/`, + { + params, + }, + config + ) .then((response) => response?.data) .catch((error) => { throw error?.response?.data; diff --git a/web/core/store/issue/archived/issue.store.ts b/web/core/store/issue/archived/issue.store.ts index 9c23f547c7..7810737790 100644 --- a/web/core/store/issue/archived/issue.store.ts +++ b/web/core/store/issue/archived/issue.store.ts @@ -83,19 +83,22 @@ export class ArchivedIssues extends BaseIssuesStore implements IArchivedIssues { workspaceSlug: string, projectId: string, loadType: TLoader = "init-loader", - options: IssuePaginationOptions + options: IssuePaginationOptions, + isExistingPaginationOptions: boolean = false ) => { try { // set loader and clear store runInAction(() => { this.setLoader(loadType); }); - this.clear(); + this.clear(!isExistingPaginationOptions); // get params from pagination options const params = this.issueFilterStore?.getFilterParams(options, undefined, undefined, undefined); // call the fetch issues API with the params - const response = await this.issueArchiveService.getArchivedIssues(workspaceSlug, projectId, params); + const response = await this.issueArchiveService.getArchivedIssues(workspaceSlug, projectId, params, { + signal: this.controller.signal, + }); // after fetching issues, call the base method to process the response further this.onfetchIssues(response, options, workspaceSlug, projectId); @@ -159,7 +162,7 @@ export class ArchivedIssues extends BaseIssuesStore implements IArchivedIssues { loadType: TLoader = "mutation" ) => { if (!this.paginationOptions) return; - return await this.fetchIssues(workspaceSlug, projectId, loadType, this.paginationOptions); + return await this.fetchIssues(workspaceSlug, projectId, loadType, this.paginationOptions, true); }; /** diff --git a/web/core/store/issue/cycle/issue.store.ts b/web/core/store/issue/cycle/issue.store.ts index a607926173..75bf5001f9 100644 --- a/web/core/store/issue/cycle/issue.store.ts +++ b/web/core/store/issue/cycle/issue.store.ts @@ -150,19 +150,22 @@ export class CycleIssues extends BaseIssuesStore implements ICycleIssues { projectId: string, loadType: TLoader, options: IssuePaginationOptions, - cycleId: string + cycleId: string, + isExistingPaginationOptions: boolean = false ) => { try { // set loader and clear store runInAction(() => { this.setLoader(loadType); }); - this.clear(); + this.clear(!isExistingPaginationOptions); // get params from pagination options const params = this.issueFilterStore?.getFilterParams(options, undefined, undefined, undefined); // call the fetch issues API with the params - const response = await this.cycleService.getCycleIssues(workspaceSlug, projectId, cycleId, params); + const response = await this.cycleService.getCycleIssues(workspaceSlug, projectId, cycleId, params, { + signal: this.controller.signal, + }); // after fetching issues, call the base method to process the response further this.onfetchIssues(response, options, workspaceSlug, projectId, cycleId); @@ -235,7 +238,7 @@ export class CycleIssues extends BaseIssuesStore implements ICycleIssues { cycleId: string ) => { if (!this.paginationOptions) return; - return await this.fetchIssues(workspaceSlug, projectId, loadType, this.paginationOptions, cycleId); + return await this.fetchIssues(workspaceSlug, projectId, loadType, this.paginationOptions, cycleId, true); }; /** diff --git a/web/core/store/issue/draft/issue.store.ts b/web/core/store/issue/draft/issue.store.ts index 4295113822..cc48f48d19 100644 --- a/web/core/store/issue/draft/issue.store.ts +++ b/web/core/store/issue/draft/issue.store.ts @@ -81,19 +81,22 @@ export class DraftIssues extends BaseIssuesStore implements IDraftIssues { workspaceSlug: string, projectId: string, loadType: TLoader = "init-loader", - options: IssuePaginationOptions + options: IssuePaginationOptions, + isExistingPaginationOptions: boolean = false ) => { try { // set loader and clear store runInAction(() => { this.setLoader(loadType); }); - this.clear(); + this.clear(!isExistingPaginationOptions); // get params from pagination options const params = this.issueFilterStore?.getFilterParams(options, undefined, undefined, undefined); // call the fetch issues API with the params - const response = await this.issueDraftService.getDraftIssues(workspaceSlug, projectId, params); + const response = await this.issueDraftService.getDraftIssues(workspaceSlug, projectId, params, { + signal: this.controller.signal, + }); // after fetching issues, call the base method to process the response further this.onfetchIssues(response, options, workspaceSlug, projectId); @@ -157,7 +160,7 @@ export class DraftIssues extends BaseIssuesStore implements IDraftIssues { loadType: TLoader = "mutation" ) => { if (!this.paginationOptions) return; - return await this.fetchIssues(workspaceSlug, projectId, loadType, this.paginationOptions); + return await this.fetchIssues(workspaceSlug, projectId, loadType, this.paginationOptions, true); }; createIssue = this.createDraftIssue; diff --git a/web/core/store/issue/helpers/base-issues.store.ts b/web/core/store/issue/helpers/base-issues.store.ts index 24dccaf235..62f7a93a51 100644 --- a/web/core/store/issue/helpers/base-issues.store.ts +++ b/web/core/store/issue/helpers/base-issues.store.ts @@ -187,6 +187,8 @@ export abstract class BaseIssuesStore implements IBaseIssuesStore { // root store rootIssueStore; issueFilterStore; + // API Abort controller + controller: AbortController; constructor(_rootStore: IIssueRootStore, issueFilterStore: IBaseIssueFilterStore, isArchived = false) { makeObservable(this, { @@ -246,6 +248,8 @@ export abstract class BaseIssuesStore implements IBaseIssuesStore { this.issueDraftService = new IssueDraftService(); this.moduleService = new ModuleService(); this.cycleService = new CycleService(); + + this.controller = new AbortController(); } // Abstract class to be implemented to fetch parent stats such as project, module or cycle details @@ -1096,13 +1100,17 @@ export abstract class BaseIssuesStore implements IBaseIssuesStore { /** * Method called to clear out the current store */ - clear() { + clear(shouldClearPaginationOptions = true) { runInAction(() => { this.groupedIssueIds = undefined; this.issuePaginationData = {}; this.groupedIssueCount = {}; - this.paginationOptions = undefined; + if (shouldClearPaginationOptions) { + this.paginationOptions = undefined; + } }); + this.controller.abort(); + this.controller = new AbortController(); } /** diff --git a/web/core/store/issue/module/issue.store.ts b/web/core/store/issue/module/issue.store.ts index 29a10132bd..46fc577ba4 100644 --- a/web/core/store/issue/module/issue.store.ts +++ b/web/core/store/issue/module/issue.store.ts @@ -105,19 +105,22 @@ export class ModuleIssues extends BaseIssuesStore implements IModuleIssues { projectId: string, loadType: TLoader, options: IssuePaginationOptions, - moduleId: string + moduleId: string, + isExistingPaginationOptions: boolean = false ) => { try { // set loader and clear store runInAction(() => { this.setLoader(loadType); }); - this.clear(); + this.clear(!isExistingPaginationOptions); // get params from pagination options const params = this.issueFilterStore?.getFilterParams(options, undefined, undefined, undefined); // call the fetch issues API with the params - const response = await this.moduleService.getModuleIssues(workspaceSlug, projectId, moduleId, params); + const response = await this.moduleService.getModuleIssues(workspaceSlug, projectId, moduleId, params, { + signal: this.controller.signal, + }); // after fetching issues, call the base method to process the response further this.onfetchIssues(response, options, workspaceSlug, projectId, moduleId); @@ -190,7 +193,7 @@ export class ModuleIssues extends BaseIssuesStore implements IModuleIssues { moduleId: string ) => { if (!this.paginationOptions) return; - return await this.fetchIssues(workspaceSlug, projectId, loadType, this.paginationOptions, moduleId); + return await this.fetchIssues(workspaceSlug, projectId, loadType, this.paginationOptions, moduleId, true); }; /** diff --git a/web/core/store/issue/profile/issue.store.ts b/web/core/store/issue/profile/issue.store.ts index 91a49ea326..6e164ab7a1 100644 --- a/web/core/store/issue/profile/issue.store.ts +++ b/web/core/store/issue/profile/issue.store.ts @@ -105,14 +105,15 @@ export class ProfileIssues extends BaseIssuesStore implements IProfileIssues { userId: string, loadType: TLoader, options: IssuePaginationOptions, - view: "assigned" | "created" | "subscribed" + view: "assigned" | "created" | "subscribed", + isExistingPaginationOptions: boolean = false ) => { try { // set loader and clear store runInAction(() => { this.setLoader(loadType); }); - this.clear(); + this.clear(!isExistingPaginationOptions); // set ViewId this.setViewId(view); @@ -131,7 +132,9 @@ export class ProfileIssues extends BaseIssuesStore implements IProfileIssues { else if (this.currentView === "subscribed") params = { ...params, subscriber: userId }; // call the fetch issues API with the params - const response = await this.userService.getUserProfileIssues(workspaceSlug, userId, params); + const response = await this.userService.getUserProfileIssues(workspaceSlug, userId, params, { + signal: this.controller.signal, + }); // after fetching issues, call the base method to process the response further this.onfetchIssues(response, options, workspaceSlug); @@ -201,7 +204,7 @@ export class ProfileIssues extends BaseIssuesStore implements IProfileIssues { */ fetchIssuesWithExistingPagination = async (workspaceSlug: string, userId: string, loadType: TLoader) => { if (!this.paginationOptions || !this.currentView) return; - return await this.fetchIssues(workspaceSlug, userId, loadType, this.paginationOptions, this.currentView); + return await this.fetchIssues(workspaceSlug, userId, loadType, this.paginationOptions, this.currentView, true); }; archiveBulkIssues = this.bulkArchiveIssues; diff --git a/web/core/store/issue/project-views/issue.store.ts b/web/core/store/issue/project-views/issue.store.ts index 02af914dfc..e17c51af9b 100644 --- a/web/core/store/issue/project-views/issue.store.ts +++ b/web/core/store/issue/project-views/issue.store.ts @@ -79,19 +79,22 @@ export class ProjectViewIssues extends BaseIssuesStore implements IProjectViewIs workspaceSlug: string, projectId: string, loadType: TLoader, - options: IssuePaginationOptions + options: IssuePaginationOptions, + isExistingPaginationOptions: boolean = false ) => { try { // set loader and clear store runInAction(() => { this.setLoader(loadType); }); - this.clear(); + this.clear(!isExistingPaginationOptions); // get params from pagination options const params = this.issueFilterStore?.getFilterParams(options, undefined, undefined, undefined); // call the fetch issues API with the params - const response = await this.issueService.getIssues(workspaceSlug, projectId, params); + const response = await this.issueService.getIssues(workspaceSlug, projectId, params, { + signal: this.controller.signal, + }); // after fetching issues, call the base method to process the response further this.onfetchIssues(response, options, workspaceSlug, projectId); @@ -151,7 +154,7 @@ export class ProjectViewIssues extends BaseIssuesStore implements IProjectViewIs */ fetchIssuesWithExistingPagination = async (workspaceSlug: string, projectId: string, loadType: TLoader) => { if (!this.paginationOptions) return; - return await this.fetchIssues(workspaceSlug, projectId, loadType, this.paginationOptions); + return await this.fetchIssues(workspaceSlug, projectId, loadType, this.paginationOptions, true); }; archiveBulkIssues = this.bulkArchiveIssues; diff --git a/web/core/store/issue/project/issue.store.ts b/web/core/store/issue/project/issue.store.ts index 212add8f5b..0136fe907c 100644 --- a/web/core/store/issue/project/issue.store.ts +++ b/web/core/store/issue/project/issue.store.ts @@ -82,19 +82,22 @@ export class ProjectIssues extends BaseIssuesStore implements IProjectIssues { workspaceSlug: string, projectId: string, loadType: TLoader = "init-loader", - options: IssuePaginationOptions + options: IssuePaginationOptions, + isExistingPaginationOptions: boolean = false ) => { try { // set loader and clear store runInAction(() => { this.setLoader(loadType); }); - this.clear(); + this.clear(!isExistingPaginationOptions); // get params from pagination options const params = this.issueFilterStore?.getFilterParams(options, undefined, undefined, undefined); // call the fetch issues API with the params - const response = await this.issueService.getIssues(workspaceSlug, projectId, params); + const response = await this.issueService.getIssues(workspaceSlug, projectId, params, { + signal: this.controller.signal, + }); // after fetching issues, call the base method to process the response further this.onfetchIssues(response, options, workspaceSlug, projectId); @@ -158,7 +161,7 @@ export class ProjectIssues extends BaseIssuesStore implements IProjectIssues { loadType: TLoader = "mutation" ) => { if (!this.paginationOptions) return; - return await this.fetchIssues(workspaceSlug, projectId, loadType, this.paginationOptions); + return await this.fetchIssues(workspaceSlug, projectId, loadType, this.paginationOptions, true); }; archiveBulkIssues = this.bulkArchiveIssues; diff --git a/web/core/store/issue/workspace/issue.store.ts b/web/core/store/issue/workspace/issue.store.ts index c1eaaa66dd..20191fa544 100644 --- a/web/core/store/issue/workspace/issue.store.ts +++ b/web/core/store/issue/workspace/issue.store.ts @@ -77,18 +77,26 @@ export class WorkspaceIssues extends BaseIssuesStore implements IWorkspaceIssues * @param options * @returns */ - fetchIssues = async (workspaceSlug: string, viewId: string, loadType: TLoader, options: IssuePaginationOptions) => { + fetchIssues = async ( + workspaceSlug: string, + viewId: string, + loadType: TLoader, + options: IssuePaginationOptions, + isExistingPaginationOptions: boolean = false + ) => { try { // set loader and clear store runInAction(() => { this.setLoader(loadType); }); - this.clear(); + this.clear(!isExistingPaginationOptions); // get params from pagination options const params = this.issueFilterStore?.getFilterParams(viewId, options, undefined, undefined, undefined); // call the fetch issues API with the params - const response = await this.workspaceService.getViewIssues(workspaceSlug, params); + const response = await this.workspaceService.getViewIssues(workspaceSlug, params, { + signal: this.controller.signal, + }); // after fetching issues, call the base method to process the response further this.onfetchIssues(response, options, workspaceSlug); @@ -149,7 +157,7 @@ export class WorkspaceIssues extends BaseIssuesStore implements IWorkspaceIssues */ fetchIssuesWithExistingPagination = async (workspaceSlug: string, viewId: string, loadType: TLoader) => { if (!this.paginationOptions) return; - return await this.fetchIssues(workspaceSlug, viewId, loadType, this.paginationOptions); + return await this.fetchIssues(workspaceSlug, viewId, loadType, this.paginationOptions, true); }; archiveBulkIssues = this.bulkArchiveIssues;