Skip to content

Commit a7551ec

Browse files
Update ProvidersTab.tsx
1 parent db769e0 commit a7551ec

File tree

1 file changed

+90
-138
lines changed

1 file changed

+90
-138
lines changed

app/components/settings/providers/ProvidersTab.tsx

Lines changed: 90 additions & 138 deletions
Original file line numberDiff line numberDiff line change
@@ -6,17 +6,14 @@ import type { IProviderConfig } from '~/types/model';
66
import { logStore } from '~/lib/stores/logs';
77

88
// Import a default fallback icon
9-
import DefaultIcon from '/icons/Default.svg';
10-
const ADVANCED_PROVIDERS = ['Ollama', 'OpenAILike', 'LMStudio'];
9+
import DefaultIcon from '/icons/Default.svg'; // Adjust the path as necessary
1110
import { providerBaseUrlEnvKeys } from '~/utils/constants';
1211

13-
1412
export default function ProvidersTab() {
1513
const { providers, updateProviderSettings, isLocalModel } = useSettings();
1614
const [filteredProviders, setFilteredProviders] = useState<IProviderConfig[]>([]);
17-
const [advancedProviders, setAdvancedProviders] = useState<IProviderConfig[]>([]);
18-
const [regularProviders, setRegularProviders] = useState<IProviderConfig[]>([]);
1915

16+
// Load base URLs from cookies
2017
const [searchTerm, setSearchTerm] = useState('');
2118

2219
useEffect(() => {
@@ -35,76 +32,88 @@ export default function ProvidersTab() {
3532
newFilteredProviders = newFilteredProviders.filter((provider) => !LOCAL_PROVIDERS.includes(provider.name));
3633
}
3734

38-
// Split providers into regular and advanced
39-
const regular = newFilteredProviders.filter(
40-
(provider) => !ADVANCED_PROVIDERS.includes(provider.name)
41-
);
42-
const advanced = newFilteredProviders.filter(
43-
(provider) => ADVANCED_PROVIDERS.includes(provider.name)
44-
);
45-
46-
// Sort advanced providers in specific order - OpenAILike at the end
47-
const advancedOrder = ['Ollama', 'LMStudio', 'OpenAILike'];
48-
advanced.sort((a, b) => {
49-
return advancedOrder.indexOf(a.name) - advancedOrder.indexOf(b.name);
50-
});
35+
newFilteredProviders.sort((a, b) => a.name.localeCompare(b.name));
5136

52-
// Sort regular providers alphabetically
53-
regular.sort((a, b) => a.name.localeCompare(b.name));
37+
// Split providers into regular and URL-configurable
38+
const regular = newFilteredProviders.filter(p => !URL_CONFIGURABLE_PROVIDERS.includes(p.name));
39+
const urlConfigurable = newFilteredProviders.filter(p => URL_CONFIGURABLE_PROVIDERS.includes(p.name));
5440

55-
setRegularProviders(regular);
56-
setAdvancedProviders(advanced);
57-
setFilteredProviders(newFilteredProviders);
41+
setFilteredProviders([...regular, ...urlConfigurable]);
5842
}, [providers, searchTerm, isLocalModel]);
5943

60-
const ProviderCard = ({ provider }: { provider: IProviderConfig }) => (
61-
<div className="flex flex-col provider-item hover:bg-bolt-elements-bg-depth-3 p-4 rounded-lg border border-bolt-elements-borderColor">
62-
<div className="flex items-center justify-between mb-2">
63-
<div className="flex items-center gap-2">
64-
<img
65-
src={`/icons/${provider.name}.svg`}
66-
onError={(e) => {
67-
e.currentTarget.src = DefaultIcon;
44+
const renderProviderCard = (provider: IProviderConfig) => {
45+
const envBaseUrlKey = providerBaseUrlEnvKeys[provider.name].baseUrlKey;
46+
const envBaseUrl = envBaseUrlKey ? import.meta.env[envBaseUrlKey] : undefined;
47+
const isUrlConfigurable = URL_CONFIGURABLE_PROVIDERS.includes(provider.name);
48+
49+
return (
50+
<div
51+
key={provider.name}
52+
className="flex flex-col provider-item hover:bg-bolt-elements-bg-depth-3 p-4 rounded-lg border border-bolt-elements-borderColor"
53+
>
54+
<div className="flex items-center justify-between mb-2">
55+
<div className="flex items-center gap-2">
56+
<img
57+
src={`/icons/${provider.name}.svg`}
58+
onError={(e) => {
59+
e.currentTarget.src = DefaultIcon;
60+
}}
61+
alt={`${provider.name} icon`}
62+
className="w-6 h-6 dark:invert"
63+
/>
64+
<span className="text-bolt-elements-textPrimary">{provider.name}</span>
65+
</div>
66+
<Switch
67+
className="ml-auto"
68+
checked={provider.settings.enabled}
69+
onCheckedChange={(enabled) => {
70+
updateProviderSettings(provider.name, { ...provider.settings, enabled });
71+
72+
if (enabled) {
73+
logStore.logProvider(`Provider ${provider.name} enabled`, { provider: provider.name });
74+
} else {
75+
logStore.logProvider(`Provider ${provider.name} disabled`, { provider: provider.name });
76+
}
6877
}}
69-
alt={`${provider.name} icon`}
70-
className="w-6 h-6 dark:invert"
7178
/>
72-
<span className="text-bolt-elements-textPrimary">{provider.name}</span>
7379
</div>
74-
<Switch
75-
className="ml-auto"
76-
checked={provider.settings.enabled}
77-
onCheckedChange={(enabled) => {
78-
updateProviderSettings(provider.name, { ...provider.settings, enabled });
79-
if (enabled) {
80-
logStore.logProvider(`Provider ${provider.name} enabled`, { provider: provider.name });
81-
} else {
82-
logStore.logProvider(`Provider ${provider.name} disabled`, { provider: provider.name });
83-
}
84-
}}
85-
/>
80+
{isUrlConfigurable && provider.settings.enabled && (
81+
<div className="mt-2">
82+
{envBaseUrl && (
83+
<label className="block text-xs text-bolt-elements-textSecondary text-green-300 mb-2">
84+
Set On (.env) : {envBaseUrl}
85+
</label>
86+
)}
87+
<label className="block text-sm text-bolt-elements-textSecondary mb-2">
88+
{envBaseUrl ? 'Override Base Url' : 'Base URL '}:{' '}
89+
</label>
90+
<input
91+
type="text"
92+
value={provider.settings.baseUrl || ''}
93+
onChange={(e) => {
94+
let newBaseUrl: string | undefined = e.target.value;
95+
96+
if (newBaseUrl && newBaseUrl.trim().length === 0) {
97+
newBaseUrl = undefined;
98+
}
99+
100+
updateProviderSettings(provider.name, { ...provider.settings, baseUrl: newBaseUrl });
101+
logStore.logProvider(`Base URL updated for ${provider.name}`, {
102+
provider: provider.name,
103+
baseUrl: newBaseUrl,
104+
});
105+
}}
106+
placeholder={`Enter ${provider.name} base URL`}
107+
className="w-full bg-white dark:bg-bolt-elements-background-depth-4 relative px-2 py-1.5 rounded-md focus:outline-none placeholder-bolt-elements-textTertiary text-bolt-elements-textPrimary dark:text-bolt-elements-textPrimary border border-bolt-elements-borderColor"
108+
/>
109+
</div>
110+
)}
86111
</div>
87-
{URL_CONFIGURABLE_PROVIDERS.includes(provider.name) && provider.settings.enabled && (
88-
<div className="mt-2">
89-
<label className="block text-sm text-bolt-elements-textSecondary mb-1">Base URL:</label>
90-
<input
91-
type="text"
92-
value={provider.settings.baseUrl || ''}
93-
onChange={(e) => {
94-
const newBaseUrl = e.target.value;
95-
updateProviderSettings(provider.name, { ...provider.settings, baseUrl: newBaseUrl });
96-
logStore.logProvider(`Base URL updated for ${provider.name}`, {
97-
provider: provider.name,
98-
baseUrl: newBaseUrl,
99-
});
100-
}}
101-
placeholder={`Enter ${provider.name} base URL`}
102-
className="w-full bg-white dark:bg-bolt-elements-background-depth-4 relative px-2 py-1.5 rounded-md focus:outline-none placeholder-bolt-elements-textTertiary text-bolt-elements-textPrimary dark:text-bolt-elements-textPrimary border border-bolt-elements-borderColor"
103-
/>
104-
</div>
105-
)}
106-
</div>
107-
);
112+
);
113+
};
114+
115+
const regularProviders = filteredProviders.filter(p => !URL_CONFIGURABLE_PROVIDERS.includes(p.name));
116+
const urlConfigurableProviders = filteredProviders.filter(p => URL_CONFIGURABLE_PROVIDERS.includes(p.name));
108117

109118
return (
110119
<div className="p-4">
@@ -118,77 +127,20 @@ export default function ProvidersTab() {
118127
/>
119128
</div>
120129

121-
{filteredProviders.map((provider) => {
122-
const envBaseUrlKey = providerBaseUrlEnvKeys[provider.name].baseUrlKey;
123-
const envBaseUrl = envBaseUrlKey ? import.meta.env[envBaseUrlKey] : undefined;
124-
125-
return (
126-
<div
127-
key={provider.name}
128-
className="flex flex-col mb-2 provider-item hover:bg-bolt-elements-bg-depth-3 p-4 rounded-lg border border-bolt-elements-borderColor "
129-
>
130-
<div className="flex items-center justify-between mb-2">
131-
<div className="flex items-center gap-2">
132-
<img
133-
src={`/icons/${provider.name}.svg`} // Attempt to load the specific icon
134-
onError={(e) => {
135-
// Fallback to default icon on error
136-
e.currentTarget.src = DefaultIcon;
137-
}}
138-
alt={`${provider.name} icon`}
139-
className="w-6 h-6 dark:invert"
140-
/>
141-
<span className="text-bolt-elements-textPrimary">{provider.name}</span>
142-
</div>
143-
<Switch
144-
className="ml-auto"
145-
checked={provider.settings.enabled}
146-
onCheckedChange={(enabled) => {
147-
updateProviderSettings(provider.name, { ...provider.settings, enabled });
148-
149-
if (enabled) {
150-
logStore.logProvider(`Provider ${provider.name} enabled`, { provider: provider.name });
151-
} else {
152-
logStore.logProvider(`Provider ${provider.name} disabled`, { provider: provider.name });
153-
}
154-
}}
155-
/>
156-
</div>
157-
{/* Base URL input for configurable providers */}
158-
{URL_CONFIGURABLE_PROVIDERS.includes(provider.name) && provider.settings.enabled && (
159-
<div className="mt-2">
160-
{envBaseUrl && (
161-
<label className="block text-xs text-bolt-elements-textSecondary text-green-300 mb-2">
162-
Set On (.env) : {envBaseUrl}
163-
</label>
164-
)}
165-
<label className="block text-sm text-bolt-elements-textSecondary mb-2">
166-
{envBaseUrl ? 'Override Base Url' : 'Base URL '}:{' '}
167-
</label>
168-
<input
169-
type="text"
170-
value={provider.settings.baseUrl || ''}
171-
onChange={(e) => {
172-
let newBaseUrl: string | undefined = e.target.value;
173-
174-
if (newBaseUrl && newBaseUrl.trim().length === 0) {
175-
newBaseUrl = undefined;
176-
}
177-
178-
updateProviderSettings(provider.name, { ...provider.settings, baseUrl: newBaseUrl });
179-
logStore.logProvider(`Base URL updated for ${provider.name}`, {
180-
provider: provider.name,
181-
baseUrl: newBaseUrl,
182-
});
183-
}}
184-
placeholder={`Enter ${provider.name} base URL`}
185-
className="w-full bg-white dark:bg-bolt-elements-background-depth-4 relative px-2 py-1.5 rounded-md focus:outline-none placeholder-bolt-elements-textTertiary text-bolt-elements-textPrimary dark:text-bolt-elements-textPrimary border border-bolt-elements-borderColor"
186-
/>
187-
</div>
188-
)}
130+
{/* Regular Providers Grid */}
131+
<div className="grid grid-cols-2 gap-4 mb-8">
132+
{regularProviders.map(renderProviderCard)}
133+
</div>
134+
135+
{/* URL Configurable Providers Section */}
136+
{urlConfigurableProviders.length > 0 && (
137+
<div className="mt-8">
138+
<h3 className="text-lg font-semibold mb-4 text-bolt-elements-textPrimary">Providers with Custom Base URL</h3>
139+
<div className="space-y-4">
140+
{urlConfigurableProviders.map(renderProviderCard)}
189141
</div>
190-
);
191-
})}
142+
</div>
143+
)}
192144
</div>
193145
);
194-
}
146+
}

0 commit comments

Comments
 (0)