chore(UI): ux model settings (#64)
This commit is contained in:
3
resources/icons/icon-plain.svg
Normal file
3
resources/icons/icon-plain.svg
Normal file
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 9.0 KiB |
@@ -21,7 +21,6 @@ import { Label } from '@/components/ui/label';
|
|||||||
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card';
|
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card';
|
||||||
import { Badge } from '@/components/ui/badge';
|
import { Badge } from '@/components/ui/badge';
|
||||||
import { Separator } from '@/components/ui/separator';
|
import { Separator } from '@/components/ui/separator';
|
||||||
import { Switch } from '@/components/ui/switch';
|
|
||||||
import { useProviderStore, type ProviderConfig, type ProviderWithKeyInfo } from '@/stores/providers';
|
import { useProviderStore, type ProviderConfig, type ProviderWithKeyInfo } from '@/stores/providers';
|
||||||
import {
|
import {
|
||||||
PROVIDER_TYPE_INFO,
|
PROVIDER_TYPE_INFO,
|
||||||
@@ -41,7 +40,6 @@ export function ProvidersSettings() {
|
|||||||
loading,
|
loading,
|
||||||
fetchProviders,
|
fetchProviders,
|
||||||
addProvider,
|
addProvider,
|
||||||
updateProvider,
|
|
||||||
deleteProvider,
|
deleteProvider,
|
||||||
updateProviderWithKey,
|
updateProviderWithKey,
|
||||||
setDefaultProvider,
|
setDefaultProvider,
|
||||||
@@ -108,14 +106,6 @@ export function ProvidersSettings() {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleToggleEnabled = async (provider: ProviderWithKeyInfo) => {
|
|
||||||
try {
|
|
||||||
await updateProvider(provider.id, { enabled: !provider.enabled });
|
|
||||||
} catch (error) {
|
|
||||||
toast.error(`${t('aiProviders.toast.failedUpdate')}: ${error}`);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="space-y-4">
|
<div className="space-y-4">
|
||||||
<div className="flex justify-end">
|
<div className="flex justify-end">
|
||||||
@@ -155,7 +145,6 @@ export function ProvidersSettings() {
|
|||||||
onCancelEdit={() => setEditingProvider(null)}
|
onCancelEdit={() => setEditingProvider(null)}
|
||||||
onDelete={() => handleDeleteProvider(provider.id)}
|
onDelete={() => handleDeleteProvider(provider.id)}
|
||||||
onSetDefault={() => handleSetDefault(provider.id)}
|
onSetDefault={() => handleSetDefault(provider.id)}
|
||||||
onToggleEnabled={() => handleToggleEnabled(provider)}
|
|
||||||
onSaveEdits={async (payload) => {
|
onSaveEdits={async (payload) => {
|
||||||
await updateProviderWithKey(
|
await updateProviderWithKey(
|
||||||
provider.id,
|
provider.id,
|
||||||
@@ -191,7 +180,6 @@ interface ProviderCardProps {
|
|||||||
onCancelEdit: () => void;
|
onCancelEdit: () => void;
|
||||||
onDelete: () => void;
|
onDelete: () => void;
|
||||||
onSetDefault: () => void;
|
onSetDefault: () => void;
|
||||||
onToggleEnabled: () => void;
|
|
||||||
onSaveEdits: (payload: { newApiKey?: string; updates?: Partial<ProviderConfig> }) => Promise<void>;
|
onSaveEdits: (payload: { newApiKey?: string; updates?: Partial<ProviderConfig> }) => Promise<void>;
|
||||||
onValidateKey: (
|
onValidateKey: (
|
||||||
key: string,
|
key: string,
|
||||||
@@ -209,7 +197,6 @@ function ProviderCard({
|
|||||||
onCancelEdit,
|
onCancelEdit,
|
||||||
onDelete,
|
onDelete,
|
||||||
onSetDefault,
|
onSetDefault,
|
||||||
onToggleEnabled,
|
|
||||||
onSaveEdits,
|
onSaveEdits,
|
||||||
onValidateKey,
|
onValidateKey,
|
||||||
}: ProviderCardProps) {
|
}: ProviderCardProps) {
|
||||||
@@ -291,7 +278,7 @@ function ProviderCard({
|
|||||||
return (
|
return (
|
||||||
<Card className={cn(isDefault && 'ring-2 ring-primary')}>
|
<Card className={cn(isDefault && 'ring-2 ring-primary')}>
|
||||||
<CardContent className="p-4">
|
<CardContent className="p-4">
|
||||||
{/* Top row: icon + name + toggle */}
|
{/* Top row: icon + name */}
|
||||||
<div className="flex items-center justify-between mb-3">
|
<div className="flex items-center justify-between mb-3">
|
||||||
<div className="flex items-center gap-3">
|
<div className="flex items-center gap-3">
|
||||||
{getProviderIconUrl(provider.type) ? (
|
{getProviderIconUrl(provider.type) ? (
|
||||||
@@ -302,17 +289,10 @@ function ProviderCard({
|
|||||||
<div>
|
<div>
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
<span className="font-semibold">{provider.name}</span>
|
<span className="font-semibold">{provider.name}</span>
|
||||||
{isDefault && (
|
|
||||||
<Badge variant="default" className="text-xs">{t('aiProviders.card.default')}</Badge>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
<span className="text-xs text-muted-foreground capitalize">{provider.type}</span>
|
<span className="text-xs text-muted-foreground capitalize">{provider.type}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<Switch
|
|
||||||
checked={provider.enabled}
|
|
||||||
onCheckedChange={onToggleEnabled}
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Key row */}
|
{/* Key row */}
|
||||||
@@ -403,11 +383,23 @@ function ProviderCard({
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div className="flex gap-0.5 shrink-0 ml-2">
|
<div className="flex gap-0.5 shrink-0 ml-2">
|
||||||
{!isDefault && (
|
<Button
|
||||||
<Button variant="ghost" size="icon" className="h-7 w-7" onClick={onSetDefault} title={t('aiProviders.card.setDefault')}>
|
variant="ghost"
|
||||||
<Star className="h-3.5 w-3.5" />
|
size="icon"
|
||||||
</Button>
|
className="h-7 w-7"
|
||||||
)}
|
onClick={isDefault ? undefined : onSetDefault}
|
||||||
|
title={isDefault ? t('aiProviders.card.default') : t('aiProviders.card.setDefault')}
|
||||||
|
disabled={isDefault}
|
||||||
|
>
|
||||||
|
<Star
|
||||||
|
className={cn(
|
||||||
|
'h-3.5 w-3.5 transition-colors',
|
||||||
|
isDefault
|
||||||
|
? 'fill-yellow-400 text-yellow-400'
|
||||||
|
: 'text-muted-foreground'
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</Button>
|
||||||
<Button variant="ghost" size="icon" className="h-7 w-7" onClick={onEdit} title={t('aiProviders.card.editKey')}>
|
<Button variant="ghost" size="icon" className="h-7 w-7" onClick={onEdit} title={t('aiProviders.card.editKey')}>
|
||||||
<Edit className="h-3.5 w-3.5" />
|
<Edit className="h-3.5 w-3.5" />
|
||||||
</Button>
|
</Button>
|
||||||
|
|||||||
@@ -102,6 +102,7 @@ const defaultSkills: DefaultSkill[] = [
|
|||||||
];
|
];
|
||||||
|
|
||||||
import { SETUP_PROVIDERS, type ProviderTypeInfo, getProviderIconUrl, shouldInvertInDark } from '@/lib/providers';
|
import { SETUP_PROVIDERS, type ProviderTypeInfo, getProviderIconUrl, shouldInvertInDark } from '@/lib/providers';
|
||||||
|
import clawxIcon from '@/assets/logo.svg';
|
||||||
|
|
||||||
// Use the shared provider registry for setup providers
|
// Use the shared provider registry for setup providers
|
||||||
const providers = SETUP_PROVIDERS;
|
const providers = SETUP_PROVIDERS;
|
||||||
@@ -314,7 +315,9 @@ function WelcomeContent() {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="text-center space-y-4">
|
<div className="text-center space-y-4">
|
||||||
<div className="text-6xl mb-4">🤖</div>
|
<div className="mb-4 flex justify-center">
|
||||||
|
<img src={clawxIcon} alt="ClawX" className="h-16 w-16" />
|
||||||
|
</div>
|
||||||
<h2 className="text-xl font-semibold">{t('welcome.title')}</h2>
|
<h2 className="text-xl font-semibold">{t('welcome.title')}</h2>
|
||||||
<p className="text-muted-foreground">
|
<p className="text-muted-foreground">
|
||||||
{t('welcome.description')}
|
{t('welcome.description')}
|
||||||
|
|||||||
Reference in New Issue
Block a user