Skip to content

Commit c144d10

Browse files
author
Lasim
committed
feat(frontend): replace switches with checkboxes for settings
1 parent dfab0ed commit c144d10

File tree

14 files changed

+318
-202
lines changed

14 files changed

+318
-202
lines changed

package-lock.json

Lines changed: 12 additions & 12 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

services/backend/src/global-settings/index.ts

Lines changed: 48 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,18 @@ export class GlobalSettingsInitService {
129129
await this.createSettingsIndividually(allSettings, result);
130130
}
131131

132+
// Update existing settings with name field if missing
133+
try {
134+
await this.updateSettingsMetadata(allSettings);
135+
} catch (error) {
136+
if (logger) {
137+
logger.debug({
138+
operation: 'update_settings_metadata',
139+
error: error instanceof Error ? error.message : String(error)
140+
}, 'Failed to update settings metadata during initialization');
141+
}
142+
}
143+
132144
// Check for missing required settings
133145
try {
134146
await this.validateRequiredSettings();
@@ -316,7 +328,7 @@ export class GlobalSettingsInitService {
316328
for (const setting of allSettings) {
317329
try {
318330
const exists = await GlobalSettingsService.exists(setting.key);
319-
331+
320332
if (!exists) {
321333
const groupIdForThisSetting = this.getGroupIdForSetting(setting.key);
322334
await GlobalSettingsService.setTyped(setting.key, setting.defaultValue, setting.type, {
@@ -325,7 +337,7 @@ export class GlobalSettingsInitService {
325337
encrypted: setting.encrypted,
326338
group_id: groupIdForThisSetting === 'unknown' ? undefined : groupIdForThisSetting
327339
});
328-
340+
329341
result.created++;
330342
result.createdSettings.push(setting.key);
331343
} else {
@@ -338,6 +350,40 @@ export class GlobalSettingsInitService {
338350
}
339351
}
340352

353+
/**
354+
* Update existing settings with metadata (name) from definitions
355+
* This ensures settings created before the name field was added get updated
356+
*/
357+
private static async updateSettingsMetadata(allSettings: GlobalSettingDefinition[]): Promise<void> {
358+
const db = getDb();
359+
const schema = getSchema();
360+
361+
if (!db) {
362+
return;
363+
}
364+
365+
for (const setting of allSettings) {
366+
try {
367+
// Get the current setting from database
368+
const existingSetting = await GlobalSettingsService.get(setting.key);
369+
370+
// If setting exists but has no name, update it with the name from definition
371+
if (existingSetting && !existingSetting.name && setting.name) {
372+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
373+
await (db as any)
374+
.update(schema.globalSettings)
375+
.set({
376+
name: setting.name,
377+
updated_at: new Date()
378+
})
379+
.where(eq(schema.globalSettings.key, setting.key));
380+
}
381+
} catch {
382+
// Silently continue on error
383+
}
384+
}
385+
}
386+
341387
/**
342388
* Universal batch wrapper that works across all database types
343389
*/

services/backend/tests/unit/global-settings/github-app.test.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ describe('GitHub App Settings Module', () => {
111111
expect(setting.key).toBe('github.app.app_id')
112112
expect(setting.defaultValue).toBe('')
113113
expect(setting.type).toBe('string')
114-
expect(setting.description).toBe('GitHub App ID for API authentication')
114+
expect(setting.description).toBe('GitHub App ID used for API authentication.')
115115
expect(setting.encrypted).toBe(false)
116116
expect(setting.required).toBe(false)
117117
})
@@ -139,7 +139,7 @@ describe('GitHub App Settings Module', () => {
139139
expect(setting.key).toBe('github.app.private_key_base64')
140140
expect(setting.defaultValue).toBe('')
141141
expect(setting.type).toBe('string')
142-
expect(setting.description).toBe('GitHub App private key (base64 encoded)')
142+
expect(setting.description).toBe('GitHub App private key encoded in base64 format.')
143143
expect(setting.encrypted).toBe(true) // Should be encrypted for security
144144
expect(setting.required).toBe(false)
145145
})
@@ -170,7 +170,7 @@ describe('GitHub App Settings Module', () => {
170170
expect(setting.key).toBe('github.app.installation_id')
171171
expect(setting.defaultValue).toBe('')
172172
expect(setting.type).toBe('string')
173-
expect(setting.description).toBe('GitHub App installation ID')
173+
expect(setting.description).toBe('GitHub App installation ID for your organization or account.')
174174
expect(setting.encrypted).toBe(false)
175175
expect(setting.required).toBe(false)
176176
})
@@ -195,7 +195,7 @@ describe('GitHub App Settings Module', () => {
195195
expect(setting.key).toBe('github.app.enabled')
196196
expect(setting.defaultValue).toBe(false)
197197
expect(setting.type).toBe('boolean')
198-
expect(setting.description).toBe('Enable GitHub App integration for MCP catalog')
198+
expect(setting.description).toBe('Use GitHub App authentication for MCP catalog integration.')
199199
expect(setting.encrypted).toBe(false)
200200
expect(setting.required).toBe(false)
201201
})

services/frontend/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
"@tailwindcss/vite": "^4.1.17",
1818
"@tanstack/vue-table": "^8.21.3",
1919
"@vee-validate/zod": "^4.15.1",
20-
"@vueuse/core": "^14.0.0",
20+
"@vueuse/core": "^14.1.0",
2121
"class-variance-authority": "^0.7.1",
2222
"clsx": "^2.1.1",
2323
"echarts": "^6.0.0",

services/frontend/src/components/globalSettings/GitHubAppSettings.vue

Lines changed: 49 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,14 @@ import { useConnectionTest } from '@/composables/useConnectionTest'
66
import type { SettingsComponentProps, SettingsComponentEvents } from '@/composables/useSettingsComponentRegistry'
77
import {
88
Card,
9-
CardContent
9+
CardContent,
10+
CardDescription,
11+
CardHeader,
12+
CardTitle,
1013
} from '@/components/ui/card'
1114
import { Button } from '@/components/ui/button'
1215
import { Input } from '@/components/ui/input'
13-
import { Switch } from '@/components/ui/switch'
16+
import { Checkbox } from '@/components/ui/checkbox'
1417
import { Label } from '@/components/ui/label'
1518
import { Alert, AlertDescription, AlertTitle } from '@/components/ui/alert'
1619
import { Separator } from '@/components/ui/separator'
@@ -144,21 +147,24 @@ function getSetting(key: string) {
144147
</p>
145148
</div>
146149

147-
<!-- Enable Toggle -->
148-
<div class="space-y-2">
149-
<div class="flex items-center space-x-2">
150-
<Switch
151-
id="enabled"
152-
:model-value="Boolean(formValues['github.app.enabled'])"
153-
@update:model-value="(value) => updateField('github.app.enabled', value)"
154-
/>
155-
<Label for="enabled">
156-
{{ getSetting('github.app.enabled')?.description || t('githubApp.fields.enabled.label') }}
157-
</Label>
150+
<!-- Enable Checkbox -->
151+
<div class="flex items-start gap-3">
152+
<Checkbox
153+
id="enabled"
154+
:checked="Boolean(formValues['github.app.enabled'])"
155+
@update:checked="(value: boolean) => updateField('github.app.enabled', value)"
156+
/>
157+
<div class="grid gap-1">
158+
<label
159+
for="enabled"
160+
class="text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70"
161+
>
162+
{{ getSetting('github.app.enabled')?.name || t('githubApp.fields.enabled.label') }}
163+
</label>
164+
<p class="text-muted-foreground text-sm">
165+
{{ getSetting('github.app.enabled')?.description || t('githubApp.fields.enabled.description') }}
166+
</p>
158167
</div>
159-
<p class="text-xs text-muted-foreground">
160-
{{ t('githubApp.fields.enabled.description') }}
161-
</p>
162168
</div>
163169

164170
<Separator />
@@ -240,7 +246,16 @@ function getSetting(key: string) {
240246

241247
<!-- Desktop: Form with Card wrapper -->
242248
<Card class="hidden md:block">
243-
<CardContent class="pt-6">
249+
<CardHeader class="pb-3">
250+
<CardTitle>
251+
{{ props.group.name }}
252+
</CardTitle>
253+
<CardDescription v-if="props.group.description">
254+
{{ props.group.description }}
255+
</CardDescription>
256+
</CardHeader>
257+
<Separator />
258+
<CardContent class="pt-10">
244259
<form @submit.prevent="handleSave" class="space-y-6">
245260
<!-- App ID Field -->
246261
<div class="space-y-2">
@@ -303,21 +318,24 @@ function getSetting(key: string) {
303318
</p>
304319
</div>
305320

306-
<!-- Enable Toggle -->
307-
<div class="space-y-2">
308-
<div class="flex items-center space-x-2">
309-
<Switch
310-
id="enabled-desktop"
311-
:model-value="Boolean(formValues['github.app.enabled'])"
312-
@update:model-value="(value) => updateField('github.app.enabled', value)"
313-
/>
314-
<Label for="enabled-desktop">
315-
{{ getSetting('github.app.enabled')?.description || t('githubApp.fields.enabled.label') }}
316-
</Label>
321+
<!-- Enable Checkbox -->
322+
<div class="flex items-start gap-3">
323+
<Checkbox
324+
id="enabled-desktop"
325+
:checked="Boolean(formValues['github.app.enabled'])"
326+
@update:checked="(value: boolean) => updateField('github.app.enabled', value)"
327+
/>
328+
<div class="grid gap-1">
329+
<label
330+
for="enabled-desktop"
331+
class="text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70"
332+
>
333+
{{ getSetting('github.app.enabled')?.name || t('githubApp.fields.enabled.label') }}
334+
</label>
335+
<p class="text-muted-foreground text-sm">
336+
{{ getSetting('github.app.enabled')?.description || t('githubApp.fields.enabled.description') }}
337+
</p>
317338
</div>
318-
<p class="text-xs text-muted-foreground">
319-
{{ t('githubApp.fields.enabled.description') }}
320-
</p>
321339
</div>
322340

323341
<Separator />

services/frontend/src/components/globalSettings/GlobalSettingsSidebarNav.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,13 @@ import { Button } from '@/components/ui/button' // Adjusted path assuming shadcn
66
77
export interface Setting {
88
key: string
9+
name?: string
910
// eslint-disable-next-line @typescript-eslint/no-explicit-any
1011
value: any
1112
type: 'string' | 'number' | 'boolean'
1213
description?: string
1314
is_encrypted?: boolean
1415
group_id?: string
15-
// Add other potential fields like 'required', 'type' if known/needed
1616
}
1717
1818
export interface GlobalSettingGroup {

0 commit comments

Comments
 (0)