main
vue 130 lines 3.3 KB
Raw
1 <template>
2 <CardEntity>
3 <template #headerMain>
4 <div
5 class="hover:text-primary flex cursor-pointer items-center gap-2"
6 @click="routeIndex(alertsSummary.index_name).navigate()"
7 >
8 <IndexIcon v-if="alertsSummary.indexStats?.health" :health="alertsSummary.indexStats?.health" color />
9 <Icon v-else :name="PlaceholderIcon" :size="18" />
10 index: {{ alertsSummary.index_name }}
11 <Icon :name="LinkIcon" :size="14" />
12 </div>
13 </template>
14 <template #headerExtra>
15 <div class="flex min-h-6 flex-wrap items-center justify-end gap-3">
16 <n-button
17 v-if="alertsSummary.alerts.length > 3 && showAllAlerts"
18 class="animate-fade opacity-0"
19 size="tiny"
20 @click="showAllAlerts = false"
21 >
22 Show less
23 </n-button>
24 <span>
25 Alerts:
26 <strong class="ml-2 font-mono">{{ alertsSummary.total_alerts }}</strong>
27 </span>
28 </div>
29 </template>
30 <template #mainExtra>
31 <div class="alert-list" :class="{ expand: showAllAlerts }">
32 <n-scrollbar class="list-scroll" trigger="none">
33 <div class="flex flex-col gap-2">
34 <Alert v-for="alert of alertsSummary.alerts" :key="alert._id" :alert embedded />
35 </div>
36 </n-scrollbar>
37
38 <div v-if="alertsSummary.alerts.length > 3" class="load-more" @click="showAllAlerts = true">
39 <n-button size="small" text class="w-full!">
40 <template #icon>
41 <Icon :name="ExpandIcon" />
42 </template>
43 See all alerts
44 </n-button>
45 </div>
46 </div>
47 </template>
48 </CardEntity>
49 </template>
50
51 <script setup lang="ts">
52 import type { AlertsSummary } from "@/types/alerts.d"
53 import type { IndexStats } from "@/types/indices.d"
54 import { NButton, NScrollbar } from "naive-ui"
55 import { ref } from "vue"
56 import CardEntity from "@/components/common/cards/CardEntity.vue"
57 import Icon from "@/components/common/Icon.vue"
58 import IndexIcon from "@/components/indices/IndexIcon.vue"
59 import { useNavigation } from "@/composables/useNavigation"
60 import Alert from "./Alert.vue"
61
62 export interface AlertsSummaryExt extends AlertsSummary {
63 indexStats?: IndexStats
64 }
65
66 const { alertsSummary } = defineProps<{ alertsSummary: AlertsSummaryExt }>()
67
68 const ExpandIcon = "carbon:chevron-down"
69 const PlaceholderIcon = "ph:question"
70 const LinkIcon = "carbon:launch"
71
72 const showAllAlerts = ref(false)
73 const { routeIndex } = useNavigation()
74 </script>
75
76 <style lang="scss" scoped>
77 .alert-list {
78 position: relative;
79 overflow: hidden;
80 transition: all 0.2s var(--bezier-ease);
81
82 .alert-details {
83 border-bottom: 1px solid var(--border-color);
84
85 &:last-child {
86 border-bottom: none;
87 border-bottom-left-radius: var(--border-radius);
88 border-bottom-right-radius: var(--border-radius);
89 }
90 }
91
92 .load-more {
93 position: absolute;
94 top: 0;
95 bottom: 0;
96 left: 0;
97 right: 0;
98 height: 100%;
99 width: 100%;
100 background: rgba(var(--bg-default-color-rgb) / 0.6);
101 background: linear-gradient(transparent 0%, var(--bg-default-color) 85%);
102 display: flex;
103 align-items: center;
104 text-align: center;
105 padding: 10px;
106 flex-direction: column;
107 justify-content: flex-end;
108 cursor: pointer;
109 transition: all 0.6s var(--bezier-ease);
110 }
111
112 :deep() {
113 .list-scroll {
114 max-height: 250px;
115 transition: all 0.4s var(--bezier-ease);
116 }
117 }
118 &.expand {
119 :deep() {
120 .list-scroll {
121 max-height: 600px;
122 }
123 }
124
125 .load-more {
126 transform: translateY(100%);
127 }
128 }
129 }
130 </style>