Steht ein Feld nicht in der Liste,
+ „✎ Anderer Feldname" wählen und den Namen eintippen.
Als Mail-Attribut „Fester Wert"
wählen, um einen festen Text (z. B. NEU) ins Feld zu schreiben.
diff --git a/options/options.js b/options/options.js
index aefc7d7..c9de665 100644
--- a/options/options.js
+++ b/options/options.js
@@ -58,7 +58,12 @@ async function invalidateSession(s) {
let next = s;
if (server) {
next = await Settings.set({ defaultCabinetId: "", dialogByCabinet: {} });
+ // Gemerkte Feldlisten hängen an Schrank-GUIDs des alten Servers -> weg damit.
+ fieldsByCabinet = {};
+ await browser.storage.local.remove("fieldsByCabinet").catch(() => {});
+ availableFields = [];
fillCabinets([], ""); // Dropdowns leeren – die alte Liste gilt nicht mehr
+ refreshFieldSelects();
}
snapshotAuth(next);
return next;
@@ -71,13 +76,23 @@ async function load() {
CHECKS.forEach((c) => ($(c).checked = !!s[c]));
setMailFormat(s.mailFormat === "pdf" ? "pdf" : "eml");
$("mappingUrl").value = s.mappingUrl || "";
- 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);
- // Best-effort: Felder des Standard-Archivs gleich laden – nur wenn schon ein
- // Sitzungs-Token da ist (sonst wählt der Nutzer das Archiv manuell).
+ // Gemerkte Schrank- und Feldlisten VOR dem Aufbau der Zeilen lesen, damit die
+ // Feldname-Dropdowns schon beim ersten Rendern gefüllt sind.
+ const local = await browser.storage.local.get(["cabinets", "fieldsByCabinet"]);
+ fieldsByCabinet = local.fieldsByCabinet || {};
+ if (s.defaultCabinetId && Array.isArray(fieldsByCabinet[s.defaultCabinetId])) {
+ availableFields = fieldsByCabinet[s.defaultCabinetId];
+ }
+
+ loadMapping(s.fieldMapping && Object.keys(s.fieldMapping).length ? s.fieldMapping : DEFAULT_FIELD_MAP);
+ fillCabinets(local.cabinets || [], s.defaultCabinetId);
+ if (availableFields.length) {
+ $("mapFieldStatus").textContent = `${availableFields.length} Felder zur Auswahl (gemerkt).`;
+ }
+
+ // Best-effort auffrischen – nur wenn schon ein Sitzungs-Token da ist. Ohne
+ // Token bleibt es bei der gemerkten Liste, die Auswahl funktioniert trotzdem.
if (s.defaultCabinetId && [...$("mapCabinet").options].some((o) => o.value === s.defaultCabinetId)) {
$("mapCabinet").value = s.defaultCabinetId;
try {
@@ -86,10 +101,11 @@ async function load() {
Auth.setToken(stt.token);
availableFields = (await DocuWare.cabinetFieldNames(s, s.defaultCabinetId))
.filter((n) => n && !/^DW[A-Z]/.test(n)).sort();
+ await rememberFields(s.defaultCabinetId, availableFields);
refreshFieldSelects();
$("mapFieldStatus").textContent = `${availableFields.length} Felder zur Auswahl geladen.`;
}
- } catch (_) { /* egal – Archiv kann manuell gewählt werden */ }
+ } catch (_) { /* egal – gemerkte Liste bleibt nutzbar */ }
}
}
@@ -159,8 +175,19 @@ async function ensureToken() {
// --- Feld-Mapping-Editor ---------------------------------------------------
-const CONST_OPT = "__const__"; // Sentinel im Quelle-Dropdown für „Fester Wert"
-let availableFields = []; // Feldnamen aus dem zuletzt gewählten Archiv
+const CONST_OPT = "__const__"; // Sentinel im Quelle-Dropdown für „Fester Wert"
+const CUSTOM_OPT = "__custom__"; // Sentinel im Feldname-Dropdown für „eigener Name"
+let availableFields = []; // Feldnamen des zuletzt gewählten Archivs
+
+// Gemerkte Feldnamen je Archiv (storage.local, Schlüssel "fieldsByCabinet").
+// Ohne diesen Cache war die Auswahlliste bei jedem Thunderbird-Start wieder leer:
+// sie kam nur vom Server und setzte damit Passworteingabe + Archivwahl voraus.
+let fieldsByCabinet = {};
+
+async function rememberFields(cabinetId, names) {
+ fieldsByCabinet = { ...fieldsByCabinet, [cabinetId]: names };
+ await browser.storage.local.set({ fieldsByCabinet }).catch(() => {});
+}
// Zerlegt einen Mapping-Wert (Token-String ODER { const } / { token }) in den UI-Zustand.
function mapValueState(value) {
@@ -172,25 +199,52 @@ function mapValueState(value) {
return { sel: "", konst: "" };
}
-// Vorschläge für die Feldname-Eingaben: Felder des gewählten Archivs, dazu die
-// Standard-Feldnamen und alles schon Eingetragene. Der Archiv-Teil ist erst nach
-// Anmeldung + Archivwahl da – ohne die beiden anderen Quellen stünde man vorher
-// vor einer leeren Liste.
+// Feldname einer Zeile – aus dem Dropdown oder, bei „Anderer Feldname", aus der
+// daneben eingeblendeten Eingabe.
+function rowFieldName(row) {
+ const sel = row.querySelector(".map-field-sel");
+ if (!sel) return "";
+ if (sel.value === CUSTOM_OPT) {
+ const inp = row.querySelector(".map-field-custom");
+ return inp ? inp.value.trim() : "";
+ }
+ return sel.value.trim();
+}
+
+// Auswahlliste für die Feldname-Dropdowns. Drei Quellen, damit sie NIE leer ist:
+// Felder des gewählten Archivs (auch aus dem Cache, also ohne Anmeldung), die
+// Standard-Feldnamen und alles im Formular bereits Vergebene.
function fieldSuggestions() {
- const used = [...document.querySelectorAll("#mapBody .map-field")].map((i) => i.value);
+ const used = [...document.querySelectorAll("#mapBody .map-row")].map(rowFieldName);
const all = [...(availableFields || []), ...Object.keys(DEFAULT_FIELD_MAP), ...used];
return [...new Set(all.filter(Boolean))].sort();
}
-// Baut die gemeinsame