From 06e20a5c16d2956c6479571c5b6ec3cbcd443c96 Mon Sep 17 00:00:00 2001 From: Jared Camins-Esakov Date: Thu, 31 May 2012 07:24:29 -0400 Subject: [PATCH] Bug 8204: Add user friendly authority view to OPAC Content-Type: text/plain; charset="UTF-8" Up until now, the only authority view in the OPAC was a rather-unfriendly expanded MARC view. This patch adds a user-friendly view similar to the biblio details view. Specific features to be aware of: * Right-to-left text in the MARC21 880 field will show up in the appropriate location with the appropriate alignment and wrapping * There is very little CSS styling. Any suggestions for how to make the display more attractive would be gratefully received. To test: 1) Do a search for an authority in the OPAC. 2) Choose an authority record to view. 3) Observe that the view is more user-friendly and polished. --- C4/AuthoritiesMarc.pm | 95 +++++++---- koha-tmpl/opac-tmpl/prog/en/css/opac.css | 13 ++- .../prog/en/modules/opac-auth-MARCdetail.tt | 2 + .../opac-tmpl/prog/en/modules/opac-auth-detail.tt | 173 ++++++++++++++++++++ opac/opac-authoritiesdetail.pl | 152 +++++++++--------- 5 files changed, 327 insertions(+), 108 deletions(-) create mode 100644 koha-tmpl/opac-tmpl/prog/en/modules/opac-auth-detail.tt diff --git a/C4/AuthoritiesMarc.pm b/C4/AuthoritiesMarc.pm index c92c319..264a420 100644 --- a/C4/AuthoritiesMarc.pm +++ b/C4/AuthoritiesMarc.pm @@ -955,6 +955,7 @@ sub BuildSummary { 'f' => 'musical', 'g' => 'broader', 'h' => 'narrower', + 'n' => 'notapplicable', 'i' => 'subfi', 't' => 'parent' ); @@ -1014,35 +1015,36 @@ sub BuildSummary { # construct UNIMARC summary, that is quite different from MARC21 one # accepted form foreach my $field ($record->field('2..')) { - push @authorized, $field->as_string('abcdefghijlmnopqrstuvwxyz'); + push @authorized, { heading => $field->as_string('abcdefghijlmnopqrstuvwxyz'), field => $field->tag() }; } # rejected form(s) foreach my $field ($record->field('3..')) { - push @notes, $field->subfield('a'); + push @notes, { note => $field->subfield('a'), field => $field->tag() }; } foreach my $field ($record->field('4..')) { my $thesaurus = $field->subfield('2') ? "thes. : ".$thesaurus{"$field->subfield('2')"}." : " : ''; - push @seefrom, { heading => $thesaurus . $field->as_string('abcdefghijlmnopqrstuvwxyz'), type => 'seefrom' }; + push @seefrom, { heading => $thesaurus . $field->as_string('abcdefghijlmnopqrstuvwxyz'), type => 'seefrom', field => $field->tag() }; } # see : foreach my $field ($record->field('5..')) { if (($field->subfield('5')) && ($field->subfield('a')) && ($field->subfield('5') eq 'g')) { - push @seealso, { $field->as_string('abcdefgjxyz'), type => 'broader' }; + push @seealso, { $field->as_string('abcdefgjxyz'), type => 'broader', field => $field->tag() }; } elsif (($field->subfield('5')) && ($field->as_string) && ($field->subfield('5') eq 'h')){ - push @seealso, { heading => $field->as_string('abcdefgjxyz'), type => 'narrower' }; + push @seealso, { heading => $field->as_string('abcdefgjxyz'), type => 'narrower', field => $field->tag() }; } elsif ($field->subfield('a')) { - push @seealso, { heading => $field->as_string('abcdefgxyz'), type => 'seealso' }; + push @seealso, { heading => $field->as_string('abcdefgxyz'), type => 'seealso', field => $field->tag() }; } } # // form foreach my $field ($record->field('7..')) { my $lang = substr($field->subfield('8'),3,3); - push @otherscript, { lang => $lang, term => $field->subfield('a') }; + push @otherscript, { lang => $lang, term => $field->subfield('a'), direction => 'ltr', field => $field->tag() }; } } else { # construct MARC21 summary # FIXME - looping over 1XX is questionable # since MARC21 authority should have only one 1XX + my $subfields_to_report; foreach my $field ($record->field('1..')) { my $tag = $field->tag(); next if "152" eq $tag; @@ -1050,55 +1052,86 @@ sub BuildSummary { # in MARC21 -- purely local tags really ought to be # 9XX if ($tag eq '100') { - push @authorized, $field->as_string('abcdefghjklmnopqrstvxyz68'); + $subfields_to_report = 'abcdefghjklmnopqrstvxyz'; } elsif ($tag eq '110') { - push @authorized, $field->as_string('abcdefghklmnoprstvxyz68'); + $subfields_to_report = 'abcdefghklmnoprstvxyz'; } elsif ($tag eq '111') { - push @authorized, $field->as_string('acdefghklnpqstvxyz68'); + $subfields_to_report = 'acdefghklnpqstvxyz'; } elsif ($tag eq '130') { - push @authorized, $field->as_string('adfghklmnoprstvxyz68'); + $subfields_to_report = 'adfghklmnoprstvxyz'; } elsif ($tag eq '148') { - push @authorized, $field->as_string('abvxyz68'); + $subfields_to_report = 'abvxyz'; } elsif ($tag eq '150') { - push @authorized, $field->as_string('abvxyz68'); + $subfields_to_report = 'abvxyz'; } elsif ($tag eq '151') { - push @authorized, $field->as_string('avxyz68'); + $subfields_to_report = 'avxyz'; } elsif ($tag eq '155') { - push @authorized, $field->as_string('abvxyz68'); + $subfields_to_report = 'abvxyz'; } elsif ($tag eq '180') { - push @authorized, $field->as_string('vxyz68'); + $subfields_to_report = 'vxyz'; } elsif ($tag eq '181') { - push @authorized, $field->as_string('vxyz68'); + $subfields_to_report = 'vxyz'; } elsif ($tag eq '182') { - push @authorized, $field->as_string('vxyz68'); + $subfields_to_report = 'vxyz'; } elsif ($tag eq '185') { - push @authorized, $field->as_string('vxyz68'); + $subfields_to_report = 'vxyz'; + } + if ($subfields_to_report) { + push @authorized, { heading => $field->as_string($subfields_to_report), field => $tag }; } else { - push @authorized, $field->as_string(); + push @authorized, { heading => $field->as_string(), field => $tag }; } - } #See From - foreach my $field ($record->field('4..')) { + } + foreach my $field ($record->field('4..')) { #See From my $type = 'seefrom'; - $type = $marc21controlrefs{substr $field->subfield('w'), '0'} if ($field->subfield('w')); + $type = $marc21controlrefs{substr $field->subfield('w'), 0, 1} if ($field->subfield('w')); + if ($type eq 'notapplicable') { + substr $field->subfield('w'), 2, 1; + $type = 'earlier' if $type && $type ne 'n'; + } if ($type eq 'subfi') { - push @seefrom, { heading => $field->as_string($marc21subfields), type => $field->subfield('i') }; + push @seefrom, { heading => $field->as_string($marc21subfields), type => $field->subfield('i'), field => $field->tag() }; } else { - push @seefrom, { heading => $field->as_string($marc21subfields), type => $type }; + push @seefrom, { heading => $field->as_string($marc21subfields), type => $type, field => $field->tag() }; } - } #See Also - foreach my $field ($record->field('5..')) { + } + foreach my $field ($record->field('5..')) { #See Also my $type = 'seealso'; - $type = $marc21controlrefs{substr $field->subfield('w'), '0'} if ($field->subfield('w')); + $type = $marc21controlrefs{substr $field->subfield('w'), 0, 1} if ($field->subfield('w')); + if ($type eq 'notapplicable') { + substr $field->subfield('w'), 2, 1; + $type = 'earlier' if $type && $type ne 'n'; + } if ($type eq 'subfi') { - push @seealso, { heading => $field->as_string($marc21subfields), type => $field->subfield('i') }; + push @seealso, { heading => $field->as_string($marc21subfields), type => $field->subfield('i'), field => $field->tag() }; } else { - push @seealso, { heading => $field->as_string($marc21subfields), type => $type }; + push @seealso, { heading => $field->as_string($marc21subfields), type => $type, field => $field->tag() }; } } foreach my $field ($record->field('6..')) { - push @notes, $field->as_string(); + push @notes, { note => $field->as_string(), field => $field->tag() }; + } + foreach my $field ($record->field('880')) { + my $linkage = $field->subfield('6'); + my $category = substr $linkage, 0, 1; + if ($category eq '1') { + $category = 'preferred'; + } elsif ($category eq '4') { + $category = 'seefrom'; + } elsif ($category eq '5') { + $category = 'seealso'; + } + my $type; + if ($field->subfield('w')) { + $type = $marc21controlrefs{substr $field->subfield('w'), '0'}; + } else { + $type = $category; + } + my $direction = $linkage =~ m#/r$# ? 'rtl' : 'ltr'; + push @otherscript, { term => $field->as_string($subfields_to_report), category => $category, type => $type, direction => $direction, linkage => $linkage }; } } + $summary{mainentry} = $authorized[0]->{heading}; $summary{authorized} = \@authorized; $summary{notes} = \@notes; $summary{seefrom} = \@seefrom; diff --git a/koha-tmpl/opac-tmpl/prog/en/css/opac.css b/koha-tmpl/opac-tmpl/prog/en/css/opac.css index 1e5b0c6..d4e7071 100644 --- a/koha-tmpl/opac-tmpl/prog/en/css/opac.css +++ b/koha-tmpl/opac-tmpl/prog/en/css/opac.css @@ -2594,9 +2594,20 @@ ul.ui-tabs-nav li { } .authref .label { - font-style: italic; + font-style: italic; } +.authstanza { + margin-top: 1em; +} + +.authstanzaheading { + font-weight: bold; +} + +.authstanza li { + margin-left: 0.5em; +} /* jQuery UI Datepicker */ .ui-datepicker-trigger { diff --git a/koha-tmpl/opac-tmpl/prog/en/modules/opac-auth-MARCdetail.tt b/koha-tmpl/opac-tmpl/prog/en/modules/opac-auth-MARCdetail.tt index 8e87d71..3863fad 100644 --- a/koha-tmpl/opac-tmpl/prog/en/modules/opac-auth-MARCdetail.tt +++ b/koha-tmpl/opac-tmpl/prog/en/modules/opac-auth-MARCdetail.tt @@ -35,6 +35,8 @@ function showChildren(mynumber) {
+
Normal view MARC view
+ [% IF ( displayhierarchy ) %]
diff --git a/koha-tmpl/opac-tmpl/prog/en/modules/opac-auth-detail.tt b/koha-tmpl/opac-tmpl/prog/en/modules/opac-auth-detail.tt new file mode 100644 index 0000000..f55a58f --- /dev/null +++ b/koha-tmpl/opac-tmpl/prog/en/modules/opac-auth-detail.tt @@ -0,0 +1,173 @@ +[% BLOCK authtypelabel %] + [% UNLESS ( type=='seefrom' || type=='seealso' || type=='' ) %] + [% FILTER trim %][% SWITCH type %] + [% CASE 'earlier' %]Earlier heading + [% CASE 'later' %]Later heading + [% CASE 'acronym' %]Acronym + [% CASE 'musical' %]Musical composition + [% CASE 'broader' %]Broader heading + [% CASE 'narrower' %]Narrower heading + [% CASE %][% type %] + [% END %][% END %] + [% END %] +[% END %] +[% BLOCK otherscript %] + [% FOREACH heading IN headings %] + [% IF heading.category == wantcategory %] + [% IF heading.direction == 'ltr' %] +
+ [% heading.term %] +
+ [% ELSIF heading.direction == 'rtl' %] +
+ [% heading.term %] +
+ [% END %] + [% END %] + [% END %] +[% END %] +[% BLOCK authheadingdisplay %] + [% IF authid %][% heading %] + [% ELSIF search %][% heading %] + [% ELSE %][% heading %] + [% END %] +[% END %] +[% INCLUDE 'doc-head-open.inc' %][% IF ( LibraryNameTitle ) %][% LibraryNameTitle %][% ELSE %]Koha online[% END %] catalog › Entry +[% INCLUDE 'doc-head-close.inc' %] +[% IF ( displayhierarchy ) %] + +[% END %] + + + + +
+
+[% INCLUDE 'masthead.inc' %] +
+
+ +
Normal view MARC view
+ +
+ +[% IF ( displayhierarchy ) %] + +
+[% FOREACH loophierarchie IN loophierarchies %] +
+ [% FOREACH loopelemen IN loophierarchie.loopelement %] +
+ [% IF ( loopelemen.current_value ) %] + [% loopelemen.value %] + [% ELSE %] + [% loopelemen.value %] + [% END %] + [% IF ( loopelemen.ifchildren ) %] + +
+ [% FOREACH loopchildre IN loopelemen.loopchildren %] + + [% END %] + [% END %] +
+ [% END %] + +
+[% END %] +
+[% END %] +

[% summary.mainentry %] ([% authtypetext %])

+ +
+[% FOREACH authorize IN summary.authorized %] +
Preferred form: [% authorize.heading %]
+[% END %] +[% PROCESS otherscript headings=summary.otherscript wantcategory='preferred' %] +
+[% IF summary.seefrom %] +
+
Used for/see from:
+
    + [% FOREACH seefro IN summary.seefrom %] +
  • + [% IF seefro.type && seefro.type != 'seefrom' %][% PROCESS authtypelabel type=seefro.type | trim %]:[% END %] + [% PROCESS authheadingdisplay heading=seefro.heading search=seefrosearch authid=seefro.authid %] +
  • + [% END %] + [% PROCESS otherscript headings=summary.otherscript wantcategory='seefrom' %] +
+[% END %] +[% IF summary.seealso %] +
+
See also:
+
    + [% FOREACH seeals IN summary.seealso %] +
  • [% IF seeals.type && seeals.type != 'seealso' %][% PROCESS authtypelabel type=seeals.type | trim %]:[% END %] + [% PROCESS authheadingdisplay heading=seeals.heading search=seeals.search authid=seeals.authid %] +
  • + [% END %] + [% PROCESS otherscript headings=summary.otherscript wantcategory='seealso' %] +
+[% END %] +[% IF marcflavour == 'UNIMARC' && summary.otherscript %] +
+ [% FOREACH otherscrip IN summary.otherscript %] +
See also[% PROCESS language lang=otherscript.lang | trim %] term: + [% otherscrip.term %] +
+ [% END %] +
+[% END %] +
+ +
+
+[% FOREACH note IN summary.notes %] +

[% note.note %]

+[% END %] +
+
+
+
+
+ +
+
+
+[% IF ( OpacNav ) %] +
+
+[% INCLUDE 'navigation.inc' %] +
+
[% END %] +
+[% INCLUDE 'opac-bottom.inc' %] diff --git a/opac/opac-authoritiesdetail.pl b/opac/opac-authoritiesdetail.pl index 2884373..278db99 100755 --- a/opac/opac-authoritiesdetail.pl +++ b/opac/opac-authoritiesdetail.pl @@ -53,7 +53,7 @@ my $query = new CGI; my $dbh = C4::Context->dbh; my $display_hierarchy = C4::Context->preference("AuthDisplayHierarchy"); -my $show_marc = $query->param('marc') || 1; # Currently only MARC view is available +my $show_marc = $query->param('marc'); # open template my ( $template, $loggedinuser, $cookie ) = get_template_and_user( @@ -68,8 +68,6 @@ my ( $template, $loggedinuser, $cookie ) = get_template_and_user( my $authid = $query->param('authid'); my $authtypecode = &GetAuthTypeCode( $authid ); -my $tagslib = &GetTagsLabels( 0, $authtypecode ); - my $record; if ($display_hierarchy){ @@ -101,90 +99,92 @@ else { } my $count = CountUsage($authid); -# find the marc field/subfield used in biblio by this authority -my $sth = - $dbh->prepare( - "select distinct tagfield from marc_subfield_structure where authtypecode=?" - ); -$sth->execute($authtypecode); -my $biblio_fields; -while ( my ($tagfield) = $sth->fetchrow ) { - $biblio_fields .= $tagfield . "9,"; + +my $authtypes = getauthtypes(); +my @authtypesloop = (); +foreach my $thisauthtype ( keys %{$authtypes} ) { + push @authtypesloop, + { value => $thisauthtype, + selected => $thisauthtype eq $authtypecode, + authtypetext => $authtypes->{$thisauthtype}{'authtypetext'}, + }; } -chop $biblio_fields; +$template->{VARS}->{'authtypesloop'} = \@authtypesloop; +$template->{VARS}->{'authtypetext'} = $authtypes->{$authtypecode}{'authtypetext'}; +$template->{VARS}->{'authid'} = $authid; +$template->{VARS}->{'count'} = $count; + +# find the marc field/subfield used in biblio by this authority +if ($show_marc) { + my $tagslib = &GetTagsLabels( 0, $authtypecode ); + my $sth = + $dbh->prepare( + "select distinct tagfield from marc_subfield_structure where authtypecode=?" + ); + $sth->execute($authtypecode); + my $biblio_fields; + while ( my ($tagfield) = $sth->fetchrow ) { + $biblio_fields .= $tagfield . "9,"; + } + chop $biblio_fields; # fill arrays -my @loop_data = (); -my $tag; + my @loop_data = (); + my $tag; -# loop through each tab 0 through 9 -# for (my $tabloop = 0; $tabloop<=10;$tabloop++) { # loop through each tag -my @fields = $record->fields(); -foreach my $field (@fields) { - my @subfields_data; - - # skip UNIMARC fields <200, they are useless for a patron - next if C4::Context->preference('MarcFlavour') eq 'UNIMARC' && $field->tag() <200; - - # if tag <10, there's no subfield, use the "@" trick - if ( $field->tag() < 10 ) { - next if ( $tagslib->{ $field->tag() }->{'@'}->{hidden} ); - my %subfield_data; - $subfield_data{marc_lib} = $tagslib->{ $field->tag() }->{'@'}->{lib}; - $subfield_data{marc_value} = $field->data(); - $subfield_data{marc_subfield} = '@'; - $subfield_data{marc_tag} = $field->tag(); - push( @subfields_data, \%subfield_data ); - } - else { - my @subf = $field->subfields; - - # loop through each subfield - for my $i ( 0 .. $#subf ) { - $subf[$i][0] = "@" unless $subf[$i][0]; - next if ( $tagslib->{ $field->tag() }->{ $subf[$i][0] }->{hidden} ); - # skip useless subfields (for patrons) - next if $subf[$i][0] =~ /7|8|9/; + my @fields = $record->fields(); + foreach my $field (@fields) { + my @subfields_data; + +# skip UNIMARC fields <200, they are useless for a patron + next if C4::Context->preference('MarcFlavour') eq 'UNIMARC' && $field->tag() <200; + +# if tag <10, there's no subfield, use the "@" trick + if ( $field->tag() < 10 ) { + next if ( $tagslib->{ $field->tag() }->{'@'}->{hidden} ); my %subfield_data; - $subfield_data{marc_lib} = - $tagslib->{ $field->tag() }->{ $subf[$i][0] }->{lib}; - $subfield_data{marc_subfield} = $subf[$i][0]; + $subfield_data{marc_lib} = $tagslib->{ $field->tag() }->{'@'}->{lib}; + $subfield_data{marc_value} = $field->data(); + $subfield_data{marc_subfield} = '@'; $subfield_data{marc_tag} = $field->tag(); - $subfield_data{isurl} = $tagslib->{ $field->tag() }->{ $subf[$i][0] }->{isurl}; - $subfield_data{marc_value} = $subf[$i][1]; push( @subfields_data, \%subfield_data ); } + else { + my @subf = $field->subfields; + +# loop through each subfield + for my $i ( 0 .. $#subf ) { + $subf[$i][0] = "@" unless $subf[$i][0]; + next if ( $tagslib->{ $field->tag() }->{ $subf[$i][0] }->{hidden} ); +# skip useless subfields (for patrons) + next if $subf[$i][0] =~ /7|8|9/; + my %subfield_data; + $subfield_data{marc_lib} = + $tagslib->{ $field->tag() }->{ $subf[$i][0] }->{lib}; + $subfield_data{marc_subfield} = $subf[$i][0]; + $subfield_data{marc_tag} = $field->tag(); + $subfield_data{isurl} = $tagslib->{ $field->tag() }->{ $subf[$i][0] }->{isurl}; + $subfield_data{marc_value} = $subf[$i][1]; + push( @subfields_data, \%subfield_data ); + } + } + if ( $#subfields_data >= 0 ) { + my %tag_data; + $tag_data{tag} = + $field->tag() + . ' ' + . C4::Koha::display_marc_indicators($field) + . ' - ' . $tagslib->{ $field->tag() }->{lib}; + $tag_data{subfield} = \@subfields_data; + push( @loop_data, \%tag_data ); + } } - if ( $#subfields_data >= 0 ) { - my %tag_data; - $tag_data{tag} = - $field->tag() - . ' ' - . C4::Koha::display_marc_indicators($field) - . ' - ' . $tagslib->{ $field->tag() }->{lib}; - $tag_data{subfield} = \@subfields_data; - push( @loop_data, \%tag_data ); - } -} -$template->param( "Tab0XX" => \@loop_data ); - -my $authtypes = getauthtypes(); -my @authtypesloop = (); -foreach my $thisauthtype ( keys %{$authtypes} ) { - push @authtypesloop, - { value => $thisauthtype, - selected => $thisauthtype eq $authtypecode, - authtypetext => $authtypes->{$thisauthtype}{'authtypetext'}, - }; + $template->param( "Tab0XX" => \@loop_data ); +} else { + my $summary = BuildSummary($record, $authid, $authtypecode); + $template->{VARS}->{'summary'} = $summary; } -$template->param( - authid => $authid, - count => $count, - biblio_fields => $biblio_fields, - authtypetext => $authtypes->{$authtypecode}{'authtypetext'}, - authtypesloop => \@authtypesloop, -); output_html_with_http_headers $query, $cookie, $template->output; -- 1.7.2.5