main
vue 152 lines 3.5 KB
Raw
1 <template>
2 <div class="soc-users-list">
3 <n-spin :show="loadingUsers">
4 <n-scrollbar x-scrollable style="width: 100%">
5 <n-table :bordered="false" class="min-w-max">
6 <thead>
7 <tr>
8 <th>ID</th>
9 <th>Login</th>
10 <th>Name</th>
11 <th>Active</th>
12 <th style="max-width: 300px">Alerts</th>
13 </tr>
14 </thead>
15 <tbody>
16 <tr
17 v-for="user of usersList"
18 :key="user.user_id"
19 :class="{ highlight: highlight === user.user_id.toString() }"
20 >
21 <td>
22 <div class="flex items-center gap-3">
23 <span>#{{ user.user_id }}</span>
24 <n-tooltip trigger="hover">
25 <template #trigger>
26 <Icon :name="InfoIcon" :size="16" class="cursor-help" />
27 </template>
28 {{ user.user_uuid }}
29 </n-tooltip>
30 </div>
31 </td>
32 <td>
33 {{ user.user_login }}
34 </td>
35 <td>
36 {{ user.user_name }}
37 </td>
38 <td>
39 <strong
40 class="active-field"
41 :class="{ success: user.user_active, warning: !user.user_active }"
42 >
43 {{ user.user_active ? "Yes" : "No" }}
44 </strong>
45 </td>
46 <td style="max-width: 300px">
47 <SocUserAlerts :user-id="user.user_id" />
48 </td>
49 </tr>
50 </tbody>
51 </n-table>
52 </n-scrollbar>
53 </n-spin>
54 </div>
55 </template>
56
57 <script setup lang="ts">
58 import type { SocAlert } from "@/types/soc/alert.d"
59 import type { SocUser } from "@/types/soc/user.d"
60 import { NScrollbar, NSpin, NTable, NTooltip, useMessage } from "naive-ui"
61 import { onBeforeMount, ref, toRefs } from "vue"
62 import Api from "@/api"
63 import Icon from "@/components/common/Icon.vue"
64 import SocUserAlerts from "./SocUserAlerts.vue"
65
66 const props = defineProps<{ highlight: string | null | undefined }>()
67 const { highlight } = toRefs(props)
68
69 const InfoIcon = "carbon:information"
70
71 const message = useMessage()
72 const loadingAlerts = ref(false)
73 const loadingUsers = ref(false)
74 const usersList = ref<SocUser[]>([])
75 const alertsList = ref<SocAlert[]>([])
76
77 function getUsers() {
78 loadingUsers.value = true
79
80 Api.soc
81 .getUsers()
82 .then(res => {
83 if (res.data.success) {
84 usersList.value = res.data?.users || []
85 } else {
86 message.warning(res.data?.message || "An error occurred. Please try again later.")
87 }
88 })
89 .catch(err => {
90 usersList.value = []
91
92 message.error(err.response?.data?.message || "An error occurred. Please try again later.")
93 })
94 .finally(() => {
95 loadingUsers.value = false
96 })
97 }
98
99 function getAlerts() {
100 loadingAlerts.value = true
101
102 Api.soc
103 .getAlerts()
104 .then(res => {
105 if (res.data.success) {
106 alertsList.value = res.data?.alerts || []
107 } else {
108 message.warning(res.data?.message || "An error occurred. Please try again later.")
109 }
110 })
111 .catch(err => {
112 message.error(err.response?.data?.message || "An error occurred. Please try again later.")
113 })
114 .finally(() => {
115 loadingAlerts.value = false
116 })
117 }
118
119 onBeforeMount(() => {
120 getUsers()
121 getAlerts()
122 })
123 </script>
124
125 <style lang="scss" scoped>
126 .soc-users-list {
127 border-radius: var(--border-radius);
128 overflow: hidden;
129 .active-field {
130 &.success {
131 color: var(--success-color);
132 }
133 &.warning {
134 color: var(--warning-color);
135 }
136 }
137
138 tr:hover {
139 td {
140 background-color: rgba(var(--primary-color-rgb) / 0.05);
141 }
142 }
143
144 .highlight {
145 td {
146 border-top: 1px solid rgba(var(--primary-color-rgb) / 0.3);
147 border-bottom: 1px solid rgba(var(--primary-color-rgb) / 0.3);
148 background-color: rgba(var(--primary-color-rgb) / 0.05);
149 }
150 }
151 }
152 </style>