Bug 32991: Improve our Dialog component
[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" 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="agreements.length" class="page-section">
36             <table :id="table_id"></table>
37         </div>
38         <div v-else-if="initialized" 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 { setWarning, 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             setWarning,
72             setMessage,
73         }
74     },
75     data: function () {
76         return {
77             fp_config: flatpickr_defaults,
78             agreements: [],
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.getAgreements().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 getAgreements() {
110             const client = APIClient.erm
111             await client.agreements.getAll().then(
112                 agreements => {
113                     this.agreements = agreements
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) {
128             this.setWarning(this.$__("Are you sure you want to remove this agreement?"), () => {
129                 const client = APIClient.erm
130                 client.agreements.delete(agreement_id).then(
131                     success => {
132                         this.setMessage(this.$__("Agreement deleted"))
133                         this.refresh_table()
134                     },
135                     error => {}
136                 )
137             })
138         },
139         select_agreement: function (agreement_id) {
140             this.$emit("select-agreement", agreement_id)
141             this.$emit("close")
142         },
143         refresh_table: function(){
144             $("#" + this.table_id)
145                 .DataTable()
146                 .ajax.url(this.datatable_url)
147                 .draw()
148         },
149         filter_table: async function () {
150             if (this.before_route_entered) {
151                 let new_route = build_url(
152                     "/cgi-bin/koha/erm/agreements",
153                     this.filters
154                 )
155                 this.$router.push(new_route)
156             }
157             if (this.filters.by_expired) {
158                 if (!this.filters.max_expiration_date)
159                     this.filters.max_expiration_date = new Date()
160                         .toISOString()
161                         .substring(0, 10)
162             }
163             this.refresh_table()
164         },
165         table_url: function () {},
166         build_datatable: function () {
167             let show_agreement = this.show_agreement
168             let edit_agreement = this.edit_agreement
169             let delete_agreement = this.delete_agreement
170             let select_agreement = this.select_agreement
171             let get_lib_from_av = this.get_lib_from_av
172             let map_av_dt_filter = this.map_av_dt_filter
173             let datatable_url = this.datatable_url
174             let default_search = this.$route.query.q
175             let actions = this.before_route_entered ? "edit_delete" : "select"
176             let filters = this.filters
177             let table_id = this.table_id
178             let logged_in_user = this.logged_in_user
179
180             window["vendors"] = this.vendors.map(e => {
181                 e["_id"] = e["id"]
182                 e["_str"] = e["name"]
183                 return e
184             })
185             let vendors_map = this.vendors.reduce((map, e) => {
186                 map[e.id] = e
187                 return map
188             }, {})
189             let avs = [
190                 "av_agreement_statuses",
191                 "av_agreement_closure_reasons",
192                 "av_agreement_renewal_priorities",
193             ]
194             avs.forEach(function (av_cat) {
195                 window[av_cat] = map_av_dt_filter(av_cat)
196             })
197
198             window["av_agreement_is_perpetual"] = [
199                 { _id: 0, _str: _("No") },
200                 { _id: 1, _str: _("Yes") },
201             ]
202
203             let additional_filters = {
204                 "user_roles.user_id": function () {
205                     return filters.by_mine ? logged_in_user.borrowernumber : ""
206                 },
207             }
208             const table = $("#" + table_id).kohaTable(
209                 {
210                     ajax: {
211                         url: datatable_url,
212                     },
213                     embed: ["user_roles"],
214                     order: [[0, "asc"]],
215                     autoWidth: false,
216                     search: { search: default_search },
217                     columnDefs: [
218                         {
219                             targets: [0, 2],
220                             render: function (data, type, row, meta) {
221                                 if (type == "display") {
222                                     return escape_str(data)
223                                 }
224                                 return data
225                             },
226                         },
227                     ],
228                     columns: [
229                         {
230                             title: __("Name"),
231                             data: "me.agreement_id:me.name",
232                             searchable: true,
233                             orderable: true,
234                             render: function (data, type, row, meta) {
235                                 // Rendering done in drawCallback
236                                 return ""
237                             },
238                         },
239                         {
240                             title: __("Vendor"),
241                             data: "vendor_id",
242                             searchable: true,
243                             orderable: true,
244                             render: function (data, type, row, meta) {
245                                 return row.vendor_id != undefined
246                                     ? escape_str(
247                                           vendors_map[row.vendor_id].name
248                                       )
249                                     : ""
250                             },
251                         },
252                         {
253                             title: __("Description"),
254                             data: "description",
255                             searchable: true,
256                             orderable: true,
257                         },
258                         {
259                             title: __("Status"),
260                             data: "status",
261                             searchable: true,
262                             orderable: true,
263                             render: function (data, type, row, meta) {
264                                 return escape_str(
265                                     get_lib_from_av(
266                                         "av_agreement_statuses",
267                                         row.status
268                                     )
269                                 )
270                             },
271                         },
272                         {
273                             title: __("Closure reason"),
274                             data: "closure_reason",
275                             searchable: true,
276                             orderable: true,
277                             render: function (data, type, row, meta) {
278                                 return escape_str(
279                                     get_lib_from_av(
280                                         "av_agreement_closure_reasons",
281                                         row.closure_reason
282                                     )
283                                 )
284                             },
285                         },
286                         {
287                             title: __("Is perpetual"),
288                             data: "is_perpetual",
289                             searchable: true,
290                             orderable: true,
291                             render: function (data, type, row, meta) {
292                                 return escape_str(
293                                     row.is_perpetual ? _("Yes") : _("No")
294                                 )
295                             },
296                         },
297                         {
298                             title: __("Renewal priority"),
299                             data: "renewal_priority",
300                             searchable: true,
301                             orderable: true,
302                             render: function (data, type, row, meta) {
303                                 return escape_str(
304                                     get_lib_from_av(
305                                         "av_agreement_renewal_priorities",
306                                         row.renewal_priority
307                                     )
308                                 )
309                             },
310                         },
311                         {
312                             title: __("Actions"),
313                             data: function (row, type, val, meta) {
314                                 return '<div class="actions"></div>'
315                             },
316                             className: "actions noExport",
317                             searchable: false,
318                             orderable: false,
319                         },
320                     ],
321                     drawCallback: function (settings) {
322                         var api = new $.fn.dataTable.Api(settings)
323
324                         if (actions == "edit_delete") {
325                             $.each(
326                                 $(this).find("td .actions"),
327                                 function (index, e) {
328                                     let tr = $(this).parent().parent()
329                                     let agreement_id = api
330                                         .row(tr)
331                                         .data().agreement_id
332                                     let editButton = createVNode(
333                                         "a",
334                                         {
335                                             class: "btn btn-default btn-xs",
336                                             role: "button",
337                                             onClick: () => {
338                                                 edit_agreement(agreement_id)
339                                             },
340                                         },
341                                         [
342                                             createVNode("i", {
343                                                 class: "fa fa-pencil",
344                                                 "aria-hidden": "true",
345                                             }),
346                                             __("Edit"),
347                                         ]
348                                     )
349
350                                     let deleteButton = createVNode(
351                                         "a",
352                                         {
353                                             class: "btn btn-default btn-xs",
354                                             role: "button",
355                                             onClick: () => {
356                                                 delete_agreement(agreement_id)
357                                             },
358                                         },
359                                         [
360                                             createVNode("i", {
361                                                 class: "fa fa-trash",
362                                                 "aria-hidden": "true",
363                                             }),
364                                             __("Delete"),
365                                         ]
366                                     )
367
368                                     let n = createVNode("span", {}, [
369                                         editButton,
370                                         " ",
371                                         deleteButton,
372                                     ])
373                                     render(n, e)
374                                 }
375                             )
376                         } else {
377                             $.each(
378                                 $(this).find("td .actions"),
379                                 function (index, e) {
380                                     let tr = $(this).parent().parent()
381                                     let agreement_id = api
382                                         .row(tr)
383                                         .data().agreement_id
384                                     let selectButton = createVNode(
385                                         "a",
386                                         {
387                                             class: "btn btn-default btn-xs",
388                                             role: "button",
389                                             onClick: () => {
390                                                 select_agreement(agreement_id)
391                                             },
392                                         },
393                                         [
394                                             createVNode("i", {
395                                                 class: "fa fa-check",
396                                                 "aria-hidden": "true",
397                                             }),
398                                             __("Select"),
399                                         ]
400                                     )
401
402                                     let n = createVNode("span", {}, [
403                                         selectButton,
404                                     ])
405                                     render(n, e)
406                                 }
407                             )
408                         }
409
410                         $.each(
411                             $(this).find("tbody tr td:first-child"),
412                             function (index, e) {
413                                 let tr = $(this).parent()
414                                 let row = api.row(tr).data()
415                                 if (!row) return // Happen if the table is empty
416                                 let n = createVNode(
417                                     "a",
418                                     {
419                                         role: "button",
420                                         onClick: () => {
421                                             show_agreement(row.agreement_id)
422                                         },
423                                     },
424                                     `${row.name} (#${row.agreement_id})`
425                                 )
426                                 render(n, e)
427                             }
428                         )
429                     },
430                     preDrawCallback: function (settings) {
431                         $("#" + table_id)
432                             .find("thead th")
433                             .eq(1)
434                             .attr("data-filter", "vendors")
435                         $("#" + table_id)
436                             .find("thead th")
437                             .eq(3)
438                             .attr("data-filter", "av_agreement_statuses")
439                         $("#" + table_id)
440                             .find("thead th")
441                             .eq(4)
442                             .attr("data-filter", "av_agreement_closure_reasons")
443                         $("#" + table_id)
444                             .find("thead th")
445                             .eq(5)
446                             .attr("data-filter", "av_agreement_is_perpetual")
447                         $("#" + table_id)
448                             .find("thead th")
449                             .eq(6)
450                             .attr(
451                                 "data-filter",
452                                 "av_agreement_renewal_priorities"
453                             )
454                     },
455                 },
456                 agreement_table_settings,
457                 1,
458                 additional_filters
459             )
460         },
461     },
462     mounted() {
463         if (!this.building_table) {
464             this.building_table = true
465             this.getAgreements().then(() => this.build_datatable())
466         }
467     },
468     components: { flatPickr, Toolbar },
469     name: "AgreementsList",
470     emits: ["select-agreement", "close"],
471 }
472 </script>
473
474 <style scoped>
475 #agreement_list {
476     display: table;
477 }
478 .filters > label[for="by_mine_filter"],
479 .filters > input[type="checkbox"],
480 .filters > input[type="button"] {
481     margin-left: 1rem;
482 }
483 </style>