+Create new beitrag

This commit is contained in:
Simon Martens
2026-01-21 22:28:02 +01:00
parent df555d5c0b
commit e2b9fca6d9
9 changed files with 185 additions and 103 deletions

View File

@@ -177,6 +177,13 @@
<span id="content-filter-count" class="text-sm text-gray-600 whitespace-nowrap ml-auto" data-role="content-filter-count">
{{ len $model.result.Contents }} Einträge
</span>
<button
type="button"
class="content-action-button"
onclick="window.location.assign('/almanach/{{ $model.result.Entry.MusenalmID }}/contents/new')">
<i class="ri-add-line"></i>
<span>Neuer Beitrag</span>
</button>
</div>
<div class="flex flex-col gap-0 mt-2"
data-role="contents-list"
@@ -197,6 +204,15 @@
) -}}
{{- end -}}
</div>
<div class="px-4 py-2 mt-2 flex items-center">
<button
type="button"
class="content-action-button"
onclick="window.location.assign('/almanach/{{ $model.result.Entry.MusenalmID }}/contents/new')">
<i class="ri-add-line"></i>
<span>Neuer Beitrag</span>
</button>
</div>
</div>
<dialog id="content-delete-dialog" class="dbform fixed inset-0 m-auto rounded-md border border-slate-200 p-0 shadow-xl backdrop:bg-black/40">

View File

@@ -10,13 +10,18 @@
<h1 class="text-2xl w-full font-bold text-slate-900 mb-1">
{{- if $model.result -}}
{{- $model.result.Entry.PreferredTitle -}}<br>
<span class="text-base font-semibold text-slate-700">Beitrag Nr. {{ $model.content.MusenalmID }}</span>
{{- if $model.is_new -}}
<span class="text-base font-semibold text-slate-700">Neuer Beitrag</span>
{{- else -}}
<span class="text-base font-semibold text-slate-700">Beitrag Nr. {{ $model.content.MusenalmID }}</span>
{{- end -}}
{{- else -}}
Beiträge bearbeiten
{{- end -}}
</h1>
{{- if $model.result -}}
<div class="flex flex-row gap-x-3">
{{- if not $model.is_new -}}
<div>
<a
href="/beitrag/{{ $model.content.MusenalmID }}"
@@ -51,6 +56,7 @@
</a>
</div>
&middot;
{{- end -}}
<div>
<a href="/almanach/{{- $model.result.Entry.MusenalmID -}}/contents/edit" class="text-gray-700 no-underline hover:text-slate-950 block">
<i class="ri-arrow-left-line"></i> Zurück zur Liste
@@ -73,6 +79,7 @@
<i class="ri-navigation-line"></i> Navigation
</div>
<div class="flex items-center gap-3">
{{- if not $model.is_new -}}
{{- if $model.prev_content -}}
<tool-tip position="top" class="!inline">
<div class="data-tip">
@@ -112,6 +119,9 @@
</a>
</tool-tip>
{{- end -}}
{{- else -}}
<span class="text-gray-800 font-bold no-underline">Neu</span>
{{- end -}}
</div>
</div>
</div>
@@ -154,6 +164,7 @@
hx-boost="false"
action="/almanach/{{ $model.result.Entry.MusenalmID }}/contents/edit">
<input type="hidden" name="csrf_token" value="{{ $model.csrf_token }}" />
<input type="hidden" name="content_id" value="{{ $model.content_id }}" />
<div class="flex gap-8">
<div class="flex-1 flex flex-col gap-4">
@@ -227,10 +238,12 @@
<i class="ri-arrow-left-line"></i>
<span>Zurück</span>
</a>
<button type="button" class="resetbutton w-40 flex items-center gap-2 justify-center bg-red-50 text-red-800 hover:bg-red-100 hover:text-red-900" data-role="content-delete">
<i class="ri-delete-bin-line"></i>
<span>Eintrag loeschen</span>
</button>
{{- if not $model.is_new -}}
<button type="button" class="resetbutton w-40 flex items-center gap-2 justify-center bg-red-50 text-red-800 hover:bg-red-100 hover:text-red-900" data-role="content-delete">
<i class="ri-delete-bin-line"></i>
<span>Eintrag loeschen</span>
</button>
{{- end -}}
<button type="submit" class="submitbutton w-40 flex items-center gap-2 justify-center">
<i class="ri-save-line"></i>
<span>Speichern</span>
@@ -304,59 +317,58 @@
initMultiSelects();
}
if (!deleteButton || !deleteDialog || !deleteConfirm || !deleteCancel) {
return;
}
deleteButton.addEventListener("click", () => {
if (deleteDialog.showModal) {
deleteDialog.showModal();
} else {
deleteDialog.setAttribute("open", "true");
}
});
deleteCancel.addEventListener("click", () => {
deleteDialog.close();
});
deleteDialog.addEventListener("cancel", (event) => {
event.preventDefault();
deleteDialog.close();
});
deleteConfirm.addEventListener("click", () => {
const payload = new URLSearchParams();
payload.set("csrf_token", csrfToken);
payload.set("content_id", contentId);
fetch(deleteEndpoint, {
method: "POST",
headers: {
"Content-Type": "application/x-www-form-urlencoded",
},
body: payload.toString(),
}).then((response) => {
if (response.ok) {
window.location.assign("/almanach/{{ $model.result.Entry.MusenalmID }}/contents/edit");
return;
if (deleteButton && deleteDialog && deleteConfirm && deleteCancel) {
deleteButton.addEventListener("click", () => {
if (deleteDialog.showModal) {
deleteDialog.showModal();
} else {
deleteDialog.setAttribute("open", "true");
}
deleteDialog.close();
}).catch(() => {
});
deleteCancel.addEventListener("click", () => {
deleteDialog.close();
});
});
deleteDialog.addEventListener("cancel", (event) => {
event.preventDefault();
deleteDialog.close();
});
deleteConfirm.addEventListener("click", () => {
const payload = new URLSearchParams();
payload.set("csrf_token", csrfToken);
payload.set("content_id", contentId);
fetch(deleteEndpoint, {
method: "POST",
headers: {
"Content-Type": "application/x-www-form-urlencoded",
},
body: payload.toString(),
}).then((response) => {
if (response.ok) {
window.location.assign("/almanach/{{ $model.result.Entry.MusenalmID }}/contents/edit");
return;
}
deleteDialog.close();
}).catch(() => {
deleteDialog.close();
});
});
}
const form = document.querySelector("form.dbform");
const uploadInput = document.querySelector("[data-role='content-images-upload-input']");
const userMessage = document.getElementById("user-message");
if (form && uploadInput && userMessage) {
form.addEventListener("submit", async (event) => {
event.preventDefault();
event.stopPropagation();
event.stopImmediatePropagation();
const files = Array.from(uploadInput.files || []);
if (files.length > 0) {
const hasInvalid = files.some((file) => !file.type || !file.type.startsWith("image/"));
if (hasInvalid) {
event.preventDefault();
userMessage.innerHTML = `
<div class="text-red-800 text-sm mt-2 rounded-xs bg-red-200 p-2 font-bold border-red-700 shadow border mb-3">
<i class="ri-error-warning-fill"></i> Bitte nur Bilddateien auswählen.
@@ -366,7 +378,6 @@
}
}
event.preventDefault();
const payload = new FormData(form);
if (payload.has("scans")) {
payload.delete("scans");
@@ -402,9 +413,6 @@
window.location.assign(response.url);
return;
}
if (!response.ok) {
return;
}
const html = await response.text();
if (!html) {
return;
@@ -413,8 +421,14 @@
const nextMessage = doc.getElementById("user-message");
if (nextMessage) {
userMessage.innerHTML = nextMessage.innerHTML;
} else if (!response.ok) {
userMessage.innerHTML = `
<div class="text-red-800 text-sm mt-2 rounded-xs bg-red-200 p-2 font-bold border-red-700 shadow border mb-3">
<i class="ri-error-warning-fill"></i> Speichern fehlgeschlagen.
</div>
`;
}
});
}, true);
}
})();
</script>

View File

@@ -39,23 +39,32 @@
</div>
</div>
<div class="inputwrapper">
<div class="inputlabelrow">
<label for="{{ $baseID }}-title" class="inputlabel">Titel</label>
</div>
<textarea name="{{ $prefix }}title_statement" id="{{ $baseID }}-title" class="inputinput no-enter whitespace-normal" autocomplete="off" rows="1">{{- $content.TitleStmt -}}</textarea>
</div>
<div class="inputwrapper">
<div class="inputlabelrow">
<label for="{{ $baseID }}-incipit" class="inputlabel">Incipit</label>
</div>
<textarea name="{{ $prefix }}incipit_statement" id="{{ $baseID }}-incipit" class="inputinput no-enter whitespace-normal" autocomplete="off" rows="1">{{- $content.IncipitStmt -}}</textarea>
</div>
<div class="inputwrapper">
<div class="inputlabelrow">
<label for="{{ $baseID }}-responsibility" class="inputlabel">Autorangabe</label>
</div>
<textarea name="{{ $prefix }}responsibility_statement" id="{{ $baseID }}-responsibility" class="inputinput no-enter whitespace-normal" autocomplete="off" rows="1">{{- $content.ResponsibilityStmt -}}</textarea>
</div>
<div id="{{ $baseID }}-edit-fields" class="mt-2 flex flex-col gap-2"></div>
<div-manager dm-target="{{ $baseID }}-edit-fields" class="flex items-center justify-end mt-1">
<button class="dm-menu-button text-right cursor-pointer whitespace-nowrap"><i class="ri-add-line"></i>
Felder hinzufügen</button>
<div class="inputwrapper {{ if eq $content.TitleStmt "" }}hidden{{ end }}">
<div class="inputlabelrow">
<label for="{{ $baseID }}-title" class="inputlabel menu-label">Titel</label>
<div class="pr-2">
<button class="dm-close-button font-bold input-label">
<i class="ri-close-line"></i>
</button>
</div>
</div>
<textarea name="{{ $prefix }}title_statement" id="{{ $baseID }}-title" class="inputinput no-enter whitespace-normal" autocomplete="off" rows="1">{{- $content.TitleStmt -}}</textarea>
</div>
<div class="inputwrapper {{ if eq $content.SubtitleStmt "" }}hidden{{ end }}">
<div class="inputlabelrow">
<label for="{{ $baseID }}-subtitle" class="inputlabel menu-label">Untertitel</label>
@@ -68,29 +77,7 @@
<textarea name="{{ $prefix }}subtitle_statement" id="{{ $baseID }}-subtitle" class="inputinput no-enter whitespace-normal" autocomplete="off" rows="1">{{- $content.SubtitleStmt -}}</textarea>
</div>
<div class="inputwrapper {{ if eq $content.IncipitStmt "" }}hidden{{ end }}">
<div class="inputlabelrow">
<label for="{{ $baseID }}-incipit" class="inputlabel menu-label">Incipit</label>
<div class="pr-2">
<button class="dm-close-button font-bold input-label">
<i class="ri-close-line"></i>
</button>
</div>
</div>
<textarea name="{{ $prefix }}incipit_statement" id="{{ $baseID }}-incipit" class="inputinput no-enter whitespace-normal" autocomplete="off" rows="1">{{- $content.IncipitStmt -}}</textarea>
</div>
<div class="inputwrapper {{ if eq $content.ResponsibilityStmt "" }}hidden{{ end }}">
<div class="inputlabelrow">
<label for="{{ $baseID }}-responsibility" class="inputlabel menu-label">Autorangabe</label>
<div class="pr-2">
<button class="dm-close-button font-bold input-label">
<i class="ri-close-line"></i>
</button>
</div>
</div>
<textarea name="{{ $prefix }}responsibility_statement" id="{{ $baseID }}-responsibility" class="inputinput no-enter whitespace-normal" autocomplete="off" rows="1">{{- $content.ResponsibilityStmt -}}</textarea>
</div>
<div class="inputwrapper {{ if eq $content.ParallelTitle "" }}hidden{{ end }}">
<div class="inputlabelrow">

View File

@@ -23,18 +23,12 @@
aria-label="Beitrag verschieben">
<i class="ri-draggable"></i>
</button>
<tool-tip position="top" class="!inline">
<div class="data-tip">Nach oben verschieben</div>
<button type="button" class="text-slate-600 rounded-sm px-2 py-1 text-sm transition-colors hover:bg-stone-300" data-role="content-move-up" aria-label="Beitrag nach oben">
<i class="ri-arrow-up-line"></i>
</button>
</tool-tip>
<tool-tip position="top" class="!inline">
<div class="data-tip">Nach unten verschieben</div>
<button type="button" class="text-slate-600 rounded-sm px-2 py-1 text-sm transition-colors hover:bg-stone-300" data-role="content-move-down" aria-label="Beitrag nach unten">
<i class="ri-arrow-down-line"></i>
</button>
</tool-tip>
<button type="button" class="text-slate-600 rounded-sm px-2 py-1 text-sm transition-colors hover:bg-stone-300" data-role="content-move-up" aria-label="Beitrag nach oben">
<i class="ri-arrow-up-line"></i>
</button>
<button type="button" class="text-slate-600 rounded-sm px-2 py-1 text-sm transition-colors hover:bg-stone-300" data-role="content-move-down" aria-label="Beitrag nach unten">
<i class="ri-arrow-down-line"></i>
</button>
</div>
{{- if $content.Extent -}}
<span class="content-search-text bg-slate-200 text-slate-900 px-1.5 py-0.5 rounded text-sm font-semibold shadow-sm shrink-0" data-role="content-page-pill">S. {{- $content.Extent -}}</span>