mirror of
https://github.com/Theodor-Springmann-Stiftung/musenalm.git
synced 2026-02-04 10:35:30 +00:00
Saving success messages betteR
This commit is contained in:
@@ -18,6 +18,7 @@ export class AlmanachEditPage extends HTMLElement {
|
||||
this._preferredSeriesRelationId = "";
|
||||
this._preferredSeriesSeriesId = "";
|
||||
this._handleSaveClick = this._handleSaveClick.bind(this);
|
||||
this._handleSaveViewClick = this._handleSaveViewClick.bind(this);
|
||||
this._handleResetClick = this._handleResetClick.bind(this);
|
||||
this._handleDeleteClick = this._handleDeleteClick.bind(this);
|
||||
this._handleDeleteConfirmClick = this._handleDeleteConfirmClick.bind(this);
|
||||
@@ -145,6 +146,7 @@ export class AlmanachEditPage extends HTMLElement {
|
||||
this._teardownSaveHandling();
|
||||
this._form = this.querySelector("#changealmanachform");
|
||||
this._saveButton = this.querySelector("[data-role='almanach-save']");
|
||||
this._saveViewButton = this.querySelector("[data-role='almanach-save-view']");
|
||||
this._resetButton = this.querySelector("[data-role='almanach-reset']");
|
||||
this._deleteButton = this.querySelector("[data-role='almanach-delete']");
|
||||
this._deleteDialog = this.querySelector("[data-role='almanach-delete-dialog']");
|
||||
@@ -157,6 +159,9 @@ export class AlmanachEditPage extends HTMLElement {
|
||||
this._saveEndpoint = this._form.getAttribute("data-save-endpoint") || this._deriveSaveEndpoint();
|
||||
this._deleteEndpoint = this._form.getAttribute("data-delete-endpoint") || "";
|
||||
this._saveButton.addEventListener("click", this._handleSaveClick);
|
||||
if (this._saveViewButton) {
|
||||
this._saveViewButton.addEventListener("click", this._handleSaveViewClick);
|
||||
}
|
||||
if (this._resetButton) {
|
||||
this._resetButton.addEventListener("click", this._handleResetClick);
|
||||
}
|
||||
@@ -188,6 +193,9 @@ export class AlmanachEditPage extends HTMLElement {
|
||||
if (this._saveButton) {
|
||||
this._saveButton.removeEventListener("click", this._handleSaveClick);
|
||||
}
|
||||
if (this._saveViewButton) {
|
||||
this._saveViewButton.removeEventListener("click", this._handleSaveViewClick);
|
||||
}
|
||||
if (this._resetButton) {
|
||||
this._resetButton.removeEventListener("click", this._handleResetClick);
|
||||
}
|
||||
@@ -204,6 +212,7 @@ export class AlmanachEditPage extends HTMLElement {
|
||||
this._deleteDialog.removeEventListener("cancel", this._handleDeleteCancelClick);
|
||||
}
|
||||
this._saveButton = null;
|
||||
this._saveViewButton = null;
|
||||
this._resetButton = null;
|
||||
this._deleteButton = null;
|
||||
this._deleteDialog = null;
|
||||
@@ -258,13 +267,54 @@ export class AlmanachEditPage extends HTMLElement {
|
||||
throw new Error(message);
|
||||
}
|
||||
|
||||
if (data?.redirect) {
|
||||
window.location.assign(data.redirect);
|
||||
return;
|
||||
await this._reloadForm(data?.message || "Änderungen gespeichert.");
|
||||
} catch (error) {
|
||||
this._showStatus(error instanceof Error ? error.message : "Speichern fehlgeschlagen.", "error");
|
||||
} finally {
|
||||
this._setSavingState(false);
|
||||
}
|
||||
}
|
||||
|
||||
async _handleSaveViewClick(event) {
|
||||
event.preventDefault();
|
||||
if (this._isSaving) {
|
||||
return;
|
||||
}
|
||||
const redirectUrl = this._saveViewButton?.getAttribute("data-redirect-url");
|
||||
if (!redirectUrl) {
|
||||
return;
|
||||
}
|
||||
this._clearStatus();
|
||||
let payload;
|
||||
try {
|
||||
payload = this._buildPayload();
|
||||
} catch (error) {
|
||||
this._showStatus(error instanceof Error ? error.message : String(error), "error");
|
||||
return;
|
||||
}
|
||||
this._setSavingState(true);
|
||||
try {
|
||||
const response = await fetch(this._saveEndpoint, {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
Accept: "application/json",
|
||||
},
|
||||
body: JSON.stringify(payload),
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
let message = `Speichern fehlgeschlagen (${response.status}).`;
|
||||
try {
|
||||
const data = await response.clone().json();
|
||||
message = data?.error || message;
|
||||
} catch {
|
||||
// ignore parsing error
|
||||
}
|
||||
throw new Error(message);
|
||||
}
|
||||
|
||||
await this._reloadForm(data?.message || "Änderungen gespeichert.");
|
||||
this._clearStatus();
|
||||
window.location.assign(redirectUrl);
|
||||
} catch (error) {
|
||||
this._showStatus(error instanceof Error ? error.message : "Speichern fehlgeschlagen.", "error");
|
||||
} finally {
|
||||
|
||||
@@ -134,6 +134,44 @@
|
||||
@apply w-full inline-flex justify-center py-2 px-4 border border-transparent rounded-md text-sm font-medium text-gray-800 bg-stone-200 hover:bg-stone-300 cursor-pointer focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-slate-500 no-underline;
|
||||
}
|
||||
|
||||
.form-with-action-bar {
|
||||
@apply pb-0;
|
||||
}
|
||||
|
||||
.form-action-bar {
|
||||
@apply sticky bottom-0 z-30 border-t border-transparent bg-stone-50;
|
||||
box-shadow: none;
|
||||
width: calc(100% + 120px);
|
||||
margin-left: -60px;
|
||||
margin-right: -60px;
|
||||
}
|
||||
|
||||
.form-action-bar-inner {
|
||||
@apply w-full max-w-(--breakpoint-xl) mx-auto px-8 py-3 flex items-center justify-between gap-4 flex-wrap;
|
||||
}
|
||||
|
||||
.form-action-bar-actions {
|
||||
@apply ml-auto flex items-center gap-3 flex-wrap justify-end w-full md:w-auto;
|
||||
}
|
||||
|
||||
.form-action-bar-message {
|
||||
@apply text-left mr-auto w-full md:w-auto;
|
||||
}
|
||||
|
||||
.form-action-bar .submitbutton,
|
||||
.form-action-bar .resetbutton {
|
||||
@apply !w-auto px-4;
|
||||
}
|
||||
|
||||
.form-action-bar.is-stuck {
|
||||
@apply border-t border-l border-r border-transparent;
|
||||
background-color: rgb(250 250 249);
|
||||
border-color: rgba(15, 23, 42, 0.06);
|
||||
box-shadow: 0 -1px 6px rgba(15, 23, 42, 0.06);
|
||||
border-top-left-radius: 6px;
|
||||
border-top-right-radius: 6px;
|
||||
}
|
||||
|
||||
.content-action-button {
|
||||
@apply inline-flex items-center justify-center gap-2 rounded-xs border border-slate-300 bg-white px-3 py-1.5 text-base font-semibold text-gray-800 shadow-sm transition-all duration-75 hover:bg-stone-50 focus:outline-none focus:ring-2 focus:ring-slate-400/30;
|
||||
}
|
||||
|
||||
@@ -616,6 +616,32 @@ function FormLoad(form) {
|
||||
// Update on change
|
||||
checkbox.addEventListener("change", updateHiddenInput);
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
function InitStickyActionBars() {
|
||||
if (InitStickyActionBars._initialized) {
|
||||
return;
|
||||
}
|
||||
InitStickyActionBars._initialized = true;
|
||||
|
||||
const update = () => {
|
||||
const bars = document.querySelectorAll(".form-action-bar");
|
||||
if (!bars.length) {
|
||||
return;
|
||||
}
|
||||
const viewportBottom = window.innerHeight || document.documentElement.clientHeight;
|
||||
bars.forEach((bar) => {
|
||||
const rect = bar.getBoundingClientRect();
|
||||
const stuck = rect.bottom >= viewportBottom - 1;
|
||||
bar.classList.toggle("is-stuck", stuck);
|
||||
});
|
||||
};
|
||||
|
||||
update();
|
||||
window.addEventListener("scroll", update, { passive: true });
|
||||
window.addEventListener("resize", update);
|
||||
document.addEventListener("htmx:afterSwap", update);
|
||||
}
|
||||
|
||||
document.addEventListener("keydown", (event) => {
|
||||
@@ -639,5 +665,6 @@ window.HookupRBChange = HookupRBChange;
|
||||
window.FormLoad = FormLoad;
|
||||
window.TextareaAutoResize = TextareaAutoResize;
|
||||
InitGlobalHtmxNotice();
|
||||
InitStickyActionBars();
|
||||
|
||||
export { FilterList, ScrollButton, AbbreviationTooltips, MultiSelectSimple, MultiSelectRole, ToolTip, PopupImage, TabList, FilterPill, ImageReel, IntLink, ItemsEditor, SingleSelectRemote, AlmanachEditPage, RelationsEditor, EditPage, FabMenu, LookupField };
|
||||
|
||||
@@ -11,7 +11,7 @@ export class ScrollButton extends HTMLElement {
|
||||
<button
|
||||
class="
|
||||
scroll-to-top
|
||||
fixed bottom-5 right-5
|
||||
fixed bottom-12 right-8 z-50
|
||||
hidden
|
||||
bg-gray-800 text-white
|
||||
p-2
|
||||
|
||||
Reference in New Issue
Block a user