plane/web/store/inbox/inbox-issue.store.ts
guru_sainath 20b0edeaa6
[WEB-999] chore: updated UI improvements and workflow updates in the project inbox (#4180)
* chore: snoozed filter in the issue inbox filter

* chore: navigating to the next or previous issue when we accept, decline, or duplicate the issue in inbox

* chore: Implemented state, label, assignee and target_date in the inbox issue description and Implemented issue edit confirmation once we click accept the inbox issue

* chore: removed logs

* chore: inbox issue create response

* chore: update inbox issue response

* chore: updated inbox issue accept workflow and added issue properties in inbox issue create modal

* chore: resolved build errors and upgraded lucide react

* chore: updated inbox issue store hook

* chore: code cleanup and removed validation for inbox description

* fix: renamed the variable isLoading to loader in project-inbox store

* fix: updated set function for issue property update

---------

Co-authored-by: NarayanBavisetti <narayan3119@gmail.com>
2024-04-15 12:49:14 +05:30

193 lines
6.6 KiB
TypeScript

import clone from "lodash/clone";
import set from "lodash/set";
import { makeObservable, observable, runInAction, action } from "mobx";
import { TIssue, TInboxIssue, TInboxIssueStatus, TInboxDuplicateIssueDetails } from "@plane/types";
// helpers
import { EInboxIssueStatus } from "@/helpers/inbox.helper";
// services
import { InboxIssueService } from "@/services/inbox";
import { IssueService } from "@/services/issue";
// root store
import { RootStore } from "@/store/root.store";
export interface IInboxIssueStore {
isLoading: boolean;
id: string;
status: TInboxIssueStatus;
issue: Partial<TIssue>;
snoozed_till: Date | 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) => 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;
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: RootStore) {
this.id = data.id;
this.status = data.status;
this.issue = data?.issue;
this.snoozed_till = data?.snoozed_till ? new Date(data.snoozed_till) : undefined;
this.duplicate_to = data?.duplicate_to || undefined;
this.created_by = data?.created_by || 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,
// 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));
} 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,
};
try {
if (!this.issue.id) return;
const issueResponse = await this.inboxIssueService.update(this.workspaceSlug, this.projectId, this.issue.id, {
status: inboxStatus,
duplicate_to: issueId,
});
runInAction(() => {
this.status = issueResponse.status;
this.duplicate_to = issueResponse.duplicate_to;
this.duplicate_issue_detail = issueResponse.duplicate_issue_detail;
});
} catch {
runInAction(() => {
set(this, "status", previousData.status);
set(this, "duplicate_to", previousData.duplicate_to);
});
}
};
updateInboxIssueSnoozeTill = async (date: Date) => {
const inboxStatus = EInboxIssueStatus.SNOOZED;
const previousData: Partial<TInboxIssue> = {
status: this.status,
snoozed_till: this.snoozed_till,
};
try {
if (!this.issue.id) return;
const issueResponse = await this.inboxIssueService.update(this.workspaceSlug, this.projectId, this.issue.id, {
status: inboxStatus,
snoozed_till: new Date(date),
});
runInAction(() => {
this.status = issueResponse?.status;
this.snoozed_till = issueResponse?.snoozed_till ? new Date(issueResponse.snoozed_till) : undefined;
});
} 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);
// 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");
}
};
}