Bugfix
This commit is contained in:
@@ -0,0 +1,24 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace MummertMedia\ContaoMeilisearchBundle\Controller\FrontendModule;
|
||||||
|
|
||||||
|
use Contao\FrontendModule;
|
||||||
|
|
||||||
|
class MeilisearchSearchController extends FrontendModule
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Template
|
||||||
|
*/
|
||||||
|
protected $strTemplate = 'mod_meilisearch_search';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compile the frontend module
|
||||||
|
*/
|
||||||
|
protected function compile(): void
|
||||||
|
{
|
||||||
|
// Fallback, falls das Feld leer ist
|
||||||
|
$limit = (int) ($this->meiliLimit ?: 50);
|
||||||
|
|
||||||
|
$this->Template->meiliLimit = $limit;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -17,3 +17,5 @@ $GLOBALS['TL_HOOKS']['indexPage'][] = [
|
|||||||
'onIndexPage',
|
'onIndexPage',
|
||||||
];
|
];
|
||||||
|
|
||||||
|
$GLOBALS['FE_MOD']['search']['meilisearch_search']
|
||||||
|
= MummertMedia\ContaoMeilisearchBundle\Controller\FrontendModule\MeilisearchSearchController::class;
|
||||||
|
|||||||
@@ -0,0 +1,19 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
$GLOBALS['TL_DCA']['tl_module']['palettes']['meilisearch_search'] =
|
||||||
|
'{title_legend},name,type;
|
||||||
|
{search_legend},meiliLimit;
|
||||||
|
{protected_legend:hide},protected;
|
||||||
|
{expert_legend:hide},cssID';
|
||||||
|
|
||||||
|
$GLOBALS['TL_DCA']['tl_module']['fields']['meiliLimit'] = [
|
||||||
|
'label' => &$GLOBALS['TL_LANG']['tl_module']['meiliLimit'],
|
||||||
|
'inputType' => 'text',
|
||||||
|
'default' => 50,
|
||||||
|
'eval' => [
|
||||||
|
'rgxp' => 'digit',
|
||||||
|
'mandatory' => true,
|
||||||
|
'tl_class' => 'w50',
|
||||||
|
],
|
||||||
|
'sql' => "int(10) unsigned NOT NULL default 50",
|
||||||
|
];
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
|
||||||
|
$GLOBALS['TL_LANG']['FMD']['meilisearch_search'] = [
|
||||||
|
'Meilisearch-Suche',
|
||||||
|
'Suchfeld mit Meilisearch-Anbindung.'
|
||||||
|
];
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
|
||||||
|
$GLOBALS['TL_LANG']['tl_module']['meiliLimit'] = [
|
||||||
|
'Treffer-Limit',
|
||||||
|
'Maximale Anzahl der Suchergebnisse, die Meilisearch zurückliefert.'
|
||||||
|
];
|
||||||
@@ -0,0 +1,140 @@
|
|||||||
|
{#
|
||||||
|
Meilisearch Frontend Search
|
||||||
|
Default Twig template
|
||||||
|
#}
|
||||||
|
|
||||||
|
<div
|
||||||
|
class="meilisearch-search"
|
||||||
|
data-limit="{{ meiliLimit }}"
|
||||||
|
>
|
||||||
|
<div class="meilisearch-search-field">
|
||||||
|
<input
|
||||||
|
type="search"
|
||||||
|
id="meilisearch-input"
|
||||||
|
placeholder="Suche …"
|
||||||
|
autocomplete="off"
|
||||||
|
>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
class="meilisearch-clear"
|
||||||
|
aria-label="Suche löschen"
|
||||||
|
hidden
|
||||||
|
>
|
||||||
|
×
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="meilisearch-results" class="meilisearch-results"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script type="module">
|
||||||
|
import MeiliSearch from 'https://cdn.jsdelivr.net/npm/meilisearch@latest/dist/bundles/meilisearch.esm.js';
|
||||||
|
|
||||||
|
document.addEventListener('DOMContentLoaded', () => {
|
||||||
|
|
||||||
|
const wrapper = document.querySelector('.meilisearch-search');
|
||||||
|
if (!wrapper) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const input = wrapper.querySelector('#meilisearch-input');
|
||||||
|
const clear = wrapper.querySelector('.meilisearch-clear');
|
||||||
|
const results = wrapper.querySelector('#meilisearch-results');
|
||||||
|
|
||||||
|
const limit = parseInt(wrapper.dataset.limit, 10) || 50;
|
||||||
|
|
||||||
|
const client = new MeiliSearch({
|
||||||
|
host: '{{ config("meilisearch_host") }}',
|
||||||
|
apiKey: '{{ config("meilisearch_api_search") }}'
|
||||||
|
});
|
||||||
|
|
||||||
|
const index = client.index('{{ config("meilisearch_index") }}');
|
||||||
|
|
||||||
|
let abortController = null;
|
||||||
|
|
||||||
|
clear.addEventListener('click', () => {
|
||||||
|
input.value = '';
|
||||||
|
results.innerHTML = '';
|
||||||
|
clear.hidden = true;
|
||||||
|
input.focus();
|
||||||
|
});
|
||||||
|
|
||||||
|
input.addEventListener('input', async () => {
|
||||||
|
|
||||||
|
const query = input.value.trim();
|
||||||
|
clear.hidden = query.length === 0;
|
||||||
|
|
||||||
|
if (query.length < 2) {
|
||||||
|
results.innerHTML = '';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
abortController?.abort();
|
||||||
|
abortController = new AbortController();
|
||||||
|
|
||||||
|
try {
|
||||||
|
const response = await index.search(query, {
|
||||||
|
limit: limit,
|
||||||
|
attributesToRetrieve: [
|
||||||
|
'title',
|
||||||
|
'url',
|
||||||
|
'text',
|
||||||
|
'poster',
|
||||||
|
'type'
|
||||||
|
],
|
||||||
|
attributesToHighlight: ['text'],
|
||||||
|
highlightPreTag: '<mark>',
|
||||||
|
highlightPostTag: '</mark>'
|
||||||
|
});
|
||||||
|
|
||||||
|
renderResults(response.hits);
|
||||||
|
|
||||||
|
} catch (e) {
|
||||||
|
if (e.name !== 'AbortError') {
|
||||||
|
console.error('Meilisearch error:', e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
function renderResults(hits) {
|
||||||
|
|
||||||
|
results.innerHTML = '';
|
||||||
|
|
||||||
|
if (!hits.length) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const hit of hits) {
|
||||||
|
|
||||||
|
const article = document.createElement('article');
|
||||||
|
article.className = 'meilisearch-result type-' + (hit.type || 'unknown');
|
||||||
|
|
||||||
|
const link = document.createElement('a');
|
||||||
|
link.href = hit.url || '#';
|
||||||
|
link.className = 'meilisearch-link';
|
||||||
|
|
||||||
|
if (hit.poster) {
|
||||||
|
const img = document.createElement('img');
|
||||||
|
img.src = hit.poster;
|
||||||
|
img.alt = '';
|
||||||
|
img.loading = 'lazy';
|
||||||
|
link.appendChild(img);
|
||||||
|
}
|
||||||
|
|
||||||
|
const title = document.createElement('h3');
|
||||||
|
title.textContent = hit.title || '';
|
||||||
|
link.appendChild(title);
|
||||||
|
|
||||||
|
if (hit._formatted?.text) {
|
||||||
|
const extract = document.createElement('p');
|
||||||
|
extract.className = 'meilisearch-extract';
|
||||||
|
extract.innerHTML = hit._formatted.text;
|
||||||
|
link.appendChild(extract);
|
||||||
|
}
|
||||||
|
|
||||||
|
article.appendChild(link);
|
||||||
|
results.appendChild(article);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
Reference in New Issue
Block a user