mirror of
https://github.com/MODSetter/SurfSense.git
synced 2026-05-17 18:35:19 +02:00
refactor: simplify alert descriptions, improved icons, improved UI in LLM settings
This commit is contained in:
parent
0925f89b7c
commit
42572ad09d
11 changed files with 28 additions and 117 deletions
|
|
@ -190,7 +190,7 @@ export function ImageModelManager({ searchSpaceId }: ImageModelManagerProps) {
|
|||
? "model"
|
||||
: "models"}
|
||||
</span>{" "}
|
||||
available from your administrator. Use the model selector to view and select them.
|
||||
available from your administrator.
|
||||
</p>
|
||||
</AlertDescription>
|
||||
</Alert>
|
||||
|
|
|
|||
|
|
@ -10,7 +10,6 @@ import {
|
|||
FileText,
|
||||
ImageIcon,
|
||||
RefreshCw,
|
||||
Shuffle,
|
||||
} from "lucide-react";
|
||||
import { useCallback, useEffect, useRef, useState } from "react";
|
||||
import { toast } from "sonner";
|
||||
|
|
@ -44,7 +43,6 @@ import {
|
|||
} from "@/components/ui/select";
|
||||
import { Skeleton } from "@/components/ui/skeleton";
|
||||
import { Spinner } from "@/components/ui/spinner";
|
||||
import { getProviderIcon } from "@/lib/provider-icons";
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
const ROLE_DESCRIPTIONS = {
|
||||
|
|
@ -79,8 +77,8 @@ const ROLE_DESCRIPTIONS = {
|
|||
icon: Eye,
|
||||
title: "Vision LLM",
|
||||
description: "Vision-capable model for screenshot analysis and context extraction",
|
||||
color: "text-amber-600 dark:text-amber-400",
|
||||
bgColor: "bg-amber-500/10",
|
||||
color: "text-muted-foreground",
|
||||
bgColor: "bg-muted",
|
||||
prefKey: "vision_llm_config_id" as const,
|
||||
configType: "vision" as const,
|
||||
},
|
||||
|
|
@ -205,11 +203,6 @@ export function LLMRoleManager({ searchSpaceId }: LLMRoleManagerProps) {
|
|||
),
|
||||
];
|
||||
|
||||
const isAssignmentComplete =
|
||||
allLLMConfigs.some((c) => c.id === assignments.agent_llm_id) &&
|
||||
allLLMConfigs.some((c) => c.id === assignments.document_summary_llm_id) &&
|
||||
allImageConfigs.some((c) => c.id === assignments.image_generation_config_id);
|
||||
|
||||
const isLoading =
|
||||
configsLoading ||
|
||||
preferencesLoading ||
|
||||
|
|
@ -231,7 +224,7 @@ export function LLMRoleManager({ searchSpaceId }: LLMRoleManagerProps) {
|
|||
return (
|
||||
<div className="space-y-5 md:space-y-6">
|
||||
{/* Header actions */}
|
||||
<div className="flex items-center justify-between">
|
||||
<div className="flex items-center justify-start">
|
||||
<Button
|
||||
variant="secondary"
|
||||
size="sm"
|
||||
|
|
@ -239,15 +232,9 @@ export function LLMRoleManager({ searchSpaceId }: LLMRoleManagerProps) {
|
|||
disabled={isLoading}
|
||||
className="gap-2"
|
||||
>
|
||||
<RefreshCw className="h-3.5 w-3.5" />
|
||||
<RefreshCw className={cn("h-3.5 w-3.5", isLoading && "animate-spin")} />
|
||||
Refresh
|
||||
</Button>
|
||||
{isAssignmentComplete && !isLoading && !hasError && (
|
||||
<Badge variant="outline" className="text-xs gap-1.5 text-muted-foreground">
|
||||
<CircleCheck className="h-3 w-3" />
|
||||
All roles assigned
|
||||
</Badge>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Error Alert */}
|
||||
|
|
@ -343,8 +330,6 @@ export function LLMRoleManager({ searchSpaceId }: LLMRoleManagerProps) {
|
|||
|
||||
const assignedConfig = roleAllConfigs.find((config) => config.id === currentAssignment);
|
||||
const isAssigned = !!assignedConfig;
|
||||
const isAutoMode =
|
||||
assignedConfig && "is_auto_mode" in assignedConfig && assignedConfig.is_auto_mode;
|
||||
|
||||
return (
|
||||
<div key={key}>
|
||||
|
|
@ -389,7 +374,7 @@ export function LLMRoleManager({ searchSpaceId }: LLMRoleManagerProps) {
|
|||
<SelectTrigger className="w-full h-9 md:h-10 text-xs md:text-sm">
|
||||
<SelectValue placeholder="Select a configuration" />
|
||||
</SelectTrigger>
|
||||
<SelectContent className="max-w-[calc(100vw-2rem)]">
|
||||
<SelectContent className="max-w-[calc(100vw-2rem)] select-none">
|
||||
<SelectItem
|
||||
value="unassigned"
|
||||
className="text-xs md:text-sm py-1.5 md:py-2"
|
||||
|
|
@ -412,21 +397,9 @@ export function LLMRoleManager({ searchSpaceId }: LLMRoleManagerProps) {
|
|||
className="text-xs md:text-sm py-1.5 md:py-2"
|
||||
>
|
||||
<div className="flex items-center gap-1 md:gap-1.5 flex-wrap min-w-0">
|
||||
{isAuto ? (
|
||||
<Shuffle className="size-3 md:size-3.5 shrink-0 text-muted-foreground" />
|
||||
) : (
|
||||
getProviderIcon(config.provider, {
|
||||
className: "size-3 md:size-3.5 shrink-0",
|
||||
})
|
||||
)}
|
||||
<span className="truncate text-xs md:text-sm">
|
||||
{config.name}
|
||||
</span>
|
||||
{!isAuto && (
|
||||
<span className="text-muted-foreground text-[10px] md:text-[11px] truncate">
|
||||
({config.model_name})
|
||||
</span>
|
||||
)}
|
||||
{isAuto && (
|
||||
<Badge
|
||||
variant="secondary"
|
||||
|
|
@ -455,15 +428,9 @@ export function LLMRoleManager({ searchSpaceId }: LLMRoleManagerProps) {
|
|||
className="text-xs md:text-sm py-1.5 md:py-2"
|
||||
>
|
||||
<div className="flex items-center gap-1 md:gap-1.5 flex-wrap min-w-0">
|
||||
{getProviderIcon(config.provider, {
|
||||
className: "size-3 md:size-3.5 shrink-0",
|
||||
})}
|
||||
<span className="truncate text-xs md:text-sm">
|
||||
{config.name}
|
||||
</span>
|
||||
<span className="text-muted-foreground text-[10px] md:text-[11px] truncate">
|
||||
({config.model_name})
|
||||
</span>
|
||||
</div>
|
||||
</SelectItem>
|
||||
))}
|
||||
|
|
@ -473,62 +440,6 @@ export function LLMRoleManager({ searchSpaceId }: LLMRoleManagerProps) {
|
|||
</Select>
|
||||
</div>
|
||||
|
||||
{/* Assigned Config Summary */}
|
||||
{assignedConfig && (
|
||||
<div
|
||||
className={cn(
|
||||
"rounded-lg p-3 border",
|
||||
isAutoMode
|
||||
? "bg-violet-50 dark:bg-violet-900/10 border-violet-200/50 dark:border-violet-800/30"
|
||||
: "bg-muted/40 border-border/50"
|
||||
)}
|
||||
>
|
||||
{isAutoMode ? (
|
||||
<div className="flex items-center gap-2">
|
||||
<Shuffle
|
||||
className={cn(
|
||||
"w-3.5 h-3.5 shrink-0 text-violet-600 dark:text-violet-400"
|
||||
)}
|
||||
/>
|
||||
<div className="min-w-0">
|
||||
<p className="text-xs font-medium text-violet-700 dark:text-violet-300">
|
||||
Auto Mode
|
||||
</p>
|
||||
<p className="text-[10px] text-violet-600/70 dark:text-violet-400/70 mt-0.5">
|
||||
Routes across all available providers
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
) : (
|
||||
<div className="flex items-start gap-2">
|
||||
<IconComponent className="w-3.5 h-3.5 shrink-0 mt-0.5 text-muted-foreground" />
|
||||
<div className="min-w-0 flex-1">
|
||||
<div className="flex items-center gap-1.5 flex-wrap">
|
||||
<span className="text-xs font-medium">{assignedConfig.name}</span>
|
||||
{"is_global" in assignedConfig && assignedConfig.is_global && (
|
||||
<Badge variant="secondary" className="text-[9px] px-1.5 py-0">
|
||||
🌐 Global
|
||||
</Badge>
|
||||
)}
|
||||
</div>
|
||||
<div className="flex items-center gap-1.5 mt-1">
|
||||
{getProviderIcon(assignedConfig.provider, {
|
||||
className: "size-3 shrink-0",
|
||||
})}
|
||||
<code className="text-[10px] text-muted-foreground font-mono truncate">
|
||||
{assignedConfig.model_name}
|
||||
</code>
|
||||
</div>
|
||||
{assignedConfig.api_base && (
|
||||
<p className="text-[10px] text-muted-foreground/60 mt-1 truncate">
|
||||
{assignedConfig.api_base}
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -196,7 +196,7 @@ export function ModelConfigManager({ searchSpaceId }: ModelConfigManagerProps) {
|
|||
<span className="font-medium">
|
||||
{globalConfigs.length} global {globalConfigs.length === 1 ? "model" : "models"}
|
||||
</span>{" "}
|
||||
available from your administrator. Use the model selector to view and select them.
|
||||
available from your administrator.
|
||||
</p>
|
||||
</AlertDescription>
|
||||
</Alert>
|
||||
|
|
|
|||
|
|
@ -2,15 +2,15 @@
|
|||
|
||||
import { useAtom } from "jotai";
|
||||
import {
|
||||
BookMarked,
|
||||
Bot,
|
||||
BookText,
|
||||
Brain,
|
||||
CircleUser,
|
||||
Earth,
|
||||
Eye,
|
||||
FileText,
|
||||
Globe,
|
||||
ImageIcon,
|
||||
MessageSquare,
|
||||
Shield,
|
||||
ListChecks,
|
||||
UserKey
|
||||
} from "lucide-react";
|
||||
import dynamic from "next/dynamic";
|
||||
import { useTranslations } from "next-intl";
|
||||
|
|
@ -86,9 +86,9 @@ export function SearchSpaceSettingsDialog({ searchSpaceId }: SearchSpaceSettings
|
|||
const [state, setState] = useAtom(searchSpaceSettingsDialogAtom);
|
||||
|
||||
const navItems = [
|
||||
{ value: "general", label: t("nav_general"), icon: <FileText className="h-4 w-4" /> },
|
||||
{ value: "general", label: t("nav_general"), icon: <CircleUser className="h-4 w-4" /> },
|
||||
{ value: "roles", label: t("nav_role_assignments"), icon: <ListChecks className="h-4 w-4" /> },
|
||||
{ value: "models", label: t("nav_agent_configs"), icon: <Bot className="h-4 w-4" /> },
|
||||
{ value: "roles", label: t("nav_role_assignments"), icon: <Brain className="h-4 w-4" /> },
|
||||
{
|
||||
value: "image-models",
|
||||
label: t("nav_image_models"),
|
||||
|
|
@ -99,18 +99,18 @@ export function SearchSpaceSettingsDialog({ searchSpaceId }: SearchSpaceSettings
|
|||
label: t("nav_vision_models"),
|
||||
icon: <Eye className="h-4 w-4" />,
|
||||
},
|
||||
{ value: "team-roles", label: t("nav_team_roles"), icon: <Shield className="h-4 w-4" /> },
|
||||
{ value: "team-roles", label: t("nav_team_roles"), icon: <UserKey className="h-4 w-4" /> },
|
||||
{
|
||||
value: "prompts",
|
||||
label: t("nav_system_instructions"),
|
||||
icon: <MessageSquare className="h-4 w-4" />,
|
||||
icon: <BookText className="h-4 w-4" />,
|
||||
},
|
||||
{
|
||||
value: "team-memory",
|
||||
label: "Team Memory",
|
||||
icon: <BookMarked className="h-4 w-4" />,
|
||||
icon: <Brain className="h-4 w-4" />,
|
||||
},
|
||||
{ value: "public-links", label: t("nav_public_links"), icon: <Globe className="h-4 w-4" /> },
|
||||
{ value: "public-links", label: t("nav_public_links"), icon: <Earth className="h-4 w-4" /> },
|
||||
];
|
||||
|
||||
const content: Record<string, React.ReactNode> = {
|
||||
|
|
|
|||
|
|
@ -188,7 +188,7 @@ export function TeamMemoryManager({ searchSpaceId }: TeamMemoryManagerProps) {
|
|||
<AlertDescription className="text-xs md:text-sm">
|
||||
<p>
|
||||
SurfSense uses this shared memory to provide team-wide context across all conversations
|
||||
in this search space. Use the input below to add, update, or remove memory entries.
|
||||
in this search space.
|
||||
</p>
|
||||
</AlertDescription>
|
||||
</Alert>
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
"use client";
|
||||
|
||||
import { useAtom } from "jotai";
|
||||
import { Brain, Globe, KeyRound, Monitor, Receipt, Sparkles, User } from "lucide-react";
|
||||
import { Brain, CircleUser, Globe, KeyRound, Monitor, ReceiptText, Sparkles } from "lucide-react";
|
||||
import dynamic from "next/dynamic";
|
||||
import { useTranslations } from "next-intl";
|
||||
import { useMemo } from "react";
|
||||
|
|
@ -66,7 +66,7 @@ export function UserSettingsDialog() {
|
|||
|
||||
const navItems = useMemo(
|
||||
() => [
|
||||
{ value: "profile", label: t("profile_nav_label"), icon: <User className="h-4 w-4" /> },
|
||||
{ value: "profile", label: t("profile_nav_label"), icon: <CircleUser className="h-4 w-4" /> },
|
||||
{
|
||||
value: "api-key",
|
||||
label: t("api_key_nav_label"),
|
||||
|
|
@ -90,7 +90,7 @@ export function UserSettingsDialog() {
|
|||
{
|
||||
value: "purchases",
|
||||
label: "Purchase History",
|
||||
icon: <Receipt className="h-4 w-4" />,
|
||||
icon: <ReceiptText className="h-4 w-4" />,
|
||||
},
|
||||
...(isDesktop
|
||||
? [{ value: "desktop", label: "Desktop", icon: <Monitor className="h-4 w-4" /> }]
|
||||
|
|
|
|||
|
|
@ -191,7 +191,7 @@ export function VisionModelManager({ searchSpaceId }: VisionModelManagerProps) {
|
|||
? "model"
|
||||
: "models"}
|
||||
</span>{" "}
|
||||
available from your administrator. Use the model selector to view and select them.
|
||||
available from your administrator.
|
||||
</p>
|
||||
</AlertDescription>
|
||||
</Alert>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue