@@ -5,7 +5,6 @@ import { toast } from 'react-toastify';
5
5
import { db , deleteById , getAll } from '~/lib/persistence' ;
6
6
import { logStore } from '~/lib/stores/logs' ;
7
7
import { classNames } from '~/utils/classNames' ;
8
- import styles from '~/components/settings/Settings.module.scss' ;
9
8
10
9
// List of supported providers that can have API keys
11
10
const API_KEY_PROVIDERS = [
@@ -25,8 +24,6 @@ const API_KEY_PROVIDERS = [
25
24
'AzureOpenAI' ,
26
25
] as const ;
27
26
28
- type Provider = typeof API_KEY_PROVIDERS [ number ] ;
29
-
30
27
interface ApiKeys {
31
28
[ key : string ] : string ;
32
29
}
@@ -52,6 +49,7 @@ export default function DataTab() {
52
49
const error = new Error ( 'Database is not available' ) ;
53
50
logStore . logError ( 'Failed to export chats - DB unavailable' , error ) ;
54
51
toast . error ( 'Database is not available' ) ;
52
+
55
53
return ;
56
54
}
57
55
@@ -83,11 +81,13 @@ export default function DataTab() {
83
81
const error = new Error ( 'Database is not available' ) ;
84
82
logStore . logError ( 'Failed to delete chats - DB unavailable' , error ) ;
85
83
toast . error ( 'Database is not available' ) ;
84
+
86
85
return ;
87
86
}
88
87
89
88
try {
90
89
setIsDeleting ( true ) ;
90
+
91
91
const allChats = await getAll ( db ) ;
92
92
await Promise . all ( allChats . map ( ( chat ) => deleteById ( db ! , chat . id ) ) ) ;
93
93
logStore . logSystem ( 'All chats deleted successfully' , { count : allChats . length } ) ;
@@ -125,16 +125,22 @@ export default function DataTab() {
125
125
126
126
const handleImportSettings = ( event : React . ChangeEvent < HTMLInputElement > ) => {
127
127
const file = event . target . files ?. [ 0 ] ;
128
- if ( ! file ) return ;
128
+
129
+ if ( ! file ) {
130
+ return ;
131
+ }
129
132
130
133
const reader = new FileReader ( ) ;
134
+
131
135
reader . onload = ( e ) => {
132
136
try {
133
137
const settings = JSON . parse ( e . target ?. result as string ) ;
134
-
138
+
135
139
Object . entries ( settings ) . forEach ( ( [ key , value ] ) => {
136
140
if ( key === 'bolt_theme' ) {
137
- if ( value ) localStorage . setItem ( key , value as string ) ;
141
+ if ( value ) {
142
+ localStorage . setItem ( key , value as string ) ;
143
+ }
138
144
} else if ( value ) {
139
145
Cookies . set ( key , value as string ) ;
140
146
}
@@ -152,32 +158,37 @@ export default function DataTab() {
152
158
153
159
const handleExportApiKeyTemplate = ( ) => {
154
160
const template : ApiKeys = { } ;
155
- API_KEY_PROVIDERS . forEach ( provider => {
161
+ API_KEY_PROVIDERS . forEach ( ( provider ) => {
156
162
template [ `${ provider } _API_KEY` ] = '' ;
157
163
} ) ;
158
164
159
- template [ ' OPENAI_LIKE_API_BASE_URL' ] = '' ;
160
- template [ ' LMSTUDIO_API_BASE_URL' ] = '' ;
161
- template [ ' OLLAMA_API_BASE_URL' ] = '' ;
162
- template [ ' TOGETHER_API_BASE_URL' ] = '' ;
165
+ template . OPENAI_LIKE_API_BASE_URL = '' ;
166
+ template . LMSTUDIO_API_BASE_URL = '' ;
167
+ template . OLLAMA_API_BASE_URL = '' ;
168
+ template . TOGETHER_API_BASE_URL = '' ;
163
169
164
170
downloadAsJson ( template , 'api-keys-template.json' ) ;
165
171
toast . success ( 'API keys template exported successfully' ) ;
166
172
} ;
167
173
168
174
const handleImportApiKeys = ( event : React . ChangeEvent < HTMLInputElement > ) => {
169
175
const file = event . target . files ?. [ 0 ] ;
170
- if ( ! file ) return ;
176
+
177
+ if ( ! file ) {
178
+ return ;
179
+ }
171
180
172
181
const reader = new FileReader ( ) ;
182
+
173
183
reader . onload = ( e ) => {
174
184
try {
175
185
const apiKeys = JSON . parse ( e . target ?. result as string ) ;
176
186
let importedCount = 0 ;
177
187
const consolidatedKeys : Record < string , string > = { } ;
178
188
179
- API_KEY_PROVIDERS . forEach ( provider => {
189
+ API_KEY_PROVIDERS . forEach ( ( provider ) => {
180
190
const keyName = `${ provider } _API_KEY` ;
191
+
181
192
if ( apiKeys [ keyName ] ) {
182
193
consolidatedKeys [ provider ] = apiKeys [ keyName ] ;
183
194
importedCount ++ ;
@@ -187,13 +198,14 @@ export default function DataTab() {
187
198
if ( importedCount > 0 ) {
188
199
// Store all API keys in a single cookie as JSON
189
200
Cookies . set ( 'apiKeys' , JSON . stringify ( consolidatedKeys ) ) ;
190
-
201
+
191
202
// Also set individual cookies for backward compatibility
192
203
Object . entries ( consolidatedKeys ) . forEach ( ( [ provider , key ] ) => {
193
204
Cookies . set ( `${ provider } _API_KEY` , key ) ;
194
205
} ) ;
195
206
196
207
toast . success ( `Successfully imported ${ importedCount } API keys/URLs. Refreshing page to apply changes...` ) ;
208
+
197
209
// Reload the page after a short delay to allow the toast to be seen
198
210
setTimeout ( ( ) => {
199
211
window . location . reload ( ) ;
@@ -203,12 +215,13 @@ export default function DataTab() {
203
215
}
204
216
205
217
// Set base URLs if they exist
206
- [ 'OPENAI_LIKE_API_BASE_URL' , 'LMSTUDIO_API_BASE_URL' , 'OLLAMA_API_BASE_URL' , 'TOGETHER_API_BASE_URL' ] . forEach ( baseUrl => {
207
- if ( apiKeys [ baseUrl ] ) {
208
- Cookies . set ( baseUrl , apiKeys [ baseUrl ] ) ;
209
- }
210
- } ) ;
211
-
218
+ [ 'OPENAI_LIKE_API_BASE_URL' , 'LMSTUDIO_API_BASE_URL' , 'OLLAMA_API_BASE_URL' , 'TOGETHER_API_BASE_URL' ] . forEach (
219
+ ( baseUrl ) => {
220
+ if ( apiKeys [ baseUrl ] ) {
221
+ Cookies . set ( baseUrl , apiKeys [ baseUrl ] ) ;
222
+ }
223
+ } ,
224
+ ) ;
212
225
} catch ( error ) {
213
226
toast . error ( 'Failed to import API keys. Make sure the file is a valid JSON file.' ) ;
214
227
console . error ( 'Failed to import API keys:' , error ) ;
@@ -226,9 +239,7 @@ export default function DataTab() {
226
239
< div className = "flex flex-col gap-4" >
227
240
< div >
228
241
< h4 className = "text-bolt-elements-textPrimary mb-2" > Chat History</ h4 >
229
- < p className = "text-sm text-bolt-elements-textSecondary mb-4" >
230
- Export or delete all your chat history.
231
- </ p >
242
+ < p className = "text-sm text-bolt-elements-textSecondary mb-4" > Export or delete all your chat history.</ p >
232
243
< div className = "flex gap-4" >
233
244
< button
234
245
onClick = { handleExportAllChats }
@@ -241,7 +252,7 @@ export default function DataTab() {
241
252
disabled = { isDeleting }
242
253
className = { classNames (
243
254
'px-4 py-2 bg-bolt-elements-button-danger-background hover:bg-bolt-elements-button-danger-backgroundHover text-bolt-elements-button-danger-text rounded-lg transition-colors' ,
244
- isDeleting ? 'opacity-50 cursor-not-allowed' : ''
255
+ isDeleting ? 'opacity-50 cursor-not-allowed' : '' ,
245
256
) }
246
257
>
247
258
{ isDeleting ? 'Deleting...' : 'Delete All Chats' }
@@ -263,12 +274,7 @@ export default function DataTab() {
263
274
</ button >
264
275
< label className = "px-4 py-2 bg-bolt-elements-button-primary-background hover:bg-bolt-elements-button-primary-backgroundHover text-bolt-elements-textPrimary rounded-lg transition-colors cursor-pointer" >
265
276
Import Settings
266
- < input
267
- type = "file"
268
- accept = ".json"
269
- onChange = { handleImportSettings }
270
- className = "hidden"
271
- />
277
+ < input type = "file" accept = ".json" onChange = { handleImportSettings } className = "hidden" />
272
278
</ label >
273
279
</ div >
274
280
</ div >
@@ -287,12 +293,7 @@ export default function DataTab() {
287
293
</ button >
288
294
< label className = "px-4 py-2 bg-bolt-elements-button-primary-background hover:bg-bolt-elements-button-primary-backgroundHover text-bolt-elements-textPrimary rounded-lg transition-colors cursor-pointer" >
289
295
Import API Keys
290
- < input
291
- type = "file"
292
- accept = ".json"
293
- onChange = { handleImportApiKeys }
294
- className = "hidden"
295
- />
296
+ < input type = "file" accept = ".json" onChange = { handleImportApiKeys } className = "hidden" />
296
297
</ label >
297
298
</ div >
298
299
</ div >
@@ -301,4 +302,4 @@ export default function DataTab() {
301
302
</ div >
302
303
</ div >
303
304
) ;
304
- }
305
+ }
0 commit comments