Bug 32030: DT - Prevent wrong row to be used
[koha.git] / koha-tmpl / intranet-tmpl / prog / js / vue / components / ERM / AgreementsList.vue
1 <template>
2     <div v-if="!this.initialized">{{ $t("Loading") }}</div>
3     <div v-else-if="this.agreements" id="agreements_list">
4         <Toolbar v-if="before_route_entered" />
5         <table v-if="this.agreements.length" :id="table_id"></table>
6         <div v-else-if="this.initialized" class="dialog message">
7             {{ $t("There are no agreements defined") }}
8         </div>
9     </div>
10 </template>
11
12 <script>
13 import Toolbar from "./AgreementsToolbar.vue"
14 import { createVNode, render } from 'vue'
15 import { useVendorStore } from "../../stores/vendors"
16 import { useAVStore } from "../../stores/authorised_values"
17 import { storeToRefs } from "pinia"
18 import { fetchAgreements } from "../../fetch"
19 import { useDataTable } from "../../composables/datatables"
20
21 export default {
22     setup() {
23         const vendorStore = useVendorStore()
24         const { vendors } = storeToRefs(vendorStore)
25
26         const AVStore = useAVStore()
27         const { get_lib_from_av, map_av_dt_filter } = AVStore
28
29         const table_id = "agreement_list"
30         useDataTable(table_id)
31
32         return {
33             vendors,
34             get_lib_from_av,
35             map_av_dt_filter,
36             table_id,
37         }
38     },
39     data: function () {
40         return {
41             agreements: [],
42             initialized: false,
43             before_route_entered: false,
44             building_table: false,
45         }
46     },
47     beforeRouteEnter(to, from, next) {
48         next(vm => {
49             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)
50             if (!vm.building_table) {
51                 vm.building_table = true
52                 vm.getAgreements().then(() => vm.build_datatable())
53             }
54         })
55     },
56     methods: {
57         async getAgreements() {
58             const agreements = await fetchAgreements()
59             this.agreements = agreements
60             this.initialized = true
61         },
62         show_agreement: function (agreement_id) {
63             this.$router.push("/cgi-bin/koha/erm/agreements/" + agreement_id)
64         },
65         edit_agreement: function (agreement_id) {
66             this.$router.push("/cgi-bin/koha/erm/agreements/edit/" + agreement_id)
67         },
68         delete_agreement: function (agreement_id) {
69             this.$router.push("/cgi-bin/koha/erm/agreements/delete/" + agreement_id)
70         },
71         select_agreement: function (agreement_id) {
72             this.$emit('select-agreement', agreement_id)
73             this.$emit('close')
74         },
75         build_datatable: function () {
76             let show_agreement = this.show_agreement
77             let edit_agreement = this.edit_agreement
78             let delete_agreement = this.delete_agreement
79             let select_agreement = this.select_agreement
80             let get_lib_from_av = this.get_lib_from_av
81             let map_av_dt_filter = this.map_av_dt_filter
82             let default_search = this.$route.query.q
83             let actions = this.before_route_entered ? 'edit_delete' : 'select'
84             let table_id = this.table_id
85
86             window['vendors'] = this.vendors.map(e => {
87                 e['_id'] = e['id']
88                 e['_str'] = e['name']
89                 return e
90             })
91             let vendors_map = this.vendors.reduce((map, e) => {
92                 map[e.id] = e
93                 return map
94             }, {})
95             let avs = ['av_agreement_statuses', 'av_agreement_closure_reasons', 'av_agreement_renewal_priorities']
96             avs.forEach(function (av_cat) {
97                 window[av_cat] = map_av_dt_filter(av_cat)
98             })
99
100             window['av_agreement_is_perpetual'] = [{ _id: 0, _str: _('No') }, { _id: 1, _str: _("Yes") }]
101
102             const table = $("#" + table_id).kohaTable({
103                 ajax: {
104                     url: "/api/v1/erm/agreements",
105                 },
106                 order: [[0, "asc"]],
107                 autoWidth: false,
108                 search: { search: default_search },
109                 columnDefs: [{
110                     targets: [0, 2],
111                     render: function (data, type, row, meta) {
112                         if (type == 'display') {
113                             return escape_str(data)
114                         }
115                         return data
116                     }
117                 }],
118                 columns: [
119                     {
120                         title: __("Name"),
121                         data: "me.agreement_id:me.name",
122                         searchable: true,
123                         orderable: true,
124                         render: function (data, type, row, meta) {
125                             // Rendering done in drawCallback
126                             return ""
127                         }
128                     },
129                     {
130                         title: __("Vendor"),
131                         data: "vendor_id",
132                         searchable: true,
133                         orderable: true,
134                         render: function (data, type, row, meta) {
135                             return row.vendor_id != undefined ? escape_str(vendors_map[row.vendor_id].name) : ""
136                         }
137                     },
138                     {
139                         title: __("Description"),
140                         data: "description",
141                         searchable: true,
142                         orderable: true
143                     },
144                     {
145                         title: __("Status"),
146                         data: "status",
147                         searchable: true,
148                         orderable: true,
149                         render: function (data, type, row, meta) {
150                             return escape_str(get_lib_from_av("av_agreement_statuses", row.status))
151                         }
152                     },
153                     {
154                         title: __("Closure reason"),
155                         data: "closure_reason",
156                         searchable: true,
157                         orderable: true,
158                         render: function (data, type, row, meta) {
159                             return escape_str(get_lib_from_av("av_agreement_closure_reasons", row.closure_reason))
160                         }
161                     },
162                     {
163                         title: __("Is perpetual"),
164                         data: "is_perpetual",
165                         searchable: true,
166                         orderable: true,
167                         render: function (data, type, row, meta) {
168                             return escape_str(row.is_perpetual ? _("Yes") : _("No"))
169                         }
170                     },
171                     {
172                         title: __("Renewal priority"),
173                         data: "renewal_priority",
174                         searchable: true,
175                         orderable: true,
176                         render: function (data, type, row, meta) {
177                             return escape_str(get_lib_from_av("av_agreement_renewal_priorities", row.renewal_priority))
178                         }
179                     },
180                     {
181                         title: __("Actions"),
182                         data: function (row, type, val, meta) {
183                             return '<div class="actions"></div>'
184                         },
185                         className: "actions noExport",
186                         searchable: false,
187                         orderable: false
188                     }
189                 ],
190                 drawCallback: function (settings) {
191
192                     var api = new $.fn.dataTable.Api(settings)
193
194                     if (actions == 'edit_delete') {
195                         $.each($(this).find("td .actions"), function (index, e) {
196                             let tr = $(this).parent().parent()
197                             let agreement_id = api.row(tr).data().agreement_id
198                             let editButton = createVNode("a", {
199                                 class: "btn btn-default btn-xs", role: "button", onClick: () => {
200                                     edit_agreement(agreement_id)
201                                 }
202                             },
203                                 [createVNode("i", { class: "fa fa-pencil", 'aria-hidden': "true" }), __("Edit")])
204
205                             let deleteButton = createVNode("a", {
206                                 class: "btn btn-default btn-xs", role: "button", onClick: () => {
207                                     delete_agreement(agreement_id)
208                                 }
209                             },
210                                 [createVNode("i", { class: "fa fa-trash", 'aria-hidden': "true" }), __("Delete")])
211
212                             let n = createVNode('span', {}, [editButton, " ", deleteButton])
213                             render(n, e)
214                         })
215                     } else {
216                         $.each($(this).find("td .actions"), function (index, e) {
217                             let tr = $(this).parent().parent()
218                             let agreement_id = api.row(tr).data().agreement_id
219                             let selectButton = createVNode("a", {
220                                 class: "btn btn-default btn-xs", role: "button", onClick: () => {
221                                     select_agreement(agreement_id)
222                                 }
223                             },
224                                 [createVNode("i", { class: "fa fa-check", 'aria-hidden': "true" }), __("Select")])
225
226                             let n = createVNode('span', {}, [selectButton])
227                             render(n, e)
228                         })
229                     }
230
231                     $.each($(this).find("tbody tr td:first-child"), function (index, e) {
232                         let tr = $(this).parent()
233                         let row = api.row(tr).data()
234                         if (!row) return // Happen if the table is empty
235                         let n = createVNode("a", {
236                             role: "button",
237                             onClick: () => {
238                                 show_agreement(row.agreement_id)
239                             }
240                         },
241                             `${row.name} (#${row.agreement_id})`
242                         )
243                         render(n, e)
244                     })
245                 },
246                 preDrawCallback: function (settings) {
247                     $("#" + table_id).find("thead th").eq(1).attr('data-filter', 'vendors')
248                     $("#" + table_id).find("thead th").eq(3).attr('data-filter', 'av_agreement_statuses')
249                     $("#" + table_id).find("thead th").eq(4).attr('data-filter', 'av_agreement_closure_reasons')
250                     $("#" + table_id).find("thead th").eq(5).attr('data-filter', 'av_agreement_is_perpetual')
251                     $("#" + table_id).find("thead th").eq(6).attr('data-filter', 'av_agreement_renewal_priorities')
252                 }
253
254             }, agreement_table_settings, 1)
255         },
256     },
257     mounted() {
258         if (!this.building_table) {
259             this.building_table = true
260             this.getAgreements().then(() => this.build_datatable())
261         }
262     },
263     components: { Toolbar },
264     name: "AgreementsList",
265     emits: ["select-agreement", "close"],
266 }
267 </script>
268
269 <style scoped>
270 #agreement_list {
271     display: table;
272 }
273 </style>