Skip to content

Commit b8f24d6

Browse files
author
Lasim
committed
refactor(frontend): improve team selection logic and error handling
1 parent 7a28eb2 commit b8f24d6

File tree

22 files changed

+194
-153
lines changed

22 files changed

+194
-153
lines changed

services/frontend/src/components/AppSidebar.vue

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -141,14 +141,18 @@ const fetchTeams = async (forceRefresh = false) => {
141141
} else {
142142
// Stored team not found, fallback to default team
143143
const defaultTeam = userTeams.find(team => team.is_default) || userTeams[0]
144-
selectedTeam.value = defaultTeam
145-
eventBus.setState('selected_team_id', defaultTeam.id)
144+
if (defaultTeam) {
145+
selectedTeam.value = defaultTeam
146+
eventBus.setState('selected_team_id', defaultTeam.id)
147+
}
146148
}
147149
} else {
148150
// No stored team, use default team
149151
const defaultTeam = userTeams.find(team => team.is_default) || userTeams[0]
150-
selectedTeam.value = defaultTeam
151-
eventBus.setState('selected_team_id', defaultTeam.id)
152+
if (defaultTeam) {
153+
selectedTeam.value = defaultTeam
154+
eventBus.setState('selected_team_id', defaultTeam.id)
155+
}
152156
}
153157
}
154158
} catch (error) { console.error('Error fetching teams:', error); teamsError.value = error instanceof Error ? error.message : 'Failed to load teams'; } finally { teamsLoading.value = false; }

services/frontend/src/components/admin/mcp-catalog/CapabilitiesStep.vue

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -205,7 +205,16 @@ const openEditModal = (index: number) => {
205205
modalMode.value = 'edit'
206206
editingIndex.value = index
207207
const variable = environmentVariables.value[index]
208-
formDataLocal.value = { ...variable }
208+
if (variable) {
209+
formDataLocal.value = {
210+
name: variable.name || '',
211+
description: variable.description || '',
212+
required: variable.required || false,
213+
type: (variable as ExtendedEnvironmentVariable).type || 'text',
214+
validation: (variable as ExtendedEnvironmentVariable).validation || '',
215+
placeholder: (variable as ExtendedEnvironmentVariable).placeholder || ''
216+
}
217+
}
209218
formErrors.value = {}
210219
isModalOpen.value = true
211220
}
@@ -354,6 +363,7 @@ const updateClaudeDesktopConfigInStorage = (envVars: EnvironmentVariable[]) => {
354363
}
355364
356365
const serverKey = serverKeys[0]
366+
if (!serverKey) return
357367
const serverConfig = parsed.mcpServers[serverKey]
358368
359369
// Build new env vars object

services/frontend/src/components/admin/mcp-catalog/ClaudeDesktopConfigStep.vue

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,9 @@ const validateJson = (jsonString: string) => {
102102
}
103103
104104
const serverKey = serverKeys[0]
105+
if (!serverKey) {
106+
return { isValid: false, error: t('mcpCatalog.form.claudeConfig.validation.noServers') }
107+
}
105108
const serverConfig = parsed.mcpServers[serverKey]
106109
107110
// Validate server configuration structure

services/frontend/src/components/admin/mcp-catalog/McpServerAddFormWizard.vue

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,9 @@ const progressTitle = computed(() => {
136136
}
137137
138138
const currentStepData = steps[currentStep.value]
139+
if (!currentStepData) {
140+
return t('mcpCatalog.form.steps.configuring')
141+
}
139142
return `${currentStepData.label} - ${t('mcpCatalog.form.steps.configuring')}`
140143
})
141144
@@ -242,13 +245,15 @@ const goToStep = (stepIndex: number) => {
242245
if (stepIndex >= 0 && stepIndex < currentStep.value) {
243246
const oldStep = currentStep.value
244247
currentStep.value = stepIndex
245-
emit('stepChanged', { step: stepIndex, stepKey: steps[stepIndex].key })
248+
const stepData = steps[stepIndex]
249+
if (!stepData) return
250+
emit('stepChanged', { step: stepIndex, stepKey: stepData.key })
246251
247252
// Emit event bus event for other components
248253
eventBus.emit('mcp-form-step-changed', {
249254
from: oldStep,
250255
to: stepIndex,
251-
stepKey: steps[stepIndex].key
256+
stepKey: stepData.key
252257
})
253258
}
254259
}
@@ -265,13 +270,15 @@ const nextStep = () => {
265270
if (canGoNext.value) {
266271
const oldStep = currentStep.value
267272
currentStep.value++
268-
emit('stepChanged', { step: currentStep.value, stepKey: steps[currentStep.value].key })
273+
const stepData = steps[currentStep.value]
274+
if (!stepData) return
275+
emit('stepChanged', { step: currentStep.value, stepKey: stepData.key })
269276
270277
// Emit event bus event
271278
eventBus.emit('mcp-form-step-changed', {
272279
from: oldStep,
273280
to: currentStep.value,
274-
stepKey: steps[currentStep.value].key
281+
stepKey: stepData.key
275282
})
276283
}
277284
}
@@ -280,13 +287,15 @@ const previousStep = () => {
280287
if (canGoPrevious.value) {
281288
const oldStep = currentStep.value
282289
currentStep.value--
283-
emit('stepChanged', { step: currentStep.value, stepKey: steps[currentStep.value].key })
290+
const stepData = steps[currentStep.value]
291+
if (!stepData) return
292+
emit('stepChanged', { step: currentStep.value, stepKey: stepData.key })
284293
285294
// Emit event bus event
286295
eventBus.emit('mcp-form-step-changed', {
287296
from: oldStep,
288297
to: currentStep.value,
289-
stepKey: steps[currentStep.value].key
298+
stepKey: stepData.key
290299
})
291300
}
292301
}

services/frontend/src/components/admin/mcp-catalog/McpServerEditFormWizard.vue

Lines changed: 32 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,9 @@ const progressTitle = computed(() => {
146146
}
147147
148148
const currentStepData = steps[currentStep.value]
149+
if (!currentStepData) {
150+
return t('mcpCatalog.form.steps.configuring')
151+
}
149152
return `${currentStepData.label} - ${t('mcpCatalog.form.steps.configuring')}`
150153
})
151154
@@ -175,12 +178,12 @@ const initializeStorageWithData = (data: McpServerFormData) => {
175178
// Initialize Claude Desktop config if available
176179
if (data.technical.installation_methods && data.technical.installation_methods.length > 0) {
177180
const method = data.technical.installation_methods[0]
178-
if (method.client === 'claude-desktop') {
181+
if (method && method.client === 'claude-desktop') {
179182
const claudeConfig = {
180183
mcpServers: {
181184
[data.basic.name || 'server']: {
182-
command: method.command,
183-
args: method.args,
185+
command: method.command || '',
186+
args: method.args || [],
184187
env: method.env || {}
185188
}
186189
}
@@ -265,7 +268,7 @@ watch(
265268
)
266269
267270
// Computed properties
268-
const currentStepData = computed(() => steps[currentStep.value])
271+
const currentStepData = computed(() => steps[currentStep.value] || null)
269272
const isFirstStep = computed(() => currentStep.value === 0)
270273
const isLastStep = computed(() => currentStep.value === steps.length - 1)
271274
const canGoNext = computed(() => !isLastStep.value)
@@ -289,13 +292,15 @@ const goToStep = (stepIndex: number) => {
289292
if (stepIndex >= 0 && stepIndex < currentStep.value) {
290293
const oldStep = currentStep.value
291294
currentStep.value = stepIndex
292-
emit('stepChanged', { step: stepIndex, stepKey: steps[stepIndex].key })
295+
const stepData = steps[stepIndex]
296+
if (!stepData) return
297+
emit('stepChanged', { step: stepIndex, stepKey: stepData.key })
293298
294299
// Emit event bus event for other components
295300
eventBus.emit('mcp-form-step-changed', {
296301
from: oldStep,
297302
to: stepIndex,
298-
stepKey: steps[stepIndex].key
303+
stepKey: stepData.key
299304
})
300305
}
301306
}
@@ -312,13 +317,15 @@ const nextStep = () => {
312317
if (canGoNext.value) {
313318
const oldStep = currentStep.value
314319
currentStep.value++
315-
emit('stepChanged', { step: currentStep.value, stepKey: steps[currentStep.value].key })
320+
const stepData = steps[currentStep.value]
321+
if (!stepData) return
322+
emit('stepChanged', { step: currentStep.value, stepKey: stepData.key })
316323
317324
// Emit event bus event
318325
eventBus.emit('mcp-form-step-changed', {
319326
from: oldStep,
320327
to: currentStep.value,
321-
stepKey: steps[currentStep.value].key
328+
stepKey: stepData.key
322329
})
323330
}
324331
}
@@ -327,13 +334,15 @@ const previousStep = () => {
327334
if (canGoPrevious.value) {
328335
const oldStep = currentStep.value
329336
currentStep.value--
330-
emit('stepChanged', { step: currentStep.value, stepKey: steps[currentStep.value].key })
337+
const stepData = steps[currentStep.value]
338+
if (!stepData) return
339+
emit('stepChanged', { step: currentStep.value, stepKey: stepData.key })
331340
332341
// Emit event bus event
333342
eventBus.emit('mcp-form-step-changed', {
334343
from: oldStep,
335344
to: currentStep.value,
336-
stepKey: steps[currentStep.value].key
345+
stepKey: stepData.key
337346
})
338347
}
339348
}
@@ -582,7 +591,9 @@ const submitForm = async () => {
582591
if (parsed.mcpServers) {
583592
const serverKeys = Object.keys(parsed.mcpServers)
584593
if (serverKeys.length === 1) {
585-
const serverConfig = parsed.mcpServers[serverKeys[0]]
594+
const serverKey = serverKeys[0]
595+
if (!serverKey) return
596+
const serverConfig = parsed.mcpServers[serverKey]
586597
587598
finalFormData.technical = {
588599
...finalFormData.technical,
@@ -671,33 +682,33 @@ onUnmounted(() => {
671682
<!-- Step Content -->
672683
<ContentWrapper>
673684
<component
674-
:is="currentStepData.component"
675-
v-if="currentStepData.key === 'capabilities'"
685+
:is="currentStepData?.component"
686+
v-if="currentStepData?.key === 'capabilities'"
676687
:form-data="formData"
677688
@update:form-data="(newFormData: McpServerFormData) => formData = newFormData"
678689
/>
679690
<component
680-
:is="currentStepData.component"
681-
v-else-if="currentStepData.key === 'basic'"
691+
:is="currentStepData?.component"
692+
v-else-if="currentStepData?.key === 'basic'"
682693
v-model="formData[currentStepData.key]"
683694
:form-data="formData"
684695
:mode="props.mode"
685-
@update:modelValue="(newValue: any) => formData[currentStepData.key] = newValue"
696+
@update:modelValue="(newValue: any) => currentStepData && (formData[currentStepData.key] = newValue)"
686697
@update:formData="(newFormData: any) => formData = newFormData"
687698
/>
688699
<component
689-
:is="currentStepData.component"
690-
v-else-if="currentStepData.key === 'technical'"
700+
:is="currentStepData?.component"
701+
v-else-if="currentStepData?.key === 'technical'"
691702
:form-data="formData"
692703
:mode="props.mode"
693704
@update:formData="(newFormData: any) => formData = newFormData"
694705
/>
695706
<component
696-
:is="currentStepData.component"
697-
v-else
707+
:is="currentStepData?.component"
708+
v-else-if="currentStepData"
698709
v-model="formData[currentStepData.key]"
699710
:form-data="formData"
700-
@update:modelValue="(newValue: any) => formData[currentStepData.key] = newValue"
711+
@update:modelValue="(newValue: any) => currentStepData && (formData[currentStepData.key] = newValue)"
701712
@update:formData="(newFormData: any) => formData = newFormData"
702713
/>
703714
</ContentWrapper>

services/frontend/src/components/admin/mcp-catalog/TechnicalStep.vue

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -237,6 +237,9 @@ const validateJson = (jsonString: string) => {
237237
}
238238
239239
const serverKey = serverKeys[0]
240+
if (!serverKey) {
241+
return { isValid: false, error: t('mcpCatalog.form.technical.claudeConfig.validation.noServers') }
242+
}
240243
const serverConfig = parsed.mcpServers[serverKey]
241244
242245
// Validate server configuration structure

services/frontend/src/components/credentials/AddCredentialDialog.vue

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,7 @@ const validateField = (fieldKey: string, value: string) => {
143143
}
144144
145145
if (errors.length > 0) {
146-
validationErrors.value[fieldKey] = errors[0]
146+
validationErrors.value[fieldKey] = errors[0] || ''
147147
} else {
148148
delete validationErrors.value[fieldKey]
149149
}
@@ -159,7 +159,7 @@ const validateCredentialName = () => {
159159
}
160160
161161
if (errors.length > 0) {
162-
validationErrors.value['name'] = errors[0]
162+
validationErrors.value['name'] = errors[0] || ''
163163
} else {
164164
delete validationErrors.value['name']
165165
}
@@ -228,7 +228,10 @@ watch(selectedProviderId, (newProviderId) => {
228228
// Watch for field changes to validate
229229
watch(credentialFields, (newFields) => {
230230
Object.keys(newFields).forEach(fieldKey => {
231-
validateField(fieldKey, newFields[fieldKey])
231+
const fieldValue = newFields[fieldKey]
232+
if (fieldValue !== undefined) {
233+
validateField(fieldKey, fieldValue)
234+
}
232235
})
233236
}, { deep: true })
234237

services/frontend/src/components/gateway-config/ClientConfigurationModal.vue

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,10 @@ async function loadSupportedClients() {
6363
supportedClients.value = clients
6464
// Set first client as default if no client is selected
6565
if (!selectedClient.value && clients.length > 0) {
66-
selectedClient.value = clients[0]
66+
const firstClient = clients[0]
67+
if (firstClient) {
68+
selectedClient.value = firstClient
69+
}
6770
}
6871
} catch (error) {
6972
const errorMessage = error instanceof Error ? error.message : 'Failed to load supported clients'

services/frontend/src/components/mcp-server/installation/EnvironmentVariables.vue

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ const openEditModal = (variable: any) => {
9090
if (!props.canEdit) {
9191
return
9292
}
93-
93+
9494
editingVariable.value = variable
9595
editingValue.value = variable.currentValue
9696
showPassword.value = false
@@ -151,6 +151,9 @@ const handleSubmit = async () => {
151151
}
152152
153153
const currentTeam = teams[0] // Use first team for now
154+
if (!currentTeam) {
155+
throw new Error('No team available')
156+
}
154157
155158
// Create updated environment variables object
156159
const updatedEnvVars = {
@@ -267,9 +270,9 @@ const modalTitle = computed(() => {
267270
<TooltipProvider v-if="!canEdit">
268271
<Tooltip>
269272
<TooltipTrigger as-child>
270-
<Button
271-
variant="ghost"
272-
class="h-8 w-8 p-0 cursor-not-allowed opacity-50"
273+
<Button
274+
variant="ghost"
275+
class="h-8 w-8 p-0 cursor-not-allowed opacity-50"
273276
disabled
274277
>
275278
<span class="sr-only">{{ t('mcpInstallations.details.environmentVariables.table.editDisabled') }}</span>
@@ -281,7 +284,7 @@ const modalTitle = computed(() => {
281284
</TooltipContent>
282285
</Tooltip>
283286
</TooltipProvider>
284-
287+
285288
<DropdownMenu v-else>
286289
<DropdownMenuTrigger as-child>
287290
<Button variant="ghost" class="h-8 w-8 p-0">

0 commit comments

Comments
 (0)