feat: Rueckgaengig gemachte Importe sammelweise entfernen
Die Aktionsspalte im Verlauf ist fest und war zu schmal fuer den beschrifteten Knopf. Ausserdem sammeln sich nach einer Testreihe schnell zwanzig rueckgaengig gemachte Eintraege – die einzeln wegzuklicken ist Fleissarbeit. Neben der Ueberschrift steht jetzt ein Knopf, der alle auf einmal entfernt; einzeln geht weiterhin. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -360,7 +360,9 @@
|
|||||||
"removeEntryConfirm": "Den Verlaufs-Eintrag „{{file}}“ entfernen? Die Buchungen sind bereits zurückgenommen.",
|
"removeEntryConfirm": "Den Verlaufs-Eintrag „{{file}}“ entfernen? Die Buchungen sind bereits zurückgenommen.",
|
||||||
"reconMixedHint": "Enthält die Datei mehrere Konten oder Produkte? Revolut legt Giro, Erspartes und Anlagekonto in EINE Datei, jedes mit eigener Kontostand-Spalte. Dann greift der Abgleich erst, wenn du oben den Zeilenfilter setzt (z. B. Produkt = Giro) und die übrigen Produkte einzeln einliest.",
|
"reconMixedHint": "Enthält die Datei mehrere Konten oder Produkte? Revolut legt Giro, Erspartes und Anlagekonto in EINE Datei, jedes mit eigener Kontostand-Spalte. Dann greift der Abgleich erst, wenn du oben den Zeilenfilter setzt (z. B. Produkt = Giro) und die übrigen Produkte einzeln einliest.",
|
||||||
"filterTitle": "Diese Datei enthält mehrere Konten",
|
"filterTitle": "Diese Datei enthält mehrere Konten",
|
||||||
"filterValueOption": "{{value}} ({{count}} Zeilen)"
|
"filterValueOption": "{{value}} ({{count}} Zeilen)",
|
||||||
|
"removeAllUndone": "Rückgängig gemachte entfernen",
|
||||||
|
"removeAllUndoneConfirm": "{{n}} rückgängig gemachte Einträge aus dem Verlauf entfernen? Die Buchungen sind bereits weg, es verschwindet nur der Eintrag."
|
||||||
},
|
},
|
||||||
"password": {
|
"password": {
|
||||||
"show": "Passwort anzeigen",
|
"show": "Passwort anzeigen",
|
||||||
|
|||||||
@@ -360,7 +360,9 @@
|
|||||||
"removeEntryConfirm": "Remove the history entry “{{file}}”? Its transactions have already been undone.",
|
"removeEntryConfirm": "Remove the history entry “{{file}}”? Its transactions have already been undone.",
|
||||||
"reconMixedHint": "Does the file hold several accounts or products? Revolut puts current, savings and investment into ONE file, each with its own balance column. The check only works once you set the row filter above (e.g. Product = Current) and import the other products separately.",
|
"reconMixedHint": "Does the file hold several accounts or products? Revolut puts current, savings and investment into ONE file, each with its own balance column. The check only works once you set the row filter above (e.g. Product = Current) and import the other products separately.",
|
||||||
"filterTitle": "This file holds several accounts",
|
"filterTitle": "This file holds several accounts",
|
||||||
"filterValueOption": "{{value}} ({{count}} rows)"
|
"filterValueOption": "{{value}} ({{count}} rows)",
|
||||||
|
"removeAllUndone": "Remove undone entries",
|
||||||
|
"removeAllUndoneConfirm": "Remove {{n}} undone entries from the history? The bookings are already gone; only the entry disappears."
|
||||||
},
|
},
|
||||||
"password": {
|
"password": {
|
||||||
"show": "Show password",
|
"show": "Show password",
|
||||||
|
|||||||
@@ -206,6 +206,22 @@ export default function Import() {
|
|||||||
try { await api.removeImportBatch(b.id); loadStamm(); } catch (e) { toast(e.message, "error"); }
|
try { await api.removeImportBatch(b.id); loadStamm(); } catch (e) { toast(e.message, "error"); }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Nach einer Reihe von Versuchen stehen schnell zwanzig rueckgaengig gemachte
|
||||||
|
// Importe im Verlauf. Die einzeln wegzuklicken ist Fleissarbeit ohne Nutzen.
|
||||||
|
async function alleErledigtenEntfernen() {
|
||||||
|
const weg = batches.filter((b) => b.status === "undone");
|
||||||
|
if (!weg.length) return;
|
||||||
|
if (!(await confirm({
|
||||||
|
title: t("import.removeAllUndone"),
|
||||||
|
message: t("import.removeAllUndoneConfirm", { n: weg.length }),
|
||||||
|
danger: true, confirmLabel: t("common.delete"),
|
||||||
|
}))) return;
|
||||||
|
try {
|
||||||
|
for (const b of weg) await api.removeImportBatch(b.id);
|
||||||
|
loadStamm();
|
||||||
|
} catch (e) { toast(e.message, "error"); }
|
||||||
|
}
|
||||||
|
|
||||||
async function undo(b) {
|
async function undo(b) {
|
||||||
if (!(await confirm({ title: t("import.undo"), message: t("import.undoConfirm", { file: b.filename }), danger: true, confirmLabel: t("import.undo") }))) return;
|
if (!(await confirm({ title: t("import.undo"), message: t("import.undoConfirm", { file: b.filename }), danger: true, confirmLabel: t("import.undo") }))) return;
|
||||||
try { await api.undoImportBatch(b.id); loadStamm(); } catch (e) { toast(e.message, "error"); }
|
try { await api.undoImportBatch(b.id); loadStamm(); } catch (e) { toast(e.message, "error"); }
|
||||||
@@ -336,7 +352,7 @@ export default function Import() {
|
|||||||
render: (b) => <span className="nowrap">{t("import.importedCount", { n: b.imported_count })}</span>,
|
render: (b) => <span className="nowrap">{t("import.importedCount", { n: b.imported_count })}</span>,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: "action", header: "", width: 168, fixed: true,
|
key: "action", header: "", width: 196, fixed: true,
|
||||||
render: (b) => (b.status === "committed" ? (
|
render: (b) => (b.status === "committed" ? (
|
||||||
<button className="btn sm danger" onClick={() => undo(b)}>
|
<button className="btn sm danger" onClick={() => undo(b)}>
|
||||||
<Icon name="refresh-ccw" size={14} /> {t("import.undo")}
|
<Icon name="refresh-ccw" size={14} /> {t("import.undo")}
|
||||||
@@ -673,7 +689,15 @@ export default function Import() {
|
|||||||
{/* Verlauf */}
|
{/* Verlauf */}
|
||||||
{batches.length > 0 && (
|
{batches.length > 0 && (
|
||||||
<div className="card">
|
<div className="card">
|
||||||
<h2>{t("import.history")}</h2>
|
<div className="card-head">
|
||||||
|
<h2>{t("import.history")}</h2>
|
||||||
|
{batches.some((b) => b.status === "undone") && (
|
||||||
|
<button className="btn sm ghost" style={{ marginLeft: "auto" }} onClick={alleErledigtenEntfernen}>
|
||||||
|
<Icon name="trash" size={14} />{" "}
|
||||||
|
{t("import.removeAllUndone")} ({batches.filter((b) => b.status === "undone").length})
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
<DataTable
|
<DataTable
|
||||||
id="import-history"
|
id="import-history"
|
||||||
rows={batches}
|
rows={batches}
|
||||||
|
|||||||
Reference in New Issue
Block a user