mirror of
https://github.com/danswer-ai/danswer.git
synced 2025-09-28 21:05:17 +02:00
Improved tenant handling for slack bot (#4099)
This commit is contained in:
@@ -1,8 +1,8 @@
|
|||||||
import React, { useState, useEffect } from "react";
|
import React, { useState, useEffect, useCallback } from "react";
|
||||||
import { InputPrompt } from "@/app/chat/interfaces";
|
import { InputPrompt } from "@/app/chat/interfaces";
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
import { TrashIcon, PlusIcon } from "@/components/icons/icons";
|
import { PlusIcon } from "@/components/icons/icons";
|
||||||
import { MoreVertical, CheckIcon, XIcon } from "lucide-react";
|
import { MoreVertical, XIcon } from "lucide-react";
|
||||||
import { Textarea } from "@/components/ui/textarea";
|
import { Textarea } from "@/components/ui/textarea";
|
||||||
import Title from "@/components/ui/title";
|
import Title from "@/components/ui/title";
|
||||||
import Text from "@/components/ui/text";
|
import Text from "@/components/ui/text";
|
||||||
@@ -153,114 +153,6 @@ export default function InputPrompts() {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const PromptCard = ({ prompt }: { prompt: InputPrompt }) => {
|
|
||||||
const isEditing = editingPromptId === prompt.id;
|
|
||||||
const [localPrompt, setLocalPrompt] = useState(prompt.prompt);
|
|
||||||
const [localContent, setLocalContent] = useState(prompt.content);
|
|
||||||
|
|
||||||
// Sync local edits with any prompt changes from outside
|
|
||||||
useEffect(() => {
|
|
||||||
setLocalPrompt(prompt.prompt);
|
|
||||||
setLocalContent(prompt.content);
|
|
||||||
}, [prompt, isEditing]);
|
|
||||||
|
|
||||||
const handleLocalEdit = (field: "prompt" | "content", value: string) => {
|
|
||||||
if (field === "prompt") {
|
|
||||||
setLocalPrompt(value);
|
|
||||||
} else {
|
|
||||||
setLocalContent(value);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleSaveLocal = () => {
|
|
||||||
handleSave(prompt.id, localPrompt, localContent);
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className="border dark:border-none dark:bg-[#333333] rounded-lg p-4 mb-4 relative">
|
|
||||||
{isEditing ? (
|
|
||||||
<>
|
|
||||||
<div className="absolute top-2 right-2">
|
|
||||||
<Button
|
|
||||||
variant="ghost"
|
|
||||||
size="sm"
|
|
||||||
onClick={() => {
|
|
||||||
setEditingPromptId(null);
|
|
||||||
fetchInputPrompts(); // Revert changes from server
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<XIcon size={14} />
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
<div className="flex">
|
|
||||||
<div className="flex-grow mr-4">
|
|
||||||
<Textarea
|
|
||||||
value={localPrompt}
|
|
||||||
onChange={(e) => handleLocalEdit("prompt", e.target.value)}
|
|
||||||
className="mb-2 resize-none"
|
|
||||||
placeholder="Prompt"
|
|
||||||
/>
|
|
||||||
<Textarea
|
|
||||||
value={localContent}
|
|
||||||
onChange={(e) => handleLocalEdit("content", e.target.value)}
|
|
||||||
className="resize-vertical min-h-[100px]"
|
|
||||||
placeholder="Content"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div className="flex items-end">
|
|
||||||
<Button onClick={handleSaveLocal}>
|
|
||||||
{prompt.id ? "Save" : "Create"}
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</>
|
|
||||||
) : (
|
|
||||||
<>
|
|
||||||
<TooltipProvider>
|
|
||||||
<Tooltip>
|
|
||||||
<TooltipTrigger asChild>
|
|
||||||
<div className="mb-2 flex gap-x-2 ">
|
|
||||||
<p className="font-semibold">{prompt.prompt}</p>
|
|
||||||
{isPromptPublic(prompt) && <SourceChip title="Built-in" />}
|
|
||||||
</div>
|
|
||||||
</TooltipTrigger>
|
|
||||||
{isPromptPublic(prompt) && (
|
|
||||||
<TooltipContent>
|
|
||||||
<p>This is a built-in prompt and cannot be edited</p>
|
|
||||||
</TooltipContent>
|
|
||||||
)}
|
|
||||||
</Tooltip>
|
|
||||||
</TooltipProvider>
|
|
||||||
<div className="whitespace-pre-wrap">{prompt.content}</div>
|
|
||||||
<div className="absolute top-2 right-2">
|
|
||||||
<DropdownMenu>
|
|
||||||
<DropdownMenuTrigger className="hover:bg-transparent" asChild>
|
|
||||||
<Button
|
|
||||||
className="!hover:bg-transparent"
|
|
||||||
variant="ghost"
|
|
||||||
size="sm"
|
|
||||||
>
|
|
||||||
<MoreVertical size={14} />
|
|
||||||
</Button>
|
|
||||||
</DropdownMenuTrigger>
|
|
||||||
<DropdownMenuContent>
|
|
||||||
{!isPromptPublic(prompt) && (
|
|
||||||
<DropdownMenuItem onClick={() => handleEdit(prompt.id)}>
|
|
||||||
Edit
|
|
||||||
</DropdownMenuItem>
|
|
||||||
)}
|
|
||||||
<DropdownMenuItem onClick={() => handleDelete(prompt.id)}>
|
|
||||||
Delete
|
|
||||||
</DropdownMenuItem>
|
|
||||||
</DropdownMenuContent>
|
|
||||||
</DropdownMenu>
|
|
||||||
</div>
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="mx-auto max-w-4xl">
|
<div className="mx-auto max-w-4xl">
|
||||||
<div className="absolute top-4 left-4">
|
<div className="absolute top-4 left-4">
|
||||||
@@ -272,13 +164,21 @@ export default function InputPrompts() {
|
|||||||
<Title>Prompt Shortcuts</Title>
|
<Title>Prompt Shortcuts</Title>
|
||||||
<Text>
|
<Text>
|
||||||
Manage and customize prompt shortcuts for your assistants. Use your
|
Manage and customize prompt shortcuts for your assistants. Use your
|
||||||
prompt shortcuts by starting a new message “/” in chat.
|
prompt shortcuts by starting a new message with "/" in
|
||||||
|
chat.
|
||||||
</Text>
|
</Text>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{inputPrompts.map((prompt) => (
|
{inputPrompts.map((prompt) => (
|
||||||
<PromptCard key={prompt.id} prompt={prompt} />
|
<PromptCard
|
||||||
|
key={prompt.id}
|
||||||
|
prompt={prompt}
|
||||||
|
onEdit={handleEdit}
|
||||||
|
onSave={handleSave}
|
||||||
|
onDelete={handleDelete}
|
||||||
|
isEditing={editingPromptId === prompt.id}
|
||||||
|
/>
|
||||||
))}
|
))}
|
||||||
|
|
||||||
{isCreatingNew ? (
|
{isCreatingNew ? (
|
||||||
@@ -315,3 +215,129 @@ export default function InputPrompts() {
|
|||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface PromptCardProps {
|
||||||
|
prompt: InputPrompt;
|
||||||
|
onEdit: (id: number) => void;
|
||||||
|
onSave: (id: number, prompt: string, content: string) => void;
|
||||||
|
onDelete: (id: number) => void;
|
||||||
|
isEditing: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
const PromptCard: React.FC<PromptCardProps> = ({
|
||||||
|
prompt,
|
||||||
|
onEdit,
|
||||||
|
onSave,
|
||||||
|
onDelete,
|
||||||
|
isEditing,
|
||||||
|
}) => {
|
||||||
|
const [localPrompt, setLocalPrompt] = useState(prompt.prompt);
|
||||||
|
const [localContent, setLocalContent] = useState(prompt.content);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setLocalPrompt(prompt.prompt);
|
||||||
|
setLocalContent(prompt.content);
|
||||||
|
}, [prompt, isEditing]);
|
||||||
|
|
||||||
|
const handleLocalEdit = useCallback(
|
||||||
|
(field: "prompt" | "content", value: string) => {
|
||||||
|
if (field === "prompt") {
|
||||||
|
setLocalPrompt(value);
|
||||||
|
} else {
|
||||||
|
setLocalContent(value);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[]
|
||||||
|
);
|
||||||
|
|
||||||
|
const handleSaveLocal = useCallback(() => {
|
||||||
|
onSave(prompt.id, localPrompt, localContent);
|
||||||
|
}, [prompt.id, localPrompt, localContent, onSave]);
|
||||||
|
|
||||||
|
const isPromptPublic = useCallback((p: InputPrompt): boolean => {
|
||||||
|
return p.is_public;
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="border dark:border-none dark:bg-[#333333] rounded-lg p-4 mb-4 relative">
|
||||||
|
{isEditing ? (
|
||||||
|
<>
|
||||||
|
<div className="absolute top-2 right-2">
|
||||||
|
<Button
|
||||||
|
variant="ghost"
|
||||||
|
size="sm"
|
||||||
|
onClick={() => {
|
||||||
|
onEdit(0);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<XIcon size={14} />
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
<div className="flex">
|
||||||
|
<div className="flex-grow mr-4">
|
||||||
|
<Textarea
|
||||||
|
value={localPrompt}
|
||||||
|
onChange={(e) => handleLocalEdit("prompt", e.target.value)}
|
||||||
|
className="mb-2 resize-none"
|
||||||
|
placeholder="Prompt"
|
||||||
|
/>
|
||||||
|
<Textarea
|
||||||
|
value={localContent}
|
||||||
|
onChange={(e) => handleLocalEdit("content", e.target.value)}
|
||||||
|
className="resize-vertical min-h-[100px]"
|
||||||
|
placeholder="Content"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="flex items-end">
|
||||||
|
<Button onClick={handleSaveLocal}>
|
||||||
|
{prompt.id ? "Save" : "Create"}
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
<>
|
||||||
|
<TooltipProvider>
|
||||||
|
<Tooltip>
|
||||||
|
<TooltipTrigger asChild>
|
||||||
|
<div className="mb-2 flex gap-x-2 ">
|
||||||
|
<p className="font-semibold">{prompt.prompt}</p>
|
||||||
|
{isPromptPublic(prompt) && <SourceChip title="Built-in" />}
|
||||||
|
</div>
|
||||||
|
</TooltipTrigger>
|
||||||
|
{isPromptPublic(prompt) && (
|
||||||
|
<TooltipContent>
|
||||||
|
<p>This is a built-in prompt and cannot be edited</p>
|
||||||
|
</TooltipContent>
|
||||||
|
)}
|
||||||
|
</Tooltip>
|
||||||
|
</TooltipProvider>
|
||||||
|
<div className="whitespace-pre-wrap">{prompt.content}</div>
|
||||||
|
<div className="absolute top-2 right-2">
|
||||||
|
<DropdownMenu>
|
||||||
|
<DropdownMenuTrigger className="hover:bg-transparent" asChild>
|
||||||
|
<Button
|
||||||
|
className="!hover:bg-transparent"
|
||||||
|
variant="ghost"
|
||||||
|
size="sm"
|
||||||
|
>
|
||||||
|
<MoreVertical size={14} />
|
||||||
|
</Button>
|
||||||
|
</DropdownMenuTrigger>
|
||||||
|
<DropdownMenuContent>
|
||||||
|
{!isPromptPublic(prompt) && (
|
||||||
|
<DropdownMenuItem onClick={() => onEdit(prompt.id)}>
|
||||||
|
Edit
|
||||||
|
</DropdownMenuItem>
|
||||||
|
)}
|
||||||
|
<DropdownMenuItem onClick={() => onDelete(prompt.id)}>
|
||||||
|
Delete
|
||||||
|
</DropdownMenuItem>
|
||||||
|
</DropdownMenuContent>
|
||||||
|
</DropdownMenu>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
147
web/src/app/chat/input-prompts/PromptCard.tsx
Normal file
147
web/src/app/chat/input-prompts/PromptCard.tsx
Normal file
@@ -0,0 +1,147 @@
|
|||||||
|
import { SourceChip } from "../input/ChatInputBar";
|
||||||
|
|
||||||
|
import { useEffect } from "react";
|
||||||
|
import { useState } from "react";
|
||||||
|
import { InputPrompt } from "../interfaces";
|
||||||
|
import { Button } from "@/components/ui/button";
|
||||||
|
import { XIcon } from "@/components/icons/icons";
|
||||||
|
import { Textarea } from "@/components/ui/textarea";
|
||||||
|
import {
|
||||||
|
Tooltip,
|
||||||
|
TooltipContent,
|
||||||
|
TooltipProvider,
|
||||||
|
TooltipTrigger,
|
||||||
|
} from "@/components/ui/tooltip";
|
||||||
|
import {
|
||||||
|
DropdownMenu,
|
||||||
|
DropdownMenuContent,
|
||||||
|
DropdownMenuItem,
|
||||||
|
DropdownMenuTrigger,
|
||||||
|
} from "@/components/ui/dropdown-menu";
|
||||||
|
import { MoreVertical } from "lucide-react";
|
||||||
|
|
||||||
|
export const PromptCard = ({
|
||||||
|
prompt,
|
||||||
|
editingPromptId,
|
||||||
|
setEditingPromptId,
|
||||||
|
handleSave,
|
||||||
|
handleDelete,
|
||||||
|
isPromptPublic,
|
||||||
|
handleEdit,
|
||||||
|
fetchInputPrompts,
|
||||||
|
}: {
|
||||||
|
prompt: InputPrompt;
|
||||||
|
editingPromptId: number | null;
|
||||||
|
setEditingPromptId: (id: number | null) => void;
|
||||||
|
handleSave: (id: number, prompt: string, content: string) => void;
|
||||||
|
handleDelete: (id: number) => void;
|
||||||
|
isPromptPublic: (prompt: InputPrompt) => boolean;
|
||||||
|
handleEdit: (id: number) => void;
|
||||||
|
fetchInputPrompts: () => void;
|
||||||
|
}) => {
|
||||||
|
const isEditing = editingPromptId === prompt.id;
|
||||||
|
const [localPrompt, setLocalPrompt] = useState(prompt.prompt);
|
||||||
|
const [localContent, setLocalContent] = useState(prompt.content);
|
||||||
|
|
||||||
|
// Sync local edits with any prompt changes from outside
|
||||||
|
useEffect(() => {
|
||||||
|
setLocalPrompt(prompt.prompt);
|
||||||
|
setLocalContent(prompt.content);
|
||||||
|
}, [prompt, isEditing]);
|
||||||
|
|
||||||
|
const handleLocalEdit = (field: "prompt" | "content", value: string) => {
|
||||||
|
if (field === "prompt") {
|
||||||
|
setLocalPrompt(value);
|
||||||
|
} else {
|
||||||
|
setLocalContent(value);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleSaveLocal = () => {
|
||||||
|
handleSave(prompt.id, localPrompt, localContent);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="border dark:border-none dark:bg-[#333333] rounded-lg p-4 mb-4 relative">
|
||||||
|
{isEditing ? (
|
||||||
|
<>
|
||||||
|
<div className="absolute top-2 right-2">
|
||||||
|
<Button
|
||||||
|
variant="ghost"
|
||||||
|
size="sm"
|
||||||
|
onClick={() => {
|
||||||
|
setEditingPromptId(null);
|
||||||
|
fetchInputPrompts(); // Revert changes from server
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<XIcon size={14} />
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
<div className="flex">
|
||||||
|
<div className="flex-grow mr-4">
|
||||||
|
<Textarea
|
||||||
|
value={localPrompt}
|
||||||
|
onChange={(e) => handleLocalEdit("prompt", e.target.value)}
|
||||||
|
className="mb-2 resize-none"
|
||||||
|
placeholder="Prompt"
|
||||||
|
/>
|
||||||
|
<Textarea
|
||||||
|
value={localContent}
|
||||||
|
onChange={(e) => handleLocalEdit("content", e.target.value)}
|
||||||
|
className="resize-vertical min-h-[100px]"
|
||||||
|
placeholder="Content"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="flex items-end">
|
||||||
|
<Button onClick={handleSaveLocal}>
|
||||||
|
{prompt.id ? "Save" : "Create"}
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
<>
|
||||||
|
<TooltipProvider>
|
||||||
|
<Tooltip>
|
||||||
|
<TooltipTrigger asChild>
|
||||||
|
<div className="mb-2 flex gap-x-2 ">
|
||||||
|
<p className="font-semibold">{prompt.prompt}</p>
|
||||||
|
{isPromptPublic(prompt) && <SourceChip title="Built-in" />}
|
||||||
|
</div>
|
||||||
|
</TooltipTrigger>
|
||||||
|
{isPromptPublic(prompt) && (
|
||||||
|
<TooltipContent>
|
||||||
|
<p>This is a built-in prompt and cannot be edited</p>
|
||||||
|
</TooltipContent>
|
||||||
|
)}
|
||||||
|
</Tooltip>
|
||||||
|
</TooltipProvider>
|
||||||
|
<div className="whitespace-pre-wrap">{prompt.content}</div>
|
||||||
|
<div className="absolute top-2 right-2">
|
||||||
|
<DropdownMenu>
|
||||||
|
<DropdownMenuTrigger className="hover:bg-transparent" asChild>
|
||||||
|
<Button
|
||||||
|
className="!hover:bg-transparent"
|
||||||
|
variant="ghost"
|
||||||
|
size="sm"
|
||||||
|
>
|
||||||
|
<MoreVertical size={14} />
|
||||||
|
</Button>
|
||||||
|
</DropdownMenuTrigger>
|
||||||
|
<DropdownMenuContent>
|
||||||
|
{!isPromptPublic(prompt) && (
|
||||||
|
<DropdownMenuItem onClick={() => handleEdit(prompt.id)}>
|
||||||
|
Edit
|
||||||
|
</DropdownMenuItem>
|
||||||
|
)}
|
||||||
|
<DropdownMenuItem onClick={() => handleDelete(prompt.id)}>
|
||||||
|
Delete
|
||||||
|
</DropdownMenuItem>
|
||||||
|
</DropdownMenuContent>
|
||||||
|
</DropdownMenu>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
@@ -154,7 +154,6 @@ export const SourceChip = ({
|
|||||||
gap-x-1
|
gap-x-1
|
||||||
h-6
|
h-6
|
||||||
${onClick ? "cursor-pointer" : ""}
|
${onClick ? "cursor-pointer" : ""}
|
||||||
animate-fade-in-scale
|
|
||||||
`}
|
`}
|
||||||
>
|
>
|
||||||
{icon}
|
{icon}
|
||||||
|
@@ -40,8 +40,13 @@ export function UserSettingsModal({
|
|||||||
onClose: () => void;
|
onClose: () => void;
|
||||||
defaultModel: string | null;
|
defaultModel: string | null;
|
||||||
}) {
|
}) {
|
||||||
const { refreshUser, user, updateUserAutoScroll, updateUserShortcuts } =
|
const {
|
||||||
useUser();
|
refreshUser,
|
||||||
|
user,
|
||||||
|
updateUserAutoScroll,
|
||||||
|
updateUserShortcuts,
|
||||||
|
updateUserTemperatureOverrideEnabled,
|
||||||
|
} = useUser();
|
||||||
const containerRef = useRef<HTMLDivElement>(null);
|
const containerRef = useRef<HTMLDivElement>(null);
|
||||||
const messageRef = useRef<HTMLDivElement>(null);
|
const messageRef = useRef<HTMLDivElement>(null);
|
||||||
const { theme, setTheme } = useTheme();
|
const { theme, setTheme } = useTheme();
|
||||||
@@ -156,11 +161,6 @@ export function UserSettingsModal({
|
|||||||
const settings = useContext(SettingsContext);
|
const settings = useContext(SettingsContext);
|
||||||
const autoScroll = settings?.settings?.auto_scroll;
|
const autoScroll = settings?.settings?.auto_scroll;
|
||||||
|
|
||||||
const checked =
|
|
||||||
user?.preferences?.auto_scroll === null
|
|
||||||
? autoScroll
|
|
||||||
: user?.preferences?.auto_scroll;
|
|
||||||
|
|
||||||
const handleChangePassword = async (e: React.FormEvent) => {
|
const handleChangePassword = async (e: React.FormEvent) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
if (newPassword !== confirmPassword) {
|
if (newPassword !== confirmPassword) {
|
||||||
@@ -288,12 +288,26 @@ export function UserSettingsModal({
|
|||||||
<SubLabel>Automatically scroll to new content</SubLabel>
|
<SubLabel>Automatically scroll to new content</SubLabel>
|
||||||
</div>
|
</div>
|
||||||
<Switch
|
<Switch
|
||||||
checked={checked}
|
checked={user?.preferences.auto_scroll}
|
||||||
onCheckedChange={(checked) => {
|
onCheckedChange={(checked) => {
|
||||||
updateUserAutoScroll(checked);
|
updateUserAutoScroll(checked);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
<div className="flex items-center justify-between">
|
||||||
|
<div>
|
||||||
|
<h3 className="text-lg font-medium">
|
||||||
|
Temperature override
|
||||||
|
</h3>
|
||||||
|
<SubLabel>Set the temperature for the LLM</SubLabel>
|
||||||
|
</div>
|
||||||
|
<Switch
|
||||||
|
checked={user?.preferences.temperature_override_enabled}
|
||||||
|
onCheckedChange={(checked) => {
|
||||||
|
updateUserTemperatureOverrideEnabled(checked);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
<div className="flex items-center justify-between">
|
<div className="flex items-center justify-between">
|
||||||
<div>
|
<div>
|
||||||
<h3 className="text-lg font-medium">Prompt Shortcuts</h3>
|
<h3 className="text-lg font-medium">Prompt Shortcuts</h3>
|
||||||
|
@@ -13,7 +13,7 @@ interface UserContextType {
|
|||||||
isCurator: boolean;
|
isCurator: boolean;
|
||||||
refreshUser: () => Promise<void>;
|
refreshUser: () => Promise<void>;
|
||||||
isCloudSuperuser: boolean;
|
isCloudSuperuser: boolean;
|
||||||
updateUserAutoScroll: (autoScroll: boolean | null) => Promise<void>;
|
updateUserAutoScroll: (autoScroll: boolean) => Promise<void>;
|
||||||
updateUserShortcuts: (enabled: boolean) => Promise<void>;
|
updateUserShortcuts: (enabled: boolean) => Promise<void>;
|
||||||
toggleAssistantPinnedStatus: (
|
toggleAssistantPinnedStatus: (
|
||||||
currentPinnedAssistantIDs: number[],
|
currentPinnedAssistantIDs: number[],
|
||||||
@@ -163,7 +163,7 @@ export function UserProvider({
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const updateUserAutoScroll = async (autoScroll: boolean | null) => {
|
const updateUserAutoScroll = async (autoScroll: boolean) => {
|
||||||
try {
|
try {
|
||||||
const response = await fetch("/api/auto-scroll", {
|
const response = await fetch("/api/auto-scroll", {
|
||||||
method: "PATCH",
|
method: "PATCH",
|
||||||
|
@@ -10,7 +10,7 @@ interface UserPreferences {
|
|||||||
pinned_assistants?: number[];
|
pinned_assistants?: number[];
|
||||||
default_model: string | null;
|
default_model: string | null;
|
||||||
recent_assistants: number[];
|
recent_assistants: number[];
|
||||||
auto_scroll: boolean | null;
|
auto_scroll: boolean;
|
||||||
shortcut_enabled: boolean;
|
shortcut_enabled: boolean;
|
||||||
temperature_override_enabled: boolean;
|
temperature_override_enabled: boolean;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user