Almanach list

This commit is contained in:
Simon Martens
2026-01-09 14:00:15 +01:00
parent 2d7751b4cb
commit ecfd3579a5
9 changed files with 797 additions and 10 deletions

View File

@@ -5,6 +5,69 @@ export class EditPage extends HTMLElement {
if (form && typeof window.FormLoad === "function") {
window.FormLoad(form);
}
this._setupDelete();
}, 0);
}
_setupDelete() {
const form = this.querySelector("form");
if (!form) {
return;
}
const deleteEndpoint = form.getAttribute("data-delete-endpoint");
if (!deleteEndpoint) {
return;
}
const dialog = this.querySelector("[data-role='edit-delete-dialog']");
const deleteButton = this.querySelector("[data-role='edit-delete']");
const confirmButton = this.querySelector("[data-role='edit-delete-confirm']");
const cancelButton = this.querySelector("[data-role='edit-delete-cancel']");
if (!dialog || !deleteButton || !confirmButton || !cancelButton) {
return;
}
deleteButton.addEventListener("click", (event) => {
event.preventDefault();
if (typeof dialog.showModal === "function") {
dialog.showModal();
}
});
const closeDialog = (event) => {
if (event) {
event.preventDefault();
}
if (dialog.open) {
dialog.close();
}
};
cancelButton.addEventListener("click", closeDialog);
dialog.addEventListener("cancel", closeDialog);
confirmButton.addEventListener("click", async (event) => {
event.preventDefault();
closeDialog();
const formData = new FormData(form);
const payload = {
csrf_token: formData.get("csrf_token") || "",
last_edited: formData.get("last_edited") || "",
};
const response = await fetch(deleteEndpoint, {
method: "POST",
headers: {
"Content-Type": "application/json",
Accept: "application/json",
},
body: JSON.stringify(payload),
});
if (!response.ok) {
return;
}
const data = await response.json().catch(() => null);
const redirect = data?.redirect || "/";
window.location.assign(redirect);
});
}
}

View File

@@ -102,6 +102,18 @@
@apply px-1.5 italic text-gray-600;
}
/* Reset global list indentation inside tab panels */
.tab-list-panel ul {
margin-left: 0;
padding-left: 0;
list-style: none;
}
.tab-list-panel li {
margin-left: 0;
padding-left: 0;
}
/* Disabled form controls in deleted relations */
[data-rel-row].bg-red-50 select:disabled,
[data-rel-row].bg-red-50 input[type="checkbox"]:disabled:not([data-delete-toggle]) {

View File

@@ -8,16 +8,25 @@ export class TabList extends HTMLElement {
this._headings = [];
this._contents = [];
this._checkbox = null;
this._disabled = new Set();
this._defaultIndex = null;
}
connectedCallback() {
this._headings = Array.from(this.querySelectorAll(".tab-list-head"));
this._contents = Array.from(this.querySelectorAll(".tab-list-panel"));
this._readConfig();
this.hookupEvtHandlers();
this._applyDisabled();
this.hideDependent();
if (this._headings.length === 1) {
this.expand(0);
return;
}
if (this._defaultIndex !== null) {
this._expandFirstAvailable(this._defaultIndex);
}
}
@@ -25,6 +34,9 @@ export class TabList extends HTMLElement {
if (index < 0 || index >= this._headings.length) {
return;
}
if (this._disabled.has(index)) {
return;
}
this.shown = index;
@@ -67,6 +79,53 @@ export class TabList extends HTMLElement {
}
}
_readConfig() {
const disabledRaw = (this.getAttribute("data-disabled-indices") || "").trim();
const defaultRaw = (this.getAttribute("data-default-index") || "").trim();
this._disabled.clear();
if (disabledRaw) {
disabledRaw
.split(",")
.map((value) => parseInt(value.trim(), 10))
.filter((value) => Number.isFinite(value))
.forEach((value) => this._disabled.add(value));
}
if (defaultRaw !== "") {
const parsed = parseInt(defaultRaw, 10);
this._defaultIndex = Number.isFinite(parsed) ? parsed : null;
} else {
this._defaultIndex = null;
}
}
_applyDisabled() {
this._headings.forEach((heading, index) => {
if (this._disabled.has(index)) {
heading.classList.add("pointer-events-none", "opacity-60");
} else {
heading.classList.remove("pointer-events-none", "opacity-60");
}
});
}
_expandFirstAvailable(preferredIndex) {
if (this._headings.length === 0) {
return;
}
if (!this._disabled.has(preferredIndex)) {
this.expand(preferredIndex);
return;
}
for (let i = 0; i < this._headings.length; i += 1) {
if (!this._disabled.has(i)) {
this.expand(i);
return;
}
}
}
restore() {
for (let heading of this._headings) {
heading.classList.add("cursor-pointer");