LP#1053397 MR search, results display, and holds
authorBill Erickson <berick@esilibrary.com>
Mon, 20 Jan 2014 20:54:35 +0000 (15:54 -0500)
committerBill Erickson <berick@esilibrary.com>
Mon, 10 Feb 2014 16:00:28 +0000 (11:00 -0500)
Signed-off-by: Bill Erickson <berick@esilibrary.com>
Open-ILS/src/perlmods/lib/OpenILS/Application/Circ/Holds.pm
Open-ILS/src/perlmods/lib/OpenILS/WWW/EGCatLoader/Account.pm
Open-ILS/src/perlmods/lib/OpenILS/WWW/EGCatLoader/Search.pm
Open-ILS/src/perlmods/lib/OpenILS/WWW/EGCatLoader/Util.pm
Open-ILS/src/templates/opac/myopac/holds/edit.tt2
Open-ILS/src/templates/opac/parts/advanced/search.tt2
Open-ILS/src/templates/opac/parts/metarecord_hold_filters.tt2 [new file with mode: 0644]
Open-ILS/src/templates/opac/parts/place_hold.tt2
Open-ILS/src/templates/opac/parts/result/table.tt2
Open-ILS/src/templates/opac/results.tt2
Open-ILS/web/js/ui/default/opac/simple.js

index 8ba48ab..00a0da1 100644 (file)
@@ -92,8 +92,15 @@ sub test_and_create_hold_batch {
     elsif ($$params{'hold_type'} eq 'P') { $target_field = 'partid'; }
     else { return undef; }
 
+    my $formats_map = delete $$params{holdable_formats_map};
+
     foreach (@$target_list) {
         $$params{$target_field} = $_;
+
+        # copy the requested formats from the target->formats map
+        # into the top-level formats attr for each hold
+        $$params{holdable_formats} = $formats_map->{$_};
+
         my $res;
         ($res) = $self->method_lookup(
             'open-ils.circ.title_hold.is_possible')->run($auth, $params, $override ? $oargs : {});
index 61b1028..82f6013 100644 (file)
@@ -575,6 +575,9 @@ sub fetch_user_holds {
                     [$blob->{hold}->{bre_id}], undef, {flesh => '{mra}'}
                 );
                 $blob->{marc_xml} = $data[0]->{marc_xml};
+                my $hold = $blob->{hold}->{hold};
+                $blob->{metarecord_ccvms} = $self->get_mr_ccvms($hold->target)
+                    if $hold->hold_type eq 'M';
                 push(@holds, $blob);
             }
         }
@@ -777,6 +780,46 @@ sub load_place_hold {
     };
 
     my $type_dispatch = {
+        M => sub {
+
+            # target metarecords
+            my $mrecs = $e->batch_retrieve_metabib_metarecord([
+                \@targets, 
+                {flesh => 1, flesh_fields => {mmr => ['master_record']}}], 
+                {substream => 1}
+            );
+
+            for my $id (@targets) {
+                my ($mr) = grep {$_->id eq $id} @$mrecs;
+
+                my $avail_attrs = $self->get_mr_ccvms($mr->id);
+                my $format_attr = $avail_attrs->{formats}{attr};
+
+                # during hold placement submission, the user selects
+                # which of the available formats/langs are acceptiable.
+                # Capture those here as the holdable_formats for the MR hold.
+                my @selected_formats = $cgi->param('metarecord_formats_' . $mr->id);
+                my @selected_langs = $cgi->param('metarecord_langs_' . $mr->id);
+
+                # map the selected attrs into the JSON holdable_formats structure
+                @selected_formats = map {
+                    {_attr => $format_attr, _val => $_} } @selected_formats;
+                @selected_langs = map {
+                    {_attr => 'item_lang', _val => $_} } @selected_langs;
+
+                my $holdable_formats = OpenSRF::Utils::JSON->perl2JSON({
+                    0 => \@selected_formats,
+                    1 => \@selected_langs
+                });
+
+                push(@hold_data, $data_filler->({
+                    target => $mr, 
+                    record => $mr->master_record,
+                    metarecord_ccvms => $avail_attrs,
+                    holdable_formats => $holdable_formats
+                }));
+            }
+        },
         T => sub {
             my $recs = $e->batch_retrieve_biblio_record_entry(\@targets, {substream => 1});
 
@@ -984,13 +1027,25 @@ sub attempt_hold_placement {
 
     if(@create_targets) {
 
+        # holdable formats may be different for each MR hold.
+        # map each set to the ID of the target.
+        my $holdable_formats = {};
+        if ($hold_type eq 'M') {
+            $holdable_formats->{$_->{target_id}} = 
+                $_->{holdable_formats} for @hold_data;
+            # TODO: cleanup
+            warn "MR Holdable formats " . Dumper($holdable_formats) . "\n";
+        }
+
         my $bses = OpenSRF::AppSession->create('open-ils.circ');
         my $breq = $bses->request( 
             $method, 
             $e->authtoken, 
-            $data_filler->({   patronid => $usr,
+            $data_filler->({   
+                patronid => $usr,
                 pickup_lib => $pickup_lib, 
-                hold_type => $hold_type
+                hold_type => $hold_type,
+                holdable_formats_map => $holdable_formats
             }),
             \@create_targets
         );
@@ -1053,6 +1108,52 @@ sub attempt_hold_placement {
     }
 }
 
+# fetches the CCVMs IDs representing available languages and formats 
+# for the constituent records of the selected metarecord.  
+sub get_mr_ccvms {
+    my ($self, $mr_id) = @_;
+    my $e = $self->editor;
+
+    # crad.name which defines the set of metarecord formats
+    my $format_attr = $self->ctx->{search_cgf}->( # leverage caching
+        name => 'opac.metarecord.holds.format_attr')->[0]->value;
+
+    my $bre_ids = 
+        $e->search_metabib_metarecord_source_map({metarecord => $mr_id});
+    $bre_ids = [map {$_->source} @$bre_ids];
+    
+    my $query = {
+        select => {ccvm => [{column => 'id', transform => 'distinct'}]},
+        from => {mraf => {
+            ccvm => {
+                fkey => 'attr',
+                field => 'ctype',
+                filter => {code => {'=' => {'+mraf' => 'value'}}}
+            }
+        }},
+        where => {'+mraf' => {id => $bre_ids, attr => ''}}
+    };
+
+    $query->{where}{'+mraf'}{attr} = 'item_lang';
+    my $langs = $e->json_query($query);
+
+    $query->{where}{'+mraf'}{attr} = $format_attr;
+    my $formats = $e->json_query($query);
+
+    return {
+        formats => {
+            attr => $format_attr,
+            values => [map { $_->{id} } @$formats],
+        },
+        langs => {
+            attr => 'item_lang',
+            values => [map { $_->{id} } @$langs]
+        }
+    };
+}
+
+
+
 sub fetch_user_circs {
     my $self = shift;
     my $flesh = shift; # flesh bib data, etc.
index 1a8740c..b02b596 100644 (file)
@@ -67,7 +67,8 @@ sub _prepare_biblio_search {
 
     foreach ($cgi->param('modifier')) {
         # The unless bit is to avoid stacking modifiers.
-        $query = ('#' . $_ . ' ' . $query) unless $query =~ qr/\#\Q$_/;
+        $query = ('#' . $_ . ' ' . $query) unless 
+            $query =~ qr/\#\Q$_/ or $_ eq 'metabib';
     }
 
     # filters
@@ -307,6 +308,13 @@ sub load_rresults {
     my $ctx = $self->ctx;
     my $e = $self->editor;
 
+    # 1. param->metarecord : view constituent bib records for a metarecord
+    # 2. param->modifier=metabib : perform a metarecord search
+    my $metarecord = $ctx->{metarecord} = $cgi->param('metarecord');
+    my @mods = $cgi->param('modifier');
+    my $is_meta = (@mods and grep {$_ eq 'metabib'} @mods and !$metarecord);
+    my $id_key = $is_meta ? 'mmr_id' : 'bre_id';
+
     # find the last record in the set, then redirect
     my $find_last = $cgi->param('find_last');
 
@@ -316,7 +324,9 @@ sub load_rresults {
         return $bbag_err;
     }
 
-    $ctx->{page} = 'rresult' unless $internal;
+    if (!$internal) {
+        $ctx->{page} = $is_meta ? 'mresult' : 'rresult';
+    }
     $ctx->{ids} = [];
     $ctx->{records} = [];
     $ctx->{search_facets} = {};
@@ -343,7 +353,6 @@ sub load_rresults {
     $ctx->{search_ou} = $self->_get_search_lib();
     $ctx->{pref_ou} = $self->_get_pref_lib() || $ctx->{search_ou};
     my $offset = $page * $limit;
-    my $metarecord = $cgi->param('metarecord');
     my $results; 
     my $tag_circs = $self->tag_circed_items;
     $self->timelog("Got search parameters");
@@ -411,12 +420,14 @@ sub load_rresults {
 
         $query = "$_ $query" for @facets;
 
-        $logger->activity("EGWeb: [search] $query");
+        my $ltag = $is_meta ? '[mmr search]' : '[bre search]';
+        $logger->activity("EGWeb: $ltag $query");
 
         try {
 
             my $method = 'open-ils.search.biblio.multiclass.query';
             $method .= '.staff' if $ctx->{is_staff};
+            $method =~ s/biblio/metabib/ if $is_meta;
 
             my $ses = OpenSRF::AppSession->create('open-ils.search');
 
@@ -443,6 +454,7 @@ sub load_rresults {
         my $rec_id = pop @$rec_ids;
         $cgi->delete('find_last');
         my $url = $cgi->url(-full => 1, -path => 1, -query => 1);
+        # TODO: metarecord => /rresults?metarecord=$mmr_id
         $url =~ s|/results|/record/$rec_id|;
         return $self->generic_redirect($url);
     }
@@ -451,12 +463,27 @@ sub load_rresults {
 
     $self->load_rresults_bookbag_item_notes($rec_ids) if $ctx->{bookbag};
 
+    my $fetch_recs = $rec_ids;
+
+    my $metarecord_master;
+    if ($metarecord) {
+        # when listing the contents of a metarecord, be sure to fetch
+        # the lead record for summary display.  Adding the ID to
+        # $fetch_recs lets us grab the record (if necessary) w/o it
+        # unintentially becoming a member of the result set.
+        my $mr = $e->retrieve_metabib_metarecord($metarecord);
+        push(@$fetch_recs, $mr->master_record)
+            unless grep {$_ eq $mr->master_record} @$fetch_recs;
+        $metarecord_master = $mr->master_record;
+    }
+
     $self->timelog("Calling get_records_and_facets()");
     my ($facets, @data) = $self->get_records_and_facets(
-        $rec_ids, $results->{facet_key}, 
+        $fetch_recs, $results->{facet_key}, 
         {
             flesh => '{holdings_xml,mra,acp,acnp,acns,bmp}',
             site => $site,
+            metarecord => $is_meta,
             depth => $depth,
             pref_lib => $ctx->{pref_ou},
         }
@@ -464,6 +491,7 @@ sub load_rresults {
     $self->timelog("Returned from get_records_and_facets()");
 
     if ($page == 0) {
+        # TODO: handle metarecords
         my $stat = $self->check_1hit_redirect($rec_ids);
         return $stat if $stat;
     }
@@ -473,15 +501,16 @@ sub load_rresults {
 
     # shove recs into context in search results order
     for my $rec_id (@$rec_ids) {
-        push(
-            @{$ctx->{records}},
-            grep { $_->{id} == $rec_id } @data
-        );
+        my ($rec) = grep { $_->{$id_key} == $rec_id } @data;
+        push(@{$ctx->{records}}, $rec);
+
+        $ctx->{metarecord_master} = $rec
+            if $metarecord_master and $metarecord_master eq $rec_id;
     }
 
     if ($tag_circs) {
         for my $rec (@{$ctx->{records}}) {
-            my ($res_rec) = grep { $_->[0] == $rec->{id} } @{$results->{ids}};
+            my ($res_rec) = grep { $_->[0] == $rec->{$id_key} } @{$results->{ids}};
             # index 1 in the per-record result array is a boolean which
             # indicates whether the record in question is in the users
             # accessible circ history list
index ce009dd..2bc2c16 100644 (file)
@@ -277,9 +277,13 @@ sub get_records_and_facets {
     $unapi_args->{depth} ||= $self->ctx->{aou_tree}->()->ou_type->depth;
     $unapi_args->{flesh_depth} ||= 5;
 
+    my $is_meta = delete $unapi_args->{metarecord};
+    my $unapi_type = $is_meta ? 'unapi.mmr' : 'unapi.bre';
+
     $unapi_cache ||= OpenSRF::Utils::Cache->new('global');
     my $unapi_cache_key_suffix = join(
         '_',
+        $is_meta || 0,
         $unapi_args->{site},
         $unapi_args->{depth},
         $unapi_args->{flesh_depth},
@@ -299,36 +303,59 @@ sub get_records_and_facets {
             $outer_self->timelog("get_records_and_facets(): got response content");
 
             # Protect against requests for non-existent records
-            return unless $data->{'unapi.bre'};
+            return unless $data->{$unapi_type};
 
-            my $xml = XML::LibXML->new->parse_string($data->{'unapi.bre'})->documentElement;
+            my $xml = XML::LibXML->new->parse_string($data->{$unapi_type})->documentElement;
 
             $outer_self->timelog("get_records_and_facets(): parsed xml");
             # Protect against legacy invalid MARCXML that might not have a 901c
             my $bre_id;
+            my $mmr_id;
             my $bre_id_nodes =  $xml->find('*[@tag="901"]/*[@code="c"]');
             if ($bre_id_nodes) {
                 $bre_id =  $bre_id_nodes->[0]->textContent;
             } else {
                 $logger->warn("Missing 901 subfield 'c' in " . $xml->toString());
             }
-            $tmp_data{$bre_id} = {id => $bre_id, marc_xml => $xml};
 
-            if ($bre_id) {
+            if ($is_meta) {
+                # extract metarecord ID from mmr.unapi tag
+                for my $node ($xml->getElementsByTagName('abbr')) {
+                    my $title = $node->getAttribute('title');
+                    ($mmr_id = $title) =~ 
+                        s/tag:open-ils.org:U2\@mmr\/(\d+)\/.*/$1/g;
+                    last if $mmr_id;
+                }
+            }
+
+            my $rec_id = $mmr_id ? $mmr_id : $bre_id;
+            $tmp_data{$rec_id} = {
+                id => $rec_id, 
+                bre_id => $bre_id, 
+                mmr_id => $mmr_id,
+                marc_xml => $xml
+            };
+
+            if ($rec_id) {
                 # Let other backends grab our data now that we're done.
-                my $key = 'TPAC_unapi_cache_'.$bre_id.'_'.$unapi_cache_key_suffix;
+                my $key = 'TPAC_unapi_cache_'.$rec_id.'_'.$unapi_cache_key_suffix;
                 my $cache_data = $unapi_cache->get_cache($key);
                 if ($$cache_data{running}) {
-                    $unapi_cache->put_cache($key, { id => $bre_id, marc_xml => $data->{'unapi.bre'} }, 10);
+                    $unapi_cache->put_cache($key, {
+                        bre_id => $bre_id,
+                        mmr_id => $mmr_id,
+                        id => $rec_id, 
+                        marc_xml => $data->{$unapi_type} 
+                    }, 10);
                 }
             }
 
-
             $outer_self->timelog("get_records_and_facets(): end of success handler");
         }
     );
 
-    $self->timelog("get_records_and_facets(): about to call unapi.bre via json_query (rec_ids has " . scalar(@$rec_ids));
+    $self->timelog("get_records_and_facets(): about to call ".
+        "$unapi_type via json_query (rec_ids has " . scalar(@$rec_ids));
 
     my @loop_recs = @$rec_ids;
     my %rec_timeout;
@@ -359,19 +386,26 @@ sub get_records_and_facets {
             $tmp_data{$unapi_data->{id}} = $unapi_data;
         } else { # we're the first or we timed out. success_handler will populate the real value
             $unapi_cache->put_cache($unapi_cache_key, { running => $$ }, 10);
+
+            my $sdepth = $unapi_args->{flesh_depth};
+            my $slimit = "acn=>$sdepth,acp=>$sdepth";
+            $slimit .= ",bre=>$sdepth" if $is_meta;
+            my $flesh = $unapi_args->{flesh} || '';
+
+            # tag the record with the MR id
+            $flesh =~ s/}$/,mmr.unapi}/g if $is_meta;
+
             $ses->request(
                 'open-ils.cstore.json_query',
                  {from => [
-                    'unapi.bre', $bid, 'marcxml','record', 
-                    $unapi_args->{flesh}, 
+                    $unapi_type, $bid, 'marcxml','record', $flesh,
                     $unapi_args->{site}, 
                     $unapi_args->{depth}, 
-                    'acn=>' . $unapi_args->{flesh_depth} . ',acp=>' . $unapi_args->{flesh_depth}, 
+                    $slimit,
                     undef, undef, $unapi_args->{pref_lib}
                 ]}
             );
         }
-
     }
 
 
index 271cdad..8e0a81d 100644 (file)
@@ -2,6 +2,7 @@
     PROCESS "opac/parts/misc_util.tt2";
     PROCESS "opac/parts/hold_status.tt2";
     PROCESS "opac/parts/org_selector.tt2";
+    PROCESS "opac/parts/metarecord_hold_filters.tt2";
     WRAPPER "opac/parts/myopac/base.tt2";
     myopac_page = "holds"; # in this case, just for tab coloring.
 
                 <strong>[% l('Format:') %]</strong>
                 <img src="[% attrs.format_icon %]" alt="[% attrs.format_label | html %]" title="[% attrs.format_label | html %]" />
             </p>[% END %]
+            [% IF hold.metarecord_ccvms.formats.values.size OR # should this be size > 1
+                  hold.metarecord_ccvms.langs.values.size > 1;
+                PROCESS metarecord_hold_filters_selector hold_data=hold;
+            END %]
             <p>
                 <strong>[% l('Status') %]</strong>: [% hold.human_status %]
             </p>
index 42e5cfc..1fbd037 100644 (file)
                 CASE "sort_selector";
                     INCLUDE "opac/parts/filtersort.tt2"
                         value=CGI.param('sort') class='results_header_sel';
+                    %]
 
-                CASE "copy_location" %]
+                    <!-- applies metarecord search -->
+                    <div class="adv_search_available">
+                        <input type='checkbox' name="modifier" value="metabib"
+                          [%- CGI.param('modifier').grep('metabib').size ? 
+                                ' checked="checked"' : '' %]
+                            id='opac.result.ismetabib' />
+                        <label for='opac.result.ismetabib'>
+                            [% l("Group Formats and Editions") %]</label>
+                    </div>
+
+                [% CASE "copy_location" %]
                     <select id="adv_copy_location_selector" 
                         aria-label="[% l('Select Shelving Location') %]"
                         name="fi:locations" size="3" multiple="multiple">
diff --git a/Open-ILS/src/templates/opac/parts/metarecord_hold_filters.tt2 b/Open-ILS/src/templates/opac/parts/metarecord_hold_filters.tt2
new file mode 100644 (file)
index 0000000..bc36bf2
--- /dev/null
@@ -0,0 +1,75 @@
+[%#
+Draws the format multi-select and the language multi-select for
+limiting the set of desired records for a given metarecord.
+%]
+
+<style>
+  /* TODO: MOVE ME */
+  .metarecord_filters {
+      padding: 5px;
+      margin-top: 5px;
+      border-bottom: 1px solid #333;
+      border-top: 1px solid #333;
+  }
+  .metarecord_filter_container {
+    float : left;
+    margin-right: 10px;
+  }
+  .metarecord_filter_container select {
+    padding: 2px;
+    width: 13em; /* consistent w/ adv search selectors */
+  }
+  .metarecord_filter_header {
+    padding-bottom: 5px;
+  }
+</style>
+
+[% BLOCK metarecord_hold_filters_selector;
+  format_ccvms = [];
+  lang_ccvms = [];
+  # some CCVMs have search_labels, some use the value as the label
+  # instead.  Accommodate both, starting with search_label
+  FOR ccvm_id IN hold_data.metarecord_ccvms.formats.values;
+    ccvm = ctx.get_ccvm(ccvm_id);
+    CALL ccvm.search_label(ccvm.value) UNLESS ccvm.search_label;
+    format_ccvms.push(ccvm);
+  END;
+  FOR ccvm_id IN hold_data.metarecord_ccvms.langs.values;
+    ccvm = ctx.get_ccvm(ccvm_id);
+    CALL ccvm.search_label(ccvm.value) UNLESS ccvm.search_label;
+    lang_ccvms.push(ccvm);
+  END;
+%]
+
+<div class="metarecord_filters">
+  <div class="metarecord_filter_container">
+    <div class="metarecord_filter_header">
+      <div>[% l('Select your desired format(s).') %]</div>
+    </div>
+    <select multiple='multiple' 
+      name="metarecord_formats_[% hold_data.target.id %]">
+      [% FOR ccvm IN format_ccvms.sort('search_label') %]
+        <option value="[% ccvm.code %]">
+          [% ccvm.search_label | html %]
+        </option>
+      [% END %]
+    </select>
+    <input type="hidden" 
+      name="metarecord_format_attr" value="[% format_ccvms.0.ctype %]"/>
+  </div>
+  <div class="metarecord_filter_container">
+    <div class="metarecord_filter_header">
+      [% l('Select your desired language(s)') %]
+    </div>
+    <select multiple='multiple' 
+      name="metarecord_langs_[% hold_data.target.id %]">
+      [% FOR lang_ccvm IN lang_ccvms.sort('search_label') %]
+        <option value="[% lang_ccvm.code %]">
+          [% lang_ccvm.search_label | html %]
+        </option>
+      [% END %]
+    </select>
+  </div>
+  <div class="clear-both">&nbsp;</div>
+</div>
+[% END # metarecord_hold_filters_selector %]
index f12cd56..8366843 100644 (file)
@@ -1,5 +1,6 @@
 [%  PROCESS "opac/parts/misc_util.tt2";
     PROCESS "opac/parts/hold_error_messages.tt2";
+    PROCESS "opac/parts/metarecord_hold_filters.tt2";
 %]
 
 <div id='holds_box' class='canvas' style='margin-top: 6px;'>
                         <input type='hidden' name='part' value=''/>
                         [% END %]
                     [% END %]
+                    [% IF hdata.metarecord_ccvms.formats.values.size OR # should this be size > 1
+                          hdata.metarecord_ccvms.langs.values.size > 1;
+                        PROCESS metarecord_hold_filters_selector hold_data=hdata;
+                    END %]
                 </td>
             </tr>
         [% END %]
index e960a63..b72e638 100644 (file)
                             IF CGI.param('detail_record_view');
                                 attrs.title = attrs.title_extended;
                             END;
+                            # note: rec.id refers to the record identifier, regardless
+                            # of the type of record. i.e. rec.id = mmr_id ? mmr_id : bre_id
+                            IF rec.mmr_id;
+                                # metarecords link to record list page
+                                record_url = mkurl(ctx.opac_root _ '/results', 
+                                    {metarecord => rec.mmr_id}, ['page']);
+                                hold_type = 'M';
+                            ELSE;
+                                record_url = mkurl(ctx.opac_root _ '/record/' _ rec.bre_id);
+                                hold_type = 'T';
+                            END;
                     -%]
                         <tr class="result_table_row">
                                             <td class="results_row_count" name="results_row_count">[%
                                                     result_count; result_count = result_count + 1
                                                 %].</td>
                                             <td class='result_table_pic_header'>
-                                                <a href="[% mkurl(ctx.opac_root _ '/record/' _ rec.id) %]"><img alt="[% l('Image of item') %]"
+                                                <a href="[% record_url %]"><img alt="[% l('Image of item') %]"
                                                         name='item_jacket' class='result_table_pic' width="55"
-                                                        src='[% ctx.media_prefix %]/opac/extras/ac/jacket/small/r/[% rec.id | uri %]' /></a><br />
+                                                        src='[% ctx.media_prefix %]/opac/extras/ac/jacket/small/r/[% rec.bre_id | uri %]' /></a><br />
                                             </td>
                                             <td class='result_table_title_cell' name='result_table_title_cell'>
                                                <div class="result_metadata">
-                                                    <abbr class="unapi-id" title='tag:[% ctx.hostname %],[% date.format(date.now, '%Y') %]:biblio-record_entry/[% rec.id %]'></abbr>
+                                                    [% IF rec.mmr_id %]
+                                                    <abbr class="unapi-id" 
+                                                      title='tag:[% ctx.hostname %],[% date.format(date.now, '%Y') %]:metabib-metarecord/[% rec.mmr_id %]'>
+                                                    </abbr>
+                                                    [% ELSE %]
+                                                    <abbr class="unapi-id" 
+                                                      title='tag:[% ctx.hostname %],[% date.format(date.now, '%Y') %]:biblio-record_entry/[% rec.bre_id %]'>
+                                                    </abbr>
+                                                    [% END %]
                                                     <a class='record_title' name='record_[% rec.id %]' name='item_title'
-                                                        href="[% mkurl(ctx.opac_root _ '/record/' _ rec.id) %]"
+                                                        href="[% record_url %]"
                                                         [% HTML.attributes(title => l('Display record details for "[_1]"', attrs.title)) %]
                                                         class='search_link'>[% attrs.title | html %]</a>
 [%-
@@ -294,7 +313,8 @@ END;
 %]
                                                         <div class="results_aux_utils place_hold"><a
                                                                 href="[% mkurl(ctx.opac_root _ '/place_hold',
-                                                                    {hold_target => rec.id, hold_type => 'T', hold_source_page => mkurl()}, ['query']) %]"
+                                                                    {hold_target => rec.id, hold_type => hold_type, 
+                                                                      hold_source_page => mkurl()}, ['query']) %]"
                                                                     name="place_hold_link" class="no-dec"><img
                                                                 src="[% ctx.media_prefix %]/images/green_check.png"
                                                                 alt=""/><span class="result_place_hold">[% l('Place Hold') %]</span></a>
index 5006800..7ea66a0 100644 (file)
     <form action="[% ctx.opac_root %]/results" method="get">
     [% INCLUDE "opac/parts/searchbar.tt2" took_care_of_form=1 %]
     <div class="almost-content-wrapper">
-        <div id="results_header_bar">
+
+        [%# hide the header bar when displaying metarecord constituents 
+          instead of skipping it altogether to allow the search form
+          variables to propagate %]
+        [% IF ctx.metarecord;
+          mr_attrs = {marc_xml => ctx.metarecord_master.marc_xml};
+          PROCESS get_marc_attrs args=mr_attrs %]
+          <div class="results_header_lbl">
+            [% l('Viewing Results for Grouped Record: [_1]', 
+                mr_attrs.title) | html %]
+          </div>
+        [% END %]
+        <div class="results_header_bar[%- IF ctx.metarecord %] hidden[% END -%]">
             <div id="results_header_inner">
                 <div class="results_header_btns">
                     <a href="[% mkurl(ctx.opac_root _ '/home', {$loc_name => loc_value}, 1) %]">[% l('Another Search') %]</a>
 
                     <label class="results_header_lbl">
                         <input type="checkbox" id="limit_to_available" name="modifier" value="available"
-                            onchange="limit_to_avail_onchange(this, true)"
+                            onchange="search_modifier_onchange('available', this, true)"
                             [% CGI.param('modifier').grep('available').size ? ' checked="checked"' : '' %] />
                         [% l('Limit to available items') %]
                     </label>
+                    <label class="results_header_lbl">
+                        <input type="checkbox" name="modifier" value="metabib"
+                            onchange="search_modifier_onchange('metabib', this, true)"
+                            [% CGI.param('modifier').grep('metabib').size ? ' checked="checked"' : '' %] />
+                        [% l('Group Formats and Editions') %]
+                    </label>
                     [% IF CGI.param('detail_record_view') %]
                         <input type="hidden" name="detail_record_view" value="1" />
                     [% END %]
index 6e3d29f..b491586 100644 (file)
@@ -74,10 +74,11 @@ function select_all_checkboxes(name, checked) {
     }
 }
 
-function limit_to_avail_onchange(checkbox, submitOnChange) {
+function search_modifier_onchange(type, checkbox, submitOnChange) {
     if (checkbox.form._adv && !checkbox.checked) {
         var search_box = $('search_box');
-        search_box.value = search_box.value.replace(/#available ?/g, "");
+        var reg = new RegExp('#' + type + ' ?', 'g');
+        search_box.value = search_box.value.replace(reg, "");
     }
 
     if (submitOnChange) {