mirror of
https://github.com/danny-avila/LibreChat.git
synced 2026-01-15 15:08:52 +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
|
|
@ -4,8 +4,8 @@ import { useLocation } from 'react-router-dom';
|
|||
import { TConversation } from 'librechat-data-provider';
|
||||
import { Content, Portal, Root, Trigger } from '@radix-ui/react-popover';
|
||||
import { BookmarkFilledIcon, BookmarkIcon } from '@radix-ui/react-icons';
|
||||
import { useGetConversationTags } from 'librechat-data-provider/react-query';
|
||||
import { BookmarkContext } from '~/Providers/BookmarkContext';
|
||||
import { useGetConversationTags } from '~/data-provider';
|
||||
import BookmarkNavItems from './BookmarkNavItems';
|
||||
import { useLocalize } from '~/hooks';
|
||||
import { cn } from '~/utils';
|
||||
|
|
@ -39,22 +39,22 @@ const BookmarkNav: FC<BookmarkNavProps> = ({ tags, setTags }: BookmarkNavProps)
|
|||
<Trigger asChild>
|
||||
<button
|
||||
className={cn(
|
||||
'relative mt-1 flex h-10 w-full cursor-pointer items-center gap-1 rounded-lg border-white bg-gray-50 px-1 py-2 text-black transition-colors duration-200 focus-within:bg-gray-200 hover:bg-gray-200 dark:bg-gray-850 dark:text-white dark:focus-within:bg-gray-800 dark:hover:bg-gray-800',
|
||||
open ? 'bg-gray-200 dark:bg-gray-800' : '',
|
||||
'relative mt-1 flex h-10 w-full cursor-pointer items-center gap-1 rounded-lg border-border-light bg-transparent px-1 py-2 text-text-primary transition-colors duration-200 focus-within:bg-surface-hover hover:bg-surface-hover',
|
||||
open ? 'bg-surface-hover' : '',
|
||||
)}
|
||||
id="presets-button"
|
||||
data-testid="presets-button"
|
||||
title={localize('com_endpoint_examples')}
|
||||
id="show-bookmarks"
|
||||
data-testid="show-bookmarks"
|
||||
title={localize('com_ui_bookmarks')}
|
||||
>
|
||||
<div className="relative flex h-8 w-8 items-center justify-center rounded-full p-1 dark:text-white">
|
||||
<div className="relative flex h-8 w-8 items-center justify-center rounded-full p-1 text-text-primary">
|
||||
{tags.length > 0 ? (
|
||||
<BookmarkFilledIcon className="h-5 w-5" />
|
||||
) : (
|
||||
<BookmarkIcon className="h-5 w-5" />
|
||||
)}
|
||||
</div>
|
||||
<div className="grow overflow-hidden whitespace-nowrap text-left text-sm text-black dark:text-gray-100">
|
||||
{tags.length > 0 ? tags.join(',') : localize('com_ui_bookmarks')}
|
||||
<div className="grow overflow-hidden whitespace-nowrap text-left text-sm text-text-primary">
|
||||
{tags.length > 0 ? tags.join(', ') : localize('com_ui_bookmarks')}
|
||||
</div>
|
||||
</button>
|
||||
</Trigger>
|
||||
|
|
@ -63,7 +63,7 @@ const BookmarkNav: FC<BookmarkNavProps> = ({ tags, setTags }: BookmarkNavProps)
|
|||
<Content
|
||||
side="bottom"
|
||||
align="start"
|
||||
className="mt-2 max-h-96 min-w-[240px] overflow-y-auto rounded-lg border border-gray-200 bg-white shadow-lg dark:border-gray-700 dark:bg-gray-700 dark:text-white lg:max-h-96"
|
||||
className="mt-2 max-h-96 min-w-[240px] overflow-y-auto rounded-lg border border-border-medium bg-surface-primary-alt text-text-primary shadow-lg lg:max-h-96"
|
||||
>
|
||||
{data && conversation && (
|
||||
// Display bookmarks and highlight the selected tag
|
||||
|
|
|
|||
|
|
@ -39,12 +39,11 @@ const BookmarkNavItems: FC<{
|
|||
return Promise.resolve();
|
||||
};
|
||||
|
||||
console.log('bookmarks', bookmarks);
|
||||
|
||||
if (bookmarks.length === 0) {
|
||||
return (
|
||||
<div className="flex flex-col">
|
||||
<BookmarkItem
|
||||
ctx="nav"
|
||||
tag={localize('com_ui_no_bookmarks')}
|
||||
data-testid="bookmark-item-clear"
|
||||
handleSubmit={() => Promise.resolve()}
|
||||
|
|
@ -58,11 +57,13 @@ const BookmarkNavItems: FC<{
|
|||
return (
|
||||
<div className="flex flex-col">
|
||||
<BookmarkItems
|
||||
ctx="nav"
|
||||
tags={tags}
|
||||
handleSubmit={handleSubmit}
|
||||
highlightSelected={true}
|
||||
header={
|
||||
<BookmarkItem
|
||||
ctx="nav"
|
||||
tag="Clear all"
|
||||
data-testid="bookmark-item-clear"
|
||||
handleSubmit={clear}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,6 @@
|
|||
/* eslint-disable @typescript-eslint/no-unnecessary-condition */
|
||||
/* Reason: SearchContext is not specifying potential undefined type */
|
||||
import { useCallback, useEffect, useState, useMemo, memo } from 'react';
|
||||
import { useParams } from 'react-router-dom';
|
||||
import { useRecoilValue } from 'recoil';
|
||||
import { useParams } from 'react-router-dom';
|
||||
import type { ConversationListResponse } from 'librechat-data-provider';
|
||||
import {
|
||||
useMediaQuery,
|
||||
|
|
@ -159,7 +157,7 @@ const Nav = ({ navVisible, setNavVisible }) => {
|
|||
toggleNav={itemToggleNav}
|
||||
subHeaders={
|
||||
<>
|
||||
{isSearchEnabled && <SearchBar clearSearch={clearSearch} />}
|
||||
{isSearchEnabled && <SearchBar clearSearch={clearSearch} />}
|
||||
<BookmarkNav tags={tags} setTags={setTags} />
|
||||
</>
|
||||
}
|
||||
|
|
|
|||
|
|
@ -58,12 +58,12 @@ const SearchBar = forwardRef((props: SearchBarProps, ref: Ref<HTMLDivElement>) =
|
|||
return (
|
||||
<div
|
||||
ref={ref}
|
||||
className="relative mt-1 flex h-10 cursor-pointer items-center gap-3 rounded-lg border-white bg-gray-50 px-2 px-3 py-2 text-black transition-colors duration-200 focus-within:bg-gray-200 hover:bg-gray-200 dark:bg-gray-850 dark:text-white dark:focus-within:bg-gray-800 dark:hover:bg-gray-800"
|
||||
className="relative mt-1 flex h-10 cursor-pointer items-center gap-3 rounded-lg border-border-medium px-3 py-2 text-text-primary transition-colors duration-200 focus-within:bg-surface-hover hover:bg-surface-hover dark:focus-within:bg-surface-hover"
|
||||
>
|
||||
{<Search className="absolute left-3 h-4 w-4" />}
|
||||
<input
|
||||
type="text"
|
||||
className="m-0 mr-0 w-full border-none bg-transparent p-0 pl-7 text-sm leading-tight placeholder-gray-500 placeholder-opacity-100 outline-none dark:placeholder-white dark:placeholder-opacity-100"
|
||||
className="m-0 mr-0 w-full border-none bg-transparent p-0 pl-7 text-sm leading-tight placeholder-text-secondary placeholder-opacity-100 outline-none dark:placeholder-opacity-100"
|
||||
value={text}
|
||||
onChange={onChange}
|
||||
onKeyDown={(e) => {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue