main
vue 95 lines 2.89 KB
Raw
1 <template>
2 <n-card size="small" bordered hoverable class="artifact-card-compact">
3 <div class="flex items-start justify-between gap-3">
4 <div class="min-w-0 flex-1">
5 <div class="mb-1 flex items-center gap-2">
6 <Icon :name="FileIcon" :size="16" class="text-primary-color shrink-0" />
7 <span class="truncate text-sm font-semibold">{{ artifact.artifact_name }}</span>
8 <n-tag :type="statusType" size="small" round>
9 {{ artifact.status }}
10 </n-tag>
11 </div>
12 <div class="text-secondary-color mb-2 text-xs">
13 <code class="text-xs">{{ artifact.file_name }}</code>
14 </div>
15 <div class="text-secondary-color flex flex-wrap gap-x-3 gap-y-1 text-xs">
16 <span>Size: {{ fileSize }}</span>
17 <span>{{ formatDate(artifact.collection_time, dFormats.datetime) }}</span>
18 </div>
19 </div>
20
21 <div v-if="showActions" class="flex shrink-0 flex-col gap-1">
22 <n-button size="tiny" secondary type="info" @click.stop="emit('details', artifact)">
23 <template #icon>
24 <Icon :name="InfoIcon" :size="14" />
25 </template>
26 </n-button>
27 <n-button size="tiny" secondary type="primary" @click.stop="emit('download', artifact)">
28 <template #icon>
29 <Icon :name="DownloadIcon" :size="14" />
30 </template>
31 </n-button>
32 <n-button size="tiny" secondary type="error" @click.stop="emit('delete', artifact)">
33 <template #icon>
34 <Icon :name="DeleteIcon" :size="14" />
35 </template>
36 </n-button>
37 </div>
38 </div>
39 </n-card>
40 </template>
41
42 <script setup lang="ts">
43 import type { TagProps } from "naive-ui"
44 import type { AgentArtifactData } from "@/types/agents.d"
45 import bytes from "bytes"
46 import { NButton, NCard, NTag } from "naive-ui"
47 import { computed } from "vue"
48 import Icon from "@/components/common/Icon.vue"
49 import { useSettingsStore } from "@/stores/settings"
50 import { formatDate } from "@/utils/format"
51
52 const { artifact, showActions = false } = defineProps<{
53 artifact: AgentArtifactData
54 showActions?: boolean
55 }>()
56
57 const emit = defineEmits<{
58 (e: "download", artifact: AgentArtifactData): void
59 (e: "delete", artifact: AgentArtifactData): void
60 (e: "details", artifact: AgentArtifactData): void
61 }>()
62
63 const dFormats = useSettingsStore().dateFormat
64
65 const FileIcon = "lsicon:file-zip-outline"
66 const DownloadIcon = "carbon:download"
67 const DeleteIcon = "carbon:trash-can"
68 const InfoIcon = "carbon:information"
69
70 const STATUS_TYPE_MAP: Record<string, TagProps["type"]> = {
71 completed: "success",
72 failed: "error",
73 processing: "warning",
74 pending: "info"
75 } as const
76
77 const fileSize = computed(() => bytes(artifact.file_size))
78
79 const statusType = computed<TagProps["type"]>(() => {
80 const normalizedStatus = artifact.status.toLowerCase()
81 return STATUS_TYPE_MAP[normalizedStatus] ?? "default"
82 })
83 </script>
84
85 <style lang="scss" scoped>
86 // TODO-FE: remove style
87
88 .artifact-card-compact {
89 transition: all 0.2s var(--bezier-ease);
90
91 &:hover {
92 border-color: var(--primary-color);
93 }
94 }
95 </style>