Add top transfer dropdown
This commit is contained in:
parent
6675e73b0f
commit
e8fc294c5d
3 changed files with 113 additions and 16 deletions
|
|
@ -57,15 +57,15 @@ func renderShell(w http.ResponseWriter, active, readingPane string) {
|
||||||
fmt.Fprintf(w, `<!doctype html><html lang="de"><head><meta charset="utf-8">
|
fmt.Fprintf(w, `<!doctype html><html lang="de"><head><meta charset="utf-8">
|
||||||
<meta name="viewport" content="width=device-width,initial-scale=1">
|
<meta name="viewport" content="width=device-width,initial-scale=1">
|
||||||
<title>Mail-Graveyard</title>
|
<title>Mail-Graveyard</title>
|
||||||
<link rel="stylesheet" href="/static/style.css?v=20260712-11">
|
<link rel="stylesheet" href="/static/style.css?v=20260712-12">
|
||||||
<script src="/static/htmx.min.js"></script>
|
<script src="/static/htmx.min.js"></script>
|
||||||
<script src="/static/app.js?v=20260712-11" defer></script></head>
|
<script src="/static/app.js?v=20260712-12" defer></script></head>
|
||||||
<body class="ol2013">
|
<body class="ol2013">
|
||||||
<header class="ribbon">
|
<header class="ribbon">
|
||||||
<button class="app-menu-button" type="button" aria-label="Mail-Graveyard-Menue" aria-expanded="false" data-backstage-toggle><span class="mail-logo" aria-hidden="true"></span></button>
|
<button class="app-menu-button" type="button" aria-label="Mail-Graveyard-Menue" aria-expanded="false" data-backstage-toggle><span class="mail-logo" aria-hidden="true"></span></button>
|
||||||
<nav class="ribbon-tabs">
|
<nav class="ribbon-tabs">
|
||||||
<a class="tab %s" href="/view">Archiv-Boxen</a>
|
<a class="tab %s" href="/view">Archiv-Boxen</a>
|
||||||
<a class="tab" href="/transfer/postfach-archiv">Mail-Transfer</a>
|
%s
|
||||||
<a class="tab" href="/accounts">Einstellungen</a>
|
<a class="tab" href="/accounts">Einstellungen</a>
|
||||||
</nav>
|
</nav>
|
||||||
<div class="ribbon-title">Mail-Graveyard</div>
|
<div class="ribbon-title">Mail-Graveyard</div>
|
||||||
|
|
@ -98,7 +98,7 @@ func renderShell(w http.ResponseWriter, active, readingPane string) {
|
||||||
</div>
|
</div>
|
||||||
<footer class="statusbar"><span id="mig-status"
|
<footer class="statusbar"><span id="mig-status"
|
||||||
hx-get="/migrate/status" hx-trigger="every 3s" hx-swap="innerHTML">bereit</span></footer>
|
hx-get="/migrate/status" hx-trigger="every 3s" hx-swap="innerHTML">bereit</span></footer>
|
||||||
</body></html>`, active, renderInitialReadPane(readingPane))
|
</body></html>`, active, renderRibbonTransferMenu(""), renderInitialReadPane(readingPane))
|
||||||
}
|
}
|
||||||
|
|
||||||
func accountsHandler(w http.ResponseWriter, r *http.Request) {
|
func accountsHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
@ -312,15 +312,15 @@ func renderAccountsPage(w http.ResponseWriter, accounts []Account, edit Account,
|
||||||
fmt.Fprintf(w, `<!doctype html><html lang="de"><head><meta charset="utf-8">
|
fmt.Fprintf(w, `<!doctype html><html lang="de"><head><meta charset="utf-8">
|
||||||
<meta name="viewport" content="width=device-width,initial-scale=1">
|
<meta name="viewport" content="width=device-width,initial-scale=1">
|
||||||
<title>Konten-Verwaltung - Mail-Graveyard</title>
|
<title>Konten-Verwaltung - Mail-Graveyard</title>
|
||||||
<link rel="stylesheet" href="/static/style.css?v=20260712-11">
|
<link rel="stylesheet" href="/static/style.css?v=20260712-12">
|
||||||
<script src="/static/htmx.min.js"></script>
|
<script src="/static/htmx.min.js"></script>
|
||||||
<script src="/static/app.js?v=20260712-11" defer></script></head>
|
<script src="/static/app.js?v=20260712-12" defer></script></head>
|
||||||
<body class="ol2013">
|
<body class="ol2013">
|
||||||
<header class="ribbon">
|
<header class="ribbon">
|
||||||
<button class="app-menu-button" type="button" aria-label="Mail-Graveyard-Menue" aria-expanded="false" data-backstage-toggle><span class="mail-logo" aria-hidden="true"></span></button>
|
<button class="app-menu-button" type="button" aria-label="Mail-Graveyard-Menue" aria-expanded="false" data-backstage-toggle><span class="mail-logo" aria-hidden="true"></span></button>
|
||||||
<nav class="ribbon-tabs">
|
<nav class="ribbon-tabs">
|
||||||
<a class="tab" href="/view">Archiv-Boxen</a>
|
<a class="tab" href="/view">Archiv-Boxen</a>
|
||||||
<a class="tab" href="/transfer/postfach-archiv">Mail-Transfer</a>
|
%s
|
||||||
<a class="tab" href="/accounts">Einstellungen</a>
|
<a class="tab" href="/accounts">Einstellungen</a>
|
||||||
</nav>
|
</nav>
|
||||||
<div class="ribbon-title">Mail-Graveyard</div>
|
<div class="ribbon-title">Mail-Graveyard</div>
|
||||||
|
|
@ -337,7 +337,7 @@ func renderAccountsPage(w http.ResponseWriter, accounts []Account, edit Account,
|
||||||
<a class="backstage-item" href="/accounts">Einstellungen</a>
|
<a class="backstage-item" href="/accounts">Einstellungen</a>
|
||||||
</aside>
|
</aside>
|
||||||
<button class="backstage-shade" type="button" aria-label="Menue schliessen" data-backstage-close></button>
|
<button class="backstage-shade" type="button" aria-label="Menue schliessen" data-backstage-close></button>
|
||||||
<main class="accounts-page">`)
|
<main class="accounts-page">`, renderRibbonTransferMenu(""))
|
||||||
if msg != "" {
|
if msg != "" {
|
||||||
fmt.Fprintf(w, `<div class="notice ok">%s</div>`, html.EscapeString(msg))
|
fmt.Fprintf(w, `<div class="notice ok">%s</div>`, html.EscapeString(msg))
|
||||||
}
|
}
|
||||||
|
|
@ -356,15 +356,15 @@ func renderArchivesPage(w http.ResponseWriter, archives []string, accounts []Acc
|
||||||
fmt.Fprintf(w, `<!doctype html><html lang="de"><head><meta charset="utf-8">
|
fmt.Fprintf(w, `<!doctype html><html lang="de"><head><meta charset="utf-8">
|
||||||
<meta name="viewport" content="width=device-width,initial-scale=1">
|
<meta name="viewport" content="width=device-width,initial-scale=1">
|
||||||
<title>Archiv-mbox Verwaltung - Mail-Graveyard</title>
|
<title>Archiv-mbox Verwaltung - Mail-Graveyard</title>
|
||||||
<link rel="stylesheet" href="/static/style.css?v=20260712-11">
|
<link rel="stylesheet" href="/static/style.css?v=20260712-12">
|
||||||
<script src="/static/htmx.min.js"></script>
|
<script src="/static/htmx.min.js"></script>
|
||||||
<script src="/static/app.js?v=20260712-11" defer></script></head>
|
<script src="/static/app.js?v=20260712-12" defer></script></head>
|
||||||
<body class="ol2013">
|
<body class="ol2013">
|
||||||
<header class="ribbon">
|
<header class="ribbon">
|
||||||
<button class="app-menu-button" type="button" aria-label="Mail-Graveyard-Menue" aria-expanded="false" data-backstage-toggle><span class="mail-logo" aria-hidden="true"></span></button>
|
<button class="app-menu-button" type="button" aria-label="Mail-Graveyard-Menue" aria-expanded="false" data-backstage-toggle><span class="mail-logo" aria-hidden="true"></span></button>
|
||||||
<nav class="ribbon-tabs">
|
<nav class="ribbon-tabs">
|
||||||
<a class="tab" href="/view">Archiv-Boxen</a>
|
<a class="tab" href="/view">Archiv-Boxen</a>
|
||||||
<a class="tab" href="/transfer/postfach-archiv">Mail-Transfer</a>
|
%s
|
||||||
<a class="tab" href="/accounts">Einstellungen</a>
|
<a class="tab" href="/accounts">Einstellungen</a>
|
||||||
</nav>
|
</nav>
|
||||||
<div class="ribbon-title">Mail-Graveyard</div>
|
<div class="ribbon-title">Mail-Graveyard</div>
|
||||||
|
|
@ -381,7 +381,7 @@ func renderArchivesPage(w http.ResponseWriter, archives []string, accounts []Acc
|
||||||
<a class="backstage-item" href="/accounts">Einstellungen</a>
|
<a class="backstage-item" href="/accounts">Einstellungen</a>
|
||||||
</aside>
|
</aside>
|
||||||
<button class="backstage-shade" type="button" aria-label="Menue schliessen" data-backstage-close></button>
|
<button class="backstage-shade" type="button" aria-label="Menue schliessen" data-backstage-close></button>
|
||||||
<main class="accounts-page archive-page">`)
|
<main class="accounts-page archive-page">`, renderRibbonTransferMenu(""))
|
||||||
if msg != "" {
|
if msg != "" {
|
||||||
fmt.Fprintf(w, `<div class="notice ok">%s</div>`, html.EscapeString(msg))
|
fmt.Fprintf(w, `<div class="notice ok">%s</div>`, html.EscapeString(msg))
|
||||||
}
|
}
|
||||||
|
|
@ -423,15 +423,15 @@ func renderTransferPage(w http.ResponseWriter, mode transferMode, accounts []Acc
|
||||||
fmt.Fprintf(w, `<!doctype html><html lang="de"><head><meta charset="utf-8">
|
fmt.Fprintf(w, `<!doctype html><html lang="de"><head><meta charset="utf-8">
|
||||||
<meta name="viewport" content="width=device-width,initial-scale=1">
|
<meta name="viewport" content="width=device-width,initial-scale=1">
|
||||||
<title>%s - Mail-Graveyard</title>
|
<title>%s - Mail-Graveyard</title>
|
||||||
<link rel="stylesheet" href="/static/style.css?v=20260712-11">
|
<link rel="stylesheet" href="/static/style.css?v=20260712-12">
|
||||||
<script src="/static/htmx.min.js"></script>
|
<script src="/static/htmx.min.js"></script>
|
||||||
<script src="/static/app.js?v=20260712-11" defer></script></head>
|
<script src="/static/app.js?v=20260712-12" defer></script></head>
|
||||||
<body class="ol2013">
|
<body class="ol2013">
|
||||||
<header class="ribbon">
|
<header class="ribbon">
|
||||||
<button class="app-menu-button" type="button" aria-label="Mail-Graveyard-Menue" aria-expanded="false" data-backstage-toggle><span class="mail-logo" aria-hidden="true"></span></button>
|
<button class="app-menu-button" type="button" aria-label="Mail-Graveyard-Menue" aria-expanded="false" data-backstage-toggle><span class="mail-logo" aria-hidden="true"></span></button>
|
||||||
<nav class="ribbon-tabs">
|
<nav class="ribbon-tabs">
|
||||||
<a class="tab" href="/view">Archiv-Boxen</a>
|
<a class="tab" href="/view">Archiv-Boxen</a>
|
||||||
<a class="tab active" href="/transfer/postfach-archiv">Mail-Transfer</a>
|
%s
|
||||||
<a class="tab" href="/accounts">Einstellungen</a>
|
<a class="tab" href="/accounts">Einstellungen</a>
|
||||||
</nav>
|
</nav>
|
||||||
<div class="ribbon-title">Mail-Graveyard</div>
|
<div class="ribbon-title">Mail-Graveyard</div>
|
||||||
|
|
@ -453,7 +453,7 @@ func renderTransferPage(w http.ResponseWriter, mode transferMode, accounts []Acc
|
||||||
</section>
|
</section>
|
||||||
</main>
|
</main>
|
||||||
<footer class="statusbar"><span id="mig-status" hx-get="/migrate/status" hx-trigger="load,every 3s" hx-swap="innerHTML">bereit</span></footer></body></html>`,
|
<footer class="statusbar"><span id="mig-status" hx-get="/migrate/status" hx-trigger="load,every 3s" hx-swap="innerHTML">bereit</span></footer></body></html>`,
|
||||||
html.EscapeString(mode.Title), transferMenuItems(mode.Slug),
|
html.EscapeString(mode.Title), renderRibbonTransferMenu(mode.Slug), transferMenuItems(mode.Slug),
|
||||||
html.EscapeString(mode.LeftTitle), renderTransferPicker(mode.LeftKind, accounts, archives),
|
html.EscapeString(mode.LeftTitle), renderTransferPicker(mode.LeftKind, accounts, archives),
|
||||||
html.EscapeString(mode.RightTitle), renderTransferPicker(mode.RightKind, accounts, archives))
|
html.EscapeString(mode.RightTitle), renderTransferPicker(mode.RightKind, accounts, archives))
|
||||||
}
|
}
|
||||||
|
|
@ -475,6 +475,29 @@ func transferMenuItems(active string) string {
|
||||||
return b.String()
|
return b.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func renderRibbonTransferMenu(active string) string {
|
||||||
|
items := []transferMode{
|
||||||
|
{Slug: "postfach-archiv", Title: "Postfach <--> Archiv-MBox"},
|
||||||
|
{Slug: "archiv-postfach", Title: "Archiv-MBox <--> Postfach"},
|
||||||
|
{Slug: "postfach-postfach", Title: "Postfach <--> Postfach"},
|
||||||
|
}
|
||||||
|
buttonClass := "tab ribbon-menu-button"
|
||||||
|
if active != "" {
|
||||||
|
buttonClass += " active"
|
||||||
|
}
|
||||||
|
var b strings.Builder
|
||||||
|
fmt.Fprintf(&b, `<div class="ribbon-menu"><button class="%s" type="button" aria-expanded="false" data-ribbon-menu-toggle>Mail-Transfer</button><div class="ribbon-dropdown">`, buttonClass)
|
||||||
|
for _, item := range items {
|
||||||
|
class := "ribbon-dropdown-item"
|
||||||
|
if item.Slug == active {
|
||||||
|
class += " active"
|
||||||
|
}
|
||||||
|
fmt.Fprintf(&b, `<a class="%s" href="/transfer/%s">%s</a>`, class, item.Slug, html.EscapeString(item.Title))
|
||||||
|
}
|
||||||
|
b.WriteString(`</div></div>`)
|
||||||
|
return b.String()
|
||||||
|
}
|
||||||
|
|
||||||
func renderTransferPicker(kind string, accounts []Account, archives []string) string {
|
func renderTransferPicker(kind string, accounts []Account, archives []string) string {
|
||||||
var b strings.Builder
|
var b strings.Builder
|
||||||
b.WriteString(`<div class="transfer-picker">`)
|
b.WriteString(`<div class="transfer-picker">`)
|
||||||
|
|
|
||||||
27
frontend-js/dist/app.js
vendored
27
frontend-js/dist/app.js
vendored
|
|
@ -93,6 +93,33 @@
|
||||||
window.addEventListener("DOMContentLoaded", () => bind(document.querySelector(".three-pane")));
|
window.addEventListener("DOMContentLoaded", () => bind(document.querySelector(".three-pane")));
|
||||||
})();
|
})();
|
||||||
|
|
||||||
|
(function () {
|
||||||
|
function closeAll() {
|
||||||
|
document.querySelectorAll(".ribbon-menu.open").forEach((menu) => {
|
||||||
|
menu.classList.remove("open");
|
||||||
|
const button = menu.querySelector("[data-ribbon-menu-toggle]");
|
||||||
|
if (button) button.setAttribute("aria-expanded", "false");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
document.addEventListener("click", (event) => {
|
||||||
|
const button = event.target.closest("[data-ribbon-menu-toggle]");
|
||||||
|
if (button) {
|
||||||
|
const menu = button.closest(".ribbon-menu");
|
||||||
|
const willOpen = !menu.classList.contains("open");
|
||||||
|
closeAll();
|
||||||
|
menu.classList.toggle("open", willOpen);
|
||||||
|
button.setAttribute("aria-expanded", willOpen ? "true" : "false");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!event.target.closest(".ribbon-menu")) closeAll();
|
||||||
|
});
|
||||||
|
|
||||||
|
document.addEventListener("keydown", (event) => {
|
||||||
|
if (event.key === "Escape") closeAll();
|
||||||
|
});
|
||||||
|
})();
|
||||||
|
|
||||||
(function () {
|
(function () {
|
||||||
function setOpen(open) {
|
function setOpen(open) {
|
||||||
document.body.classList.toggle("backstage-open", open);
|
document.body.classList.toggle("backstage-open", open);
|
||||||
|
|
|
||||||
47
frontend-js/dist/style.css
vendored
47
frontend-js/dist/style.css
vendored
|
|
@ -60,9 +60,56 @@ body.ol2013 {
|
||||||
padding: 0 16px; height: 100%;
|
padding: 0 16px; height: 100%;
|
||||||
color: #eaf3fb; text-decoration: none;
|
color: #eaf3fb; text-decoration: none;
|
||||||
border-bottom: 3px solid transparent;
|
border-bottom: 3px solid transparent;
|
||||||
|
background: transparent;
|
||||||
|
border-left: 0;
|
||||||
|
border-right: 0;
|
||||||
|
border-top: 0;
|
||||||
|
font: inherit;
|
||||||
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
.tab:hover { background: var(--ol-blue-dark); color: #fff; }
|
.tab:hover { background: var(--ol-blue-dark); color: #fff; }
|
||||||
.tab.active { background: #fff; color: var(--ol-blue); border-bottom-color: #fff; }
|
.tab.active { background: #fff; color: var(--ol-blue); border-bottom-color: #fff; }
|
||||||
|
.ribbon-menu {
|
||||||
|
position: relative;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
.ribbon-menu-button::after {
|
||||||
|
content: "";
|
||||||
|
width: 0;
|
||||||
|
height: 0;
|
||||||
|
border-left: 4px solid transparent;
|
||||||
|
border-right: 4px solid transparent;
|
||||||
|
border-top: 5px solid currentColor;
|
||||||
|
}
|
||||||
|
.ribbon-dropdown {
|
||||||
|
position: absolute;
|
||||||
|
top: 44px;
|
||||||
|
left: 0;
|
||||||
|
min-width: 238px;
|
||||||
|
background: #fff;
|
||||||
|
color: var(--ol-text);
|
||||||
|
border: 1px solid var(--ol-border);
|
||||||
|
box-shadow: 0 7px 18px rgba(0, 0, 0, .18);
|
||||||
|
display: none;
|
||||||
|
z-index: 25;
|
||||||
|
}
|
||||||
|
.ribbon-menu.open .ribbon-dropdown { display: block; }
|
||||||
|
.ribbon-dropdown-item {
|
||||||
|
display: block;
|
||||||
|
padding: 9px 13px;
|
||||||
|
color: var(--ol-text);
|
||||||
|
text-decoration: none;
|
||||||
|
border-left: 3px solid transparent;
|
||||||
|
}
|
||||||
|
.ribbon-dropdown-item:hover {
|
||||||
|
background: #eef6fd;
|
||||||
|
}
|
||||||
|
.ribbon-dropdown-item.active {
|
||||||
|
color: var(--ol-blue-dark);
|
||||||
|
background: var(--ol-sel);
|
||||||
|
border-left-color: var(--ol-blue);
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
.mail-logo {
|
.mail-logo {
|
||||||
position: relative;
|
position: relative;
|
||||||
width: 17px;
|
width: 17px;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue