mirror of
https://github.com/danny-avila/LibreChat.git
synced 2025-12-16 16:30:15 +01:00
refactor(Settings.jsx) move tabs to separate components, rewrite General in TS, fix react warnings
chore(client): remove unnecessary dependencies from package.json feat(client): add General tab to Settings component feat(client): add CogIcon component refactor(client): move General tab content to separate file fix(client): fix clearConvosMutation call in Settings component feat(svg): add CogIcon component refactor(conversation.js): add useCallback hook to newConversation function refactor(conversations.js): add useCallback hook to refreshConversations function chore(tsconfig.json): change jsx option to 'preserve'
This commit is contained in:
parent
f171628948
commit
544d72ee1d
10 changed files with 134 additions and 125 deletions
|
|
@ -39,10 +39,6 @@
|
|||
"@radix-ui/react-tabs": "^1.0.3",
|
||||
"@tailwindcss/forms": "^0.5.3",
|
||||
"@tanstack/react-query": "^4.28.0",
|
||||
"@types/jest": "^29.5.0",
|
||||
"@types/node": "^20.2.3",
|
||||
"@types/react": "^18.0.30",
|
||||
"@types/react-dom": "^18.0.11",
|
||||
"@zattoo/use-double-click": "1.2.0",
|
||||
"axios": "^1.3.4",
|
||||
"class-variance-authority": "^0.6.0",
|
||||
|
|
@ -94,10 +90,10 @@
|
|||
"@testing-library/jest-dom": "^5.16.5",
|
||||
"@testing-library/react": "^14.0.0",
|
||||
"@testing-library/user-event": "^14.4.3",
|
||||
"@types/jest": "^29.5.1",
|
||||
"@types/node": "^18.16.13",
|
||||
"@types/react": "^18.2.6",
|
||||
"@types/react-dom": "^18.0.11",
|
||||
"@types/jest": "^29.5.2",
|
||||
"@types/node": "^20.3.0",
|
||||
"@types/react": "^18.2.11",
|
||||
"@types/react-dom": "^18.2.4",
|
||||
"@vitejs/plugin-react": "^4.0.0",
|
||||
"autoprefixer": "^10.4.13",
|
||||
"babel-jest": "^29.5.0",
|
||||
|
|
|
|||
|
|
@ -1,34 +1,18 @@
|
|||
import { Dialog } from '../ui/Dialog.tsx';
|
||||
import * as Tabs from '@radix-ui/react-tabs';
|
||||
import { DialogContent, DialogHeader, DialogTitle } from '../ui/Dialog.tsx';
|
||||
import { useEffect, useState, useContext } from 'react';
|
||||
import { Dialog, DialogContent, DialogHeader, DialogTitle } from '../ui/Dialog.tsx';
|
||||
import { General } from './SettingsTabs/';
|
||||
import { CogIcon } from '~/components/svg';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { cn } from '~/utils/';
|
||||
import { useClearConversationsMutation } from '~/data-provider';
|
||||
import { ThemeContext } from '~/hooks/ThemeContext';
|
||||
import store from '~/store';
|
||||
import { CheckIcon } from 'lucide-react';
|
||||
|
||||
export default function Settings({ open, onOpenChange }) {
|
||||
const { theme, setTheme } = useContext(ThemeContext);
|
||||
const { newConversation } = store.useConversation();
|
||||
const { refreshConversations } = store.useConversations();
|
||||
const clearConvosMutation = useClearConversationsMutation();
|
||||
const [isMobile, setIsMobile] = useState(false);
|
||||
const [confirmClear, setConfirmClear] = useState(false);
|
||||
|
||||
const clearConvos = () => {
|
||||
if (confirmClear) {
|
||||
console.log('Clearing conversations...');
|
||||
clearConvosMutation.mutate();
|
||||
setConfirmClear(false);
|
||||
} else {
|
||||
setConfirmClear(true);
|
||||
}
|
||||
};
|
||||
|
||||
const changeTheme = (e) => {
|
||||
setTheme(e.target.value);
|
||||
};
|
||||
const [isMobile, setIsMobile] = useState(false);
|
||||
|
||||
// check if mobile dynamically and update
|
||||
useEffect(() => {
|
||||
|
|
@ -46,10 +30,10 @@ export default function Settings({ open, onOpenChange }) {
|
|||
|
||||
useEffect(() => {
|
||||
if (clearConvosMutation.isSuccess) {
|
||||
newConversation();
|
||||
refreshConversations();
|
||||
newConversation();
|
||||
}
|
||||
}, [clearConvosMutation.isSuccess]);
|
||||
}, [clearConvosMutation.isSuccess, newConversation, refreshConversations]);
|
||||
|
||||
useEffect(() => {
|
||||
// If the user clicks in the dialog when confirmClear is true, set it to false
|
||||
|
|
@ -71,7 +55,9 @@ export default function Settings({ open, onOpenChange }) {
|
|||
<Dialog open={open} onOpenChange={onOpenChange}>
|
||||
<DialogContent className={cn('shadow-2xl dark:bg-gray-900 dark:text-white')}>
|
||||
<DialogHeader>
|
||||
<DialogTitle className="text-gray-800 dark:text-white">Settings</DialogTitle>
|
||||
<DialogTitle className="text-lg font-medium leading-6 text-gray-900 dark:text-gray-200">
|
||||
Settings
|
||||
</DialogTitle>
|
||||
</DialogHeader>
|
||||
<div className="px-6">
|
||||
<Tabs.Root
|
||||
|
|
@ -97,71 +83,11 @@ export default function Settings({ open, onOpenChange }) {
|
|||
)}
|
||||
value="general"
|
||||
>
|
||||
<svg
|
||||
stroke="currentColor"
|
||||
fill="currentColor"
|
||||
strokeWidth="0"
|
||||
viewBox="0 0 20 20"
|
||||
className="group-radix-state-active:fill-white h-4 h-5 w-4 w-5 fill-white dark:fill-gray-500"
|
||||
height="1em"
|
||||
width="1em"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
fillRule="evenodd"
|
||||
d="M11.49 3.17c-.38-1.56-2.6-1.56-2.98 0a1.532 1.532 0 01-2.286.948c-1.372-.836-2.942.734-2.106 2.106.54.886.061 2.042-.947 2.287-1.561.379-1.561 2.6 0 2.978a1.532 1.532 0 01.947 2.287c-.836 1.372.734 2.942 2.106 2.106a1.532 1.532 0 012.287.947c.379 1.561 2.6 1.561 2.978 0a1.533 1.533 0 012.287-.947c1.372.836 2.942-.734 2.106-2.106a1.533 1.533 0 01.947-2.287c1.561-.379 1.561-2.6 0-2.978a1.532 1.532 0 01-.947-2.287c.836-1.372-.734-2.942-2.106-2.106a1.532 1.532 0 01-2.287-.947zM10 13a3 3 0 100-6 3 3 0 000 6z"
|
||||
clipRule="evenodd"
|
||||
/>
|
||||
</svg>
|
||||
<CogIcon />
|
||||
General
|
||||
</Tabs.Trigger>
|
||||
</Tabs.List>
|
||||
|
||||
<Tabs.Content value="general" role="tabpanel" className="w-full md:min-h-[300px]">
|
||||
<div className="flex flex-col gap-3 text-sm text-gray-600 dark:text-gray-300">
|
||||
<div className="border-b pb-3 last-of-type:border-b-0 dark:border-gray-700">
|
||||
<div className="flex items-center justify-between">
|
||||
<div>Theme</div>
|
||||
<select
|
||||
className="w-24 rounded border border-black/10 bg-transparent text-sm dark:border-white/20 dark:bg-gray-900"
|
||||
onChange={changeTheme}
|
||||
value={theme}
|
||||
>
|
||||
<option value="system">System</option>
|
||||
<option value="dark">Dark</option>
|
||||
<option value="light">Light</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div className="border-b pb-3 last-of-type:border-b-0 dark:border-gray-700">
|
||||
<div className="flex items-center justify-between">
|
||||
<div>Clear all chats</div>
|
||||
<button
|
||||
className="btn relative bg-red-600 text-white hover:bg-red-800"
|
||||
type="button"
|
||||
id="clearConvosBtn"
|
||||
onClick={clearConvos}
|
||||
>
|
||||
{confirmClear ? (
|
||||
<div
|
||||
className="flex w-full items-center justify-center gap-2"
|
||||
id="clearConvosTxt"
|
||||
>
|
||||
<CheckIcon className="h-5 w-5" /> Confirm Clear
|
||||
</div>
|
||||
) : (
|
||||
<div
|
||||
className="flex w-full items-center justify-center gap-2"
|
||||
id="clearConvosTxt"
|
||||
>
|
||||
Clear
|
||||
</div>
|
||||
)}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Tabs.Content>
|
||||
<General />
|
||||
</Tabs.Root>
|
||||
</div>
|
||||
</DialogContent>
|
||||
|
|
|
|||
77
client/src/components/Nav/SettingsTabs/General.tsx
Normal file
77
client/src/components/Nav/SettingsTabs/General.tsx
Normal file
|
|
@ -0,0 +1,77 @@
|
|||
import * as Tabs from '@radix-ui/react-tabs';
|
||||
import { CheckIcon } from 'lucide-react';
|
||||
import { ThemeContext } from '~/hooks/ThemeContext';
|
||||
import React, { useState, useContext, useCallback } from 'react';
|
||||
import { useClearConversationsMutation } from '~/data-provider';
|
||||
|
||||
const ThemeSelector = ({ theme, onChange }: { theme: string, onChange: (value: string) => void }) => (
|
||||
<div className="flex items-center justify-between">
|
||||
<div>Theme</div>
|
||||
<select
|
||||
className="w-24 rounded border border-black/10 bg-transparent text-sm dark:border-white/20 dark:bg-gray-900"
|
||||
onChange={(e) => onChange(e.target.value)}
|
||||
value={theme}
|
||||
>
|
||||
<option value="system">System</option>
|
||||
<option value="dark">Dark</option>
|
||||
<option value="light">Light</option>
|
||||
</select>
|
||||
</div>
|
||||
);
|
||||
|
||||
const ClearChatsButton = ({ confirmClear, onClick }: { confirmClear: boolean, onClick: () => void }) => (
|
||||
<div className="flex items-center justify-between">
|
||||
<div>Clear all chats</div>
|
||||
<button
|
||||
className="btn relative bg-red-600 text-white hover:bg-red-800"
|
||||
type="button"
|
||||
id="clearConvosBtn"
|
||||
onClick={onClick}
|
||||
>
|
||||
{confirmClear ? (
|
||||
<div className="flex w-full items-center justify-center gap-2" id="clearConvosTxt">
|
||||
<CheckIcon className="h-5 w-5" /> Confirm Clear
|
||||
</div>
|
||||
) : (
|
||||
<div className="flex w-full items-center justify-center gap-2" id="clearConvosTxt">
|
||||
Clear
|
||||
</div>
|
||||
)}
|
||||
</button>
|
||||
</div>
|
||||
);
|
||||
|
||||
function General() {
|
||||
const { theme, setTheme } = useContext(ThemeContext);
|
||||
const clearConvosMutation = useClearConversationsMutation();
|
||||
const [confirmClear, setConfirmClear] = useState(false);
|
||||
|
||||
const clearConvos = useCallback(() => {
|
||||
if (confirmClear) {
|
||||
console.log('Clearing conversations...');
|
||||
clearConvosMutation.mutate({});
|
||||
setConfirmClear(false);
|
||||
} else {
|
||||
setConfirmClear(true);
|
||||
}
|
||||
}, [confirmClear, clearConvosMutation]);
|
||||
|
||||
const changeTheme = useCallback((value: string) => {
|
||||
setTheme(value);
|
||||
}, [setTheme]);
|
||||
|
||||
return (
|
||||
<Tabs.Content value="general" role="tabpanel" className="w-full md:min-h-[300px]" >
|
||||
<div className="flex flex-col gap-3 text-sm text-gray-600 dark:text-gray-300">
|
||||
<div className="border-b pb-3 last-of-type:border-b-0 dark:border-gray-700">
|
||||
<ThemeSelector theme={theme} onChange={changeTheme} />
|
||||
</div>
|
||||
<div className="border-b pb-3 last-of-type:border-b-0 dark:border-gray-700">
|
||||
<ClearChatsButton confirmClear={confirmClear} onClick={clearConvos} />
|
||||
</div>
|
||||
</div>
|
||||
</Tabs.Content>
|
||||
);
|
||||
}
|
||||
|
||||
export default React.memo(General);
|
||||
1
client/src/components/Nav/SettingsTabs/index.ts
Normal file
1
client/src/components/Nav/SettingsTabs/index.ts
Normal file
|
|
@ -0,0 +1 @@
|
|||
export { default as General } from './General';
|
||||
22
client/src/components/svg/CogIcon.tsx
Normal file
22
client/src/components/svg/CogIcon.tsx
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
import * as React from 'react'
|
||||
|
||||
export default function CogIcon() {
|
||||
return (
|
||||
<svg
|
||||
stroke="currentColor"
|
||||
fill="currentColor"
|
||||
strokeWidth="0"
|
||||
viewBox="0 0 20 20"
|
||||
className="group-radix-state-active:fill-white h-4 h-5 w-4 w-5 fill-white dark:fill-gray-500"
|
||||
height="1em"
|
||||
width="1em"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
fillRule="evenodd"
|
||||
d="M11.49 3.17c-.38-1.56-2.6-1.56-2.98 0a1.532 1.532 0 01-2.286.948c-1.372-.836-2.942.734-2.106 2.106.54.886.061 2.042-.947 2.287-1.561.379-1.561 2.6 0 2.978a1.532 1.532 0 01.947 2.287c-.836 1.372.734 2.942 2.106 2.106a1.532 1.532 0 012.287.947c.379 1.561 2.6 1.561 2.978 0a1.533 1.533 0 012.287-.947c1.372.836 2.942-.734 2.106-2.106a1.533 1.533 0 01.947-2.287c1.561-.379 1.561-2.6 0-2.978a1.532 1.532 0 01-.947-2.287c.836-1.372-.734-2.942-2.106-2.106a1.532 1.532 0 01-2.287-.947zM10 13a3 3 0 100-6 3 3 0 000 6z"
|
||||
clipRule="evenodd"
|
||||
/>
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
|
|
@ -1,4 +1,5 @@
|
|||
export { default as Plugin } from './Plugin';
|
||||
export { default as GPTIcon } from './GPTIcon';
|
||||
export { default as BingIcon } from './BingIcon';
|
||||
export { default as CogIcon } from './CogIcon';
|
||||
export { default as MessagesSquared } from './MessagesSquared';
|
||||
|
|
@ -1,4 +1,5 @@
|
|||
import endpoints from './endpoints';
|
||||
import { useCallback } from 'react';
|
||||
import {
|
||||
atom,
|
||||
selector,
|
||||
|
|
@ -112,7 +113,7 @@ const useConversation = () => {
|
|||
);
|
||||
|
||||
|
||||
const newConversation = (template = {}, preset) => {
|
||||
const newConversation = useCallback((template = {}, preset) => {
|
||||
switchToConversation(
|
||||
{
|
||||
conversationId: 'new',
|
||||
|
|
@ -122,7 +123,7 @@ const useConversation = () => {
|
|||
[],
|
||||
preset
|
||||
);
|
||||
};
|
||||
}, [switchToConversation]);
|
||||
|
||||
const searchPlaceholderConversation = () => {
|
||||
switchToConversation(
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import { atom, useSetRecoilState } from 'recoil';
|
||||
import { useCallback } from 'react';
|
||||
|
||||
const refreshConversationsHint = atom({
|
||||
key: 'refreshConversationsHint',
|
||||
|
|
@ -8,7 +9,9 @@ const refreshConversationsHint = atom({
|
|||
const useConversations = () => {
|
||||
const setRefreshConversationsHint = useSetRecoilState(refreshConversationsHint);
|
||||
|
||||
const refreshConversations = () => setRefreshConversationsHint((prevState) => prevState + 1);
|
||||
const refreshConversations = useCallback(() => {
|
||||
setRefreshConversationsHint((prevState) => prevState + 1);
|
||||
}, [setRefreshConversationsHint]);
|
||||
|
||||
return { refreshConversations };
|
||||
};
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
"noEmit": false,
|
||||
"declaration": true,
|
||||
"declarationDir": "./types",
|
||||
"jsx": "react-jsx",
|
||||
"jsx": "preserve",
|
||||
"baseUrl": ".",
|
||||
"paths": {
|
||||
"~/*": ["./src/*"]
|
||||
|
|
|
|||
36
package-lock.json
generated
36
package-lock.json
generated
|
|
@ -342,10 +342,6 @@
|
|||
"@radix-ui/react-tabs": "^1.0.3",
|
||||
"@tailwindcss/forms": "^0.5.3",
|
||||
"@tanstack/react-query": "^4.28.0",
|
||||
"@types/jest": "^29.5.0",
|
||||
"@types/node": "^20.2.3",
|
||||
"@types/react": "^18.0.30",
|
||||
"@types/react-dom": "^18.0.11",
|
||||
"@zattoo/use-double-click": "1.2.0",
|
||||
"axios": "^1.3.4",
|
||||
"class-variance-authority": "^0.6.0",
|
||||
|
|
@ -397,10 +393,10 @@
|
|||
"@testing-library/jest-dom": "^5.16.5",
|
||||
"@testing-library/react": "^14.0.0",
|
||||
"@testing-library/user-event": "^14.4.3",
|
||||
"@types/jest": "^29.5.1",
|
||||
"@types/node": "^18.16.13",
|
||||
"@types/react": "^18.2.6",
|
||||
"@types/react-dom": "^18.0.11",
|
||||
"@types/jest": "^29.5.2",
|
||||
"@types/node": "^20.3.0",
|
||||
"@types/react": "^18.2.11",
|
||||
"@types/react-dom": "^18.2.4",
|
||||
"@vitejs/plugin-react": "^4.0.0",
|
||||
"autoprefixer": "^10.4.13",
|
||||
"babel-jest": "^29.5.0",
|
||||
|
|
@ -433,12 +429,6 @@
|
|||
"vite-plugin-html": "^3.2.0"
|
||||
}
|
||||
},
|
||||
"client/node_modules/@types/node": {
|
||||
"version": "18.16.17",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-18.16.17.tgz",
|
||||
"integrity": "sha512-QAkjjRA1N7gPJeAP4WLXZtYv6+eMXFNviqktCDt4GLcmCugMr5BcRHfkOjCQzvCsnMp+L79a54zBkbw356xv9Q==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@adobe/css-tools": {
|
||||
"version": "4.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@adobe/css-tools/-/css-tools-4.2.0.tgz",
|
||||
|
|
@ -32056,7 +32046,7 @@
|
|||
"jsonwebtoken": "^9.0.0",
|
||||
"keyv": "^4.5.2",
|
||||
"keyv-file": "^0.2.0",
|
||||
"langchain": "0.0.92",
|
||||
"langchain": "^0.0.92",
|
||||
"lodash": "^4.17.21",
|
||||
"meilisearch": "^0.33.0",
|
||||
"mongoose": "^7.1.1",
|
||||
|
|
@ -32145,10 +32135,10 @@
|
|||
"@testing-library/jest-dom": "^5.16.5",
|
||||
"@testing-library/react": "^14.0.0",
|
||||
"@testing-library/user-event": "^14.4.3",
|
||||
"@types/jest": "^29.5.1",
|
||||
"@types/node": "^18.16.13",
|
||||
"@types/react": "^18.2.6",
|
||||
"@types/react-dom": "^18.0.11",
|
||||
"@types/jest": "^29.5.2",
|
||||
"@types/node": "^20.3.0",
|
||||
"@types/react": "^18.2.11",
|
||||
"@types/react-dom": "^18.2.4",
|
||||
"@vitejs/plugin-react": "^4.0.0",
|
||||
"@zattoo/use-double-click": "1.2.0",
|
||||
"autoprefixer": "^10.4.13",
|
||||
|
|
@ -32215,14 +32205,6 @@
|
|||
"url": "^0.11.0",
|
||||
"vite": "^4.3.9",
|
||||
"vite-plugin-html": "^3.2.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@types/node": {
|
||||
"version": "18.16.17",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-18.16.17.tgz",
|
||||
"integrity": "sha512-QAkjjRA1N7gPJeAP4WLXZtYv6+eMXFNviqktCDt4GLcmCugMr5BcRHfkOjCQzvCsnMp+L79a54zBkbw356xv9Q==",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"cheerio": {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue