main
vue 201 lines 4.73 KB
Raw
1 <template>
2 <div ref="list" class="soc-alerts-list">
3 <n-split
4 v-if="!compactMode"
5 direction="horizontal"
6 :default-size="splitDefault"
7 :resize-trigger-size="26"
8 :min="splitMin"
9 :max="splitMax"
10 >
11 <template #1>
12 <SocAlertsBookmarks
13 :users-list
14 @bookmark="reloadAlerts()"
15 @deleted="itemDeleted($event)"
16 @loaded="bookmarksList = $event"
17 @mounted="socAlertsBookmarksCTX = $event"
18 />
19 </template>
20 <template #2>
21 <SocAlertsList
22 :highlight
23 :bookmarks-list
24 :users-list
25 @bookmark="reloadBookmarks()"
26 @deleted="reloadBookmarks()"
27 @mounted="socAlertsCTX = $event"
28 />
29 </template>
30 <template #resize-trigger>
31 <div class="split-trigger">
32 <div class="split-trigger-icon">
33 <Icon :name="SplitIcon" />
34 </div>
35 </div>
36 </template>
37 </n-split>
38
39 <template v-else>
40 <SocAlertsList
41 :highlight
42 :bookmarks-list
43 :users-list
44 @bookmark="reloadBookmarks()"
45 @deleted="reloadBookmarks()"
46 @mounted="socAlertsCTX = $event"
47 >
48 <template #header>
49 <n-button size="small" @click="showBookmarkedDrawer = true">
50 <template #icon>
51 <Icon :name="StarIcon" :size="14" />
52 </template>
53 </n-button>
54 </template>
55 </SocAlertsList>
56
57 <n-drawer
58 v-model:show="showBookmarkedDrawer"
59 :width="700"
60 style="max-width: 90vw"
61 :trap-focus="false"
62 display-directive="show"
63 placement="left"
64 >
65 <n-drawer-content title="Alerts list" closable :native-scrollbar="false">
66 <SocAlertsBookmarks
67 :users-list
68 @bookmark="reloadAlerts()"
69 @deleted="itemDeleted($event)"
70 @loaded="bookmarksList = $event"
71 @mounted="socAlertsBookmarksCTX = $event"
72 />
73 </n-drawer-content>
74 </n-drawer>
75 </template>
76
77 <n-back-top :visibility-height="300"></n-back-top>
78 </div>
79 </template>
80
81 <script setup lang="ts">
82 import type { SocAlert } from "@/types/soc/alert.d"
83 import type { SocUser } from "@/types/soc/user.d"
84 import { useResizeObserver } from "@vueuse/core"
85 import { NBackTop, NButton, NDrawer, NDrawerContent, NSplit, useMessage } from "naive-ui"
86 import { onBeforeMount, ref, toRefs } from "vue"
87 import Api from "@/api"
88 import Icon from "@/components/common/Icon.vue"
89 import SocAlertsBookmarks from "./SocAlertsBookmarks.vue"
90 import SocAlertsList from "./SocAlertsList.vue"
91
92 const props = defineProps<{ highlight: string | null | undefined }>()
93 const { highlight } = toRefs(props)
94
95 const SplitIcon = "carbon:draggable"
96 const StarIcon = "carbon:star-filled"
97
98 const message = useMessage()
99 const bookmarksList = ref<SocAlert[]>([])
100 const usersList = ref<SocUser[]>([])
101 const socAlertsBookmarksCTX = ref<{ reload: () => void } | null>(null)
102 const socAlertsCTX = ref<{ reload: () => void; itemDeleted: (alertId: string, noEmit?: boolean) => void } | null>(null)
103
104 const list = ref(null)
105 const showBookmarkedDrawer = ref(false)
106 const compactMode = ref(false)
107 const splitMin = ref(0.25)
108 const splitMax = ref(0.75)
109 const splitDefault = ref(0.3)
110
111 function reloadBookmarks() {
112 socAlertsBookmarksCTX.value?.reload()
113 }
114
115 function reloadAlerts() {
116 socAlertsCTX.value?.reload()
117 }
118
119 function itemDeleted(alertId?: string) {
120 if (alertId) {
121 socAlertsCTX.value?.itemDeleted(alertId, true)
122 }
123 }
124
125 function getUsers() {
126 Api.soc
127 .getUsers()
128 .then(res => {
129 if (res.data.success) {
130 usersList.value = res.data?.users || []
131 } else {
132 message.warning(res.data?.message || "An error occurred. Please try again later.")
133 }
134 })
135 .catch(err => {
136 message.error(err.response?.data?.message || "An error occurred. Please try again later.")
137 })
138 }
139
140 useResizeObserver(list, entries => {
141 const entry = entries[0]
142 if (!entry) return
143
144 const { width } = entry.contentRect
145
146 compactMode.value = width < 680
147 splitMin.value = width < 850 ? 0.5 : 0.25
148 splitMax.value = width < 850 ? 0.5 : 0.75
149 splitDefault.value = width < 850 ? 0.5 : 0.3
150
151 if (width > 680) {
152 showBookmarkedDrawer.value = false
153 }
154 })
155
156 onBeforeMount(() => {
157 getUsers()
158 })
159 </script>
160
161 <style lang="scss" scoped>
162 .soc-alerts-list {
163 .n-split {
164 :deep() {
165 .n-split-pane-1 {
166 min-width: 290px;
167 max-width: 500px;
168 }
169 }
170 }
171 .split-trigger {
172 height: 100%;
173 width: 3px;
174 background-color: var(--border-color);
175 display: flex;
176 justify-content: center;
177 transition: background-color 0.3s var(--bezier-ease);
178 margin-left: 11px;
179
180 .split-trigger-icon {
181 position: relative;
182 top: min(48%, 300px);
183 background-color: var(--border-color);
184 border-radius: var(--border-radius-small);
185 height: 20px;
186 display: flex;
187 justify-content: center;
188 align-items: center;
189 transition: background-color 0.3s var(--bezier-ease);
190 }
191
192 &:hover {
193 background-color: var(--primary-color);
194
195 .split-trigger-icon {
196 background-color: var(--primary-color);
197 }
198 }
199 }
200 }
201 </style>