main
vue 223 lines 6.14 KB
Raw
1 <template>
2 <div>
3 <CardEntity :loading :embedded hoverable>
4 <template #headerMain>{{ entity.name }}</template>
5 <template #headerExtra>
6 <div class="hidden font-sans sm:block">
7 <ExclusionRuleStatusToggler
8 :entity
9 @loading="updatingStatus = $event"
10 @updated="setStatus($event)"
11 />
12 </div>
13 </template>
14 <template #default>
15 {{ entity.title }}
16 </template>
17 <template #footerMain>
18 <div class="hidden flex-wrap items-center gap-3 sm:flex">
19 <Badge type="splitted" color="primary">
20 <template #iconLeft>
21 <Icon :name="TargetIcon" />
22 </template>
23 <template #label>Match count</template>
24 <template #value>{{ entity.match_count }}</template>
25 </Badge>
26
27 <Badge v-if="entity.last_matched_at" type="splitted" color="primary">
28 <template #iconLeft>
29 <Icon :name="TimeIcon" />
30 </template>
31 <template #label>Last match</template>
32 <template #value>
33 {{ formatDate(entity.last_matched_at, dFormats.datetimesec) }}
34 </template>
35 </Badge>
36
37 <Badge v-if="entity.customer_code" type="splitted">
38 <template #label>Customer</template>
39 <template #value>
40 <code
41 class="text-primary cursor-pointer leading-none"
42 @click.stop="routeCustomer({ code: entity.customer_code }).navigate()"
43 >
44 #{{ entity.customer_code }}
45 <Icon :name="LinkIcon" :size="14" class="relative top-0.5" />
46 </code>
47 </template>
48 </Badge>
49 </div>
50 </template>
51
52 <template #footerExtra>
53 <div class="flex items-center gap-3">
54 <div class="block sm:hidden">
55 <ExclusionRuleStatusToggler
56 :entity
57 @loading="updatingStatus = $event"
58 @updated="setStatus($event)"
59 />
60 </div>
61
62 <n-button size="small" @click.stop="openDetails()">
63 <template #icon>
64 <Icon :name="DetailsIcon" />
65 </template>
66 Details
67 </n-button>
68 </div>
69 </template>
70 </CardEntity>
71
72 <n-modal
73 v-model:show="showDetails"
74 :style="{ maxWidth: 'min(850px, 90vw)', minHeight: 'min(480px, 90vh)', overflow: 'hidden' }"
75 display-directive="show"
76 >
77 <n-card
78 content-class="flex flex-col p-0!"
79 :title="`#${entity.id} • ${entity.name}`"
80 closable
81 :bordered="false"
82 segmented
83 role="modal"
84 @close="closeDetails()"
85 >
86 <n-spin :show="loadingDelete">
87 <ExclusionRuleForm v-if="editing" :entity class="p-6" @submitted="updateEntity($event)">
88 <template #additionalActions>
89 <n-button v-if="editing" @click="editing = false">Close</n-button>
90 </template>
91 </ExclusionRuleForm>
92 <ExclusionRuleDetails v-else :entity />
93 </n-spin>
94
95 <template #footer>
96 <div v-if="!editing" class="flex items-center justify-end gap-4">
97 <n-button text type="error" ghost :loading="loadingDelete" @click="handleDelete">
98 <template #icon>
99 <Icon :name="DeleteIcon" :size="15" />
100 </template>
101 Delete
102 </n-button>
103 <n-button :disabled="loadingDelete" @click="editing = true">
104 <template #icon>
105 <Icon :name="EditIcon" :size="14" />
106 </template>
107 Edit
108 </n-button>
109 </div>
110 </template>
111 </n-card>
112 </n-modal>
113 </div>
114 </template>
115
116 <script setup lang="ts">
117 import type { ExclusionRule } from "@/types/incidentManagement/exclusionRules.d"
118 import { NButton, NCard, NModal, NSpin, useDialog, useMessage } from "naive-ui"
119 import { computed, h, ref, toRefs } from "vue"
120 import Api from "@/api"
121 import Badge from "@/components/common/Badge.vue"
122 import CardEntity from "@/components/common/cards/CardEntity.vue"
123 import Icon from "@/components/common/Icon.vue"
124 import { useNavigation } from "@/composables/useNavigation"
125 import { useSettingsStore } from "@/stores/settings"
126 import { formatDate } from "@/utils/format"
127 import ExclusionRuleDetails from "./ExclusionRuleDetails.vue"
128 import ExclusionRuleForm from "./ExclusionRuleForm.vue"
129 import ExclusionRuleStatusToggler from "./ExclusionRuleStatusToggler.vue"
130
131 const props = defineProps<{
132 entity: ExclusionRule
133 embedded?: boolean
134 }>()
135
136 const emit = defineEmits<{
137 (e: "deleted"): void
138 (e: "updated"): void
139 }>()
140
141 const { entity, embedded } = toRefs(props)
142
143 const TimeIcon = "carbon:time"
144 const LinkIcon = "carbon:launch"
145 const DetailsIcon = "carbon:settings-adjust"
146 const DeleteIcon = "ph:trash"
147 const EditIcon = "uil:edit-alt"
148 const TargetIcon = "zondicons:target"
149
150 const message = useMessage()
151 const dialog = useDialog()
152 const updatingStatus = ref(false)
153 const loadingDelete = ref(false)
154 const loading = computed(() => updatingStatus.value || loadingDelete.value)
155 const editing = ref(false)
156 const showDetails = ref(false)
157 const { routeCustomer } = useNavigation()
158 const dFormats = useSettingsStore().dateFormat
159
160 function openDetails() {
161 showDetails.value = true
162 }
163
164 function closeDetails() {
165 showDetails.value = false
166 }
167
168 function setStatus(value: ExclusionRule) {
169 entity.value.enabled = value.enabled
170 }
171
172 function updateEntity(value: ExclusionRule) {
173 entity.value.name = value.name
174 entity.value.description = value.description
175 entity.value.channel = value.channel
176 entity.value.title = value.title
177 entity.value.field_matches = value.field_matches
178 entity.value.enabled = value.enabled
179 entity.value.customer_code = value.customer_code
180
181 editing.value = false
182 emit("updated")
183 }
184
185 function deleteExclusionRules() {
186 loadingDelete.value = true
187
188 Api.incidentManagement.exclusionRules
189 .deleteExclusionRules(entity.value.id)
190 .then(res => {
191 if (res.data.success) {
192 showDetails.value = false
193 emit("deleted")
194 } else {
195 message.warning(res.data?.message || "An error occurred. Please try again later.")
196 }
197 })
198 .catch(err => {
199 message.error(err.response?.data?.message || "An error occurred. Please try again later.")
200 })
201 .finally(() => {
202 loadingDelete.value = false
203 })
204 }
205
206 function handleDelete() {
207 dialog.warning({
208 title: "Confirm",
209 content: () =>
210 h("div", {
211 innerHTML: `Are you sure you want to delete the Exclusion Rule: <strong>${entity.value.name}</strong> ?`
212 }),
213 positiveText: "Yes I'm sure",
214 negativeText: "Cancel",
215 onPositiveClick: () => {
216 deleteExclusionRules()
217 },
218 onNegativeClick: () => {
219 message.info("Delete canceled")
220 }
221 })
222 }
223 </script>