Playwright Tests / test (push) Canceled after 0s
- Added MailerAttachmentPolicy for validating email attachments against server rules. - Introduced fis.specialties.js for managing hidden maintenance actions via an admin interface. - Created fis.specialties.scss for styling the specialties management UI. - Added German localization for specialties management in fis.specialties_txt_de.js. - Developed CSS for specialties management in fis.specialties.css. - Implemented server-side stored procedure fds__admin_backupAndClearInvoiceFile for backing up and clearing invoice files. - Created fds__invoice_file_backups table to store backup records of invoice files.
98 lines
5.2 KiB
JavaScript
98 lines
5.2 KiB
JavaScript
/* "Specialties" — admin-only page (URL /specialties, menu Administration → Spezialfunktionen)
|
|
that exposes the otherwise hidden maintenance actions as cards with small forms. Each card
|
|
calls its real action endpoint (which enforces the fds_sys > 4 gate itself); this module only
|
|
renders and reports. Add a card per action in `cards`. */
|
|
let $spc = {
|
|
init2: function () {
|
|
$ocms.getScript([], function () { $spc.init3(); });
|
|
},
|
|
init3: function () {
|
|
$fis.cf(true);
|
|
$fis.lf(true);
|
|
$('#activemodule').text($spt.mdl);
|
|
$('#topbar').ocmsmenu([]);
|
|
let frm = $$.dc('spcfrm', $('#contentframe'));
|
|
$$.dc('spc_intro', frm).text($spt.intro);
|
|
let grid = $$.dc('spc_grid', frm);
|
|
$.each($spc.cards, function (i, build) { build(grid); });
|
|
},
|
|
|
|
/* ── building blocks ─────────────────────────────────────────────────── */
|
|
card: function (grid, title, desc) {
|
|
let card = $$.dc('spc_card', grid);
|
|
let hd = $$.dc('spc_card_hd', card);
|
|
$$.s(title).appendTo(hd);
|
|
let bd = $$.dc('spc_card_bd', card);
|
|
if (desc) { $$.dc('spc_card_desc', bd).text(desc); }
|
|
let form = $('<form/>', { class: 'spc_form', novalidate: 'novalidate' }).appendTo(bd);
|
|
let result = $$.dc('spc_result', bd).hide();
|
|
return { card: card, body: bd, form: form, result: result };
|
|
},
|
|
field: function (form, name, label, options) {
|
|
options = options || {};
|
|
let fg = $$.dc('spc_field', form);
|
|
let id = 'spc_' + name;
|
|
$$.lbl(label, { for: id }).appendTo(fg);
|
|
let inp = $$.i({ id: id, name: name, type: options.type || 'text', placeholder: options.placeholder || '' }).appendTo(fg);
|
|
if (options.required) { inp.attr('required', 'required'); }
|
|
if (options.pattern) { inp.attr('pattern', options.pattern); }
|
|
if (options.note) { $$.dc('spc_field_note', fg).text(options.note); }
|
|
return inp;
|
|
},
|
|
showResult: function (result, ok, lines) {
|
|
result.empty().attr('class', 'spc_result ' + (ok ? 'spc_result_ok' : 'spc_result_err'));
|
|
$.each([].concat(lines || []), function (i, l) { if (l) { $$.dc('spc_result_line', result).text(l); } });
|
|
result.show();
|
|
},
|
|
/* Wires a card form: validates, confirms, POSTs, reports. `run(values)` must return a
|
|
postXT options object without success/error/complete; `report(response)` returns
|
|
{ ok, lines }. Callbacks run inside jQuery's dispatch and must never throw. */
|
|
submit: function (c, options) {
|
|
let btn = $$.bbtn(options.button, 'spc_btn spc_btn_primary').attr('type', 'submit').appendTo($$.dc('spc_actions', c.form));
|
|
c.form.on('submit', function (ev) {
|
|
ev.preventDefault();
|
|
let f = c.form[0];
|
|
if (typeof f.reportValidity === 'function' && !f.reportValidity()) { return; }
|
|
let values = c.form.serializeObject(true, { typedvalues: false });
|
|
if (typeof options.confirm === 'function' && !confirm(options.confirm(values))) { return; }
|
|
c.result.hide();
|
|
btn.prop('disabled', true).text($spt.working);
|
|
$ocms.postXT($.extend(options.run(values), {
|
|
success: function (r) {
|
|
let rep = options.report(r || {});
|
|
$spc.showResult(c.result, rep.ok, rep.lines);
|
|
},
|
|
error: function (jqXHR) {
|
|
$spc.showResult(c.result, false, [$spt.failed, (jqXHR && jqXHR.internalText) || '']);
|
|
},
|
|
complete: function () { btn.prop('disabled', false).text(options.button); }
|
|
}));
|
|
});
|
|
},
|
|
|
|
/* ── cards ───────────────────────────────────────────────────────────── */
|
|
cards: [
|
|
/* Invoice file backup + clear → POST /do/admin/backupclearinvoicefile/<id> (ADR 0027). */
|
|
function (grid) {
|
|
let c = $spc.card(grid, $spt.ifc_title, $spt.ifc_desc);
|
|
$spc.field(c.form, 'id', $spt.ifc_id, { required: true, placeholder: $spt.ifc_id_ph, note: $spt.ifc_id_note, pattern: '[A-Za-z0-9]{1,10}' });
|
|
$spc.submit(c, {
|
|
button: $spt.ifc_btn,
|
|
confirm: function (v) { return $spt.ifc_confirm.replace('{0}', v.id); },
|
|
run: function (v) {
|
|
return { url: $ocms.url('admin/backupclearinvoicefile/' + encodeURIComponent((v.id || '').trim())), method: 'post', data: {} };
|
|
},
|
|
report: function (r) {
|
|
let b = r.backup || {};
|
|
if (b.success === true) {
|
|
return { ok: true, lines: [$spt.ifc_ok, b.blobBackupUri ? $spt.ifc_ok_blob.replace('{0}', b.blobBackupUri) : $spt.ifc_ok_noblob] };
|
|
}
|
|
return { ok: false, lines: [$spt.ifc_reason[b.reason] || ($spt.failed + ' (' + (b.reason || '?') + ')')] };
|
|
}
|
|
});
|
|
}
|
|
]
|
|
};
|
|
let $$spc = { init2: $spc.init2, auth: {} };
|
|
export default $$spc;
|