Bug 32030: DT - Prevent wrong row to be used
[koha.git] / koha-tmpl / intranet-tmpl / prog / js / vue / components / ERM / EHoldingsEBSCOTitlesList.vue
1 <template>
2     <div>
3         <fieldset>
4             {{ $t("Publication title") }}:
5             <input
6                 type="text"
7                 id="publication_title_filter"
8                 v-model="filters.publication_title"
9                 @keyup.enter="filter_table"
10             />
11             {{ $t("Publication type") }}:
12             <select
13                 id="publication_type_filter"
14                 v-model="filters.publication_type"
15             >
16                 <option value="">{{ $t("All") }}</option>
17                 <option
18                     v-for="type in av_title_publication_types"
19                     :key="type.authorised_values"
20                     :value="type.authorised_value"
21                 >
22                     {{ type.lib }}
23                 </option>
24             </select>
25             {{ $t("Selection status") }}:
26             <select id="selection_type_filter" v-model="filters.selection_type">
27                 <option value="0">{{ $t("All") }}</option>
28                 <option value="1">{{ $t("Selected") }}</option>
29                 <option value="2">{{ $t("Not selected") }}</option>
30             </select>
31             <input
32                 @click="filter_table"
33                 id="filter_table"
34                 type="button"
35                 :value="$t('Submit')"
36             />
37             <span v-if="cannot_search">{{
38                 $t("Please enter a search term")
39             }}</span>
40         </fieldset>
41
42         <!-- We need to display the table element to initiate DataTable -->
43         <div
44             id="title_list_result"
45             :style="show_table ? 'display: block' : 'display: none'"
46         >
47             <div
48                 v-if="
49                     local_count_titles !== undefined &&
50                     local_count_titles !== null
51                 "
52             >
53                 <router-link :to="local_titles_url">
54                     {{
55                         $t("{count} titles found locally", {
56                             count: local_count_titles,
57                         })
58                     }}</router-link
59                 >
60             </div>
61             <div id="title_list_result">
62                 <table :id="table_id"></table>
63             </div>
64         </div>
65     </div>
66 </template>
67
68 <script>
69 import { createVNode, render } from 'vue'
70 import { useVendorStore } from "../../stores/vendors"
71 import { useAVStore } from "../../stores/authorised_values"
72 import { storeToRefs } from "pinia"
73 import { fetchCountLocalTitles } from "./../../fetch"
74 import { useDataTable } from "../../composables/datatables"
75
76 export default {
77     setup() {
78         const vendorStore = useVendorStore()
79         const { vendors } = storeToRefs(vendorStore)
80
81         const AVStore = useAVStore()
82         const { av_title_publication_types } = storeToRefs(AVStore)
83         const { get_lib_from_av } = AVStore
84
85         const table_id = "title_list"
86         useDataTable(table_id)
87
88         return {
89             vendors,
90             av_title_publication_types,
91             get_lib_from_av,
92             erm_providers,
93             table_id,
94         }
95     },
96     data: function () {
97         return {
98             titles: [],
99             initialized: true,
100             filters: {
101                 publication_title: this.$route.query.publication_title || "",
102                 publication_type: this.$route.query.publication_type || "",
103                 selection_type: this.$route.query.selection_type || "",
104             },
105             cannot_search: false,
106             show_table: false,
107             local_count_titles: null,
108         }
109     },
110     computed: {
111         local_titles_url() { return this.build_url("/cgi-bin/koha/erm/eholdings/local/titles") },
112     },
113     beforeRouteEnter(to, from, next) {
114         next(vm => {
115             vm.build_datatable()
116         })
117     },
118     methods: {
119         show_title: function (title_id) {
120             this.$router.push("/cgi-bin/koha/erm/eholdings/ebsco/titles/" + title_id)
121         },
122         build_url_params: function () {
123             return Object.entries(this.filters)
124                 .map(([k, v]) => v ? k + "=" + v : undefined)
125                 .filter(e => e !== undefined)
126                 .join('&')
127         },
128         build_url: function (base_url) {
129             let params = this.build_url_params()
130             return base_url + (params.length ? '?' + params : '')
131         },
132         filter_table: async function () {
133             if (this.filters.publication_title.length) {
134                 this.cannot_search = false
135                 let new_route = this.build_url("/cgi-bin/koha/erm/eholdings/ebsco/titles")
136                 this.$router.push(new_route)
137                 this.show_table = true
138                 this.local_count_titles = null
139                 $('#' + this.table_id).DataTable().draw()
140                 if (this.erm_providers.includes('local')) {
141                     this.local_count_titles = await fetchCountLocalTitles(this.filters)
142                 }
143             } else {
144                 this.cannot_search = true
145             }
146         },
147         build_datatable: function () {
148             let show_title = this.show_title
149             let get_lib_from_av = this.get_lib_from_av
150             if (!this.show_table) {
151                 this.show_table = this.build_url_params().length ? true : false
152             }
153             let filters = this.filters
154             let table_id = this.table_id
155
156             window['vendors'] = this.vendors.map(e => {
157                 e['_id'] = e['id']
158                 e['_str'] = e['name']
159                 return e
160             })
161             let vendors_map = this.vendors.reduce((map, e) => {
162                 map[e.id] = e
163                 return map
164             }, {})
165             window['av_title_publication_types'] = this.av_title_publication_types.map(e => {
166                 e['_id'] = e['authorised_value']
167                 e['_str'] = e['lib']
168                 return e
169             })
170
171             let additional_filters = {
172                 publication_title: function () {
173                     return filters.publication_title || ""
174                 },
175                 publication_type: function () {
176                     return filters.publication_type || ""
177                 },
178                 selection_type: function () {
179                     return filters.selection_type || ""
180                 },
181             }
182             $('#' + table_id).kohaTable({
183                 ajax: {
184                     url: "/api/v1/erm/eholdings/ebsco/titles",
185                 },
186                 embed: ["resources.package"],
187                 ordering: false,
188                 dom: '<"top pager"<"table_entries"ilp>>tr<"bottom pager"ip>',
189                 aLengthMenu: [[10, 20, 50, 100], [10, 20, 50, 100]],
190                 deferLoading: true,
191                 autoWidth: false,
192                 columns: [
193                     {
194                         title: __("Title"),
195                         data: "me.publication_title",
196                         searchable: false,
197                         orderable: false,
198                         render: function (data, type, row, meta) {
199                             // Rendering done in drawCallback
200                             return ""
201                         }
202                     },
203                     {
204                         title: __("Vendor"),
205                         data: "vendor_id",
206                         searchable: false,
207                         orderable: false,
208                         render: function (data, type, row, meta) {
209                             return row.vendor_id != undefined ? escape_str(vendors_map[row.vendor_id].name) : ""
210                         }
211                     },
212                     {
213                         title: __("Publication type"),
214                         data: "publication_type",
215                         searchable: false,
216                         orderable: false,
217                         render: function (data, type, row, meta) {
218                             return escape_str(get_lib_from_av("av_title_publication_types", row.publication_type))
219                         }
220                     },
221                     {
222                         title: __("Identifier"),
223                         data: "print_identifier:online_identifier",
224                         searchable: false,
225                         orderable: false,
226                         render: function (data, type, row, meta) {
227                             let print_identifier = row.print_identifier
228                             let online_identifier = row.online_identifier
229                             return (print_identifier ? escape_str(_("ISBN (Print): %s").format(print_identifier)) : "") +
230                                 (online_identifier ? escape_str(_("ISBN (Online): %s").format(online_identifier)) : "")
231                         }
232                     },
233                 ],
234                 drawCallback: function (settings) {
235
236                     var api = new $.fn.dataTable.Api(settings)
237
238                     if (!api.rows({ search: 'applied' }).count()) return
239
240                     $.each($(this).find("tbody tr td:first-child"), function (index, e) {
241                         let tr = $(this).parent()
242                         let row = api.row(tr).data()
243                         if (!row) return // Happen if the table is empty
244                         let n = createVNode("a", {
245                             role: "button",
246                             onClick: (e) => {
247                                 e.preventDefault()
248                                 show_title(row.title_id)
249                             }
250                         },
251                             `${row.publication_title} (#${row.title_id})`
252                         )
253                         // TODO? We don't have is_selected at title level
254                         //if (row.is_selected) {
255                         //    n = createVNode('span', {}, [n, " ", createVNode("i", { class: "fa fa-check-square-o", style: { color: "green" }, title: __("Is selected") })])
256                         //}
257                         render(n, e)
258                     })
259                 },
260             }, eholdings_titles_table_settings, 0, additional_filters)
261
262             if (filters.publication_title.length) {
263                 this.filter_table()
264             }
265         },
266     },
267     name: "EHoldingsEBSCOTitlesList",
268 }
269 </script>