| 1 | <template> |
| 2 | <div class="flex items-center gap-6"> |
| 3 | <n-progress |
| 4 | v-if="showScore" |
| 5 | type="circle" |
| 6 | :percentage="config.last_audit_score ?? 0" |
| 7 | :status="scoreStatus" |
| 8 | gap-position="bottom" |
| 9 | > |
| 10 | <div class="flex flex-col items-center justify-between gap-1 text-center"> |
| 11 | <span class="text-xs">Security Score</span> |
| 12 | </div> |
| 13 | </n-progress> |
| 14 | |
| 15 | <div v-if="showGrade || hasMetaFields" class="flex min-w-0 flex-1 flex-col gap-3"> |
| 16 | <div v-if="showGrade" class="flex items-end justify-between gap-3"> |
| 17 | <div class="min-w-0"> |
| 18 | <p class="text-secondary mb-1 text-[10px] font-medium tracking-widest uppercase">Grade</p> |
| 19 | <GitHubAuditGradeLabel :grade="config.last_audit_grade" class="text-4xl" /> |
| 20 | </div> |
| 21 | <p |
| 22 | v-if="showScore && config.last_audit_score != null" |
| 23 | class="text-secondary shrink-0 font-mono text-xs tabular-nums" |
| 24 | > |
| 25 | {{ config.last_audit_score.toFixed(1) }}% |
| 26 | </p> |
| 27 | </div> |
| 28 | |
| 29 | <dl v-if="hasMetaFields" class="border-border flex flex-col gap-2" :class="{ 'border-t pt-3': showGrade }"> |
| 30 | <div v-if="showCustomer" class="flex items-baseline justify-between gap-3"> |
| 31 | <dt class="text-secondary shrink-0 text-[10px] tracking-wider uppercase">Customer</dt> |
| 32 | <dd class="text-default min-w-0 truncate font-mono text-xs"> |
| 33 | {{ config.customer_code }} |
| 34 | </dd> |
| 35 | </div> |
| 36 | <div v-if="showOrganization" class="flex items-baseline justify-between gap-3"> |
| 37 | <dt class="text-secondary shrink-0 text-[10px] tracking-wider uppercase">Organization</dt> |
| 38 | <dd class="text-default min-w-0 truncate font-mono text-xs"> |
| 39 | {{ config.organization }} |
| 40 | </dd> |
| 41 | </div> |
| 42 | <div v-if="showLastAudit" class="flex items-baseline justify-between gap-3"> |
| 43 | <dt class="text-secondary shrink-0 text-[10px] tracking-wider uppercase">Last audit</dt> |
| 44 | <dd class="text-default min-w-0 truncate text-right font-mono text-xs tabular-nums"> |
| 45 | {{ config.last_audit_at ? formatDate(config.last_audit_at, dFormats.datetime) : "—" }} |
| 46 | </dd> |
| 47 | </div> |
| 48 | <div v-if="showTokenType" class="flex items-baseline justify-between gap-3"> |
| 49 | <dt class="text-secondary shrink-0 text-[10px] tracking-wider uppercase">Token type</dt> |
| 50 | <dd class="text-default min-w-0 truncate text-right font-mono text-xs"> |
| 51 | {{ tokenTypeLabel }} |
| 52 | </dd> |
| 53 | </div> |
| 54 | </dl> |
| 55 | </div> |
| 56 | </div> |
| 57 | </template> |
| 58 | |
| 59 | <script setup lang="ts"> |
| 60 | import type { GitHubAuditConfig } from "@/types/githubAudit.d" |
| 61 | import { NProgress } from "naive-ui" |
| 62 | import { computed } from "vue" |
| 63 | import { useSettingsStore } from "@/stores/settings" |
| 64 | import { formatDate } from "@/utils/format" |
| 65 | import GitHubAuditGradeLabel from "./GitHubAuditGradeLabel.vue" |
| 66 | |
| 67 | export type GitHubAuditConfigSummaryMetaFields = "all" | "card" | "none" |
| 68 | |
| 69 | const props = withDefaults( |
| 70 | defineProps<{ |
| 71 | config: GitHubAuditConfig |
| 72 | showScore?: boolean |
| 73 | showGrade?: boolean |
| 74 | metaFields?: GitHubAuditConfigSummaryMetaFields |
| 75 | }>(), |
| 76 | { |
| 77 | showScore: true, |
| 78 | showGrade: true, |
| 79 | metaFields: "all" |
| 80 | } |
| 81 | ) |
| 82 | |
| 83 | const dFormats = useSettingsStore().dateFormat |
| 84 | |
| 85 | const showCustomer = computed(() => props.metaFields === "all" || props.metaFields === "card") |
| 86 | const showOrganization = computed(() => props.metaFields === "all") |
| 87 | const showLastAudit = computed(() => props.metaFields === "all" || props.metaFields === "card") |
| 88 | const showTokenType = computed(() => props.metaFields === "all") |
| 89 | |
| 90 | const hasMetaFields = computed( |
| 91 | () => showCustomer.value || showOrganization.value || showLastAudit.value || showTokenType.value |
| 92 | ) |
| 93 | |
| 94 | const scoreStatus = computed(() => { |
| 95 | const score = props.config.last_audit_score ?? 0 |
| 96 | if (score >= 80) return "success" |
| 97 | if (score >= 60) return "warning" |
| 98 | return "error" |
| 99 | }) |
| 100 | |
| 101 | const tokenTypeLabel = computed(() => (props.config.token_type === "pat" ? "Personal Access Token" : "GitHub App")) |
| 102 | </script> |