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