[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>
This commit is contained in:
parent
7927b7678d
commit
03e5f4a5bd
31 changed files with 490 additions and 324 deletions
|
|
@ -17,7 +17,7 @@ export interface IArchivedIssues {
|
|||
groupedIssueIds: TGroupedIssues | TSubGroupedIssues | TUnGroupedIssues | undefined;
|
||||
// actions
|
||||
fetchIssues: (workspaceSlug: string, projectId: string, loadType: TLoader) => Promise<TIssue>;
|
||||
removeIssue: (workspaceSlug: string, projectId: string, issueId: string) => Promise<TIssue>;
|
||||
removeIssue: (workspaceSlug: string, projectId: string, issueId: string) => Promise<void>;
|
||||
removeIssueFromArchived: (workspaceSlug: string, projectId: string, issueId: string) => Promise<void>;
|
||||
quickAddIssue: undefined;
|
||||
}
|
||||
|
|
@ -111,15 +111,13 @@ export class ArchivedIssues extends IssueHelperStore implements IArchivedIssues
|
|||
|
||||
removeIssue = async (workspaceSlug: string, projectId: string, issueId: string) => {
|
||||
try {
|
||||
const response = await this.rootIssueStore.projectIssues.removeIssue(workspaceSlug, projectId, issueId);
|
||||
await this.rootIssueStore.projectIssues.removeIssue(workspaceSlug, projectId, issueId);
|
||||
|
||||
const issueIndex = this.issues[projectId].findIndex((_issueId) => _issueId === issueId);
|
||||
if (issueIndex >= 0)
|
||||
runInAction(() => {
|
||||
this.issues[projectId].splice(issueIndex, 1);
|
||||
});
|
||||
|
||||
return response;
|
||||
} catch (error) {
|
||||
throw error;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -41,13 +41,13 @@ export interface ICycleIssues {
|
|||
issueId: string,
|
||||
data: Partial<TIssue>,
|
||||
cycleId?: string | undefined
|
||||
) => Promise<TIssue | undefined>;
|
||||
) => Promise<void>;
|
||||
removeIssue: (
|
||||
workspaceSlug: string,
|
||||
projectId: string,
|
||||
issueId: string,
|
||||
cycleId?: string | undefined
|
||||
) => Promise<TIssue | undefined>;
|
||||
) => Promise<void>;
|
||||
quickAddIssue: (
|
||||
workspaceSlug: string,
|
||||
projectId: string,
|
||||
|
|
@ -207,9 +207,8 @@ export class CycleIssues extends IssueHelperStore implements ICycleIssues {
|
|||
try {
|
||||
if (!cycleId) throw new Error("Cycle Id is required");
|
||||
|
||||
const response = await this.rootIssueStore.projectIssues.updateIssue(workspaceSlug, projectId, issueId, data);
|
||||
await this.rootIssueStore.projectIssues.updateIssue(workspaceSlug, projectId, issueId, data);
|
||||
this.rootIssueStore.rootStore.cycle.fetchCycleDetails(workspaceSlug, projectId, cycleId);
|
||||
return response;
|
||||
} catch (error) {
|
||||
this.fetchIssues(workspaceSlug, projectId, "mutation", cycleId);
|
||||
throw error;
|
||||
|
|
@ -225,7 +224,7 @@ export class CycleIssues extends IssueHelperStore implements ICycleIssues {
|
|||
try {
|
||||
if (!cycleId) throw new Error("Cycle Id is required");
|
||||
|
||||
const response = await this.rootIssueStore.projectIssues.removeIssue(workspaceSlug, projectId, issueId);
|
||||
await this.rootIssueStore.projectIssues.removeIssue(workspaceSlug, projectId, issueId);
|
||||
this.rootIssueStore.rootStore.cycle.fetchCycleDetails(workspaceSlug, projectId, cycleId);
|
||||
|
||||
const issueIndex = this.issues[cycleId].findIndex((_issueId) => _issueId === issueId);
|
||||
|
|
@ -233,8 +232,6 @@ export class CycleIssues extends IssueHelperStore implements ICycleIssues {
|
|||
runInAction(() => {
|
||||
this.issues[cycleId].splice(issueIndex, 1);
|
||||
});
|
||||
|
||||
return response;
|
||||
} catch (error) {
|
||||
throw error;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,8 +22,8 @@ export interface IDraftIssues {
|
|||
// actions
|
||||
fetchIssues: (workspaceSlug: string, projectId: string, loadType: TLoader) => Promise<TIssue[]>;
|
||||
createIssue: (workspaceSlug: string, projectId: string, data: Partial<TIssue>) => Promise<TIssue>;
|
||||
updateIssue: (workspaceSlug: string, projectId: string, issueId: string, data: Partial<TIssue>) => Promise<TIssue>;
|
||||
removeIssue: (workspaceSlug: string, projectId: string, issueId: string) => Promise<TIssue>;
|
||||
updateIssue: (workspaceSlug: string, projectId: string, issueId: string, data: Partial<TIssue>) => Promise<void>;
|
||||
removeIssue: (workspaceSlug: string, projectId: string, issueId: string) => Promise<void>;
|
||||
quickAddIssue: undefined;
|
||||
}
|
||||
|
||||
|
|
@ -141,7 +141,7 @@ export class DraftIssues extends IssueHelperStore implements IDraftIssues {
|
|||
|
||||
updateIssue = async (workspaceSlug: string, projectId: string, issueId: string, data: Partial<TIssue>) => {
|
||||
try {
|
||||
const response = await this.rootIssueStore.projectIssues.updateIssue(workspaceSlug, projectId, issueId, data);
|
||||
await this.rootIssueStore.projectIssues.updateIssue(workspaceSlug, projectId, issueId, data);
|
||||
|
||||
if (data.hasOwnProperty("is_draft") && data?.is_draft === false) {
|
||||
runInAction(() => {
|
||||
|
|
@ -151,8 +151,6 @@ export class DraftIssues extends IssueHelperStore implements IDraftIssues {
|
|||
});
|
||||
});
|
||||
}
|
||||
|
||||
return response;
|
||||
} catch (error) {
|
||||
this.fetchIssues(workspaceSlug, projectId, "mutation");
|
||||
throw error;
|
||||
|
|
@ -161,7 +159,7 @@ export class DraftIssues extends IssueHelperStore implements IDraftIssues {
|
|||
|
||||
removeIssue = async (workspaceSlug: string, projectId: string, issueId: string) => {
|
||||
try {
|
||||
const response = await this.rootIssueStore.projectIssues.removeIssue(workspaceSlug, projectId, issueId);
|
||||
await this.rootIssueStore.projectIssues.removeIssue(workspaceSlug, projectId, issueId);
|
||||
|
||||
runInAction(() => {
|
||||
update(this.issues, [projectId], (issueIds = []) => {
|
||||
|
|
@ -169,8 +167,6 @@ export class DraftIssues extends IssueHelperStore implements IDraftIssues {
|
|||
return issueIds;
|
||||
});
|
||||
});
|
||||
|
||||
return response;
|
||||
} catch (error) {
|
||||
throw error;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ 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,
|
||||
|
|
@ -54,6 +55,7 @@ export class IssueAttachmentStore implements IIssueAttachmentStore {
|
|||
// computed
|
||||
issueAttachments: computed,
|
||||
// actions
|
||||
addAttachments: action.bound,
|
||||
fetchAttachments: action,
|
||||
createAttachment: action,
|
||||
removeAttachment: action,
|
||||
|
|
@ -83,17 +85,21 @@ export class IssueAttachmentStore implements IIssueAttachmentStore {
|
|||
};
|
||||
|
||||
// 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);
|
||||
|
||||
if (response && response.length > 0) {
|
||||
const _attachmentIds = response.map((attachment) => attachment.id);
|
||||
runInAction(() => {
|
||||
update(this.attachments, [issueId], (attachmentIds = []) => uniq(concat(attachmentIds, _attachmentIds)));
|
||||
response.forEach((attachment) => set(this.attachmentMap, attachment.id, attachment));
|
||||
});
|
||||
}
|
||||
this.addAttachments(issueId, response);
|
||||
|
||||
return response;
|
||||
} catch (error) {
|
||||
|
|
|
|||
|
|
@ -2,15 +2,15 @@ import { makeObservable } from "mobx";
|
|||
// services
|
||||
import { IssueArchiveService, IssueService } from "services/issue";
|
||||
// types
|
||||
import { IIssueDetail } from "./root.store";
|
||||
import { TIssue } from "@plane/types";
|
||||
import { computedFn } from "mobx-utils";
|
||||
import { IIssueDetail } from "./root.store";
|
||||
|
||||
export interface IIssueStoreActions {
|
||||
// actions
|
||||
fetchIssue: (workspaceSlug: string, projectId: string, issueId: string, isArchived?: boolean) => Promise<TIssue>;
|
||||
updateIssue: (workspaceSlug: string, projectId: string, issueId: string, data: Partial<TIssue>) => Promise<TIssue>;
|
||||
removeIssue: (workspaceSlug: string, projectId: string, issueId: string) => Promise<TIssue>;
|
||||
updateIssue: (workspaceSlug: string, projectId: string, issueId: string, data: Partial<TIssue>) => Promise<void>;
|
||||
removeIssue: (workspaceSlug: string, projectId: string, issueId: string) => Promise<void>;
|
||||
addIssueToCycle: (workspaceSlug: string, projectId: string, cycleId: string, issueIds: string[]) => Promise<void>;
|
||||
removeIssueFromCycle: (workspaceSlug: string, projectId: string, cycleId: string, issueId: string) => Promise<TIssue>;
|
||||
addModulesToIssue: (workspaceSlug: string, projectId: string, issueId: string, moduleIds: string[]) => Promise<any>;
|
||||
|
|
@ -54,12 +54,13 @@ export class IssueStore implements IIssueStore {
|
|||
fetchIssue = async (workspaceSlug: string, projectId: string, issueId: string, isArchived = false) => {
|
||||
try {
|
||||
const query = {
|
||||
expand: "state,assignees,labels,parent",
|
||||
expand: "issue_reactions,issue_attachment,issue_link,parent",
|
||||
};
|
||||
|
||||
let issue: any;
|
||||
let issue: TIssue;
|
||||
|
||||
if (isArchived) issue = await this.issueArchiveService.retrieveArchivedIssue(workspaceSlug, projectId, issueId);
|
||||
if (isArchived)
|
||||
issue = await this.issueArchiveService.retrieveArchivedIssue(workspaceSlug, projectId, issueId, query);
|
||||
else issue = await this.issueService.retrieve(workspaceSlug, projectId, issueId, query);
|
||||
|
||||
if (!issue) throw new Error("Issue not found");
|
||||
|
|
@ -75,13 +76,15 @@ export class IssueStore implements IIssueStore {
|
|||
// state
|
||||
|
||||
// issue reactions
|
||||
this.rootIssueDetailStore.reaction.fetchReactions(workspaceSlug, projectId, issueId);
|
||||
if (issue.issue_reactions) this.rootIssueDetailStore.addReactions(issueId, issue.issue_reactions);
|
||||
|
||||
// fetch issue links
|
||||
this.rootIssueDetailStore.link.fetchLinks(workspaceSlug, projectId, issueId);
|
||||
if (issue.issue_link) this.rootIssueDetailStore.addLinks(issueId, issue.issue_link);
|
||||
|
||||
// fetch issue attachments
|
||||
this.rootIssueDetailStore.attachment.fetchAttachments(workspaceSlug, projectId, issueId);
|
||||
if (issue.issue_attachment) this.rootIssueDetailStore.addAttachments(issueId, issue.issue_attachment);
|
||||
|
||||
this.rootIssueDetailStore.addSubscription(issueId, issue.is_subscribed);
|
||||
|
||||
// fetch issue activity
|
||||
this.rootIssueDetailStore.activity.fetchActivities(workspaceSlug, projectId, issueId);
|
||||
|
|
@ -89,9 +92,6 @@ export class IssueStore implements IIssueStore {
|
|||
// fetch issue comments
|
||||
this.rootIssueDetailStore.comment.fetchComments(workspaceSlug, projectId, issueId);
|
||||
|
||||
// fetch issue subscription
|
||||
this.rootIssueDetailStore.subscription.fetchSubscriptions(workspaceSlug, projectId, issueId);
|
||||
|
||||
// fetch sub issues
|
||||
this.rootIssueDetailStore.subIssues.fetchSubIssues(workspaceSlug, projectId, issueId);
|
||||
|
||||
|
|
@ -109,14 +109,8 @@ export class IssueStore implements IIssueStore {
|
|||
};
|
||||
|
||||
updateIssue = async (workspaceSlug: string, projectId: string, issueId: string, data: Partial<TIssue>) => {
|
||||
const issue = await this.rootIssueDetailStore.rootIssueStore.projectIssues.updateIssue(
|
||||
workspaceSlug,
|
||||
projectId,
|
||||
issueId,
|
||||
data
|
||||
);
|
||||
await this.rootIssueDetailStore.rootIssueStore.projectIssues.updateIssue(workspaceSlug, projectId, issueId, data);
|
||||
await this.rootIssueDetailStore.activity.fetchActivities(workspaceSlug, projectId, issueId);
|
||||
return issue;
|
||||
};
|
||||
|
||||
removeIssue = async (workspaceSlug: string, projectId: string, issueId: string) =>
|
||||
|
|
|
|||
|
|
@ -7,16 +7,22 @@ import { IIssueDetail } from "./root.store";
|
|||
import { TIssueLink, TIssueLinkMap, TIssueLinkIdMap } from "@plane/types";
|
||||
|
||||
export interface IIssueLinkStoreActions {
|
||||
addLinks: (issueId: string, links: TIssueLink[]) => void;
|
||||
fetchLinks: (workspaceSlug: string, projectId: string, issueId: string) => Promise<TIssueLink[]>;
|
||||
createLink: (workspaceSlug: string, projectId: string, issueId: string, data: Partial<TIssueLink>) => Promise<any>;
|
||||
createLink: (
|
||||
workspaceSlug: string,
|
||||
projectId: string,
|
||||
issueId: string,
|
||||
data: Partial<TIssueLink>
|
||||
) => Promise<TIssueLink>;
|
||||
updateLink: (
|
||||
workspaceSlug: string,
|
||||
projectId: string,
|
||||
issueId: string,
|
||||
linkId: string,
|
||||
data: Partial<TIssueLink>
|
||||
) => Promise<any>;
|
||||
removeLink: (workspaceSlug: string, projectId: string, issueId: string, linkId: string) => Promise<any>;
|
||||
) => Promise<TIssueLink>;
|
||||
removeLink: (workspaceSlug: string, projectId: string, issueId: string, linkId: string) => Promise<void>;
|
||||
}
|
||||
|
||||
export interface IIssueLinkStore extends IIssueLinkStoreActions {
|
||||
|
|
@ -47,6 +53,7 @@ export class IssueLinkStore implements IIssueLinkStore {
|
|||
// computed
|
||||
issueLinks: computed,
|
||||
// actions
|
||||
addLinks: action.bound,
|
||||
fetchLinks: action,
|
||||
createLink: action,
|
||||
updateLink: action,
|
||||
|
|
@ -77,15 +84,17 @@ export class IssueLinkStore implements IIssueLinkStore {
|
|||
};
|
||||
|
||||
// actions
|
||||
addLinks = (issueId: string, links: TIssueLink[]) => {
|
||||
runInAction(() => {
|
||||
this.links[issueId] = links.map((link) => link.id);
|
||||
links.forEach((link) => set(this.linkMap, link.id, link));
|
||||
});
|
||||
};
|
||||
|
||||
fetchLinks = async (workspaceSlug: string, projectId: string, issueId: string) => {
|
||||
try {
|
||||
const response = await this.issueService.fetchIssueLinks(workspaceSlug, projectId, issueId);
|
||||
|
||||
runInAction(() => {
|
||||
this.links[issueId] = response.map((link) => link.id);
|
||||
response.forEach((link) => set(this.linkMap, link.id, link));
|
||||
});
|
||||
|
||||
this.addLinks(issueId, response);
|
||||
return response;
|
||||
} catch (error) {
|
||||
throw error;
|
||||
|
|
@ -136,7 +145,7 @@ export class IssueLinkStore implements IIssueLinkStore {
|
|||
|
||||
removeLink = async (workspaceSlug: string, projectId: string, issueId: string, linkId: string) => {
|
||||
try {
|
||||
const response = await this.issueService.deleteIssueLink(workspaceSlug, projectId, issueId, linkId);
|
||||
await this.issueService.deleteIssueLink(workspaceSlug, projectId, issueId, linkId);
|
||||
|
||||
const linkIndex = this.links[issueId].findIndex((_comment) => _comment === linkId);
|
||||
if (linkIndex >= 0)
|
||||
|
|
@ -147,7 +156,6 @@ export class IssueLinkStore implements IIssueLinkStore {
|
|||
|
||||
// fetching activity
|
||||
this.rootIssueDetailStore.activity.fetchActivities(workspaceSlug, projectId, issueId);
|
||||
return response;
|
||||
} catch (error) {
|
||||
throw error;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ import { groupReactions } from "helpers/emoji.helper";
|
|||
|
||||
export interface IIssueReactionStoreActions {
|
||||
// actions
|
||||
addReactions: (issueId: string, reactions: TIssueReaction[]) => void;
|
||||
fetchReactions: (workspaceSlug: string, projectId: string, issueId: string) => Promise<TIssueReaction[]>;
|
||||
createReaction: (workspaceSlug: string, projectId: string, issueId: string, reaction: string) => Promise<any>;
|
||||
removeReaction: (
|
||||
|
|
@ -50,6 +51,7 @@ export class IssueReactionStore implements IIssueReactionStore {
|
|||
reactions: observable,
|
||||
reactionMap: observable,
|
||||
// actions
|
||||
addReactions: action.bound,
|
||||
fetchReactions: action,
|
||||
createReaction: action,
|
||||
removeReaction: action,
|
||||
|
|
@ -82,30 +84,35 @@ export class IssueReactionStore implements IIssueReactionStore {
|
|||
if (reactions?.[reaction])
|
||||
reactions?.[reaction].map((reactionId) => {
|
||||
const currentReaction = this.getReactionById(reactionId);
|
||||
if (currentReaction && currentReaction.actor === userId) _userReactions.push(currentReaction);
|
||||
if (currentReaction && currentReaction.actor_id === userId) _userReactions.push(currentReaction);
|
||||
});
|
||||
});
|
||||
|
||||
return _userReactions;
|
||||
};
|
||||
|
||||
addReactions = (issueId: string, reactions: TIssueReaction[]) => {
|
||||
const groupedReactions = groupReactions(reactions || [], "reaction");
|
||||
|
||||
const issueReactionIdsMap: { [reaction: string]: string[] } = {};
|
||||
|
||||
Object.keys(groupedReactions).map((reactionId) => {
|
||||
const reactionIds = (groupedReactions[reactionId] || []).map((reaction) => reaction.id);
|
||||
issueReactionIdsMap[reactionId] = reactionIds;
|
||||
});
|
||||
|
||||
runInAction(() => {
|
||||
set(this.reactions, issueId, issueReactionIdsMap);
|
||||
reactions.forEach((reaction) => set(this.reactionMap, reaction.id, reaction));
|
||||
});
|
||||
};
|
||||
|
||||
// actions
|
||||
fetchReactions = async (workspaceSlug: string, projectId: string, issueId: string) => {
|
||||
try {
|
||||
const response = await this.issueReactionService.listIssueReactions(workspaceSlug, projectId, issueId);
|
||||
const groupedReactions = groupReactions(response || [], "reaction");
|
||||
|
||||
const issueReactionIdsMap: { [reaction: string]: string[] } = {};
|
||||
|
||||
Object.keys(groupedReactions).map((reactionId) => {
|
||||
const reactionIds = (groupedReactions[reactionId] || []).map((reaction) => reaction.id);
|
||||
issueReactionIdsMap[reactionId] = reactionIds;
|
||||
});
|
||||
|
||||
runInAction(() => {
|
||||
set(this.reactions, issueId, issueReactionIdsMap);
|
||||
response.forEach((reaction) => set(this.reactionMap, reaction.id, reaction));
|
||||
});
|
||||
this.addReactions(issueId, response);
|
||||
|
||||
return response;
|
||||
} catch (error) {
|
||||
|
|
@ -144,7 +151,7 @@ export class IssueReactionStore implements IIssueReactionStore {
|
|||
) => {
|
||||
try {
|
||||
const userReactions = this.reactionsByUser(issueId, userId);
|
||||
const currentReaction = find(userReactions, { actor: userId, reaction: reaction });
|
||||
const currentReaction = find(userReactions, { actor_id: userId, reaction: reaction });
|
||||
|
||||
if (currentReaction && currentReaction.id) {
|
||||
runInAction(() => {
|
||||
|
|
|
|||
|
|
@ -15,8 +15,15 @@ import {
|
|||
IssueCommentReactionStore,
|
||||
IIssueCommentReactionStoreActions,
|
||||
} from "./comment_reaction.store";
|
||||
|
||||
import { TIssue, TIssueComment, TIssueCommentReaction, TIssueLink, TIssueRelationTypes } from "@plane/types";
|
||||
import {
|
||||
TIssue,
|
||||
TIssueAttachment,
|
||||
TIssueComment,
|
||||
TIssueCommentReaction,
|
||||
TIssueLink,
|
||||
TIssueReaction,
|
||||
TIssueRelationTypes,
|
||||
} from "@plane/types";
|
||||
|
||||
export type TPeekIssue = {
|
||||
workspaceSlug: string;
|
||||
|
|
@ -151,6 +158,7 @@ export class IssueDetail implements IIssueDetail {
|
|||
this.issue.removeIssueFromModule(workspaceSlug, projectId, moduleId, issueId);
|
||||
|
||||
// reactions
|
||||
addReactions = (issueId: string, reactions: TIssueReaction[]) => this.reaction.addReactions(issueId, reactions);
|
||||
fetchReactions = async (workspaceSlug: string, projectId: string, issueId: string) =>
|
||||
this.reaction.fetchReactions(workspaceSlug, projectId, issueId);
|
||||
createReaction = async (workspaceSlug: string, projectId: string, issueId: string, reaction: string) =>
|
||||
|
|
@ -164,6 +172,8 @@ export class IssueDetail implements IIssueDetail {
|
|||
) => this.reaction.removeReaction(workspaceSlug, projectId, issueId, reaction, userId);
|
||||
|
||||
// attachments
|
||||
addAttachments = (issueId: string, attachments: TIssueAttachment[]) =>
|
||||
this.attachment.addAttachments(issueId, attachments);
|
||||
fetchAttachments = async (workspaceSlug: string, projectId: string, issueId: string) =>
|
||||
this.attachment.fetchAttachments(workspaceSlug, projectId, issueId);
|
||||
createAttachment = async (workspaceSlug: string, projectId: string, issueId: string, data: FormData) =>
|
||||
|
|
@ -172,6 +182,7 @@ export class IssueDetail implements IIssueDetail {
|
|||
this.attachment.removeAttachment(workspaceSlug, projectId, issueId, attachmentId);
|
||||
|
||||
// link
|
||||
addLinks = (issueId: string, links: TIssueLink[]) => this.link.addLinks(issueId, links);
|
||||
fetchLinks = async (workspaceSlug: string, projectId: string, issueId: string) =>
|
||||
this.link.fetchLinks(workspaceSlug, projectId, issueId);
|
||||
createLink = async (workspaceSlug: string, projectId: string, issueId: string, data: Partial<TIssueLink>) =>
|
||||
|
|
@ -206,6 +217,8 @@ export class IssueDetail implements IIssueDetail {
|
|||
this.subIssues.deleteSubIssue(workspaceSlug, projectId, parentIssueId, issueId);
|
||||
|
||||
// subscription
|
||||
addSubscription = (issueId: string, isSubscribed: boolean | undefined | null) =>
|
||||
this.subscription.addSubscription(issueId, isSubscribed);
|
||||
fetchSubscriptions = async (workspaceSlug: string, projectId: string, issueId: string) =>
|
||||
this.subscription.fetchSubscriptions(workspaceSlug, projectId, issueId);
|
||||
createSubscription = async (workspaceSlug: string, projectId: string, issueId: string) =>
|
||||
|
|
|
|||
|
|
@ -6,21 +6,22 @@ import { NotificationService } from "services/notification.service";
|
|||
import { IIssueDetail } from "./root.store";
|
||||
|
||||
export interface IIssueSubscriptionStoreActions {
|
||||
fetchSubscriptions: (workspaceSlug: string, projectId: string, issueId: string) => Promise<any>;
|
||||
createSubscription: (workspaceSlug: string, projectId: string, issueId: string) => Promise<any>;
|
||||
removeSubscription: (workspaceSlug: string, projectId: string, issueId: string) => Promise<any>;
|
||||
addSubscription: (issueId: string, isSubscribed: boolean | undefined | null) => void;
|
||||
fetchSubscriptions: (workspaceSlug: string, projectId: string, issueId: string) => Promise<boolean>;
|
||||
createSubscription: (workspaceSlug: string, projectId: string, issueId: string) => Promise<void>;
|
||||
removeSubscription: (workspaceSlug: string, projectId: string, issueId: string) => Promise<void>;
|
||||
}
|
||||
|
||||
export interface IIssueSubscriptionStore extends IIssueSubscriptionStoreActions {
|
||||
// observables
|
||||
subscriptionMap: Record<string, Record<string, Record<string, boolean>>>; // Record defines subscriptionId as key and link as value
|
||||
subscriptionMap: Record<string, Record<string, boolean>>; // Record defines subscriptionId as key and link as value
|
||||
// helper methods
|
||||
getSubscriptionByIssueId: (issueId: string) => Record<string, boolean> | undefined;
|
||||
getSubscriptionByIssueId: (issueId: string) => boolean | undefined;
|
||||
}
|
||||
|
||||
export class IssueSubscriptionStore implements IIssueSubscriptionStore {
|
||||
// observables
|
||||
subscriptionMap: Record<string, Record<string, Record<string, boolean>>> = {};
|
||||
subscriptionMap: Record<string, Record<string, boolean>> = {};
|
||||
// root store
|
||||
rootIssueDetail: IIssueDetail;
|
||||
// services
|
||||
|
|
@ -31,6 +32,7 @@ export class IssueSubscriptionStore implements IIssueSubscriptionStore {
|
|||
// observables
|
||||
subscriptionMap: observable,
|
||||
// actions
|
||||
addSubscription: action.bound,
|
||||
fetchSubscriptions: action,
|
||||
createSubscription: action,
|
||||
removeSubscription: action,
|
||||
|
|
@ -49,22 +51,26 @@ export class IssueSubscriptionStore implements IIssueSubscriptionStore {
|
|||
return this.subscriptionMap[issueId]?.[currentUserId] ?? undefined;
|
||||
};
|
||||
|
||||
addSubscription = (issueId: string, isSubscribed: boolean | undefined | null) => {
|
||||
const currentUserId = this.rootIssueDetail.rootIssueStore.currentUserId;
|
||||
if (!currentUserId) throw new Error("user id not available");
|
||||
|
||||
runInAction(() => {
|
||||
set(this.subscriptionMap, [issueId, currentUserId], isSubscribed ?? false);
|
||||
});
|
||||
};
|
||||
|
||||
fetchSubscriptions = async (workspaceSlug: string, projectId: string, issueId: string) => {
|
||||
try {
|
||||
const currentUserId = this.rootIssueDetail.rootIssueStore.currentUserId;
|
||||
if (!currentUserId) throw new Error("user id not available");
|
||||
|
||||
const subscription = await this.notificationService.getIssueNotificationSubscriptionStatus(
|
||||
workspaceSlug,
|
||||
projectId,
|
||||
issueId
|
||||
);
|
||||
|
||||
runInAction(() => {
|
||||
set(this.subscriptionMap, [issueId, currentUserId], subscription);
|
||||
});
|
||||
this.addSubscription(issueId, subscription?.subscribed);
|
||||
|
||||
return subscription;
|
||||
return subscription?.subscribed;
|
||||
} catch (error) {
|
||||
throw error;
|
||||
}
|
||||
|
|
@ -79,9 +85,7 @@ export class IssueSubscriptionStore implements IIssueSubscriptionStore {
|
|||
set(this.subscriptionMap, [issueId, currentUserId], { subscribed: true });
|
||||
});
|
||||
|
||||
const response = await this.notificationService.subscribeToIssueNotifications(workspaceSlug, projectId, issueId);
|
||||
|
||||
return response;
|
||||
await this.notificationService.subscribeToIssueNotifications(workspaceSlug, projectId, issueId);
|
||||
} catch (error) {
|
||||
this.fetchSubscriptions(workspaceSlug, projectId, issueId);
|
||||
throw error;
|
||||
|
|
@ -97,13 +101,7 @@ export class IssueSubscriptionStore implements IIssueSubscriptionStore {
|
|||
set(this.subscriptionMap, [issueId, currentUserId], { subscribed: false });
|
||||
});
|
||||
|
||||
const response = await this.notificationService.unsubscribeFromIssueNotifications(
|
||||
workspaceSlug,
|
||||
projectId,
|
||||
issueId
|
||||
);
|
||||
|
||||
return response;
|
||||
await this.notificationService.unsubscribeFromIssueNotifications(workspaceSlug, projectId, issueId);
|
||||
} catch (error) {
|
||||
this.fetchSubscriptions(workspaceSlug, projectId, issueId);
|
||||
throw error;
|
||||
|
|
|
|||
|
|
@ -39,13 +39,13 @@ export interface IModuleIssues {
|
|||
issueId: string,
|
||||
data: Partial<TIssue>,
|
||||
moduleId?: string | undefined
|
||||
) => Promise<TIssue | undefined>;
|
||||
) => Promise<void>;
|
||||
removeIssue: (
|
||||
workspaceSlug: string,
|
||||
projectId: string,
|
||||
issueId: string,
|
||||
moduleId?: string | undefined
|
||||
) => Promise<TIssue | undefined>;
|
||||
) => Promise<void>;
|
||||
quickAddIssue: (
|
||||
workspaceSlug: string,
|
||||
projectId: string,
|
||||
|
|
@ -212,9 +212,8 @@ export class ModuleIssues extends IssueHelperStore implements IModuleIssues {
|
|||
try {
|
||||
if (!moduleId) throw new Error("Module Id is required");
|
||||
|
||||
const response = await this.rootIssueStore.projectIssues.updateIssue(workspaceSlug, projectId, issueId, data);
|
||||
await this.rootIssueStore.projectIssues.updateIssue(workspaceSlug, projectId, issueId, data);
|
||||
this.rootIssueStore.rootStore.module.fetchModuleDetails(workspaceSlug, projectId, moduleId);
|
||||
return response;
|
||||
} catch (error) {
|
||||
this.fetchIssues(workspaceSlug, projectId, "mutation", moduleId);
|
||||
throw error;
|
||||
|
|
@ -230,7 +229,7 @@ export class ModuleIssues extends IssueHelperStore implements IModuleIssues {
|
|||
try {
|
||||
if (!moduleId) throw new Error("Module Id is required");
|
||||
|
||||
const response = await this.rootIssueStore.projectIssues.removeIssue(workspaceSlug, projectId, issueId);
|
||||
await this.rootIssueStore.projectIssues.removeIssue(workspaceSlug, projectId, issueId);
|
||||
this.rootIssueStore.rootStore.module.fetchModuleDetails(workspaceSlug, projectId, moduleId);
|
||||
|
||||
const issueIndex = this.issues[moduleId].findIndex((_issueId) => _issueId === issueId);
|
||||
|
|
@ -238,8 +237,6 @@ export class ModuleIssues extends IssueHelperStore implements IModuleIssues {
|
|||
runInAction(() => {
|
||||
this.issues[moduleId].splice(issueIndex, 1);
|
||||
});
|
||||
|
||||
return response;
|
||||
} catch (error) {
|
||||
throw error;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -41,13 +41,13 @@ export interface IProfileIssues {
|
|||
issueId: string,
|
||||
data: Partial<TIssue>,
|
||||
userId?: string | undefined
|
||||
) => Promise<TIssue | undefined>;
|
||||
) => Promise<void>;
|
||||
removeIssue: (
|
||||
workspaceSlug: string,
|
||||
projectId: string,
|
||||
issueId: string,
|
||||
userId?: string | undefined
|
||||
) => Promise<TIssue | undefined>;
|
||||
) => Promise<void>;
|
||||
quickAddIssue: undefined;
|
||||
}
|
||||
|
||||
|
|
@ -221,14 +221,7 @@ export class ProfileIssues extends IssueHelperStore implements IProfileIssues {
|
|||
if (!userId) throw new Error("user id is required");
|
||||
|
||||
this.rootStore.issues.updateIssue(issueId, data);
|
||||
const response = await this.rootIssueStore.projectIssues.updateIssue(
|
||||
workspaceSlug,
|
||||
projectId,
|
||||
data.id as keyof TIssue,
|
||||
data
|
||||
);
|
||||
|
||||
return response;
|
||||
await this.rootIssueStore.projectIssues.updateIssue(workspaceSlug, projectId, data.id as keyof TIssue, data);
|
||||
} catch (error) {
|
||||
if (this.currentView) this.fetchIssues(workspaceSlug, undefined, "mutation", userId, this.currentView);
|
||||
throw error;
|
||||
|
|
@ -243,7 +236,7 @@ export class ProfileIssues extends IssueHelperStore implements IProfileIssues {
|
|||
) => {
|
||||
if (!userId) return;
|
||||
try {
|
||||
const response = await this.rootIssueStore.projectIssues.removeIssue(workspaceSlug, projectId, issueId);
|
||||
await this.rootIssueStore.projectIssues.removeIssue(workspaceSlug, projectId, issueId);
|
||||
|
||||
const uniqueViewId = `${workspaceSlug}_${this.currentView}`;
|
||||
|
||||
|
|
@ -252,8 +245,6 @@ export class ProfileIssues extends IssueHelperStore implements IProfileIssues {
|
|||
runInAction(() => {
|
||||
this.issues[userId][uniqueViewId].splice(issueIndex, 1);
|
||||
});
|
||||
|
||||
return response;
|
||||
} catch (error) {
|
||||
throw error;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,13 +34,13 @@ export interface IProjectViewIssues {
|
|||
issueId: string,
|
||||
data: Partial<TIssue>,
|
||||
viewId?: string | undefined
|
||||
) => Promise<TIssue | undefined>;
|
||||
) => Promise<void>;
|
||||
removeIssue: (
|
||||
workspaceSlug: string,
|
||||
projectId: string,
|
||||
issueId: string,
|
||||
viewId?: string | undefined
|
||||
) => Promise<TIssue | undefined>;
|
||||
) => Promise<void>;
|
||||
quickAddIssue: (
|
||||
workspaceSlug: string,
|
||||
projectId: string,
|
||||
|
|
@ -181,8 +181,7 @@ export class ProjectViewIssues extends IssueHelperStore implements IProjectViewI
|
|||
try {
|
||||
if (!viewId) throw new Error("View Id is required");
|
||||
|
||||
const response = await this.rootIssueStore.projectIssues.updateIssue(workspaceSlug, projectId, issueId, data);
|
||||
return response;
|
||||
await this.rootIssueStore.projectIssues.updateIssue(workspaceSlug, projectId, issueId, data);
|
||||
} catch (error) {
|
||||
this.fetchIssues(workspaceSlug, projectId, "mutation");
|
||||
throw error;
|
||||
|
|
@ -198,15 +197,13 @@ export class ProjectViewIssues extends IssueHelperStore implements IProjectViewI
|
|||
try {
|
||||
if (!viewId) throw new Error("View Id is required");
|
||||
|
||||
const response = await this.rootIssueStore.projectIssues.removeIssue(workspaceSlug, projectId, issueId);
|
||||
await this.rootIssueStore.projectIssues.removeIssue(workspaceSlug, projectId, issueId);
|
||||
|
||||
const issueIndex = this.issues[viewId].findIndex((_issueId) => _issueId === issueId);
|
||||
if (issueIndex >= 0)
|
||||
runInAction(() => {
|
||||
this.issues[viewId].splice(issueIndex, 1);
|
||||
});
|
||||
|
||||
return response;
|
||||
} catch (error) {
|
||||
this.fetchIssues(workspaceSlug, projectId, "mutation");
|
||||
throw error;
|
||||
|
|
|
|||
|
|
@ -21,8 +21,8 @@ export interface IProjectIssues {
|
|||
// action
|
||||
fetchIssues: (workspaceSlug: string, projectId: string, loadType: TLoader) => Promise<TIssue[]>;
|
||||
createIssue: (workspaceSlug: string, projectId: string, data: Partial<TIssue>) => Promise<TIssue>;
|
||||
updateIssue: (workspaceSlug: string, projectId: string, issueId: string, data: Partial<TIssue>) => Promise<TIssue>;
|
||||
removeIssue: (workspaceSlug: string, projectId: string, issueId: string) => Promise<TIssue>;
|
||||
updateIssue: (workspaceSlug: string, projectId: string, issueId: string, data: Partial<TIssue>) => Promise<void>;
|
||||
removeIssue: (workspaceSlug: string, projectId: string, issueId: string) => Promise<void>;
|
||||
quickAddIssue: (workspaceSlug: string, projectId: string, data: TIssue) => Promise<TIssue>;
|
||||
removeBulkIssues: (workspaceSlug: string, projectId: string, issueIds: string[]) => Promise<void>;
|
||||
}
|
||||
|
|
@ -144,8 +144,7 @@ export class ProjectIssues extends IssueHelperStore implements IProjectIssues {
|
|||
try {
|
||||
this.rootStore.issues.updateIssue(issueId, data);
|
||||
|
||||
const response = await this.issueService.patchIssue(workspaceSlug, projectId, issueId, data);
|
||||
return response;
|
||||
await this.issueService.patchIssue(workspaceSlug, projectId, issueId, data);
|
||||
} catch (error) {
|
||||
this.fetchIssues(workspaceSlug, projectId, "mutation");
|
||||
throw error;
|
||||
|
|
@ -154,14 +153,13 @@ export class ProjectIssues extends IssueHelperStore implements IProjectIssues {
|
|||
|
||||
removeIssue = async (workspaceSlug: string, projectId: string, issueId: string) => {
|
||||
try {
|
||||
const response = await this.issueService.deleteIssue(workspaceSlug, projectId, issueId);
|
||||
await this.issueService.deleteIssue(workspaceSlug, projectId, issueId);
|
||||
|
||||
runInAction(() => {
|
||||
pull(this.issues[projectId], issueId);
|
||||
});
|
||||
|
||||
this.rootStore.issues.removeIssue(issueId);
|
||||
return response;
|
||||
} catch (error) {
|
||||
throw error;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,13 +30,13 @@ export interface IWorkspaceIssues {
|
|||
issueId: string,
|
||||
data: Partial<TIssue>,
|
||||
viewId?: string | undefined
|
||||
) => Promise<TIssue | undefined>;
|
||||
) => Promise<void>;
|
||||
removeIssue: (
|
||||
workspaceSlug: string,
|
||||
projectId: string,
|
||||
issueId: string,
|
||||
viewId?: string | undefined
|
||||
) => Promise<TIssue | undefined>;
|
||||
) => Promise<void>;
|
||||
}
|
||||
|
||||
export class WorkspaceIssues extends IssueHelperStore implements IWorkspaceIssues {
|
||||
|
|
@ -165,8 +165,7 @@ export class WorkspaceIssues extends IssueHelperStore implements IWorkspaceIssue
|
|||
if (!viewId) throw new Error("View id is required");
|
||||
|
||||
this.rootStore.issues.updateIssue(issueId, data);
|
||||
const response = await this.issueService.patchIssue(workspaceSlug, projectId, issueId, data);
|
||||
return response;
|
||||
await this.issueService.patchIssue(workspaceSlug, projectId, issueId, data);
|
||||
} catch (error) {
|
||||
if (viewId) this.fetchIssues(workspaceSlug, viewId, "mutation");
|
||||
throw error;
|
||||
|
|
@ -184,7 +183,7 @@ export class WorkspaceIssues extends IssueHelperStore implements IWorkspaceIssue
|
|||
|
||||
const uniqueViewId = `${workspaceSlug}_${viewId}`;
|
||||
|
||||
const response = await this.issueService.deleteIssue(workspaceSlug, projectId, issueId);
|
||||
await this.issueService.deleteIssue(workspaceSlug, projectId, issueId);
|
||||
|
||||
const issueIndex = this.issues[uniqueViewId].findIndex((_issueId) => _issueId === issueId);
|
||||
if (issueIndex >= 0)
|
||||
|
|
@ -193,8 +192,6 @@ export class WorkspaceIssues extends IssueHelperStore implements IWorkspaceIssue
|
|||
});
|
||||
|
||||
this.rootStore.issues.removeIssue(issueId);
|
||||
|
||||
return response;
|
||||
} catch (error) {
|
||||
throw error;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue