main
vue 134 lines 4.02 KB
Raw
1 <template>
2 <div class="page md:page-wrapped flex flex-col gap-6 md:overflow-hidden">
3 <p>Monitor your organization's security posture and recent activity</p>
4
5 <div class="flex grow flex-col gap-6 overflow-hidden">
6 <div class="@container flex grow flex-col gap-6 overflow-hidden">
7 <OverviewStatsCards />
8
9 <div class="flex max-h-full grow flex-col overflow-hidden">
10 <div class="flex grow flex-col gap-6 overflow-hidden @2xl:flex-row">
11 <div class="max-h-full basis-1/2 overflow-hidden">
12 <n-spin :show="loadingAlerts" class="h-full" content-class="h-full">
13 <OverviewRecentAlerts
14 :recent-alerts
15 class="h-full"
16 size="small"
17 @updated="fetchAlerts()"
18 />
19 </n-spin>
20 </div>
21 <div class="max-h-full basis-1/2 overflow-hidden">
22 <n-spin :show="loadingCases" class="h-full" content-class="h-full">
23 <OverviewRecentCases
24 :recent-cases
25 class="h-full"
26 size="small"
27 @updated="fetchCases()"
28 />
29 </n-spin>
30 </div>
31 </div>
32 </div>
33 </div>
34 </div>
35 </div>
36 </template>
37
38 <script setup lang="ts">
39 import type { DashboardAlert, DashboardCase } from "@/components/overview/types"
40 import type { ApiError } from "@/types/common"
41 import { NSpin, useMessage } from "naive-ui"
42 import { onBeforeMount, ref, watch } from "vue"
43 import Api from "@/api"
44 import OverviewRecentAlerts from "@/components/overview/OverviewRecentAlerts.vue"
45 import OverviewRecentCases from "@/components/overview/OverviewRecentCases.vue"
46 import OverviewStatsCards from "@/components/overview/OverviewStatsCards.vue"
47 import { useCustomerFilterStore } from "@/stores/customerFilter"
48 import { getApiErrorMessage } from "@/utils"
49
50 const loadingAlerts = ref(false)
51 const loadingCases = ref(false)
52 const message = useMessage()
53 const recentAlerts = ref<DashboardAlert[]>([])
54 const recentCases = ref<DashboardCase[]>([])
55 const customerFilterStore = useCustomerFilterStore()
56
57 async function fetchAlerts() {
58 loadingAlerts.value = true
59
60 try {
61 // Fetch alerts, cases, and agents data using our API services
62 const alertsResponse = await Api.alerts.getAlerts(
63 { page: 1, pageSize: 10, order: "desc" },
64 undefined,
65 customerFilterStore.queryCustomerCodes
66 )
67
68 const alerts = alertsResponse.data.alerts || []
69
70 // Get recent alerts (last 5, sorted by creation time)
71 recentAlerts.value = alerts
72 .map(alert => ({
73 id: alert.id,
74 name: alert.alert_name || "Unnamed Alert",
75 description: alert.alert_description || "No description available",
76 severity: alert.status === "OPEN" ? "high" : alert.status === "IN_PROGRESS" ? "medium" : "low",
77 created_at: alert.alert_creation_time || new Date()
78 }))
79 .sort((a, b) => new Date(b.created_at).getTime() - new Date(a.created_at).getTime())
80 .slice(0, 10)
81 } catch (err) {
82 message.error(getApiErrorMessage(err as ApiError))
83 } finally {
84 loadingAlerts.value = false
85 }
86 }
87
88 async function fetchCases() {
89 loadingCases.value = true
90
91 try {
92 // Fetch alerts, cases, and agents data using our API services
93 const casesResponse = await Api.cases.getCases(
94 { page: 1, pageSize: 10, order: "desc" },
95 undefined,
96 customerFilterStore.queryCustomerCodes
97 )
98
99 const cases = casesResponse.data.cases || []
100
101 // Get recent cases (last 5, sorted by creation time)
102 recentCases.value = cases
103 .map(o => ({
104 id: o.id,
105 name: o.case_name || "Unnamed Case",
106 description: o.case_description || "No description available",
107 status: o.case_status || "open",
108 created_at: o.case_creation_time || new Date(),
109 assigned_to: o.assigned_to || undefined
110 }))
111 .sort((a, b) => new Date(b.created_at).getTime() - new Date(a.created_at).getTime())
112 .slice(0, 10)
113 } catch (err) {
114 message.error(getApiErrorMessage(err as ApiError))
115 } finally {
116 loadingCases.value = false
117 }
118 }
119
120 onBeforeMount(() => {
121 fetchAlerts()
122 fetchCases()
123 })
124
125 // Refetch whenever the global customer filter changes.
126 watch(
127 () => customerFilterStore.selectedCustomerCodes,
128 () => {
129 fetchAlerts()
130 fetchCases()
131 },
132 { deep: true }
133 )
134 </script>