Bug 8204: Add user friendly authority view to OPAC

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.

Signed-off-by: Katrin Fischer <Katrin.Fischer.83@web.de>
Works very nicely now. The old view is still available, but the
user is presented with a nicer non-MARC view first.
This commit is contained in:
Jared Camins-Esakov 2012-05-31 07:24:29 -04:00 committed by Paul Poulain
parent 899597c826
commit 569e3823fd
6 changed files with 337 additions and 118 deletions

View File

@ -959,6 +959,7 @@ sub BuildSummary {
'f' => 'musical',
'g' => 'broader',
'h' => 'narrower',
'n' => 'notapplicable',
'i' => 'subfi',
't' => 'parent'
);
@ -1018,35 +1019,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;
@ -1054,55 +1056,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');
} else {
push @authorized, $field->as_string();
$subfields_to_report = 'vxyz';
}
} #See From
foreach my $field ($record->field('4..')) {
if ($subfields_to_report) {
push @authorized, { heading => $field->as_string($subfields_to_report), field => $tag };
} else {
push @authorized, { heading => $field->as_string(), field => $tag };
}
}
foreach my $field ($record->field('4..')) { #See From
my $type = 'seefrom';
$type = $marc21controlrefs{substr $field->subfield('w'), '0'} if ($field->subfield('w'));
if ($type eq 'subfi') {
push @seefrom, { heading => $field->as_string($marc21subfields), type => $field->subfield('i') };
} else {
push @seefrom, { heading => $field->as_string($marc21subfields), type => $type };
$type = $marc21controlrefs{substr $field->subfield('w'), 0, 1} if ($field->subfield('w'));
if ($type eq 'notapplicable') {
$type = substr $field->subfield('w'), 2, 1;
$type = 'earlier' if $type && $type ne 'n';
}
} #See Also
foreach my $field ($record->field('5..')) {
my $type = 'seealso';
$type = $marc21controlrefs{substr $field->subfield('w'), '0'} if ($field->subfield('w'));
if ($type eq 'subfi') {
push @seealso, { 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 @seealso, { heading => $field->as_string($marc21subfields), type => $type };
push @seefrom, { heading => $field->as_string($marc21subfields), type => $type, field => $field->tag() };
}
}
foreach my $field ($record->field('5..')) { #See Also
my $type = 'seealso';
$type = $marc21controlrefs{substr $field->subfield('w'), 0, 1} if ($field->subfield('w'));
if ($type eq 'notapplicable') {
$type = 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'), field => $field->tag() };
} else {
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;

View File

@ -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 {

View File

@ -30,7 +30,7 @@
[% IF ( summary.summary ) %][% summary.summary %]:[% END %]
[% UNLESS ( summary.summaryonly ) %]
[% FOREACH authorize IN summary.authorized %]
<span class="authorizedheading">[% authorize %]</span>
<span class="authorizedheading">[% authorize.heading %]</span>
[% END %]
[% IF ( marcflavour == 'UNIMARC' ) %]
[% FOREACH note IN summary.notes %]

View File

@ -35,6 +35,8 @@ function showChildren(mynumber) {
<div class="yui-b"><div class="yui-g">
<div id="userauthdetails" class="container">
<div id="views"><span class="view"><a id="MARCview" href="/cgi-bin/koha/opac-authoritiesdetail.pl?authid=[% authid %]">Normal view</a></span> <span class="view"><span id="MARCview">MARC view</span></span></div>
[% IF ( displayhierarchy ) %]
<div class="hierarchies">

View File

@ -0,0 +1,173 @@
[% BLOCK authtypelabel %]
[% UNLESS ( type=='seefrom' || type=='seealso' || type=='' ) %]
<span class="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 %]</span>
[% END %]
[% END %]
[% BLOCK otherscript %]
[% FOREACH heading IN headings %]
[% IF heading.category == wantcategory %]
[% IF heading.direction == 'ltr' %]
<div class="heading otherscript [% heading.category %]">
<span class="[% heading.category %]">[% heading.term %]</span>
</div>
[% ELSIF heading.direction == 'rtl' %]
<div class="heading otherscript [% heading.category %] rtl">
<span class="[% heading.category %]">[% heading.term %]</span>
</div>
[% END %]
[% END %]
[% END %]
[% END %]
[% BLOCK authheadingdisplay %]
[% IF authid %]<a href="/cgi-bin/koha/opac-authoritiesdetail.pl?authid=[% authid %]">[% heading %]</a>
[% ELSIF search %]<a href="/cgi-bin/koha/opac-authorities-home.pl?op=do_search&type=opac&operator=contains&marclist=mainentry&and_ora=and&orderby=HeadingAsc&value=[% search %]">[% heading %]</a>
[% ELSE %][% heading %]
[% END %]
[% END %]
[% INCLUDE 'doc-head-open.inc' %][% IF ( LibraryNameTitle ) %][% LibraryNameTitle %][% ELSE %]Koha online[% END %] catalog &rsaquo; Entry
[% INCLUDE 'doc-head-close.inc' %]
[% IF ( displayhierarchy ) %]
<link rel="stylesheet" type="text/css" href="[% themelang %]/css/hierarchy.css">
[% END %]
<script language="JavaScript" type="text/javascript">
$(document).ready(function() {
$('#authdescriptions').tabs();
});
[% IF ( displayhierarchy ) %]
function showParents(mynumber) {
var parents=document.getElementsByName(mynumber+'p')
for(i=0;i<parents.length;i++){
if (parents[i].style.display == "none") {
parents[i].style.display ="block";
} else {
parents[i].style.display ="none";
}
}
}
function showChildren(mynumber) {
var children=document.getElementsByName(mynumber+'c')
for(i=0;i<children.length;i++){
if (children[i].style.display == "none") {
children[i].style.display = "block";
} else {
children[i].style.display = "none";
}
}
}
[% END %]
</script>
</head>
<body id="opac-authoritiesdetail">
<div id="doc3" class="yui-t1">
<div id="bd">
[% INCLUDE 'masthead.inc' %]
<div id="yui-main">
<div class="yui-b"><div class="yui-g">
<div id="views"><span class="view"><span id="Normalview">Normal view</span></span> <span class="view"><a id="MARCview" href="/cgi-bin/koha/opac-authoritiesdetail.pl?authid=[% authid %]&marc=1">MARC view</a></span></div>
<div id="userauthdetails" class="container">
[% IF ( displayhierarchy ) %]
<div class="hierarchies">
[% FOREACH loophierarchie IN loophierarchies %]
<div class="hierarchy">
[% FOREACH loopelemen IN loophierarchie.loopelement %]
<div id="[% loopelemen.loopauthid %]" class="[% loopelemen.class %]">
[% IF ( loopelemen.current_value ) %]
[% loopelemen.value %]
[% ELSE %]
<a href="opac-authoritiesdetail.pl?authid=[% loopelemen.loopauthid %]" title="Term">[% loopelemen.value %]</a>
[% END %]
[% IF ( loopelemen.ifchildren ) %]
<sub><a class="parents" title="Narrower terms" href="JavaScript:showChildren('[% loopelemen.loopauthid %]');">+</a></sub><br/>
[% FOREACH loopchildre IN loopelemen.loopchildren %]
<div name="[% loopchildre.loopauthid %]c" class="child"> <a href="opac-authoritiesdetail.pl?authid=[% loopchildre.childauthid %]">[% loopchildre.childvalue %]</a></div>
[% END %]
[% END %]
</div>
[% END %]
</div>
[% END %]
</div>
[% END %]
<h1>[% summary.mainentry %][% IF authtypetext %]([% authtypetext %])[% END %]</h1>
<div class="usedin">Used in <a href="opac-search.pl?type=opac&amp;q=[% authid %]&amp;idx=an,phr">[% count %] records</a></div>
<div class="authstanza">
[% FOREACH authorize IN summary.authorized %]
<div class="heading authorized auth[% seefro.field %]"><span class="label">Preferred form: </span><span class="authorized">[% authorize.heading %]</span></div>
[% END %]
[% PROCESS otherscript headings=summary.otherscript wantcategory='preferred' %]
</div>
[% IF summary.seefrom.size %]
<div class="authstanza seefrom">
<div class="authstanzaheading">Used for/see from:</div>
<ul class="seefrom">
[% FOREACH seefro IN summary.seefrom %]
<li class="heading seefrom auth[% seefro.field %]">
[% IF seefro.type && seefro.type != 'seefrom' %]<span class="label">[% PROCESS authtypelabel type=seefro.type | trim %]:</span>[% END %]
<span class="seefrom">[% PROCESS authheadingdisplay heading=seefro.heading search=seefrosearch authid=seefro.authid %]</span>
</li>
[% END %]
[% PROCESS otherscript headings=summary.otherscript wantcategory='seefrom' %]
</div>
[% END %]
[% IF summary.seealso.size %]
<div class="authstanza seealso">
<div class="authstanzaheading">See also:</div>
<ul class="seelso">
[% FOREACH seeals IN summary.seealso %]
<li class="heading seealso auth[% seeals.field %]">[% IF seeals.type && seeals.type != 'seealso' %]<span class="label">[% PROCESS authtypelabel type=seeals.type | trim %]:</span>[% END %]
<span class="seealso">[% PROCESS authheadingdisplay heading=seeals.heading search=seeals.search authid=seeals.authid %]</span>
</li>
[% END %]
[% PROCESS otherscript headings=summary.otherscript wantcategory='seealso' %]
</div>
[% END %]
[% IF marcflavour == 'UNIMARC' && summary.otherscript %]
<div class="authstanza">
[% FOREACH otherscrip IN summary.otherscript %]
<div class="heading otherscript auth[% otherscrip.field %]"><span class="label">See also[% PROCESS language lang=otherscript.lang | trim %] term:</span>
<span class="otherscript">[% otherscrip.term %]</span>
</div>
[% END %]
</div>
[% END %]
<div id="authdescriptions" class="toptabs">
<ul>
<li id="tab_descriptions" class="ui-tabs-selected"><a href="#descriptions">Notes</a></li>
</ul>
<div id="descriptions">
<div class="content_set">
[% FOREACH note IN summary.notes %]
<p class="note auth[% note.field %]">[% note.note %]</p>
[% END %]
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
[% IF ( OpacNav ) %]
<div class="yui-b">
<div id="leftmenus" class="container">
[% INCLUDE 'navigation.inc' %]
</div>
</div>[% END %]
</div>
[% INCLUDE 'opac-bottom.inc' %]

View File

@ -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,";
}
chop $biblio_fields;
# fill arrays
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 %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 );
}
}
$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'},
};
{ value => $thisauthtype,
selected => $thisauthtype eq $authtypecode,
authtypetext => $authtypes->{$thisauthtype}{'authtypetext'},
};
}
$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;
# 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 %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 );
}
}
$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;