Bug 32030: (follow-up) Fix date handling - conflicts with bug 30718
[koha.git] / koha-tmpl / intranet-tmpl / prog / js / vue / components / ERM / AgreementsList.vue
1 <template>
2     <div v-if="!initialized">{{ $__("Loading") }}</div>
3     <div v-else-if="agreements" id="agreements_list">
4         <Toolbar v-if="before_route_entered" />
5         <fieldset v-if="agreements.length">
6             <label for="expired_filter">{{ $__("Filter by expired") }}:</label>
7             <input
8                 type="checkbox"
9                 id="expired_filter"
10                 v-model="filters.by_expired"
11                 @keyup.enter="filter_table"
12             />
13             {{ $__("on") }}
14             <flat-pickr
15                 id="max_expiration_date_filter"
16                 v-model="filters.max_expiration_date"
17                 :config="fp_config"
18             />
19
20             <input
21                 @click="filter_table"
22                 id="filter_table"
23                 type="button"
24                 :value="$__('Filter')"
25             />
26         </fieldset>
27         <table v-if="agreements.length" :id="table_id"></table>
28         <div v-else-if="initialized" class="dialog message">
29             {{ $__("There are no agreements defined") }}
30         </div>
31     </div>
32 </template>
33
34 <script>
35 import flatPickr from "vue-flatpickr-component"
36 import Toolbar from "./AgreementsToolbar.vue"
37 import { inject, createVNode, render } from "vue"
38 import { storeToRefs } from "pinia"
39 import { fetchAgreements } from "../../fetch"
40 import { useDataTable, build_url } from "../../composables/datatables"
41
42 export default {
43     setup() {
44         const vendorStore = inject("vendorStore")
45         const { vendors } = storeToRefs(vendorStore)
46
47         const AVStore = inject("AVStore")
48         const { get_lib_from_av, map_av_dt_filter } = AVStore
49
50         const table_id = "agreement_list"
51         useDataTable(table_id)
52
53         return {
54             vendors,
55             get_lib_from_av,
56             map_av_dt_filter,
57             table_id,
58         }
59     },
60     data: function () {
61         return {
62             fp_config: flatpickr_defaults,
63             agreements: [],
64             initialized: false,
65             filters: {
66                 by_expired: this.$route.query.by_expired || false,
67                 max_expiration_date:
68                     this.$route.query.max_expiration_date || "",
69             },
70             before_route_entered: false,
71             building_table: false,
72         }
73     },
74     beforeRouteEnter(to, from, next) {
75         next(vm => {
76             vm.before_route_entered = true // FIXME This is ugly, but we need to distinguish when it's used as main component or child component (from EHoldingsEBSCOPAckagesShow for instance)
77             if (!vm.building_table) {
78                 vm.building_table = true
79                 vm.getAgreements().then(() => vm.build_datatable())
80             }
81         })
82     },
83     computed: {
84         datatable_url() {
85             let url = "/api/v1/erm/agreements"
86             if (this.filters.by_expired)
87                 url +=
88                     "?max_expiration_date=" + this.filters.max_expiration_date
89             return url
90         },
91     },
92     methods: {
93         async getAgreements() {
94             const agreements = await fetchAgreements()
95             this.agreements = agreements
96             this.initialized = true
97         },
98         show_agreement: function (agreement_id) {
99             this.$router.push("/cgi-bin/koha/erm/agreements/" + agreement_id)
100         },
101         edit_agreement: function (agreement_id) {
102             this.$router.push(
103                 "/cgi-bin/koha/erm/agreements/edit/" + agreement_id
104             )
105         },
106         delete_agreement: function (agreement_id) {
107             this.$router.push(
108                 "/cgi-bin/koha/erm/agreements/delete/" + agreement_id
109             )
110         },
111         select_agreement: function (agreement_id) {
112             this.$emit("select-agreement", agreement_id)
113             this.$emit("close")
114         },
115         filter_table: async function () {
116             let new_route = build_url(
117                 "/cgi-bin/koha/erm/agreements",
118                 this.filters
119             )
120             this.$router.push(new_route)
121             if (this.filters.by_expired) {
122                 if (!this.filters.max_expiration_date)
123                     this.filters.max_expiration_date = new Date()
124                         .toISOString()
125                         .substring(0, 10)
126             }
127             $("#" + this.table_id)
128                 .DataTable()
129                 .ajax.url(this.datatable_url)
130                 .draw()
131         },
132         table_url: function () {},
133         build_datatable: function () {
134             let show_agreement = this.show_agreement
135             let edit_agreement = this.edit_agreement
136             let delete_agreement = this.delete_agreement
137             let select_agreement = this.select_agreement
138             let get_lib_from_av = this.get_lib_from_av
139             let map_av_dt_filter = this.map_av_dt_filter
140             let datatable_url = this.datatable_url
141             let default_search = this.$route.query.q
142             let actions = this.before_route_entered ? "edit_delete" : "select"
143             let table_id = this.table_id
144
145             window["vendors"] = this.vendors.map(e => {
146                 e["_id"] = e["id"]
147                 e["_str"] = e["name"]
148                 return e
149             })
150             let vendors_map = this.vendors.reduce((map, e) => {
151                 map[e.id] = e
152                 return map
153             }, {})
154             let avs = [
155                 "av_agreement_statuses",
156                 "av_agreement_closure_reasons",
157                 "av_agreement_renewal_priorities",
158             ]
159             avs.forEach(function (av_cat) {
160                 window[av_cat] = map_av_dt_filter(av_cat)
161             })
162
163             window["av_agreement_is_perpetual"] = [
164                 { _id: 0, _str: _("No") },
165                 { _id: 1, _str: _("Yes") },
166             ]
167
168             const table = $("#" + table_id).kohaTable(
169                 {
170                     ajax: {
171                         url: datatable_url,
172                     },
173                     order: [[0, "asc"]],
174                     autoWidth: false,
175                     search: { search: default_search },
176                     columnDefs: [
177                         {
178                             targets: [0, 2],
179                             render: function (data, type, row, meta) {
180                                 if (type == "display") {
181                                     return escape_str(data)
182                                 }
183                                 return data
184                             },
185                         },
186                     ],
187                     columns: [
188                         {
189                             title: __("Name"),
190                             data: "me.agreement_id:me.name",
191                             searchable: true,
192                             orderable: true,
193                             render: function (data, type, row, meta) {
194                                 // Rendering done in drawCallback
195                                 return ""
196                             },
197                         },
198                         {
199                             title: __("Vendor"),
200                             data: "vendor_id",
201                             searchable: true,
202                             orderable: true,
203                             render: function (data, type, row, meta) {
204                                 return row.vendor_id != undefined
205                                     ? escape_str(
206                                           vendors_map[row.vendor_id].name
207                                       )
208                                     : ""
209                             },
210                         },
211                         {
212                             title: __("Description"),
213                             data: "description",
214                             searchable: true,
215                             orderable: true,
216                         },
217                         {
218                             title: __("Status"),
219                             data: "status",
220                             searchable: true,
221                             orderable: true,
222                             render: function (data, type, row, meta) {
223                                 return escape_str(
224                                     get_lib_from_av(
225                                         "av_agreement_statuses",
226                                         row.status
227                                     )
228                                 )
229                             },
230                         },
231                         {
232                             title: __("Closure reason"),
233                             data: "closure_reason",
234                             searchable: true,
235                             orderable: true,
236                             render: function (data, type, row, meta) {
237                                 return escape_str(
238                                     get_lib_from_av(
239                                         "av_agreement_closure_reasons",
240                                         row.closure_reason
241                                     )
242                                 )
243                             },
244                         },
245                         {
246                             title: __("Is perpetual"),
247                             data: "is_perpetual",
248                             searchable: true,
249                             orderable: true,
250                             render: function (data, type, row, meta) {
251                                 return escape_str(
252                                     row.is_perpetual ? _("Yes") : _("No")
253                                 )
254                             },
255                         },
256                         {
257                             title: __("Renewal priority"),
258                             data: "renewal_priority",
259                             searchable: true,
260                             orderable: true,
261                             render: function (data, type, row, meta) {
262                                 return escape_str(
263                                     get_lib_from_av(
264                                         "av_agreement_renewal_priorities",
265                                         row.renewal_priority
266                                     )
267                                 )
268                             },
269                         },
270                         {
271                             title: __("Actions"),
272                             data: function (row, type, val, meta) {
273                                 return '<div class="actions"></div>'
274                             },
275                             className: "actions noExport",
276                             searchable: false,
277                             orderable: false,
278                         },
279                     ],
280                     drawCallback: function (settings) {
281                         var api = new $.fn.dataTable.Api(settings)
282
283                         if (actions == "edit_delete") {
284                             $.each(
285                                 $(this).find("td .actions"),
286                                 function (index, e) {
287                                     let tr = $(this).parent().parent()
288                                     let agreement_id = api
289                                         .row(tr)
290                                         .data().agreement_id
291                                     let editButton = createVNode(
292                                         "a",
293                                         {
294                                             class: "btn btn-default btn-xs",
295                                             role: "button",
296                                             onClick: () => {
297                                                 edit_agreement(agreement_id)
298                                             },
299                                         },
300                                         [
301                                             createVNode("i", {
302                                                 class: "fa fa-pencil",
303                                                 "aria-hidden": "true",
304                                             }),
305                                             __("Edit"),
306                                         ]
307                                     )
308
309                                     let deleteButton = createVNode(
310                                         "a",
311                                         {
312                                             class: "btn btn-default btn-xs",
313                                             role: "button",
314                                             onClick: () => {
315                                                 delete_agreement(agreement_id)
316                                             },
317                                         },
318                                         [
319                                             createVNode("i", {
320                                                 class: "fa fa-trash",
321                                                 "aria-hidden": "true",
322                                             }),
323                                             __("Delete"),
324                                         ]
325                                     )
326
327                                     let n = createVNode("span", {}, [
328                                         editButton,
329                                         " ",
330                                         deleteButton,
331                                     ])
332                                     render(n, e)
333                                 }
334                             )
335                         } else {
336                             $.each(
337                                 $(this).find("td .actions"),
338                                 function (index, e) {
339                                     let tr = $(this).parent().parent()
340                                     let agreement_id = api
341                                         .row(tr)
342                                         .data().agreement_id
343                                     let selectButton = createVNode(
344                                         "a",
345                                         {
346                                             class: "btn btn-default btn-xs",
347                                             role: "button",
348                                             onClick: () => {
349                                                 select_agreement(agreement_id)
350                                             },
351                                         },
352                                         [
353                                             createVNode("i", {
354                                                 class: "fa fa-check",
355                                                 "aria-hidden": "true",
356                                             }),
357                                             __("Select"),
358                                         ]
359                                     )
360
361                                     let n = createVNode("span", {}, [
362                                         selectButton,
363                                     ])
364                                     render(n, e)
365                                 }
366                             )
367                         }
368
369                         $.each(
370                             $(this).find("tbody tr td:first-child"),
371                             function (index, e) {
372                                 let tr = $(this).parent()
373                                 let row = api.row(tr).data()
374                                 if (!row) return // Happen if the table is empty
375                                 let n = createVNode(
376                                     "a",
377                                     {
378                                         role: "button",
379                                         onClick: () => {
380                                             show_agreement(row.agreement_id)
381                                         },
382                                     },
383                                     `${row.name} (#${row.agreement_id})`
384                                 )
385                                 render(n, e)
386                             }
387                         )
388                     },
389                     preDrawCallback: function (settings) {
390                         $("#" + table_id)
391                             .find("thead th")
392                             .eq(1)
393                             .attr("data-filter", "vendors")
394                         $("#" + table_id)
395                             .find("thead th")
396                             .eq(3)
397                             .attr("data-filter", "av_agreement_statuses")
398                         $("#" + table_id)
399                             .find("thead th")
400                             .eq(4)
401                             .attr("data-filter", "av_agreement_closure_reasons")
402                         $("#" + table_id)
403                             .find("thead th")
404                             .eq(5)
405                             .attr("data-filter", "av_agreement_is_perpetual")
406                         $("#" + table_id)
407                             .find("thead th")
408                             .eq(6)
409                             .attr(
410                                 "data-filter",
411                                 "av_agreement_renewal_priorities"
412                             )
413                     },
414                 },
415                 agreement_table_settings,
416                 1
417             )
418         },
419     },
420     mounted() {
421         if (!this.building_table) {
422             this.building_table = true
423             this.getAgreements().then(() => this.build_datatable())
424         }
425     },
426     components: { flatPickr, Toolbar },
427     name: "AgreementsList",
428     emits: ["select-agreement", "close"],
429 }
430 </script>
431
432 <style scoped>
433 #agreement_list {
434     display: table;
435 }
436 </style>