LlamaFinetuneGGUF commited on
Commit
75ec49b
·
unverified ·
2 Parent(s): d4400a5 bbd9a17

feat: providers list is now 2 columns

Browse files

The providers list in the settings modal is now 2 columns allowing you to see more at once.

app/components/settings/providers/ProvidersTab.tsx CHANGED
@@ -34,9 +34,87 @@ export default function ProvidersTab() {
34
 
35
  newFilteredProviders.sort((a, b) => a.name.localeCompare(b.name));
36
 
37
- setFilteredProviders(newFilteredProviders);
 
 
 
 
38
  }, [providers, searchTerm, isLocalModel]);
39
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
40
  return (
41
  <div className="p-4">
42
  <div className="flex mb-4">
@@ -48,77 +126,24 @@ export default function ProvidersTab() {
48
  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"
49
  />
50
  </div>
51
- {filteredProviders.map((provider) => {
52
- const envBaseUrlKey = providerBaseUrlEnvKeys[provider.name].baseUrlKey;
53
- const envBaseUrl = envBaseUrlKey ? import.meta.env[envBaseUrlKey] : undefined;
54
-
55
- return (
56
- <div
57
- key={provider.name}
58
- className="flex flex-col mb-2 provider-item hover:bg-bolt-elements-bg-depth-3 p-4 rounded-lg border border-bolt-elements-borderColor "
59
- >
60
- <div className="flex items-center justify-between mb-2">
61
- <div className="flex items-center gap-2">
62
- <img
63
- src={`/icons/${provider.name}.svg`} // Attempt to load the specific icon
64
- onError={(e) => {
65
- // Fallback to default icon on error
66
- e.currentTarget.src = DefaultIcon;
67
- }}
68
- alt={`${provider.name} icon`}
69
- className="w-6 h-6 dark:invert"
70
- />
71
- <span className="text-bolt-elements-textPrimary">{provider.name}</span>
72
- </div>
73
- <Switch
74
- className="ml-auto"
75
- checked={provider.settings.enabled}
76
- onCheckedChange={(enabled) => {
77
- updateProviderSettings(provider.name, { ...provider.settings, enabled });
78
-
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
- />
86
- </div>
87
- {/* Base URL input for configurable providers */}
88
- {URL_CONFIGURABLE_PROVIDERS.includes(provider.name) && provider.settings.enabled && (
89
- <div className="mt-2">
90
- {envBaseUrl && (
91
- <label className="block text-xs text-bolt-elements-textSecondary text-green-300 mb-2">
92
- Set On (.env) : {envBaseUrl}
93
- </label>
94
- )}
95
- <label className="block text-sm text-bolt-elements-textSecondary mb-2">
96
- {envBaseUrl ? 'Override Base Url' : 'Base URL '}:{' '}
97
- </label>
98
- <input
99
- type="text"
100
- value={provider.settings.baseUrl || ''}
101
- onChange={(e) => {
102
- let newBaseUrl: string | undefined = e.target.value;
103
-
104
- if (newBaseUrl && newBaseUrl.trim().length === 0) {
105
- newBaseUrl = undefined;
106
- }
107
-
108
- updateProviderSettings(provider.name, { ...provider.settings, baseUrl: newBaseUrl });
109
- logStore.logProvider(`Base URL updated for ${provider.name}`, {
110
- provider: provider.name,
111
- baseUrl: newBaseUrl,
112
- });
113
- }}
114
- placeholder={`Enter ${provider.name} base URL`}
115
- 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"
116
- />
117
- </div>
118
- )}
119
  </div>
120
- );
121
- })}
122
  </div>
123
  );
124
- }
 
34
 
35
  newFilteredProviders.sort((a, b) => a.name.localeCompare(b.name));
36
 
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));
40
+
41
+ setFilteredProviders([...regular, ...urlConfigurable]);
42
  }, [providers, searchTerm, isLocalModel]);
43
 
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
+ }
77
+ }}
78
+ />
79
+ </div>
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
+ )}
111
+ </div>
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));
117
+
118
  return (
119
  <div className="p-4">
120
  <div className="flex mb-4">
 
126
  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"
127
  />
128
  </div>
129
+
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-2 text-bolt-elements-textPrimary">Experimental Providers</h3>
139
+ <p className="text-sm text-bolt-elements-textSecondary mb-4">
140
+ These providers are experimental and allow you to run AI models locally or connect to your own infrastructure. They require additional setup but offer more flexibility.
141
+ </p>
142
+ <div className="space-y-4">
143
+ {urlConfigurableProviders.map(renderProviderCard)}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
144
  </div>
145
+ </div>
146
+ )}
147
  </div>
148
  );
149
+ }