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