SOLR-4759: Velocity template cleanup

git-svn-id: https://svn.apache.org/repos/asf/lucene/dev/trunk@1476858 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Erik Hatcher 2013-04-28 23:30:57 +00:00
parent 1de26ff2ee
commit d8d4072cf2
40 changed files with 988 additions and 311 deletions

View File

@ -93,6 +93,9 @@ Other Changes
* SOLR-4757: Change the example to use the new solr.xml format and core
discovery by directory structure. (Mark Miller)
* SOLR-4759: Velocity (/browse) template cosmetic cleanup.
(Mark Bennett, ehatcher)
================== 4.3.0 ==================
Versions of Major Components

View File

@ -0,0 +1,101 @@
Introduction
------------
Solr Search Velocity Templates
A quick demo of using Solr using http://wiki.apache.org/solr/VelocityResponseWriter
You typically access these templates via:
http://localhost:8983/solr/collection1/browse
It's called "browse" because you can click around with your mouse
without needing to type any search terms. And of course it
also works as a standard search app as well.
Known Limitations
-----------------
* The /browse and the VelocityResponseWriter component
serve content directly from Solr, which usually requires
Solr's HTTP API to be exposed. Advanced users could
potentially access other parts of Solr directly.
* There are some hard coded fields in these templates.
Since these templates live under conf, they should be
considered part of the overall configuration, and
must be coordinated with schema.xml and solrconfig.xml
Velocity Info
-------------
Java-based template language.
It's nice in this context because change to the templates
are immediately visible in browser on the next visit.
Links:
http://velocity.apache.org
http://wiki.apache.org/velocity/
http://velocity.apache.org/engine/releases/velocity-1.7/user-guide.html
File List
---------
System and Misc:
VM_global_library.vm - Macros used other templates,
exact filename is important for Velocity to see it
error.vm - shows errors, if any
debug.vm - includes toggle links for "explain" and "all fields"
activated by debug link in footer.vm
README.txt - this file
Overall Page Composition:
browse.vm - Main entry point into templates
layout.vm - overall HTML page layout
head.vm - elements in the <head> section of the HTML document
header.vm - top section of page visible to users
footer.vm - bottom section of page visible to users,
includes debug and help links
main.css - CSS style for overall pages
see also jquery.autocomplete.css
Query Form and Options:
query_form.vm - renders query form
query_group.vm - group by fields
e.g.: Manufacturer or Poplularity
query_spatial.vm - select box for location based Geospacial search
Spelling Suggestions:
did_you_mean.vm - hyperlinked spelling suggestions in results
suggest.vm - dynamic spelling suggestions
as you type in the search form
jquery.autocomplete.js - supporting files for dynamic suggestions
jquery.autocomplete.css - Most CSS is defined in main.css
Search Results, General:
(see also browse.vm)
tabs.vm - provides navigation to advanced search options
pagination_top.vm - paging and staticis at top of results
pagination_bottom.vm - paging and staticis at bottom of results
results_list.vm
hit.vm - called for each matching doc,
decides which template to use
hit_grouped.vm - display results grouped by field values
product_doc.vm - display a Product
join_doc.vm - display a joined document
richtext_doc.vm - display a complex/misc. document
hit_plain.vm - basic display of all fields,
edit results_list.vm to enable this
Search Results, Facets & Clusters:
facets.vm - calls the 4 facet and 1 cluster template
facet_fields.vm - display facets based on field values
e.g.: fields specified by &facet.field=
facet_queries.vm - display facets based on specific facet queries
e.g.: facets specified by &facet.query=
facet_ranges.vm - display facets based on ranges
e.g.: ranges specified by &facet.range=
facet_pivot.vm - display pivot based facets
e.g.: facets specified by &facet.pivot=
cluster.vm - if clustering is available
then call cluster_results.vm
cluster_results.vm - actual rendering of clusters

View File

@ -1,3 +1,8 @@
#**
* Global macros used by other templates.
* This file must be named VM_global_library.vm
* in order for Velocity to find it.
*#
#macro(param $key)$request.params.get($key)#end
@ -167,4 +172,4 @@ $math.toDouble($math.add($inval,$gapval))##
#else
$math.add($inval,$gapval)##
#end
#end
#end

View File

@ -1,9 +1,13 @@
#set($searcher=$request.searcher)
#set($params=$request.params)
#**
* Main entry point into the /browse templates
*#
#set($searcher = $request.searcher)
#set($params = $request.params)
#set($clusters = $response.response.clusters)
#set($mltResults = $response.response.get("moreLikeThis"))
#set($annotate = $params.get("annotateBrowse"))
#parse('query.vm')
#parse('query_form.vm')
#parse('did_you_mean.vm')
<div class="navigators">
@ -11,40 +15,19 @@
</div>
<div class="pagination">
#if($response.response.get('grouped'))
<span><span class="results-found">$response.response.get('grouped').size() group(s)</span> found in ${response.responseHeader.QTime} ms</span>
#else<span><span class="results-found">$page.results_found</span> results found in ${response.responseHeader.QTime} ms</span>
Page <span class="page-num">$page.current_page_number</span> of <span
class="page-count">$page.page_count</span>#end
#parse("pagination_top.vm")
</div>
## Show Error Message, if any
<div class="error">
#if(${response.response.error.code})
<h1>ERROR ${response.response.error.code}</h1>
${response.response.error.msg}
#end
#parse("error.vm")
</div>
## Render Results, actual matching docs
<div class="results">
#if($response.response.get('grouped'))
#foreach($grouping in $response.response.get('grouped'))
#parse("hitGrouped.vm")
#end
#else
#foreach($doc in $response.results)
#parse("hit.vm")
#end
#end
#parse("results_list.vm")
</div>
<div class="pagination">
#if($response.response.get('grouped'))
#else
#link_to_previous_page("previous")
<span class="results-found">$page.results_found</span> results found.
Page <span class="page-num">$page.current_page_number</span> of <span
class="page-count">$page.page_count</span>
#link_to_next_page("next")
#end
<br/>
#parse("pagination_bottom.vm")
</div>

View File

@ -1,9 +1,19 @@
<h2 #annTitle("Clusters generated by Carrot2 using the /clustering RequestHandler")>Clusters</h2>
#**
* Check if Clustering is Enabled and then
* call cluster_results.vm
*#
<h2 #annTitle("Clusters generated by Carrot2 using the /clustering RequestHandler")>
Clusters
</h2>
## Div tag has placeholder text by default
<div id="clusters">
Run Solr with java -Dsolr.clustering.enabled=true -jar start.jar to see results
</div>
<script type="text/javascript">
## Replace the div content *if* Carrot^2 is available
<script type="text/javascript">
$('#clusters').load("#url_for_solr/clustering#lens",
{'wt':'velocity', 'v.template':"clusterResults"});
{'wt':'velocity', 'v.template':"cluster_results"});
</script>

View File

@ -1,12 +0,0 @@
#foreach ($clusters in $response.response.clusters)
#set($labels = $clusters.get('labels'))
#set($docs = $clusters.get('docs'))
<h3>#foreach ($label in $labels)$label#if( $foreach.hasNext ),#end#end</h3>
<ol>
#foreach ($cluDoc in $docs)
<li><a href="#url_for_home?q=id:$cluDoc">$cluDoc</a></li>
#end
</ol>
#end

View File

@ -0,0 +1,31 @@
#**
* Actual rendering of Clusters
*#
## For each cluster
#foreach ($clusters in $response.response.clusters)
#set($labels = $clusters.get('labels'))
#set($docs = $clusters.get('docs'))
## This Cluster's Heading
<h3>
#foreach ($label in $labels)
## Keep the following line together to prevent
## a space appearing before each comma
$label#if( $foreach.hasNext ),#end
#end
</h3>
## This Cluster's Documents
<ol>
## For each doc in this cluster
#foreach ($cluDoc in $docs)
<li>
<a href="#url_for_home?q=id:$cluDoc">
$cluDoc</a>
</li>
#end
</ol>
#end ## end for each Cluster

View File

@ -1,17 +1,28 @@
#if($params.getBool("debugQuery",false))
<a href="#" onclick='jQuery(this).siblings("pre").toggle(); return false;'>toggle explain</a>
<pre style="display:none">$response.getExplainMap().get($doc.getFirstValue('id'))</pre>
<a href="#" onclick='jQuery(this).siblings("pre2").toggle(); return false;'>toggle all fields</a>
#**
* Show Debugging Information, if enabled
*#
#if( $params.getBool("debugQuery",false) )
<a href="#" onclick='jQuery(this).siblings("pre").toggle(); return false;'>
toggle explain</a>
<pre style="display:none">
$response.getExplainMap().get($doc.getFirstValue('id'))
</pre>
<a href="#" onclick='jQuery(this).siblings("pre2").toggle(); return false;'>
toggle all fields</a>
<pre2 style="display:none">
#foreach($fieldname in $doc.fieldNames)
<br>
<span class="field-name">$fieldname :</span>
<span>
#foreach($value in $doc.getFieldValues($fieldname))
$esc.html($value)
#end
</span>
#end
</br>
#foreach($fieldname in $doc.fieldNames)
<br>
<span class="field-name">$fieldname :</span>
<span>
#foreach($value in $doc.getFieldValues($fieldname))
$esc.html($value)
#end
</span>
</br>
#end
</pre2>
#end
#end

View File

@ -1,4 +1,9 @@
#**
* Hyperlinked spelling suggestions in results list
*#
#set($dym = $response.response.spellcheck.suggestions.collation.collationQuery)
#if($dym)
Did you mean <a href="#{url_for_home}#{lensNoQ}&q=$esc.url($dym)">$esc.html($dym)</a>?
#end
Did you mean
<a href="#{url_for_home}#{lensNoQ}&q=$esc.url($dym)">$esc.html($dym)</a>?
#end

View File

@ -0,0 +1,11 @@
#**
* Show Error Message, if any
*#
## Show Error Message, if any
## Usually rendered inside div class=error
#if( $response.response.error.code )
<h1>ERROR $response.response.error.code</h1>
$response.response.error.msg
#end

View File

@ -1,15 +1,23 @@
#if($response.facetFields)
<h2 #annTitle("Facets generated by adding &facet.field= to the request")>Field Facets</h2>
#foreach($field in $response.facetFields)
## Hide facets without value
#if($field.values.size() > 0)
<span class="facet-field">$field.name</span>
#**
* Display facets based on field values
* e.g.: fields specified by &facet.field=
*#
#if($response.facetFields)
<h2 #annTitle("Facets generated by adding &facet.field= to the request")>
Field Facets
</h2>
#foreach($field in $response.facetFields)
## Hide facets without value
#if($field.values.size() > 0)
<span class="facet-field">$field.name</span>
<ul>
#foreach($facet in $field.values)
<li><a href="#url_for_facet_filter($field.name, $facet.name)">$facet.name</a> ($facet.count)</li>
<li>
<a href="#url_for_facet_filter($field.name, $facet.name)">$facet.name</a> ($facet.count)
</li>
#end
</ul>
#end
#end
#end
#end ## end if > 0
#end ## end for each facet field
#end ## end if response has facet fields

View File

@ -1,3 +1,12 @@
<h2 #annTitle("Facets generated by adding &facet.pivot= to the request")>Pivot Facets</h2>
#**
* Display Pivot-Based Facets
* e.g.: facets specified by &facet.pivot=
*#
<h2 #annTitle("Facets generated by adding &facet.pivot= to the request")>
Pivot Facets
</h2>
#set($pivot = $response.response.facet_counts.facet_pivot)
#display_facet_pivot($pivot, "")

View File

@ -1,3 +1,12 @@
#**
* Display facets based on specific facet queries
* e.g.: facets specified by &facet.query=
*#
#set($field = $response.response.facet_counts.facet_queries)
<h2 #annTitle("Facets generated by adding &facet.query= to the request")>Query Facets</h2>
#display_facet_query($field, "", "")
<h2 #annTitle("Facets generated by adding &facet.query= to the request")>
Query Facets
</h2>
#display_facet_query($field, "", "")

View File

@ -1,4 +1,12 @@
<h2 #annTitle("Facets generated by adding &facet.range= to the request")>Range Facets</h2>
#**
* Display facets based on ranges of values, AKA "Bukets"
* e.g.: ranges specified by &facet.range=
*#
<h2 #annTitle("Facets generated by adding &facet.range= to the request")>
Range Facets
</h2>
#foreach ($field in $response.response.facet_counts.facet_ranges)
## Hide facets without value
#if($field.value.counts.size() > 0)
@ -11,5 +19,5 @@
#set($before = $field.value.before)
#set($after = $field.value.after)
#display_facet_range($f, $display, $name, $start, $end, $gap, $before, $after)
#end
#end
#end ## end if has any values
#end ## end for each facet range

View File

@ -1,5 +1,10 @@
#**
* Overall Facet display block
* Invokes the 4 facet and 1 cluster template
*#
#parse('facet_fields.vm')
#parse('facet_queries.vm')
#parse('facet_ranges.vm')
#parse('facet_pivot.vm')
#parse('cluster.vm')
#parse('cluster.vm')

View File

@ -1,17 +1,43 @@
#**
* Render the bottom section of the page visible to users
*#
<hr/>
<div>
<span>Options:</span>
#if($request.params.get('debugQuery'))
<a href="#url_for_home?#q#if($list.size($request.params.getParams('fq')) > 0)&#fqs($request.params.getParams('fq'))#end">disable debug</a>
<a href="#url_for_home?#q#if($list.size($request.params.getParams('fq')) > 0)&#fqs($request.params.getParams('fq'))#end">
disable debug</a>
#else
<a href="#url_for_lens&debugQuery=true&fl=*,score">enable debug</a>
<a href="#url_for_lens&debugQuery=true&fl=*,score">
enable debug</a>
#end
-
#if($annotate)
<a href="#url_for_home?#q#if($list.size($request.params.getParams('fq')) > 0)&#fqs($request.params.getParams('fq'))#end#boostPrice">disable annotation</a>
<a href="#url_for_home?#q#if($list.size($request.params.getParams('fq')) > 0)&#fqs($request.params.getParams('fq'))#end#boostPrice">
disable annotation</a>
#else
<a href="#url_for_lens&annotateBrowse=true">enable annotation</a>
<a href="#url_for_lens&annotateBrowse=true">
enable annotation</a>
#end
<a #annTitle("Click to switch to an XML response: &wt=xml") href="#url_for_lens&wt=xml#if($request.params.get('debugQuery'))&debugQuery=true#end">XML</a></div>
<div>Generated by <a href="http://wiki.apache.org/solr/VelocityResponseWriter">VelocityResponseWriter</a></div>
<div><span>Documentation: </span> <a href="http://lucene.apache.org/solr">Solr Home Page</a>, <a href="http://wiki.apache.org/solr">Solr Wiki</a></div>
<div>Disclaimer: The locations displayed in this demonstration are purely fictional. It is more than likely that no store with the items listed actually exists at that location!</div>
-
<a #annTitle("Click to switch to an XML response: &wt=xml") href="#url_for_lens&wt=xml#if($request.params.get('debugQuery'))&debugQuery=true#end">
XML results</a>
</div>
<div>
Generated by <a href="http://wiki.apache.org/solr/VelocityResponseWriter">VelocityResponseWriter</a>
</div>
<div>
<span>Documentation: </span>
<a href="http://lucene.apache.org/solr">Solr Home Page</a>, <a href="http://wiki.apache.org/solr">
Solr Wiki</a>
</div>
<div>
Disclaimer:
The locations displayed in this demonstration are purely fictional.
It is more than likely that no store with the items listed actually
exists at that location!
</div>

View File

@ -1,7 +1,10 @@
#**
* Provide elements for the <head> section of the HTML document
*#
## An example of using an arbitrary request parameter
<title>#param('title')</title>
<meta http-equiv="content-type" content="text/html; charset=UTF-8"/>
## An example of using an arbitrary request parameter
<title>#param('title')</title>
<meta http-equiv="content-type" content="text/html; charset=UTF-8"/>
<script type="text/javascript" src="#{url_root}/js/lib/jquery-1.7.2.min.js"></script>
<link rel="stylesheet" type="text/css" href="#{url_for_solr}/admin/file?file=/velocity/main.css&contentType=text/css"/>
@ -26,7 +29,7 @@
}
});
// http://localhost:8983/solr/terms?terms.fl=name&terms.prefix=i&terms.sort=count
// http://localhost:8983/solr/collection1/terms?terms.fl=name&terms.prefix=i&terms.sort=count&wt=velocity&v.template=suggest
});
</script>
</script>

View File

@ -1,3 +1,7 @@
#**
* Render the top section of the page visible to users
*#
<div id="head">
<span ><a href="#url_for_home#if($request.params.get('debugQuery'))?debugQuery=true#end"><img src="#{url_root}/img/solr.png" id="logo"/></a></span>
</div>
</div>

View File

@ -1,11 +1,25 @@
#**
* Called for each matching document but then
* calls one of product_doc, join_doc or richtext_doc
* depending on which fields the doc has
*#
#set($docId = $doc.getFieldValue('id'))
<div class="result-document">
#if($doc.getFieldValue('name'))
#parse("product-doc.vm")
#elseif($doc.getFieldValue('compName_s'))
#parse("join-doc.vm")
#else
#parse("richtext-doc.vm")
#end
## Has a "name" field ?
#if($doc.getFieldValue('name'))
#parse("product_doc.vm")
## Has a "compName_s" field ?
#elseif($doc.getFieldValue('compName_s'))
#parse("join_doc.vm")
## Fallback to richtext_doc
#else
#parse("richtext_doc.vm")
#end
</div>

View File

@ -1,24 +0,0 @@
<div class="result-document">
<div class="result-title"><b>$grouping.key</b></div>
<div>Total Matches in Group: $grouping.value.matches</div>
<div>#foreach ($group in $grouping.value.groups)
<div class="group-value">$group.groupValue <span #annTitle("The count of the number of documents in this group")>($group.doclist.numFound)</span></div>
<div class="group-doclist" #annTitle("Contains the top scoring documents in the group")>
#foreach ($doc in $group.doclist)
#set($docId = $doc.getFieldValue('id'))
#if($doc.getFieldValue('name'))
#parse("product-doc.vm")
#elseif($doc.getFieldValue('compName_s'))
#parse("join-doc.vm")
#else
#parse("richtext-doc.vm")
#end
#end
</div>
#end</div>
</div>
#if($params.getBool("debugQuery",false))
<a href="#" onclick='jQuery(this).siblings("pre").toggle(); return false;'>toggle explain</a>
<pre style="display:none">$response.getExplainMap().get($doc.getFirstValue('id'))</pre>
#end
</div>

View File

@ -0,0 +1,43 @@
#**
* Display grouped results
*#
<div class="result-document">
<div class="result-title">
<b>$grouping.key</b>
</div>
<div>
Total Matches in Group: $grouping.value.matches
</div>
<div> ## list of groups
#foreach ($group in $grouping.value.groups)
<div class="group-value">
#if($group.groupValue)$group.groupValue#{else}<i>No group</i>#end
<span #annTitle("The count of the number of documents in this group")>
($group.doclist.numFound)
</span>
</div>
<div class="group-doclist"
#annTitle("Contains the top scoring documents in the group")
>
#foreach ($doc in $group.doclist)
#set($docId = $doc.getFieldValue('id'))
#if($doc.getFieldValue('name'))
#parse("product_doc.vm")
#elseif($doc.getFieldValue('compName_s'))
#parse("join_doc.vm")
#else
#parse("richtext_doc.vm")
#end
#end
</div>
#end ## end of foreach group in grouping.value.groups
</div> ## div tag for entire list of groups
</div> ## end of div class=result-document

View File

@ -0,0 +1,25 @@
#**
* An extremely plain / debug version of hit.vm
*#
<table>
## For each field
#foreach( $fieldName in $doc.fieldNames )
## For each value
#foreach( $value in $doc.getFieldValues($fieldName) )
<tr>
## Field Name
<th align="right" valign="top">
#if( $foreach.count == 1 )
$fieldName:
#end
</th>
## Field Value(s)
<td align="left" valign="top">
$esc.html($value) <br/>
</td>
</tr>
#end ## end for each value
#end ## end for each field
</table>
<hr/>

View File

@ -1,4 +0,0 @@
<div class="result-title"><b>#field('compName_s')</b></div>
<div>Id: #field('id') (company-details document for <a href="http://wiki.apache.org/solr/Join" target="_new">join</a>)</div>
<div>Address: #field('address_s')</div>
#parse('debug.vm')

View File

@ -0,0 +1,20 @@
#**
* Display documents that are joined to other documents
*#
<div class="result-title">
<b>#field('compName_s')</b>
</div>
<div>
Id: #field('id')
(company-details document for
<a href="http://wiki.apache.org/solr/Join" target="_new">join</a>
)
</div>
<div>
Address: #field('address_s')
</div>
#parse('debug.vm')

View File

@ -1,3 +1,7 @@
#**
* Overall HTML page layout
*#
<html>
<head>
#parse("head.vm")

View File

@ -49,10 +49,32 @@ a {
position: relative;
}
.tabs-bar {
padding: 5px;
width: 100%;
border: 1px solid;
border-width: 0px 0px 1px 0px;
}
.tab {
font-weight: bold;
padding: 5px;
margin: 0px 5px;
border: 1px solid;
background-color: #dddddd;
border-top-left-radius: 4px;
border-top-right-radius: 4px;
}
.tab:hover {
background: #FEC293;
}
.tab.selected {
background-color: #ffffff;
border-bottom: 1px solid #ffffff;
}
.navigators h2 {
background: #FEC293;
border: 1px solid #ce9d77;
padding: 5px;
padding: 2px 5px;
}
.navigators ul {

View File

@ -0,0 +1,68 @@
#**
* Define some Mime-Types, short and long form
*#
## MimeType to extension map for detecting file type
## and showing proper icon
## List of types match the icons in /solr/img/filetypes
## Short MimeType Names
## Was called $supportedtypes
#set($supportedMimeTypes = "7z;ai;aiff;asc;audio;bin;bz2;c;cfc;cfm;chm;class;conf;cpp;cs;css;csv;deb;divx;doc;dot;eml;enc;file;gif;gz;hlp;htm;html;image;iso;jar;java;jpeg;jpg;js;lua;m;mm;mov;mp3;mpg;odc;odf;odg;odi;odp;ods;odt;ogg;pdf;pgp;php;pl;png;ppt;ps;py;ram;rar;rb;rm;rpm;rtf;sig;sql;swf;sxc;sxd;sxi;sxw;tar;tex;tgz;txt;vcf;video;vsd;wav;wma;wmv;xls;xml;xpi;xvid;zip")
## Long Form: map MimeType headers to our Short names
## Was called $extMap
#set( $mimeExtensionsMap = {
"application/x-7z-compressed": "7z",
"application/postscript": "ai",
"application/pgp-signature": "asc",
"application/octet-stream": "bin",
"application/x-bzip2": "bz2",
"text/x-c": "c",
"application/vnd.ms-htmlhelp": "chm",
"application/java-vm": "class",
"text/css": "css",
"text/csv": "csv",
"application/x-debian-package": "deb",
"application/msword": "doc",
"message/rfc822": "eml",
"image/gif": "gif",
"application/winhlp": "hlp",
"text/html": "html",
"application/java-archive": "jar",
"text/x-java-source": "java",
"image/jpeg": "jpeg",
"application/javascript": "js",
"application/vnd.oasis.opendocument.chart": "odc",
"application/vnd.oasis.opendocument.formula": "odf",
"application/vnd.oasis.opendocument.graphics": "odg",
"application/vnd.oasis.opendocument.image": "odi",
"application/vnd.oasis.opendocument.presentation": "odp",
"application/vnd.oasis.opendocument.spreadsheet": "ods",
"application/vnd.oasis.opendocument.text": "odt",
"application/pdf": "pdf",
"application/pgp-encrypted": "pgp",
"image/png": "png",
"application/vnd.ms-powerpoint": "ppt",
"audio/x-pn-realaudio": "ram",
"application/x-rar-compressed": "rar",
"application/vnd.rn-realmedia": "rm",
"application/rtf": "rtf",
"application/x-shockwave-flash": "swf",
"application/vnd.sun.xml.calc": "sxc",
"application/vnd.sun.xml.draw": "sxd",
"application/vnd.sun.xml.impress": "sxi",
"application/vnd.sun.xml.writer": "sxw",
"application/x-tar": "tar",
"application/x-tex": "tex",
"text/plain": "txt",
"text/x-vcard": "vcf",
"application/vnd.visio": "vsd",
"audio/x-wav": "wav",
"audio/x-ms-wma": "wma",
"video/x-ms-wmv": "wmv",
"application/vnd.ms-excel": "xls",
"application/xml": "xml",
"application/x-xpinstall": "xpi",
"application/zip": "zip"
})

View File

@ -0,0 +1,22 @@
#**
* Paging and Statistics at bottom of results
*#
## Usually rendered in pagination div tag
#if($response.response.get('grouped'))
## pass
#else
#link_to_previous_page("previous")
<span class="results-found">$page.results_found</span>
results found.
Page <span class="page-num">$page.current_page_number</span>
of <span class="page-count">$page.page_count</span>
#link_to_next_page("next")
#end
<br/>

View File

@ -0,0 +1,29 @@
#**
* Paging and Statistics at top of results
*#
## Usually rendered in pagination div tag
## Grouped Results / Not Paginated
#if($response.response.get('grouped'))
<span>
<span class="results-found">
$response.response.get('grouped').size() group(s)
</span>
found in ${response.responseHeader.QTime} ms
</span>
## Regular Results / Use Paging Links if needed
#else
<span>
<span class="results-found">$page.results_found</span>
results found in
${response.responseHeader.QTime} ms
</span>
Page <span class="page-num">$page.current_page_number</span>
of <span class="page-count">$page.page_count</span>
#end ## end else non-grouped results, normal pagination

View File

@ -1,3 +1,8 @@
#**
* Render a hit representing a Product
* assumed to have a field called "name"
*#
<div class="result-title"><b>#field('name')</b><span class="mlt"> #if($params.getBool('mlt', false) == false)<a href="#lensNoQ&q=id:$docId&mlt=true">More Like This</a>#end</span></div>
##do we have a physical store for this product
#set($store = $doc.getFieldValue('store'))
@ -24,4 +29,4 @@
<div>No Similar Items Found</div>
#end
</div>
#parse('debug.vm')
#parse('debug.vm')

View File

@ -1,19 +0,0 @@
#set($queryOpts = $params.get("queryOpts"))
#if($queryOpts == "group")
<div>
#set($groupF = $request.params.get('group.field'))
<label #annTitle("Add the &group.field parameter. Multiselect is supported")>Group By:
<select id="group" name="group.field" multiple="true">
##TODO: Handle multiple selects correctly
<option value="none"
#if($groupF == '')selected="true"#end>No Group</option>
<option value="manu_exact"
#if($groupF == 'manu_exact')selected="true"#end>Manufacturer</option>
<option value="popularity"
#if($groupF == 'popularity')selected="true"#end>Popularity</option>
</select>
</label>
<input type="hidden" name="group" value="true"/>
</div>
#end

View File

@ -1,40 +0,0 @@
#set($queryOpts = $params.get("queryOpts"))
#if($queryOpts == "spatial")
<div>
#set($loc = $request.params.get('pt'))
#set($dist = $request.params.get('d', "10"))
<label #annTitle("Add the &pt parameter")>Location Filter:
<select id="pt" name="pt">
<option value="none"
#if($loc == '')selected="true"#end>No Filter</option>
<option value="45.17614,-93.87341"
#if($loc == '45.17614,-93.87341')selected="true"#end>Buffalo, MN</option>
<option value="37.7752,-100.0232"
#if($loc == '37.7752,-100.0232')selected="true"#end>Dodge City, KS</option>
<option value="35.0752,-97.032"
#if($loc == '35.0752,-97.032')selected="true"#end>Oklahoma City, OK</option>
<option value="37.7752,-122.4232"
#if($loc == '37.7752,-122.4232')selected="true"#end>San Francisco CA</option>
</select>
</label>
<span #annTitle("Add the &d parameter")>Distance (KM): <input id="d" name="d" type="text" size="6"
value="#if($dist != '')${dist}#{else}10#end"/></span>
<input type="hidden" name="sfield" value="store"/>
<input type="hidden" id="spatialFQ" name="fq" value=""/>
<input type="hidden" name="queryOpts" value="spatial"/>
</div>
<script type="text/javascript">
$('#query-form').submit(function() {
if ($("#pt").val() != "none") {
$("#spatialFQ").val("{!bbox}");
}
$fqs = $("#allFQs").val();
$fqs = $fqs.replace("{!bbox}", "");
if ($fqs == ''){
$("#allFQs").remove();
}
$("#allFQs").val($fqs);
return true;
});
</script>
#end

View File

@ -0,0 +1,64 @@
#**
* Renders the main query form
*#
<div class="query-box">
<form id="query-form" action="#{url_for_home}" method="GET">
<div class="inputs">
<span #annTitle("Add the query using the &q= parameter")>
Find:
<input type="text" id="q" name="q" value="$!esc.html($params.get('q'))"/>
<input type="submit" id="querySubmit"/>
<input type="reset"/>
</span>
<div class="query-boost">
<span #annTitle("Add the boost function &bf=price to the query")>
<input type="checkbox" name="bf" value="price"
#if($request.params.get('bf') == 'price')checked="true"#end
>
Boost by Price
</input>
</span>
#parse("query_spatial.vm")
#parse("query_group.vm")
</div>
</div>
#if($request.params.get('debugQuery'))
<input type="hidden" name="debugQuery" value="true"/>
#end
#if($annotate == true)
<input type="hidden" name="annotateBrowse" value="true"/>
#end
#foreach($fq in $request.params.getParams('fq'))
#if ($fq != "{!bbox}")
<input type="hidden" name="fq" id="allFQs" value="$esc.html($fq)"/>
#end
#end
<div class="constraints" #annTitle("Lists out the &fq filters. Click to remove.")>
#foreach($fq in $params.getParams('fq'))
#set($previous_fq_count=$velocityCount - 1)
#if($fq != '')
&gt;
<a style="{text-decoration: line-through;}"
href="#url_for_filters($request.params.getParams('fq').subList(0,$previous_fq_count))"
>$fq</a>
#end
#end
</div>
<div class="parsed_query_header">
#if($request.params.get('debugQuery'))
<a href="#" onclick='jQuery(this).siblings("div").toggle(); return false;'>toggle parsed query</a>
<div class="parsed_query" style="display:none">$response.response.debug.parsedquery</div>
#end
#set($queryOpts = $request.params.get("queryOpts"))
#if($queryOpts && $queryOpts != "")
<input type="hidden" name="queryOpts" value="$queryOpts"/>
#end
</div>
</form>
</div>

View File

@ -0,0 +1,43 @@
#**
* Query settings for grouping by fields,
* e.g.: Manufacturer or Popularity
*#
#set($queryOpts = $params.get("queryOpts"))
#if($queryOpts == "group")
<div>
#set($groupF = $request.params.get('group.field'))
<label #annTitle("Add the &group.field parameter. Multiselect is supported")>
Group By:
<select id="group" name="group.field" multiple="true">
## TODO: Handle multiple selects correctly
## TODO: fix empty / "No Group" selection
<option value=""
#if($groupF == '')selected="true"#end
>
No Group
</option>
<option value="manu_exact"
#if($groupF == 'manu_exact')selected="true"#end
>
Manufacturer
</option>
<option value="popularity"
#if($groupF == 'popularity')selected="true"#end
>
Popularity
</option>
</select>
</label>
<input type="hidden" name="group" value="true"/>
</div>
#end

View File

@ -0,0 +1,75 @@
#**
* Query logic for selecting location / Geospatial search
*#
#set($queryOpts = $params.get("queryOpts"))
#if($queryOpts == "spatial")
<div>
#set($loc = $request.params.get('pt'))
## Normalize first trip through to "none" because
## an empty string generates an error message later on
#if( ! $loc )
#set( $loc = "none" )
#end
#set($dist = $request.params.get('d', "10"))
## Cities for The Select List
#set( $cities = {
"none": "No Filter",
"45.17614,-93.87341": "Buffalo, MN",
"37.7752,-100.0232": "Dodge City, KS",
"35.0752,-97.032": "Oklahoma City, OK",
"37.7752,-122.4232": "San Francisco CA"
})
<label #annTitle("Add the &pt parameter")>
Location Filter:
<select id="pt" name="pt">
## Generate <option> tag for each city
#foreach( $city_lon_lat in $cities.keySet() )
#set( $city_name = $cities.get($city_lon_lat) )
<option value="$city_lon_lat"
#if($loc == $city_lon_lat)selected="true"#end
>
$city_name
</option>
#end
</select>
</label>
<span #annTitle("Add the &d parameter")>
Distance (KM):
<input id="d" name="d" type="text" size="6"
value="#if($dist != '')${dist}#{else}10#end" ## TODO: isn't the default of 10 above sufficient? no if/else needed?
/>
</span>
<input type="hidden" name="sfield" value="store"/>
<input type="hidden" id="spatialFQ" name="fq" value=""/>
<input type="hidden" name="queryOpts" value="spatial"/>
</div>
<script type="text/javascript">
$('#query-form').submit(function() {
if ($("#pt").val() != "none") {
$("#spatialFQ").val("{!bbox}");
}
$fqs = $("#allFQs").val();
$fqs = $fqs.replace("{!bbox}", "");
if ($fqs == ''){
$("#allFQs").remove();
}
$("#allFQs").val($fqs);
return true;
});
</script>
#end

View File

@ -0,0 +1,22 @@
#**
* Render the main Results List
*#
## Usually displayed inside <div class="results">
#if($response.response.get('grouped'))
#foreach($grouping in $response.response.get('grouped'))
#parse("hit_grouped.vm")
#end
#else
#foreach($doc in $response.results)
#parse("hit.vm")
## Can get an extremely simple view of the doc
## which might be nicer for debugging
##parse("hit_plain.vm")
#end
#end

View File

@ -1,114 +0,0 @@
## Mimetype to extension map for detecting file type and show icon
## List of types match the icons in /solr/img/filetypes
#set($extMap = {"application/x-7z-compressed": "7z",
"application/postscript": "ai",
"application/pgp-signature": "asc",
"application/octet-stream": "bin",
"application/x-bzip2": "bz2",
"text/x-c": "c",
"application/vnd.ms-htmlhelp": "chm",
"application/java-vm": "class",
"text/css": "css",
"text/csv": "csv",
"application/x-debian-package": "deb",
"application/msword": "doc",
"message/rfc822": "eml",
"image/gif": "gif",
"application/winhlp": "hlp",
"text/html": "html",
"application/java-archive": "jar",
"text/x-java-source": "java",
"image/jpeg": "jpeg",
"application/javascript": "js",
"application/vnd.oasis.opendocument.chart": "odc",
"application/vnd.oasis.opendocument.formula": "odf",
"application/vnd.oasis.opendocument.graphics": "odg",
"application/vnd.oasis.opendocument.image": "odi",
"application/vnd.oasis.opendocument.presentation": "odp",
"application/vnd.oasis.opendocument.spreadsheet": "ods",
"application/vnd.oasis.opendocument.text": "odt",
"application/pdf": "pdf",
"application/pgp-encrypted": "pgp",
"image/png": "png",
"application/vnd.ms-powerpoint": "ppt",
"audio/x-pn-realaudio": "ram",
"application/x-rar-compressed": "rar",
"application/vnd.rn-realmedia": "rm",
"application/rtf": "rtf",
"application/x-shockwave-flash": "swf",
"application/vnd.sun.xml.calc": "sxc",
"application/vnd.sun.xml.draw": "sxd",
"application/vnd.sun.xml.impress": "sxi",
"application/vnd.sun.xml.writer": "sxw",
"application/x-tar": "tar",
"application/x-tex": "tex",
"text/plain": "txt",
"text/x-vcard": "vcf",
"application/vnd.visio": "vsd",
"audio/x-wav": "wav",
"audio/x-ms-wma": "wma",
"video/x-ms-wmv": "wmv",
"application/vnd.ms-excel": "xls",
"application/xml": "xml",
"application/x-xpinstall": "xpi",
"application/zip": "zip"})
#if($doc.getFieldValue('title'))
#set($title = $esc.html($doc.getFirstValue('title')))
#else
#set($title = "["+$doc.getFieldValue('id')+"]")
#end
#if($doc.getFieldValue('url'))
#set($url = $doc.getFieldValue('url'))
#elseif($doc.getFieldValue('resourcename'))
#set($url = "file:///$doc.getFieldValue('resourcename')")
#else
#set($url = "$doc.getFieldValue('id')")
#end
#set($supportedtypes = "7z;ai;aiff;asc;audio;bin;bz2;c;cfc;cfm;chm;class;conf;cpp;cs;css;csv;deb;divx;doc;dot;eml;enc;file;gif;gz;hlp;htm;html;image;iso;jar;java;jpeg;jpg;js;lua;m;mm;mov;mp3;mpg;odc;odf;odg;odi;odp;ods;odt;ogg;pdf;pgp;php;pl;png;ppt;ps;py;ram;rar;rb;rm;rpm;rtf;sig;sql;swf;sxc;sxd;sxi;sxw;tar;tex;tgz;txt;vcf;video;vsd;wav;wma;wmv;xls;xml;xpi;xvid;zip")
#set($ct = $list.get($doc.getFirstValue('content_type').split(";"),0))
#set($filename = $doc.getFieldValue('resourcename'))
#set($filetype = false)
#set($filetype = $extMap.get($ct))
##TODO: falling back to file extension is convenient, except when you don't have an icon for that extension
## example "application/vnd.openxmlformats-officedocument.wordprocessingml.document" document
## with a .docx extension. It'd be nice to fall back to an "unknown" or the existing "file" type
## We sort of do this below, but only if the filename has no extension (anything after the last dot).
#if(!$filetype)#set($filetype = $filename.substring($filename.lastIndexOf(".")).substring(1))#end
##if(!$filetype)#set($filetype = "file")#end
##if(!$supportedtypes.contains($filetype))#set($filetype = "file")#end
<div class="result-title">
## Small file type icons from http://www.splitbrain.org/projects/file_icons (public domain)
<img src="#{url_root}/img/filetypes/${filetype}.png" align="center">
<a href="${url}" target="_blank"><b>$title</b></a><span class="mlt"> #if($params.getBool('mlt', false) == false)<a href="#lensNoQ&q=id:%22$docId%22&mlt=true">More Like This</a>#end</span></div>
<div>Id: #field('id')</div>
<div>
#if($doc.getFieldValue('resourcename'))Resource name: $filename
#elseif($url)URL: $url
#end
#if($ct) ($ct)#end
</div>
#if($doc.getFieldValue('author'))<div>Author: #field('author')</div>#end
#if($doc.getFieldValue('last_modified'))<div>last-modified: #field('last_modified')</div>#end
<div class="result-body">#field('content')</div>
<div class="mlt">
#set($mlt = $mltResults.get($docId))
#set($mltOn = $params.getBool('mlt'))
#if($mltOn == true)<div class="field-name">Similar Items</div>#end
#if ($mltOn && $mlt && $mlt.size() > 0)
<ul>
#foreach($mltHit in $mlt)
#set($mltId = $mltHit.getFieldValue('id'))
<li><div><a href="#url_for_home?q=id:$mltId">$mltId</a></div><div><span class="field-name">Title:</span> $mltHit.getFieldValue('title')</div>
<div><span class="field-name">Author:</span> $mltHit.getFieldValue('author') <span class="field-name">Description:</span> $mltHit.getFieldValue('description')</div>
</li>
#end
</ul>
#elseif($mltOn && $mlt.size() == 0)
<div>No Similar Items Found</div>
#end
</div>
#parse('debug.vm')

View File

@ -0,0 +1,153 @@
#**
* Render a complex document in the results list
*#
## Load Mime-Type List and Mapping
#parse('mime_type_lists.vm')
## Sets:
## * supportedMimeTypes, AKA supportedtypes
## * mimeExtensionsMap, AKA extMap
## Title
#if($doc.getFieldValue('title'))
#set($title = $esc.html($doc.getFirstValue('title')))
#else
#set($title = "["+$doc.getFieldValue('id')+"]")
#end
## URL
#if($doc.getFieldValue('url'))
#set($url = $doc.getFieldValue('url'))
#elseif($doc.getFieldValue('resourcename'))
#set($url = "file:///$doc.getFieldValue('resourcename')")
#else
#set($url = "$doc.getFieldValue('id')")
#end
## Sort out Mime-Type
#set($ct = $list.get($doc.getFirstValue('content_type').split(";"),0))
#set($filename = $doc.getFieldValue('resourcename'))
#set($filetype = false)
#set($filetype = $mimeExtensionsMap.get($ct))
## TODO: falling back to file extension is convenient,
## except when you don't have an icon for that extension
## example "application/vnd.openxmlformats-officedocument.wordprocessingml.document"
## document with a .docx extension.
## It'd be nice to fall back to an "unknown" or the existing "file" type
## We sort of do this below, but only if the filename has no extension
## (anything after the last dot).
#if(!$filetype)
#set($filetype = $filename.substring($filename.lastIndexOf(".")).substring(1))
#end
## #if(!$filetype)
## #set($filetype = "file")
## #end
## #if(!$supportedMimeTypes.contains($filetype))
## #set($filetype = "file")
## #end
## Row 1: Icon and Title and mlt link
<div class="result-title">
## Icon
## Small file type icons from http://www.splitbrain.org/projects/file_icons (public domain)
<img src="#{url_root}/img/filetypes/${filetype}.png" align="center">
## Title, hyperlinked
<a href="${url}" target="_blank">
<b>$title</b></a>
## Link for MLT / More Like This / Find Similar
<span class="mlt">
#if($params.getBool('mlt', false) == false)
<a href="#lensNoQ&q=id:%22$docId%22&mlt=true">
More Like This</a>
#end
</span>
</div>
## Row 2?: ID / URL
<div>
Id: #field('id')
</div>
## Resource Name
<div>
#if($doc.getFieldValue('resourcename'))
Resource name: $filename
#elseif($url)
URL: $url
#end
#if($ct)
($ct)
#end
</div>
## Author
#if($doc.getFieldValue('author'))
<div>
Author: #field('author')
</div>
#end
## Last_Modified Date
#if($doc.getFieldValue('last_modified'))
<div>
last-modified:
#field('last_modified')
</div>
#end
## Main content of doc
<div class="result-body">
#field('content')
</div>
## Display Similar Documents / MLT = More Like This
<div class="mlt">
#set($mlt = $mltResults.get($docId))
#set($mltOn = $params.getBool('mlt'))
#if($mltOn == true)
<div class="field-name">
Similar Items
</div>
#end
## If has MLT enabled An Entries to show
#if ($mltOn && $mlt && $mlt.size() > 0)
<ul>
#foreach($mltHit in $mlt)
#set($mltId = $mltHit.getFieldValue('id'))
<li>
<div>
<a href="#url_for_home?q=id:$mltId">
$mltId</a>
</div>
<div>
<span class="field-name">
Title:
</span>
$mltHit.getFieldValue('title')
</div>
<div>
<span class="field-name">
Author:
</span>
$mltHit.getFieldValue('author')
<span class="field-name">
Description:
</span>
$mltHit.getFieldValue('description')
</div>
</li>
#end ## end for each mltHit in $mlt
</ul>
## Else MLT Enabled but no mlt results for this query
#elseif($mltOn && $mlt.size() == 0)
<div>No Similar Items Found</div>
#end
</div> ## div class=mlt
#parse('debug.vm')

View File

@ -1,3 +1,8 @@
#**
* Provides cynamic spelling suggestions
* as you type in the search form
*#
#foreach($t in $response.response.terms.name)
$t.key
#end
$t.key
#end

View File

@ -1,6 +1,50 @@
#**
* Provides navigation/access to Advanced search options
* Usually displayed near the top of the page
*#
##TODO: Make some nice tabs here
#set($queryOpts = $params.get("queryOpts"))
<span #annTitle("Click the link to demonstrate various Solr capabilities")><span>Examples: </span><span class="tab">#if($queryOpts && $queryOpts != "")<a href="#url_for_home/?#debug#annotate">Simple</a>#{else}Simple#end</span>
<span class="tab">#if($queryOpts == "spatial")Spatial#else<a href="#url_for_home?&queryOpts=spatial#debug#annotate">Spatial</a>#end</span>
<span class="tab">#if($queryOpts == "group")Group By#else<a href="#url_for_home?#debug#annotate&queryOpts=group&group=true&group.field=manu_exact">Group By</a>#end</span></span>
<hr/>
<div class="tabs-bar" #annTitle("Click the link to demonstrate various Solr capabilities")>
<span>Type of Search:</span>
##queryOpts=$queryOpts
## return to Simple Search
##set( $selected = ($queryOpts && $queryOpts != "") )
#set( $selected = ! $queryOpts )
<span class="tab #if($selected)selected#end">
#if($selected)
Simple
#else
<a href="#url_for_home/?#debug#annotate">
Simple</a>
#end
</span>
## GEO-Spatial / Location Based
#set( $selected = ($queryOpts == "spatial") )
<span class="tab #if($selected)selected#end">
#if($selected)
Spatial
#else
<a href="#url_for_home?&queryOpts=spatial#debug#annotate">
Spatial</a>
#end
</span>
## Group By Field
#set( $selected = ($queryOpts == "group") )
<span class="tab #if($selected)selected#end">
#if($selected)
Group By
#else
<a href="#url_for_home?#debug#annotate&queryOpts=group&group=true&group.field=manu_exact">
Group By</a>
#end
</span>
</div>