Skip to content

Commit

Permalink
adding a search session and query parameter to singleViews, closes #282
Browse files Browse the repository at this point in the history
… (#329)

* add processing and styling of exist:match elements #282

* add lucene search to single views #282

via URL parameter `q`

* pass query parameter from search page to subsequent single view #282

* store search results in session

* first shot at adding a search navigation in document singleView #282

* add search navigation to further singleViews #282

* improve links
  • Loading branch information
peterstadler authored and jakosch committed Nov 22, 2019
1 parent b3767f9 commit e0fd590
Show file tree
Hide file tree
Showing 8 changed files with 224 additions and 76 deletions.
37 changes: 30 additions & 7 deletions modules/app.xqm
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import module namespace gl="http://xquery.weber-gesamtausgabe.de/modules/gl" at
import module namespace er="http://xquery.weber-gesamtausgabe.de/modules/external-requests" at "external-requests.xqm";
import module namespace dev-app="http://xquery.weber-gesamtausgabe.de/modules/dev/dev-app" at "dev/dev-app.xqm";
import module namespace functx="http://www.functx.com";
import module namespace kwic="http://exist-db.org/xquery/kwic";
import module namespace templates="http://exist-db.org/xquery/templates";
import module namespace str="http://xquery.weber-gesamtausgabe.de/modules/str" at "xmldb:exist:///db/apps/WeGA-WebApp-lib/xquery/str.xqm";
import module namespace app-shared="http://xquery.weber-gesamtausgabe.de/modules/app-shared" at "xmldb:exist:///db/apps/WeGA-WebApp-lib/xquery/app-shared.xqm";
Expand Down Expand Up @@ -899,7 +900,8 @@ declare
declare
%templates:default("lang", "en")
function app:print-wega-bio($node as node(), $model as map(*), $lang as xs:string) as element(div)* {
let $bio := wega-util:transform($model('doc')//(tei:note[@type='bioSummary'] | tei:event[tei:head] | tei:note[parent::tei:org]), doc(concat($config:xsl-collection-path, '/persons.xsl')), config:get-xsl-params(()))
let $query-result:= app:inject-query($model?doc/*)
let $bio := wega-util:transform($query-result//(tei:note[@type='bioSummary'] | tei:event[tei:head] | tei:note[parent::tei:org]), doc(concat($config:xsl-collection-path, '/persons.xsl')), config:get-xsl-params(()))
return
if(some $i in $bio satisfies $i instance of element()) then $bio
else
Expand Down Expand Up @@ -1251,11 +1253,11 @@ declare
default return doc(concat($config:xsl-collection-path, '/var.xsl'))
let $textRoot :=
switch($docType)
case 'diaries' return $doc/tei:ab
case 'works' return $doc/mei:mei
case 'var' case 'addenda' return $doc//tei:text/tei:body/(tei:div[@xml:lang=$lang] | tei:divGen | tei:div[not(@xml:lang)])
case 'thematicCommentaries' return $doc//tei:text/(tei:body | tei:back)
default return $doc//tei:text/tei:body
case 'diaries' return $doc/tei:ab ! app:inject-query(.)
case 'works' return $doc/mei:mei ! app:inject-query(.)
case 'var' case 'addenda' return ($doc//tei:text/tei:body ! app:inject-query(.))/(tei:div[@xml:lang=$lang] | tei:divGen | tei:div[not(@xml:lang)])
case 'thematicCommentaries' return $doc//tei:text/tei:body ! app:inject-query(.) | $doc//tei:text/tei:back
default return $doc//tei:text/tei:body ! app:inject-query(.)
let $body :=
if(functx:all-whitespace(<root>{$textRoot}</root>))
then
Expand Down Expand Up @@ -1289,6 +1291,27 @@ declare
}
};

(:~
: Search and highlight query strings in a document
: Helper function for app:prepare-text()
:
: @param $input must be node() that is indexed by Lucene
: @return if a hit was found in $input, an expanded copy of the $input with exist:match elements wrapping the hits.
: If no hit was found, the initial $input is returned
:)
declare %private function app:inject-query($input as node()) {
let $q := request:get-parameter('q', '')
return
if($q) then
let $sanitized-query-string := wega-util:strip-diacritics(str:normalize-space(str:sanitize(string-join($q, ' '))))
let $query := search:create-lucene-query-element($sanitized-query-string)
let $result := ft:query($input, $query)
return
if($result) then $result ! kwic:expand(.)
else $input
else $input
};

declare
%templates:wrap
function app:series($node as node(), $model as map(*)) as xs:string {
Expand Down Expand Up @@ -1695,7 +1718,7 @@ declare
return
element {name($node)} {
$node/@*[not(name(.) = 'href')],
if($node[self::xhtml:a]) then attribute href {app:createUrlForDoc($model('doc'), $lang)}
if($node[self::xhtml:a]) then attribute href {app:createUrlForDoc($model('doc'), $lang) || (if(map:contains($model, 'query-string-org')) then ('?q=' || $model?query-string-org) else ())}
else (),
if($title instance of xs:string or $title instance of text() or count($title) gt 1) then $title
else $title/node()
Expand Down
58 changes: 55 additions & 3 deletions modules/search.xqm
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ import module namespace str="http://xquery.weber-gesamtausgabe.de/modules/str" a
import module namespace wdt="http://xquery.weber-gesamtausgabe.de/modules/wdt" at "wdt.xqm";
import module namespace lang="http://xquery.weber-gesamtausgabe.de/modules/lang" at "lang.xqm";
import module namespace wega-util="http://xquery.weber-gesamtausgabe.de/modules/wega-util" at "wega-util.xqm";
import module namespace controller="http://xquery.weber-gesamtausgabe.de/modules/controller" at "controller.xqm";
import module namespace app="http://xquery.weber-gesamtausgabe.de/modules/app" at "app.xqm";
import module namespace functx="http://www.functx.com";

declare variable $search:ERROR := QName("http://xquery.weber-gesamtausgabe.de/modules/search", "Error");
Expand Down Expand Up @@ -46,7 +48,7 @@ declare
return
switch($docType)
(: search page :)
case 'search' return search:search(map:merge(($model, $filters, map:entry('docID', 'indices'))))
case 'search' return search:search-session(map:merge(($model, $filters, map:entry('docID', 'indices'))), search:search#1)
(: controller sends docType=persons which needs to be turned into "personsPlus" here :)
case 'persons' return search:list(map:merge(($filters, map:put($model, 'docType', 'personsPlus'))))
(: various list views :)
Expand Down Expand Up @@ -160,7 +162,7 @@ declare
: Search results and other goodies for the *search* page
~:)
declare %private function search:search($model as map(*)) as map(*) {
let $updatedModel := search:prepare-search-string($model)
let $updatedModel := $model
let $docTypes :=
if($updatedModel?query-docTypes = 'all') then ($search:wega-docTypes, 'var', 'addenda') (: silently add 'var' (= special pages, e.g. "Impressum/About" or "Sonderband/Special Volume") to the list of docTypes :)
else $search:wega-docTypes[.=$updatedModel?query-docTypes]
Expand All @@ -176,6 +178,10 @@ declare %private function search:search($model as map(*)) as map(*) {
let $fulltext-search :=
if($updatedModel('query-string')) then search:merge-hits($docTypes ! search:fulltext($filtered-results, $updatedModel('query-string'), $updatedModel?filters, .))
else $filtered-results
let $store-session :=
if(count($fulltext-search) gt 0)
then session:set-attribute('wegasearch', map:merge(($updatedModel, map:entry('search-results', $fulltext-search))))
else ()
return
map:merge(($updatedModel, map:entry('search-results', $fulltext-search)))
};
Expand Down Expand Up @@ -235,7 +241,7 @@ declare %private function search:fulltext($items as item()*, $searchString as xs
(:~
: Parse the query string and create an XML query element for the lucene search
~:)
declare %private function search:create-lucene-query-element($searchString as xs:string) as element(query) {
declare function search:create-lucene-query-element($searchString as xs:string) as element(query) {
let $groups := analyze-string($searchString, '(-?"(.+?)")')/* (: split into fn:match – for expressions in parentheses – and fn:non-match elements :)
let $queryElement := function($elementName as xs:string, $token as item()) as element() {
element {$elementName} {
Expand Down Expand Up @@ -432,3 +438,49 @@ declare %private function search:prepare-search-string($model as map()) as map(*
}
))
};

(:~
: Cache search results in browser session
:
: @param $model the current model map of the templating module
: @param $callback a callback function to actually do the search if the session is empty
: @return a map object {'filters': {}, 'search-results': {}, 'query-string-org': '', 'query-docTypes': ('') }
~:)
declare %private function search:search-session($model as map(), $callback as function() as map(*)) as map(*) {
let $updatedModel := search:prepare-search-string($model)
let $session-exists :=
try {
count(session:get-attribute('wegasearch')?search-results) gt 0
and session:get-attribute('wegasearch')?query-string-org = $updatedModel?query-string-org
and functx:sequence-deep-equal(session:get-attribute('wegasearch')?filters?*, $updatedModel?filters?*)
and functx:sequence-deep-equal(session:get-attribute('wegasearch')?query-docTypes, $updatedModel?query-docTypes)
}
catch * {false()}
return
if($session-exists)
then session:get-attribute('wegasearch')
else $callback($updatedModel)
};

declare
%templates:wrap
function search:get-session-for-singleview($node as node(), $model as map(*)) as map()? {
let $wegasearch := session:get-attribute('wegasearch')
let $index-of-current-doc := functx:index-of-node($wegasearch?search-results?doc, $model?doc)
let $page := ceiling($index-of-current-doc div config:entries-per-page())
let $url := controller:resolve-link('$link/search', $model) || '?q=' || $wegasearch?query-string-org || '&amp;d=' || string-join($wegasearch?query-docTypes, '&amp;d=') || '&amp;page=' || $page
let $search-prev-item-url :=
if($index-of-current-doc gt 1) then app:createUrlForDoc($wegasearch?search-results[$index-of-current-doc - 1]?doc, $model?lang) || '?q=' || $wegasearch?query-string-org
else '#'
let $search-next-item-url :=
if($index-of-current-doc lt count($wegasearch?search-results)) then app:createUrlForDoc($wegasearch?search-results[$index-of-current-doc + 1]?doc, $model?lang) || '?q=' || $wegasearch?query-string-org
else '#'
return
map:merge((
$wegasearch,
map:entry('index-of-current-doc', $index-of-current-doc),
map:entry('search-backlink', $url),
map:entry('search-prev-item-url', $search-prev-item-url),
map:entry('search-next-item-url', $search-next-item-url)
))
};
2 changes: 1 addition & 1 deletion resources/sass/pages/_search.scss
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
}
}

*[class*="hi-"], *[class*="hi-"] *, .kwic .hi {
*[class*="hi-"], *[class*="hi-"] *, .hi {
color: #ffffff !important;
background-color: $primary !important;
}
Expand Down
57 changes: 36 additions & 21 deletions templates/document.html
Original file line number Diff line number Diff line change
Expand Up @@ -11,28 +11,43 @@ <h1 class="document" data-template="app:document-title">CARL MARIA VON WEBER AN
</div>
<div class="colored borderBottom">
<div class="container">
<div class="row">
<div class="col-sm-10">
<ol class="breadcrumb">
<li>
<a href="$link/index">Home</a>
</li>
<li>
<a data-template="app:breadcrumb-person">Carl Maria von Weber</a>
</li>
<li>
<a data-template="app:breadcrumb-docType">Korrespondenz</a>
</li>
<li>
<span data-template="app-shared:print" data-template-key="docID">A040080</span> <span data-template="app-shared:if-not-matches" data-template-key="docType" data-template-value="news" data-template-wrap="no">
<span data-template="app:status" class="docStatus">in Bearbeitung</span>
</span>
</li>
</ol>
<div data-template="templates:if-parameter-unset" data-template-param="q">
<div class="row">
<div class="col-sm-10">
<ol class="breadcrumb">
<li>
<a href="$link/index">Home</a>
</li>
<li>
<a data-template="app:breadcrumb-person">Carl Maria von Weber</a>
</li>
<li>
<a data-template="app:breadcrumb-docType">Korrespondenz</a>
</li>
<li>
<span data-template="app-shared:print" data-template-key="docID">A040080</span> <span data-template="app-shared:if-not-matches" data-template-key="docType" data-template-value="news" data-template-wrap="no">
<span data-template="app:status" class="docStatus">in Bearbeitung</span>
</span>
</li>
</ol>
</div>
<div class="col-sm-2 d-none d-sm-block backLinkInBreadcrumb" onclick="history.back();">
<i class="fa fa-arrow-left"/>
<span data-template="lang:translate">back</span>
</div>
</div>
<div class="col-sm-2 d-none d-sm-block backLinkInBreadcrumb" onclick="history.back();">
<i class="fa fa-arrow-left"/>
<span data-template="lang:translate">back</span>
</div>
<div data-template="templates:if-parameter-set" data-template-param="q">
<div class="row" data-template="search:get-session-for-singleview">
<div class="col-md-4">
<a href="$link/search" data-template="app-shared:set-attr" data-template-attr="href" data-template-key="search-prev-item-url"><i class="fa fa-arrow-left"/> Zurück in der Trefferliste</a>
</div>
<div class="col-md-4">
<span data-template="app-shared:print" data-template-key="index-of-current-doc">15</span> / <a href="$link/search" data-template="app-shared:set-attr" data-template-attr="href" data-template-key="search-backlink"><span data-template="search:results-count">124 Suchergebnisse</span></a>
</div>
<div class="col-md-4">
<a href="$link/search" data-template="app-shared:set-attr" data-template-attr="href" data-template-key="search-next-item-url">Vor in der Trefferliste <i class="fa fa-arrow-right"/></a>
</div>
</div>
</div>
</div>
Expand Down
33 changes: 24 additions & 9 deletions templates/person.html
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,31 @@ <h1 data-template="app:person-title">Weber, Carl Maria von</h1>
</div>
<div class="colored borderBottom">
<div class="container">
<div class="row">
<div class="col-sm-10">
<ol class="breadcrumb">
<li><a href="$link/index">Home</a></li>
<li><span data-template="app:person-forename-surname">Carl Maria von Weber</span></li>
<!-- <li data-template="lang:translate">bio</li>-->
</ol>
<div data-template="templates:if-parameter-unset" data-template-param="q">
<div class="row">
<div class="col-sm-10">
<ol class="breadcrumb">
<li><a href="$link/index">Home</a></li>
<li><span data-template="app:person-forename-surname">Carl Maria von Weber</span></li>
<!-- <li data-template="lang:translate">bio</li>-->
</ol>
</div>
<div class="col-sm-2 d-none d-sm-block backLinkInBreadcrumb" onclick="history.back();">
<i class="fa fa-arrow-left"/> <span data-template="lang:translate">back</span>
</div>
</div>
<div class="col-sm-2 d-none d-sm-block backLinkInBreadcrumb" onclick="history.back();">
<i class="fa fa-arrow-left"/> <span data-template="lang:translate">back</span>
</div>
<div data-template="templates:if-parameter-set" data-template-param="q">
<div class="row" data-template="search:get-session-for-singleview">
<div class="col-md-4">
<a href="$link/search" data-template="app-shared:set-attr" data-template-attr="href" data-template-key="search-prev-item-url"><i class="fa fa-arrow-left"/> Zurück in der Trefferliste</a>
</div>
<div class="col-md-4">
<span data-template="app-shared:print" data-template-key="index-of-current-doc">15</span> / <a href="$link/search" data-template="app-shared:set-attr" data-template-attr="href" data-template-key="search-backlink"><span data-template="search:results-count">124 Suchergebnisse</span></a>
</div>
<div class="col-md-4">
<a href="$link/search" data-template="app-shared:set-attr" data-template-attr="href" data-template-key="search-next-item-url">Vor in der Trefferliste <i class="fa fa-arrow-right"/></a>
</div>
</div>
</div>
</div>
Expand Down
Loading

0 comments on commit e0fd590

Please sign in to comment.