Created
January 24, 2024 08:40
-
-
Save zopyx/9897d692571caccba60e49480fc36461 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* global instantsearch */ | |
/* global vars first */ | |
var remote_url = CONTEXT_URL + "/@@typesense-search-settings"; | |
var ts_settings = null; | |
/* Show initially all hits with all form control (true) | |
* or show only empty search field by default (false). | |
*/ | |
var SHOW_ALL_HITS_INITIALLY = true; | |
const TRANSLATIONS = { | |
"10-per-page": { | |
de: "10 je Seite", | |
en: "10 per page", | |
}, | |
"20-per-page": { | |
de: "20 je Seite", | |
en: "20 per page", | |
}, | |
"50-per-page": { | |
de: "50 je Seite", | |
en: "50 per page", | |
}, | |
"100-per-page": { | |
de: "100 je Seite", | |
en: "100 per page", | |
}, | |
"250-per-page": { | |
de: "250 je Seite", | |
en: "250 per page", | |
}, | |
"placeholder-search-by-topic": { | |
de: "Suche nach Themengebiet", | |
en: "Search by topic", | |
}, | |
"placeholder-search-by": { | |
de: "Suchbegriff(e) eingeben...", | |
en: "Search by", | |
}, | |
hits: { | |
de: "Treffer", | |
en: "hits", | |
}, | |
hit: { | |
de: "Treffer", | |
en: "hit", | |
}, | |
"no-hits": { | |
de: "Keine Treffer", | |
en: "No hits", | |
}, | |
"one-hit": { | |
de: "ein Treffer", | |
en: "one hit", | |
}, | |
"show-more": { | |
de: "Alle Themengebiete", | |
en: "Show more", | |
}, | |
"chapter-wise": { | |
de: "kapitelweise", | |
en: "chapter-wise", | |
}, | |
"reset-filters": { | |
de: "Alle Filter zurücksetzen", | |
en: "Reset all filters", | |
}, | |
"no-filters-set": { | |
de: "Keine Filter gesetzt", | |
en: "No filters set", | |
}, | |
chapter: { | |
de: "Kapitel", | |
en: "Chapter", | |
}, | |
"document-locked": { | |
de: "Zugriff nur für angemeldete Mitglieder unserer medizinischen Fachgesellschaften", | |
en: "Access only for logged-in members of our medical societies", | |
}, | |
area: { | |
de: "Bereich", | |
en: "Section", | |
}, | |
language: { | |
de: "Sprache", | |
en: "Language", | |
}, | |
"filtered-by": { | |
de: "Gefiltert nach", | |
en: "Filtered by", | |
}, | |
ayapedia: { | |
de: "AYApedia", | |
en: "AYApediaby", | |
}, | |
"onkopedia-p": { | |
de: "Onkopedia Pflege", | |
}, | |
onkopedia: { | |
de: "Onkopedia", | |
en: "Onkopedia", | |
}, | |
"drug-assessment": { | |
de: "Arzneimittel", | |
}, | |
"knowledge-database": { | |
de: "Wissensdatenbank", | |
}, | |
"reset-search": { | |
de: "Eingabe löschen", | |
en: "Clear input", | |
}, | |
de: { | |
de: "Deutsch", | |
en: "German", | |
}, | |
en: { | |
de: "Englisch", | |
en: "English", | |
}, | |
"area-label": { | |
de: "Bereich", | |
en: "Area", | |
}, | |
"no-topics": { | |
de: "Keine passenden Themengebiete", | |
en: "No matching topics", | |
}, | |
date: { | |
de: "Stand", | |
en: "Date", | |
}, | |
}; | |
/* translate */ | |
function tr(msg_id) { | |
var arr = TRANSLATIONS[msg_id]; | |
if (arr == undefined) { | |
console.log("Unknown msg_id " + msg_id); | |
return msg_id; | |
} | |
translation = TRANSLATIONS[msg_id][LANGUAGE]; | |
if (translation == undefined) { | |
console.log("Unknown msg_id " + msg_id + "/" + LANGUAGE); | |
return msg_id; | |
} | |
return translation; | |
} | |
DOCUMENT_TYPE_ORDERING = [ | |
"Leitlinie", | |
"Guideline", | |
"Algorithmus", | |
"Algorithm", | |
"Studienergebnisse", | |
"Protokolle", | |
"Wechselwirkungen und Nebenwirkungen", | |
"Frühe Nutzenbewertung", | |
"Fact Sheet", | |
"Zulassungen", | |
"AYApedia", | |
"Ayapedia", | |
"Datei/PDF", | |
"File/PDF", | |
"Dokument", | |
"Document", | |
"Nachricht", | |
"Anderer Inhalt", | |
]; | |
AREA_ORDERING = [ | |
"Onkopedia", | |
"Arzneimittel", | |
"Ayapedia", | |
"Pflege", | |
"Wissensdatenbank", | |
"Allgemein", | |
]; | |
instantsearch.widgets.configure({ | |
facetFilters: ['document_type:guideline'] | |
}); | |
function sort_document_type(d1, d2) { | |
var idx1 = DOCUMENT_TYPE_ORDERING.indexOf(d1.name); | |
var idx2 = DOCUMENT_TYPE_ORDERING.indexOf(d2.name); | |
return idx1 === idx2 ? 0 : (idx1> idx2? 1 : -1); | |
} | |
function sort_topic(t1, t2) { | |
return t1.name.localeCompare(t2.name, "de"); | |
} | |
function sort_area(d1, d2) { | |
var idx1 = AREA_ORDERING.indexOf(d1.name); | |
var idx2 = AREA_ORDERING.indexOf(d2.name); | |
return idx1 === idx2 ? 0 : (idx1> idx2? 1 : -1); | |
} | |
/* Retrieve search settings through JSON */ | |
function getSearchSettings() { | |
return $.getJSON({ | |
type: "GET", | |
url: remote_url, | |
async: false, | |
}).responseText; | |
} | |
/* get settings form backend */ | |
ts_settings = JSON.parse(getSearchSettings()); | |
var is_anonymous = ts_settings.is_anonymous; | |
let area = ts_settings["area"]; | |
let language = ts_settings["language"]; | |
/* Query parameters from URL */ | |
const urlSearchParams = new URLSearchParams(window.location.search); | |
const params = Object.fromEntries(urlSearchParams.entries()); | |
// global language for UI | |
let LANGUAGE = language; | |
const typesenseInstantsearchAdapter = new TypesenseInstantSearchAdapter({ | |
server: { | |
apiKey: ts_settings["api_key"], | |
nodes: ts_settings["nodes"], | |
}, | |
// The following parameters are directly passed to Typesense's search API | |
// endpoint. So you can pass any parameters supported by the search | |
// endpoint below. queryBy is required. filterBy is managed and | |
// overridden by InstantSearch.js. To set it, you want to use one of the | |
// filter widgets like refinementList or use the `configure` widget. | |
additionalSearchParameters: { | |
query_by: ts_settings["query_by"], | |
query_by_weights: ts_settings["query_by_weights"], | |
sort_by: "sort_key:desc,_text_match:desc,date_sort_key:desc", | |
enable_highlight_v1: false, | |
highlight_full_fields: "none", | |
// exclude_fields: "text", | |
use_cache: true, | |
cache_ttl: 120, | |
}, | |
transformRequest: (request) => { | |
return request; | |
}, | |
}); | |
const searchClient = typesenseInstantsearchAdapter.searchClient; | |
const search = instantsearch({ | |
searchClient, | |
indexName: ts_settings["collection"], | |
searchFunction(helper) { | |
if (helper.state.query.length == 0) { | |
$("#search-control").hide(); | |
$("#hits").hide(); | |
$(".search-panel__filters").hide(); | |
} else { | |
$("#search-control").show(); | |
$("#hits").show(); | |
$(".search-panel__filters").show(); | |
} | |
helper.search(); | |
}, | |
}); | |
function renderHit(hit, highlight) { | |
var hl_result = hit._highlightResult; | |
var title = hl_result.title.value; | |
var subtitle = hit.subtitle; | |
var topic = ""; | |
if (hit.topic_de.length > 0) topic += hit.topic_de; | |
if (hit.specification_de && hit.specification_de.length >= 0) | |
topic += " → " + hit.specification_de; | |
if (hit.specification2_de && hit.specification2_de.length >= 0) | |
topic += " → " + hit.specification2_de; | |
/* Hide Plone content having "no-topic" as topic set */ | |
if (topic == "no-topic") topic = ""; | |
var figure_title = ""; | |
if (hit.document_type == "algorithm") | |
figure_title = `<div class="hit-figure-title">${hit.figure_title}</div>`; | |
var svg_markup = ""; | |
if (hit.svg_url) { | |
svg_markup = `<figure class="hit-figure"><object data="${hit.svg_url}" class="hit-svg" type="image/svg+xml"></object></figure>`; | |
} | |
if ( | |
hit.document_fragment == "yes" && | |
!["File", "News Item", "Document"].includes(hit.document_type) | |
) { | |
chapter_str = tr("chapter"); | |
subtitle = `<div class="subtitle"> ➡ ${chapter_str} ${hit.section_number} ${hit._highlightResult.section_title.value}</div>`; | |
} | |
/* | |
text = `<div class="text-highlights">${hit._highlightResult.text.value}</div>`; | |
*/ | |
text2 = ""; | |
if (hit._snippetResult.text.matchedWords.length > 0) { | |
text2 = `<div class="text-snippets">${hit._snippetResult.text.value}</div>`; | |
} | |
anchor = ""; | |
if (hit.anchor.length > 0) anchor = `#${hit.anchor}`; | |
locked = ""; | |
locked_text = ""; | |
if (is_anonymous && hit.public == false) { | |
locked = `<span class="hit-locked">🔒</span>`; | |
document_locked = tr("document-locked"); | |
locked_text = `<div class="locked-text">${document_locked}</div>`; | |
} | |
date_str = ""; | |
if (hit.date_str.indexOf("/") != -1) { | |
date_str = `(${tr("date")} ${hit.date_str})`; | |
} | |
hit_document_type = | |
LANGUAGE == "de" ? hit.document_type_de : hit.document_type_en; | |
hit_area = LANGUAGE == "de" ? hit.area_de : hit.area_en; | |
var area_label = tr("area-label"); | |
return ` | |
<div class="hit"> | |
<div class="hit-title">${locked} <a target="_blank" class="hit-link" href="${hit.url}${anchor}">${title} ${date_str}</a></div> | |
<div class="hit-subtitle"> ${subtitle} </div> | |
<div class="hit-topic">${topic}</div> | |
${figure_title} | |
${svg_markup} | |
${locked_text} | |
${text2} | |
<div class="hit-meta"> | |
<span class="hit-portal_type">${hit_document_type}</span> | | |
<span class="hit-area">${area_label}: ${hit_area}</span> | | |
<span class="hit-date">${hit.date_str}</span> | | |
<span class="hit-date">${hit.language} </span> | |
<span class="hit-date" hidden>Public=${hit.public} | </span> | |
<span class="hit-date" hidden>SortKey=${hit.sort_key}</span> | |
| Score: ${hit.text_match_info.score} | |
| Fragment: ${hit.document_fragment} | |
</div> | |
</div>`; | |
} | |
function renderStats(stats) { | |
var num_hits = stats.nbHits.toLocaleString("de-DE"); | |
// if (stats.hasNoResults) return tr("no-hits"); | |
if (stats.hasOneResults) return tr("one-hit"); | |
if (stats.hasManyResults) { | |
var str_hits = tr("hits"); | |
return `${num_hits} ${str_hits}`; | |
} | |
} | |
function transform_topic_items(items) { | |
// Filter out items where the label is 'no-topic' | |
return items.filter((item) => item.label !== "no-topic"); | |
} | |
search.addWidgets([ | |
instantsearch.widgets.searchBox({ | |
container: "#searchbox", | |
showSubmit: false, | |
showReset: true, | |
placeholder: tr("placeholder-search-by"), | |
autofocus: false, | |
searchAsYouType: true, | |
showLoadingIndicator: true, | |
cssClasses: { | |
input: "form-control form-control-sm border border-light text-dark", | |
loadingIcon: "stroke-primary", | |
}, | |
templates: { | |
reset: tr("reset-search"), | |
}, | |
}), | |
instantsearch.widgets.configure({ | |
hitsPerPage: 20, | |
}), | |
instantsearch.widgets.hits({ | |
container: "#hits", | |
templates: { | |
item: renderHit, | |
empty: tr("no-hits"), | |
}, | |
}), | |
instantsearch.widgets.currentRefinements({ | |
container: "#current-refinements", | |
excludedAttributes: ["document_fragment", "query", "area", "language"], | |
}), | |
instantsearch.widgets.clearRefinements({ | |
container: "#clear-refinements", | |
excludedAttributes: ["query", "area", "language"], | |
templates: { | |
resetLabel(hasRefinements) { | |
if (hasRefinements.hasRefinements) return tr("reset-filters"); | |
else return tr("no-filters-set"); | |
}, | |
}, | |
}), | |
instantsearch.widgets.pagination({ | |
container: "#pagination", | |
root: "nav", | |
cssClasses: { | |
root: "navigation", | |
list: "pagination ", | |
item: "page-item ", | |
link: "text-decoration-none", | |
disabledItem: "text-muted", | |
selectedItem: "fw-bold text-primary", | |
}, | |
}), | |
instantsearch.widgets.refinementList({ | |
container: "#document-type", | |
attribute: `document_type_${LANGUAGE.toLowerCase()}`, | |
sortBy: sort_document_type, | |
limit: 20, | |
}), | |
instantsearch.widgets.toggleRefinement({ | |
container: "#document-fragment", | |
attribute: "document_fragment", | |
on: "yes", | |
off: "no", | |
templates: { | |
labelText(count) { | |
return tr("chapter-wise"); | |
}, | |
}, | |
}), | |
instantsearch.widgets.refinementList({ | |
container: "#topic", | |
attribute: `topic_${LANGUAGE.toLowerCase()}`, | |
searchable: true, | |
limit: 10, | |
showMore: true, | |
showMoreLimit: 150, | |
sortBy: sort_topic, | |
searchablePlaceholder: tr("placeholder-search-by-topic"), | |
transformItems: transform_topic_items, | |
templates: { | |
searchableNoResults(data) { | |
return tr("no-topics"); | |
}, | |
showMoreText(data) { | |
return tr("show-more"); | |
}, | |
noRefinementRoot() { | |
return "xxx"; | |
}, | |
noResults() { | |
return "xxx"; | |
}, | |
}, | |
}), | |
instantsearch.widgets.stats({ | |
container: "#stats", | |
templates: { | |
text: renderStats, | |
}, | |
cssClasses: { | |
text: "small", | |
}, | |
}), | |
instantsearch.widgets.hitsPerPage({ | |
container: "#hits-per-page", | |
items: [ | |
{ | |
label: tr("10-per-page"), | |
value: 10, | |
}, | |
{ | |
label: tr("20-per-page"), | |
value: 20, | |
default: true, | |
}, | |
{ | |
label: tr("50-per-page"), | |
value: 50, | |
}, | |
{ | |
label: tr("100-per-page"), | |
value: 100, | |
}, | |
{ | |
label: tr("250-per-page"), | |
value: 250, | |
}, | |
], | |
cssClasses: { | |
select: "custom-select custom-select-sm", | |
}, | |
}), | |
]); | |
/* If area is set, then use toggleRefinement instead of refinementList */ | |
if (area.length == 0) { | |
search.addWidgets([ | |
instantsearch.widgets.refinementList({ | |
container: "#area", | |
attribute: `area_${LANGUAGE.toLowerCase()}`, | |
sortBy: sort_area, | |
}), | |
]); | |
} else { | |
$("#area").hide() | |
$("#area-label").hide() | |
search.addWidgets([ | |
instantsearch.widgets.toggleRefinement({ | |
container: "#area", | |
attribute: "area", | |
off: `area-${area}`, | |
on: `area-${area}`, | |
}), | |
]); | |
} | |
/* If language is set, then use toggleRefinement instead of refinementList */ | |
if (language.length == 0) { | |
instantsearch.widgets.refinementList({ | |
container: "#language", | |
attribute: "language", | |
sortBy: ["name:asc"], | |
}) | |
} else { | |
$("#language").hide() | |
$("#language-label").hide() | |
search.addWidgets([ | |
instantsearch.widgets.toggleRefinement({ | |
container: "#language", | |
attribute: "language", | |
off: language, | |
on: language, | |
}), | |
]); | |
} | |
/* Hide refinements for knowledge database */ | |
if (area == "knowledge-database") { | |
$("#document-fragment").hide() | |
$("#document-fragment-label").hide() | |
$("#topic").hide() | |
$("#topic-label").hide() | |
} | |
search.start(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment