[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:
Nikhil 2024-02-22 20:58:34 +05:30 committed by GitHub
parent 7927b7678d
commit 03e5f4a5bd
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
31 changed files with 490 additions and 324 deletions

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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) {

View file

@ -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) =>

View file

@ -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;
}

View file

@ -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(() => {

View file

@ -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) =>

View file

@ -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;

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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;

View file

@ -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;
}

View file

@ -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;
}