import { action, makeObservable, observable, runInAction } from "mobx"; import set from "lodash/set"; // services import { NotificationService } from "services/notification.service"; // types import { IIssueDetail } from "./root.store"; export interface IIssueSubscriptionStoreActions { fetchSubscriptions: (workspaceSlug: string, projectId: string, issueId: string) => Promise; createSubscription: (workspaceSlug: string, projectId: string, issueId: string) => Promise; removeSubscription: (workspaceSlug: string, projectId: string, issueId: string) => Promise; } export interface IIssueSubscriptionStore extends IIssueSubscriptionStoreActions { // observables subscriptionMap: Record>>; // Record defines subscriptionId as key and link as value // helper methods getSubscriptionByIssueId: (issueId: string) => Record | undefined; } export class IssueSubscriptionStore implements IIssueSubscriptionStore { // observables subscriptionMap: Record>> = {}; // root store rootIssueDetail: IIssueDetail; // services notificationService; constructor(rootStore: IIssueDetail) { makeObservable(this, { // observables subscriptionMap: observable, // actions fetchSubscriptions: action, createSubscription: action, removeSubscription: action, }); // root store this.rootIssueDetail = rootStore; // services this.notificationService = new NotificationService(); } // helper methods getSubscriptionByIssueId = (issueId: string) => { if (!issueId) return undefined; const currentUserId = this.rootIssueDetail.rootIssueStore.currentUserId; if (!currentUserId) return undefined; return this.subscriptionMap[issueId]?.[currentUserId] ?? undefined; }; 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); }); return subscription; } catch (error) { throw error; } }; createSubscription = async (workspaceSlug: string, projectId: string, issueId: string) => { try { const currentUserId = this.rootIssueDetail.rootIssueStore.currentUserId; if (!currentUserId) throw new Error("user id not available"); runInAction(() => { set(this.subscriptionMap, [issueId, currentUserId], { subscribed: true }); }); const response = await this.notificationService.subscribeToIssueNotifications(workspaceSlug, projectId, issueId); return response; } catch (error) { this.fetchSubscriptions(workspaceSlug, projectId, issueId); throw error; } }; removeSubscription = async (workspaceSlug: string, projectId: string, issueId: string) => { try { const currentUserId = this.rootIssueDetail.rootIssueStore.currentUserId; if (!currentUserId) throw new Error("user id not available"); runInAction(() => { set(this.subscriptionMap, [issueId, currentUserId], { subscribed: false }); }); const response = await this.notificationService.unsubscribeFromIssueNotifications( workspaceSlug, projectId, issueId ); return response; } catch (error) { this.fetchSubscriptions(workspaceSlug, projectId, issueId); throw error; } }; }