main
vue 176 lines 4.84 KB
Raw
1 <template>
2 <n-button secondary :loading="merging" :size @click="openDialog()">
3 <template #icon>
4 <Icon :name="MergeIcon" />
5 </template>
6 Merge into Case
7 </n-button>
8
9 <n-modal
10 v-model:show="showMergeBox"
11 display-directive="show"
12 preset="card"
13 :title="`Select the case you want to merge ${alerts.length > 1 ? 'them' : 'it'} with :`"
14 :style="{ maxWidth: 'min(850px, 90vw)', minHeight: 'min(540px, 90vh)', maxHeight: '80vh' }"
15 content-class="flex flex-col overflow-hidden px-2! py-0!"
16 segmented
17 >
18 <n-spin
19 :show="loadingCases"
20 class="flex grow flex-col overflow-hidden"
21 content-class="flex grow flex-col overflow-hidden"
22 >
23 <n-scrollbar class="flex grow flex-col" content-class="grow" trigger="none">
24 <div class="flex flex-col gap-2 px-5 py-5">
25 <template v-if="linkableCases.length">
26 <CaseItem
27 v-for="item of linkableCases"
28 :key="item.id"
29 :case-data="item"
30 compact
31 embedded
32 :highlight="selectedCase?.id === item.id"
33 @click="toggleSelectedCase(item)"
34 />
35 </template>
36 <template v-else>
37 <n-empty v-if="!loadingCases" description="No items found" class="h-48 justify-center" />
38 </template>
39 </div>
40 </n-scrollbar>
41 </n-spin>
42
43 <template #footer>
44 <div class="flex justify-end">
45 <n-button type="success" :disabled="!selectedCase" :loading="merging" @click="linkCase()">
46 <template #icon>
47 <Icon :name="MergeIcon" />
48 </template>
49 Confirm Merge {{ selectedCase ? `with Case #${selectedCase.id}` : "" }}
50 </n-button>
51 </div>
52 </template>
53 </n-modal>
54 </template>
55
56 <script setup lang="ts">
57 import type { ButtonSize } from "naive-ui"
58 import type { Ref } from "vue"
59 import type { Alert } from "@/types/incidentManagement/alerts.d"
60 import type { Case } from "@/types/incidentManagement/cases.d"
61 import _orderBy from "lodash/orderBy"
62 import { NButton, NEmpty, NModal, NScrollbar, NSpin, useMessage } from "naive-ui"
63 import { inject, ref, watch } from "vue"
64 import Api from "@/api"
65 import Icon from "@/components/common/Icon.vue"
66 import CaseItem from "../cases/CaseItem.vue"
67
68 const { alerts, size } = defineProps<{ alerts: Alert[]; size?: ButtonSize }>()
69
70 const emit = defineEmits<{
71 (e: "updated", value: Alert): void
72 (e: "merged"): void
73 }>()
74
75 const MergeIcon = "carbon:ibm-cloud-direct-link-1-connect"
76 const message = useMessage()
77 const merging = ref(false)
78 const showMergeBox = ref(false)
79 const loadingCases = ref(false)
80 const linkableCases = inject<Ref<Case[]>>("linkable-cases", ref([]))
81 const selectedCase = ref<Case | null>(null)
82
83 watch(showMergeBox, val => {
84 if (val && !linkableCases.value.length) {
85 getCasesList()
86 }
87 })
88
89 function updateAlert(updatedAlert: Alert) {
90 emit("updated", updatedAlert)
91 }
92
93 function openDialog() {
94 showMergeBox.value = true
95 }
96
97 function closeDialog() {
98 showMergeBox.value = false
99 }
100
101 function toggleSelectedCase(caseEntity: Case) {
102 if (selectedCase.value?.id === caseEntity.id) {
103 selectedCase.value = null
104 } else {
105 selectedCase.value = caseEntity
106 }
107 }
108
109 function getCasesList() {
110 loadingCases.value = true
111
112 Api.incidentManagement.cases
113 .getCasesList(undefined, { page: 1, pageSize: 9999 })
114 .then(res => {
115 if (res.data.success) {
116 linkableCases.value = _orderBy(res.data?.cases || [], ["id"], ["desc"])
117 } else {
118 message.warning(res.data?.message || "An error occurred. Please try again later.")
119 }
120 })
121 .catch(err => {
122 message.error(err.response?.data?.message || "An error occurred. Please try again later.")
123 })
124 .finally(() => {
125 loadingCases.value = false
126 })
127 }
128
129 function linkCase() {
130 if (selectedCase.value?.id) {
131 merging.value = true
132
133 Api.incidentManagement.cases
134 .multiLinkCase(
135 alerts.map(o => o.id),
136 selectedCase.value.id
137 )
138 .then(res => {
139 if (res.data.success) {
140 closeDialog()
141
142 for (const alert of alerts) {
143 const caseId = res.data.case_alert_links.find(o => o.alert_id === alert.id)?.case_id || 0
144 const caseData = linkableCases.value.find(o => o.id === caseId) || null
145 updateAlert({
146 ...alert,
147 linked_cases: [
148 {
149 id: caseId,
150 case_name: caseData?.case_name || "",
151 case_description: caseData?.case_description || "",
152 case_creation_time: caseData?.case_creation_time || new Date(),
153 assigned_to: caseData?.assigned_to || null,
154 case_status: caseData?.case_status || null,
155 customer_code: caseData?.customer_code || null,
156 comments: caseData?.comments || []
157 }
158 ]
159 })
160 }
161
162 emit("merged")
163 message.success(res.data?.message || "Case linked successfully")
164 } else {
165 message.warning(res.data?.message || "An error occurred. Please try again later.")
166 }
167 })
168 .catch(err => {
169 message.error(err.response?.data?.message || "An error occurred. Please try again later.")
170 })
171 .finally(() => {
172 merging.value = false
173 })
174 }
175 }
176 </script>