Skip to content

Commit 5ab49b8

Browse files
author
Lasim
committed
refactor: add category display component and update relevant views for category handling
1 parent a2e1523 commit 5ab49b8

File tree

6 files changed

+116
-2
lines changed

6 files changed

+116
-2
lines changed
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
<script setup lang="ts">
2+
import { ref, onMounted, computed } from 'vue'
3+
import { useI18n } from 'vue-i18n'
4+
import { DynamicIcon } from '@/components/ui/dynamic-icon'
5+
import { McpCatalogService } from '@/services/mcpCatalogService'
6+
import type { McpCategory } from '@/services/mcpCategoriesService'
7+
8+
const { t } = useI18n()
9+
10+
interface Props {
11+
categoryId?: string | null
12+
category?: McpCategory | null
13+
showNotProvided?: boolean
14+
iconClass?: string
15+
textClass?: string
16+
containerClass?: string
17+
}
18+
19+
const props = withDefaults(defineProps<Props>(), {
20+
categoryId: null,
21+
category: null,
22+
showNotProvided: true,
23+
iconClass: 'h-4 w-4 text-muted-foreground',
24+
textClass: '',
25+
containerClass: 'flex items-center gap-2'
26+
})
27+
28+
const category = ref<McpCategory | null>(props.category)
29+
const isLoading = ref(false)
30+
const error = ref<string | null>(null)
31+
32+
// Fetch category by ID if not provided as prop
33+
async function fetchCategory(categoryId: string): Promise<McpCategory | null> {
34+
try {
35+
isLoading.value = true
36+
const categories = await McpCatalogService.getCategories()
37+
return categories.find(cat => cat.id === categoryId) || null
38+
} catch (err) {
39+
error.value = err instanceof Error ? err.message : 'Failed to fetch category'
40+
console.error('Failed to fetch category:', err)
41+
return null
42+
} finally {
43+
isLoading.value = false
44+
}
45+
}
46+
47+
// Load category on mount if categoryId is provided but category is not
48+
onMounted(async () => {
49+
if (props.categoryId && !props.category) {
50+
category.value = await fetchCategory(props.categoryId)
51+
}
52+
})
53+
54+
// Computed property to determine what to display
55+
const displayCategory = computed(() => {
56+
return props.category || category.value
57+
})
58+
59+
const shouldShowNotProvided = computed(() => {
60+
return props.showNotProvided && !displayCategory.value && !isLoading.value
61+
})
62+
</script>
63+
64+
<template>
65+
<div v-if="displayCategory" :class="containerClass">
66+
<DynamicIcon
67+
:name="displayCategory.icon"
68+
:class="iconClass"
69+
/>
70+
<span :class="textClass">{{ displayCategory.name }}</span>
71+
</div>
72+
73+
<div v-else-if="isLoading" :class="containerClass">
74+
<div class="h-4 w-4 bg-gray-200 rounded animate-pulse"></div>
75+
<div class="h-4 w-16 bg-gray-200 rounded animate-pulse"></div>
76+
</div>
77+
78+
<div v-else-if="shouldShowNotProvided" class="text-muted-foreground italic">
79+
{{ t('mcpCatalog.edit.values.notProvided') }}
80+
</div>
81+
</template>

services/frontend/src/components/mcp-server/wizard/McpServerSelectionStep.vue

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { useRouter } from 'vue-router'
55
import { Loader2, Info, Download, ChevronDown, PackagePlus, AlertTriangle } from 'lucide-vue-next'
66
import { Button } from '@/components/ui/button'
77
import { Alert, AlertDescription } from '@/components/ui/alert'
8+
import CategoryDisplay from '@/components/mcp-server/CategoryDisplay.vue'
89
import { McpCatalogService } from '@/services/mcpCatalogService'
910
import { McpCategoriesService } from '@/services/mcpCategoriesService'
1011
import type { McpServerSearchParams, McpServerSearchResponse } from '@/types/mcp-catalog'
@@ -292,8 +293,15 @@ onMounted(() => {
292293
<dd class="md:mt-1">{{ server.author_name || t('mcpInstallations.wizard.server.unknownAuthor') }}</dd>
293294
</div>
294295
<div class="max-md:flex max-md:justify-between max-md:py-4 max-md:first:pt-0 max-md:last:pb-0">
295-
<dt class="font-medium text-gray-900">{{ t('mcpInstallations.wizard.server.language') }}</dt>
296-
<dd class="md:mt-1">{{ server.language || t('mcpInstallations.wizard.server.unknownLanguage') }}</dd>
296+
<dt class="font-medium text-gray-900">{{ t('mcpInstallations.wizard.server.category') }}</dt>
297+
<dd class="md:mt-1">
298+
<CategoryDisplay
299+
:category-id="server.category_id"
300+
:show-not-provided="true"
301+
text-class="text-sm"
302+
icon-class="h-4 w-4 text-gray-600"
303+
/>
304+
</dd>
297305
</div>
298306
</dl>
299307

services/frontend/src/i18n/locales/en/mcp-catalog.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -435,6 +435,7 @@ export default {
435435
name: 'Server Name',
436436
description: 'Description',
437437
longDescription: 'Detailed Description',
438+
category: 'Category',
438439
author: 'Author Information',
439440
technical: 'Technical Specifications',
440441
links: 'Repository Links',

services/frontend/src/i18n/locales/en/mcp-installations.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@ export default {
9292
install: 'Install',
9393
name: 'Server Name',
9494
author: 'Author',
95+
category: 'Category',
9596
language: 'Language',
9697
unknownAuthor: 'Unknown Author',
9798
unknownLanguage: 'Not Specified'
@@ -192,6 +193,7 @@ export default {
192193
name: 'Name',
193194
description: 'Description',
194195
longDescription: 'Long Description',
196+
category: 'Category',
195197
author: 'Author Information',
196198
technical: 'Technical Specifications',
197199
links: 'Repository Links',

services/frontend/src/views/admin/mcp-server-catalog/view/[id].vue

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { useI18n } from 'vue-i18n'
55
import { Button } from '@/components/ui/button'
66
import { Badge } from '@/components/ui/badge'
77
import { DsAlert } from '@/components/ui/ds-alert'
8+
import CategoryDisplay from '@/components/mcp-server/CategoryDisplay.vue'
89
import { ArrowLeft, Github, ExternalLink, Star, Package, Code, Settings, Calendar, Tag, Trash2, AlertTriangle, Edit } from 'lucide-vue-next'
910
import DashboardLayout from '@/components/DashboardLayout.vue'
1011
import EnvironmentVariablesDisplay from '@/components/admin/mcp-catalog/EnvironmentVariablesDisplay.vue'
@@ -341,6 +342,14 @@ const closeSuccessAlert = () => {
341342
</dd>
342343
</div>
343344

345+
<!-- Category -->
346+
<div class="px-4 py-6 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-0">
347+
<dt class="text-sm/6 font-medium text-gray-900">{{ t('mcpCatalog.edit.fields.category') }}</dt>
348+
<dd class="mt-1 text-sm/6 text-gray-700 sm:col-span-2 sm:mt-0">
349+
<CategoryDisplay :category-id="server.category_id" />
350+
</dd>
351+
</div>
352+
344353
<!-- Author Information -->
345354
<div class="px-4 py-6 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-0">
346355
<dt class="text-sm/6 font-medium text-gray-900">{{ t('mcpCatalog.edit.fields.author') }}</dt>

services/frontend/src/views/mcp-server/view/[id].vue

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import { Badge } from '@/components/ui/badge'
77
import { ArrowLeft, Github, ExternalLink, Star, Package, Code, Settings, Calendar, Tag, Download } from 'lucide-vue-next'
88
import DashboardLayout from '@/components/DashboardLayout.vue'
99
import EnvironmentVariablesDisplay from '@/components/admin/mcp-catalog/EnvironmentVariablesDisplay.vue'
10+
import CategoryDisplay from '@/components/mcp-server/CategoryDisplay.vue'
1011
import { McpCatalogService } from '@/services/mcpCatalogService'
1112
import type { McpServer } from '@/views/admin/mcp-server-catalog/types'
1213
@@ -272,6 +273,18 @@ const installServer = () => {
272273
</dd>
273274
</div>
274275

276+
<!-- Category -->
277+
<div class="px-4 py-6 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-0">
278+
<dt class="text-sm/6 font-medium text-gray-900">{{ t('mcpInstallations.view.fields.category') }}</dt>
279+
<dd class="mt-1 text-sm/6 text-gray-700 sm:col-span-2 sm:mt-0">
280+
<CategoryDisplay
281+
:category-id="server.category_id"
282+
:show-not-provided="true"
283+
text-class="text-sm/6"
284+
/>
285+
</dd>
286+
</div>
287+
275288
<!-- Author Information -->
276289
<div class="px-4 py-6 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-0">
277290
<dt class="text-sm/6 font-medium text-gray-900">{{ t('mcpInstallations.view.fields.author') }}</dt>

0 commit comments

Comments
 (0)