From a9dacc2841c16a9c8d343ddf0cae418b8da64767 Mon Sep 17 00:00:00 2001 From: Jonathan Druart Date: Tue, 1 Dec 2020 18:08:20 +0100 Subject: [PATCH] Bug 8976: Add the ability to sort subfields for the MARC frameworks This new enhancement adds the ability to change the default order the subfields. Both bibliographic and authority MARC subfield structure are taken into account. And so the item edition as well (in the different screens when item can be added/edited). This will answer the following needs that have been listed in the comments of the bug report: - $i in 7xx fields should be the first subfield in the sequence - 300 fields are sorted number first when cataloguers enter the letter fields first - 100 field, it's commonly $a, $q, $d. Test plan: 1. Edit a MARC frameworks, field 300 2. Resort the subfield (drag and drop the tab of the subfield) as you like 3. Save => Notice that the list of fields are displayed following the order you chose 4. Edit it again => The order is correctly kept! 5. Create a new bibliographic record 6. Notice that the subfields are order in the same sequence 7. Fill different subfields, not all 8. Save, edit again 9. Note that the subfields that have been filled are listed first, then the empty ones. But the sequence defined at the framework level is kept. 10. Do the same for an authority framework and create/edit an authority record 11. Modify item (952) subfields order 12. Create an item and confirm that the order is correct 13. Modify the ACQ framework, 952, modify the order of the subfield 14. Create a new order and confirm that the item form has the subfield ordered following the sequence defined at the framework level QA: Note that this patch is about bibliographic records only, next patches deal with authotiries and items. Sponsored-by: Orex Digital Signed-off-by: Michal Denar --- C4/Biblio.pm | 13 +++++++---- admin/marc_subfields_structure.pl | 12 ++++++---- cataloguing/addbiblio.pl | 19 ++++++++------- .../modules/admin/marc_subfields_structure.tt | 16 +++++++------ .../prog/js/marc_subfields_structure.js | 23 ++++++++++++++++++- 5 files changed, 58 insertions(+), 25 deletions(-) diff --git a/C4/Biblio.pm b/C4/Biblio.pm index e84110cccc..0a50a32c0a 100644 --- a/C4/Biblio.pm +++ b/C4/Biblio.pm @@ -961,10 +961,10 @@ sub GetMarcStructure { } $sth = $dbh->prepare( - "SELECT tagfield,tagsubfield,liblibrarian,libopac,tab,mandatory,repeatable,authorised_value,authtypecode,value_builder,kohafield,seealso,hidden,isurl,link,defaultvalue,maxlength,important + "SELECT tagfield,tagsubfield,liblibrarian,libopac,tab,mandatory,repeatable,authorised_value,authtypecode,value_builder,kohafield,seealso,hidden,isurl,link,defaultvalue,maxlength,important, display_order FROM marc_subfield_structure WHERE frameworkcode=? - ORDER BY tagfield,tagsubfield + ORDER BY tagfield, tagsubfield " ); @@ -981,16 +981,18 @@ sub GetMarcStructure { my $link; my $defaultvalue; my $maxlength; + my $display_order; while ( ( $tag, $subfield, $liblibrarian, $libopac, $tab, $mandatory, $repeatable, $authorised_value, $authtypecode, $value_builder, $kohafield, $seealso, $hidden, $isurl, $link, $defaultvalue, - $maxlength, $important + $maxlength, $important, $display_order ) = $sth->fetchrow ) { $res->{$tag}->{$subfield}->{lib} = ( $forlibrarian or !$libopac ) ? $liblibrarian : $libopac; $res->{$tag}->{$subfield}->{tab} = $tab; + $res->{$tag}->{$subfield}->{subfield} = $subfield; $res->{$tag}->{$subfield}->{mandatory} = $mandatory; $res->{$tag}->{$subfield}->{important} = $important; $res->{$tag}->{$subfield}->{repeatable} = $repeatable; @@ -1004,6 +1006,7 @@ sub GetMarcStructure { $res->{$tag}->{$subfield}->{'link'} = $link; $res->{$tag}->{$subfield}->{defaultvalue} = $defaultvalue; $res->{$tag}->{$subfield}->{maxlength} = $maxlength; + $res->{$tag}->{$subfield}->{display_order} = $display_order; } $cache->set_in_cache($cache_key, $res); @@ -1031,7 +1034,7 @@ sub GetUsedMarcStructure { FROM marc_subfield_structure WHERE tab > -1 AND frameworkcode = ? - ORDER BY tagfield, tagsubfield + ORDER BY tagfield, display_order, tagsubfield }; my $sth = C4::Context->dbh->prepare($query); $sth->execute($frameworkcode); @@ -1096,7 +1099,7 @@ sub GetMarcSubfieldStructure { FROM marc_subfield_structure WHERE frameworkcode = ? AND kohafield > '' - ORDER BY frameworkcode,tagfield,tagsubfield + ORDER BY frameworkcode, tagfield, display_order, tagsubfield |, { Slice => {} }, $frameworkcode ); # Now map the output to a hash structure my $subfield_structure = {}; diff --git a/admin/marc_subfields_structure.pl b/admin/marc_subfields_structure.pl index 63ae97732d..22ebcce0a3 100755 --- a/admin/marc_subfields_structure.pl +++ b/admin/marc_subfields_structure.pl @@ -37,7 +37,7 @@ sub string_search { my $count = @data; my $sth = $dbh->prepare( -"Select * from marc_subfield_structure where (tagfield like ? and frameworkcode=?) order by tagfield" +"Select * from marc_subfield_structure where (tagfield like ? and frameworkcode=?) order by tagfield, display_order" ); $sth->execute( "$searchstring%", $frameworkcode ); my @results; @@ -161,7 +161,7 @@ if ( $op eq 'add_form' ) { # build values list my $sth = $dbh->prepare( -"select * from marc_subfield_structure where tagfield=? and frameworkcode=?" +"select * from marc_subfield_structure where tagfield=? and frameworkcode=? order by display_order" ); # and tagsubfield='$tagsubfield'"); $sth->execute( $tagfield, $frameworkcode ); my @loop_data = (); @@ -263,7 +263,7 @@ elsif ( $op eq 'add_validate' ) { my $dbh = C4::Context->dbh; $template->param( tagfield => "$input->param('tagfield')" ); my $sth_update = $dbh->prepare(qq{ - update marc_subfield_structure set tagfield=?, tagsubfield=?, liblibrarian=?, libopac=?, repeatable=?, mandatory=?, important=?, kohafield=?, tab=?, seealso=?, authorised_value=?, authtypecode=?, value_builder=?, hidden=?, isurl=?, frameworkcode=?, link=?, defaultvalue=?, maxlength=? + update marc_subfield_structure set tagfield=?, tagsubfield=?, liblibrarian=?, libopac=?, repeatable=?, mandatory=?, important=?, kohafield=?, tab=?, seealso=?, authorised_value=?, authtypecode=?, value_builder=?, hidden=?, isurl=?, frameworkcode=?, link=?, defaultvalue=?, maxlength=?, display_order=? where tagfield=? and tagsubfield=? and frameworkcode=? }); my @tagsubfield = $input->multi_param('tagsubfield'); @@ -279,7 +279,8 @@ elsif ( $op eq 'add_validate' ) { my @link = $input->multi_param('link'); my @defaultvalue = $input->multi_param('defaultvalue'); my @maxlength = $input->multi_param('maxlength'); - + + my $display_order; for ( my $i = 0 ; $i <= $#tagsubfield ; $i++ ) { my $tagfield = $input->param('tagfield'); my $tagsubfield = $tagsubfield[$i]; @@ -323,6 +324,7 @@ elsif ( $op eq 'add_validate' ) { $link, $defaultvalue, $maxlength, + $display_order->{$tagfield} || 0, ( $tagfield, $tagsubfield, @@ -356,9 +358,11 @@ elsif ( $op eq 'add_validate' ) { link => $link, defaultvalue => $defaultvalue, maxlength => $maxlength, + display_order => $display_order->{$tagfield} || 0, } )->store; } + $display_order->{$tagfield}++; } } $sth_update->finish; diff --git a/cataloguing/addbiblio.pl b/cataloguing/addbiblio.pl index a4614cc941..a91f6dacfc 100755 --- a/cataloguing/addbiblio.pl +++ b/cataloguing/addbiblio.pl @@ -580,7 +580,7 @@ sub build_tabs { } # now, loop again to add parameter subfield that are not in the MARC::Record - foreach my $subfield ( sort( keys %{ $tagslib->{$tag} } ) ) + foreach my $subfield ( keys %{ $tagslib->{$tag} } ) { next if ( length $subfield != 1 ); next if ( $tagslib->{$tag}->{$subfield}->{tab} ne $tabloop ); @@ -633,12 +633,15 @@ sub build_tabs { } else { my @subfields_data; - foreach my $subfield ( sort( keys %{ $tagslib->{$tag} } ) ) { - next if ( length $subfield != 1 ); + foreach my $subfield ( + sort { $a->{display_order} <=> $b->{display_order} || $a->{subfield} cmp $b->{subfield} } + grep { ref($_) && %$_ } # Not a subfield (values for "important", "lib", "mandatory", etc.) or empty + values %{ $tagslib->{$tag} } ) + { next - if ( ( $tagslib->{$tag}->{$subfield}->{hidden} <= -4 ) - or ( $tagslib->{$tag}->{$subfield}->{hidden} >= 5 ) ) - and not ( $subfield eq "9" and + if ( ( $subfield->{hidden} <= -4 ) + or ( $subfield->{hidden} >= 5 ) ) + and not ( $subfield->{subfield} eq "9" and exists($tagslib->{$tag}->{'a'}->{authtypecode}) and defined($tagslib->{$tag}->{'a'}->{authtypecode}) and $tagslib->{$tag}->{'a'}->{authtypecode} ne "" @@ -647,11 +650,11 @@ sub build_tabs { # if subfield is $9 in a field whose $a is authority-controlled, # always include in the form regardless of the hidden setting - bug 2206 next - if ( $tagslib->{$tag}->{$subfield}->{tab} ne $tabloop ); + if ( $subfield->{tab} ne $tabloop ); push( @subfields_data, &create_input( - $tag, $subfield, '', $index_tag, $tabloop, $record, + $tag, $subfield->{subfield}, '', $index_tag, $tabloop, $record, $authorised_values_sth,$input ) ); diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/marc_subfields_structure.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/marc_subfields_structure.tt index 84ce249425..e7d90a7f8a 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/marc_subfields_structure.tt +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/marc_subfields_structure.tt @@ -80,13 +80,15 @@
diff --git a/koha-tmpl/intranet-tmpl/prog/js/marc_subfields_structure.js b/koha-tmpl/intranet-tmpl/prog/js/marc_subfields_structure.js index 081afd2484..2da2eb1461 100644 --- a/koha-tmpl/intranet-tmpl/prog/js/marc_subfields_structure.js +++ b/koha-tmpl/intranet-tmpl/prog/js/marc_subfields_structure.js @@ -1,6 +1,26 @@ /* global dataTablesDefaults */ $(document).ready(function() { - $('#subfieldtabs').tabs(); + var tabs = $('#subfieldtabs').tabs(); + var current_index; + tabs.find( ".ui-tabs-nav" ).sortable({ + axis: "x", + start: function (e, ui) { + current_index = $(ui.item[0]).index(); + }, + stop: function (e, ui) { + var new_index = $(ui.item[0]).index(); + if (current_index < new_index) new_index++; + var subfield_code = $(ui.item[0]).attr('id').replace( /^tab_subfield_/, ''); + var content = $('#sub' + subfield_code + 'field'); + var panels = $("#subfieldtabs > div"); + if ( new_index < $(panels).size() ){ + $(content).insertBefore($("#subfieldtabs > div")[new_index]); + } else { + $(content).insertAfter($("#subfieldtabs > div")[new_index-1]); + } + tabs.tabs("refresh"); + } + }); $("input[id^='hidden_']").click(setHiddenValue); $("input[id^='hidden-']").each(function() { populateHiddenCheckboxes($(this).attr('id').split('-')[1]); @@ -9,6 +29,7 @@ $(document).ready(function() { "columnDefs": [ { 'sortable': false, 'targets': [ 'NoSort' ] } ], + aaSorting: [], paginate: false })); }); -- 2.20.1