Bug 14957: (QA follow-up) Update for bug 17858
[koha.git] / koha-tmpl / intranet-tmpl / prog / en / modules / admin / marc-overlay-rules.tt
1 [% USE raw %]
2 [% USE Asset %]
3 [% SET footerjs = 1 %]
4 [% USE Koha %]
5 [% INCLUDE 'doc-head-open.inc' %]
6 <title>MARC overlay rules &rsaquo; Koha &rsaquo; Administration</title>
7 [% INCLUDE 'doc-head-close.inc' %]
8 [% Asset.css("css/datatables.css") | $raw %]
9 [% INCLUDE 'datatables.inc' %]
10
11 <style>
12     .required {
13         background-color: #C00;
14     }
15 </style>
16
17 </head>
18 <body id="admin_marc-overlay-rules" class="admin">
19 [% INCLUDE 'header.inc' %]
20 [% INCLUDE 'cat-search.inc' %]
21
22 <div id="breadcrumbs"><a href="/cgi-bin/koha/mainpage.pl">Home</a> &rsaquo; <a href="/cgi-bin/koha/admin/admin-home.pl">Administration</a>
23  &rsaquo; MARC overlay rules
24 </div>
25
26 <div class="main container-fluid">
27 <div class="row">
28 <div class="col-sm-10 col-sm-push-2">
29
30 <h1>Manage MARC overlay rules</h1>
31
32 [% FOR m IN messages %]
33   <div class="dialog [% m.type | html %]">
34     [% SWITCH m.code %]
35     [% CASE 'invalid_tag_regexp' %]
36       Invalid regular expression "[% m.tag | html %]".
37     [% CASE 'invalid_control_field_actions' %]
38       Invalid combination of actions for tag [% m.tag | html %]. Control field rules do not allow "Appended: Append" and "Removed: Skip".
39     [% CASE %]
40       [% m.code | html %]
41     [% END %]
42   </div>
43 [% END %]
44
45 [% UNLESS Koha.Preference( 'MARCOverlayRules' ) %]
46     <div class="dialog message">
47         The <b>MARCOverlayRules</b> preference is not set, don't forget to enable it for rules to take effect.
48     </div>
49 [% END %]
50 [% IF removeConfirm %]
51 <div class="dialog alert">
52 <h3>Remove rule?</h3>
53 <p>Are you sure you want to remove the selected rule(s)?</p>
54
55 <form action="[% script_name | uri %]" method="GET">
56     <button type="submit" class="deny"><i class="fa fa-fw fa-remove"></i> No, do not remove</button>
57 </form>
58     <button type="button" class="approve" id="doremove"><i class="fa fa-fw fa-check"></i> Yes, remove</button>
59 </div>
60 [% END %]
61
62 <form action="[% script_name | uri %]" method="POST" id="marc-overlay-rules-form">
63 <table id="marc-overlay-rules">
64     <thead><tr>
65         <th>Rule</th>
66         <th>Module</th>
67         <th>Filter</th>
68         <th>Tag</th>
69         <th>Preset</th>
70         <th>Added <i id="info_added" data-toggle="tooltip" title="If a field matching the rule tag only exists in the incoming record" data-placement="right" class="fa fa-info-circle"></i></th>
71         <th>Appended <i id="info_appended" data-toggle="tooltip" title="If the original record has one or more fields matching with the rule tag, but one or more fields matching the rule tag differ in the incoming record" data-placement="right" class="fa fa-info-circle"></i></th>
72         <th>Removed <i id="info_removed" data-toggle="tooltip" title="If the original record has a field matching the rule tag, but the matching field is not in the incoming record" data-placement="right" class="fa fa-info-circle"></i></th>
73         <th>Deleted <i id="info_deleted" data-toggle="tooltip" title="If the original record has fields matching the rule tag, but no fields with this are found in the incoming record" data-placement="right" class="fa fa-info-circle"></i></th>
74         <th>Actions</th>
75         <th>&nbsp;</th>
76     </tr></thead>
77     [% UNLESS edit %]
78     <tfoot>
79         <tr class="rule-new">
80             <th>&nbsp;</th>
81             <th>
82                 <select name="module">
83                     <option value="source">Source</option>
84                     <option value="categorycode">User category</option>
85                     <option value="userid">Username</option>
86                 </select>
87             </th>
88             <th id="filter-container"></th>
89             <th><input type="text" size="5" name="tag"/></th>
90             <th>
91                 <select name="preset">
92                     <option value="" selected>Custom</option>
93                     <option value="Protect">Protect</option>
94                     <option value="Overwrite">Overwrite</option>
95                     <option value="Add new">Add new</option>
96                     <option value="Add and append">Add and append</option>
97                     <option value="Protect from deletion">Protect from deletion</option>
98                 </select>
99             </th>
100             <th class="rule-operation-action-edit">
101                 <select name="add">
102                     <option value="0">Skip</option>
103                     <option value="1">Add</option>
104                 </select>
105             </th>
106             <th class="rule-operation-action-edit">
107                 <select name="append">
108                     <option value="0">Skip</option>
109                     <option value="1">Append</option>
110                 </select>
111             </th>
112             <th class="rule-operation-action-edit">
113                 <select name="remove">
114                     <option value="0">Skip</option>
115                     <option value="1">Remove</option>
116                 </select>
117             </th>
118             <th class="rule-operation-action-edit">
119                 <select name="delete">
120                     <option value="0">Skip</option>
121                     <option value="1">Delete</option>
122                 </select>
123             </th>
124             <th><button class="btn btn-default btn-xs" title="Add" id="add"><i class="fa fa-plus"></i> Add rule</button></th>
125             <th><button id="btn_batchremove" disabled="disabled" class="btn btn-default btn-xs" title="Batch remove"><i class="fa fa-trash"></i> Delete selected</button></th>
126         </tr>
127     </tfoot>
128     [% END %]
129     <tbody>
130         [% FOREACH rule IN rules %]
131             <tr id="[% rule.id | html %]" class="rule[% IF rule.edit %]-edit[% END %]">
132             [% IF rule.edit %]
133                 <td>[% rule.id | html %]</td>
134                 <td>
135                     <select name="module">
136                         [% IF rule.module == "source" %]
137                             <option value="source" selected="selected">Source</option>
138                         [% ELSE %]
139                             <option value="source">Source</option>
140                         [% END %]
141                         [% IF rule.module == "categorycode" %]
142                             <option value="categorycode" selected="selected">User category</option>
143                         [% ELSE %]
144                             <option value="categorycode">User category</option>
145                         [% END %]
146                         [% IF rule.module == "userid" %]
147                             <option value="userid" selected="selected">Username</option>
148                         [% ELSE %]
149                             <option value="userid">Username</option>
150                         [% END %]
151                     </select>
152                 </td>
153                 <td id="filter-container" data-filter="[% rule.filter | html %]"></td>
154                 <td><input type="text" size="3" name="tag" value="[% rule.tag | html %]"/></td>
155                 <th>
156                     <select name="preset">
157                         <option value="" selected>Custom</option>
158                         <option value="Protect">Protect</option>
159                         <option value="Overwrite">Overwrite</option>
160                         <option value="Add new">Add new</option>
161                         <option value="Add and append">Add and append</option>
162                         <option value="Protect from deletion">Protect from deletion</option>
163                     </select>
164                 </th>
165                 <td class="rule-operation-action-edit">
166                     <select name="add">
167                         [% IF rule.add %]
168                             <option value="0">Skip</option>
169                             <option value="1" selected="selected">Add</option>
170                         [% ELSE %]
171                             <option value="0" selected="selected">Skip</option>
172                             <option value="1">Add</option>
173                         [% END %]
174                     </select>
175                 </td>
176                 <td class="rule-operation-action-edit">
177                     <select name="append">
178                         [% IF rule.append %]
179                             <option value="0">Skip</option>
180                             <option value="1" selected="selected">Append</option>
181                         [% ELSE %]
182                             <option value="0" selected="selected">Skip</option>
183                             <option value="1">Append</option>
184                         [% END %]
185                     </select>
186                 </td>
187                 <td class="rule-operation-action-edit">
188                     <select name="remove">
189                         [% IF rule.remove %]
190                             <option value="0">Skip</option>
191                             <option value="1" selected="selected">Remove</option>
192                         [% ELSE %]
193                             <option value="0" selected="selected">Skip</option>
194                             <option value="1">Remove</option>
195                         [% END %]
196                     </select>
197                 </td>
198                 <td class="rule-operation-action-edit">
199                     <select name="delete">
200                         [% IF rule.delete %]
201                             <option value="0">Skip</option>
202                             <option value="1" selected="selected">Delete</option>
203                         [% ELSE %]
204                             <option value="0" selected="selected">Skip</option>
205                             <option value="1">Delete</option>
206                         [% END %]
207                     </select>
208                 </td>
209                 <td class="actions">
210                     <button class="btn btn-default btn-xs" title="Save" id="doedit" value="[% rule.id | html %]"><i class="fa fa-check"></i> Save</button>
211                     <button type="submit" class="btn btn-default btn-xs" title="Cancel" ><i class="fa fa-times"></i> Cancel</button>
212                 </td>
213                 <td></td>
214             [% ELSE %]
215                 <td>[% rule.id | html %]</td>
216                 <td class="rule-module">[% rule.module | html %]</td>
217                 <td class="rule-filter">[% rule.filter | html %]</td>
218                 <td>[% rule.tag | html %]</td>
219                 <td class="rule-preset"></td>
220                 <td class="rule-operation-action" data-operation="add">[% IF rule.add %]Add[% ELSE %]Skip[% END %]</td>
221                 <td class="rule-operation-action" data-operation="append">[% IF rule.append %]Append[% ELSE %]Skip[% END %]</td>
222                 <td class="rule-operation-action" data-operation="remove">[% IF rule.remove %]Remove[% ELSE %]Skip[% END %]</td>
223                 <td class="rule-operation-action" data-operation="delete">[% IF rule.delete %]Delete[% ELSE %]Skip[% END %]</td>
224                 <td class="actions">
225                     <a href="?op=remove&id=[% rule.id | uri %]" title="Delete" class="btn btn-default btn-xs"><i class="fa fa-trash"></i> Delete</a>
226                     <a href="?op=edit&id=[% rule.id | uri %]" title="Edit" class="btn btn-default btn-xs"><i class="fa fa-pencil"></i> Edit</a>
227                 </td>
228                 <td>
229                     [% IF rule.removemarked %]
230                         <input type="checkbox" name="batchremove" value="[% rule.id | html %]" checked="checked"/>
231                     [% ELSE %]
232                         <input type="checkbox" name="batchremove" value="[% rule.id | html %]"/>
233                     [% END %]
234                 </td>
235             [% END %]
236             </tr>
237         [% END %]
238     </tbody>
239 </table>
240 </form>
241
242 <form action="[% script_name | uri %]" method="post">
243 <input type="hidden" name="op" value="redo-matching" />
244 </form>
245
246 </div>
247 <!-- /.col-sm-10.col-sm-push-2 -->
248
249 <div class="col-sm-2 col-sm-pull-10">
250     <aside>
251         [% INCLUDE 'admin-menu.inc' %]
252     </aside>
253 </div>
254
255 </div><!-- /.row -->
256 </div><!-- /main container-fluid -->
257
258 [% MACRO jsinclude BLOCK %]
259     <script>
260     function doSubmit(op, id) {
261         $('<input type="hidden"/>')
262         .attr('name', 'op')
263         .attr('value', op)
264         .appendTo('#marc-overlay-rules-form');
265
266         if(id) {
267             $('<input type="hidden"/>')
268             .attr('name', 'id')
269             .attr('value', id)
270             .appendTo('#marc-overlay-rules-form');
271         }
272
273         var valid = true;
274         if (op == 'add' || op == 'edit') {
275             var validate = [
276                 $('#marc-overlay-rules-form input[name="filter"]'),
277                 $('#marc-overlay-rules-form input[name="tag"]')
278             ];
279             for(var i = 0; i < validate.length; i++) {
280                 if (validate[i].length) {
281                     if(validate[i].val().length == 0) {
282                         validate[i].addClass('required');
283                         valid = false;
284                     } else {
285                         validate[i].removeClass('required');
286                     }
287                 }
288             }
289         }
290
291         if (valid) {
292             $('#marc-overlay-rules-form').submit();
293         }
294
295         return valid;
296     }
297
298     $(document).ready(function(){
299         $('#doremove').on('click', function(){
300             doSubmit('doremove');
301         });
302         $('#doedit').on('click', function(){
303             doSubmit('doedit', $("#doedit").attr('value'));
304         });
305         $('#add').on('click', function(){
306             doSubmit('add');
307             return false;
308         });
309         $('#btn_batchremove').on('click', function(){
310             doSubmit('remove');
311         });
312
313         /* Disable batch remove unless one or more checkboxes are checked */
314         $('input[name="batchremove"]').change(function() {
315             if($('input[name="batchremove"]:checked').length > 0) {
316                 $('#btn_batchremove').removeAttr('disabled');
317             } else {
318                 $('#btn_batchremove').attr('disabled', 'disabled');
319             }
320         });
321
322         $.fn.dataTable.ext.order['dom-input'] = function (settings, col) {
323             return this.api().column(col, { order: 'index' }).nodes()
324                 .map(function (td, i) {
325                     if($('input', td).val() != undefined) {
326                         return $('input', td).val();
327                     } else if($('select', td).val() != undefined) {
328                         return $('option[selected="selected"]', td).val();
329                     } else {
330                         return $(td).html();
331                     }
332                 });
333         }
334
335         $('#marc-overlay-rules').dataTable($.extend(true, {}, dataTablesDefaults, {
336             "aoColumns": [
337                 {"bSearchable": false, "bSortable": false},
338                 {"sSortDataType": "dom-input"},
339                 {"sSortDataType": "dom-input"},
340                 {"bSearchable": false, "sSortDataType": "dom-input"},
341                 {"bSearchable": false, "sSortDataType": "dom-input"},
342                 {"bSearchable": false, "sSortDataType": "dom-input"},
343                 {"bSearchable": false, "sSortDataType": "dom-input"},
344                 {"bSearchable": false, "sSortDataType": "dom-input"},
345                 {"bSearchable": false, "sSortDataType": "dom-input"},
346                 {"bSearchable": false, "bSortable": false},
347                 {"bSearchable": false, "bSortable": false}
348             ],
349             "pagingType": "simple"
350         }));
351
352         var overlay_rules_presets = {};
353         overlay_rules_presets[_("Protect")] = {
354           'add': 0,
355           'append': 0,
356           'remove': 0,
357           'delete': 0
358         };
359         overlay_rules_presets[_("Overwrite")] = {
360           'add': 1,
361           'append': 1,
362           'remove': 1,
363           'delete': 1
364         };
365         overlay_rules_presets[_("Add new")] = {
366           'add': 1,
367           'append': 0,
368           'remove': 0,
369           'delete': 0
370         };
371         overlay_rules_presets[_("Add and append")] = {
372           'add': 1,
373           'append': 1,
374           'remove': 0,
375           'delete': 0
376         };
377         overlay_rules_presets[_("Protect from deletion")] = {
378           'add': 1,
379           'append': 1,
380           'remove': 1,
381           'delete': 0
382         };
383
384         var overlay_rules_label_to_value = {};
385         overlay_rules_label_to_value[_("Add")] = 1;
386         overlay_rules_label_to_value[_("Append")] = 1;
387         overlay_rules_label_to_value[_("Remove")] = 1;
388         overlay_rules_label_to_value[_("Delete")] = 1;
389         overlay_rules_label_to_value[_("Skip")] = 0;
390
391         function hash_config(config) {
392           return JSON.stringify(config, Object.keys(config).sort());
393         }
394
395         var overlay_rules_preset_map = {};
396         $.each(overlay_rules_presets, function(preset, config) {
397           overlay_rules_preset_map[hash_config(config)] = preset;
398         });
399
400         function operations_config_overlay_rule_preset(config) {
401           return overlay_rules_preset_map[hash_config(config)] || '';
402         }
403
404         /* Set preset values according to operation config */
405         $('.rule').each(function() {
406           var $this = $(this);
407           var operations_config = {};
408           $('.rule-operation-action', $this).each(function() {
409             var $operation = $(this);
410             operations_config[$operation.data('operation')] = overlay_rules_label_to_value[$operation.text()];
411           });
412           $('.rule-preset', $this).text(
413             operations_config_overlay_rule_preset(operations_config) || _("Custom")
414           );
415         });
416
417         /* Listen to operations config changes and set presets accordingly */
418         $('.rule-operation-action-edit select').change(function() {
419           var operations_config = {};
420           var $parent_row = $(this).closest('tr');
421           $('.rule-operation-action-edit select', $parent_row).each(function() {
422             var $this = $(this);
423             operations_config[$this.attr('name')] = parseInt($this.val());
424           });
425           $('select[name="preset"]', $parent_row).val(
426               operations_config_overlay_rule_preset(operations_config)
427           );
428         });
429
430         /* Listen to preset changes and set operations config accordingly */
431         $('select[name="preset"]').change(function() {
432           var $this = $(this);
433           var $parent_row = $this.closest('tr');
434           var preset = $this.val();
435           if (preset) {
436             $.each(overlay_rules_presets[preset], function(operation, action) {
437               $('select[name="' + operation + '"]', $parent_row).val(action);
438             });
439           }
440         });
441
442         var module_filter_options = {
443           source: {
444             '*': '*',
445             batchmod: _("Batch record modification"),
446             intranet: _("Staff client MARC editor"),
447             batchimport: _("Staged MARC import"),
448             z3950: _("Z39.50"),
449             /* bulkmarcimport: _("bulkmarcimport.pl"), */
450             import_lexile: _("import_lexile.pl")
451           },
452           categorycode: {
453             '*': '*',
454             [% FOREACH categorycode IN categorycodes %]
455               [% categorycode.categorycode | html %]: "[% categorycode.description | html %]",
456             [% END %]
457           }
458         };
459
460         //Kind of hack: Replace filter value with label when one exist
461         $('.rule-module').each(function() {
462           var $this = $(this);
463           var module = $this.text();
464           if (module in module_filter_options) {
465             let $filter = $this.siblings('.rule-filter');
466             if ($filter.text() in module_filter_options[module]) {
467               $filter.text(module_filter_options[module][$filter.text()]);
468             }
469           }
470         });
471
472         var $filter_container = $('#filter-container');
473
474         /* Listen to module changes and set filter input accordingly */
475         $('select[name="module"]').change(function() {
476           var $this = $(this);
477           var module_name = $this.val();
478
479           /* Remove current element if any */
480           $filter_container.empty();
481
482           var filter_elem = null;
483           if (module_name in module_filter_options) {
484             // Create select element
485             filter_elem = document.createElement('select');
486             for (var filter_value in module_filter_options[module_name]) {
487               var option = document.createElement('option');
488               option.value = filter_value;
489               option.text = module_filter_options[module_name][filter_value];
490               filter_elem.appendChild(option);
491             }
492           }
493           else {
494             // Create text input element
495             filter_elem = document.createElement('input');
496             filter_elem.type = 'text';
497             filter_elem.setAttribute('size', 5);
498           }
499           filter_elem.name = 'filter';
500           filter_elem.id = 'filter';
501           $filter_container.append(filter_elem);
502         }).change(); // Trigger change
503
504         // Hack: set value if editing rule
505         if ($filter_container.data('filter')) {
506           $('#filter').val($filter_container.data('filter'));
507         }
508
509     });
510     </script>
511 [% END %]
512 [% INCLUDE 'intranet-bottom.inc' %]