1<template>
2 <div
3 class="grid grid-cols-6 items-center gap-4 cursor-pointer hover:bg-surface-sidebar rounded-4"
4 >
5 <div
6 @click="slaActiveScreen = { screen: 'view', data: data, fetchData: true }"
7 class="w-full ps-2 col-span-5 flex flex-col justify-center h-14"
8 >
9 <div class="text-base-medium text-ink-gray-7 flex items-center gap-2">
10 {{ data.name }}
11 <Badge v-if="data.default_sla" color="gray" size="sm">Default</Badge>
12 </div>
13 <div
14 v-if="data.description && data.description.length > 0"
15 class="text-sm w-full text-ink-gray-5 mt-1 truncate"
16 >
17 {{ data.description }}
18 </div>
19 </div>
20 <div class="flex justify-between items-center w-full pe-2">
21 <div>
22 <Switch
23 size="sm"
24 :modelValue="Boolean(data.enabled)"
25 @update:modelValue="onToggle"
26 />
27 </div>
28 <div>
29 <Dropdown
30 align="end"
31 :options="dropdownOptions"
32 @update:open="(open) => open && (isConfirmingDelete = false)"
33 >
34 <Button icon="lucide-more-horizontal" variant="ghost" />
35 </Dropdown>
36 </div>
37 </div>
38 </div>
39 <Dialog
40 :title="__('Duplicate SLA Policy')"
41 v-model:open="duplicateDialog.show"
42 >
43 <template #default>
44 <div class="flex flex-col gap-4">
45 <FormControl
46 :label="__('New SLA Policy Name')"
47 type="text"
48 v-model="duplicateDialog.newName"
49 />
50 </div>
51 </template>
52 <template #actions>
53 <div class="flex gap-2 justify-end">
54 <Button
55 variant="subtle"
56 :label="__('Close')"
57 @click="duplicateDialog.show = false"
58 />
59 <Button variant="solid" :label="__('Duplicate')" @click="duplicate()" />
60 </div>
61 </template>
62 </Dialog>
63</template>
64<script setup lang="ts">
65import {
66 Switch,
67 Button,
68 createResource,
69 toast,
70 Dialog,
71 Badge,
72 Dropdown,
73} from "frappe-ui";
74import { ref, inject } from "vue";
75import { slaActiveScreen } from "@/stores/sla";
76import { ConfirmDelete } from "@/utils";
77import { __ } from "@/translation";
78import { SlaPolicyListResourceSymbol } from "@/types";
79import { ODServiceLevelAgreement } from "@/types/doctypes";
80
81const slaPolicyList = inject(SlaPolicyListResourceSymbol);
82
83const duplicateDialog = ref({
84 show: false,
85 newName: "",
86 name: "",
87});
88
89const props = defineProps({
90 data: {
91 type: Object,
92 required: true,
93 },
94});
95
96const isConfirmingDelete = ref(false);
97
98const dropdownOptions = [
99 {
100 label: __("Duplicate"),
101 onClick: () => {
102 duplicateDialog.value = {
103 show: true,
104 newName: props.data.name + " (Copy)",
105 name: props.data.name,
106 };
107 },
108 icon: "lucide-copy",
109 },
110 ...ConfirmDelete({
111 onConfirmDelete: () => deleteSla(),
112 isConfirmingDelete,
113 }),
114];
115
116const duplicate = () => {
117 createResource({
118 url: "frappe.client.get",
119 params: {
120 doctype: "OD Service Level Agreement",
121 name: duplicateDialog.value.name,
122 },
123 onSuccess: (data: ODServiceLevelAgreement) => {
124 createResource({
125 url: "frappe.client.insert",
126 params: {
127 doc: {
128 ...data,
129 default_sla: false,
130 service_level: duplicateDialog.value.newName,
131 name: duplicateDialog.value.newName,
132 },
133 },
134 auto: true,
135 onSuccess(newSlaPolicyData: ODServiceLevelAgreement) {
136 slaPolicyList?.reload();
137 toast.success(__("SLA policy duplicated successfully."));
138 duplicateDialog.value = {
139 show: false,
140 newName: "",
141 name: "",
142 };
143 setTimeout(() => {
144 slaActiveScreen.value = {
145 screen: "view",
146 data: newSlaPolicyData,
147 fetchData: true,
148 };
149 }, 250);
150 },
151 });
152 },
153 auto: true,
154 });
155};
156
157const deleteSla = () => {
158 if (!isConfirmingDelete.value) {
159 isConfirmingDelete.value = true;
160 return;
161 }
162
163 slaPolicyList?.delete.submit(props.data.name, {
164 onSuccess: () => {
165 toast.success(__("SLA policy deleted successfully."));
166 },
167 });
168};
169
170const onToggle = () => {
171 slaPolicyList?.setValue.submit(
172 {
173 name: props.data.name,
174 enabled: !props.data.enabled,
175 },
176 {
177 onSuccess: () => {
178 toast.success(__("SLA policy status updated successfully."));
179 },
180 }
181 );
182};
183</script>
184