main
vue 185 lines 4.45 KB
Raw
1 <template>
2 <div class="monitoring-alerts-list">
3 <div ref="header" class="header flex items-center justify-end gap-2">
4 <div class="info flex grow gap-2">
5 <n-popover overlap placement="bottom-start">
6 <template #trigger>
7 <div class="bg-default rounded-lg">
8 <n-button size="small" class="cursor-help!">
9 <template #icon>
10 <Icon :name="InfoIcon" />
11 </template>
12 </n-button>
13 </div>
14 </template>
15 <div class="flex flex-col gap-2">
16 <div class="box">
17 Total :
18 <code>{{ total }}</code>
19 </div>
20 </div>
21 </n-popover>
22
23 <n-button
24 v-if="monitoringAlerts.length"
25 size="small"
26 type="error"
27 ghost
28 :loading="loadingPurge"
29 @click="handlePurge()"
30 >
31 <div class="flex items-center gap-2">
32 <Icon :name="TrashIcon" :size="16" />
33 <span class="xs:block hidden">Purge</span>
34 </div>
35 </n-button>
36 </div>
37 <n-pagination
38 v-model:page="currentPage"
39 v-model:page-size="pageSize"
40 :page-slot
41 :show-size-picker
42 :page-sizes
43 :item-count="total"
44 :simple="simpleMode"
45 />
46 </div>
47 <n-spin :show="loading">
48 <div class="my-3 flex min-h-52 flex-col gap-2">
49 <template v-if="monitoringAlerts.length">
50 <Alert
51 v-for="alert of itemsPaginated"
52 :key="alert.id"
53 :alert
54 class="item-appear item-appear-bottom item-appear-005"
55 @deleted="getData()"
56 @invoked="getData()"
57 />
58 </template>
59 <template v-else>
60 <n-empty v-if="!loading" description="No items found" class="h-48 justify-center" />
61 </template>
62 </div>
63 </n-spin>
64 <div class="footer flex justify-end">
65 <n-pagination
66 v-if="itemsPaginated.length > 3"
67 v-model:page="currentPage"
68 :page-size
69 :item-count="total"
70 :page-slot="6"
71 />
72 </div>
73 </div>
74 </template>
75
76 <script setup lang="ts">
77 // TODO-FE: refactor
78 import type { MonitoringAlert } from "@/types/monitoringAlerts.d"
79 import { useResizeObserver } from "@vueuse/core"
80 import { NButton, NEmpty, NPagination, NPopover, NSpin, useDialog, useMessage } from "naive-ui"
81 import { computed, onBeforeMount, ref } from "vue"
82 import Api from "@/api"
83 import Icon from "@/components/common/Icon.vue"
84 import Alert from "./Item.vue"
85
86 const dialog = useDialog()
87 const message = useMessage()
88 const loadingPurge = ref(false)
89 const loading = ref(false)
90 const monitoringAlerts = ref<MonitoringAlert[]>([])
91
92 const pageSize = ref(25)
93 const currentPage = ref(1)
94 const simpleMode = ref(false)
95 const showSizePicker = ref(true)
96 const pageSizes = [10, 25, 50, 100]
97 const header = ref()
98 const pageSlot = ref(8)
99
100 const itemsPaginated = computed(() => {
101 const from = (currentPage.value - 1) * pageSize.value
102 const to = currentPage.value * pageSize.value
103
104 return monitoringAlerts.value.slice(from, to)
105 })
106
107 const TrashIcon = "carbon:trash-can"
108 const InfoIcon = "carbon:information"
109
110 const total = computed<number>(() => {
111 return monitoringAlerts.value.length || 0
112 })
113
114 function getData() {
115 loading.value = true
116
117 Api.monitoringAlerts
118 .listAll()
119 .then(res => {
120 if (res.data.success) {
121 monitoringAlerts.value = res.data?.monitoring_alerts || []
122 } else {
123 message.warning(res.data?.message || "An error occurred. Please try again later.")
124 }
125 })
126 .catch(err => {
127 monitoringAlerts.value = []
128
129 message.error(err.response?.data?.message || "An error occurred. Please try again later.")
130 })
131 .finally(() => {
132 loading.value = false
133 })
134 }
135
136 function handlePurge() {
137 dialog.warning({
138 title: "Confirm",
139 content: "This will remove ALL Pending Alerts, are you sure you want to proceed?",
140 positiveText: "Yes I'm sure",
141 negativeText: "Cancel",
142 onPositiveClick: () => {
143 purge()
144 },
145 onNegativeClick: () => {
146 message.info("Purge canceled")
147 }
148 })
149 }
150
151 function purge() {
152 loadingPurge.value = true
153
154 Api.monitoringAlerts
155 .purge()
156 .then(res => {
157 if (res.data.success) {
158 getData()
159 message.success(res.data?.message || "Pending Alerts purged successfully")
160 } else {
161 message.warning(res.data?.message || "An error occurred. Please try again later.")
162 }
163 })
164 .catch(err => {
165 message.error(err.response?.data?.message || "An error occurred. Please try again later.")
166 })
167 .finally(() => {
168 loadingPurge.value = false
169 })
170 }
171
172 useResizeObserver(header, entries => {
173 const entry = entries[0]
174 if (!entry) return
175
176 const { width } = entry.contentRect
177
178 pageSlot.value = width < 700 ? 5 : 8
179 simpleMode.value = width < 550
180 })
181
182 onBeforeMount(() => {
183 getData()
184 })
185 </script>