# filters.
sub basic_opac_copy_query {
- # Pass a defined value for $rec_id OR $iss_id, not both.
- my ($self, $rec_id, $iss_id, $copy_limit, $copy_offset, $staff) = @_;
+ ######################################################################
+ # Pass a defined value for either $rec_id OR ($iss_id AND $dist_id), #
+ # not both. #
+ ######################################################################
+ my ($self,$rec_id,$iss_id,$dist_id,$copy_limit,$copy_offset,$staff) = @_;
return {
select => {
sitem => {
fkey => 'id',
field => 'unit',
- filter => {issuance => $iss_id}
+ filter => {issuance => $iss_id},
+ join => {
+ sstr => { }
+ }
}
) : ()),
acn => {
'+acp' => {
deleted => 'f',
($staff ? () : (opac_visible => 't'))
- }
+ },
+ ($dist_id ? ( '+sstr' => { distribution => $dist_id } ) : ())
},
order_by => [
# This is a helper for grouped_holdings_for_summary() later.
sub _opac_visible_unit_data {
- my ($issuance_id_list, $staff, $e) = @_;
+ my ($issuance_id_list, $dist_id, $staff, $e) = @_;
+
+ return {} unless @$issuance_id_list;
my $rows = $e->json_query(
$U->basic_opac_copy_query(
- undef, $issuance_id_list,
+ undef, $issuance_id_list, $dist_id,
1000, 0, # XXX no mechanism for users to page at this level yet
$staff
)
# Now get the top level of holdings.
my $top = $e->json_query({
select => {
+ sstr => ["distribution"],
"smhc_$subfield" => ["value"], (
$subfield eq $deepest_level ?
(siss => [qw/id label date_published/]) : ()
pop @$top;
}
+ # Distribution is the same for all rows anyway, but we may need it for a
+ # copy query later.
+ my $dist_id = @$top ? $top->[0]->{distribution} : undef;
+
# This will help us avoid certain repetitive calculations. Examine
# _label_holding_level() to see what I mean.
my $mfhd_cache = {};
if ($with_units and $subfield eq $deepest_level) {
$unit_data = _opac_visible_unit_data(
- [map { $_->{id} } @$top], $with_units > 1, $e
+ [map { $_->{id} } @$top], $dist_id, $with_units > 1, $e
);
return $unit_data if defined $U->event_code($unit_data);
}
# Prepare related unit data if appropriate.
if ($with_units and $subfield eq $deepest_level) {
$unit_data = _opac_visible_unit_data(
- [map { $_->{id} } @$level], $with_units > 1, $e
+ [map { $_->{id} } @$level], $dist_id, $with_units > 1, $e
);
return $unit_data if defined $U->event_code($unit_data);
}
my $copy_offset = shift;
my $query = $U->basic_opac_copy_query(
- $rec_id, undef, $copy_limit, $copy_offset, $self->ctx->{is_staff}
+ $rec_id, undef, undef, $copy_limit, $copy_offset, $self->ctx->{is_staff}
);
# XXX In the future, $sort_org should be understood to be an abstration
"open-ils.serial.holdings.grouped_by_summary",
$summary_type, $summary_id,
$expand_path, $expand_limit, $expand_offsets,
- $auto_expand_first
+ $auto_expand_first,
+ 1 + ($self->ctx->{is_staff} ? 1 : 0)
)->gather(1);
if ($holdings and ref $holdings eq "ARRAY") {
[%-
-FOREACH copy_info IN ctx.copies;
+
+# If being used in serial mode, flatten list of units so that they can be
+# used like one long list of copies without changing so much code below.
+IF serial_holdings;
+ copies = [];
+ FOREACH h IN serial_holdings;
+ units = h.units.slice(0); # copy
+ FOREACH unit IN units;
+ unit.holding_label = h.label;
+ END;
+ copies = copies.merge(units);
+ END;
+END;
+
+FOREACH copy_info IN copies;
IF copy_info.call_number_label != '##URI##';
has_copies = 'true';
END;
LAST;
END;
END;
-%]
+-%]
[%- IF has_copies; %]
<table cellpadding="0" cellspacing="0" border="0" width="100%" id="rdetails_status">
<thead>
<tr>
+ [% IF serial_holdings -%]
+ <th id='copy_header_holding_label'>[% l("Holding Label") %]</th>
+ [%- ELSE -%]
<th id='copy_header_library'>[% l("Location") %]</th>
+ [%- END %]
<th id='copy_header_callnmber'>[% l("Call Number") %]</th>
[%- IF has_parts == 'true' %]
<th id='copy_header_part'>[% l("Part") %]</th>
[%- IF ctx.is_staff %]
<th id='copy_header_age_hold'>[% l("Age Hold Protection") %]</th>
<th id='copy_header_create_date'>[% l("Create Date") %]</th>
+ [%- END %]
+ [%- IF ctx.is_staff OR serial_holdings %]
<th id='copy_header_holdable'>[% l("Holdable?") %]</th>
[%- END %]
<th id='copy_header_status'>[% l("Status") %]</th>
</thead>
<tbody class="copy_details_table">
[%- last_cn = 0;
- FOR copy_info IN ctx.copies;
+ FOR copy_info IN copies;
callnum = copy_info.call_number_label;
NEXT IF callnum == '##URI##';
END;
-%]
<tr>
- <td header='copy_header_library'>
+ [%- IF serial_holdings %]<td header='copy_header_holding_label' class='rdetail-issue-issue'>
+ [%- copy_info.holding_label | html; -%]
+ </td>
+ [%- ELSE %]<td header='copy_header_library'>
[%-
org_name = ctx.get_aou(copy_info.circ_lib).name;
org_name | html
-%]
- </td>
+ </td>[% END %]
<td header='copy_header_callnumber'>[% callnum | html %] [% IF ctx.get_org_setting(CGI.param('loc') OR ctx.aou_tree.id, 'sms.enable') == 1 %](<a href="[% mkurl(ctx.opac_root _ '/sms_cn', {copy_id => copy_info.id}) %]">Text</a>)[% END %]</td>
[%- IF has_parts == 'true' %]
<td header='copy_header_part'>[% copy_info.part_label | html %]</td>
ctx.parse_datetime(copy_info.create_date),
DATE_FORMAT
) %]</td>
+ [% END # is_staff %]
+ [% IF ctx.is_staff OR serial_holdings %]
<td header='copy_header_holdable'>[% # Show copy/volume hold links to staff (without
# checking whether they have permissions to do those).
- overall_holdable = (copy_info.holdable == 't' AND
+ overall_holdable = (
+ copy_info.holdable == 't' AND
copy_info.location_holdable == 't' AND
copy_info.status_holdable == 't');
IF overall_holdable;
- l("Place on"); %]
+ l("Place on");
+ IF ctx.is_staff;
+ %]
<a href="[% mkurl(ctx.opac_root _ '/place_hold',
{hold_target => copy_info.id, hold_type => 'C', hold_source_page => mkurl()}) %]">[% l("copy") %]</a>
[%- IF copy_info.call_number != last_cn;
<a href="[% mkurl(ctx.opac_root _ '/place_hold',
{hold_target => copy_info.call_number, hold_type => 'V', hold_source_page => mkurl()}) %]">[% l("volume") %]</a>
[%- END;
+ IF serial_holdings;
+ l(" / ");
+ END;
+ END;
+ IF serial_holdings;
+ %]
+ <a class="rdetail-issue-place-hold"
+ href="[% mkurl(ctx.opac_root _ '/place_hold', {
+ hold_target => copy_info.issuance, hold_type => 'I',
+ hold_source_page => mkurl()
+ }) %]">[% l("holding") %]</a>[%-
+ END;
ELSE;
l("No");
END %]</td>
</tr>
[%- END %]
<tr>
- [%- IF ctx.copy_offset > 0;
+ [%- IF ctx.copy_offset > 0 AND NOT serial_holdings;
new_offset = ctx.copy_offset - ctx.copy_limit;
IF new_offset < 0; new_offset = 0; END %]
<td>
l('Previous [_1]', ctx.copy_offset - new_offset) %]</a>
</td>
[%- END %]
- [%- IF ctx.copies.size >= ctx.copy_limit %]
+ [%- IF copies.size >= ctx.copy_limit AND NOT serial_holdings %]
<td>
<a href="[% mkurl('', {copy_offset => ctx.copy_offset + ctx.copy_limit, copy_limit => ctx.copy_limit}) %]">[%
l('Next [_1]', ctx.copy_limit) %] »</a>
</td>
[%- END %]
</tr>
+ [% IF NOT serial_holdings -%]
<tr>
<td>
[%- more_copies_limit = 50 %] [%# TODO: config %]
- [%- IF ctx.copy_limit != more_copies_limit AND ctx.copies.size >= ctx.copy_limit %]
+ [%- IF ctx.copy_limit != more_copies_limit AND copies.size >= ctx.copy_limit %]
<div class="rdetail_show_copies">
<img src="[% ctx.media_prefix %]/images/plus_sign.png" />
<a href="[% mkurl('', {copy_limit => more_copies_limit, copy_offset => 0}) %]">[% l('Show more copies') %]</a>
[%- END %]
</td>
</tr>
+ [%- END %]
</tbody>
</table>
[% END; %]
--- /dev/null
+[%-
+expand_path = CGI.param('sepath') || [];
+seoffset_list = CGI.param('seoffset') || [];
+IF expand_path.size == 0 AND seoffset_list.size == 0;
+ seoffset_list = [0,0]; # compensate for $auto_expand_first; see ML
+END;
+
+selimit = CGI.param('selimit') || 10;
+ght_sepath = [];
+ght_depth = 0;
+
+VIEW grouped_holding_tree;
+ BLOCK list;
+ '<div class="rdetail-holding-group">';
+ prev_seoffset_list = seoffset_list.slice(0, ght_depth + 1);
+ next_seoffset_list = seoffset_list.slice(0, ght_depth + 1);
+
+ prev_seoffset_list.$ght_depth = prev_seoffset_list.$ght_depth - selimit;
+ IF prev_seoffset_list.$ght_depth < 0;
+ prev_seoffset_list.$ght_depth = 0;
+ END;
+
+ next_seoffset_list.$ght_depth = next_seoffset_list.$ght_depth + selimit;
+ IF item.0.units.size;
+ INCLUDE "opac/parts/record/copy_table.tt2" serial_holdings=item;
+ "<hr />";
+ "</div>";
+ ELSE;
+ FOREACH node IN item;
+ IF NOT node.label;
+ has_more = 1;
+ LAST;
+ END;
+
+ IF node.value;
+ ght_sepath.push(node.value);
+ all_balls = [];
+ FOREACH i IN [-1 .. ght_depth]; # aka [0 .. ght_depth+1]
+ all_balls.push(0);
+ END;
+
+ expand_link = mkurl(
+ '', {'sepath' => ght_sepath, 'seoffset' => all_balls},
+ 0, 'issues'
+ );
+
+ collapse_sepath = ght_sepath.slice(0, -2);
+ IF collapse_sepath.size == 0;
+ collapse_clear_params = ['sepath'];
+ ELSE;
+ collapse_clear_params = 0;
+ END;
+
+ collapse_link = mkurl(
+ '', {
+ 'sepath' => collapse_sepath,
+ 'seoffset' => all_balls.slice(0, -2)
+ }, collapse_clear_params, 'issues'
+ );
+
+ "<div class='rdetail-holding-group'><a href='";
+ IF node.children.size;
+ collapse_link;
+ ELSE;
+ expand_link;
+ END;
+ "'>"; node.label; "</a></div>";
+
+ IF node.children.size;
+ ght_depth = ght_depth + 1;
+ view.print(node.children);
+ ght_depth = ght_depth - 1;
+ END;
+
+ waste = ght_sepath.pop;
+ ELSE;
+ "<div class='rdetail-holding-group'>"; node.label; "</div>";
+ # XXX Hold placement link here? Maybe not if no units.
+ END;
+ END;
+ IF seoffset_list.$ght_depth > 0;
+ '<a href="';
+ mkurl('', {seoffset => prev_seoffset_list}, 0, 'issues');
+ '">'; l('Previous'); '</a>';
+ END;
+ IF has_more;
+ '<a href="';
+ mkurl('', {seoffset => next_seoffset_list}, 0, 'issues');
+ '">'; l('Next'); '</a>';
+ END;
+ '</div>';
+ END;
+ END;
+END;
+
+VIEW holding_summary_tree;
+ BLOCK hash;
+ '<div class="rdetail-holding-group">';
+ ctx.get_aou(item.org_unit).name; "<br />";
+ FOREACH summary IN item.holding_summaries;
+ IF summary.holdings;
+ link = mkurl(
+ '', {},
+ ['sid','stype','selimit','sepath','seoffset'], 'issues'
+ );
+ link_title = l('Collapse');
+ ELSE;
+ link = mkurl(
+ '', {sid => summary.id, stype => summary.summary_type},
+ ['selimit','sepath','seoffset'], 'issues'
+ );
+ link_title = l('Expand');
+ END;
+ '<span><a href="' _ link _ '" title="' _ link_title _ '">';
+ summary.generated_coverage.join(", ");
+ '</a></span><br />';
+ IF summary.holdings;
+ grouped_holding_tree.print(summary.holdings);
+ END;
+ END;
+ FOREACH child IN item.children;
+ view.print(child);
+ END;
+ '</div>';
+ END;
+END %]
+ <div class="holding-summary-tree">
+ [% holding_summary_tree.print(ctx.holding_summary_tree) %]
+ </div>
+ <div class="holding-summary-tree-pager">
+ [% slimit = CGI.param('slimit') || 10;
+ soffset = CGI.param('soffset') || 0;
+ soffset_prev = soffset - slimit;
+ IF soffset_prev < 0; soffset_prev = 0; END;
+ soffset_next = soffset + slimit;
+ %]
+ [% IF soffset > 0 %]
+ <a href="[% mkurl('', {soffset => soffset_prev}, ['sid','stype','sepath','selimit','seoffset'], 'issues') %]>[% l('Previous') %]</a>
+ [% END %]
+ [% IF ctx.holding_summary_tree.more %]
+ <a href="[% mkurl('', {soffset => soffset_next}, ['sid','stype','sepath','selimit','seoffset'], 'issues') %]">[% l('Next') %]</a>
+ [% END %]
+ </div>
--- /dev/null
+[% IF ctx.mfhd_summaries.size; %]
+ <div class="rdetail-mfhd-holdings">
+ <table><tbody>
+[%
+ mfhd = {
+ basic_holdings = l('Volumes'),
+ basic_holdings_add = l('Additional Volume Information'),
+ supplement_holdings = l('Supplements'),
+ supplement_holdings_add = l('Additional Supplement Information'),
+ index_holdings = l('Indexes'),
+ index_holdings_add = l('Additional Index Information'),
+ online = l('Online'),
+ missing = l('Missing'),
+ incomplete = l('Incomplete'),
+ };
+
+ FOREACH serial IN ctx.mfhd_summaries;
+%]
+ <tr>
+ <td class="rdetail-mfhd-head" colspan="2">[% l('Holdings summary ([_1])', serial.location) %]</td>
+ </tr>
+[%
+ FOREACH type IN mfhd.keys;
+ NEXT UNLESS serial.$type.size;
+%]
+ <tr>
+ <td class="rdetail-mfhd-type">[% mfhd.$type %]</td>
+ <td class="rdetail-mfhd-contents">[%
+ FOR thing IN serial.$type;
+ thing.join(", ");
+ END %]</td>
+ </tr>
+ [% END %]
+ <tr>
+ <td class="rdetail-mfhd-foot" colspan="2"> </td>
+ </tr>
+ [% END %]
+ </tbody></table>
+ </div>
+[% END %]
-<div class='rdetail_extras_div'>[%
-expand_path = CGI.param('sepath') || [];
-seoffset_list = CGI.param('seoffset') || [];
-IF expand_path.size == 0 AND seoffset_list.size == 0;
- seoffset_list = [0,0]; # compensate for $auto_expand_first; see ML
-END;
-
-selimit = CGI.param('selimit') || 10;
-ght_sepath = [];
-ght_depth = 0;
-
-VIEW grouped_holding_tree;
- BLOCK list;
- '<ul class="rdetail-holding-group">';
- prev_seoffset_list = seoffset_list.slice(0, ght_depth + 1);
- next_seoffset_list = seoffset_list.slice(0, ght_depth + 1);
-
- prev_seoffset_list.$ght_depth = prev_seoffset_list.$ght_depth - selimit;
- IF prev_seoffset_list.$ght_depth < 0;
- prev_seoffset_list.$ght_depth = 0;
- END;
-
- next_seoffset_list.$ght_depth = next_seoffset_list.$ght_depth + selimit;
- FOREACH node IN item;
- IF NOT node.label;
- has_more = 1;
- LAST;
- END;
-
- IF node.value;
- ght_sepath.push(node.value);
- all_balls = [];
- FOREACH i IN [-1 .. ght_depth]; # aka [0 .. ght_depth+1]
- all_balls.push(0);
- END;
-
- expand_link = mkurl(
- '', {'sepath' => ght_sepath, 'seoffset' => all_balls},
- 0, 'issues'
- );
-
- collapse_sepath = ght_sepath.slice(0, -2);
- IF collapse_sepath.size == 0;
- collapse_clear_params = ['sepath'];
- ELSE;
- collapse_clear_params = 0;
- END;
-
- collapse_link = mkurl(
- '', {
- 'sepath' => collapse_sepath,
- 'seoffset' => all_balls.slice(0, -2)
- }, collapse_clear_params, 'issues'
- );
-
- "<li><a href='";
- IF node.children.size;
- collapse_link;
- ELSE;
- expand_link;
- END;
- "'>"; node.label; "</a></li>";
-
- IF node.children.size;
- ght_depth = ght_depth + 1;
- view.print(node.children);
- ght_depth = ght_depth - 1;
- END;
-
- waste = ght_sepath.pop;
- ELSE;
- "<li>"; node.label; "</li>"; # XXX hold placement link here
- END;
- END;
- IF seoffset_list.$ght_depth > 0;
- '<a href="';
- mkurl('', {seoffset => prev_seoffset_list}, 0, 'issues');
- '">'; l('Previous'); '</a>';
- END;
- IF has_more;
- '<a href="';
- mkurl('', {seoffset => next_seoffset_list}, 0, 'issues');
- '">'; l('Next'); '</a>';
- END;
- '</ul>';
- END;
-END;
-
-VIEW holding_summary_tree;
- BLOCK hash;
- '<ul>';
- '<span class="rdetail-issue-org-unit">';
- ctx.get_aou(item.org_unit).name;
- '</span>';
- FOREACH summary IN item.holding_summaries;
- IF summary.holdings;
- link = mkurl(
- '', {},
- ['sid','stype','selimit','sepath','seoffset'], 'issues'
- );
- link_title = l('Collapse');
- ELSE;
- link = mkurl(
- '', {sid => summary.id, stype => summary.summary_type},
- ['selimit','sepath','seoffset'], 'issues'
- );
- link_title = l('Expand');
- END;
- '<li><a href="' _ link _ '" title="' _ link_title _ '">';
- summary.generated_coverage.join(", ");
- '</a></li>';
- IF summary.holdings;
- grouped_holding_tree.print(summary.holdings);
- END;
- END;
- FOREACH child IN item.children;
- view.print(child);
- END;
- '</ul>';
- END;
-END %]
-<div class="holding-summary-tree">
-[% holding_summary_tree.print(ctx.holding_summary_tree) %]
-</div>
-<div class="holding-summary-tree-pager">
- [% slimit = CGI.param('slimit') || 10;
- soffset = CGI.param('soffset') || 0;
- soffset_prev = soffset - slimit;
- IF soffset_prev < 0; soffset_prev = 0; END;
- soffset_next = soffset + slimit;
- %]
- [% IF soffset > 0 %]
- <a href="[% mkurl('', {soffset => soffset_prev}, ['sid','stype','sepath','selimit','seoffset'], 'issues') %]>[% l('Previous') %]</a>
- [% END %]
- [% IF ctx.holding_summary_tree.more %]
- <a href="[% mkurl('', {soffset => soffset_next}, ['sid','stype','sepath','selimit','seoffset'], 'issues') %]">[% l('Next') %]</a>
- [% END %]
-</div>
-[% IF ctx.mfhd_summaries.size; %]
- <div class="rdetail-mfhd-holdings">
- <table><tbody>
-[%
- mfhd = {
- basic_holdings = l('Volumes'),
- basic_holdings_add = l('Additional Volume Information'),
- supplement_holdings = l('Supplements'),
- supplement_holdings_add = l('Additional Supplement Information'),
- index_holdings = l('Indexes'),
- index_holdings_add = l('Additional Index Information'),
- online = l('Online'),
- missing = l('Missing'),
- incomplete = l('Incomplete'),
- };
-
- FOREACH serial IN ctx.mfhd_summaries;
-%]
- <tr>
- <td class="rdetail-mfhd-head" colspan="2">[% l('Holdings summary ([_1])', serial.location) %]</td>
- </tr>
-[%
- FOREACH type IN mfhd.keys;
- NEXT UNLESS serial.$type.size;
-%]
- <tr>
- <td class="rdetail-mfhd-type">[% mfhd.$type %]</td>
- <td class="rdetail-mfhd-contents">[%
- FOR thing IN serial.$type;
- thing.join(", ");
- END %]</td>
- </tr>
- [% END %]
- <tr>
- <td class="rdetail-mfhd-foot" colspan="2"> </td>
- </tr>
- [% END %]
- </tbody></table>
- </div>
-[% END %]
+<div class='rdetail_extras_div'>
+ [% INCLUDE 'opac/parts/record/issues-db.tt2' %]
+ [% INCLUDE 'opac/parts/record/issues-mfhd.tt2' %]
</div>
ctx.record_hold_count, ctx.copy_summary.0.count) %]
</p>
</span>
-[%- INCLUDE "opac/parts/record/copy_table.tt2" %]
+[%- INCLUDE "opac/parts/record/copy_table.tt2" copies=ctx.copies %]
</div>
[%- END %]
table.result_holdings_table thead tr th {
font-weight: bold;
}
+.rdetail-holding-group { margin-left: 1.5em; }
+.rdetail-holding-group span { margin-left: 1.5em; }