Add sync action dropdowns

This commit is contained in:
DonVoo 2026-07-13 12:52:12 +02:00
parent f612454e5b
commit 181a91c660
3 changed files with 102 additions and 18 deletions

View file

@ -128,8 +128,8 @@ func renderStartPage(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, `<!doctype html><html lang="de"><head><meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>Mail-Graveyard</title>
<link rel="stylesheet" href="/static/style.css?v=20260713-13">
<script src="/static/app.js?v=20260713-13" defer></script></head>
<link rel="stylesheet" href="/static/style.css?v=20260713-14">
<script src="/static/app.js?v=20260713-14" defer></script></head>
<body class="ol2013">
<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>
@ -176,9 +176,9 @@ func renderShell(w http.ResponseWriter, r *http.Request, active, readingPane str
fmt.Fprintf(w, `<!doctype html><html lang="de"><head><meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>Mail-Graveyard</title>
<link rel="stylesheet" href="/static/style.css?v=20260713-13">
<link rel="stylesheet" href="/static/style.css?v=20260713-14">
<script src="/static/htmx.min.js"></script>
<script src="/static/app.js?v=20260713-13" defer></script></head>
<script src="/static/app.js?v=20260713-14" defer></script></head>
<body class="ol2013">
<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>
@ -752,9 +752,9 @@ func renderAccountsPage(w http.ResponseWriter, r *http.Request, accounts []Accou
fmt.Fprintf(w, `<!doctype html><html lang="de"><head><meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>Konten-Verwaltung - Mail-Graveyard</title>
<link rel="stylesheet" href="/static/style.css?v=20260713-13">
<link rel="stylesheet" href="/static/style.css?v=20260713-14">
<script src="/static/htmx.min.js"></script>
<script src="/static/app.js?v=20260713-13" defer></script></head>
<script src="/static/app.js?v=20260713-14" defer></script></head>
<body class="ol2013">
<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>
@ -798,9 +798,9 @@ func renderArchivesPage(w http.ResponseWriter, r *http.Request, archives []strin
fmt.Fprintf(w, `<!doctype html><html lang="de"><head><meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>Archiv-mbox Verwaltung - Mail-Graveyard</title>
<link rel="stylesheet" href="/static/style.css?v=20260713-13">
<link rel="stylesheet" href="/static/style.css?v=20260713-14">
<script src="/static/htmx.min.js"></script>
<script src="/static/app.js?v=20260713-13" defer></script></head>
<script src="/static/app.js?v=20260713-14" defer></script></head>
<body class="ol2013">
<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>
@ -846,9 +846,9 @@ func renderUsersPage(w http.ResponseWriter, r *http.Request, users []AppUser, ed
fmt.Fprintf(w, `<!doctype html><html lang="de"><head><meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>Benutzerverwaltung - Mail-Graveyard</title>
<link rel="stylesheet" href="/static/style.css?v=20260713-13">
<link rel="stylesheet" href="/static/style.css?v=20260713-14">
<script src="/static/htmx.min.js"></script>
<script src="/static/app.js?v=20260713-13" defer></script></head>
<script src="/static/app.js?v=20260713-14" defer></script></head>
<body class="ol2013">
<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>
@ -920,9 +920,9 @@ func renderTransferPage(w http.ResponseWriter, r *http.Request, mode transferMod
fmt.Fprintf(w, `<!doctype html><html lang="de"><head><meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>%s - Mail-Graveyard</title>
<link rel="stylesheet" href="/static/style.css?v=20260713-13">
<link rel="stylesheet" href="/static/style.css?v=20260713-14">
<script src="/static/htmx.min.js"></script>
<script src="/static/app.js?v=20260713-13" defer></script></head>
<script src="/static/app.js?v=20260713-14" defer></script></head>
<body class="ol2013">
<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>
@ -1372,9 +1372,9 @@ func renderSourceEmailBoxPage(w http.ResponseWriter, r *http.Request, accounts [
fmt.Fprintf(w, `<!doctype html><html lang="de"><head><meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>Quell-Postfach - Mail-Graveyard</title>
<link rel="stylesheet" href="/static/style.css?v=20260713-13">
<link rel="stylesheet" href="/static/style.css?v=20260713-14">
<script src="/static/htmx.min.js"></script>
<script src="/static/app.js?v=20260713-13" defer></script></head>
<script src="/static/app.js?v=20260713-14" defer></script></head>
<body class="ol2013">
<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>
@ -1416,9 +1416,9 @@ func renderTargetEmailBoxPage(w http.ResponseWriter, r *http.Request, accounts [
fmt.Fprintf(w, `<!doctype html><html lang="de"><head><meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>Ziel-Postfach - Mail-Graveyard</title>
<link rel="stylesheet" href="/static/style.css?v=20260713-13">
<link rel="stylesheet" href="/static/style.css?v=20260713-14">
<script src="/static/htmx.min.js"></script>
<script src="/static/app.js?v=20260713-13" defer></script></head>
<script src="/static/app.js?v=20260713-14" defer></script></head>
<body class="ol2013">
<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>

View file

@ -17,8 +17,22 @@
<button class="action-btn" type="button" data-action-forward><span aria-hidden="true">&#x21AA;</span> Weiterleiten</button>
<button class="action-btn muted" type="button" disabled><span aria-hidden="true">&#x232B;</span> Loeschen</button>
<span class="action-separator"></span>
<button class="action-btn muted" type="button" disabled><span aria-hidden="true">&#x21C4;</span> Ordner Sync</button>
<button class="action-btn muted" type="button" disabled><span aria-hidden="true">&#x2709;</span> Email-Sync</button>
<div class="action-menu">
<button class="action-btn action-menu-button" type="button" aria-expanded="false" data-action-menu-toggle><span aria-hidden="true">&#x21C4;</span> Ordner Sync</button>
<div class="action-dropdown">
<button type="button" class="action-dropdown-item" data-sync-kind="folder" data-sync-direction="push">Ordner --&gt; Ordner</button>
<button type="button" class="action-dropdown-item" data-sync-kind="folder" data-sync-direction="both">Ordner &lt;--&gt; Ordner</button>
<button type="button" class="action-dropdown-item" data-sync-kind="folder" data-sync-direction="pull">Ordner &lt;-- Ordner</button>
</div>
</div>
<div class="action-menu">
<button class="action-btn action-menu-button" type="button" aria-expanded="false" data-action-menu-toggle><span aria-hidden="true">&#x2709;</span> Email-Sync</button>
<div class="action-dropdown">
<button type="button" class="action-dropdown-item" data-sync-kind="email" data-sync-direction="push">Email --&gt; Email</button>
<button type="button" class="action-dropdown-item" data-sync-kind="email" data-sync-direction="both">Email &lt;--&gt; Email</button>
<button type="button" class="action-dropdown-item" data-sync-kind="email" data-sync-direction="pull">Email &lt;-- Email</button>
</div>
</div>
`;
ribbon.insertAdjacentElement("afterend", bar);
}
@ -113,6 +127,13 @@
}
document.addEventListener("DOMContentLoaded", ensureActionBar);
function closeActionMenus() {
document.querySelectorAll(".action-menu.open").forEach((menu) => {
menu.classList.remove("open");
menu.querySelector("[data-action-menu-toggle]")?.setAttribute("aria-expanded", "false");
});
}
document.addEventListener("click", (event) => {
const row = event.target.closest(".msg-row");
if (!row) return;
@ -120,6 +141,22 @@
row.classList.add("active");
});
document.addEventListener("click", (event) => {
const menuButton = event.target.closest("[data-action-menu-toggle]");
if (menuButton) {
const menu = menuButton.closest(".action-menu");
const willOpen = !menu.classList.contains("open");
closeActionMenus();
menu.classList.toggle("open", willOpen);
menuButton.setAttribute("aria-expanded", willOpen ? "true" : "false");
return;
}
if (!event.target.closest(".action-menu")) closeActionMenus();
const syncItem = event.target.closest("[data-sync-kind]");
if (syncItem) {
closeActionMenus();
window.alert("Sync-Funktion ist vorbereitet, aber noch nicht aktiv.");
return;
}
if (event.target.closest("[data-action-new]")) {
openCompose({ to: "", subject: "", body: "" });
}

View file

@ -239,6 +239,53 @@ body.ol2013 {
background: transparent;
border-color: transparent;
}
.action-menu {
position: relative;
height: 30px;
flex: 0 0 auto;
}
.action-menu-button::after {
content: "";
width: 0;
height: 0;
margin-left: 2px;
border-left: 4px solid transparent;
border-right: 4px solid transparent;
border-top: 5px solid currentColor;
}
.action-menu.open .action-menu-button {
background: var(--ol-blue-dark);
border-color: #4f94ca;
}
.action-dropdown {
position: absolute;
top: 34px;
left: 0;
min-width: 190px;
display: none;
padding: 4px 0;
background: #fff;
color: var(--ol-text);
border: 1px solid var(--ol-border);
box-shadow: 0 8px 20px rgba(0, 0, 0, .22);
z-index: 45;
}
.action-menu.open .action-dropdown { display: block; }
.action-dropdown-item {
width: 100%;
display: block;
padding: 8px 12px;
border: 0;
background: transparent;
color: var(--ol-text);
font: inherit;
text-align: left;
cursor: pointer;
}
.action-dropdown-item:hover {
background: #eef6fd;
color: var(--ol-blue-dark);
}
.action-separator {
width: 1px;
height: 26px;