Refactor document name sanitization for consistent filename generation

- Introduced FdsDocumentNames class to centralize the logic for sanitizing document names used in downloads.
- Updated FdsMfr to utilize the new SafeFileName method for generating safe filenames.
- Enhanced documentation for FdsDocumentNames and its methods to clarify usage and purpose.
- Added global.json file to configure testing framework settings.
This commit is contained in:
Stefan
2026-09-16 22:18:42 +02:00
parent a60d4c2eaf
commit 944a5bb442
18 changed files with 245 additions and 34 deletions
+20 -4
View File
@@ -133,13 +133,27 @@ $inv.pdfPreviewFailed = function (jqXHR, textStatus) {
alert(($ict.pvf || $t.f1) + (desc !== '' ? '\n' + desc : ''));
};
/* postXT never calls `error` for a timeout (it returns early), so the timeout is only
observable from `complete`; this builds the complete handler for a preview call. */
$inv.pdfPreviewComplete = function (layout) {
observable from `complete`; this builds the complete handler for a preview call.
`wait`, if given, is the "please wait" popup from `$inv.pdfWaitDlg` — it must close on
every outcome (success, error, timeout), so `complete` is the only place that reliably
covers all three. */
$inv.pdfPreviewComplete = function (layout, wait) {
return (jqXHR, textStatus) => {
if (wait) { wait.c.trigger('modal_close'); }
if (layout) { layout.rC('freeze'); }
if (textStatus === 'timeout') { $inv.pdfPreviewFailed(jqXHR, textStatus); }
};
};
/* A preview render can take anywhere from a couple of seconds to the full 120s timeout (a
cold miss regenerates + stores the PDF before rasterising it, ADR 0025); postXT's generic
`body.ldng` class has no CSS behind it, so nothing tells the user the click was received.
Same popup the MFR data fetch shows (see $inv.cInv2): spinner frame in a modal with the
explanation in the footer. Non-exclusive so it can sit on top of an open editor. */
$inv.pdfWaitDlg = function () {
let o = $ocms.dlg($$.dc('rfrm').ldng(1), { exclusive: false, zindex_min: 50 });
if (o) { o.ft.rwText($ict.pvw); }
return o;
};
/* ── Backend-authoritative draft editing controller (ADR 0006/0007) ───────────
The server holds the truth for an invoice draft in an in-memory session; this
object seeds it, sends single edits as deltas, and renders the totals footer +
@@ -1563,6 +1577,7 @@ $inv.disp = (id, typ) => {
break;
}
if (u !== '') {
let wait = $inv.pdfWaitDlg();
$ocms.postXT({
url: $ocms.url(u), data: { id: id || '', typ: 'img' }, timeout: $inv.pdfPreviewTimeout, success: (response) => {
let c = $$.dc('imagecollection pdfpreview'), vhr = Math.round(vh() * 0.88), invid = response.id;
@@ -1572,11 +1587,12 @@ $inv.disp = (id, typ) => {
$ocms.dlg(c, {
size: [vhr, Math.round(vw() * 0.88)], zindex_min: 50, form: false, exclusive:false
});
}, error: $inv.pdfPreviewFailed, complete: $inv.pdfPreviewComplete()
}, error: $inv.pdfPreviewFailed, complete: $inv.pdfPreviewComplete(null, wait)
});
}
};
$inv.jdbn = function (ev) {
let wait = $inv.pdfWaitDlg();
$ocms.postXT({
url: $ocms.url('inv/rdocn'), data: { name: ev.data.id || '', typ: 'img' }, timeout: $inv.pdfPreviewTimeout, success: (response) => {
let c = $$.dc('imagecollection pdfpreview'), vhr = Math.round(vh() * 0.88), invid = response.id;
@@ -1586,7 +1602,7 @@ $inv.jdbn = function (ev) {
$ocms.dlg(c, {
size: [vhr, Math.round(vw() * 0.88)], zindex: 50, form: false
});
}, error: $inv.pdfPreviewFailed, complete: $inv.pdfPreviewComplete()
}, error: $inv.pdfPreviewFailed, complete: $inv.pdfPreviewComplete(null, wait)
});
};
$inv.sp13b = () => {
@@ -38,6 +38,7 @@
pna: 'Diese Seite ist in der Vorschau nicht verfügbar',
tpe: 'Die Anzahl von {0} Seiten wird aktuell nicht unterstützt',
eis: 'Der Rechnungsentwurf konnte nicht gespeichert werden.',
pvw: 'Das Dokument wird abgerufen und für die Vorschau aufbereitet.\nDer Vorgang kann bis zu 2 Minuten dauern.',
pvf: 'Die PDF-Vorschau konnte nicht erstellt werden.',
pvto: 'Der Server hat nicht rechtzeitig geantwortet (Zeitüberschreitung). Bitte versuchen Sie es erneut.',
pvgone: 'Der Entwurf ist auf dem Server nicht mehr vorhanden (Sitzung abgelaufen). Bitte öffnen Sie den Entwurf erneut.',