mirror of
https://github.com/danny-avila/LibreChat.git
synced 2025-12-21 19:00:13 +01:00
🏷️ fix: Address Statefulness Issues for Bookmarks (#3590)
* refactor: optimize tag methods, remove rebuild * refactor(tags): add lean db operations, fix updateTagsForConversation, remove rebuild button, only send convoId once * refactor: Update BookmarkMenu to use Constants.NEW_CONVO constant for comparison * style: Update BookmarkMenu styles and constants, use theming * refactor: move tags query from package to client workspace * refactor: optimize ConversationTag document creation and update logic * style: Update BookmarkMenuItems to use theming * refactor: JSDocs + try/catch for conversation tags API routes * refactor: Update BookmarkNav theming classes and new data provider location * fix: statefulness of conversation bookmarks - move non-mutation hook to hooks/Conversation - remove use of deprecated global convo - update convo infinite data as well as current convo state upon successful tag add * refactor: Update BookmarkMenu styles and constants, use theming * refactor: Add lean option to ConversationTag deletion query * fix(BookmarkTable): position order rendering esp. when new tag is created * refactor: Update useBookmarkSucess to useBookmarkSuccess for consistency * refactor: Update ConversationTag creation logic to increment count only if addToConversation is true * style: theming
This commit is contained in:
parent
6ea2628b56
commit
016ed866a3
28 changed files with 622 additions and 536 deletions
|
|
@ -6,7 +6,9 @@ export { default as useConversation } from './useConversation';
|
|||
export { default as useGenerateConvo } from './useGenerateConvo';
|
||||
export { default as useConversations } from './useConversations';
|
||||
export { default as useDebouncedInput } from './useDebouncedInput';
|
||||
export { default as useBookmarkSuccess } from './useBookmarkSuccess';
|
||||
export { default as useNavigateToConvo } from './useNavigateToConvo';
|
||||
export { default as useSetIndexOptions } from './useSetIndexOptions';
|
||||
export { default as useParameterEffects } from './useParameterEffects';
|
||||
export { default as useUpdateTagsInConvo } from './useUpdateTagsInConvo';
|
||||
export { default as useExportConversation } from './useExportConversation';
|
||||
|
|
|
|||
27
client/src/hooks/Conversations/useBookmarkSuccess.ts
Normal file
27
client/src/hooks/Conversations/useBookmarkSuccess.ts
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
import { useSetRecoilState } from 'recoil';
|
||||
import useUpdateTagsInConvo from './useUpdateTagsInConvo';
|
||||
import store from '~/store';
|
||||
|
||||
const useBookmarkSuccess = (conversationId: string) => {
|
||||
const setConversation = useSetRecoilState(store.conversationByIndex(0));
|
||||
const { updateTagsInConversation } = useUpdateTagsInConvo();
|
||||
|
||||
return (newTags: string[]) => {
|
||||
if (!conversationId) {
|
||||
return;
|
||||
}
|
||||
updateTagsInConversation(conversationId, newTags);
|
||||
setConversation((prev) => {
|
||||
if (prev) {
|
||||
return {
|
||||
...prev,
|
||||
tags: newTags,
|
||||
};
|
||||
}
|
||||
console.error('Conversation not found for bookmark/tags update');
|
||||
return prev;
|
||||
});
|
||||
};
|
||||
};
|
||||
|
||||
export default useBookmarkSuccess;
|
||||
92
client/src/hooks/Conversations/useUpdateTagsInConvo.ts
Normal file
92
client/src/hooks/Conversations/useUpdateTagsInConvo.ts
Normal file
|
|
@ -0,0 +1,92 @@
|
|||
import { useQueryClient } from '@tanstack/react-query';
|
||||
import { QueryKeys } from 'librechat-data-provider';
|
||||
import type { ConversationListResponse } from 'librechat-data-provider';
|
||||
import type { InfiniteData } from '@tanstack/react-query';
|
||||
import type t from 'librechat-data-provider';
|
||||
import { updateConvoFields } from '~/utils/convos';
|
||||
|
||||
const useUpdateTagsInConvo = () => {
|
||||
const queryClient = useQueryClient();
|
||||
|
||||
// Update the queryClient cache with the new tag when a new tag is added/removed to a conversation
|
||||
const updateTagsInConversation = (conversationId: string, tags: string[]) => {
|
||||
// Update the tags for the current conversation
|
||||
const currentConvo = queryClient.getQueryData<t.TConversation>([
|
||||
QueryKeys.conversation,
|
||||
conversationId,
|
||||
]);
|
||||
if (!currentConvo) {
|
||||
return;
|
||||
}
|
||||
|
||||
const updatedConvo = {
|
||||
...currentConvo,
|
||||
tags,
|
||||
} as t.TConversation;
|
||||
queryClient.setQueryData([QueryKeys.conversation, conversationId], updatedConvo);
|
||||
queryClient.setQueryData<t.ConversationData>([QueryKeys.allConversations], (convoData) => {
|
||||
if (!convoData) {
|
||||
return convoData;
|
||||
}
|
||||
return updateConvoFields(
|
||||
convoData,
|
||||
{
|
||||
conversationId: currentConvo.conversationId,
|
||||
tags: updatedConvo.tags,
|
||||
} as t.TConversation,
|
||||
true,
|
||||
);
|
||||
});
|
||||
};
|
||||
|
||||
// update the tag to newTag in all conversations when a tag is updated to a newTag
|
||||
// The difference with updateTagsInConversation is that it adds or removes tags for a specific conversation,
|
||||
// whereas this function is for changing the title of a specific tag.
|
||||
const replaceTagsInAllConversations = (tag: string, newTag: string) => {
|
||||
const data = queryClient.getQueryData<InfiniteData<ConversationListResponse>>([
|
||||
QueryKeys.allConversations,
|
||||
]);
|
||||
|
||||
const conversationIdsWithTag = [] as string[];
|
||||
|
||||
// update tag to newTag in all conversations
|
||||
const newData = JSON.parse(JSON.stringify(data)) as InfiniteData<ConversationListResponse>;
|
||||
for (let pageIndex = 0; pageIndex < newData.pages.length; pageIndex++) {
|
||||
const page = newData.pages[pageIndex];
|
||||
page.conversations = page.conversations.map((conversation) => {
|
||||
if (conversation.conversationId && conversation.tags?.includes(tag)) {
|
||||
conversationIdsWithTag.push(conversation.conversationId);
|
||||
conversation.tags = conversation.tags.map((t) => (t === tag ? newTag : t));
|
||||
}
|
||||
return conversation;
|
||||
});
|
||||
}
|
||||
queryClient.setQueryData<InfiniteData<ConversationListResponse>>(
|
||||
[QueryKeys.allConversations],
|
||||
newData,
|
||||
);
|
||||
|
||||
// update the tag to newTag from the cache of each conversation
|
||||
for (let i = 0; i < conversationIdsWithTag.length; i++) {
|
||||
const conversationId = conversationIdsWithTag[i];
|
||||
const conversation = queryClient.getQueryData<t.TConversation>([
|
||||
QueryKeys.conversation,
|
||||
conversationId,
|
||||
]);
|
||||
if (conversation && conversation.tags) {
|
||||
const updatedConvo = {
|
||||
...conversation,
|
||||
tags: conversation.tags.map((t) => (t === tag ? newTag : t)),
|
||||
} as t.TConversation;
|
||||
queryClient.setQueryData<t.TConversation>(
|
||||
[QueryKeys.conversation, conversationId],
|
||||
updatedConvo,
|
||||
);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
return { updateTagsInConversation, replaceTagsInAllConversations };
|
||||
};
|
||||
|
||||
export default useUpdateTagsInConvo;
|
||||
Loading…
Add table
Add a link
Reference in a new issue