1<template>
2 <div class="rounded-5 border px-2 border-outline-gray-2 text-sm">
3 <div
4 class="grid p-2 px-4 items-center"
5 :style="{
6 gridTemplateColumns,
7 }"
8 v-if="slaData.priorities?.length !== 0"
9 >
10 <div
11 v-for="column in columns"
12 :key="column.key"
13 class="text-ink-gray-5 overflow-hidden whitespace-nowrap text-ellipsis"
14 :class="{
15 'ms-2':
16 column.key === 'priority' ||
17 column.key === 'response_time' ||
18 column.key === 'resolution_time',
19 }"
20 >
21 {{ column.label }}
22 <span v-if="column.isRequired" class="text-ink-red-6">*</span>
23 </div>
24 </div>
25 <hr v-if="slaData.priorities?.length !== 0" />
26 <SlaPriorityListItem
27 v-for="(row, index) in slaData.priorities"
28 :key="row.priority"
29 :row="row"
30 :columns="columns"
31 :isLast="index === slaData.priorities.length - 1"
32 />
33 <div
34 v-if="slaData.priorities?.length === 0"
35 class="text-center p-4 text-ink-gray-5"
36 >
37 No priorities in the list
38 </div>
39 </div>
40 <div
41 class="flex items-center justify-between mt-2.5"
42 v-if="
43 slaData.priorities.length !== priorityOptions.length ||
44 slaDataErrors.default_priority ||
45 slaDataErrors.priorities
46 "
47 >
48 <div>
49 <Button
50 v-if="slaData.priorities.length !== priorityOptions.length"
51 variant="subtle"
52 label="Add row"
53 @click="addRow"
54 icon-left="lucide-plus"
55 />
56 </div>
57 <ErrorMessage
58 :message="slaDataErrors.default_priority || slaDataErrors.priorities"
59 />
60 </div>
61</template>
62
63<script setup lang="ts">
64import {
65 slaActiveScreen,
66 slaData,
67 slaDataErrors,
68 validateSlaData,
69} from "@/stores/sla";
70import { PRIORITY_DISPLAY_ORDER } from "@/stores/ticketPriority";
71import { getGridTemplateColumnsForTable } from "@/utils";
72import { watchDebounced } from "@vueuse/core";
73import { Button, createResource, toast } from "frappe-ui";
74import { computed, provide, reactive } from "vue";
75import SlaPriorityListItem from "./SlaPriorityListItem.vue";
76
77createResource({
78 url: "frappe.client.get_list",
79 params: {
80 doctype: "OD Ticket Priority",
81 fields: ["name", "level"],
82 filters: {
83 disabled: 0,
84 },
85 },
86 auto: true,
87 onSuccess(data) {
88 const ranked = [...data].sort(
89 (a, b) =>
90 (PRIORITY_DISPLAY_ORDER[a.level] ?? 99) -
91 (PRIORITY_DISPLAY_ORDER[b.level] ?? 99)
92 );
93 priorityOptions.push(
94 ...ranked.map((p) => {
95 return {
96 label: p.name,
97 value: p.name,
98 };
99 })
100 );
101 if (!slaActiveScreen.value.data) {
102 slaData.value.priorities = priorityOptions.map((p, index) => {
103 return {
104 priority: p.value,
105 resolution_time: 60 * 60,
106 response_time: 60 * 60,
107 default_priority: index === 0,
108 };
109 });
110 }
111 },
112});
113
114const priorityOptions = reactive([]);
115
116provide("priorityOptions", priorityOptions);
117
118const addRow = () => {
119 const existingPriorities = slaData.value.priorities.map((p) => p.priority);
120 const availablePriorities = priorityOptions.filter(
121 (p) => !existingPriorities.includes(p.value)
122 );
123
124 if (availablePriorities.length === 0) {
125 toast.error("All available priorities have already been added");
126 return;
127 }
128
129 const newPriority = availablePriorities[0].value;
130
131 slaData.value.priorities.push({
132 priority: newPriority,
133 resolution_time: 60 * 60,
134 response_time: 60 * 60,
135 default_priority: slaData.value.priorities.length === 0,
136 });
137};
138
139const columns = computed(() => [
140 {
141 label: "Priority",
142 key: "priority",
143 isRequired: true,
144 },
145 {
146 label: "Default priority",
147 key: "default_priority",
148 isRequired: true,
149 },
150 {
151 label: "First response time",
152 key: "response_time",
153 isRequired: true,
154 },
155 {
156 label: "Resolution time",
157 key: "resolution_time",
158 isRequired: true,
159 },
160 // slaData.value.apply_sla_for_resolution && {
161 // label: "Resolution time",
162 // key: "resolution_time",
163 // isRequired: Boolean(slaData.value.apply_sla_for_resolution),
164 // },
165 // ].filter((c) => c)
166]);
167
168const gridTemplateColumns = computed(() => {
169 // return getGridTemplateColumnsForTable(columns.value.filter((c) => c));
170 return getGridTemplateColumnsForTable(columns.value);
171});
172
173provide("gridTemplateColumns", gridTemplateColumns);
174
175watchDebounced(
176 () => [...slaData.value.priorities],
177 () => {
178 validateSlaData("priorities");
179 },
180 { deep: true, debounce: 300 }
181);
182</script>
183