[WEB-5442] fix: favorites list on workspace switch (#8131)

This commit is contained in:
Prateek Shourya 2025-11-18 13:52:29 +05:30 committed by GitHub
parent 06300d1a8e
commit 69323f4164
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 58 additions and 24 deletions

View file

@ -45,7 +45,7 @@ type Props = {
export const FavoriteFolder: React.FC<Props> = (props) => { export const FavoriteFolder: React.FC<Props> = (props) => {
const { favorite, handleRemoveFromFavorites, isLastChild, handleDrop } = props; const { favorite, handleRemoveFromFavorites, isLastChild, handleDrop } = props;
// store hooks // store hooks
const { getGroupedFavorites } = useFavorite(); const { fetchGroupedFavorites } = useFavorite();
const { isMobile } = usePlatformOS(); const { isMobile } = usePlatformOS();
const { workspaceSlug } = useParams(); const { workspaceSlug } = useParams();
// states // states
@ -61,9 +61,9 @@ export const FavoriteFolder: React.FC<Props> = (props) => {
useEffect(() => { useEffect(() => {
if (favorite.children === undefined && workspaceSlug) { if (favorite.children === undefined && workspaceSlug) {
getGroupedFavorites(workspaceSlug.toString(), favorite.id); fetchGroupedFavorites(workspaceSlug.toString(), favorite.id);
} }
}, [favorite.id, favorite.children, workspaceSlug, getGroupedFavorites]); }, [favorite.id, favorite.children, workspaceSlug, fetchGroupedFavorites]);
useEffect(() => { useEffect(() => {
const element = elementRef.current; const element = elementRef.current;

View file

@ -7,7 +7,6 @@ import type { CoreRootStore } from "./root.store";
export interface IFavoriteStore { export interface IFavoriteStore {
// observables // observables
favoriteIds: string[]; favoriteIds: string[];
favoriteMap: { favoriteMap: {
[favoriteId: string]: IFavorite; [favoriteId: string]: IFavorite;
@ -24,7 +23,7 @@ export interface IFavoriteStore {
addFavorite: (workspaceSlug: string, data: Partial<IFavorite>) => Promise<IFavorite>; addFavorite: (workspaceSlug: string, data: Partial<IFavorite>) => Promise<IFavorite>;
updateFavorite: (workspaceSlug: string, favoriteId: string, data: Partial<IFavorite>) => Promise<IFavorite>; updateFavorite: (workspaceSlug: string, favoriteId: string, data: Partial<IFavorite>) => Promise<IFavorite>;
deleteFavorite: (workspaceSlug: string, favoriteId: string) => Promise<void>; deleteFavorite: (workspaceSlug: string, favoriteId: string) => Promise<void>;
getGroupedFavorites: (workspaceSlug: string, favoriteId: string) => Promise<IFavorite[]>; fetchGroupedFavorites: (workspaceSlug: string, favoriteId: string) => Promise<IFavorite[]>;
moveFavoriteToFolder: (workspaceSlug: string, favoriteId: string, data: Partial<IFavorite>) => Promise<void>; moveFavoriteToFolder: (workspaceSlug: string, favoriteId: string, data: Partial<IFavorite>) => Promise<void>;
removeFavoriteEntity: (workspaceSlug: string, entityId: string) => Promise<void>; removeFavoriteEntity: (workspaceSlug: string, entityId: string) => Promise<void>;
reOrderFavorite: ( reOrderFavorite: (
@ -48,6 +47,7 @@ export class FavoriteStore implements IFavoriteStore {
} = {}; } = {};
// service // service
favoriteService; favoriteService;
rootStore;
viewStore; viewStore;
projectStore; projectStore;
pageStore; pageStore;
@ -61,13 +61,14 @@ export class FavoriteStore implements IFavoriteStore {
entityMap: observable, entityMap: observable,
favoriteIds: observable, favoriteIds: observable,
//computed //computed
currentWorkspaceFavorites: computed,
existingFolders: computed, existingFolders: computed,
groupedFavorites: computed, groupedFavorites: computed,
// action // action
fetchFavorite: action, fetchFavorite: action,
// CRUD actions // CRUD actions
addFavorite: action, addFavorite: action,
getGroupedFavorites: action, fetchGroupedFavorites: action,
moveFavoriteToFolder: action, moveFavoriteToFolder: action,
removeFavoriteEntity: action, removeFavoriteEntity: action,
reOrderFavorite: action, reOrderFavorite: action,
@ -75,6 +76,7 @@ export class FavoriteStore implements IFavoriteStore {
removeFromFavoriteFolder: action, removeFromFavoriteFolder: action,
}); });
this.favoriteService = new FavoriteService(); this.favoriteService = new FavoriteService();
this.rootStore = _rootStore;
this.viewStore = _rootStore.projectView; this.viewStore = _rootStore.projectView;
this.projectStore = _rootStore.projectRoot.project; this.projectStore = _rootStore.projectRoot.project;
this.moduleStore = _rootStore.module; this.moduleStore = _rootStore.module;
@ -82,12 +84,26 @@ export class FavoriteStore implements IFavoriteStore {
this.pageStore = _rootStore.projectPages; this.pageStore = _rootStore.projectPages;
} }
get currentWorkspaceFavorites() {
const currentWorkspace = this.rootStore.workspaceRoot.currentWorkspace;
if (!currentWorkspace) return {};
return Object.values(this.favoriteMap)
.filter((fav: IFavorite) => fav.workspace_id === currentWorkspace.id)
.reduce(
(acc, fav) => {
acc[fav.id] = fav;
return acc;
},
{} as { [favoriteId: string]: IFavorite }
);
}
get existingFolders() { get existingFolders() {
return Object.values(this.favoriteMap).map((fav) => fav.name); return Object.values(this.favoriteMap).map((fav) => fav.name);
} }
get groupedFavorites() { get groupedFavorites() {
const data: { [favoriteId: string]: IFavorite } = JSON.parse(JSON.stringify(this.favoriteMap)); const data: { [favoriteId: string]: IFavorite } = JSON.parse(JSON.stringify(this.currentWorkspaceFavorites));
Object.values(data).forEach((fav) => { Object.values(data).forEach((fav) => {
if (fav.parent && data[fav.parent]) { if (fav.parent && data[fav.parent]) {
@ -118,7 +134,9 @@ export class FavoriteStore implements IFavoriteStore {
// optimistic addition // optimistic addition
runInAction(() => { runInAction(() => {
set(this.favoriteMap, [id], data); set(this.favoriteMap, [id], data);
data.entity_identifier && set(this.entityMap, [data.entity_identifier], data); if (data.entity_identifier) {
set(this.entityMap, [data.entity_identifier], data);
}
this.favoriteIds = [id, ...this.favoriteIds]; this.favoriteIds = [id, ...this.favoriteIds];
}); });
const response = await this.favoriteService.addFavorite(workspaceSlug, data); const response = await this.favoriteService.addFavorite(workspaceSlug, data);
@ -127,13 +145,19 @@ export class FavoriteStore implements IFavoriteStore {
runInAction(() => { runInAction(() => {
delete this.favoriteMap[id]; delete this.favoriteMap[id];
set(this.favoriteMap, [response.id], response); set(this.favoriteMap, [response.id], response);
response.entity_identifier && set(this.entityMap, [response.entity_identifier], response); if (response.entity_identifier) {
set(this.entityMap, [response.entity_identifier], response);
}
this.favoriteIds = [response.id, ...this.favoriteIds.filter((favId) => favId !== id)]; this.favoriteIds = [response.id, ...this.favoriteIds.filter((favId) => favId !== id)];
}); });
return response; return response;
} catch (error) { } catch (error) {
delete this.favoriteMap[id]; runInAction(() => {
data.entity_identifier && delete this.entityMap[data.entity_identifier]; delete this.favoriteMap[id];
if (data.entity_identifier) {
delete this.entityMap[data.entity_identifier];
}
});
this.favoriteIds = this.favoriteIds.filter((favId) => favId !== id); this.favoriteIds = this.favoriteIds.filter((favId) => favId !== id);
console.error("Failed to create favorite from favorite store"); console.error("Failed to create favorite from favorite store");
@ -281,11 +305,15 @@ export class FavoriteStore implements IFavoriteStore {
await this.favoriteService.deleteFavorite(workspaceSlug, favoriteId); await this.favoriteService.deleteFavorite(workspaceSlug, favoriteId);
runInAction(() => { runInAction(() => {
delete this.favoriteMap[favoriteId]; delete this.favoriteMap[favoriteId];
entity_identifier && delete this.entityMap[entity_identifier]; if (entity_identifier) {
delete this.entityMap[entity_identifier];
}
this.favoriteIds = this.favoriteIds.filter((id) => id !== favoriteId); this.favoriteIds = this.favoriteIds.filter((id) => id !== favoriteId);
}); });
runInAction(() => { runInAction(() => {
entity_identifier && this.removeFavoriteEntityFromStore(entity_identifier, initialState.entity_type); if (entity_identifier) {
this.removeFavoriteEntityFromStore(entity_identifier, initialState.entity_type);
}
if (children) { if (children) {
children.forEach((child) => { children.forEach((child) => {
if (!child.entity_identifier) return; if (!child.entity_identifier) return;
@ -298,7 +326,9 @@ export class FavoriteStore implements IFavoriteStore {
runInAction(() => { runInAction(() => {
if (parent) set(this.favoriteMap, [parent, "children"], [...this.favoriteMap[parent].children, initialState]); if (parent) set(this.favoriteMap, [parent, "children"], [...this.favoriteMap[parent].children, initialState]);
set(this.favoriteMap, [favoriteId], initialState); set(this.favoriteMap, [favoriteId], initialState);
entity_identifier && set(this.entityMap, [entity_identifier], initialState); if (entity_identifier) {
set(this.entityMap, [entity_identifier], initialState);
}
this.favoriteIds = [favoriteId, ...this.favoriteIds]; this.favoriteIds = [favoriteId, ...this.favoriteIds];
}); });
throw error; throw error;
@ -333,16 +363,20 @@ export class FavoriteStore implements IFavoriteStore {
(fav) => fav.project_id === entity_identifier && fav.entity_type !== "project" (fav) => fav.project_id === entity_identifier && fav.entity_type !== "project"
); );
runInAction(() => { runInAction(() => {
projectData && if (projectData) {
projectData.forEach(async (fav) => { projectData.forEach(async (fav) => {
this.removeFavoriteFromStore(fav.entity_identifier!); if (fav.entity_identifier) {
this.removeFavoriteEntityFromStore(fav.entity_identifier!, fav.entity_type); this.removeFavoriteFromStore(fav.entity_identifier);
this.removeFavoriteEntityFromStore(fav.entity_identifier, fav.entity_type);
}
}); });
}
if (!favoriteId) return; if (!favoriteId) return;
delete this.favoriteMap[favoriteId]; delete this.favoriteMap[favoriteId];
this.removeFavoriteEntityFromStore(entity_identifier!, oldData.entity_type); if (entity_identifier) {
this.removeFavoriteEntityFromStore(entity_identifier, oldData.entity_type);
}
delete this.entityMap[entity_identifier]; delete this.entityMap[entity_identifier];
this.favoriteIds = this.favoriteIds.filter((id) => id !== favoriteId); this.favoriteIds = this.favoriteIds.filter((id) => id !== favoriteId);
}); });
@ -357,7 +391,7 @@ export class FavoriteStore implements IFavoriteStore {
* @param favoriteId * @param favoriteId
* @returns Promise<IFavorite[]> * @returns Promise<IFavorite[]>
*/ */
getGroupedFavorites = async (workspaceSlug: string, favoriteId: string) => { fetchGroupedFavorites = async (workspaceSlug: string, favoriteId: string) => {
if (!favoriteId) return []; if (!favoriteId) return [];
try { try {
const response = await this.favoriteService.getGroupedFavorites(workspaceSlug, favoriteId); const response = await this.favoriteService.getGroupedFavorites(workspaceSlug, favoriteId);
@ -386,15 +420,14 @@ export class FavoriteStore implements IFavoriteStore {
*/ */
fetchFavorite = async (workspaceSlug: string) => { fetchFavorite = async (workspaceSlug: string) => {
try { try {
this.favoriteIds = [];
this.favoriteMap = {};
this.entityMap = {};
const favorites = await this.favoriteService.getFavorites(workspaceSlug); const favorites = await this.favoriteService.getFavorites(workspaceSlug);
runInAction(() => { runInAction(() => {
favorites.forEach((favorite) => { favorites.forEach((favorite) => {
set(this.favoriteMap, [favorite.id], favorite); set(this.favoriteMap, [favorite.id], favorite);
this.favoriteIds.push(favorite.id); this.favoriteIds.push(favorite.id);
favorite.entity_identifier && set(this.entityMap, [favorite.entity_identifier], favorite); if (favorite.entity_identifier) {
set(this.entityMap, [favorite.entity_identifier], favorite);
}
}); });
}); });
return favorites; return favorites;

View file

@ -16,4 +16,5 @@ export type IFavorite = {
children: IFavorite[]; children: IFavorite[];
project_id: string | null; project_id: string | null;
sequence: number; sequence: number;
workspace_id: string;
}; };