Modifications pour le document Solr Search Macros
Modifié par Florent Charton le 2026/03/13 11:04
Depuis la version 2.1
modifié par Florent Charton
sur 2024/08/08 18:44
sur 2024/08/08 18:44
Commentaire de modification :
Install extension [org.xwiki.platform:xwiki-platform-search-solr-ui/15.10.11]
À la version 5.1
modifié par Florent Charton
sur 2026/03/13 11:04
sur 2026/03/13 11:04
Commentaire de modification :
Install extension [org.xwiki.platform:xwiki-platform-search-solr-ui/17.10.4]
Résumé
-
Propriétés de la Page (1 modifications, 0 ajouts, 0 suppressions)
Détails
- Propriétés de la Page
-
- Contenu
-
... ... @@ -4,13 +4,11 @@ 4 4 #set ($rangePattern = $regextool.compile('^[\[{](.+) TO (.+)[\]}]$')) 5 5 #set ($wildcardPattern = $regextool.compile('^\(.*\*.*\)$')) 6 6 7 -#macro (displaySearchForm) 7 +#macro (_displaySearchFormBegin) 8 8 #set($void = $services.progress.startStep('#displaySearchForm')) 9 9 {{html clean="false"}} 10 - <form class="search-form row" action="$doc.getURL()" role="search">10 + <form class="search-form" action="$doc.getURL()" role="search"> 11 11 <div class="hidden"> 12 - <input type="hidden" name="sort" value="$!escapetool.xml($sort)"/> 13 - <input type="hidden" name="sortOrder" value="$!escapetool.xml($sortOrder)"/> 14 14 <input type="hidden" name="highlight" value="$highlightEnabled"/> 15 15 <input type="hidden" name="facet" value="$facetEnabled"/> 16 16 ## The parameter used to determine if the request has been redirected with default search filters. ... ... @@ -27,26 +27,36 @@ 27 27 #end 28 28 #end 29 29 </div> 30 - <div class=" col-xs-12col-sm-6">28 + <div class="search-bar"> 31 31 <div class="input-group"> 30 + <input id="search-page-bar-input" type="search" name="text" class="form-control" 31 + title="$escapetool.xml($services.localization.render('search.page.bar.query.title'))" 32 + placeholder="$escapetool.xml($services.localization.render('search.page.bar.query.title'))" 33 + value="$escapetool.xml($text)"/> 32 32 <label class='sr-only' for='search-page-bar-input'> 33 - $services.localization.render('search.page.bar.query.title') 35 + $escapetool.xml($services.localization.render('search.page.bar.query.title')) 34 34 </label> 35 - <input id='search-page-bar-input' type='search' name='text' class='form-control withTip useTitleAsTip' 36 - title="$services.localization.render('search.page.bar.query.title')" value="$escapetool.xml($text)"/> 37 37 <span class="input-group-btn"> 38 38 <button type="submit" class="btn btn-primary"> 39 39 $services.icon.renderHTML('search') 40 - <span class="sr-only">$services.localization.render('search.page.bar.submit')</span>40 + <span>$escapetool.xml($services.localization.render('search.page.bar.submit'))</span> 41 41 </button> 42 42 </span> 43 43 </div> 44 44 </div> 45 - </form> 46 46 {{/html}} 47 47 #set($void = $services.progress.endStep()) 48 48 #end 49 49 49 +## We make sure the html block in this macro is not considered as inline to avoid generating extra `p` tags. 50 +#macro (_displaySearchFormEnd) 51 + 52 + {{html clean="false"}} 53 + </form> 54 + {{/html}} 55 + 56 +#end 57 + 50 50 #macro (displaySearchDebugInfo) 51 51 (% class="search-debug" %)((( 52 52 === Debug Information === ... ... @@ -111,12 +111,12 @@ 111 111 #end 112 112 #extendQueryString($url $resetParameters) 113 113 [[{{translation key="solr.facets.resetAll"}}>>path:$url 114 - ||class="search-facets-action-reset"]]## Continue in the same paragraph. 122 + ||class="search-facets-action-reset force-no-underline"]]## Continue in the same paragraph. 115 115 {{html clean="false"}} 116 - <a href="#" class="search-facets-action-collapseAll hidden"> 124 + <a href="#" class="search-facets-action-collapseAll hidden force-no-underline"> 117 117 $escapetool.xml($services.localization.render('solr.facets.collapseAll')) 118 118 </a> 119 - <a href="#" class="search-facets-action-expandAll hidden"> 127 + <a href="#" class="search-facets-action-expandAll hidden force-no-underline"> 120 120 $escapetool.xml($services.localization.render('solr.facets.expandAll')) 121 121 </a> 122 122 <span class="clearfloats"></span> ... ... @@ -148,9 +148,10 @@ 148 148 ## Show active facets (that have selected values or that have an explicit limit on the number of values, i.e. 149 149 ## pagination) as expanded. Collapse the rest, otherwise you have to scroll to see all the available facets. 150 150 #set ($facetValuesLimit = $request.getParameter("l_$facetField.name")) 151 - <div class="search-facet#if ($facetRequestValues || $facetValuesLimit) expanded#end" data-name="$facetField.name"> 152 - #displaySearchFacetHeader($facetField) 153 - #displaySearchFacetBody($facetField) 159 + <div class="search-facet" data-name="$facetField.name"> 160 + #set ($expanded = ($facetRequestValues || $facetValuesLimit)) 161 + #displaySearchFacetHeader($facetField $expanded) 162 + #displaySearchFacetBody($facetField $expanded) 154 154 </div> 155 155 #end 156 156 #end ... ... @@ -167,7 +167,7 @@ 167 167 #setVariable("$property" $classDocument.xWikiClass.get($classPropertyReference.name)) 168 168 #end 169 169 170 -#macro (displaySearchFacetHeader $facetField) 179 +#macro (displaySearchFacetHeader $facetField $expanded) 171 171 #set ($facetPrettyNameKey = "solr.field.$facetField.name") 172 172 #if ($services.localization.get($facetPrettyNameKey)) 173 173 #set ($facetPrettyName = $services.localization.render($facetPrettyNameKey)) ... ... @@ -182,17 +182,21 @@ 182 182 #set ($facetPrettyName = $facetField.name) 183 183 #end 184 184 <div class="search-facet-header"> 185 - <span id="$escapetool.xml($facetField.name)-toggler-hint">$escapetool.xml($facetPrettyName)</span> 186 - <button class="btn btn-xs facet-toggler" 187 - aria-controls="$escapetool.xml($facetField.name)-dropdown" 188 - aria-labelledby="$escapetool.xml($facetField.name)-toggler-hint"> 194 + <label>$escapetool.xml($facetPrettyName) 195 + <button class="btn btn-xs facet-toggle#if(!$expanded) collapsed#end" 196 + type="button" 197 + data-toggle="collapse" 198 + data-target="#$escapetool.xml($facetField.name)-dropdown" 199 + aria-expanded="$expanded" 200 + aria-controls="$escapetool.xml($facetField.name)-dropdown"> 189 189 $services.icon.renderHTML('caret-down') 190 190 </button> 203 + </label> 191 191 </div> 192 192 #end 193 193 194 -#macro (displaySearchFacetBody $facetField) 195 - <div id="$escapetool.xml($facetField.name)-dropdown" class="search-facet-body"> 207 +#macro (displaySearchFacetBody $facetField $expanded) 208 + <div id="$escapetool.xml($facetField.name)-dropdown" class="search-facet-body collapse#if($expanded) in#end"> 196 196 #set ($facetDisplayer = $solrConfig.facetDisplayers.get($facetField.name)) 197 197 #if (!$facetDisplayer && $facetField.name.startsWith('property.')) 198 198 ## Choose a facet displayer based on the property type. ... ... @@ -245,7 +245,7 @@ 245 245 #displaySearchFacetValue($facetValue $customQueryStringParameters $customValueDisplayer false) 246 246 #end 247 247 248 -#macro (displaySearchFacetValue $facetValue $customQueryStringParameters $customValueDisplayer $displayToggle r)261 +#macro (displaySearchFacetValue $facetValue $customQueryStringParameters $customValueDisplayer $displayToggle) 249 249 #set ($selectedValues = []) 250 250 #if ($facetRequestValues) 251 251 #set ($discard = $selectedValues.addAll($facetRequestValues.subList(0, $facetRequestValues.size()))) ... ... @@ -260,7 +260,8 @@ 260 260 #set ($discard = $queryStringParameters.putAll($customQueryStringParameters)) 261 261 #end 262 262 #extendQueryString($url $queryStringParameters) 263 - <a href="$url" class="itemName#if ($selected) selected#end#if ($facetValue.name == '') empty#end"> 276 + <a href="$url" class="itemName#if ($selected) selected#end#if ($facetValue.name == '') empty#end" 277 + #if ($facetValue.name != '')data-facetvalue="$escapetool.xml($facetValue.name)"#end> 264 264 #if ($facetValue.name == '') 265 265 #set ($facetPrettyValueKey = "solr.field.${facetField.name}.emptyValue") 266 266 #if (!$services.localization.get($facetPrettyValueKey)) ... ... @@ -277,8 +277,8 @@ 277 277 #end 278 278 </a> 279 279 <div class="itemCount">$facetValue.count</div> 280 - #if ($displayToggle r)281 - <button class="btn btn-xs facet-value-toggle r">294 + #if ($displayToggle) 295 + <button class="btn btn-xs facet-value-toggle"> 282 282 <span class='sr-only'>$escapetool.xml($facetPrettyValue)</span> 283 283 $services.icon.renderHTML('caret-down') 284 284 </button> ... ... @@ -305,7 +305,7 @@ 305 305 #end 306 306 #end 307 307 308 -#macro (displaySearchResults Sort)322 +#macro (_displaySearchResultsControls) 309 309 #set ($defaultSortOrder = $solrConfig.sortFields.get($type)) 310 310 #if (!$defaultSortOrder) 311 311 #set ($defaultSortOrder = {'score': 'desc'}) ... ... @@ -314,28 +314,63 @@ 314 314 'asc': $services.icon.render('caret-up'), 315 315 'desc': $services.icon.render('caret-down') 316 316 }) 317 - (% class="search-options" %) 318 - * {{translation key="solr.options"/}} 319 - #if($highlightEnabled)#extendQueryString($url {'highlight': [false]})#else#extendQueryString($url {'highlight': [true]})#end 320 - * [[{{translation key="solr.options.highlight"/}}>>path:${url}||class="options-item#if($highlightEnabled) active#end" title="$services.localization.render('solr.options.highlight.title')"]] 321 - #if($facetEnabled)#extendQueryString($url {'facet': [false]})#else#extendQueryString($url {'facet': [true]})#end 322 - * [[{{translation key="solr.options.facet"/}}>>path:${url}||class="options-item#if($facetEnabled) active#end" title="$services.localization.render('solr.options.facet.title')"]] 331 + (% class='search-results-controls' %) 332 + ((( 323 323 324 - (% class="search-results-sort" %) 325 - * {{translation key="solr.sortBy"/}} 326 - #foreach ($entry in $defaultSortOrder.entrySet()) 327 - #set ($class = 'sort-item') 328 - #set ($sortOrderIndicator = $NULL) 329 - #set ($targetSortOrder = $entry.value) 330 - #if ($sort == $entry.key) 331 - #set ($class = "$class active") 332 - #set ($sortOrderHint = $services.localization.render("solr.sortOrder.$sortOrder")) 333 - #set ($sortOrderIndicator = "(% class=""sort-item-order"" title=""$sortOrderHint"" %)$sortOrderSymbol.get($sortOrder)(%%)") 334 - #set ($targetSortOrder = "#if ($sortOrder == 'asc')desc#{else}asc#end") 335 - #end 336 - #extendQueryString($url {'sort': [$entry.key], 'sortOrder': [$targetSortOrder]}) 337 - * [[{{translation key="solr.sortBy.$entry.key"/}}$!sortOrderIndicator>>path:${url}||class="$class"]] 338 - #end 334 + {{html clean="false"}} 335 + <div class="search-results-sort"> 336 + <label for="sort-by-input" class="sr-only">$escapetool.xml($services.localization.render('search.solr.sortBy.hint'))</label>## 337 + <select id="sort-by-input" name="sort"> 338 + #foreach ($entry in $defaultSortOrder.entrySet()) 339 + <option class="sort-item" value="$entry.key" #if($sort == $entry.key)selected='selected'#end> 340 + #set ($sortOptionNameList = $entry.key.split('_')) 341 + #set ($camelCasedSortOptionName = $sortOptionNameList.get(0)) 342 + #foreach ($namePart in $sortOptionNameList.subList(1, $sortOptionNameList.size())) 343 + #set ($camelCasedSortOptionName = "${camelCasedSortOptionName}$stringtool.capitalize($namePart)") 344 + #end 345 + $escapetool.xml($services.localization.render("search.solr.sortBy.field.$camelCasedSortOptionName")) 346 + </option> 347 + #end 348 + </select>## 349 + <label class="form-control" title="$escapetool.xml($services.localization.render("search.solr.sortOrder.$sortOrder"))">## 350 + <input id="sort-order-input" type="checkbox" name="sortOrder" value="asc" #if ("$!sortOrder" == 'asc')checked="checked"#end/>## 351 + $services.icon.renderHTML('sort-descending')## 352 + $services.icon.renderHTML('sort-ascending')## 353 + <span class="sr-only">$escapetool.xml($services.localization.render("search.solr.sortOrder.$sortOrder"))</span>## 354 + </label>## 355 + </div> 356 + <div class="search-options"> 357 + <ul>## 358 + <li>## 359 + <label>## 360 + <input id="option-highlight-input" type="checkbox" class="options-item" value="true" 361 + data-query-name="highlight" 362 + aria-describedby="option-highlight-description" 363 + title="$escapetool.xml($services.localization.render('solr.options.highlight.title'))" 364 + #if($highlightEnabled)checked#end/>## 365 + $escapetool.xml($services.localization.render('search.solr.options.showHighlight'))## 366 + </label>## 367 + <span id="option-highlight-description" class="sr-only"> 368 + $escapetool.xml($services.localization.render('solr.options.highlight.title')) 369 + </span>## 370 + </li>## 371 + <li>## 372 + <label>## 373 + <input id="option-facet-input" type="checkbox" class="options-item" value="true" data-query-name="facet" 374 + aria-describedby="option-facet-description" 375 + title="$escapetool.xml($services.localization.render('solr.options.facet.title'))" 376 + #if($facetEnabled)checked#end/>## 377 + $escapetool.xml($services.localization.render('search.solr.options.showFacet')) 378 + </label>## 379 + <span id="option-facet-description" class="sr-only"> 380 + $escapetool.xml($services.localization.render('solr.options.facet.title')) 381 + </span>## 382 + </li>## 383 + </ul>## 384 + </div> 385 + {{/html}} 386 + 387 + ))) 339 339 #end 340 340 341 341 #macro (extendQueryString $url $extraParameters) ... ... @@ -380,7 +380,8 @@ 380 380 ## Add the parameters required to output the RSS feed instead of the search UI. 381 381 #set ($discard = $parameters.put('outputSyntax', 'plain')) 382 382 #set ($discard = $parameters.put('media', 'rss')) 383 - <a href="$doc.getURL('get', $escapetool.url($parameters))" class="hasIcon iconRSS"> 432 + <a href="$doc.getURL('get', $escapetool.url($parameters))"> 433 + $services.icon.renderHTML('rss') 384 384 $services.localization.render('search.rss', ["[$escapetool.xml($text)]"]) 385 385 </a> 386 386 {{/html}} ... ... @@ -412,7 +412,7 @@ 412 412 #displaySearchResultLocation() 413 413 <div class="search-result-author"> 414 414 $services.localization.render('core.footer.modification', [ 415 - "#displayUser ProfileLink($searchResult.author$searchResult.author_display)",465 + "#displayUser($searchResult.author {'useInlineHTML': true})", 416 416 $xwiki.formatDate($searchResult.date) 417 417 ]) 418 418 </div> ... ... @@ -434,7 +434,7 @@ 434 434 </h2> 435 435 #displaySearchResultLocation($searchResult) 436 436 <div class="search-result-uploader"> 437 - #set ($uploader = "#displayUser ProfileLink($searchResult.attauthor.get(0)$searchResult.attauthor_display.get(0))")487 + #set ($uploader = "#displayUser($searchResult.attauthor.get(0) {'useInlineHTML': true})") 438 438 #set ($uploadDate = $xwiki.formatDate($searchResult.attdate.get(0))) 439 439 #set ($fileSize = "#dynamicsize($searchResult.attsize.get(0))") 440 440 $services.localization.render('solr.result.uploadedBy', [$uploader, $uploadDate, $fileSize]) ... ... @@ -485,15 +485,6 @@ 485 485 </div> 486 486 #end 487 487 488 -#macro (displayUserProfileLink $userReference $userName) 489 -#if ($userReference) 490 -## We could test if the specified user exists but we want to speed up the search. 491 -<a href="$xwiki.getURL($userReference)">$escapetool.xml($userName)</a>## 492 -#else 493 -$services.localization.render('core.users.unknownUser')## 494 -#end 495 -#end 496 - 497 497 #macro (displaySearchResultHighlighting $searchResult) 498 498 #getSearchResultHighlighting($searchResult $highlighting) 499 499 #if ($highlighting.size() > 0) ... ... @@ -517,12 +517,10 @@ 517 517 #end 518 518 </dl> 519 519 #if ($highlighting.size() > 1) 520 - ## We wrap the link in a DIV because otherwise the HTML cleaning generates a paragraph. 521 - <div> 522 - <a href="#" class="search-result-highlightAll hidden"> 523 - $escapetool.xml($services.localization.render('solr.result.highlightAll')) 524 - </a> 525 - </div> 561 + <button class="search-result-highlightAll btn btn-xs btn-default hidden"> 562 + $escapetool.xml($services.localization.render('solr.result.highlightAll')) 563 + $services.icon.renderHTML('right') 564 + </button> 526 526 #end 527 527 #end 528 528 #end ... ... @@ -594,9 +594,10 @@ 594 594 ## Set query parameters. 595 595 #set ($discard = $query.setLimit($rows)) 596 596 #set ($discard = $query.setOffset($start)) 636 + #set ($discard = $query.addFilter('searchExclusions/solr')) 597 597 #set ($discard = $query.bindValue('sort', "${sort} ${sortOrder}")) 598 598 #set ($discard = $query.bindValue('tie', $solrConfig.tieBreaker)) 599 - #set ($discard = $query.bindValue('mm', $solrConfig.minShouldMatch)) 639 + #set ($discard = $query.bindValue('mm', $solrConfig.minShouldMatch)) 600 600 #setQueryFields($query) 601 601 #setPhraseFields($query) 602 602 #setFacetFields($query) ... ... @@ -798,10 +798,7 @@ 798 798 #end 799 799 ## 800 800 ## Pagination 801 - #set ($rows = $numbertool.toNumber($request.rows).intValue()) 802 - #if ("$!rows" == '') 803 - #set ($rows = 10) 804 - #end 841 + #getAndValidateQueryLimitFromRequest('rows', 10, $rows) 805 805 #set ($start = $numbertool.toNumber($request.firstIndex).intValue()) 806 806 #if ("$!start" == '') 807 807 #set ($start = 0) ... ... @@ -812,6 +812,8 @@ 812 812 #if ("$!sort" == '') 813 813 #set ($sort = 'score') 814 814 #end 852 + ## If at any point this default behavior is changed, be extra careful with "#sort-order-input" initialization. 853 + ## We assume here that empty values are mapped to "desc" (meaning that we use "asc" as the checkbox value). 815 815 #set ($sortOrder = $request.sortOrder) 816 816 #if ("$!sortOrder" == '') 817 817 #set ($sortOrder = 'desc') ... ... @@ -853,12 +853,15 @@ 853 853 {{/html}} 854 854 855 855 #end 856 - #displaySearchForm() 895 + #_displaySearchFormBegin() 857 857 #if ($text != '') 858 858 #getSearchResults() 898 + #_displaySearchResultsControls() 899 + #_displaySearchFormEnd() 859 859 #if ($debug) 860 860 #displaySearchDebugInfo() 861 861 #end 903 + 862 862 (% class="search-results-container row" %)((( 863 863 #if ($facetEnabled) 864 864 (% class="col-xs-12 col-sm-4 col-sm-push-8 col-md-3 col-md-push-9" %)((( ... ... @@ -867,11 +867,11 @@ 867 867 #end 868 868 (% class="search-results-left col-xs-12#if ($facetEnabled) col-sm-8 col-sm-pull-4 col-md-9 col-md-pull-3#end" %) 869 869 ((( 870 - #displaySearchResultsSort() 871 - 872 872 #displaySearchResults() 873 873 ))) 874 874 ))) 915 + #else 916 + #_displaySearchFormEnd() 875 875 #end 876 876 ))) 877 877 #set($void = $services.progress.popLevel())