11<script setup lang="ts">
22import { computed , ref } from ' vue'
33import { useI18n } from ' vue-i18n'
4- import {
5- Card ,
6- CardContent ,
7- CardDescription ,
8- CardHeader ,
9- CardTitle ,
10- } from ' @/components/ui/card'
114import { Button } from ' @/components/ui/button'
125import { Badge } from ' @/components/ui/badge'
136import {
@@ -34,7 +27,8 @@ import {
3427 Trash2 ,
3528 Server ,
3629 Eye ,
37- AlertTriangle
30+ AlertTriangle ,
31+ PackagePlus
3832} from ' lucide-vue-next'
3933import type { McpInstallation } from ' @/types/mcp-installations'
4034import { McpInstallationService } from ' @/services/mcpInstallationService'
@@ -209,101 +203,100 @@ const handleInstallServer = () => {
209203 </script >
210204
211205<template >
212- <Card >
213- < CardHeader >
214- < CardTitle >{{ t('mcpInstallations.title') }}</ CardTitle >
215- < CardDescription >
216- {{ t('mcpInstallations.description') }}
217- </ CardDescription >
218- </ CardHeader >
219- < CardContent >
220- <!-- Empty State -- >
221- <div v-if = " !hasInstallations " class = " text-center py-8 " >
222- < Server class =" h-12 w-12 mx-auto text-muted-foreground mb-4 " / >
223- <h3 class =" text-lg font-medium mb-2 " >
206+ <!-- Empty State -- >
207+ < div v-if = " !hasInstallations " class = " pt-20 " >
208+ < button
209+ type = " button "
210+ @click = " handleInstallServer "
211+ class = " relative block w-full max-w-2xl mx-auto rounded-lg border-2 border-dashed border-muted-foreground/25 p-12 text-center hover:border-muted-foreground/40 hover:bg-muted/20 focus:ring-2 focus:ring-ring focus:ring-offset-2 focus:outline-hidden transition-all duration-200 group "
212+ >
213+ < div class = " mx-auto size-16 text-muted-foreground/60 group-hover:text-muted-foreground/80 transition-colors duration-200 " >
214+ < PackagePlus class = " w-full h-full " stroke-width = " 1.25 " / >
215+ </ div >
216+ < div class =" mt-4 space-y-2 " >
217+ <span class =" block text-sm font-semibold text-foreground group-hover:text-foreground/90 transition-colors duration-200 " >
224218 {{ t('mcpInstallations.emptyState.title') }}
225- </h3 >
226- <p class =" text-muted-foreground mb-4 " >
219+ </span >
220+ <span class =" block text-sm text- muted-foreground group-hover:text-muted-foreground/80 transition-colors duration-200 " >
227221 {{ t('mcpInstallations.emptyState.description') }}
228- </p >
229- <Button @click = " handleInstallServer " class =" flex items-center gap-2 " >
230- <Plus class =" h-4 w-4 " />
222+ </span >
223+ <div class =" mt-4 inline- flex items-center gap-1.5 text-xs text-primary font-medium group-hover:text-primary/80 transition-colors duration-200 " >
224+ <Plus class =" h-3.5 w-3.5 " />
231225 {{ t('mcpInstallations.actions.install') }}
232- </Button >
226+ </div >
233227 </div >
234-
235- <!-- Installations List -->
236- <div v-else class =" space-y-4" >
237- <div class =" grid gap-4" >
238- <div
239- v-for =" installation in sortedInstallations"
240- :key =" installation.id"
241- class =" flex items-center justify-between space-x-4 p-4 border rounded-lg hover:bg-muted/50 transition-colors"
242- >
243- <!-- Left side: Server info -->
244- <div class =" flex items-center space-x-4 flex-1 min-w-0" >
245- <!-- Server Icon -->
246- <div class =" flex-shrink-0" >
247- <div class =" w-10 h-10 bg-primary/10 rounded-lg flex items-center justify-center" >
248- <Server class =" h-5 w-5 text-primary" />
249- </div >
250- </div >
251-
252- <!-- Server Details -->
253- <div class =" flex-1 min-w-0" >
254- <div class =" flex items-center gap-2 mb-1" >
255- <p class =" text-sm font-medium leading-none truncate" >
256- {{ installation.installation_name }}
257- </p >
258- <Badge :variant =" getStatusVariant(installation.installation_type)" class =" text-xs" >
259- {{ getStatusText(installation.installation_type) }}
260- </Badge >
261- </div >
262- <p class =" text-sm text-muted-foreground truncate mb-1" >
263- {{ installation.server.description }}
264- </p >
265- <div class =" flex items-center gap-4 text-xs text-muted-foreground" >
266- <span >{{ installation.server.language }} • {{ installation.server.runtime }}</span >
267- <span >{{ getEnvironmentVariablesCount(installation.user_environment_variables) }} env vars</span >
268- <span >{{ formatDate(installation.created_at) }}</span >
269- </div >
270- </div >
228+ </button >
229+ </div >
230+
231+ <!-- Installations List -->
232+ <div v-else class =" space-y-4" >
233+ <div class =" grid gap-4" >
234+ <div
235+ v-for =" installation in sortedInstallations"
236+ :key =" installation.id"
237+ class =" flex items-center justify-between space-x-4 p-4 border rounded-lg hover:bg-muted/50 transition-colors"
238+ >
239+ <!-- Left side: Server info -->
240+ <div class =" flex items-center space-x-4 flex-1 min-w-0" >
241+ <!-- Server Icon -->
242+ <div class =" flex-shrink-0" >
243+ <div class =" w-10 h-10 bg-primary/10 rounded-lg flex items-center justify-center" >
244+ <Server class =" h-5 w-5 text-primary" />
271245 </div >
246+ </div >
272247
273- <!-- Right side: Actions -->
274- <div class =" flex-shrink-0" >
275- <DropdownMenu >
276- <DropdownMenuTrigger as-child >
277- <Button variant =" ghost" class =" h-8 w-8 p-0" >
278- <span class =" sr-only" >{{ t('mcpInstallations.actions.openMenu') }}</span >
279- <MoreHorizontal class =" h-4 w-4" />
280- </Button >
281- </DropdownMenuTrigger >
282- <DropdownMenuContent align =" end" >
283- <DropdownMenuItem @click =" handleView(installation.server.id)" >
284- <Eye class =" h-4 w-4 mr-2" />
285- {{ t('mcpInstallations.actions.view') }}
286- </DropdownMenuItem >
287- <DropdownMenuItem @click =" handleManage(installation.id)" >
288- <Settings class =" h-4 w-4 mr-2" />
289- {{ t('mcpInstallations.actions.configure') }}
290- </DropdownMenuItem >
291- <DropdownMenuItem
292- @click =" handleRemove(installation.id)"
293- class =" text-destructive focus:text-destructive"
294- >
295- <Trash2 class =" h-4 w-4 mr-2" />
296- {{ t('mcpInstallations.actions.remove') }}
297- </DropdownMenuItem >
298- </DropdownMenuContent >
299- </DropdownMenu >
248+ <!-- Server Details -->
249+ <div class =" flex-1 min-w-0" >
250+ <div class =" flex items-center gap-2 mb-1" >
251+ <p class =" text-sm font-medium leading-none truncate" >
252+ {{ installation.installation_name }}
253+ </p >
254+ <Badge :variant =" getStatusVariant(installation.installation_type)" class =" text-xs" >
255+ {{ getStatusText(installation.installation_type) }}
256+ </Badge >
257+ </div >
258+ <p class =" text-sm text-muted-foreground truncate mb-1" >
259+ {{ installation.server.description }}
260+ </p >
261+ <div class =" flex items-center gap-4 text-xs text-muted-foreground" >
262+ <span >{{ installation.server.language }} • {{ installation.server.runtime }}</span >
263+ <span >{{ getEnvironmentVariablesCount(installation.user_environment_variables) }} env vars</span >
264+ <span >{{ formatDate(installation.created_at) }}</span >
300265 </div >
301266 </div >
302267 </div >
303268
269+ <!-- Right side: Actions -->
270+ <div class =" flex-shrink-0" >
271+ <DropdownMenu >
272+ <DropdownMenuTrigger as-child >
273+ <Button variant =" ghost" class =" h-8 w-8 p-0" >
274+ <span class =" sr-only" >{{ t('mcpInstallations.actions.openMenu') }}</span >
275+ <MoreHorizontal class =" h-4 w-4" />
276+ </Button >
277+ </DropdownMenuTrigger >
278+ <DropdownMenuContent align =" end" >
279+ <DropdownMenuItem @click =" handleView(installation.server.id)" >
280+ <Eye class =" h-4 w-4 mr-2" />
281+ {{ t('mcpInstallations.actions.view') }}
282+ </DropdownMenuItem >
283+ <DropdownMenuItem @click =" handleManage(installation.id)" >
284+ <Settings class =" h-4 w-4 mr-2" />
285+ {{ t('mcpInstallations.actions.configure') }}
286+ </DropdownMenuItem >
287+ <DropdownMenuItem
288+ @click =" handleRemove(installation.id)"
289+ class =" text-destructive focus:text-destructive"
290+ >
291+ <Trash2 class =" h-4 w-4 mr-2" />
292+ {{ t('mcpInstallations.actions.remove') }}
293+ </DropdownMenuItem >
294+ </DropdownMenuContent >
295+ </DropdownMenu >
296+ </div >
304297 </div >
305- </CardContent >
306- </Card >
298+ </div >
299+ </div >
307300
308301 <!-- Delete Confirmation Modal -->
309302 <AlertDialog v-model:open =" showDeleteModal" >
0 commit comments