+some small frontend annoyances

This commit is contained in:
Simon Martens
2026-01-21 23:35:45 +01:00
parent 8f4558e331
commit c0146aadfb
8 changed files with 1183 additions and 1062 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -73,7 +73,7 @@
<div class="mt-8"> <div class="mt-8">
{{- range $i, $c := $model.result.Contents -}} {{- range $i, $c := $model.result.Contents -}}
{{- $rels := index $model.result.ContentsAgents $c.Id -}} {{- $rels := index $model.result.ContentsAgents $c.Id -}}
{{- template "_content" Arr $c $model.result.Entry $rels $model.result.Agents -}} {{- template "_content" Arr $c $model.result.Entry $rels $model.result.Agents false false false $model.request -}}
{{- end -}} {{- end -}}
</div> </div>
</div> </div>

View File

@@ -185,8 +185,8 @@
<span>Neuer Beitrag</span> <span>Neuer Beitrag</span>
</button> </button>
</div> </div>
<div class="mx-4 mt-2 rounded-md border border-slate-200 bg-white flex flex-col overflow-hidden" data-role="contents-panel"> <div class="mx-4 mt-2 rounded-md border border-slate-300 bg-white flex flex-col overflow-hidden p-1" data-role="contents-panel">
<div class="flex-1 min-h-0 overflow-y-auto"> <div class="flex-1 min-h-0 overflow-y-scroll">
<div class="flex flex-col gap-0" <div class="flex flex-col gap-0"
data-role="contents-list" data-role="contents-list"
data-order-endpoint="/almanach/{{ $model.result.Entry.MusenalmID }}/contents/edit"> data-order-endpoint="/almanach/{{ $model.result.Entry.MusenalmID }}/contents/edit">
@@ -562,12 +562,26 @@
}); });
}; };
const setContentsPanelHeight = () => {
const panel = document.querySelector("[data-role='contents-panel']");
if (!panel) {
return;
}
const rect = panel.getBoundingClientRect();
const viewportHeight = window.innerHeight || document.documentElement.clientHeight || 0;
const bottomGap = 16;
const available = Math.max(200, viewportHeight - rect.top - bottomGap);
panel.style.height = `${available}px`;
};
const initPage = () => { const initPage = () => {
list = document.querySelector("[data-role='contents-list']"); list = document.querySelector("[data-role='contents-list']");
if (!list) { if (!list) {
return; return;
} }
setContentsPanelHeight();
const getItems = () => Array.from(list.querySelectorAll("[data-role='content-item']")); const getItems = () => Array.from(list.querySelectorAll("[data-role='content-item']"));
if (getItems().length === 0) { if (getItems().length === 0) {
return; return;
@@ -903,4 +917,10 @@
initPage(); initPage();
} }
}); });
if (!window.__contentsPanelResizeBound) {
window.__contentsPanelResizeBound = true;
window.addEventListener("resize", () => {
setContentsPanelHeight();
});
}
</script> </script>

View File

@@ -34,7 +34,15 @@
</div> </div>
<div class="container-normal mt-12 flex flex-col font-serif"> <div class="container-normal mt-12 flex flex-col font-serif">
<div class="font-sans mb-1"><i class="ri-article-line"></i> Einzelbeitrag</div> <div class="font-sans mb-1 flex items-center gap-2">
<div><i class="ri-article-line"></i> Einzelbeitrag</div>
{{- if (IsAdminOrEditor $model.request.user) -}}
<div>
&middot;&nbsp;<i class="ri-edit-line"></i>
<a href="/almanach/{{- $model.result.Entry.MusenalmID -}}/contents/{{- $model.result.Content.MusenalmID -}}/edit">Bearbeiten</a>
</div>
{{- end -}}
</div>
<h1 class="text-3xl font-bold"> <h1 class="text-3xl font-bold">
{{ $model.result.Entry.PreferredTitle }}, {{ $model.result.Entry.PreferredTitle }},
{{ if $model.result.Content.Extent -}} {{ if $model.result.Content.Extent -}}

View File

@@ -58,7 +58,10 @@
{{- $searchparameters := false -}} {{- $searchparameters := false -}}
{{- if gt (len .) 6 -}} {{- if gt (len .) 6 -}}
{{- $searchparameters = index . 6 -}} {{- $searchparameters = index . 6 -}}
{{- if or (eq (printf "%T" $searchparameters) "bool") (eq (printf "%T" $searchparameters) "<nil>") -}}
{{- $searchparameters = false -}}
{{- end -}}
{{- if $searchparameters -}}
{{- $isAlm = $searchparameters.AlmString -}} {{- $isAlm = $searchparameters.AlmString -}}
{{- $isTitle = or $searchparameters.Title $searchparameters.TitleString -}} {{- $isTitle = or $searchparameters.Title $searchparameters.TitleString -}}
{{- $isYear = or $searchparameters.Year $searchparameters.YearString -}} {{- $isYear = or $searchparameters.Year $searchparameters.YearString -}}
@@ -66,6 +69,12 @@
{{- $isAnnotation = or $searchparameters.Annotations $searchparameters.AnnotationsString -}} {{- $isAnnotation = or $searchparameters.Annotations $searchparameters.AnnotationsString -}}
{{- $isIncipit = or $searchparameters.Incipit $searchparameters.IncipitString -}} {{- $isIncipit = or $searchparameters.Incipit $searchparameters.IncipitString -}}
{{- $isEntry = or $searchparameters.Entry $searchparameters.EntryString -}} {{- $isEntry = or $searchparameters.Entry $searchparameters.EntryString -}}
{{- end -}}
{{- end -}}
{{- $request := false -}}
{{- if gt (len .) 7 -}}
{{- $request = index . 7 -}}
{{- end -}} {{- end -}}
@@ -204,12 +213,19 @@
</div> </div>
{{- end -}} {{- end -}}
{{- end -}} {{- end -}}
<div class="font-sans py-0.5 text-sm"> <div class="font-sans py-0.5 text-sm flex flex-col items-end gap-1">
<a <a
href="/beitrag/{{ $content.MusenalmID }}" href="/beitrag/{{ $content.MusenalmID }}"
class="no-underline rounded bg-stone-100 px-1.5"> class="no-underline rounded bg-stone-100 px-1.5">
Link <i class="ri-links-line"></i> Link <i class="ri-links-line"></i>
</a> </a>
{{- if and $request (IsAdminOrEditor $request.user) -}}
<a
href="/almanach/{{- $entry.MusenalmID -}}/contents/{{- $content.MusenalmID -}}/edit"
class="no-underline rounded bg-stone-100 px-1.5">
<i class="ri-edit-line"></i> Bearbeiten
</a>
{{- end -}}
</div> </div>
</div> </div>
{{- end -}} {{- end -}}

View File

@@ -35,7 +35,7 @@
{{- if (IsAdminOrEditor $request.user) -}} {{- if (IsAdminOrEditor $request.user) -}}
<a href="/reihe/{{ $r.MusenalmID }}/edit" class="no-underline rounded bg-stone-100 px-1.5"> <a href="/reihe/{{ $r.MusenalmID }}/edit" class="no-underline rounded bg-stone-100 px-1.5">
<i class="ri-edit-line"></i> <i class="ri-edit-line"></i>
Edit Bearbeiten
</a> </a>
{{- end -}} {{- end -}}
</div> </div>

View File

@@ -25,6 +25,9 @@ export class FabMenu extends HTMLElement {
let hasEntry = false, let hasEntry = false,
entryId = "", entryId = "",
entryUpdated = ""; entryUpdated = "";
let hasContent = false,
contentId = "",
contentEntryId = "";
let hasPage = false, let hasPage = false,
pageKey = ""; pageKey = "";
@@ -59,6 +62,20 @@ export class FabMenu extends HTMLElement {
} }
} }
// Content detail page: /beitrag/{id}
const contentMatch = path.match(/^\/beitrag\/([^\/]+)\/?$/);
if (contentMatch) {
hasContent = true;
contentId = contentMatch[1];
const entryLink = document.querySelector('#breadcrumbs a[href^="/almanach/"]');
if (entryLink) {
const match = entryLink.getAttribute("href")?.match(/^\/almanach\/([^\/#]+)/);
if (match) {
contentEntryId = match[1];
}
}
}
// Page views use page editor keys via meta tag or URL mapping // Page views use page editor keys via meta tag or URL mapping
const pageKeyMeta = document.querySelector('meta[name="page-key"]'); const pageKeyMeta = document.querySelector('meta[name="page-key"]');
if (pageKeyMeta && pageKeyMeta.content) { if (pageKeyMeta && pageKeyMeta.content) {
@@ -95,11 +112,11 @@ export class FabMenu extends HTMLElement {
} }
const hasCsrf = csrfToken !== ""; const hasCsrf = csrfToken !== "";
this.hasContext = hasReihe || hasPerson || hasEntry || hasPage; this.hasContext = hasReihe || hasPerson || hasEntry || hasContent || hasPage;
// Build half-open menu content // Build half-open menu content
let halfOpenContent = ""; let halfOpenContent = "";
if (hasReihe) { if (isAdminOrEditor && hasReihe) {
halfOpenContent = ` halfOpenContent = `
<div class="px-3 py-1.5 text-xs font-semibold text-gray-500 uppercase tracking-wider"> <div class="px-3 py-1.5 text-xs font-semibold text-gray-500 uppercase tracking-wider">
Reihe Reihe
@@ -109,7 +126,7 @@ export class FabMenu extends HTMLElement {
<span class="text-gray-900">Bearbeiten</span> <span class="text-gray-900">Bearbeiten</span>
</a> </a>
`; `;
} else if (hasPerson) { } else if (isAdminOrEditor && hasPerson) {
halfOpenContent = ` halfOpenContent = `
<div class="px-3 py-1.5 text-xs font-semibold text-gray-500 uppercase tracking-wider"> <div class="px-3 py-1.5 text-xs font-semibold text-gray-500 uppercase tracking-wider">
Person Person
@@ -119,7 +136,7 @@ export class FabMenu extends HTMLElement {
<span class="text-gray-900">Bearbeiten</span> <span class="text-gray-900">Bearbeiten</span>
</a> </a>
`; `;
} else if (hasEntry) { } else if (isAdminOrEditor && hasEntry) {
halfOpenContent = ` halfOpenContent = `
<div class="px-3 py-1.5 text-xs font-semibold text-gray-500 uppercase tracking-wider"> <div class="px-3 py-1.5 text-xs font-semibold text-gray-500 uppercase tracking-wider">
Almanach Almanach
@@ -128,8 +145,34 @@ export class FabMenu extends HTMLElement {
<i class="ri-edit-line text-base text-gray-700 mr-2.5"></i> <i class="ri-edit-line text-base text-gray-700 mr-2.5"></i>
<span class="text-gray-900">Bearbeiten</span> <span class="text-gray-900">Bearbeiten</span>
</a> </a>
<a href="/almanach/${entryId}/contents/edit" class="flex items-center px-4 py-2 hover:bg-gray-100 transition-colors no-underline text-sm">
<i class="ri-file-list-3-line text-base text-gray-700 mr-2.5"></i>
<span class="text-gray-900">Beiträge bearbeiten</span>
</a>
<a href="/almanach/${entryId}/contents/new" class="flex items-center px-4 py-2 hover:bg-gray-100 transition-colors no-underline text-sm">
<i class="ri-add-line text-base text-gray-700 mr-2.5"></i>
<span class="text-gray-900">Neuer Beitrag</span>
</a>
`; `;
} else if (hasPage) { } else if (isAdminOrEditor && hasContent && contentEntryId) {
halfOpenContent = `
<div class="px-3 py-1.5 text-xs font-semibold text-gray-500 uppercase tracking-wider">
Beitrag
</div>
<a href="/almanach/${contentEntryId}/contents/${contentId}/edit" class="flex items-center px-4 py-2 hover:bg-gray-100 transition-colors no-underline text-sm">
<i class="ri-edit-line text-base text-gray-700 mr-2.5"></i>
<span class="text-gray-900">Bearbeiten</span>
</a>
<a href="/almanach/${contentEntryId}/contents/edit" class="flex items-center px-4 py-2 hover:bg-gray-100 transition-colors no-underline text-sm">
<i class="ri-file-list-3-line text-base text-gray-700 mr-2.5"></i>
<span class="text-gray-900">Beiträge bearbeiten</span>
</a>
<a href="/almanach/${contentEntryId}/contents/new" class="flex items-center px-4 py-2 hover:bg-gray-100 transition-colors no-underline text-sm">
<i class="ri-add-line text-base text-gray-700 mr-2.5"></i>
<span class="text-gray-900">Neuer Beitrag</span>
</a>
`;
} else if (isAdminOrEditor && hasPage) {
halfOpenContent = ` halfOpenContent = `
<div class="px-3 py-1.5 text-xs font-semibold text-gray-500 uppercase tracking-wider"> <div class="px-3 py-1.5 text-xs font-semibold text-gray-500 uppercase tracking-wider">
Seite Seite