View | Details | Raw Unified | Return to bug 39600
Collapse All | Expand All

(-)a/koha-tmpl/opac-tmpl/bootstrap/js/datatables.js (-2 / +315 lines)
Lines 61-66 function toggledClearFilter(searchText, tableId) { Link Here
61
    }
61
    }
62
}
62
}
63
63
64
function _dt_default_ajax(params) {
65
    let default_filters = params.default_filters;
66
    let options = params.options;
67
68
    if (
69
        !options.criteria ||
70
        ["contains", "starts_with", "ends_with", "exact"].indexOf(
71
            options.criteria.toLowerCase()
72
        ) === -1
73
    )
74
        options.criteria = "contains";
75
    options.criteria = options.criteria.toLowerCase();
76
77
    return {
78
        type: "GET",
79
        cache: true,
80
        dataSrc: "data",
81
        beforeSend: function (xhr, settings) {
82
            this._xhr = xhr;
83
            if (options.embed) {
84
                xhr.setRequestHeader(
85
                    "x-koha-embed",
86
                    Array.isArray(options.embed)
87
                        ? options.embed.join(",")
88
                        : options.embed
89
                );
90
            }
91
        },
92
        dataFilter: function (data, type) {
93
            var json = { data: JSON.parse(data) };
94
            if ((total = this._xhr.getResponseHeader("x-total-count"))) {
95
                json.recordsTotal = total;
96
                json.recordsFiltered = total;
97
            }
98
            if ((total = this._xhr.getResponseHeader("x-base-total-count"))) {
99
                json.recordsTotal = total;
100
            }
101
            if ((draw = this._xhr.getResponseHeader("x-koha-request-id"))) {
102
                json.draw = draw;
103
            }
104
105
            return JSON.stringify(json);
106
        },
107
        data: function (data, settings) {
108
            var length = data.length;
109
            var start = data.start;
110
111
            let api = new $.fn.dataTable.Api(settings);
112
            const global_search = api.search();
113
114
            var dataSet = {
115
                _page: Math.floor(start / length) + 1,
116
                _per_page: length,
117
            };
118
119
            function build_query(col, value) {
120
                var parts = [];
121
                var attributes = col.data.split(":");
122
                for (var i = 0; i < attributes.length; i++) {
123
                    var part = {};
124
                    var attr = attributes[i];
125
                    let default_build = true;
126
                    let criteria = options.criteria;
127
                    if (value.match(/^\^(.*)\$$/)) {
128
                        value = value.replace(/^\^/, "").replace(/\$$/, "");
129
                        criteria = "exact";
130
                    } else {
131
                        // escape SQL LIKE special characters %
132
                        value = value.replace(/(\%|\\)/g, "\\$1");
133
                    }
134
135
                    let built_value;
136
                    if (col.type == "date") {
137
                        let rfc3339 = $date_to_rfc3339(value);
138
                        if (rfc3339 != "Invalid Date") {
139
                            built_value = rfc3339;
140
                        }
141
                    }
142
143
                    if (col.datatype !== undefined) {
144
                        default_build = false;
145
                        let coded_datatype =
146
                            col.datatype.match(/^coded_value:(.*)/);
147
                        if (col.datatype == "related-object") {
148
                            let query_term = value;
149
150
                            if (criteria != "exact") {
151
                                query_term = {
152
                                    like:
153
                                        (["contains", "ends_with"].indexOf(
154
                                            criteria
155
                                        ) !== -1
156
                                            ? "%"
157
                                            : "") +
158
                                        value +
159
                                        (["contains", "starts_with"].indexOf(
160
                                            criteria
161
                                        ) !== -1
162
                                            ? "%"
163
                                            : ""),
164
                                };
165
                            }
166
167
                            part = {
168
                                [col.related + "." + col.relatedKey]:
169
                                    col.relatedValue,
170
                                [col.related + "." + col.relatedSearchOn]:
171
                                    query_term,
172
                            };
173
                        } else if (
174
                            coded_datatype &&
175
                            coded_datatype.length > 1
176
                        ) {
177
                            if (global_search.length || value.length) {
178
                                coded_datatype = coded_datatype[1];
179
                                const search_value = value.length
180
                                    ? value
181
                                    : global_search;
182
                                const regex = new RegExp(
183
                                    `^${search_value}`,
184
                                    "i"
185
                                );
186
                                if (
187
                                    coded_values &&
188
                                    coded_values.hasOwnProperty(coded_datatype)
189
                                ) {
190
                                    let codes = [
191
                                        ...coded_values[
192
                                            coded_datatype
193
                                        ].entries(),
194
                                    ]
195
                                        .filter(([label]) => regex.test(label))
196
                                        .map(([, code]) => code);
197
198
                                    if (codes.length) {
199
                                        part[
200
                                            !attr.includes(".")
201
                                                ? "me." + attr
202
                                                : attr
203
                                        ] = codes;
204
                                    } else {
205
                                        // Coded value not found using the description, fallback to code
206
                                        default_build = true;
207
                                    }
208
                                } else {
209
                                    console.log(
210
                                        "coded datatype %s not supported yet".format(
211
                                            coded_datatype
212
                                        )
213
                                    );
214
                                }
215
                            } else {
216
                                default_build = true;
217
                            }
218
                        } else {
219
                            console.log(
220
                                "datatype %s not supported yet".format(
221
                                    col.datatype
222
                                )
223
                            );
224
                        }
225
                    }
226
                    if (default_build) {
227
                        let value_part;
228
                        if (criteria === "exact") {
229
                            value_part = built_value
230
                                ? [value, built_value]
231
                                : value;
232
                        } else {
233
                            let like = {
234
                                like:
235
                                    (["contains", "ends_with"].indexOf(
236
                                        criteria
237
                                    ) !== -1
238
                                        ? "%"
239
                                        : "") +
240
                                    value +
241
                                    (["contains", "starts_with"].indexOf(
242
                                        criteria
243
                                    ) !== -1
244
                                        ? "%"
245
                                        : ""),
246
                            };
247
                            value_part = built_value
248
                                ? [like, built_value]
249
                                : like;
250
                        }
251
252
                        part[!attr.includes(".") ? "me." + attr : attr] =
253
                            value_part;
254
                    }
255
256
                    if (Object.keys(part).length) parts.push(part);
257
                }
258
                return parts;
259
            }
260
261
            var filter = data.search.value;
262
            // Build query for each column filter
263
            var and_query_parameters = settings.aoColumns
264
                .filter(function (col) {
265
                    return (
266
                        col.bSearchable &&
267
                        typeof col.data == "string" &&
268
                        data.columns[col.idx].search.value != ""
269
                    );
270
                })
271
                .map(function (col) {
272
                    var value = data.columns[col.idx].search.value;
273
                    return build_query(col, value);
274
                })
275
                .map(function r(e) {
276
                    return $.isArray(e) ? $.map(e, r) : e;
277
                });
278
279
            // Build query for the global search filter
280
            var or_query_parameters = settings.aoColumns
281
                .filter(function (col) {
282
                    return col.bSearchable && filter != "";
283
                })
284
                .map(function (col) {
285
                    var value = filter;
286
                    return build_query(col, value);
287
                })
288
                .map(function r(e) {
289
                    return $.isArray(e) ? $.map(e, r) : e;
290
                });
291
292
            if (default_filters) {
293
                let additional_filters = {};
294
                for (f in default_filters) {
295
                    let k;
296
                    let v;
297
                    if (typeof default_filters[f] === "function") {
298
                        let val = default_filters[f]();
299
                        if (val != undefined && val != "") {
300
                            k = f;
301
                            v = val;
302
                        }
303
                    } else {
304
                        k = f;
305
                        v = default_filters[f];
306
                    }
307
308
                    // Pass to -or if you want a separate OR clause
309
                    // It's not the usual DBIC notation!
310
                    if (f == "-or") {
311
                        if (v) or_query_parameters.push(v);
312
                    } else if (f == "-and") {
313
                        if (v) and_query_parameters.push(v);
314
                    } else if (v) {
315
                        additional_filters[k] = v;
316
                    }
317
                }
318
                if (Object.keys(additional_filters).length) {
319
                    and_query_parameters.push(additional_filters);
320
                }
321
            }
322
            query_parameters = and_query_parameters;
323
            if (or_query_parameters.length) {
324
                query_parameters.push(or_query_parameters);
325
            }
326
327
            if (query_parameters.length) {
328
                query_parameters = JSON.stringify(
329
                    query_parameters.length === 1
330
                        ? query_parameters[0]
331
                        : { "-and": query_parameters }
332
                );
333
                dataSet.q = query_parameters;
334
            }
335
336
            dataSet._match = options.criteria;
337
338
            if (data["draw"] !== undefined) {
339
                settings.ajax.headers = { "x-koha-request-id": data.draw };
340
            }
341
342
            if (options.columns) {
343
                var order = data.order;
344
                var orderArray = new Array();
345
                order.forEach(function (e, i) {
346
                    var order_col = e.column;
347
                    var order_by = options.columns[order_col].data;
348
                    order_by = order_by.split(":");
349
                    var order_dir = e.dir == "asc" ? "+" : "-";
350
                    Array.prototype.push.apply(
351
                        orderArray,
352
                        order_by.map(
353
                            x => order_dir + (!x.includes(".") ? "me." + x : x)
354
                        )
355
                    );
356
                });
357
                dataSet._order_by = orderArray
358
                    .filter((v, i, a) => a.indexOf(v) === i)
359
                    .join(",");
360
            }
361
362
            return dataSet;
363
        },
364
    };
365
}
366
64
(function () {
367
(function () {
65
    /* Plugin to allow text sorting to ignore articles
368
    /* Plugin to allow text sorting to ignore articles
66
     *
369
     *
Lines 280-286 function _dt_visibility(table_settings, table_dt) { Link Here
280
     *                                                available from the columns_settings template toolkit include
583
     *                                                available from the columns_settings template toolkit include
281
     * @return {Object}                               The dataTables instance
584
     * @return {Object}                               The dataTables instance
282
     */
585
     */
283
    $.fn.kohaTable = function (options = {}, table_settings = undefined) {
586
    $.fn.kohaTable = function (options = {}, table_settings = undefined, default_filters) {
284
        // Early return if the node does not exist
587
        // Early return if the node does not exist
285
        if (!this.length) return;
588
        if (!this.length) return;
286
589
Lines 293-298 function _dt_visibility(table_settings, table_dt) { Link Here
293
                    dataTablesDefaults.initComplete(settings, json);
596
                    dataTablesDefaults.initComplete(settings, json);
294
                };
597
                };
295
            }
598
            }
599
600
            if (options.ajax && !options.bKohaAjaxSVC) {
601
                options.ajax = Object.assign(
602
                    {},
603
                    options.ajax,
604
                    _dt_default_ajax({ default_filters, options })
605
                );
606
                options.serverSide = true;
607
                options.processing = true;
608
                options.pagingType = "full_numbers";
609
            }
296
        }
610
        }
297
611
298
        var settings = $.extend(
612
        var settings = $.extend(
299
- 

Return to bug 39600