plane/web/store/issue/issue-details/attachment.store.ts
Nikhil 03e5f4a5bd
[WEB-468] fix: issue detail endpoints (#3722)
* dev: add is_subscriber to issue details endpoint

* dev: remove is_subscribed annotation from detail serializers

* dev: update issue details endpoint

* dev: inbox issue create

* dev: issue detail serializer

* dev: optimize and add extra fields for issue details

* dev: remove data from issue updates

* dev: add fields for issue link and attachment

* remove expecting a issue response while updating and deleting an issue

* change link, attachment and reaction types and modify store to recieve their data from within the issue detail API call

* make changes for subscription store to recieve data from issue detail API call

* dev: add issue reaction id

* add query prarms for archived issue

---------

Co-authored-by: rahulramesha <rahulramesham@gmail.com>
2024-02-22 20:58:34 +05:30

149 lines
4.6 KiB
TypeScript

import { action, computed, makeObservable, observable, runInAction } from "mobx";
import set from "lodash/set";
import update from "lodash/update";
import concat from "lodash/concat";
import uniq from "lodash/uniq";
import pull from "lodash/pull";
// services
import { IssueAttachmentService } from "services/issue";
// types
import { IIssueDetail } from "./root.store";
import { TIssueAttachment, TIssueAttachmentMap, TIssueAttachmentIdMap } from "@plane/types";
export interface IIssueAttachmentStoreActions {
addAttachments: (issueId: string, attachments: TIssueAttachment[]) => void;
fetchAttachments: (workspaceSlug: string, projectId: string, issueId: string) => Promise<TIssueAttachment[]>;
createAttachment: (
workspaceSlug: string,
projectId: string,
issueId: string,
data: FormData
) => Promise<TIssueAttachment>;
removeAttachment: (
workspaceSlug: string,
projectId: string,
issueId: string,
attachmentId: string
) => Promise<TIssueAttachment>;
}
export interface IIssueAttachmentStore extends IIssueAttachmentStoreActions {
// observables
attachments: TIssueAttachmentIdMap;
attachmentMap: TIssueAttachmentMap;
// computed
issueAttachments: string[] | undefined;
// helper methods
getAttachmentsByIssueId: (issueId: string) => string[] | undefined;
getAttachmentById: (attachmentId: string) => TIssueAttachment | undefined;
}
export class IssueAttachmentStore implements IIssueAttachmentStore {
// observables
attachments: TIssueAttachmentIdMap = {};
attachmentMap: TIssueAttachmentMap = {};
// root store
rootIssueDetailStore: IIssueDetail;
// services
issueAttachmentService;
constructor(rootStore: IIssueDetail) {
makeObservable(this, {
// observables
attachments: observable,
attachmentMap: observable,
// computed
issueAttachments: computed,
// actions
addAttachments: action.bound,
fetchAttachments: action,
createAttachment: action,
removeAttachment: action,
});
// root store
this.rootIssueDetailStore = rootStore;
// services
this.issueAttachmentService = new IssueAttachmentService();
}
// computed
get issueAttachments() {
const issueId = this.rootIssueDetailStore.peekIssue?.issueId;
if (!issueId) return undefined;
return this.attachments[issueId] ?? undefined;
}
// helper methods
getAttachmentsByIssueId = (issueId: string) => {
if (!issueId) return undefined;
return this.attachments[issueId] ?? undefined;
};
getAttachmentById = (attachmentId: string) => {
if (!attachmentId) return undefined;
return this.attachmentMap[attachmentId] ?? undefined;
};
// actions
addAttachments = (issueId: string, attachments: TIssueAttachment[]) => {
if (attachments && attachments.length > 0) {
const _attachmentIds = attachments.map((attachment) => attachment.id);
runInAction(() => {
update(this.attachments, [issueId], (attachmentIds = []) => uniq(concat(attachmentIds, _attachmentIds)));
attachments.forEach((attachment) => set(this.attachmentMap, attachment.id, attachment));
});
}
};
fetchAttachments = async (workspaceSlug: string, projectId: string, issueId: string) => {
try {
const response = await this.issueAttachmentService.getIssueAttachment(workspaceSlug, projectId, issueId);
this.addAttachments(issueId, response);
return response;
} catch (error) {
throw error;
}
};
createAttachment = async (workspaceSlug: string, projectId: string, issueId: string, data: FormData) => {
try {
const response = await this.issueAttachmentService.uploadIssueAttachment(workspaceSlug, projectId, issueId, data);
if (response && response.id)
runInAction(() => {
update(this.attachments, [issueId], (attachmentIds = []) => uniq(concat(attachmentIds, [response.id])));
set(this.attachmentMap, response.id, response);
});
return response;
} catch (error) {
throw error;
}
};
removeAttachment = async (workspaceSlug: string, projectId: string, issueId: string, attachmentId: string) => {
try {
const response = await this.issueAttachmentService.deleteIssueAttachment(
workspaceSlug,
projectId,
issueId,
attachmentId
);
runInAction(() => {
update(this.attachments, [issueId], (attachmentIds = []) => {
if (attachmentIds.includes(attachmentId)) pull(attachmentIds, attachmentId);
return attachmentIds;
});
delete this.attachmentMap[attachmentId];
});
return response;
} catch (error) {
throw error;
}
};
}