refactor: migrate services (notification, favorite) from apps/web to @packages/services

This commit is contained in:
Rahulcheryala
2026-06-03 21:06:36 +05:30
parent 47606db169
commit 0c9abc14ec
6 changed files with 26 additions and 215 deletions

View File

@@ -1,62 +0,0 @@
/**
* Copyright (c) 2023-present Plane Software, Inc. and contributors
* SPDX-License-Identifier: AGPL-3.0-only
* See the LICENSE file for details.
*/
import { API_BASE_URL } from "@plane/constants";
import type { IFavorite } from "@plane/types";
// helpers
// services
import { APIService } from "@/services/api.service";
// types
export class FavoriteService extends APIService {
constructor() {
super(API_BASE_URL);
}
async addFavorite(workspaceSlug: string, data: Partial<IFavorite>): Promise<IFavorite> {
return this.post(`/api/workspaces/${workspaceSlug}/user-favorites/`, data)
.then((response) => response?.data)
.catch((error) => {
throw error?.response;
});
}
async updateFavorite(workspaceSlug: string, favoriteId: string, data: Partial<IFavorite>): Promise<IFavorite> {
return this.patch(`/api/workspaces/${workspaceSlug}/user-favorites/${favoriteId}/`, data)
.then((response) => response?.data)
.catch((error) => {
throw error?.response;
});
}
async deleteFavorite(workspaceSlug: string, favoriteId: string): Promise<void> {
return this.delete(`/api/workspaces/${workspaceSlug}/user-favorites/${favoriteId}/`)
.then((response) => response?.data)
.catch((error) => {
throw error?.response;
});
}
async getFavorites(workspaceSlug: string): Promise<IFavorite[]> {
return this.get(`/api/workspaces/${workspaceSlug}/user-favorites/`, {
params: {
all: true,
},
})
.then((response) => response?.data)
.catch((error) => {
throw error?.response?.data;
});
}
async getGroupedFavorites(workspaceSlug: string, favoriteId: string): Promise<IFavorite[]> {
return this.get(`/api/workspaces/${workspaceSlug}/user-favorites/${favoriteId}/group/`)
.then((response) => response?.data)
.catch((error) => {
throw error?.response?.data;
});
}
}

View File

@@ -1,7 +0,0 @@
/**
* Copyright (c) 2023-present Plane Software, Inc. and contributors
* SPDX-License-Identifier: AGPL-3.0-only
* See the LICENSE file for details.
*/
export * from "./favorite.service";

View File

@@ -1,124 +0,0 @@
/**
* Copyright (c) 2023-present Plane Software, Inc. and contributors
* SPDX-License-Identifier: AGPL-3.0-only
* See the LICENSE file for details.
*/
/* eslint-disable no-useless-catch */
import { API_BASE_URL } from "@plane/constants";
import type {
TNotificationPaginatedInfo,
TNotificationPaginatedInfoQueryParams,
TNotification,
TUnreadNotificationsCount,
} from "@plane/types";
// helpers
// services
import { APIService } from "@/services/api.service";
export class WorkspaceNotificationService extends APIService {
constructor() {
super(API_BASE_URL);
}
async fetchUnreadNotificationsCount(workspaceSlug: string): Promise<TUnreadNotificationsCount | undefined> {
try {
const { data } = await this.get(`/api/workspaces/${workspaceSlug}/users/notifications/unread/`);
return data || undefined;
} catch (error) {
throw error;
}
}
async fetchNotifications(
workspaceSlug: string,
params: TNotificationPaginatedInfoQueryParams
): Promise<TNotificationPaginatedInfo | undefined> {
try {
const { data } = await this.get(`/api/workspaces/${workspaceSlug}/users/notifications`, {
params,
});
return data || undefined;
} catch (error) {
throw error;
}
}
async updateNotificationById(
workspaceSlug: string,
notificationId: string,
payload: Partial<TNotification>
): Promise<TNotification | undefined> {
try {
const { data } = await this.patch(
`/api/workspaces/${workspaceSlug}/users/notifications/${notificationId}/`,
payload
);
return data || undefined;
} catch (error) {
throw error;
}
}
async markNotificationAsRead(workspaceSlug: string, notificationId: string): Promise<TNotification | undefined> {
try {
const { data } = await this.post(`/api/workspaces/${workspaceSlug}/users/notifications/${notificationId}/read/`);
return data || undefined;
} catch (error) {
throw error;
}
}
async markNotificationAsUnread(workspaceSlug: string, notificationId: string): Promise<TNotification | undefined> {
try {
const { data } = await this.delete(
`/api/workspaces/${workspaceSlug}/users/notifications/${notificationId}/read/`
);
return data || undefined;
} catch (error) {
throw error;
}
}
async markNotificationAsArchived(workspaceSlug: string, notificationId: string): Promise<TNotification | undefined> {
try {
const { data } = await this.post(
`/api/workspaces/${workspaceSlug}/users/notifications/${notificationId}/archive/`
);
return data || undefined;
} catch (error) {
throw error;
}
}
async markNotificationAsUnArchived(
workspaceSlug: string,
notificationId: string
): Promise<TNotification | undefined> {
try {
const { data } = await this.delete(
`/api/workspaces/${workspaceSlug}/users/notifications/${notificationId}/archive/`
);
return data || undefined;
} catch (error) {
throw error;
}
}
async markAllNotificationsAsRead(
workspaceSlug: string,
payload: TNotificationPaginatedInfoQueryParams
): Promise<TNotification | undefined> {
try {
const { data } = await this.post(`/api/workspaces/${workspaceSlug}/users/notifications/mark-all-read/`, payload);
return data || undefined;
} catch (error) {
throw error;
}
}
}
const workspaceNotificationService = new WorkspaceNotificationService();
export default workspaceNotificationService;

View File

@@ -8,7 +8,7 @@ import { orderBy, uniqBy, set } from "lodash-es";
import { action, observable, makeObservable, runInAction, computed } from "mobx";
import { v4 as uuidv4 } from "uuid";
import type { IFavorite } from "@plane/types";
import { FavoriteService } from "@/services/favorite";
import { UserFavoriteService } from "@plane/services";
import type { CoreRootStore } from "./root.store";
export interface IFavoriteStore {
@@ -81,7 +81,7 @@ export class FavoriteStore implements IFavoriteStore {
removeFavoriteEntityFromStore: action,
removeFromFavoriteFolder: action,
});
this.favoriteService = new FavoriteService();
this.favoriteService = new UserFavoriteService();
this.rootStore = _rootStore;
this.viewStore = _rootStore.projectView;
this.projectStore = _rootStore.projectRoot.project;
@@ -145,7 +145,7 @@ export class FavoriteStore implements IFavoriteStore {
}
this.favoriteIds = [id, ...this.favoriteIds];
});
const response = await this.favoriteService.addFavorite(workspaceSlug, data);
const response = await this.favoriteService.add(workspaceSlug, data);
// overwrite the temp id
runInAction(() => {
@@ -184,7 +184,7 @@ export class FavoriteStore implements IFavoriteStore {
runInAction(() => {
set(this.favoriteMap, [favoriteId], { ...this.favoriteMap[favoriteId], ...data });
});
const response = await this.favoriteService.updateFavorite(workspaceSlug, favoriteId, data);
const response = await this.favoriteService.update(workspaceSlug, favoriteId, data);
return response;
} catch (error) {
@@ -205,7 +205,7 @@ export class FavoriteStore implements IFavoriteStore {
*/
moveFavoriteToFolder = async (workspaceSlug: string, favoriteId: string, data: Partial<IFavorite>) => {
try {
await this.favoriteService.updateFavorite(workspaceSlug, favoriteId, data);
await this.favoriteService.update(workspaceSlug, favoriteId, data);
runInAction(() => {
// add parent of the favorite
set(this.favoriteMap, [favoriteId, "parent"], data.parent);
@@ -242,7 +242,7 @@ export class FavoriteStore implements IFavoriteStore {
}
}
await this.favoriteService.updateFavorite(workspaceSlug, favoriteId, { sequence: resultSequence });
await this.favoriteService.update(workspaceSlug, favoriteId, { sequence: resultSequence });
runInAction(() => {
set(this.favoriteMap, [favoriteId, "sequence"], resultSequence);
@@ -255,7 +255,7 @@ export class FavoriteStore implements IFavoriteStore {
removeFromFavoriteFolder = async (workspaceSlug: string, favoriteId: string) => {
try {
await this.favoriteService.updateFavorite(workspaceSlug, favoriteId, { parent: null });
await this.favoriteService.update(workspaceSlug, favoriteId, { parent: null });
runInAction(() => {
//remove parent
set(this.favoriteMap, [favoriteId, "parent"], null);
@@ -308,7 +308,7 @@ export class FavoriteStore implements IFavoriteStore {
const initialState = this.favoriteMap[favoriteId];
try {
await this.favoriteService.deleteFavorite(workspaceSlug, favoriteId);
await this.favoriteService.remove(workspaceSlug, favoriteId);
runInAction(() => {
delete this.favoriteMap[favoriteId];
if (entity_identifier) {
@@ -400,7 +400,7 @@ export class FavoriteStore implements IFavoriteStore {
fetchGroupedFavorites = async (workspaceSlug: string, favoriteId: string) => {
if (!favoriteId) return [];
try {
const response = await this.favoriteService.getGroupedFavorites(workspaceSlug, favoriteId);
const response = await this.favoriteService.groupedList(workspaceSlug, favoriteId);
runInAction(() => {
// add the favorites to the map
response.forEach((favorite) => {
@@ -426,7 +426,7 @@ export class FavoriteStore implements IFavoriteStore {
*/
fetchFavorite = async (workspaceSlug: string) => {
try {
const favorites = await this.favoriteService.getFavorites(workspaceSlug);
const favorites = await this.favoriteService.list(workspaceSlug);
runInAction(() => {
favorites.forEach((favorite) => {
set(this.favoriteMap, [favorite.id], favorite);

View File

@@ -9,7 +9,7 @@ import { set } from "lodash-es";
import { action, computed, makeObservable, observable, runInAction } from "mobx";
import type { IUserLite, TNotification, TNotificationData } from "@plane/types";
// services
import workspaceNotificationService from "@/services/workspace-notification.service";
import { WorkspaceNotificationService } from "@plane/services";
// store
import type { CoreRootStore } from "../root.store";
@@ -30,6 +30,8 @@ export interface INotification extends TNotification {
unSnoozeNotification: (workspaceSlug: string) => Promise<TNotification | undefined>;
}
const workspaceNotificationService = new WorkspaceNotificationService();
export class Notification implements INotification {
// observables
id: string;
@@ -176,7 +178,7 @@ export class Notification implements INotification {
payload: Partial<TNotification>
): Promise<TNotification | undefined> => {
try {
const notification = await workspaceNotificationService.updateNotificationById(workspaceSlug, this.id, payload);
const notification = await workspaceNotificationService.update(workspaceSlug, this.id, payload);
if (notification) {
runInAction(() => this.mutateNotification(notification));
}
@@ -199,7 +201,7 @@ export class Notification implements INotification {
};
this.store.workspaceNotification.setUnreadNotificationsCount("decrement");
runInAction(() => this.mutateNotification(payload));
const notification = await workspaceNotificationService.markNotificationAsRead(workspaceSlug, this.id);
const notification = await workspaceNotificationService.markAsRead(workspaceSlug, this.id);
if (notification) {
runInAction(() => this.mutateNotification(notification));
}
@@ -224,7 +226,7 @@ export class Notification implements INotification {
};
this.store.workspaceNotification.setUnreadNotificationsCount("increment");
runInAction(() => this.mutateNotification(payload));
const notification = await workspaceNotificationService.markNotificationAsUnread(workspaceSlug, this.id);
const notification = await workspaceNotificationService.markAsUnread(workspaceSlug, this.id);
if (notification) {
runInAction(() => this.mutateNotification(notification));
}
@@ -248,7 +250,7 @@ export class Notification implements INotification {
archived_at: new Date().toISOString(),
};
runInAction(() => this.mutateNotification(payload));
const notification = await workspaceNotificationService.markNotificationAsArchived(workspaceSlug, this.id);
const notification = await workspaceNotificationService.archive(workspaceSlug, this.id);
if (notification) {
runInAction(() => this.mutateNotification(notification));
}
@@ -271,7 +273,7 @@ export class Notification implements INotification {
archived_at: undefined,
};
runInAction(() => this.mutateNotification(payload));
const notification = await workspaceNotificationService.markNotificationAsUnArchived(workspaceSlug, this.id);
const notification = await workspaceNotificationService.unarchive(workspaceSlug, this.id);
if (notification) {
runInAction(() => this.mutateNotification(notification));
}
@@ -295,7 +297,7 @@ export class Notification implements INotification {
snoozed_till: snoozeTill.toISOString(),
};
runInAction(() => this.mutateNotification(payload));
const notification = await workspaceNotificationService.updateNotificationById(workspaceSlug, this.id, payload);
const notification = await workspaceNotificationService.update(workspaceSlug, this.id, payload);
return notification;
} catch (error) {
runInAction(() => this.mutateNotification({ snoozed_till: currentNotificationSnoozeTill }));
@@ -315,7 +317,7 @@ export class Notification implements INotification {
snoozed_till: undefined,
};
runInAction(() => this.mutateNotification(payload));
const notification = await workspaceNotificationService.updateNotificationById(workspaceSlug, this.id, payload);
const notification = await workspaceNotificationService.update(workspaceSlug, this.id, payload);
return notification;
} catch (error) {
runInAction(() => this.mutateNotification({ snoozed_till: currentNotificationSnoozeTill }));

View File

@@ -21,7 +21,7 @@ import type {
// helpers
import { convertToEpoch } from "@plane/utils";
// services
import workspaceNotificationService from "@/services/workspace-notification.service";
import { WorkspaceNotificationService } from "@plane/services";
// store
import type { INotification } from "@/store/notifications/notification";
import { Notification } from "@/store/notifications/notification";
@@ -60,6 +60,8 @@ export interface IWorkspaceNotificationStore {
markAllNotificationsAsRead: (workspaceId: string) => Promise<void>;
}
const workspaceNotificationService = new WorkspaceNotificationService();
export class WorkspaceNotificationStore implements IWorkspaceNotificationStore {
// constants
paginatedCount = 300;
@@ -316,7 +318,7 @@ export class WorkspaceNotificationStore implements IWorkspaceNotificationStore {
*/
getUnreadNotificationsCount = async (workspaceSlug: string): Promise<TUnreadNotificationsCount | undefined> => {
try {
const unreadNotificationCount = await workspaceNotificationService.fetchUnreadNotificationsCount(workspaceSlug);
const unreadNotificationCount = await workspaceNotificationService.getUnreadCount(workspaceSlug);
if (unreadNotificationCount)
runInAction(() => {
set(this, "unreadNotificationsCount", unreadNotificationCount);
@@ -343,7 +345,7 @@ export class WorkspaceNotificationStore implements IWorkspaceNotificationStore {
try {
const queryParams = this.generateNotificationQueryParams(queryParamType);
await this.getUnreadNotificationsCount(workspaceSlug);
const notificationResponse = await workspaceNotificationService.fetchNotifications(workspaceSlug, queryParams);
const notificationResponse = await workspaceNotificationService.list(workspaceSlug, queryParams);
if (notificationResponse) {
const { results, ...paginationInfo } = notificationResponse;
runInAction(() => {
@@ -377,7 +379,7 @@ export class WorkspaceNotificationStore implements IWorkspaceNotificationStore {
archived: queryParams.archived,
read: queryParams.read,
};
await workspaceNotificationService.markAllNotificationsAsRead(workspaceSlug, params);
await workspaceNotificationService.markAllAsRead(workspaceSlug, params);
runInAction(() => {
update(
this.unreadNotificationsCount,