main
vue 237 lines 5.96 KB
Raw
1 <template>
2 <div class="alerts-stats">
3 <n-tabs default-value="countByHost" animated type="line" :tabs-padding="24">
4 <n-tab-pane name="countByHost" tab="By Host">
5 <n-spin :show="loadingCountByHost">
6 <template #description>Alerts are being fetched, this may take up to 1 minute.</template>
7
8 <div class="list">
9 <template v-if="countByHost.length">
10 <AlertsStatsItem
11 v-for="summary of countByHost"
12 :key="summary.agent_name"
13 :summary
14 class="mb-2"
15 />
16 </template>
17 <template v-else>
18 <n-empty
19 v-if="!loadingCountByHost"
20 description="No items found"
21 class="h-48 justify-center"
22 />
23 </template>
24 </div>
25 </n-spin>
26 </n-tab-pane>
27 <n-tab-pane name="countByRule" tab="By Rule">
28 <n-spin :show="loadingCountByRule">
29 <template #description>Alerts are being fetched, this may take up to 1 minute.</template>
30
31 <div class="list">
32 <template v-if="countByRule.length">
33 <AlertsStatsItem v-for="summary of countByRule" :key="summary.rule" :summary class="mb-2" />
34 </template>
35 <template v-else>
36 <n-empty
37 v-if="!loadingCountByRule"
38 description="No items found"
39 class="h-48 justify-center"
40 />
41 </template>
42 </div>
43 </n-spin>
44 </n-tab-pane>
45 <n-tab-pane name="countByRuleHost" tab="By Rule & Host">
46 <n-spin :show="loadingCountByRuleHost">
47 <template #description>Alerts are being fetched, this may take up to 1 minute.</template>
48
49 <div class="list">
50 <template v-if="countByRuleHost.length">
51 <AlertsStatsItem
52 v-for="summary of countByRuleHost"
53 :key="summary.agent_name + summary.rule"
54 :summary
55 class="mb-2"
56 />
57 </template>
58 <template v-else>
59 <n-empty
60 v-if="!loadingCountByRuleHost"
61 description="No items found"
62 class="h-48 justify-center"
63 />
64 </template>
65 </div>
66 </n-spin>
67 </n-tab-pane>
68 </n-tabs>
69 </div>
70 </template>
71
72 <script setup lang="ts">
73 import type { AlertsSummaryQuery } from "@/api/endpoints/alerts"
74 import type { AlertsByHost, AlertsByRule, AlertsByRulePerHost } from "@/types/alerts.d"
75 import axios from "axios"
76 import { NEmpty, NSpin, NTabPane, NTabs, useMessage } from "naive-ui"
77 import { onBeforeMount, onBeforeUnmount, onMounted, ref, toRefs } from "vue"
78 import Api from "@/api"
79 import AlertsStatsItem from "./AlertsStatsItem.vue"
80 // import { alerts_by_host, alerts_by_rule, alerts_by_rule_per_host } from "./mock"
81
82 const props = withDefaults(defineProps<{ filters?: AlertsSummaryQuery }>(), {
83 filters: () => ({})
84 })
85 const emit = defineEmits<{
86 (e: "mounted", value: AlertsStatsCTX): void
87 }>()
88
89 const { filters } = toRefs(props)
90
91 export interface AlertsStatsCTX {
92 startSearch: () => void
93 }
94
95 const message = useMessage()
96 const countByHost = ref<AlertsByHost[]>([])
97 const countByRule = ref<AlertsByRule[]>([])
98 const countByRuleHost = ref<AlertsByRulePerHost[]>([])
99 const loadingCountByHost = ref(false)
100 const loadingCountByRule = ref(false)
101 const loadingCountByRuleHost = ref(false)
102 let abortControllerByHost: AbortController | null = null
103 let abortControllerByRule: AbortController | null = null
104 let abortControllerByRuleHost: AbortController | null = null
105
106 function getCountByHost() {
107 loadingCountByHost.value = true
108
109 abortControllerByHost = new AbortController()
110
111 Api.alerts
112 .getCountByHost(filters.value, abortControllerByHost.signal)
113 .then(res => {
114 if (res.data.success) {
115 countByHost.value = res.data?.alerts_by_host || []
116 } else {
117 message.warning(res.data?.message || "An error occurred. Please try again later.")
118 }
119 })
120 .catch(err => {
121 if (!axios.isCancel(err)) {
122 countByHost.value = []
123
124 message.error(err.response?.data?.message || "An error occurred. Please try again later.")
125 }
126 })
127 .finally(() => {
128 loadingCountByHost.value = false
129 })
130 }
131
132 function getCountByRule() {
133 loadingCountByRule.value = true
134
135 abortControllerByRule = new AbortController()
136
137 Api.alerts
138 .getCountByRule(filters.value, abortControllerByRule.signal)
139 .then(res => {
140 if (res.data.success) {
141 countByRule.value = res.data?.alerts_by_rule || []
142 } else {
143 message.warning(res.data?.message || "An error occurred. Please try again later.")
144 }
145 })
146 .catch(err => {
147 if (!axios.isCancel(err)) {
148 countByRule.value = []
149
150 message.error(err.response?.data?.message || "An error occurred. Please try again later.")
151 }
152 })
153 .finally(() => {
154 loadingCountByRule.value = false
155 })
156 }
157
158 function getCountByRuleHost() {
159 loadingCountByRuleHost.value = true
160
161 abortControllerByRuleHost = new AbortController()
162
163 Api.alerts
164 .getCountByRuleHost(filters.value, abortControllerByRuleHost.signal)
165 .then(res => {
166 if (res.data.success) {
167 countByRuleHost.value = res.data?.alerts_by_rule_per_host || []
168 } else {
169 message.warning(res.data?.message || "An error occurred. Please try again later.")
170 }
171 })
172 .catch(err => {
173 if (!axios.isCancel(err)) {
174 countByRuleHost.value = []
175
176 message.error(err.response?.data?.message || "An error occurred. Please try again later.")
177 }
178 })
179 .finally(() => {
180 loadingCountByRuleHost.value = false
181 })
182 }
183
184 function startSearch() {
185 cancelSearch()
186
187 setTimeout(() => {
188 getCountByHost()
189 getCountByRule()
190 getCountByRuleHost()
191 }, 200)
192 }
193
194 function cancelSearch() {
195 abortControllerByHost?.abort()
196 abortControllerByRule?.abort()
197 abortControllerByRuleHost?.abort()
198 }
199
200 onBeforeMount(() => {
201 /*
202 countByHost.value = alerts_by_host as AlertsByHost[]
203 countByRule.value = alerts_by_rule as AlertsByRule[]
204 countByRuleHost.value = alerts_by_rule_per_host as AlertsByRulePerHost[]
205 */
206
207 startSearch()
208 })
209
210 onMounted(() => {
211 emit("mounted", {
212 startSearch
213 })
214 })
215
216 onBeforeUnmount(() => {
217 cancelSearch()
218 })
219 </script>
220
221 <style lang="scss" scoped>
222 .alerts-stats {
223 :deep() {
224 .n-spin-container {
225 min-height: 200px;
226 }
227 .n-spin-body {
228 top: 100px;
229 text-align: center;
230 width: 80%;
231 }
232 }
233 .list {
234 padding: var(--n-body-padding);
235 }
236 }
237 </style>