thunderbird2docuware/options/options.js
sylyx 53d3675dc1 Feature: Mail-Format .eml ODER PDF (nicht beides) + konfigurierbares Feld-Mapping
- Dialog/Optionen: mailFormat-Radio (.eml/PDF) + eigener Anhänge-Haken statt
  scope/optPdf; nie mehr eml UND pdf gleichzeitig. Migration storeEml/storePdf.
- Feld-Zuordnung in den Einstellungen editierbar (MAIL_TOKENS/DEFAULT_FIELD_MAP
  in store.js); PREFILL -> TOKEN_FN + effectiveFieldMap/prefillFor.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-16 13:23:39 +02:00

204 lines
7.2 KiB
JavaScript
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.

// Logik der Einstellungsseite.
const $ = (id) => document.getElementById(id);
// Passwort ist bewusst NICHT dabei es wird nie gespeichert, nur zum Testen/Login
// transient verwendet (siehe "Verbindung testen").
const FIELDS = ["serverUrl", "organization", "username"];
const CHECKS = ["storeAttachments", "tagOnSuccess"];
function setStatus(msg, kind) {
const el = $("status");
el.textContent = msg;
el.className = kind || "";
}
async function load() {
const s = await Settings.get();
FIELDS.forEach((f) => ($(f).value = s[f] || ""));
CHECKS.forEach((c) => ($(c).checked = !!s[c]));
setMailFormat(s.mailFormat === "pdf" ? "pdf" : "eml");
loadMapping(s.fieldMapping && Object.keys(s.fieldMapping).length ? s.fieldMapping : DEFAULT_FIELD_MAP);
// Schrankliste, falls vorher schon getestet (im Storage gecached)
const cached = (await browser.storage.local.get("cabinets")).cabinets || [];
fillCabinets(cached, s.defaultCabinetId);
}
function setMailFormat(v) {
const el = document.querySelector(`input[name="mailFormat"][value="${v}"]`);
if (el) el.checked = true;
}
function getMailFormat() {
const el = document.querySelector('input[name="mailFormat"]:checked');
return el ? el.value : "eml";
}
// --- Feld-Mapping-Editor ---------------------------------------------------
function addMapRow(field = "", token = "") {
const tr = document.createElement("tr");
const inp = document.createElement("input");
inp.type = "text"; inp.className = "map-field"; inp.value = field;
inp.placeholder = "EML_SUBJECT";
const tdF = document.createElement("td"); tdF.appendChild(inp);
const sel = document.createElement("select"); sel.className = "map-token";
const none = document.createElement("option"); none.value = ""; none.textContent = "— nichts —";
sel.appendChild(none);
MAIL_TOKENS.forEach((t) => {
const o = document.createElement("option");
o.value = t.key; o.textContent = t.label;
if (t.key === token) o.selected = true;
sel.appendChild(o);
});
const tdT = document.createElement("td"); tdT.appendChild(sel);
const del = document.createElement("button");
del.type = "button"; del.className = "secondary"; del.textContent = "✕";
del.addEventListener("click", () => tr.remove());
const tdX = document.createElement("td"); tdX.className = "del"; tdX.appendChild(del);
tr.append(tdF, tdT, tdX);
$("mapBody").appendChild(tr);
}
function loadMapping(map) {
$("mapBody").innerHTML = "";
Object.entries(map || {}).forEach(([f, t]) => addMapRow(f, t));
}
function collectMapping() {
const map = {};
document.querySelectorAll("#mapBody tr").forEach((tr) => {
const f = tr.querySelector(".map-field").value.trim();
const t = tr.querySelector(".map-token").value;
if (f && t) map[f] = t; // leere Feldnamen/Token ignorieren
});
return map;
}
function fillCabinets(cabinets, selectedId) {
const sel = $("defaultCabinet");
sel.innerHTML = '<option value="">— keiner —</option>';
const addGroup = (label, list) => {
if (!list.length) return;
const g = document.createElement("optgroup");
g.label = label;
list.forEach((c) => {
const o = document.createElement("option");
o.value = c.id;
o.textContent = c.name;
if (String(c.id) === String(selectedId)) o.selected = true;
g.appendChild(o);
});
sel.appendChild(g);
};
addGroup("Archive", cabinets.filter((c) => !c.isBasket));
addGroup("Briefkörbe", cabinets.filter((c) => c.isBasket));
}
function collect() {
const partial = {};
FIELDS.forEach((f) => (partial[f] = $(f).value.trim()));
CHECKS.forEach((c) => (partial[c] = $(c).checked));
partial.defaultCabinetId = $("defaultCabinet").value;
partial.mailFormat = getMailFormat();
partial.fieldMapping = collectMapping();
return partial;
}
$("mapAdd").addEventListener("click", () => addMapRow());
$("mapReset").addEventListener("click", () => loadMapping(DEFAULT_FIELD_MAP));
$("save").addEventListener("click", async () => {
await Settings.set(collect());
setStatus("Gespeichert.", "ok");
});
$("test").addEventListener("click", async () => {
const pw = $("password").value;
if (!pw) { setStatus("Bitte Passwort eingeben.", "err"); return; }
setStatus("Verbinde …");
try {
const s = await Settings.set(collect()); // erst speichern (ohne Passwort), dann testen
// Anmeldung über den Hintergrund-Broker: primt zugleich die Sitzung, sodass
// das Ablege-Fenster danach nicht erneut nach dem Passwort fragt.
const res = await browser.runtime.sendMessage({ type: "auth:logon", password: pw });
if (!res || !res.ok) throw new Error(res && res.error ? res.error : "Anmeldung fehlgeschlagen.");
Auth.setToken(res.token);
$("password").value = ""; // Passwort nicht behalten
const cabinets = await DocuWare.listCabinets(s);
await browser.storage.local.set({ cabinets });
fillCabinets(cabinets, s.defaultCabinetId);
const arch = cabinets.filter((c) => !c.isBasket).length;
const bk = cabinets.filter((c) => c.isBasket).length;
setStatus(`Verbindung ok ${arch} Archive, ${bk} Briefkörbe gefunden.`, "ok");
} catch (e) {
setStatus(`Fehler: ${e.message}`, "err");
}
});
$("exportBtn").addEventListener("click", async () => {
const s = await Settings.get();
const blob = new Blob([JSON.stringify(s, null, 2)], { type: "application/json" });
const url = URL.createObjectURL(blob);
const a = document.createElement("a");
a.href = url;
a.download = "docuware-ablage-einstellungen.json";
document.body.appendChild(a);
a.click();
a.remove();
setTimeout(() => URL.revokeObjectURL(url), 1000);
setStatus("Einstellungen exportiert.", "ok");
});
$("importBtn").addEventListener("click", () => $("importFile").click());
$("importFile").addEventListener("change", async (e) => {
const file = e.target.files && e.target.files[0];
if (!file) return;
try {
const text = await file.text();
const data = JSON.parse(text);
await Settings.set(data);
await load();
setStatus("Einstellungen importiert.", "ok");
} catch (err) {
setStatus(`Import fehlgeschlagen: ${err.message}`, "err");
} finally {
e.target.value = "";
}
});
$("diagBtn").addEventListener("click", async () => {
const cabinetId = $("defaultCabinet").value;
const out = $("diag");
out.style.display = "block";
if (!cabinetId) {
out.value = "Bitte oben zuerst ein Standard-Ziel (Archiv) wählen.";
return;
}
out.value = "Analysiere …";
try {
const s = await Settings.set(collect());
// Sitzungs-Token nutzen; falls noch keiner da ist, Passwortfeld verwenden.
const st = await browser.runtime.sendMessage({ type: "auth:status" });
if (st && st.hasToken && st.token) {
Auth.setToken(st.token);
} else {
const pw = $("password").value;
if (!pw) { out.value = "Bitte Passwort eingeben (oder zuerst „Verbindung testen“)."; return; }
const res = await browser.runtime.sendMessage({ type: "auth:logon", password: pw });
if (!res || !res.ok) throw new Error(res && res.error ? res.error : "Anmeldung fehlgeschlagen.");
Auth.setToken(res.token);
$("password").value = "";
}
const dump = await DocuWare.diagnoseStoreDialog(s, cabinetId);
out.value = JSON.stringify(dump, null, 2);
} catch (e) {
out.value = `Fehler: ${e.message}`;
}
});
load();