nicokaiser / hugo-theme-gallery

Gallery Theme for Hugo
https://nicokaiser.github.io/hugo-theme-gallery/
MIT License
371 stars 115 forks source link

Feature Request: Search Function #73

Closed eskopp closed 4 months ago

eskopp commented 4 months ago

Hello,

Firstly, I would like to express my appreciation for this Hugo Photo Gallery template. It has been incredibly helpful and well-designed.

I am writing to request the implementation of a search functionality similar to the one available on https://kaiser.gallery/. This feature would significantly enhance the user experience by allowing users to quickly find specific photos within the gallery.

Feature Request Details:

  1. Search Bar Integration:

    • A search bar should be added to the gallery interface, ideally positioned in a prominent and accessible location (e.g., at the top of the page).
  2. Search Functionality:

    • The search feature should allow users to search for photos based on keywords, tags, or descriptions associated with the images.
    • The search results should be displayed dynamically, updating as the user types (live search functionality).
  3. Implementation of Indexing:

    • Efficient indexing of the gallery content to ensure quick and accurate search results.
  4. Filtering Options:

    • Option to filter search results based on predefined categories (e.g., date, album, tags).
  5. Responsive Design:

    • Ensure that the search functionality is fully responsive and works seamlessly across different devices and screen sizes.

Benefits:

Thank you for considering this feature request. I believe that adding a search functionality similar to https://kaiser.gallery/ would be a valuable enhancement to the Hugo Photo Gallery template.

Best regards,

@eskopp

nicokaiser commented 4 months ago

Thanks for the suggestion!

While I am using the HugoMods Search module on https://kaiser.gallery I cannot reliably maintain a theme integration for this module (search functionality should be beyond the scope of the theme, which should stay as light-weight as possible).

Here is how I integrated it into the site:

Import the module on your site, e.g. in your hugo.toml:

…
[module]
  [[module.imports]]
    path = "github.com/nicokaiser/hugo-theme-gallery/v4"
  [[module.imports]]
    path = 'github.com/hugomods/search'
…
[params]
…
  [params.search]
    filter_taxonomies = false
    filter_years = false
    ignore_location = true
    index_all_pages = false
    max_results = 20
    threshold = 0.3
    expand_results_meta = true
    histories = false
…

assets/css/search.css

search.css.txt

(This is a very customized version of the original HugoMods CSS. You can/should adjust this to you liking, in my case I remove as much clutter as possible to keep the search simple and clean)

layouts/_default/index.searchindex.json

This file generates the search index. Since we are indexing albums (not individual photos), this can be a static file with all (!) public albums of the site.

{{- $items := slice -}}
{{- $pages := .Site.RegularPages -}}
{{- $pages = where $pages "Params.noindex" "ne" true -}}
{{- $pages = where $pages "Params.private" "ne" true -}}
{{- $pages = where $pages "Layout" "eq" "" -}}
{{- range $pages -}}
  {{- $item := newScratch -}}
  {{- $item.Set "title" .Title -}}
  {{- $item.Set "summary" (default .Summary .Description | plainify | htmlUnescape) -}}
  {{- $item.Set "kind" .Kind -}}
  {{- $item.Set "lang" .Language.Lang -}}
  {{- $item.Set "url" .RelPermalink -}}
  {{- $item.Set "date" .Date.Unix -}}
  {{- $items = $items | append $item.Values -}}
{{- end -}}
{{- $items | jsonify -}}

layouts/partials/head-custom.html

This adds the CSS and JS of the Search module.

{{/* Search */}}
{{ $searchCSS := resources.Get "css/search.css" | minify | fingerprint }}
<link rel="stylesheet" href="{{ $searchCSS.RelPermalink }}" />
{{ $searchJS := partial "search/assets/js-resource" . | js.Build (dict "minify" true) | resources.Fingerprint }}
<script src="{{ $searchJS.RelPermalink }}" defer></script>

layouts/partials/header.html

This replaces the original header.html of the theme and basically adds a <li> element with the search button.

<header>
  {{ with .Parent }}
    <a class="btn btn-square" href="{{ .RelPermalink | default .Site.Home.RelPermalink }}" title="{{ .Title }}">
      <svg width="24" height="24" data-slot="icon" fill="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" aria-hidden="true">
        <path clip-rule="evenodd" fill-rule="evenodd" d="M11.03 3.97a.75.75 0 0 1 0 1.06l-6.22 6.22H21a.75.75 0 0 1 0 1.5H4.81l6.22 6.22a.75.75 0 1 1-1.06 1.06l-7.5-7.5a.75.75 0 0 1 0-1.06l7.5-7.5a.75.75 0 0 1 1.06 0Z"></path>
      </svg>
    </a>
  {{ else }}
    <a class="btn" href="{{ .Site.Home.RelPermalink }}">
      {{ .Site.Title }}
    </a>
  {{ end }}
  <ul>
    <li>
      <button class="search-modal-toggle btn btn-square" type="button" title="Search">
        <svg width="24" height="24" data-slot="icon" fill="none" stroke-width="1.5" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" aria-hidden="true">
          <path stroke-linecap="round" stroke-linejoin="round" d="m21 21-5.197-5.197m0 0A7.5 7.5 0 1 0 5.196 5.196a7.5 7.5 0 0 0 10.607 10.607Z"></path>
        </svg>
      </button>
    </li>
    <li>
      <button class="btn btn-square group" id="menu-toggle" aria-expanded="false" type="button" title="{{ T "menu" }}">
        <svg class="group-aria-expanded:hidden" width="24" height="24" fill="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" aria-hidden="true">
          <path clip-rule="evenodd" fill-rule="evenodd" d="M3 6.75A.75.75 0 0 1 3.75 6h16.5a.75.75 0 0 1 0 1.5H3.75A.75.75 0 0 1 3 6.75ZM3 12a.75.75 0 0 1 .75-.75h16.5a.75.75 0 0 1 0 1.5H3.75A.75.75 0 0 1 3 12Zm0 5.25a.75.75 0 0 1 .75-.75h16.5a.75.75 0 0 1 0 1.5H3.75a.75.75 0 0 1-.75-.75Z"></path>
        </svg>
        <svg class="hidden group-aria-expanded:block" width="24" height="24" fill="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" aria-hidden="true">
          <path clip-rule="evenodd" fill-rule="evenodd" d="M5.47 5.47a.75.75 0 0 1 1.06 0L12 10.94l5.47-5.47a.75.75 0 1 1 1.06 1.06L13.06 12l5.47 5.47a.75.75 0 1 1-1.06 1.06L12 13.06l-5.47 5.47a.75.75 0 0 1-1.06-1.06L10.94 12 5.47 6.53a.75.75 0 0 1 0-1.06Z"></path>
        </svg>
      </button>
    </li>
  </ul>
</header>
{{ partial "menu.html" . }}

Please let me know if this works for you.

eskopp commented 4 months ago

So the html and css seems to work. The only thing that doesn't quite work at the moment is the index. I can enter something, but there is no output.

nicokaiser commented 4 months ago

There seems to be no search index. Could you try to add the following to your hugo.toml:

[outputs]
  home = ["HTML", "RSS", "SearchIndex"]
  page = ["HTML"]
  section = ["HTML"]

This should generate a https://photos.erik-skopp.de/search.json with all the information in it. However I wonder why the Search module does not try to find this file in your configuration...

eskopp commented 4 months ago

Thank you @nicokaiser . You have helped me a lot. From my side, we can close the issue. However, I think that there may be others who will find your instructions helpful. Everything works for me now.