main
vue 93 lines 3 KB
Raw
1 <template>
2 <CardEntity clickable hoverable :loading @click="$emit('click', report)">
3 <div class="flex flex-wrap items-start justify-between gap-4">
4 <div class="min-w-0">
5 <div class="mb-1 flex items-center gap-2">
6 <span class="text-default truncate font-mono text-sm font-medium">
7 {{ report.report_name }}
8 </span>
9 <span class="shrink-0 font-mono text-[10px] tracking-wider uppercase" :class="statusTextClass">
10 {{ report.status }}
11 </span>
12 </div>
13 <p class="text-secondary font-mono text-xs tabular-nums">
14 {{ formatDate(report.audit_started_at, dFormats.datetime) }}
15 <template v-if="report.audit_duration_seconds != null">
16 <span class="text-tertiary mx-1.5">·</span>
17 {{ report.audit_duration_seconds.toFixed(1) }}s
18 </template>
19 </p>
20 </div>
21
22 <div class="flex shrink-0 items-end gap-4 text-right">
23 <div>
24 <p class="text-secondary mb-0.5 text-[10px] tracking-wider uppercase">Score</p>
25 <p class="font-mono text-2xl leading-none font-bold tabular-nums" :class="scoreClass">
26 {{ report.score.toFixed(0) }}%
27 </p>
28 </div>
29 <div>
30 <p class="text-secondary mb-0.5 text-[10px] tracking-wider uppercase">Grade</p>
31 <GitHubAuditGradeLabel :grade="report.grade" class="text-2xl" />
32 </div>
33 </div>
34 </div>
35
36 <template #footer>
37 <dl class="flex flex-wrap items-baseline gap-x-4 gap-y-1">
38 <Badge v-if="report.critical_findings" color="danger" type="splitted" size="small">
39 <template #label>Critical</template>
40 <template #value>{{ report.critical_findings }}</template>
41 </Badge>
42 <Badge v-if="report.high_findings" color="warning" type="splitted" size="small">
43 <template #label>High</template>
44 <template #value>{{ report.high_findings }}</template>
45 </Badge>
46 <Badge type="splitted" size="small">
47 <template #label>Passed</template>
48 <template #value>{{ report.passed_checks }}/{{ report.total_checks }}</template>
49 </Badge>
50 </dl>
51 </template>
52 </CardEntity>
53 </template>
54
55 <script setup lang="ts">
56 import type { GitHubAuditReportSummary } from "@/types/githubAudit.d"
57 import { computed } from "vue"
58 import Badge from "@/components/common/Badge.vue"
59 import CardEntity from "@/components/common/cards/CardEntity.vue"
60 import { useSettingsStore } from "@/stores/settings"
61 import { formatDate } from "@/utils/format"
62 import GitHubAuditGradeLabel from "./GitHubAuditGradeLabel.vue"
63
64 const props = defineProps<{
65 report: GitHubAuditReportSummary
66 loading?: boolean
67 }>()
68
69 defineEmits<{
70 (e: "click", report: GitHubAuditReportSummary): void
71 }>()
72
73 const dFormats = useSettingsStore().dateFormat
74
75 const statusTextClass = computed(() => {
76 switch (props.report.status) {
77 case "completed":
78 return "text-success"
79 case "running":
80 return "text-info"
81 case "failed":
82 return "text-error"
83 default:
84 return "text-tertiary"
85 }
86 })
87
88 const scoreClass = computed(() => {
89 if (props.report.score >= 80) return "text-success"
90 if (props.report.score >= 60) return "text-warning"
91 return "text-error"
92 })
93 </script>