From d28ca61d634511a6bf693b8b4e3da1ef18dcd503 Mon Sep 17 00:00:00 2001
From: Bill Erickson <berick@esilibrary.com>
Date: Fri, 30 Sep 2011 16:01:22 -0400
Subject: [PATCH] TPac: Facets on results page

Show search facets along the left side of the results page.  Clicking on
a facet re-runs the current search with the  new facet appeneded.
Selected facets are styled to indicate they are selected.  Clicking on a
selected facet removes that facet from the set of selected facets (i.e.
it backs out the facet).

TODO: update CSS to match default Evergreen skin

Signed-off-by: Bill Erickson <berick@esilibrary.com>
Signed-off-by: Dan Scott <dscott@laurentian.ca>
---
 .../perlmods/lib/OpenILS/WWW/EGCatLoader/Search.pm |   4 +-
 .../perlmods/lib/OpenILS/WWW/EGCatLoader/Util.pm   |  22 +++--
 .../src/templates/opac/parts/result/facets.tt2     |  95 +++++++++++++++++++++
 Open-ILS/src/templates/opac/parts/result/table.tt2 |   4 +-
 Open-ILS/web/css/skin/default/opac/style.css       |  73 ++++++++++++++++
 Open-ILS/web/images/adv_search_minus_btn.png       | Bin 0 -> 1292 bytes
 Open-ILS/web/images/adv_search_plus_btn.png        | Bin 0 -> 1388 bytes
 Open-ILS/web/images/facet_box_bg.png               | Bin 0 -> 449 bytes
 Open-ILS/web/images/facet_box_bg_bottom.png        | Bin 0 -> 308 bytes
 9 files changed, 188 insertions(+), 10 deletions(-)
 create mode 100644 Open-ILS/src/templates/opac/parts/result/facets.tt2
 create mode 100644 Open-ILS/web/images/adv_search_minus_btn.png
 create mode 100644 Open-ILS/web/images/adv_search_plus_btn.png
 create mode 100644 Open-ILS/web/images/facet_box_bg.png
 create mode 100644 Open-ILS/web/images/facet_box_bg_bottom.png

diff --git a/Open-ILS/src/perlmods/lib/OpenILS/WWW/EGCatLoader/Search.pm b/Open-ILS/src/perlmods/lib/OpenILS/WWW/EGCatLoader/Search.pm
index 635678b982..37fa582254 100644
--- a/Open-ILS/src/perlmods/lib/OpenILS/WWW/EGCatLoader/Search.pm
+++ b/Open-ILS/src/perlmods/lib/OpenILS/WWW/EGCatLoader/Search.pm
@@ -168,7 +168,7 @@ sub load_rresults {
     }
 
     my $page = $cgi->param('page') || 0;
-    my $facet = $cgi->param('facet');
+    my @facets = $cgi->param('facet');
     my $limit = $self->_get_search_limit;
     my $loc = $cgi->param('loc') || $ctx->{aou_tree}->()->id;
     my $offset = $page * $limit;
@@ -229,7 +229,7 @@ sub load_rresults {
         # Stuff these into the TT context so that templates can use them in redrawing forms
         $ctx->{processed_search_query} = $query;
 
-        $query = "$query $facet" if $facet; # TODO
+        $query .= " $_" for @facets;
 
         $logger->activity("EGWeb: [search] $query");
 
diff --git a/Open-ILS/src/perlmods/lib/OpenILS/WWW/EGCatLoader/Util.pm b/Open-ILS/src/perlmods/lib/OpenILS/WWW/EGCatLoader/Util.pm
index 6af3a7a9fe..3b72dbc556 100644
--- a/Open-ILS/src/perlmods/lib/OpenILS/WWW/EGCatLoader/Util.pm
+++ b/Open-ILS/src/perlmods/lib/OpenILS/WWW/EGCatLoader/Util.pm
@@ -201,13 +201,23 @@ sub get_records_and_facets {
     # gather up the unapi recs
     $ses->session_wait(1);
 
-    my $facets;
+    my $facets = {};
     if ($facet_key) {
-        $facets = $facet_req->gather(1);
-        $facets->{$_} = {
-            cmf => $self->ctx->{get_cmf}->($_),
-            data => $facets->{$_}
-        } for keys %$facets;    # quick-n-dirty
+        my $tmp_facets = $facet_req->gather(1);
+        for my $cmf_id (keys %$tmp_facets) {
+
+            # sort highest to lowest match count
+            my @entries;
+            my $entries = $tmp_facets->{$cmf_id};
+            for my $ent (keys %$entries) {
+                push(@entries, {value => $ent, count => $$entries{$ent}});
+            };
+            @entries = sort { $b->{count} <=> $a->{count} } @entries;
+            $facets->{$cmf_id} = {
+                cmf => $self->ctx->{get_cmf}->($cmf_id),
+                data => \@entries
+            }
+        }
     } else {
         $facets = undef;
     }
diff --git a/Open-ILS/src/templates/opac/parts/result/facets.tt2 b/Open-ILS/src/templates/opac/parts/result/facets.tt2
new file mode 100644
index 0000000000..c4a719d6b4
--- /dev/null
+++ b/Open-ILS/src/templates/opac/parts/result/facets.tt2
@@ -0,0 +1,95 @@
+<div class="facet_box_wrapper">
+[% 
+
+close_facets = CGI.param('close_facet') || [];
+selected_facets = CGI.param('facet') || [];
+
+# collect facet type labels for easier sorting
+labels = []; 
+FOR facet IN ctx.search_facets.values;
+    labels.push(facet.cmf.label);
+END;
+
+FOR facet_label IN labels.sort;
+    FOR facet IN ctx.search_facets.values;
+        IF facet.cmf.label == facet_label;
+            fclass = facet.cmf.field_class;
+            fname = facet.cmf.name;
+            close_key = fclass _ fname %]
+
+        <div class="facet_box_temp">
+            <div class="header">
+                <div class="title">[% facet.cmf.label %]</div>
+                <div class="button">
+
+                    [% IF close_facets.grep(close_key).0;
+                        new_close = [];
+                        FOR fct IN close_facets;
+                            IF fct != close_key;
+                                new_close.push(fct);
+                            END;
+                        END
+                    %]
+                        <a href="[% mkurl('', {close_facet => new_close}) %]"><img 
+                            src="[% ctx.media_prefix %]/images/adv_search_plus_btn.png" alt="[% l('Expand') %]" /></a>
+                    [% ELSE %]
+                        <a href="[% mkurl('', {close_facet => close_facets.merge([close_key])}) %]"><img 
+                            src="[% ctx.media_prefix %]/images/adv_search_minus_btn.png" alt="[% l('Collapse') %]" /></a>
+                    [% END %]
+                </div>
+                <div class="clear">&nbsp;</div>
+            </div>
+            [% IF !close_facets.grep(close_key).0 %]
+            <div class="box_wrapper">
+                <div class="box">
+                [% FOR facet_data IN facet.data;
+                    display_value = facet_data.value | html;
+                    param_string = fclass _ '|' _ fname _ '[' _ facet_data.value _ ']';
+                    new_facets = [];
+                    this_selected = 0;
+                    FOR selected IN selected_facets;
+                        IF selected == param_string; 
+                            this_selected = 1; 
+                        ELSE;
+                            new_facets.push(selected);
+                        END;
+                    END;
+                    IF this_selected;
+                        # This facet is already selected by the user. 
+                        # Link removes the facet from the set of selected facets.
+                    %] 
+                        <div class="facet_template facet_template_selected">
+                            <div class="facet">
+                                [% IF new_facets.size == 0 %]
+                                <a href="[% mkurl('', {}, ['facet']) %]">[% display_value %]</a>
+                                [% ELSE %]
+                                <a href="[% mkurl('', {facet => new_facets}) %]">[% display_value %]</a>
+                                [% END %]
+                            </div>
+                            <div class="count">([% facet_data.count %])</div>
+                            <div class="clear">&nbsp;</div>
+                        </div>
+                    [% 
+                        ELSE;
+                        # This facet is not currently selected.  If selected, 
+                        # append this facet to the list of currently active facets.
+                    %]
+                        <div class="facet_template">
+                            <div class="facet">
+                                <a href='[% mkurl('', {facet => selected_facets.merge([param_string])}) %]'>[% display_value %]</a>
+                            </div>
+                            <div class="count">([% facet_data.count %])</div>
+                            <div class="clear">&nbsp;</div>
+                        </div>
+                    [% END %]
+                [% END %]
+                </div>
+                <div class="clear">&nbsp;</div>
+            </div> <!-- box_wrapper -->
+            [% END %]
+        </div> <!-- facet_box_temp -->
+        [% END %]
+    [% END %]
+[% END %]
+</div> <!-- facet_box_wrapper -->
+
diff --git a/Open-ILS/src/templates/opac/parts/result/table.tt2 b/Open-ILS/src/templates/opac/parts/result/table.tt2
index 0706ef6766..b60e647d72 100644
--- a/Open-ILS/src/templates/opac/parts/result/table.tt2
+++ b/Open-ILS/src/templates/opac/parts/result/table.tt2
@@ -19,8 +19,8 @@
     <table cellpadding="0" cellspacing="0" border="0" width="100%">
         <tr>
             <td valign="top" width="1" style="padding-right:20px;">
-                <div style="width:174px;" class="hide_me">
-                    SIDEBAR TODO
+                <div style="width:174px;">
+                    [% INCLUDE 'opac/parts/result/facets.tt2' %]
                 </div>
             </td>
             <td class='opac-auto-015' width="1"></td>
diff --git a/Open-ILS/web/css/skin/default/opac/style.css b/Open-ILS/web/css/skin/default/opac/style.css
index 368dad5a5c..e90a0ef82a 100644
--- a/Open-ILS/web/css/skin/default/opac/style.css
+++ b/Open-ILS/web/css/skin/default/opac/style.css
@@ -886,6 +886,7 @@ div.select-wrapper:hover {
 }
 
 /* some facet styling */
+/*
 .facetClassContainer { margin: 2px; border: 1px solid #CCC; }
 .facetClassLabelContainer { border: 1px solid #CCC; }
 .facetClassLabel { font-weight: bold; text-align: center; }
@@ -897,6 +898,77 @@ div.select-wrapper:hover {
 .facetField { border-top: 1px solid #CCC; }
 .facetFields { padding-left: 5px; }
 .facetFieldLineValue { overflow: hidden; text-overflow: ellipsis; }
+*/
+
+.facet_box_temp {
+	padding-bottom:3px;
+	width:180px;
+	overflow:hidden;
+}
+
+.facet_box_temp .header {
+	width:180px;
+	height:31px;
+	overflow:hidden;
+	background:url('/images/facet_box_bg.png') no-repeat;
+	font-weight:bold;
+	color:#074079;
+	padding-top:4px;
+}
+
+.facet_box_temp .header .title {
+	float:left;
+	padding-top:6px;
+	padding-left:12px;
+	width:134px;
+	overflow:hidden;
+}
+
+.facet_box_temp .header .button {
+	float:right;
+	padding-right:6px;
+}
+
+.facet_box_wrapper .box_wrapper {
+	position:relative;
+	top:-4px;
+	margin-bottom:-5px;
+	*margin-bottom:-6px;
+}
+
+.facet_box_wrapper .box_wrapper .box {
+	width:166px;
+	border-top:1px solid #7ebee5;
+	border-left:1px solid #f3f3f3;
+	border-right:1px solid #f3f3f3;
+	background:white;
+	padding-left:12px;
+	padding-top:6px;
+}
+
+.facet_box_wrapper .box_wrapper .bottom {
+	background:url('/images/facet_box_bg_bottom.png') no-repeat;
+}
+
+.facet_template {
+	padding-bottom:5px;
+}
+
+.facet_template .facet {
+	float:left;
+	width:124px;
+}
+
+.facet_template .count {
+	float:right;
+	color:#818080;
+	padding-right:11px;
+}
+
+.facet_template_selected {
+    background-color: #d7d7d7;
+}
+
 #footer-wrap {
     background: linear-gradient(lightGreen, #252525);
     background: -moz-linear-gradient(lightGreen, #252525);
@@ -904,6 +976,7 @@ div.select-wrapper:hover {
     background: -webkit-linear-gradient(lightGreen, #252525);
     background-color: lightGreen;
 }
+
 #footer {
 	padding-top:5px;
 	padding-bottom: 10px;
diff --git a/Open-ILS/web/images/adv_search_minus_btn.png b/Open-ILS/web/images/adv_search_minus_btn.png
new file mode 100644
index 0000000000000000000000000000000000000000..40505959f724a7c2d45f0a390d65beb419bfe97f
GIT binary patch
literal 1292
zcmV+n1@roeP)<h;3K|Lk000e1NJLTq000~S000~a1^@s6at+^<0000PbVXQnQ*UN;
zcVTj606}DLVr3vnZDD6+Qe|Oed2z{QJOBU$u1Q2eRCwB?R$WM2XBa+zNls3TF->Mt
zU3FT}u?xEk>#k(9W$b1*yDCf=DJv63H|UhDP&#|JB8)-lD&4$t6mP~ZhC`e%!(;{5
zIbmX}m4Qu0oj*yeCOPNi{AACYo|7JR)2Ig?&dHbW`=0N8-oKAMbEcE2@bLg%>&;p)
zfdZfaawVGx`~1%VK_F1UTm#qw(ty4v;l#w`u0LQok%R%hLIr4E4Nwhah#318_q7m2
zBvr&(c$kM&2>}xJdID18e+ezJ6M*O(_j)DQ<;y*1o10I*>GgU~5?GdX<@5RZLZPsn
zOeV$#2frRmBp&CT%V;m`nRJq}6g0M^_>MX)({+QpdiC15Q>R|-;d#DE(=^5~j1o#3
z@;t+F9OH7iXe<$rPh7ck=k^~Mb4p3U^tUZ9-_+E|EG;E$pM~sMg@VT4x;5}|OH1oD
zRaJvPiO4j~@=o+kV|0*Wu^4D=ZGF45^L1%zYHC_hWIJ$N!~>38*+NVAm+Sx`vYR)*
z>WN097ZpW0kOM_gWb*mkcr5nrM{c*vmXfS{3@bIx8VK5CBx7&yC+8xO$VK?5WW_;1
zYus+n8~y!Xbkkn8>#T@p>;b=(#3s)RZusm|S_qjA1(LtMzW%+owzjanuNAdCXGJ8v
zi<)Mzmo9yH7JfN#P|J1#r2g~g-|0dWbC#q8iGH~4Q>d!KH8nNArR(~kt+PR-!C<g6
zmy-pDl^(&0qEg7pvf^^P-7h;M@hA`Wdd1}usP@|VDF}`tOySMpbjO^8*=&{>8X98u
zi&me{$HZbW#^doY&r_?woj(0qXm0M$w3VBz;0Rmfl+J-nKo!{*<_!%EOfHw(ld!tF
zx>N{us)M2+8ivVOghj!s?4?<-&O~&kQM#h#QUvm@uC7u=*|Sxk0Aw<mU4-}U{kjHe
zZ66xj2(i5m2@{Yd>Rhz8wst5VZf$KPR##W$#>NK2Qn8fyh37fQ7v|^Ze?DqT*jQQl
zXG#zRmFGFb;!ufDvzn*r^@_^y@bH){%ju)01tiu-Mn=AaoQfkY%1K!olq8>;NGvVS
z%*@<9s&$Kti$9K!|MUPxs5Tk3DbCSC3{iCJe!qY7`t`nVlgZ@dVXZ^(JnHNF>`SD|
zhR-M2E|bgciFy^i={Gbt6h+l1Cx4l3Z*OnG0bV=^Svs9wym906E32z3k0Oy5Hj!53
zE)5*2vv@PsfCdTlaQN8f)2ADMUAPeIou2;vE((HNK`GPc=H`Cr?tcG+hYugjqO5IH
zRaI$L7L;#v<pxX-zUeePNKNFOioPh1j*iaWzyDjjuCA^K9|sTw0cYqVjg}V{7RCn#
zZubuke)B!nB|@Q4=J@f5?K{<Znc8;6aNKLCzH+HlhF@P_7qi)1HLMJxV)$W=*wN7u
zkt9io$Ky{>7!;6fp=Of5Hfw8Z^Py1C&bz|So7*lz2eDu`<@NOxpGu`Y@T~{oE>QWi
zs*r)))ln$aU@)N8)C3TCA`zI>-4ApT#sVFrbW$!H4w(RLkj>@tEQr}>b=FgaRZa`&
z+xV~hXhk<~Yax*uAm^TS1&IZi9V9fjqMr7z00RJcefI{e-${-D0000<MNUMnLSTaI
C({lI#

literal 0
HcmV?d00001

diff --git a/Open-ILS/web/images/adv_search_plus_btn.png b/Open-ILS/web/images/adv_search_plus_btn.png
new file mode 100644
index 0000000000000000000000000000000000000000..7f1ae93a71e04ee4874f68acbfa38616daaf4144
GIT binary patch
literal 1388
zcmV-y1(W)TP)<h;3K|Lk000e1NJLTq000~S000~a1^@s6at+^<0000PbVXQnQ*UN;
zcVTj606}DLVr3vnZDD6+Qe|Oed2z{QJOBU%4oO5oRCwB)R$oY4R~WzllH4T5cui)k
zt~zyS*@NAKwNIjL8GG5wo(dC2%F2||4La>skUq+axR=t^cJoOXGLSuNib!FG$qKG>
z4-;Fh3~VgTqUKLEf9_50z1jEOo)fRp#B>*a<mTLSzTf$N-=A~XbLYC4G9MejPJUSe
z9gqRYfOI)Vgk!#Q014nOW3C3+14IF8Ny7R0g+m{}b0qNs_%ap1c~yW)Kn#h&ZthqQ
zfe5AYk%j-~K~+2e2iST6q*_rzLUs}$n#b*ShvnL}f%DDHE$`dy_7()ovX)dTwVKIf
zLYtexx$*Ju=7PazDf2S41vWR$q%0;4l@#7<&7P^M#tjYKym0#Ty8}GWH)XR~M$<F{
zhK4-Pa2&^2EEXIK1_JXp?%%)r7mS&u#AJF-<>i~28kvoaAdQ)a&dOx6{GB^vU$nNi
z-Bc7s0vJTPuIDY`JC5N-a=Dzlt*!0DuC8v!;^N|xET?JWSda%el6en_?r+fqL9*Mo
zza6Npt-UPE@@oZ96h$VLN<Q%WKmOcmwNNS1yJz5KmLmfaB|{kp2fw`F^Z71Aj0`Ud
z5s5^YXf%4{H(X=2+TI%(`KAwT(a@2MXXt>76tT|pf)!%+6)pssj>P2TBr`QNRrEW`
zUteGUNqc*{m)a#+%X1_n@i&*vYV6gkpPh%eoIGmx6eu%fCsS$;kh(5j{HPb^aYRyt
z1OHg*E)+%PnwpwFP*t_)?h*7UH3vy0N$N@_(}KxMn?SP2u#!&87OT~I%AAR%p5x|$
zt#>RI0edg4PeCv>VN7ohc2{jSlt?6)iHQlOFkA8e=;&zvztibt{C+=Uv)P#a(#mjW
z&YbnEto$7%waE&mw1t{dIUp0DiyTPvhK2?vnM~%#LZJ|YbD(VUW0jSaMk6Tn8k&Nr
zX*xp)a{}q?I*Ex6*%^h_mA8b3dwYA0jzXW|;bCJV{r&y>M+G#1SS)sk@ZrPXw?SGO
zL+t<|m{&o<Ajnc{UbMZvePoQn;c&?q?(OXbx3;#@jg1W&QPC*;%zh2>nbp<RUrVJs
z^?+t#DTKrSE((I6@I0px4h0Fb<nYw(c2S0+o=d0G(NZZ7>29FZ9FSO@o}QipIb~B>
zWQ^ub3ZG|LUWX$_YiW5~gidj`n6aLo9tOIIk-^30tgo;Ca_`>QkJZ)Et|;2jp)B-L
znG)iFMG*KLG;V!nW@e+iyZaPmUSpBi7-Yqscs%~}`t`vf@Gj)>NHWRL6r32kL5OD+
zA?87IO_mjPVd1ysj*gC2m&^5LDd`FUO?~~=t*>uvZH1rud~bkvBK1x&H*bavWFd~K
z*IT{&@@4#=OPBnEOG|(L01Y9191$dmy0WtJb6?-5SDrk1ybLjpS5#DFNfqR8bom1q
zA9%;z@Ib1A3<}7bo}Hate)Q;%KwVv3&f##nK_<6ZK9DxFwzl?QZ0zpH`1tof!MdQw
z<B6R(;Zta4nlDoat{A3!4fa<q5{dCUJ3C?`k*owSCFmF~@J8(H?DRPt4j~W-ynx1l
zG1`Nk8FxAzyEQd6DTo`byG-HD?GT}fSfGdU&Q64nM4~o`tqsy$!1hPFkOsA@LZeV5
z$*ojXxiyFx66kokzt%+<7N|gqJLSAyj}AZsiDWXx0x|ol&)Ra}mDvM)*N(c6mUZ(c
u3z1X<a_-fs;9vnv0SV46>rDGkfB^talgXLwY7NZ*0000<MNUMnLSTZ>Bckj8

literal 0
HcmV?d00001

diff --git a/Open-ILS/web/images/facet_box_bg.png b/Open-ILS/web/images/facet_box_bg.png
new file mode 100644
index 0000000000000000000000000000000000000000..996f0a8331a6212ed0953d938326b63231733e9a
GIT binary patch
literal 449
zcmeAS@N?(olHy`uVBq!ia0vp^TYy-ZgAGX9u2VP(q$EpRBT9nv(@M${i&7aJQ}UBi
z6+Ckj(^G>|6H_V+Po~;1Ffb;2x;TbZ+<J3oqt{^vi31;Zdw2O-YorJ`3a~F+-MnD2
zUBlvp=X&e*HTo~~%hT)XUzp71*wXY!LG8v3t!r$PWA?26$Q!fnPyL5hv&YBh7hFE6
zanj}gyKQ@SU9<cq-MdcUkZ^<bDW&u0<$r%?uf8pvoEf)b_VSA_y`O!*<f*A8#?pSH
z;qU=r@3W6`vQrm6pZ&kr;`29lwX_4K-<WN3w+HRsmYOP`x$O2DHa+Ru?hpDID=pIx
z6duh#5_I*rK!RG|l`h$YX#yr3QVJOj3mBW&9GO{o1xy?+FgP}YxDatiAQvhQRrb&D
zh1cs(y`cwEOAk-wjjHE+#2v;oz4!8yQ`>UhH-+(EEWL8`4(IcxYny`Ny1yO}O`W*>
z@Q<ILo@}T#sqwW-seQw7=FIGkhQHTv@@bx_nOSLWJn<Xb|F1`%eTlkjm8MtFqWxy-
i;$3}K+xOSANH93OOh`HZC@B&cCk&phelF{r5}E)M9L2o=

literal 0
HcmV?d00001

diff --git a/Open-ILS/web/images/facet_box_bg_bottom.png b/Open-ILS/web/images/facet_box_bg_bottom.png
new file mode 100644
index 0000000000000000000000000000000000000000..fc776c3304e5c31da66d5c352a32fe27e428726b
GIT binary patch
literal 308
zcmeAS@N?(olHy`uVBq!ia0vp^TR?0MHXzBs;nEKzB}-f*N`mv#O3D+9QW+dm@{>{(
zJaZG%Q-e|yQz{EjrrH1%UGsEt45_&F=B7Q@Ap;S%g3DT$l+rF-jCFTU|E|-Qrzdwn
zdPg<GM<%|m;{|Kg3xuPxbVdL3<OY9MXb!LV_4mQVGxG8e9b1A{Sx4tSmSQNLT<6VI
zyv=;Mj<d{xyEPh1n<XAhUvQzpiFv^V1`QJiF5ddM7hbPFwP`dM-+tJ|wO0OmLAyu8
z=5!(16{q#~UV8pOg2(N#-{sHMeUE>2u<y|5w(&fCx^C|by~`H6xObOTq%D!uDwZ{5
zRBoL)UGmr4y6*L{yAn_PlsC?4XzaSi6a8w=J9$PnhIt1~d7T#Jo&kl1r>mdKI;Vst
E0I+|0bpQYW

literal 0
HcmV?d00001

-- 
2.11.0