thunderbird2docuware/options/options.html
sylyx 81964c76d3 Mapping: feste Werte ({const}) + Teilen via JSON-Copy/Paste und Pull von raw-JSON-URL (mappingUrl)
- prefillFor löst Token-String ODER {const:...} auf; Options-Editor mit
  'Fester Wert'-Option + Konstanten-Eingabe.
- Feld-Zuordnung: JSON exportieren/anwenden/kopieren, von URL laden (Gitea/GitHub raw).
- Fix: zwei Statustexte mit ASCII-Quote in " gehärtet.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-16 15:01:37 +02:00

265 lines
12 KiB
HTML
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="utf-8" />
<title>DocuWare Ablage Einstellungen</title>
<style>
/* DocuWare-naher Dark-Style: tiefes Slate, DocuWare-Blau als Akzent. */
:root {
--bg: #11151b;
--bg-grad: radial-gradient(1200px 500px at 80% -10%, #18324a 0%, rgba(17,21,27,0) 60%);
--surface: #1a1f27;
--surface-2: #222a34;
--border: #2b3340;
--border-strong: #38424f;
--text: #e8edf2;
--muted: #8c97a4;
--accent: #2aa4df; /* DocuWare-Blau */
--accent-hover: #3cb6f0;
--accent-weak: rgba(42,164,223,.14);
--ok: #46c98a;
--err: #ec6b75;
--radius: 10px;
--shadow: 0 1px 0 rgba(255,255,255,.02) inset, 0 8px 24px rgba(0,0,0,.28);
font-synthesis: none;
}
* { box-sizing: border-box; }
html, body { background: var(--bg); }
body {
font: 14px/1.55 "Segoe UI", "Helvetica Neue", system-ui, sans-serif;
color: var(--text);
margin: 0;
padding: 0 16px 120px;
background-image: var(--bg-grad);
background-repeat: no-repeat;
-webkit-font-smoothing: antialiased;
}
.wrap { max-width: 620px; margin: 0 auto; }
/* Kopfzeile */
header.app {
display: flex; align-items: center; gap: 12px;
padding: 26px 2px 18px;
}
.logo {
width: 34px; height: 34px; border-radius: 8px; flex: none;
background: linear-gradient(135deg, var(--accent), #1c6fae);
display: grid; place-items: center;
box-shadow: 0 4px 14px rgba(42,164,223,.35);
}
.logo svg { width: 20px; height: 20px; }
header.app h1 { font-size: 18px; font-weight: 650; margin: 0; letter-spacing: .2px; }
header.app .sub { font-size: 12px; color: var(--muted); margin-top: 1px; }
/* Karten / Abschnitte */
section.card {
background: var(--surface);
border: 1px solid var(--border);
border-radius: var(--radius);
box-shadow: var(--shadow);
padding: 18px 20px 20px;
margin: 14px 0;
}
.card-head { display: flex; align-items: baseline; gap: 10px; margin: 0 0 6px; }
.card-head h2 {
font-size: 13px; font-weight: 650; text-transform: uppercase;
letter-spacing: .8px; color: var(--accent); margin: 0;
}
.card-head .num {
font-size: 11px; color: var(--muted); border: 1px solid var(--border-strong);
border-radius: 999px; padding: 1px 8px; line-height: 1.5;
}
label { display: block; margin: 14px 0 5px; font-weight: 550; font-size: 13px; }
input[type="text"], input[type="password"], input[type="url"], select {
width: 100%; padding: 9px 11px; color: var(--text);
background: var(--surface-2); border: 1px solid var(--border-strong);
border-radius: 8px; font: inherit; outline: none;
transition: border-color .15s, box-shadow .15s, background .15s;
}
select { appearance: none;
background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'><path d='M2 4l4 4 4-4' fill='none' stroke='%238c97a4' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'/></svg>");
background-repeat: no-repeat; background-position: right 11px center; padding-right: 30px;
}
input:focus, select:focus {
border-color: var(--accent);
box-shadow: 0 0 0 3px var(--accent-weak);
}
input::placeholder { color: #5f6b78; }
code { background: var(--surface-2); border: 1px solid var(--border); border-radius: 4px;
padding: 1px 5px; font-size: 12px; color: #b7c2cd; }
.hint { font-size: 12px; color: var(--muted); margin-top: 5px; }
.check { display: flex; align-items: center; gap: 9px; margin: 9px 0; font-weight: 450; }
.check label { margin: 0; font-weight: 450; font-size: 13px; }
input[type="checkbox"], input[type="radio"] { width: 16px; height: 16px; accent-color: var(--accent); flex: none; }
/* Mapping-Tabelle */
.map-toolbar { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin: 4px 0 12px; }
.map-toolbar .grow { flex: 1; min-width: 180px; }
table.map { width: 100%; border-collapse: separate; border-spacing: 0 6px; }
table.map th { text-align: left; font-size: 11px; letter-spacing: .4px; text-transform: uppercase;
color: var(--muted); font-weight: 600; padding: 0 6px 2px; }
table.map td { padding: 0 6px; vertical-align: middle; }
table.map input, table.map select { padding: 7px 9px; }
table.map td.del { width: 40px; }
.icon-btn {
width: 30px; height: 30px; padding: 0; border-radius: 7px; cursor: pointer;
background: var(--surface-2); border: 1px solid var(--border-strong); color: var(--muted);
font-size: 14px; line-height: 1; transition: .15s;
}
.icon-btn:hover { color: var(--err); border-color: var(--err); }
/* Teilen / JSON */
details.share { margin-top: 14px; border-top: 1px solid var(--border); padding-top: 10px; }
details.share summary {
cursor: pointer; font-size: 13px; font-weight: 600; color: var(--accent);
list-style: none; user-select: none; padding: 2px 0;
}
details.share summary::-webkit-details-marker { display: none; }
details.share summary::before { content: "▸ "; color: var(--muted); }
details.share[open] summary::before { content: "▾ "; }
textarea {
width: 100%; padding: 10px 11px; color: var(--text); background: var(--surface-2);
border: 1px solid var(--border-strong); border-radius: 8px; box-sizing: border-box;
font: 12px/1.45 ui-monospace, "Cascadia Code", Consolas, monospace; resize: vertical; outline: none;
}
textarea:focus { border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-weak); }
/* Buttons */
button { font: inherit; cursor: pointer; border-radius: 8px; }
button.primary {
padding: 9px 18px; border: 0; font-weight: 650; color: #04222f;
background: linear-gradient(180deg, var(--accent-hover), var(--accent));
box-shadow: 0 4px 14px rgba(42,164,223,.3);
}
button.primary:hover { filter: brightness(1.06); }
button.ghost {
padding: 8px 15px; font-weight: 550; color: var(--text);
background: var(--surface-2); border: 1px solid var(--border-strong);
}
button.ghost:hover { border-color: var(--accent); color: var(--accent); }
button:disabled { opacity: .5; cursor: default; }
/* Sticky Aktionsleiste */
.actionbar {
position: fixed; left: 0; right: 0; bottom: 0; z-index: 5;
background: rgba(17,21,27,.82); backdrop-filter: blur(8px);
border-top: 1px solid var(--border);
}
.actionbar .inner { max-width: 620px; margin: 0 auto; padding: 12px 16px;
display: flex; align-items: center; gap: 12px; }
#status { font-size: 13px; min-height: 18px; }
.ok { color: var(--ok); } .err { color: var(--err); }
.spacer { flex: 1; }
</style>
</head>
<body>
<div class="wrap">
<header class="app">
<span class="logo" aria-hidden="true">
<svg viewBox="0 0 24 24" fill="none"><path d="M4 5.5A1.5 1.5 0 0 1 5.5 4H13l3 3h2.5A1.5 1.5 0 0 1 20 8.5v10A1.5 1.5 0 0 1 18.5 20h-13A1.5 1.5 0 0 1 4 18.5v-13Z" fill="#fff" opacity=".95"/><path d="M9 13.5h6M12 11v5" stroke="#1c6fae" stroke-width="1.6" stroke-linecap="round"/></svg>
</span>
<div>
<h1>DocuWare Ablage</h1>
<div class="sub">Einstellungen</div>
</div>
</header>
<section class="card">
<div class="card-head"><span class="num">1</span><h2>Verbindung</h2></div>
<label for="serverUrl">Server-URL</label>
<input type="url" id="serverUrl" placeholder="https://docuware.example.com" />
<div class="hint">Basis-URL ohne <code>/DocuWare/Platform</code>.</div>
<label for="organization">Organisation</label>
<input type="text" id="organization" />
<label for="username">Benutzername</label>
<input type="text" id="username" autocomplete="username" />
<label for="password">Passwort</label>
<input type="password" id="password" autocomplete="off" />
<div class="hint">Wird <strong>nicht gespeichert</strong> nur zum Anmelden/Testen für
diese Sitzung. Im Ablage-Fenster wird es 1× pro Sitzung abgefragt.</div>
</section>
<section class="card">
<div class="card-head"><span class="num">2</span><h2>Standardwerte</h2></div>
<label for="defaultCabinet">Standard-Ziel (Archiv oder Briefkorb)</label>
<select id="defaultCabinet"><option value="">— keiner —</option></select>
<div class="hint">Liste wird nach erfolgreichem Verbindungstest gefüllt.</div>
<label>Standard-Format der E-Mail</label>
<div class="check"><input type="radio" name="mailFormat" id="fmtEml" value="eml" /> <label for="fmtEml">Original (.eml)</label></div>
<div class="check"><input type="radio" name="mailFormat" id="fmtPdf" value="pdf" /> <label for="fmtPdf">PDF</label></div>
<div class="hint">Die E-Mail wird immer in genau einem Format abgelegt (nicht beides). Im Ablage-Fenster umstellbar.</div>
<div class="check" style="margin-top:12px"><input type="checkbox" id="storeAttachments" /> <label for="storeAttachments">Anhänge mit ablegen</label></div>
<div class="check"><input type="checkbox" id="tagOnSuccess" /> <label for="tagOnSuccess">Mail nach Ablage als „DocuWare" markieren</label></div>
</section>
<section class="card">
<div class="card-head"><span class="num">3</span><h2>Feld-Zuordnung</h2></div>
<div class="hint" style="margin-bottom:10px">Welches DocuWare-Indexfeld wird aus welchem
Mail-Attribut vorbefüllt? Gilt für alle Aktenschränke. Leere/entfernte Zeilen befüllen
nichts vor.</div>
<div class="map-toolbar">
<div class="grow">
<select id="mapCabinet"><option value="">Feldnamen aus Archiv vorschlagen …</option></select>
</div>
<span id="mapFieldStatus" class="hint" style="margin:0"></span>
</div>
<table class="map">
<thead><tr><th>DocuWare-Feldname</th><th>Mail-Attribut</th><th></th></tr></thead>
<tbody id="mapBody"></tbody>
</table>
<datalist id="fieldNames"></datalist>
<div class="map-toolbar" style="margin-top:10px">
<button id="mapAdd" class="ghost" type="button">+ Zeile</button>
<button id="mapReset" class="ghost" type="button">Auf Standard zurücksetzen</button>
</div>
<div class="hint" style="margin-top:8px">Als Mail-Attribut „<strong>Fester Wert</strong>"
wählen, um einen festen Text (z. B. <code>NEU</code>) ins Feld zu schreiben.</div>
<details class="share">
<summary>Mapping teilen / übernehmen</summary>
<label for="mappingUrl">Aus Repo/URL laden</label>
<div class="map-toolbar">
<input type="url" id="mappingUrl" class="grow" placeholder="https://gitea.example/…/mapping.json" />
<button id="mappingPull" class="ghost" type="button">Von URL laden</button>
</div>
<div class="hint">Eine raw-JSON-Datei aus einem Gitea/GitHub-Repo. Lädt das Mapping in
den Editor mit „Speichern" übernehmen. (Lesen/Pull; Zurückschreiben ins Repo nicht.)</div>
<label for="mappingJson">JSON (kopieren / einfügen)</label>
<textarea id="mappingJson" rows="6" placeholder='{ "EML_SUBJECT": "subject", "STATUS": { "const": "NEU" } }'></textarea>
<div class="map-toolbar">
<button id="mappingExport" class="ghost" type="button">Aktuelles als JSON</button>
<button id="mappingCopy" class="ghost" type="button">Kopieren</button>
<button id="mappingApply" class="ghost" type="button">JSON anwenden</button>
</div>
</details>
</section>
</div>
<div class="actionbar">
<div class="inner">
<button id="save" class="primary">Speichern</button>
<button id="test" class="ghost">Verbindung testen</button>
<span class="spacer"></span>
<span id="status"></span>
</div>
</div>
<script src="../lib/store.js"></script>
<script src="../lib/auth.js"></script>
<script src="../lib/docuware.js"></script>
<script src="options.js"></script>
</body>
</html>