mirror of
https://github.com/danny-avila/LibreChat.git
synced 2025-12-28 06:08:50 +01:00
✨ feat: Implement CreatePromptButton and enhance AutoSendPrompt with dialog settings
This commit is contained in:
parent
0e26df0390
commit
3e698338aa
9 changed files with 108 additions and 62 deletions
34
client/src/components/Prompts/CreatePrompt.tsx
Normal file
34
client/src/components/Prompts/CreatePrompt.tsx
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
import React from 'react';
|
||||
import { Plus } from 'lucide-react';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import { PermissionTypes, Permissions } from 'librechat-data-provider';
|
||||
import { useLocalize, useHasAccess } from '~/hooks';
|
||||
import { Button } from '~/components/ui';
|
||||
|
||||
const CreatePromptButton: React.FC<{ isChatRoute: boolean }> = ({ isChatRoute }) => {
|
||||
const navigate = useNavigate();
|
||||
const localize = useLocalize();
|
||||
const hasCreateAccess = useHasAccess({
|
||||
permissionType: PermissionTypes.PROMPTS,
|
||||
permission: Permissions.CREATE,
|
||||
});
|
||||
|
||||
return (
|
||||
<>
|
||||
{hasCreateAccess && (
|
||||
<div className="flex w-full justify-end">
|
||||
<Button
|
||||
variant="outline"
|
||||
className={`w-full bg-transparent ${isChatRoute ? '' : 'mx-2'}`}
|
||||
onClick={() => navigate('/d/prompts/new')}
|
||||
>
|
||||
<Plus className="size-4" aria-hidden />
|
||||
{localize('com_ui_create_prompt')}
|
||||
</Button>
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default CreatePromptButton;
|
||||
|
|
@ -1,5 +1,14 @@
|
|||
import { Cog } from 'lucide-react';
|
||||
import { useRecoilState } from 'recoil';
|
||||
import { Switch } from '~/components/ui';
|
||||
import {
|
||||
Label,
|
||||
Switch,
|
||||
Button,
|
||||
OGDialog,
|
||||
OGDialogTrigger,
|
||||
OGDialogContent,
|
||||
OGDialogTitle,
|
||||
} from '~/components';
|
||||
import { useLocalize } from '~/hooks';
|
||||
import { cn } from '~/utils';
|
||||
import store from '~/store';
|
||||
|
|
@ -22,20 +31,30 @@ export default function AutoSendPrompt({
|
|||
};
|
||||
|
||||
return (
|
||||
<div
|
||||
className={cn(
|
||||
'flex select-none items-center justify-end gap-2 text-right text-sm',
|
||||
className,
|
||||
)}
|
||||
>
|
||||
<div> {localize('com_nav_auto_send_prompts')} </div>
|
||||
<Switch
|
||||
aria-label="toggle-auto-send-prompts"
|
||||
id="autoSendPrompts"
|
||||
checked={autoSendPrompts}
|
||||
onCheckedChange={handleCheckedChange}
|
||||
data-testid="autoSendPrompts"
|
||||
/>
|
||||
</div>
|
||||
<>
|
||||
<OGDialog>
|
||||
<OGDialogTrigger className="flex items-center justify-center">
|
||||
<Button size="sm" variant="outline" className="bg-transparent hover:bg-surface-hover">
|
||||
<Cog className="h-4 w-4 text-text-primary" />
|
||||
</Button>
|
||||
</OGDialogTrigger>
|
||||
<OGDialogContent className="w-96">
|
||||
<OGDialogTitle className="text-lg font-semibold">
|
||||
{localize('com_ui_prompts_settings')}
|
||||
</OGDialogTitle>
|
||||
|
||||
<div className={cn('flex justify-between text-text-secondary', className)}>
|
||||
<Label>{localize('com_nav_auto_send_prompts')}</Label>
|
||||
<Switch
|
||||
aria-label="toggle-auto-send-prompts"
|
||||
id="autoSendPrompts"
|
||||
checked={autoSendPrompts}
|
||||
onCheckedChange={handleCheckedChange}
|
||||
data-testid="autoSendPrompts"
|
||||
/>
|
||||
</div>
|
||||
</OGDialogContent>
|
||||
</OGDialog>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -44,11 +44,11 @@ export default function FilterPrompts({
|
|||
const categoryOptions = categories
|
||||
? [...categories]
|
||||
: [
|
||||
{
|
||||
value: SystemCategories.NO_CATEGORY,
|
||||
label: localize('com_ui_no_category'),
|
||||
},
|
||||
];
|
||||
{
|
||||
value: SystemCategories.NO_CATEGORY,
|
||||
label: localize('com_ui_no_category'),
|
||||
},
|
||||
];
|
||||
|
||||
return [...baseOptions, ...categoryOptions];
|
||||
}, [categories, localize]);
|
||||
|
|
@ -78,7 +78,7 @@ export default function FilterPrompts({
|
|||
value={categoryFilter || SystemCategories.ALL}
|
||||
onChange={onSelect}
|
||||
options={filterOptions}
|
||||
className="bg-transparent"
|
||||
className="rounded-lg bg-transparent"
|
||||
icon={<ListFilter className="h-4 w-4" />}
|
||||
label="Filter: "
|
||||
ariaLabel={localize('com_ui_filter_prompts')}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,3 @@
|
|||
import { useMemo } from 'react';
|
||||
import { useLocation } from 'react-router-dom';
|
||||
import PanelNavigation from '~/components/Prompts/Groups/PanelNavigation';
|
||||
import { useMediaQuery, usePromptGroupsNav } from '~/hooks';
|
||||
import List from '~/components/Prompts/Groups/List';
|
||||
|
|
@ -17,14 +15,14 @@ export default function GroupSidePanel({
|
|||
groupsQuery,
|
||||
promptGroups,
|
||||
hasPreviousPage,
|
||||
isChatRoute,
|
||||
}: {
|
||||
children?: React.ReactNode;
|
||||
isDetailView?: boolean;
|
||||
className?: string;
|
||||
isChatRoute: boolean;
|
||||
} & ReturnType<typeof usePromptGroupsNav>) {
|
||||
const location = useLocation();
|
||||
const isSmallerScreen = useMediaQuery('(max-width: 1024px)');
|
||||
const isChatRoute = useMemo(() => location.pathname?.startsWith('/c/'), [location.pathname]);
|
||||
|
||||
return (
|
||||
<div
|
||||
|
|
|
|||
|
|
@ -1,13 +1,10 @@
|
|||
import { Plus } from 'lucide-react';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import { PermissionTypes, Permissions } from 'librechat-data-provider';
|
||||
import type { TPromptGroup, TStartupConfig } from 'librechat-data-provider';
|
||||
import { RankablePromptList, RankingProvider } from '~/components/Prompts/Groups/RankingComponent';
|
||||
import DashGroupItem from '~/components/Prompts/Groups/DashGroupItem';
|
||||
import ChatGroupItem from '~/components/Prompts/Groups/ChatGroupItem';
|
||||
import { useGetStartupConfig } from '~/data-provider';
|
||||
import { useLocalize, useHasAccess } from '~/hooks';
|
||||
import { Button, Skeleton } from '~/components/ui';
|
||||
import { useLocalize } from '~/hooks';
|
||||
|
||||
export default function List({
|
||||
groups = [],
|
||||
|
|
@ -20,14 +17,9 @@ export default function List({
|
|||
isLoading: boolean;
|
||||
enableRanking?: boolean;
|
||||
}) {
|
||||
const navigate = useNavigate();
|
||||
const localize = useLocalize();
|
||||
const { data: startupConfig = {} as Partial<TStartupConfig> } = useGetStartupConfig();
|
||||
const { instanceProjectId } = startupConfig;
|
||||
const hasCreateAccess = useHasAccess({
|
||||
permissionType: PermissionTypes.PROMPTS,
|
||||
permission: Permissions.CREATE,
|
||||
});
|
||||
|
||||
const renderGroupItem = (group: TPromptGroup) => {
|
||||
if (isChatRoute) {
|
||||
|
|
@ -39,18 +31,6 @@ export default function List({
|
|||
return (
|
||||
<RankingProvider>
|
||||
<div className="flex h-full flex-col">
|
||||
{hasCreateAccess && (
|
||||
<div className="flex w-full justify-end">
|
||||
<Button
|
||||
variant="outline"
|
||||
className={`w-full bg-transparent ${isChatRoute ? '' : 'mx-2'}`}
|
||||
onClick={() => navigate('/d/prompts/new')}
|
||||
>
|
||||
<Plus className="size-4" aria-hidden />
|
||||
{localize('com_ui_create_prompt')}
|
||||
</Button>
|
||||
</div>
|
||||
)}
|
||||
<div className="flex-grow overflow-y-auto">
|
||||
<div className="overflow-y-auto overflow-x-hidden">
|
||||
{isLoading && isChatRoute && (
|
||||
|
|
@ -74,7 +54,7 @@ export default function List({
|
|||
{localize('com_ui_nothing_found')}
|
||||
</div>
|
||||
)}
|
||||
{!isLoading && groups.length > 0 && enableRanking ? (
|
||||
{!isLoading && groups.length > 0 && !isChatRoute && enableRanking ? (
|
||||
<RankablePromptList groups={groups} renderItem={renderGroupItem} />
|
||||
) : (
|
||||
!isLoading && groups.map((group) => renderGroupItem(group))
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
import { memo } from 'react';
|
||||
import { Button, ThemeSelector } from '~/components/ui';
|
||||
import AutoSendPrompt from '~/components/Prompts/Groups/AutoSendPrompt';
|
||||
import { Button } from '~/components';
|
||||
import { useLocalize } from '~/hooks';
|
||||
import { cn } from '~/utils';
|
||||
|
||||
function PanelNavigation({
|
||||
prevPage,
|
||||
|
|
@ -19,12 +21,16 @@ function PanelNavigation({
|
|||
}) {
|
||||
const localize = useLocalize();
|
||||
return (
|
||||
<div className="my-1 flex justify-between">
|
||||
<div className={cn('my-1 flex justify-between', !isChatRoute && 'mx-2')}>
|
||||
<AutoSendPrompt className="text-xs dark:text-white" />
|
||||
<div className="mb-2 flex gap-2">
|
||||
{!isChatRoute && <ThemeSelector returnThemeOnly={true} />}
|
||||
</div>
|
||||
<div className="mb-2 flex gap-2">
|
||||
<Button variant="outline" size="sm" onClick={() => prevPage()} disabled={!hasPreviousPage}>
|
||||
<Button
|
||||
variant="outline"
|
||||
size="sm"
|
||||
onClick={() => prevPage()}
|
||||
disabled={!hasPreviousPage}
|
||||
className="bg-transparent hover:bg-surface-hover"
|
||||
>
|
||||
{localize('com_ui_prev')}
|
||||
</Button>
|
||||
<Button
|
||||
|
|
@ -32,6 +38,7 @@ function PanelNavigation({
|
|||
size="sm"
|
||||
onClick={() => nextPage()}
|
||||
disabled={!hasNextPage || isFetching}
|
||||
className="bg-transparent hover:bg-surface-hover"
|
||||
>
|
||||
{localize('com_ui_next')}
|
||||
</Button>
|
||||
|
|
|
|||
|
|
@ -1,19 +1,24 @@
|
|||
import React, { useMemo } from 'react';
|
||||
import { useLocation } from 'react-router-dom';
|
||||
import PromptSidePanel from '~/components/Prompts/Groups/GroupSidePanel';
|
||||
import AutoSendPrompt from '~/components/Prompts/Groups/AutoSendPrompt';
|
||||
import FilterPrompts from '~/components/Prompts/Groups/FilterPrompts';
|
||||
import ManagePrompts from '~/components/Prompts/ManagePrompts';
|
||||
import CreatePrompt from '~/components/Prompts/CreatePrompt';
|
||||
import { usePromptGroupsNav } from '~/hooks';
|
||||
|
||||
export default function PromptsAccordion() {
|
||||
const location = useLocation();
|
||||
const groupsNav = usePromptGroupsNav();
|
||||
const isChatRoute = useMemo(() => location.pathname?.startsWith('/c/'), [location.pathname]);
|
||||
|
||||
return (
|
||||
<div className="flex h-full w-full flex-col">
|
||||
<PromptSidePanel className="lg:w-full xl:w-full" {...groupsNav}>
|
||||
<div className="flex w-full flex-row items-center justify-between pt-2">
|
||||
<ManagePrompts className="select-none" />
|
||||
<AutoSendPrompt className="text-xs dark:text-white" />
|
||||
</div>
|
||||
<div className="mt-2 flex h-full w-full flex-col">
|
||||
<PromptSidePanel isChatRoute={isChatRoute} className="lg:w-full xl:w-full" {...groupsNav}>
|
||||
<FilterPrompts setName={groupsNav.setName} className="items-center justify-center" />
|
||||
<div className="flex w-full flex-row items-center justify-between gap-2">
|
||||
<ManagePrompts className="select-none" />
|
||||
<CreatePrompt isChatRoute={isChatRoute} />
|
||||
</div>
|
||||
</PromptSidePanel>
|
||||
</div>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -822,6 +822,7 @@
|
|||
"com_ui_prompts_allow_create": "Allow creating Prompts",
|
||||
"com_ui_prompts_allow_share_global": "Allow sharing Prompts to all users",
|
||||
"com_ui_prompts_allow_use": "Allow using Prompts",
|
||||
"com_ui_prompts_settings": "Prompt Settings",
|
||||
"com_ui_provider": "Provider",
|
||||
"com_ui_read_aloud": "Read aloud",
|
||||
"com_ui_redirecting_to_provider": "Redirecting to {{0}}, please wait...",
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import { SystemRoles } from 'librechat-data-provider';
|
|||
import { useRecoilValue, useSetRecoilState } from 'recoil';
|
||||
import { ArrowLeft, MessageSquareQuote } from 'lucide-react';
|
||||
import {
|
||||
ThemeSelector,
|
||||
Breadcrumb,
|
||||
BreadcrumbItem,
|
||||
BreadcrumbLink,
|
||||
|
|
@ -14,7 +15,7 @@ import {
|
|||
// DropdownMenuItem,
|
||||
// DropdownMenuContent,
|
||||
// DropdownMenuTrigger,
|
||||
} from '~/components/ui';
|
||||
} from '~/components';
|
||||
import { useLocalize, useCustomLink, useAuthContext } from '~/hooks';
|
||||
import AdvancedSwitch from '~/components/Prompts/AdvancedSwitch';
|
||||
// import { RightPanel } from '../../components/Prompts/RightPanel';
|
||||
|
|
@ -106,6 +107,7 @@ export default function DashBreadcrumb() {
|
|||
</Breadcrumb>
|
||||
<div className="flex items-center justify-center gap-2">
|
||||
{isPromptsPath && <AdvancedSwitch />}
|
||||
<ThemeSelector returnThemeOnly={true} />
|
||||
{user?.role === SystemRoles.ADMIN && <AdminSettings />}
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue