feat: init
Some checks failed
CodeQL / Analyze (javascript) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled

This commit is contained in:
chuan
2025-11-11 01:56:44 +08:00
commit bba4bb40c8
4638 changed files with 447437 additions and 0 deletions

View File

@@ -0,0 +1,231 @@
import { clone, set } from "lodash-es";
import { makeObservable, observable, runInAction, action } from "mobx";
import type {
TInboxIssue,
TInboxIssueStatus,
EInboxIssueSource,
TIssue,
TInboxDuplicateIssueDetails,
} from "@plane/types";
import { EInboxIssueStatus } from "@plane/types";
// helpers
// local db
import { addIssueToPersistanceLayer } from "@/local-db/utils/utils";
// services
import { InboxIssueService } from "@/services/inbox";
import { IssueService } from "@/services/issue";
// store
import type { CoreRootStore } from "../root.store";
export interface IInboxIssueStore {
isLoading: boolean;
id: string;
status: TInboxIssueStatus;
issue: Partial<TIssue>;
snoozed_till: Date | undefined;
source: EInboxIssueSource | undefined;
duplicate_to: string | undefined;
created_by: string | undefined;
duplicate_issue_detail: TInboxDuplicateIssueDetails | undefined;
// actions
updateInboxIssueStatus: (status: TInboxIssueStatus) => Promise<void>; // accept, decline
updateInboxIssueDuplicateTo: (issueId: string) => Promise<void>; // connecting the inbox issue to the project existing issue
updateInboxIssueSnoozeTill: (date: Date | undefined) => Promise<void>; // snooze the issue
updateIssue: (issue: Partial<TIssue>) => Promise<void>; // updating the issue
updateProjectIssue: (issue: Partial<TIssue>) => Promise<void>; // updating the issue
fetchIssueActivity: () => Promise<void>; // fetching the issue activity
}
export class InboxIssueStore implements IInboxIssueStore {
// observables
isLoading: boolean = false;
id: string;
status: TInboxIssueStatus = EInboxIssueStatus.PENDING;
issue: Partial<TIssue> = {};
snoozed_till: Date | undefined;
source: EInboxIssueSource | undefined;
duplicate_to: string | undefined;
created_by: string | undefined;
duplicate_issue_detail: TInboxDuplicateIssueDetails | undefined = undefined;
workspaceSlug: string;
projectId: string;
// services
inboxIssueService;
issueService;
constructor(
workspaceSlug: string,
projectId: string,
data: TInboxIssue,
private store: CoreRootStore
) {
this.id = data.id;
this.status = data.status;
this.issue = data?.issue;
this.snoozed_till = data?.snoozed_till || undefined;
this.duplicate_to = data?.duplicate_to || undefined;
this.created_by = data?.created_by || undefined;
this.source = data?.source || undefined;
this.duplicate_issue_detail = data?.duplicate_issue_detail || undefined;
this.workspaceSlug = workspaceSlug;
this.projectId = projectId;
// services
this.inboxIssueService = new InboxIssueService();
this.issueService = new IssueService();
// observable variables should be defined after the initialization of the values
makeObservable(this, {
id: observable,
status: observable,
issue: observable,
snoozed_till: observable,
duplicate_to: observable,
duplicate_issue_detail: observable,
created_by: observable,
source: observable,
// actions
updateInboxIssueStatus: action,
updateInboxIssueDuplicateTo: action,
updateInboxIssueSnoozeTill: action,
updateIssue: action,
updateProjectIssue: action,
fetchIssueActivity: action,
});
}
updateInboxIssueStatus = async (status: TInboxIssueStatus) => {
const previousData: Partial<TInboxIssue> = {
status: this.status,
};
try {
if (!this.issue.id) return;
const inboxIssue = await this.inboxIssueService.update(this.workspaceSlug, this.projectId, this.issue.id, {
status: status,
});
runInAction(() => set(this, "status", inboxIssue?.status));
// If issue accepted sync issue to local db
if (status === EInboxIssueStatus.ACCEPTED) {
const updatedIssue = { ...this.issue, ...inboxIssue.issue };
this.store.issue.issues.addIssue([updatedIssue]);
await addIssueToPersistanceLayer(updatedIssue);
}
} catch {
runInAction(() => set(this, "status", previousData.status));
}
};
updateInboxIssueDuplicateTo = async (issueId: string) => {
const inboxStatus = EInboxIssueStatus.DUPLICATE;
const previousData: Partial<TInboxIssue> = {
status: this.status,
duplicate_to: this.duplicate_to,
duplicate_issue_detail: this.duplicate_issue_detail,
};
try {
if (!this.issue.id) return;
const inboxIssue = await this.inboxIssueService.update(this.workspaceSlug, this.projectId, this.issue.id, {
status: inboxStatus,
duplicate_to: issueId,
});
runInAction(() => {
set(this, "status", inboxIssue?.status);
set(this, "duplicate_to", inboxIssue?.duplicate_to);
set(this, "duplicate_issue_detail", inboxIssue?.duplicate_issue_detail);
});
} catch {
runInAction(() => {
set(this, "status", previousData.status);
set(this, "duplicate_to", previousData.duplicate_to);
set(this, "duplicate_issue_detail", previousData.duplicate_issue_detail);
});
}
};
updateInboxIssueSnoozeTill = async (date: Date | undefined) => {
const inboxStatus = date ? EInboxIssueStatus.SNOOZED : EInboxIssueStatus.PENDING;
const previousData: Partial<TInboxIssue> = {
status: this.status,
snoozed_till: this.snoozed_till,
};
try {
if (!this.issue.id) return;
const inboxIssue = await this.inboxIssueService.update(this.workspaceSlug, this.projectId, this.issue.id, {
status: inboxStatus,
snoozed_till: date ? new Date(date) : null,
});
runInAction(() => {
set(this, "status", inboxIssue?.status);
set(this, "snoozed_till", inboxIssue?.snoozed_till);
});
} catch {
runInAction(() => {
set(this, "status", previousData.status);
set(this, "snoozed_till", previousData.snoozed_till);
});
}
};
updateIssue = async (issue: Partial<TIssue>) => {
const inboxIssue = clone(this.issue);
try {
if (!this.issue.id) return;
Object.keys(issue).forEach((key) => {
const issueKey = key as keyof TIssue;
set(this.issue, issueKey, issue[issueKey]);
});
await this.inboxIssueService.updateIssue(this.workspaceSlug, this.projectId, this.issue.id, issue);
// fetching activity
this.fetchIssueActivity();
} catch {
Object.keys(issue).forEach((key) => {
const issueKey = key as keyof TIssue;
set(this.issue, issueKey, inboxIssue[issueKey]);
});
}
};
updateProjectIssue = async (issue: Partial<TIssue>) => {
const inboxIssue = clone(this.issue);
try {
if (!this.issue.id) return;
Object.keys(issue).forEach((key) => {
const issueKey = key as keyof TIssue;
set(this.issue, issueKey, issue[issueKey]);
});
await this.issueService.patchIssue(this.workspaceSlug, this.projectId, this.issue.id, issue);
if (issue.cycle_id) {
await this.store.issue.issueDetail.addIssueToCycle(this.workspaceSlug, this.projectId, issue.cycle_id, [
this.issue.id,
]);
}
if (issue.module_ids) {
await this.store.issue.issueDetail.changeModulesInIssue(
this.workspaceSlug,
this.projectId,
this.issue.id,
issue.module_ids,
[]
);
}
// fetching activity
this.fetchIssueActivity();
} catch {
Object.keys(issue).forEach((key) => {
const issueKey = key as keyof TIssue;
set(this.issue, issueKey, inboxIssue[issueKey]);
});
}
};
fetchIssueActivity = async () => {
try {
if (!this.issue.id) return;
await this.store.issue.issueDetail.fetchActivities(this.workspaceSlug, this.projectId, this.issue.id);
} catch {
console.error("Failed to fetch issue activity");
}
};
}

View File

@@ -0,0 +1,507 @@
import { uniq, update, isEmpty, omit, set } from "lodash-es";
import { action, computed, makeObservable, observable, runInAction } from "mobx";
import { computedFn } from "mobx-utils";
import type { EPastDurationFilters } from "@plane/constants";
// types
import type {
TInboxIssue,
TInboxIssueCurrentTab,
TInboxIssueFilter,
TInboxIssueSorting,
TInboxIssuePaginationInfo,
TInboxIssueSortingOrderByQueryParam,
} from "@plane/types";
import { EInboxIssueCurrentTab, EInboxIssueStatus } from "@plane/types";
import { getCustomDates } from "@plane/utils";
// helpers
// services
import { InboxIssueService } from "@/services/inbox";
// root store
import type { IInboxIssueStore } from "@/store/inbox/inbox-issue.store";
import { InboxIssueStore } from "@/store/inbox/inbox-issue.store";
import type { CoreRootStore } from "../root.store";
type TLoader =
| "init-loading"
| "mutation-loading"
| "filter-loading"
| "pagination-loading"
| "issue-loading"
| undefined;
export interface IProjectInboxStore {
currentTab: TInboxIssueCurrentTab;
loader: TLoader;
error: { message: string; status: "init-error" | "pagination-error" } | undefined;
currentInboxProjectId: string;
filtersMap: Record<string, Partial<TInboxIssueFilter>>; // projectId -> Partial<TInboxIssueFilter>
sortingMap: Record<string, Partial<TInboxIssueSorting>>; // projectId -> Partial<TInboxIssueSorting>
inboxIssuePaginationInfo: TInboxIssuePaginationInfo | undefined;
inboxIssues: Record<string, IInboxIssueStore>; // issue_id -> IInboxIssueStore
inboxIssueIds: string[];
// computed
inboxFilters: Partial<TInboxIssueFilter>; // computed project inbox filters
inboxSorting: Partial<TInboxIssueSorting>; // computed project inbox sorting
getAppliedFiltersCount: number;
filteredInboxIssueIds: string[];
// computed functions
getIssueInboxByIssueId: (issueId: string) => IInboxIssueStore;
getIsIssueAvailable: (inboxIssueId: string) => boolean;
// helper actions
inboxIssueQueryParams: (
inboxFilters: Partial<TInboxIssueFilter>,
inboxSorting: Partial<TInboxIssueSorting>,
pagePerCount: number,
paginationCursor: string
) => Partial<Record<keyof TInboxIssueFilter, string>>;
createOrUpdateInboxIssue: (inboxIssues: TInboxIssue[], workspaceSlug: string, projectId: string) => void;
initializeDefaultFilters: (projectId: string, tab: TInboxIssueCurrentTab) => void;
// actions
handleCurrentTab: (workspaceSlug: string, projectId: string, tab: TInboxIssueCurrentTab) => void;
handleInboxIssueFilters: <T extends keyof TInboxIssueFilter>(key: T, value: TInboxIssueFilter[T]) => void; // if user sends me undefined, I will remove the value from the filter key
handleInboxIssueSorting: <T extends keyof TInboxIssueSorting>(key: T, value: TInboxIssueSorting[T]) => void; // if user sends me undefined, I will remove the value from the filter key
fetchInboxIssues: (
workspaceSlug: string,
projectId: string,
loadingType?: TLoader,
tab?: TInboxIssueCurrentTab | undefined
) => Promise<void>;
fetchInboxPaginationIssues: (workspaceSlug: string, projectId: string) => Promise<void>;
fetchInboxIssueById: (workspaceSlug: string, projectId: string, inboxIssueId: string) => Promise<TInboxIssue>;
createInboxIssue: (
workspaceSlug: string,
projectId: string,
data: Partial<TInboxIssue>
) => Promise<TInboxIssue | undefined>;
deleteInboxIssue: (workspaceSlug: string, projectId: string, inboxIssueId: string) => Promise<void>;
}
export class ProjectInboxStore implements IProjectInboxStore {
// constants
PER_PAGE_COUNT = 10;
// observables
currentTab: TInboxIssueCurrentTab = EInboxIssueCurrentTab.OPEN;
loader: TLoader = "init-loading";
error: { message: string; status: "init-error" | "pagination-error" } | undefined = undefined;
currentInboxProjectId: string = "";
filtersMap: Record<string, Partial<TInboxIssueFilter>> = {};
sortingMap: Record<string, Partial<TInboxIssueSorting>> = {};
inboxIssuePaginationInfo: TInboxIssuePaginationInfo | undefined = undefined;
inboxIssues: Record<string, IInboxIssueStore> = {};
inboxIssueIds: string[] = [];
// services
inboxIssueService;
constructor(private store: CoreRootStore) {
makeObservable(this, {
currentTab: observable.ref,
loader: observable.ref,
error: observable,
currentInboxProjectId: observable.ref,
filtersMap: observable,
sortingMap: observable,
inboxIssuePaginationInfo: observable,
inboxIssues: observable,
inboxIssueIds: observable,
// computed
inboxFilters: computed,
inboxSorting: computed,
getAppliedFiltersCount: computed,
filteredInboxIssueIds: computed,
// actions
handleInboxIssueFilters: action,
handleInboxIssueSorting: action,
fetchInboxIssues: action,
fetchInboxPaginationIssues: action,
fetchInboxIssueById: action,
createInboxIssue: action,
deleteInboxIssue: action,
});
this.inboxIssueService = new InboxIssueService();
}
// computed
/**
* @description computed project inbox filters
*/
get inboxFilters() {
const { projectId } = this.store.router;
if (!projectId) return {} as TInboxIssueFilter;
return this.filtersMap?.[projectId];
}
/**
* @description computed project inbox sorting
*/
get inboxSorting() {
const { projectId } = this.store.router;
if (!projectId) return {} as TInboxIssueSorting;
return this.sortingMap?.[projectId];
}
get getAppliedFiltersCount() {
let count = 0;
this.inboxFilters != undefined &&
Object.keys(this.inboxFilters).forEach((key) => {
const filterKey = key as keyof TInboxIssueFilter;
if (this.inboxFilters[filterKey] && this.inboxFilters?.[filterKey])
count = count + (this.inboxFilters?.[filterKey]?.length ?? 0);
});
return count;
}
get filteredInboxIssueIds() {
let appliedFilters =
this.currentTab === EInboxIssueCurrentTab.OPEN
? [EInboxIssueStatus.PENDING, EInboxIssueStatus.SNOOZED]
: [EInboxIssueStatus.ACCEPTED, EInboxIssueStatus.DECLINED, EInboxIssueStatus.DUPLICATE];
appliedFilters = appliedFilters.filter((filter) => this.inboxFilters?.status?.includes(filter));
const currentTime = new Date().getTime();
return this.currentTab === EInboxIssueCurrentTab.OPEN
? this.inboxIssueIds.filter((id) => {
if (appliedFilters.length == 2) return true;
if (appliedFilters[0] === EInboxIssueStatus.SNOOZED)
return (
this.inboxIssues[id].status === EInboxIssueStatus.SNOOZED &&
currentTime < new Date(this.inboxIssues[id].snoozed_till!).getTime()
);
if (appliedFilters[0] === EInboxIssueStatus.PENDING)
return (
appliedFilters.includes(this.inboxIssues[id].status) ||
(this.inboxIssues[id].status === EInboxIssueStatus.SNOOZED &&
currentTime > new Date(this.inboxIssues[id].snoozed_till!).getTime())
);
})
: this.inboxIssueIds.filter((id) => appliedFilters.includes(this.inboxIssues[id].status));
}
getIssueInboxByIssueId = computedFn((issueId: string) => this.inboxIssues?.[issueId]);
getIsIssueAvailable = computedFn((inboxIssueId: string) => {
if (!this.inboxIssueIds) return true;
return this.inboxIssueIds.includes(inboxIssueId);
});
inboxIssueQueryParams = (
inboxFilters: Partial<TInboxIssueFilter>,
inboxSorting: Partial<TInboxIssueSorting>,
pagePerCount: number,
paginationCursor: string
) => {
const filters: Partial<Record<keyof TInboxIssueFilter, string>> = {};
!isEmpty(inboxFilters) &&
Object.keys(inboxFilters).forEach((key) => {
const filterKey = key as keyof TInboxIssueFilter;
if (inboxFilters[filterKey] && inboxFilters[filterKey]?.length) {
if (["created_at", "updated_at"].includes(filterKey) && (inboxFilters[filterKey] || [])?.length > 0) {
const appliedDateFilters: string[] = [];
inboxFilters[filterKey]?.forEach((value) => {
const dateValue = value as EPastDurationFilters;
appliedDateFilters.push(getCustomDates(dateValue));
});
filters[filterKey] = appliedDateFilters?.join(",");
} else filters[filterKey] = inboxFilters[filterKey]?.join(",");
}
});
const sorting: TInboxIssueSortingOrderByQueryParam = {
order_by: "-issue__created_at",
};
if (inboxSorting?.order_by && inboxSorting?.sort_by) {
switch (inboxSorting.order_by) {
case "issue__created_at":
if (inboxSorting.sort_by === "desc") sorting.order_by = `-issue__created_at`;
else sorting.order_by = "issue__created_at";
break;
case "issue__updated_at":
if (inboxSorting.sort_by === "desc") sorting.order_by = `-issue__updated_at`;
else sorting.order_by = "issue__updated_at";
break;
case "issue__sequence_id":
if (inboxSorting.sort_by === "desc") sorting.order_by = `-issue__sequence_id`;
else sorting.order_by = "issue__sequence_id";
break;
default:
sorting.order_by = "-issue__created_at";
break;
}
}
return {
...filters,
...sorting,
per_page: pagePerCount,
cursor: paginationCursor,
};
};
createOrUpdateInboxIssue = (inboxIssues: TInboxIssue[], workspaceSlug: string, projectId: string) => {
if (inboxIssues && inboxIssues.length > 0) {
inboxIssues.forEach((inbox: TInboxIssue) => {
const existingInboxIssueDetail = this.getIssueInboxByIssueId(inbox?.issue?.id);
if (existingInboxIssueDetail)
Object.assign(existingInboxIssueDetail, {
...inbox,
issue: {
...existingInboxIssueDetail.issue,
...inbox.issue,
},
});
else
set(this.inboxIssues, [inbox?.issue?.id], new InboxIssueStore(workspaceSlug, projectId, inbox, this.store));
});
}
};
// actions
handleCurrentTab = (workspaceSlug: string, projectId: string, tab: TInboxIssueCurrentTab) => {
if (workspaceSlug && projectId) {
runInAction(() => {
set(this, "currentTab", tab);
set(this, ["inboxIssueIds"], []);
set(this, ["inboxIssuePaginationInfo"], undefined);
set(this.sortingMap, [projectId], { order_by: "issue__created_at", sort_by: "desc" });
set(this.filtersMap, [projectId], {
status:
tab === EInboxIssueCurrentTab.OPEN
? [EInboxIssueStatus.PENDING]
: [EInboxIssueStatus.ACCEPTED, EInboxIssueStatus.DECLINED, EInboxIssueStatus.DUPLICATE],
});
});
this.fetchInboxIssues(workspaceSlug, projectId, "filter-loading");
}
};
handleInboxIssueFilters = <T extends keyof TInboxIssueFilter>(key: T, value: TInboxIssueFilter[T]) => {
const { workspaceSlug, projectId } = this.store.router;
if (workspaceSlug && projectId) {
runInAction(() => {
set(this.filtersMap, [projectId, key], value);
set(this, ["inboxIssuePaginationInfo"], undefined);
});
this.fetchInboxIssues(workspaceSlug, projectId, "filter-loading");
}
};
handleInboxIssueSorting = <T extends keyof TInboxIssueSorting>(key: T, value: TInboxIssueSorting[T]) => {
const { workspaceSlug, projectId } = this.store.router;
if (workspaceSlug && projectId) {
runInAction(() => {
set(this.sortingMap, [projectId, key], value);
set(this, ["inboxIssuePaginationInfo"], undefined);
});
this.fetchInboxIssues(workspaceSlug, projectId, "filter-loading");
}
};
initializeDefaultFilters = (projectId: string, tab: TInboxIssueCurrentTab) => {
if (!projectId || !tab) return;
if (isEmpty(this.inboxFilters)) {
set(this.filtersMap, [projectId], {
status:
tab === EInboxIssueCurrentTab.OPEN
? [EInboxIssueStatus.PENDING]
: [EInboxIssueStatus.ACCEPTED, EInboxIssueStatus.DECLINED, EInboxIssueStatus.DUPLICATE],
});
}
if (isEmpty(this.inboxSorting)) {
set(this.sortingMap, [projectId], { order_by: "issue__created_at", sort_by: "desc" });
}
};
/**
* @description fetch intake issues with paginated data
* @param workspaceSlug
* @param projectId
*/
fetchInboxIssues = async (
workspaceSlug: string,
projectId: string,
loadingType: TLoader = undefined,
tab: TInboxIssueCurrentTab | undefined = undefined
) => {
try {
if (loadingType === undefined && tab) this.initializeDefaultFilters(projectId, tab);
if (this.currentInboxProjectId != projectId) {
runInAction(() => {
set(this, ["currentInboxProjectId"], projectId);
set(this, ["inboxIssues"], {});
set(this, ["inboxIssueIds"], []);
set(this, ["inboxIssuePaginationInfo"], undefined);
});
}
if (Object.keys(this.inboxIssueIds).length === 0) this.loader = "init-loading";
else this.loader = "mutation-loading";
if (loadingType) this.loader = loadingType;
const status = this.inboxFilters?.status;
const queryParams = this.inboxIssueQueryParams(
{ ...this.inboxFilters, status },
this.inboxSorting,
this.PER_PAGE_COUNT,
`${this.PER_PAGE_COUNT}:0:0`
);
const { results, ...paginationInfo } = await this.inboxIssueService.list(workspaceSlug, projectId, queryParams);
runInAction(() => {
this.loader = undefined;
set(this, "inboxIssuePaginationInfo", paginationInfo);
if (results) {
const issueIds = results.map((value) => value?.issue?.id);
set(this, ["inboxIssueIds"], issueIds);
this.createOrUpdateInboxIssue(results, workspaceSlug, projectId);
}
});
} catch (error) {
console.error("Error fetching the intake issues", error);
this.loader = undefined;
this.error = {
message: "Error fetching the intake work items please try again later.",
status: "init-error",
};
throw error;
}
};
/**
* @description fetch intake issues with paginated data
* @param workspaceSlug
* @param projectId
*/
fetchInboxPaginationIssues = async (workspaceSlug: string, projectId: string) => {
try {
if (
this.inboxIssuePaginationInfo &&
(!this.inboxIssuePaginationInfo?.total_results ||
(this.inboxIssuePaginationInfo?.total_results &&
this.inboxIssueIds.length < this.inboxIssuePaginationInfo?.total_results))
) {
const queryParams = this.inboxIssueQueryParams(
this.inboxFilters,
this.inboxSorting,
this.PER_PAGE_COUNT,
this.inboxIssuePaginationInfo?.next_cursor || `${this.PER_PAGE_COUNT}:0:0`
);
const { results, ...paginationInfo } = await this.inboxIssueService.list(workspaceSlug, projectId, queryParams);
runInAction(() => {
set(this, "inboxIssuePaginationInfo", paginationInfo);
if (results && results.length > 0) {
const issueIds = results.map((value) => value?.issue?.id);
update(this, ["inboxIssueIds"], (ids) => uniq([...ids, ...issueIds]));
this.createOrUpdateInboxIssue(results, workspaceSlug, projectId);
}
});
} else set(this, ["inboxIssuePaginationInfo", "next_page_results"], false);
} catch (error) {
console.error("Error fetching the intake issues", error);
this.error = {
message: "Error fetching the paginated intake work items please try again later.",
status: "pagination-error",
};
throw error;
}
};
/**
* @description fetch intake issue with issue id
* @param workspaceSlug
* @param projectId
* @param inboxIssueId
*/
fetchInboxIssueById = async (
workspaceSlug: string,
projectId: string,
inboxIssueId: string
): Promise<TInboxIssue> => {
try {
this.loader = "issue-loading";
const inboxIssue = await this.inboxIssueService.retrieve(workspaceSlug, projectId, inboxIssueId);
const issueId = inboxIssue?.issue?.id || undefined;
if (inboxIssue && issueId) {
runInAction(() => {
this.createOrUpdateInboxIssue([inboxIssue], workspaceSlug, projectId);
set(this, "loader", undefined);
});
await Promise.all([
// fetching reactions
this.store.issue.issueDetail.fetchReactions(workspaceSlug, projectId, issueId),
// fetching activity
this.store.issue.issueDetail.fetchActivities(workspaceSlug, projectId, issueId),
// fetching comments
this.store.issue.issueDetail.fetchComments(workspaceSlug, projectId, issueId),
// fetching attachments
this.store.issue.issueDetail.fetchAttachments(workspaceSlug, projectId, issueId),
]);
}
return inboxIssue;
} catch (error) {
console.error("Error fetching the intake issue with intake issue id");
this.loader = undefined;
throw error;
}
};
/**
* @description create intake issue
* @param workspaceSlug
* @param projectId
* @param data
*/
createInboxIssue = async (workspaceSlug: string, projectId: string, data: Partial<TInboxIssue>) => {
try {
const inboxIssueResponse = await this.inboxIssueService.create(workspaceSlug, projectId, data);
if (inboxIssueResponse)
runInAction(() => {
update(this, ["inboxIssueIds"], (ids) => [...ids, inboxIssueResponse?.issue?.id]);
set(
this.inboxIssues,
[inboxIssueResponse?.issue?.id],
new InboxIssueStore(workspaceSlug, projectId, inboxIssueResponse, this.store)
);
set(
this,
["inboxIssuePaginationInfo", "total_results"],
(this.inboxIssuePaginationInfo?.total_results || 0) + 1
);
});
return inboxIssueResponse;
} catch {
console.error("Error creating the intake issue");
}
};
/**
* @description delete intake issue
* @param workspaceSlug
* @param projectId
* @param inboxIssueId
*/
deleteInboxIssue = async (workspaceSlug: string, projectId: string, inboxIssueId: string) => {
const currentIssue = this.inboxIssues?.[inboxIssueId];
try {
if (!currentIssue) return;
await this.inboxIssueService.destroy(workspaceSlug, projectId, inboxIssueId).then(() => {
runInAction(() => {
set(
this,
["inboxIssuePaginationInfo", "total_results"],
(this.inboxIssuePaginationInfo?.total_results || 0) - 1
);
set(this, "inboxIssues", omit(this.inboxIssues, inboxIssueId));
set(
this,
["inboxIssueIds"],
this.inboxIssueIds.filter((id) => id !== inboxIssueId)
);
});
});
} catch (error) {
console.error("Error removing the intake issue");
throw error;
}
};
}