- Public site (Home/Artists/Exhibitions/News/About/Contact) with EN/KO/JA i18n - Admin panel with login, CRUD, image upload, multilingual editing - Exhibition slider/lightbox view - FastAPI + MongoDB backend, JWT auth - Docker Compose deployment, behind nginx at jimi.yakenator.io
128 lines
4.7 KiB
HTML
128 lines
4.7 KiB
HTML
<!doctype html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="utf-8" />
|
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
<title>Settings — Jimi Gallery Admin</title>
|
|
<link
|
|
href="https://fonts.googleapis.com/css2?family=Cinzel:wght@500;600&family=Cormorant+Garamond:wght@400;500;600&family=Inter:wght@300;400;500&display=swap"
|
|
rel="stylesheet"
|
|
/>
|
|
<link rel="stylesheet" href="admin.css" />
|
|
</head>
|
|
<body>
|
|
<div class="app">
|
|
<div id="sidebar-slot"></div>
|
|
<div class="content">
|
|
<div class="topbar">
|
|
<div>
|
|
<h1 id="pg-title"></h1>
|
|
<div class="subtitle" id="pg-sub"></div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="panel">
|
|
<form id="form" class="form">
|
|
<div>
|
|
<label id="lbl-gn"></label>
|
|
<input id="f-galleryName" />
|
|
</div>
|
|
<div>
|
|
<label id="lbl-tagline"></label>
|
|
<div id="f-tagline-wrap"></div>
|
|
</div>
|
|
<div class="full">
|
|
<label id="lbl-address"></label>
|
|
<input id="f-address" />
|
|
</div>
|
|
<div>
|
|
<label id="lbl-phone"></label>
|
|
<input id="f-phone" />
|
|
</div>
|
|
<div>
|
|
<label id="lbl-email"></label>
|
|
<input id="f-email" />
|
|
</div>
|
|
<div class="full">
|
|
<label id="lbl-hours"></label>
|
|
<div id="f-hours-wrap"></div>
|
|
</div>
|
|
<div>
|
|
<label id="lbl-ig"></label>
|
|
<input id="f-instagram" />
|
|
</div>
|
|
<div class="full">
|
|
<label id="lbl-about"></label>
|
|
<div id="f-about-wrap"></div>
|
|
</div>
|
|
<div class="actions">
|
|
<button type="submit" class="btn" id="btn-save"></button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<script src="../assets/i18n.js"></script>
|
|
<script src="../assets/data.js"></script>
|
|
<script src="admin.js"></script>
|
|
<script>
|
|
(async () => {
|
|
requireAuth();
|
|
try { await Store.load(); } catch (e) { return showBootError(e); }
|
|
mountSidebar("settings");
|
|
|
|
document.getElementById("pg-title").textContent = t("admin.page.settings");
|
|
document.getElementById("pg-sub").textContent = t("admin.page.settings_sub");
|
|
document.getElementById("lbl-gn").textContent = t("admin.form.gallery_name");
|
|
document.getElementById("lbl-tagline").textContent = t("admin.form.tagline");
|
|
document.getElementById("lbl-address").textContent = t("admin.form.address");
|
|
document.getElementById("lbl-phone").textContent = t("admin.form.phone");
|
|
document.getElementById("lbl-email").textContent = t("admin.form.email");
|
|
document.getElementById("lbl-hours").textContent = t("admin.form.hours");
|
|
document.getElementById("lbl-ig").textContent = t("admin.form.instagram");
|
|
document.getElementById("lbl-about").textContent = t("admin.form.about");
|
|
document.getElementById("btn-save").textContent = t("admin.btn.save_changes");
|
|
|
|
const s = Store.settings();
|
|
document.getElementById("f-galleryName").value = s.galleryName || "";
|
|
document.getElementById("f-address").value = s.address || "";
|
|
document.getElementById("f-phone").value = s.phone || "";
|
|
document.getElementById("f-email").value = s.email || "";
|
|
document.getElementById("f-instagram").value = s.instagram || "";
|
|
|
|
const fTagline = mountMultilingualField(document.getElementById("f-tagline-wrap"), {
|
|
type: "input",
|
|
value: s.tagline || ""
|
|
});
|
|
const fHours = mountMultilingualField(document.getElementById("f-hours-wrap"), {
|
|
type: "input",
|
|
value: s.hours || ""
|
|
});
|
|
const fAbout = mountMultilingualField(document.getElementById("f-about-wrap"), {
|
|
type: "textarea",
|
|
value: s.about || "",
|
|
minHeight: "180px"
|
|
});
|
|
|
|
document.getElementById("form").addEventListener("submit", async (ev) => {
|
|
ev.preventDefault();
|
|
try {
|
|
await Store.updateSettings({
|
|
galleryName: document.getElementById("f-galleryName").value.trim(),
|
|
tagline: fTagline.get(),
|
|
address: document.getElementById("f-address").value.trim(),
|
|
phone: document.getElementById("f-phone").value.trim(),
|
|
email: document.getElementById("f-email").value.trim(),
|
|
hours: fHours.get(),
|
|
instagram: document.getElementById("f-instagram").value.trim(),
|
|
about: fAbout.get()
|
|
});
|
|
toast(t("admin.toast.settings_saved"));
|
|
} catch (err) { alert(err.message || err); }
|
|
});
|
|
})();
|
|
</script>
|
|
</body>
|
|
</html>
|