mirror of
https://github.com/Theodor-Springmann-Stiftung/musenalm.git
synced 2025-10-29 09:15:33 +00:00
Abschluss einfache Inhaltsuche
This commit is contained in:
@@ -67,6 +67,39 @@ func (p *BeitraegeFilterParameters) FieldSetBeitraege() []dbmodels.FTS5QueryRequ
|
|||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p BeitraegeFilterParameters) ToQueryParams() string {
|
||||||
|
r := ""
|
||||||
|
if p.Agent != "" {
|
||||||
|
r += "&" + FILTER_PARAM_BEIAEGE_AGENT + "=" + p.Agent
|
||||||
|
}
|
||||||
|
if p.Type != "" {
|
||||||
|
r += "&" + FILTER_PARAM_BEIAEGE_TYPE + "=" + p.Type
|
||||||
|
}
|
||||||
|
if p.Year != "" {
|
||||||
|
r += "&" + FILTER_PARAM_BEIAEGE_YEAR + "=" + p.Year
|
||||||
|
}
|
||||||
|
if p.OnlyScans {
|
||||||
|
r += "&" + FILTER_PARAM_BEIAEGE_ONLYSCANS + "=on"
|
||||||
|
}
|
||||||
|
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p BeitraegeFilterParameters) ToQueryParamsWOScans() string {
|
||||||
|
r := ""
|
||||||
|
if p.Agent != "" {
|
||||||
|
r += "&" + FILTER_PARAM_BEIAEGE_AGENT + "=" + p.Agent
|
||||||
|
}
|
||||||
|
if p.Type != "" {
|
||||||
|
r += "&" + FILTER_PARAM_BEIAEGE_TYPE + "=" + p.Type
|
||||||
|
}
|
||||||
|
if p.Year != "" {
|
||||||
|
r += "&" + FILTER_PARAM_BEIAEGE_YEAR + "=" + p.Year
|
||||||
|
}
|
||||||
|
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
|
||||||
type SearchResultBeitraege struct {
|
type SearchResultBeitraege struct {
|
||||||
Queries []dbmodels.FTS5QueryRequest
|
Queries []dbmodels.FTS5QueryRequest
|
||||||
|
|
||||||
|
|||||||
@@ -21,14 +21,12 @@
|
|||||||
{{ end }}
|
{{ end }}
|
||||||
|
|
||||||
|
|
||||||
<script type="module" src="/assets/scripts.js"></script>
|
|
||||||
|
|
||||||
<script src="/assets/js/alpine.min.js" defer></script>
|
<script src="/assets/js/alpine.min.js" defer></script>
|
||||||
<script src="/assets/js/htmx.min.js" defer></script>
|
<script src="/assets/js/htmx.min.js" defer></script>
|
||||||
<script src="/assets/js/htmx-response-targets.js" defer></script>
|
<script src="/assets/js/htmx-response-targets.js" defer></script>
|
||||||
<script src="/assets/js/client-side-templates.js" defer></script>
|
|
||||||
<script src="/assets/js/mark.min.js" defer></script>
|
<script src="/assets/js/mark.min.js" defer></script>
|
||||||
|
|
||||||
|
<script type="module" src="/assets/scripts.js"></script>
|
||||||
<link href="/assets/css/remixicon.css" rel="stylesheet" />
|
<link href="/assets/css/remixicon.css" rel="stylesheet" />
|
||||||
<link rel="stylesheet" type="text/css" href="/assets/css/fonts.css" />
|
<link rel="stylesheet" type="text/css" href="/assets/css/fonts.css" />
|
||||||
<link rel="stylesheet" type="text/css" href="/assets/style.css" />
|
<link rel="stylesheet" type="text/css" href="/assets/style.css" />
|
||||||
|
|||||||
@@ -140,14 +140,15 @@
|
|||||||
|
|
||||||
{{- template "_fieldscript" -}}
|
{{- template "_fieldscript" -}}
|
||||||
{{- if $model.parameters.IsBeitraegeSearch -}}
|
{{- if $model.parameters.IsBeitraegeSearch -}}
|
||||||
<div class="cotents" id="searchresult">
|
<div class="cotents" id="searchresults">
|
||||||
{{- if $model.result.Hits -}}
|
{{- if $model.result.Hits -}}
|
||||||
{{ template "_filterlist" $model }}
|
{{ template "_filterlist" $model }}
|
||||||
{{- end -}}
|
{{- end -}}
|
||||||
|
|
||||||
|
|
||||||
<div class="container-normal">
|
<div class="container-normal" id="subresults">
|
||||||
{{ template "tablehead" $model }}
|
{{ template "tablehead" $model }}
|
||||||
|
{{ template "pills" $model }}
|
||||||
{{- if $model.result.Hits -}}
|
{{- if $model.result.Hits -}}
|
||||||
<div class="mt-8" id="almanachcontents">
|
<div class="mt-8" id="almanachcontents">
|
||||||
{{- range $_, $hit := $model.result.Hits -}}
|
{{- range $_, $hit := $model.result.Hits -}}
|
||||||
|
|||||||
38
views/routes/suche/beitraege/pills.gohtml
Normal file
38
views/routes/suche/beitraege/pills.gohtml
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
{{ $model := . }}
|
||||||
|
|
||||||
|
{{- $isFiltered := or $model.filters.Agent $model.filters.Year $model.filters.Type
|
||||||
|
$model.filters.OnlyScans
|
||||||
|
-}}
|
||||||
|
|
||||||
|
{{- if $isFiltered -}}
|
||||||
|
<div class="flex flex-row gap-x-3" id="searchpills">
|
||||||
|
{{- if $model.filters.Agent -}}
|
||||||
|
<filter-pill
|
||||||
|
data-queryparam="agentfilter"
|
||||||
|
data-value="{{ $model.filters.Agent }}"
|
||||||
|
data-text="Person">
|
||||||
|
</filter-pill>
|
||||||
|
{{- end -}}
|
||||||
|
{{- if $model.filters.Year -}}
|
||||||
|
<filter-pill
|
||||||
|
data-queryparam="yearfilter"
|
||||||
|
data-value="{{ $model.filters.Year }}"
|
||||||
|
data-text="Jahr">
|
||||||
|
</filter-pill>
|
||||||
|
{{- end -}}
|
||||||
|
{{- if $model.filters.Type -}}
|
||||||
|
<filter-pill
|
||||||
|
data-queryparam="typefilter"
|
||||||
|
data-value="{{ $model.filters.Type }}"
|
||||||
|
data-text="Typ">
|
||||||
|
</filter-pill>
|
||||||
|
{{- end -}}
|
||||||
|
{{- if $model.filters.OnlyScans -}}
|
||||||
|
<filter-pill
|
||||||
|
data-queryparam="onlyscans"
|
||||||
|
data-value="{{ $model.filters.OnlyScans }}"
|
||||||
|
data-text="Nur Digitalisate">
|
||||||
|
</filter-pill>
|
||||||
|
{{- end -}}
|
||||||
|
</div>
|
||||||
|
{{- end -}}
|
||||||
@@ -63,11 +63,12 @@
|
|||||||
id="onlyscans"
|
id="onlyscans"
|
||||||
name="onlyscans"
|
name="onlyscans"
|
||||||
autocomplete="off"
|
autocomplete="off"
|
||||||
hx-get="{{- $model.parameters.ToQueryParamsBeitraege -}}"
|
hx-get="{{- $model.parameters.ToQueryParamsBeitraege -}} {{- $model.filters.ToQueryParamsWOScans -}}"
|
||||||
trigger="change"
|
trigger="change"
|
||||||
hx-push-url="true"
|
hx-push-url="true"
|
||||||
hx-select="main"
|
hx-select="#searchresults"
|
||||||
hx-target="main"
|
hx-target="#searchresults"
|
||||||
|
hx-swap="outerHTML"
|
||||||
{{ if $model.filters.OnlyScans -}}checked{{- end -}} />
|
{{ if $model.filters.OnlyScans -}}checked{{- end -}} />
|
||||||
|
|
||||||
<label
|
<label
|
||||||
@@ -82,11 +83,12 @@
|
|||||||
name="sort"
|
name="sort"
|
||||||
id="sort"
|
id="sort"
|
||||||
autocomplete="off"
|
autocomplete="off"
|
||||||
hx-get="{{- $model.parameters.ToQueryParamsBeitraege -}}"
|
hx-get="{{- $model.parameters.ToQueryParamsBeitraege -}}{{- $model.filters.ToQueryParams -}}"
|
||||||
trigger="change"
|
trigger="change"
|
||||||
hx-push-url="true"
|
hx-push-url="true"
|
||||||
hx-select="main"
|
hx-select="#subresults"
|
||||||
hx-target="main">
|
hx-target="#subresults"
|
||||||
|
hx-swap="outerHTML show:window:top">
|
||||||
<option
|
<option
|
||||||
value="year"
|
value="year"
|
||||||
{{ if eq $model.parameters.Sort "year" -}}
|
{{ if eq $model.parameters.Sort "year" -}}
|
||||||
|
|||||||
@@ -3,21 +3,24 @@
|
|||||||
{{- $isFiltered := or $model.filters.Agent $model.filters.Year $model.filters.Type -}}
|
{{- $isFiltered := or $model.filters.Agent $model.filters.Year $model.filters.Type -}}
|
||||||
|
|
||||||
|
|
||||||
<div class="container-oversize " x-data="{ filters: '{{- $isFiltered -}}' }">
|
<div class="container-oversize ">
|
||||||
<button
|
<button
|
||||||
class="w-full flex flex-row bg-slate-100 py-3 border-2 border-slate-100 hover:border-slate-900
|
class="w-full flex flex-row bg-slate-100 py-3 border-2 border-slate-100 hover:border-slate-900
|
||||||
cursor-pointer box-content hover:[&>_h2]:font-slate-900 select-none"
|
cursor-pointer box-content hover:[&>_h2]:font-slate-900 select-none"
|
||||||
@click="filters = !filters">
|
id="filterlistbtn">
|
||||||
<h2 class="text-2xl text-stone-700 px-32">
|
<h2 class="text-2xl text-stone-700 px-32">
|
||||||
Filter
|
Filter
|
||||||
<i class="ri-arrow-right-s-line" x-show="!filters"></i>
|
<i class="ri-arrow-right-s-line show-closed"></i>
|
||||||
<i class="ri-arrow-down-s-line" x-show="filters"></i>
|
<i class="ri-arrow-down-s-line show-opened"></i>
|
||||||
</h2>
|
</h2>
|
||||||
</button>
|
</button>
|
||||||
<div
|
<div
|
||||||
class="flex flex-row px-24 justify-between bg-slate-100 py-12 border-t-4 border-stone-50"
|
class="flex flex-row px-24 justify-between bg-slate-100 py-12 border-t-4 border-stone-50 {{ if
|
||||||
id="searchfilter"
|
$isFiltered
|
||||||
x-show="filters">
|
}}
|
||||||
|
hidden
|
||||||
|
{{ end }}"
|
||||||
|
id="searchfilter">
|
||||||
<div class="w-[30%] grow-0 shrink-0">
|
<div class="w-[30%] grow-0 shrink-0">
|
||||||
<filter-list
|
<filter-list
|
||||||
class=""
|
class=""
|
||||||
@@ -48,6 +51,30 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script type="module">
|
<script type="module">
|
||||||
|
let button = document.getElementById("filterlistbtn");
|
||||||
|
let filter = document.getElementById("searchfilter");
|
||||||
|
if (button && filter) {
|
||||||
|
toggleFilter();
|
||||||
|
if (button && filter) {
|
||||||
|
button.addEventListener("click", () => {
|
||||||
|
toggleFilter();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function toggleFilter() {
|
||||||
|
if (filter.classList.contains("hidden")) {
|
||||||
|
filter.classList.remove("hidden");
|
||||||
|
button.querySelector(".show-closed").classList.add("hidden");
|
||||||
|
button.querySelector(".show-opened").classList.remove("hidden");
|
||||||
|
} else {
|
||||||
|
filter.classList.add("hidden");
|
||||||
|
button.querySelector(".show-closed").classList.remove("hidden");
|
||||||
|
button.querySelector(".show-opened").classList.add("hidden");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
let agentList = document.getElementById("agent-list");
|
let agentList = document.getElementById("agent-list");
|
||||||
if (agentList) {
|
if (agentList) {
|
||||||
agentList.items = {{ $model.result.AgentsList }};
|
agentList.items = {{ $model.result.AgentsList }};
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ const ABBREV_TOOLTIPS_ELEMENT = "abbrev-tooltips";
|
|||||||
const INT_LINK_ELEMENT = "int-link";
|
const INT_LINK_ELEMENT = "int-link";
|
||||||
const POPUP_IMAGE_ELEMENT = "popup-image";
|
const POPUP_IMAGE_ELEMENT = "popup-image";
|
||||||
const TABLIST_ELEMENT = "tab-list";
|
const TABLIST_ELEMENT = "tab-list";
|
||||||
|
const FILTER_PILL_ELEMENT = "filter-pill";
|
||||||
|
|
||||||
class XSLTParseProcess {
|
class XSLTParseProcess {
|
||||||
#processors;
|
#processors;
|
||||||
@@ -107,6 +108,100 @@ function setup_templates() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class FilterPill extends HTMLElement {
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
this._value = "";
|
||||||
|
this.render();
|
||||||
|
}
|
||||||
|
|
||||||
|
static get observedAttributes() {
|
||||||
|
return ["data-text", "data-queryparam", "data-value"];
|
||||||
|
}
|
||||||
|
|
||||||
|
set value(value) {
|
||||||
|
this.setAttribute("data-value", value);
|
||||||
|
}
|
||||||
|
|
||||||
|
get value() {
|
||||||
|
return this.getAttribute("data-value") || "";
|
||||||
|
}
|
||||||
|
|
||||||
|
set text(value) {
|
||||||
|
this.setAttribute("data-text", value);
|
||||||
|
}
|
||||||
|
|
||||||
|
get text() {
|
||||||
|
return this.getAttribute("data-text") || "";
|
||||||
|
}
|
||||||
|
|
||||||
|
set queryparam(value) {
|
||||||
|
this.setAttribute("data-queryparam", value);
|
||||||
|
}
|
||||||
|
|
||||||
|
get queryparam() {
|
||||||
|
return this.getAttribute("data-queryparam") || "";
|
||||||
|
}
|
||||||
|
|
||||||
|
connectedCallback() {
|
||||||
|
this._filter = this.text;
|
||||||
|
this._queryparam = this.queryparam;
|
||||||
|
this.render();
|
||||||
|
htmx.process(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
attributeChangedCallback(name, oldValue, newValue) {
|
||||||
|
if (oldValue !== newValue) {
|
||||||
|
if (name === "data-text") {
|
||||||
|
this._filter = newValue;
|
||||||
|
}
|
||||||
|
if (name === "data-queryparam") {
|
||||||
|
this._queryparam = newValue;
|
||||||
|
}
|
||||||
|
if (name === "data-value") {
|
||||||
|
this._value = newValue;
|
||||||
|
}
|
||||||
|
this.render();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
getURL() {
|
||||||
|
if (this._queryparam) {
|
||||||
|
let url = new URL(window.location);
|
||||||
|
let params = new URLSearchParams(url.search);
|
||||||
|
params.delete(this._queryparam);
|
||||||
|
params.delete("page");
|
||||||
|
url.search = params.toString();
|
||||||
|
return url.toString();
|
||||||
|
}
|
||||||
|
return "#";
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
this.innerHTML = `
|
||||||
|
<a href="${this.getURL()}" class="!no-underline block text-base" hx-target="#searchresults" hx-select="#searchresults" hx-swap="outerHTML show:window:top">
|
||||||
|
<div class="flex flex-row filter-pill rounded-lg bg-orange-100 hover:-saturate-100 px-2.5 mt-2">
|
||||||
|
<div href="${this.getURL()}" class="filter-pill-close no-underline font-bold mr-1 text-orange-900 hover:text-orange-800">
|
||||||
|
<i class="ri-close-circle-line"></i>
|
||||||
|
</div>
|
||||||
|
<div class="flex flex-row filter-pill-label-value !items-baseline text-slate-700">
|
||||||
|
<div class="filter-pill-label font-bold mr-1.5 align-baseline">${this.text}</div>
|
||||||
|
${this.renderValue()}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
renderValue() {
|
||||||
|
const isBool = this.value === "true" || this.value === "false";
|
||||||
|
if (isBool) return ``;
|
||||||
|
return `
|
||||||
|
<div class="filter-pill-value">${this.value}</div>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class FilterList extends HTMLElement {
|
class FilterList extends HTMLElement {
|
||||||
#hiddenlist = false;
|
#hiddenlist = false;
|
||||||
#activequery = "";
|
#activequery = "";
|
||||||
@@ -318,6 +413,7 @@ class FilterList extends HTMLElement {
|
|||||||
let url = new URL(window.location);
|
let url = new URL(window.location);
|
||||||
let params = new URLSearchParams(url.search);
|
let params = new URLSearchParams(url.search);
|
||||||
params.set(this._queryparam, this.getHREF(item));
|
params.set(this._queryparam, this.getHREF(item));
|
||||||
|
params.delete("page");
|
||||||
url.search = params.toString();
|
url.search = params.toString();
|
||||||
return url.toString();
|
return url.toString();
|
||||||
}
|
}
|
||||||
@@ -1018,5 +1114,6 @@ customElements.define(SCROLL_BUTTON_ELEMENT, ScrollButton);
|
|||||||
customElements.define(TOOLTIP_ELEMENT, ToolTip);
|
customElements.define(TOOLTIP_ELEMENT, ToolTip);
|
||||||
customElements.define(POPUP_IMAGE_ELEMENT, PopupImage);
|
customElements.define(POPUP_IMAGE_ELEMENT, PopupImage);
|
||||||
customElements.define(TABLIST_ELEMENT, Tablist);
|
customElements.define(TABLIST_ELEMENT, Tablist);
|
||||||
|
customElements.define(FILTER_PILL_ELEMENT, FilterPill);
|
||||||
|
|
||||||
export { XSLTParseProcess, FilterList, ScrollButton, AbbreviationTooltips };
|
export { XSLTParseProcess, FilterList, ScrollButton, AbbreviationTooltips };
|
||||||
|
|||||||
@@ -312,6 +312,18 @@
|
|||||||
@apply border shadow-inner;
|
@apply border shadow-inner;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#searchpills {
|
||||||
|
@apply flex flex-row gap-x-2.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
#searchpills filter-pill .filter-pill {
|
||||||
|
@appply px-2.5 rounded-lg bg-orange-300;
|
||||||
|
}
|
||||||
|
|
||||||
|
#searchresults .filter-list-item[aria-current="page"] {
|
||||||
|
@apply text-orange-800 border-orange-900 bg-orange-100 pointer-events-none;
|
||||||
|
}
|
||||||
|
|
||||||
#persontype a {
|
#persontype a {
|
||||||
@apply px-1.5 border-b-[5px] border-transparent hover:border-zinc-200 no-underline font-serif mx-2.5;
|
@apply px-1.5 border-b-[5px] border-transparent hover:border-zinc-200 no-underline font-serif mx-2.5;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user