| 1 | <template> |
| 2 | <n-spin :show="loading" class="flex grow flex-col" content-class="flex grow flex-col"> |
| 3 | <n-tabs |
| 4 | v-model:value="tabActive" |
| 5 | type="line" |
| 6 | animated |
| 7 | :tabs-padding="24" |
| 8 | class="grow" |
| 9 | pane-wrapper-class="flex grow flex-col" |
| 10 | > |
| 11 | <n-tab-pane name="summary" tab="Summary" display-directive="show:lazy" class="flex grow flex-col"> |
| 12 | <div class="p-6 pt-3"> |
| 13 | <div class="flex flex-col gap-4"> |
| 14 | <div v-if="report?.severity_assessment" class="flex items-center gap-2"> |
| 15 | <Badge type="splitted" bright :color="severityColor"> |
| 16 | <template #label>Severity</template> |
| 17 | <template #value>{{ report.severity_assessment }}</template> |
| 18 | </Badge> |
| 19 | </div> |
| 20 | <CardKV v-if="report?.summary"> |
| 21 | <template #key>Summary</template> |
| 22 | <template #value>{{ report.summary }}</template> |
| 23 | </CardKV> |
| 24 | <CardKV v-if="report?.recommended_actions"> |
| 25 | <template #key>Recommended Actions</template> |
| 26 | <template #value>{{ report.recommended_actions }}</template> |
| 27 | </CardKV> |
| 28 | <div v-if="!report?.summary && !report?.recommended_actions"> |
| 29 | <n-empty description="No summary available" class="h-40" /> |
| 30 | </div> |
| 31 | </div> |
| 32 | </div> |
| 33 | </n-tab-pane> |
| 34 | <n-tab-pane name="report" tab="Full Report" display-directive="show:lazy"> |
| 35 | <div class="p-6 pt-3"> |
| 36 | <Markdown v-if="report?.report_markdown" :source="report.report_markdown" breaks /> |
| 37 | <n-empty v-else description="No report content available" class="h-40" /> |
| 38 | </div> |
| 39 | </n-tab-pane> |
| 40 | <n-tab-pane name="iocs" tab="IOCs" display-directive="show:lazy"> |
| 41 | <div class="p-6 pt-3"> |
| 42 | <AlertReportIocsList :alert-id="alert.alert_id" /> |
| 43 | </div> |
| 44 | </n-tab-pane> |
| 45 | <n-tab-pane name="jobs" tab="Jobs" display-directive="show:lazy"> |
| 46 | <div class="p-6 pt-3"> |
| 47 | <AlertReportJobsList :alert-id="alert.alert_id" /> |
| 48 | </div> |
| 49 | </n-tab-pane> |
| 50 | <n-tab-pane name="review" tab="Review" display-directive="show:lazy"> |
| 51 | <div class="p-6 pt-3"> |
| 52 | <AlertReportReviewPanel :report /> |
| 53 | </div> |
| 54 | </n-tab-pane> |
| 55 | <n-tab-pane name="compare" tab="Compare" display-directive="show:lazy"> |
| 56 | <div class="p-6 pt-3"> |
| 57 | <AlertReportCompare :alert-id="alert.alert_id" :current-report-id="report.id" /> |
| 58 | </div> |
| 59 | </n-tab-pane> |
| 60 | </n-tabs> |
| 61 | </n-spin> |
| 62 | </template> |
| 63 | |
| 64 | <script setup lang="ts"> |
| 65 | import type { AlertWithReport } from "@/types/aiAnalyst.d" |
| 66 | import { NEmpty, NSpin, NTabPane, NTabs } from "naive-ui" |
| 67 | import { computed, defineAsyncComponent, ref, toRefs, watch } from "vue" |
| 68 | import Badge from "@/components/common/Badge.vue" |
| 69 | import CardKV from "@/components/common/cards/CardKV.vue" |
| 70 | import Markdown from "@/components/common/Markdown.vue" |
| 71 | |
| 72 | const props = defineProps<{ |
| 73 | alert: AlertWithReport |
| 74 | }>() |
| 75 | |
| 76 | const emit = defineEmits<{ |
| 77 | (e: "tab-change", value: string): void |
| 78 | }>() |
| 79 | |
| 80 | const { alert } = toRefs(props) |
| 81 | |
| 82 | const AlertReportIocsList = defineAsyncComponent(() => import("./AlertReportIocsList.vue")) |
| 83 | const AlertReportJobsList = defineAsyncComponent(() => import("./AlertReportJobsList.vue")) |
| 84 | const AlertReportReviewPanel = defineAsyncComponent(() => import("./AlertReportReviewPanel/AlertReportReviewPanel.vue")) |
| 85 | const AlertReportCompare = defineAsyncComponent(() => import("./AlertReportCompare/AlertReportCompare.vue")) |
| 86 | |
| 87 | const tabActive = ref("summary") |
| 88 | |
| 89 | const loading = ref(false) |
| 90 | const report = computed(() => alert.value.report) |
| 91 | |
| 92 | const severityColor = computed(() => { |
| 93 | const severity = report.value?.severity_assessment |
| 94 | if (severity === "Critical" || severity === "High") return "danger" |
| 95 | if (severity === "Medium") return "warning" |
| 96 | if (severity === "Low" || severity === "Informational") return "success" |
| 97 | return undefined |
| 98 | }) |
| 99 | |
| 100 | watch( |
| 101 | tabActive, |
| 102 | value => { |
| 103 | emit("tab-change", value) |
| 104 | }, |
| 105 | { immediate: true } |
| 106 | ) |
| 107 | </script> |