LP#1005040: add filter control widgets to TPAC
authorMike Rylander <mrylander@gmail.com>
Tue, 20 Sep 2016 21:09:35 +0000 (17:09 -0400)
committerKathy Lussier <klussier@masslnc.org>
Thu, 9 Feb 2017 20:45:07 +0000 (15:45 -0500)
This patch also moves facet retrieval to after record retrieval, to
make sure facet data is available, and wait for it

Signed-off-by: Galen Charlton <gmc@esilibrary.com>

Open-ILS/src/perlmods/lib/OpenILS/Application/Search/Biblio.pm
Open-ILS/src/perlmods/lib/OpenILS/WWW/EGCatLoader/Search.pm
Open-ILS/src/perlmods/lib/OpenILS/WWW/EGCatLoader/Util.pm
Open-ILS/src/perlmods/lib/OpenILS/WWW/SuperCat.pm
Open-ILS/src/templates/opac/parts/result/adv_filter.tt2 [new file with mode: 0644]
Open-ILS/src/templates/opac/parts/result/table.tt2
Open-ILS/src/templates/opac/parts/searchbar.tt2

index f595c28..014d250 100644 (file)
@@ -16,7 +16,7 @@ use OpenSRF::Utils::Logger qw/:logger/;
 
 use OpenSRF::Utils::JSON;
 
-use Time::HiRes qw(time);
+use Time::HiRes qw(time sleep);
 use OpenSRF::EX qw(:try);
 use Digest::MD5 qw(md5_hex);
 
@@ -1142,7 +1142,7 @@ sub staged_search {
     $method .= '.staff' if $self->api_name =~ /staff$/;
     $method .= '.atomic';
                 
-    if (!$search_hash{query}) {
+    if (!$search_hash->{query}) {
         return {count => 0} unless (
             $search_hash and 
             $search_hash->{searches} and 
@@ -1407,6 +1407,14 @@ sub retrieve_cached_facets {
 
     return undef unless ($key and $key =~ /_facets$/);
 
+    eval {
+        local $SIG{ALARM} = sub {die};
+        alarm(2); # we'll sleep for as much as 2s
+        do {
+            die if $cache->get_cache($key . '_COMPLETE');
+        } while (sleep(0.05));
+    };
+
     my $blob = $cache->get_cache($key) || {};
 
     my $facets = {};
@@ -1477,6 +1485,7 @@ sub cache_facets {
     $logger->info("facet compilation: cached with key=$key");
 
     $cache->put_cache($key, $data, $cache_timeout);
+    $cache->put_cache($key.'_COMPLETE', 1, $cache_timeout);
 }
 
 sub cache_staged_search_page {
index 48c218a..d234753 100644 (file)
@@ -69,7 +69,9 @@ sub _prepare_biblio_search_basics {
 sub _prepare_biblio_search {
     my ($cgi, $ctx) = @_;
 
-    my $query = _prepare_biblio_search_basics($cgi) || '';
+    # XXX This will still contain the jtitle hack...
+    my $user_query = _prepare_biblio_search_basics($cgi) || '';
+    my $query = $user_query;
 
     $query .= ' ' . $ctx->{global_search_filter} if $ctx->{global_search_filter};
 
@@ -189,9 +191,9 @@ sub _prepare_biblio_search {
         return $query;
     };
 
-    $logger->info("tpac: site=$site, depth=$depth, query=$query");
+    $logger->info("tpac: site=$site, depth=$depth, user_query=$user_query, query=$query");
 
-    return ($query, $site, $depth);
+    return ($user_query, $query, $site, $depth);
 }
 
 sub _get_search_limit {
@@ -389,7 +391,7 @@ sub load_rresults {
         $offset = 0;
     }
 
-    my ($query, $site, $depth) = _prepare_biblio_search($cgi, $ctx);
+    my ($user_query, $query, $site, $depth) = _prepare_biblio_search($cgi, $ctx);
 
     $self->get_staff_search_settings;
 
@@ -430,6 +432,7 @@ sub load_rresults {
         }
 
         # Stuff these into the TT context so that templates can use them in redrawing forms
+        $ctx->{user_query} = $user_query;
         $ctx->{processed_search_query} = $query;
 
         $query = "$_ $query" for @facets;
@@ -461,7 +464,10 @@ sub load_rresults {
 
     $ctx->{ids} = $rec_ids;
     $ctx->{hit_count} = $results->{count};
-    $ctx->{parsed_query} = $results->{parsed_query};
+    $ctx->{query_struct} = $results->{global_summary}{query_struct};
+    $logger->debug('query struct: '. Dumper($ctx->{query_struct}));
+    $ctx->{canonicalized_query} = $results->{global_summary}{canonicalized_query};
+    $ctx->{search_summary} = $results->{global_summary};
 
     if ($find_last) {
         # redirect to the record detail page for the last record in the results
index fdf51f7..cf1f7e9 100644 (file)
@@ -46,6 +46,7 @@ sub child_init {
         $ro_object_subs->{$locale}->{aou_tree}();
         $ro_object_subs->{$locale}->{aouct_tree}();
         $ro_object_subs->{$locale}->{ccvm_list}();
+        $ro_object_subs->{$locale}->{crad_list}();
         $ro_object_subs->{$locale}->{get_authority_fields}(1);
     }
 }
@@ -109,17 +110,28 @@ sub init_ro_object_cache {
             my ($field, $val, $filterfield, $filterval) = @_;
             my $method = "search_$eclass";
             my $cacheval = $val;
+            my $scalar_cacheval = 1;
+
             if (ref $val) {
+                $scalar_cacheval = 0;
                 $val = [sort(@$val)] if ref $val eq 'ARRAY';
                 $cacheval = OpenSRF::Utils::JSON->perl2JSON($val);
                 #$self->apache->log->info("cacheval : $cacheval");
             }
+
             my $search_obj = {$field => $val};
             if($filterfield) {
                 $search_obj->{$filterfield} = $filterval;
                 $cacheval .= ':' . $filterfield . ':' . $filterval;
+            } elsif (
+                $scalar_cacheval
+                and $cache{list}{$locale}{$hint}
+                and !$cache{search}{$locale}{$hint}{$field}{$cacheval}
+            ) {
+                return $cache{search}{$locale}{$hint}{$field}{$cacheval} =
+                    [ grep { $_->$field() eq $val } @{$cache{list}{$locale}{$hint}} ];
             }
-            #$cache{search}{$locale}{$hint}{$field} = {} unless $cache{search}{$locale}{$hint}{$field};
+
             my $e = new_editor();
             $cache{search}{$locale}{$hint}{$field}{$cacheval} = $e->$method($search_obj)
                 unless $cache{search}{$locale}{$hint}{$field}{$cacheval};
@@ -453,20 +465,19 @@ sub get_records_and_facets {
         }
     }
 
-
-    $self->timelog("get_records_and_facets():almost ready to fetch facets");
-    # collect the facet data
-    my $search = OpenSRF::AppSession->create('open-ils.search');
-    my $facet_req = $search->request(
-        'open-ils.search.facet_cache.retrieve', $facet_key
-    ) if $facet_key;
-
     # gather up the unapi recs
     $ses->session_wait(1);
     $self->timelog("get_records_and_facets():past session wait");
 
     my $facets = {};
     if ($facet_key) {
+        $self->timelog("get_records_and_facets():almost ready to fetch facets");
+        # collect the facet data
+        my $search = OpenSRF::AppSession->create('open-ils.search');
+        my $facet_req = $search->request(
+            'open-ils.search.facet_cache.retrieve', $facet_key
+        );
+
         my $tmp_facets = $facet_req->gather(1);
         $self->timelog("get_records_and_facets(): gathered facet data");
         for my $cmf_id (keys %$tmp_facets) {
@@ -490,12 +501,11 @@ sub get_records_and_facets {
             }
         }
         $self->timelog("get_records_and_facets(): gathered/sorted facet data");
+        $search->kill_me;
     } else {
         $facets = undef;
     }
 
-    $search->kill_me;
-
     return ($facets, map { $tmp_data{$_} } @$rec_ids);
 }
 
index b4ba2d7..a599706 100644 (file)
@@ -537,7 +537,7 @@ sub unapi {
     $supercat->session_locale($locale);
 
     my $flesh_feed = parse_feed_type($format);
-    (my $base_format = $format) =~ s/(-full|-uris)$//o;
+    ($base_format = $format) =~ s/(-full|-uris)$//o;
     my ($id,$type,$command,$lib,$depth,$paging) = ('','record','');
     my $body = "Content-type: application/xml; charset=utf-8\n\n";
 
@@ -1443,9 +1443,9 @@ sub opensearch_feed {
     $safe_terms =~ s{'}{ }go;
     
     my $query_terms = 'site('.$org_unit->[0]->shortname.") $safe_terms";
-    $query_tems = "sort($sort) $query_terms" if ($sort);
-    $query_tems = "language($lang) $query_terms" if ($lang);
-    $query_tems = "#$sortdir $query_terms" if ($sortdir);
+    $query_terms = "sort($sort) $query_terms" if ($sort);
+    $query_terms = "language($lang) $query_terms" if ($lang);
+    $query_terms = "#$sortdir $query_terms" if ($sortdir);
 
     my $recs = $search->request(
         'open-ils.search.biblio.multiclass.query' => {
diff --git a/Open-ILS/src/templates/opac/parts/result/adv_filter.tt2 b/Open-ILS/src/templates/opac/parts/result/adv_filter.tt2
new file mode 100644 (file)
index 0000000..9e7bd14
--- /dev/null
@@ -0,0 +1,67 @@
+<div class="facet_box_wrapper">
+[%
+
+ignore_filters = ['sort','statuses','site'];
+
+FOR filter IN ctx.query_struct.filters;
+    fname = filter.name;
+
+    fvalues = filter.args;
+    crad = ctx.get_crad(fname);
+
+    IF crad; # will be some special ones, like locations
+        remove_filter = 'fi:' _ fname;
+%]
+    <div class="facet_box_temp">
+        <div class="header">
+            <a class="button"
+              title="[% l('Remove [_1] filter', crad.label) %]"
+              href="[% mkurl('', {}, [remove_filter]) %]" rel="nofollow" vocab="">
+              [% l("Remove") %]
+            </a>
+            <h4 class="title">[% IF filter.negate; l('Not'); END %] [% crad.label | html %]</h4>
+        </div>
+        <div class="box_wrapper">
+            <div class="box">
+            [% FOR fval IN fvalues;
+                thing = ctx.search_ccvm('ctype',fname,'code',fval).0;
+                display_value = thing.search_label || thing.value;
+                IF display_value.defined; %]
+                    <div class="facet_template">
+                        <div class="facet">
+                              [% display_value | html%]
+                        </div>
+                    </div>
+            [%  END; # IF %]
+            [% END; # FOR %]
+            </div>
+        </div> <!-- box_wrapper -->
+    </div> <!-- facet_box_temp -->
+    [% END; # IF crad %]
+
+[%  IF filter.name == 'locations'; locs = ctx.search_acpl('id',filter.args) %]
+    <div class="facet_box_temp">
+        <div class="header">
+            <a class="button"
+              title="[% l('Remove location filter') %]"
+              href="[% mkurl('', {}, ['locations']) %]" rel="nofollow" vocab="">
+              [% l("Remove") %]
+            </a>
+            <h4 class="title">[% IF filter.negate; l('Not'); END %] [% l('Locations') %]</h4>
+        </div>
+        <div class="box_wrapper">
+            <div class="box">
+            [% FOR loc IN locs %]
+                <div class="facet_template">
+                  <div class="facet">
+                    [% loc.name | html%]
+                  </div>
+                </div>
+            [% END; # FOR %]
+            </div>
+        </div> <!-- box_wrapper -->
+    </div> <!-- facet_box_temp -->
+    [% END; # IF locations %]
+[% END; # FOR %]
+</div> <!-- facet_box_wrapper -->
+
index 02fe684..7e47daf 100644 (file)
@@ -25,6 +25,8 @@
     <h3 class="sr-only">[% l('Saved Searches') %]</h3>
     [% INCLUDE "opac/parts/staff_saved_searches.tt2" %]
     [%-  END %]
+    <h3 class="sr-only">[% l('Search Results filters') %]</h3>
+    [% INCLUDE 'opac/parts/result/adv_filter.tt2' %]
     <h3 class="sr-only">[% l('Search Results facets') %]</h3>
     [% INCLUDE 'opac/parts/result/facets.tt2' %]
     <h3 class="sr-only">[% l('Search Results List') %]</h3>
index a48c4a0..2c162fe 100644 (file)
@@ -17,7 +17,7 @@
             <label id="search_box_label" for="search_box">[% l('Search: ') %]
             <input type="text" id="search_box" name="query" aria-label="[%
                     l('Enter search query:');
-                %]" value="[% is_advanced ? ctx.naive_query_scrub(ctx.processed_search_query) : CGI.param('query') | html %]"
+                %]" value="[% is_advanced ? ctx.naive_query_scrub(ctx.user_query) : CGI.param('query') | html %]"
                 [%- IF use_autosuggest.enabled == "t" %]
                 dojoType="openils.widget.AutoSuggest" type_selector="'qtype'"
                 submitter="this.textbox.form.submit();"
         [% IF ctx.processed_search_query OR (NOT is_advanced AND NOT is_special) %]
         <input name='page' type='hidden' value="0" />
         [% END %]
+        [% IF is_advanced;
+            FOR p IN CGI.params.keys;
+                NEXT UNLESS p.match('^fi:');
+                FOR pv IN CGI.params.$p;
+                    %]<input type="hidden" name="[% p %]" value="[% pv %]" />[%
+                END;
+            END;
+        END %]
         [% IF is_special %]
             <input type="hidden" name="_special" value="1" /> [%
             number_of_expert_rows = CGI.param('tag').list.size;