fix(forms): never submit an invalid form; unlock password-change dialog
Playwright Tests / test (push) Canceled after 0s
Playwright Tests / test (push) Canceled after 0s
serializeObject() returns null for an invalid form, but most callers sent
the result anyway. Add $.fn.rejectInvalid (stop the spinner, let the
browser report the offending field) and use it at every call site.
Bugs fixed:
- Password change: on a mismatch the spinner kept running, and the custom
validity on "npw" was never cleared, so the browser blocked every later
submit even after the passwords matched. It is now cleared as soon as
either password field is edited.
- sendForm: options.complete referenced an undefined jqXHR (ReferenceError)
and an invalid form was posted with partial data.
- login.send: an invalid form threw a TypeError on qs.loginaccount.
- postXT({ form }): an invalid form was posted with empty data.
- Form dialogs without required fields had no "Bitte überprüfen Sie Ihre
Eingaben" note, so a rejected submit showed nothing.
Hardening: null guards for the user, user-group, re-login, SMS password,
admin specialties and report-parameter submits.
Add e2e_tests/form-validation.cjs covering each path against the real
scripts; it fails on the previous code.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
4145ab699c
commit
4443bba63c
@@ -725,6 +725,7 @@ $ocms.postXT = function (options) {
|
||||
}
|
||||
if (options.form instanceof jQuery) {
|
||||
options.data = options.form.serializeObject();
|
||||
if (options.data === null) { options.form.rejectInvalid(); return; }
|
||||
options.contentType = 'form-data';
|
||||
} else if (options.lzw instanceof jQuery) {
|
||||
options.data.lzw = $.ccLZW(options.lzw.serializeAnything(true)).join(',');
|
||||
@@ -957,6 +958,13 @@ $ocms.vbl_send = function (ev) {
|
||||
c.toggleClass('invalid', !valid);
|
||||
return valid ? result : null;
|
||||
};
|
||||
/* For a form whose serializeObject() returned null: stop its loading indicator and let the
|
||||
browser point at the offending field, instead of submitting partial data. */
|
||||
$.fn.rejectInvalid = function () {
|
||||
var c = $(this).ldng(0), f = c.closest('form')[0] || c.find('form')[0];
|
||||
if (f && typeof f.reportValidity === 'function') { f.reportValidity(); }
|
||||
return c;
|
||||
};
|
||||
$.fn.sendForm = function (url, success, options) {
|
||||
var form = $(this);
|
||||
options = options || {};
|
||||
@@ -971,11 +979,13 @@ $ocms.vbl_send = function (ev) {
|
||||
if (typeof options.error === 'function') { options.error.call(this, jqXHR); } else {
|
||||
$ocms.failure.call(this, jqXHR);
|
||||
}
|
||||
}, complete: function () {
|
||||
}, complete: function (jqXHR) {
|
||||
form.ldng(0);
|
||||
if (typeof options.complete === 'function') { options.complete.call(this, jqXHR); }
|
||||
}
|
||||
};
|
||||
var formdata = form.serializeObject();
|
||||
if (formdata === null) { form.rejectInvalid(); return; }
|
||||
var fle = form.find('input[type="file"]');
|
||||
postoptions.data = new FormData();
|
||||
if (fle.length > 0) {
|
||||
@@ -984,8 +994,7 @@ $ocms.vbl_send = function (ev) {
|
||||
postoptions.data.append('file_lastmodified', $ocms.isodt(value.lastModifiedDate));
|
||||
});
|
||||
}
|
||||
var formdata = form.serializeObject();
|
||||
$.each(formdata || {}, function (di, dx) {
|
||||
$.each(formdata, function (di, dx) {
|
||||
postoptions.data.append(di, dx);
|
||||
});
|
||||
form.ldng();
|
||||
@@ -1018,7 +1027,7 @@ $ocms.login = {
|
||||
return false;
|
||||
} else {
|
||||
var qs = f.serializeObject();
|
||||
qs.loginaccount = ne(qs.loginaccount, $ocms.auth.account || $ocms.auth.requestedaccount || '');
|
||||
if (qs === null) { f.rejectInvalid(); return false; }
|
||||
qs.loginaccount = ne(qs.loginaccount, $ocms.auth.account || $ocms.auth.requestedaccount || '');
|
||||
if (ne(qs.loginaccount) === '' && bool($ocms.auth.accountrequired, true) === true ) {
|
||||
alert($t.l16);
|
||||
@@ -1077,6 +1086,7 @@ $ocms.login = {
|
||||
d.find('form').submit(function (e) {
|
||||
e.preventDefault();
|
||||
var qs = $(this).serializeObject(true), s2 = code === null, u = s2 ?'spwc':'spw';
|
||||
if (qs === null) { $(this).rejectInvalid(); return false; }
|
||||
$ocms.postXT.call(this, {
|
||||
url: $ocms.url(u), data: qs, complete: function () {
|
||||
if (s2) {
|
||||
@@ -2139,6 +2149,8 @@ class NumArray extends Array {
|
||||
};
|
||||
if (c.find(':input[required]').length > 0) {
|
||||
$$.dc('note_required', ft).append($$.sc('ind_required', '*')).append($$.s($t.t1 || 'Eingabe erforderlich'));
|
||||
}
|
||||
if (isform === true) { /* shown via .invalid whenever serializeObject rejects the form, required fields or not */
|
||||
$$.dc('note_invalid', ft).append($$.s($t.t2 || 'Bitte überprüfen Sie Ihre Eingaben im Formular.'));
|
||||
}
|
||||
if (f('cancel') === true) {
|
||||
@@ -2393,7 +2405,7 @@ class NumArray extends Array {
|
||||
cfm = function (e) {
|
||||
var c = $(this).ldng(1);
|
||||
var values = c.serializeObject(bool(options.checkvalidity, true), { typedvalues: bool(options.typedvalues, false) });
|
||||
if (values === null) { c.ldng(0); return; }
|
||||
if (values === null) { c.rejectInvalid(); return; }
|
||||
var qs = $.extend({ loginaccount: $ocms.auth.account || '' }, values);
|
||||
if ((options.url || '') !== ''){
|
||||
$ocms.postXT({
|
||||
@@ -2438,7 +2450,9 @@ class NumArray extends Array {
|
||||
let gf1 = $$.dc('frm').append($ocms.mform(flds).addClass('stacked'));
|
||||
let f_submit = function (e) {
|
||||
var c = $(this).ldng(1);
|
||||
var qs = $.extend({ loginaccount: $ocms.auth.account || '' }, c.serializeObject());
|
||||
var values = c.serializeObject();
|
||||
if (values === null) { c.rejectInvalid(); return; }
|
||||
var qs = $.extend({ loginaccount: $ocms.auth.account || '' }, values);
|
||||
$ocms.postXT({
|
||||
url: '/vt/login', data: qs, success: function (response) {
|
||||
if (((response || {}).login || '') !== '') {
|
||||
@@ -3000,9 +3014,18 @@ $fis.resetPass = function (id, fds) {
|
||||
title: $t.rsp || '',
|
||||
submit: function (e) {
|
||||
var c = $(this).ldng(1);
|
||||
var qs = $.extend({ loginaccount: $ocms.auth.account || '' }, c.serializeObject(true, { typedvalues: true }));
|
||||
var values = c.serializeObject(true, { typedvalues: true });
|
||||
if (values === null) { c.rejectInvalid(); return; }
|
||||
var qs = $.extend({ loginaccount: $ocms.auth.account || '' }, values);
|
||||
if ((qs.npw || '') !== (qs.npwc || '')) {
|
||||
c.find('input[name="npw"]:first')[0].setCustomValidity($t.pnm);
|
||||
/* The browser blocks every later submit while npw carries a custom error, so it
|
||||
must be cleared as soon as either password field is edited again. */
|
||||
var npw = c.find('input[name="npw"]:first');
|
||||
npw[0].setCustomValidity($t.pnm);
|
||||
c.find('input[name="npw"], input[name="npwc"]').off('input.pnm').on('input.pnm', function () {
|
||||
npw[0].setCustomValidity('');
|
||||
});
|
||||
c.rejectInvalid();
|
||||
} else {
|
||||
$ocms.postXT({
|
||||
url: $ocms.url('account/changepassword'), data: qs, success: function (response) {
|
||||
|
||||
Vendored
+2
-2
File diff suppressed because one or more lines are too long
@@ -53,9 +53,10 @@ let $rep = {
|
||||
};
|
||||
let scl = function (ev) {
|
||||
//console.debug(ev);
|
||||
let btn = $(this), rx = ev.data;
|
||||
let btn = $(this), rx = ev.data, params = btn.serializeObject();
|
||||
if (params === null) { return; }
|
||||
$ocms.postXT({
|
||||
url: $ocms.url('rep/gct/' + rx.name), data: btn.serializeObject(), success: (response) => {
|
||||
url: $ocms.url('rep/gct/' + rx.name), data: params, success: (response) => {
|
||||
btn.addClass('selected').siblings().removeClass('selected');
|
||||
$('#listframe').rC('fix').aC('hd');
|
||||
repfrm.html(response);
|
||||
|
||||
Vendored
+1
-1
@@ -1 +1 @@
|
||||
let $ct={mdl:"Berichte"},$ccol={};function getMonday(e){var t=(e=new Date(e)).getDay(),a=e.getDate()-t+(0==t?-6:1);return new Date(e.setDate(a))}let $rep={init2:function(e,t){e=e||"inv",t=t||{},$ocms.getScript([],(function(){$rep.init3(e,t)}))},init3:async function(e,t){let a=$("#contentframe").empty(),l=($$.dc("cfrm hd").appendTo(a),$$.dc("init_frm",a));$("#topbar").ocmsmenu([]);$("#activemodule").text($ct.mdl);let c=$$.dc("repfrm",l),i=(new Date,[(async()=>{if(await $fis.getAuth("fds_reports")>0){l.IN((function(){}));let e=$("#listframe").empty().aC("fix").rC("hd"),t=function(e){let t=$(this);if((e.params||[]).length>0){let a=$$.dc("ipf",t).click((function(e){e.stopPropagation()}));$.each(e.params,((e,t)=>{let l,c=$$.dc("ig",a).append($$.lbl(t.name));""===(t.valuelist||"")&&(l=$$.i({name:t.name,placeholder:t.placeholder}).appendTo(c),""!==(t.default||"")&&l.val(t.default))}))}},a=function(e){let t=$(this),a=e.data;$ocms.postXT({url:$ocms.url("rep/gct/"+a.name),data:t.serializeObject(),success:e=>{t.addClass("selected").siblings().removeClass("selected"),$("#listframe").rC("fix").aC("hd"),c.html(e)},datatype:"html"})};$ocms.postXT({url:$ocms.url("rep/catalog"),data:{},success:l=>{$.each(l.reports,((l,c)=>{let i=$$.dc("repitm",e).text(c.label).click(c,a);t.call(i,c)}))}})}})(),new Promise(((e,t)=>{}))]);await Promise.all(i)}},$$rep={init2:$rep.init2,auth:{}};export default $$rep;
|
||||
let $ct={mdl:"Berichte"},$ccol={};function getMonday(e){var t=(e=new Date(e)).getDay(),a=e.getDate()-t+(0==t?-6:1);return new Date(e.setDate(a))}let $rep={init2:function(e,t){e=e||"inv",t=t||{},$ocms.getScript([],(function(){$rep.init3(e,t)}))},init3:async function(e,t){let a=$("#contentframe").empty(),l=($$.dc("cfrm hd").appendTo(a),$$.dc("init_frm",a));$("#topbar").ocmsmenu([]);$("#activemodule").text($ct.mdl);let c=$$.dc("repfrm",l),i=(new Date,[(async()=>{if(await $fis.getAuth("fds_reports")>0){l.IN((function(){}));let e=$("#listframe").empty().aC("fix").rC("hd"),t=function(e){let t=$(this);if((e.params||[]).length>0){let a=$$.dc("ipf",t).click((function(e){e.stopPropagation()}));$.each(e.params,((e,t)=>{let l,c=$$.dc("ig",a).append($$.lbl(t.name));""===(t.valuelist||"")&&(l=$$.i({name:t.name,placeholder:t.placeholder}).appendTo(c),""!==(t.default||"")&&l.val(t.default))}))}},a=function(e){let t=$(this),a=e.data,l=t.serializeObject();null!==l&&$ocms.postXT({url:$ocms.url("rep/gct/"+a.name),data:l,success:e=>{t.addClass("selected").siblings().removeClass("selected"),$("#listframe").rC("fix").aC("hd"),c.html(e)},datatype:"html"})};$ocms.postXT({url:$ocms.url("rep/catalog"),data:{},success:l=>{$.each(l.reports,((l,c)=>{let i=$$.dc("repitm",e).text(c.label).click(c,a);t.call(i,c)}))}})}})(),new Promise(((e,t)=>{}))]);await Promise.all(i)}},$$rep={init2:$rep.init2,auth:{}};export default $$rep;
|
||||
@@ -82,6 +82,7 @@ let $spc = {
|
||||
let f = c.form[0];
|
||||
if (typeof f.reportValidity === 'function' && !f.reportValidity()) { return; }
|
||||
let values = c.form.serializeObject(true, { typedvalues: false });
|
||||
if (values === null) { c.form.rejectInvalid(); return; }
|
||||
if (typeof options.confirm === 'function' && !confirm(options.confirm(values))) { return; }
|
||||
c.result.hide();
|
||||
btn.prop('disabled', true).text($spt.working);
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
let $spt={mdl:"Spezialfunktionen",intro:"Versteckte Wartungsfunktionen für Administratoren. Jede Aktion wird protokolliert (fds__admin_activity / Anwendungslog).",run:"Ausführen",working:"Wird ausgeführt…",failed:"Die Aktion ist fehlgeschlagen.",ifc_title:"Rechnungsdatei zurücksetzen (Soft-Delete)",ifc_desc:"Sichert die gespeicherte PDF-Datei einer finalisierten Rechnung (DB-Tabelle fds__invoice_file_backups + Kopie im Blob-Archiv) und entfernt sie aus der Rechnung. Beim nächsten Aufruf des Dokuments wird die PDF neu generiert (ADR 0025/0027).",ifc_id:"Interne Rechnungs-ID",ifc_id_ph:"z.B. W7VAL",ifc_id_note:"Die interne ID (Spalte Id), nicht die Rechnungsnummer R2026-….",ifc_btn:"Datei sichern und entfernen",ifc_confirm:'Die Rechnungsdatei von "{0}" wird gesichert und aus der Rechnung entfernt. Fortfahren?',ifc_ok:"Erledigt: Die Datei wurde gesichert und entfernt. Das Dokument wird beim nächsten Aufruf neu generiert.",ifc_ok_blob:"Blob-Backup: {0}",ifc_ok_noblob:"Kein Blob-Backup angelegt (Blob-Archiv deaktiviert, kein Blob vorhanden oder Kopie fehlgeschlagen — siehe Log).",ifc_reason:{invoice_not_found:"Rechnung nicht gefunden.",not_final:"Die Rechnung ist nicht finalisiert — nur finalisierte Rechnungen können zurückgesetzt werden (Entwürfe würden sonst dauerhaft als Entwurf gespeichert).",external:"Externe (MFR-)Dokumente können nicht neu generiert werden.",no_file:"Es ist keine Datei gespeichert — nichts zu tun.",db_error:"Datenbankfehler — Details im Anwendungslog (CodeReference AdminBackupClearInvoiceFile)."}},$spc={init2:function(){$ocms.getScript([],(function(){$spc.init3()}))},init3:function(){$fis.cf(!0),$fis.lf(!0),$("#activemodule").text($spt.mdl),$("#topbar").ocmsmenu([]);let e=$$.dc("spcfrm",$("#contentframe"));$$.dc("spc_intro",e).text($spt.intro);let t=$$.dc("spc_grid",e);$.each($spc.cards,(function(e,n){n(t)}))},card:function(e,t,n){let i=$$.dc("spc_card",e),r=$$.dc("spc_card_hd",i);$$.s(t).appendTo(r);let c=$$.dc("spc_card_bd",i);return n&&$$.dc("spc_card_desc",c).text(n),{card:i,body:c,form:$("<form/>",{class:"spc_form",novalidate:"novalidate"}).appendTo(c),result:$$.dc("spc_result",c).hide()}},field:function(e,t,n,i){i=i||{};let r=$$.dc("spc_field",e),c="spc_"+t;$$.lbl(n,{for:c}).appendTo(r);let o=$$.i({id:c,name:t,type:i.type||"text",placeholder:i.placeholder||""}).appendTo(r);return i.required&&o.attr("required","required"),i.pattern&&o.attr("pattern",i.pattern),i.note&&$$.dc("spc_field_note",r).text(i.note),o},showResult:function(e,t,n){e.empty().attr("class","spc_result "+(t?"spc_result_ok":"spc_result_err")),$.each([].concat(n||[]),(function(t,n){n&&$$.dc("spc_result_line",e).text(n)})),e.show()},submit:function(e,t){let n=$$.bbtn(t.button,"spc_btn spc_btn_primary").attr("type","submit").appendTo($$.dc("spc_actions",e.form));e.form.on("submit",(function(i){i.preventDefault();let r=e.form[0];if("function"==typeof r.reportValidity&&!r.reportValidity())return;let c=e.form.serializeObject(!0,{typedvalues:!1});("function"!=typeof t.confirm||confirm(t.confirm(c)))&&(e.result.hide(),n.prop("disabled",!0).text($spt.working),$ocms.postXT($.extend(t.run(c),{success:function(n){let i=t.report(n||{});$spc.showResult(e.result,i.ok,i.lines)},error:function(t){$spc.showResult(e.result,!1,[$spt.failed,t&&t.internalText||""])},complete:function(){n.prop("disabled",!1).text(t.button)}})))}))},cards:[function(e){let t=$spc.card(e,$spt.ifc_title,$spt.ifc_desc);$spc.field(t.form,"id",$spt.ifc_id,{required:!0,placeholder:$spt.ifc_id_ph,note:$spt.ifc_id_note,pattern:"[A-Za-z0-9]{1,10}"}),$spc.submit(t,{button:$spt.ifc_btn,confirm:function(e){return $spt.ifc_confirm.replace("{0}",e.id)},run:function(e){return{url:$ocms.url("admin/backupclearinvoicefile/"+encodeURIComponent((e.id||"").trim())),method:"post",data:{}}},report:function(e){let t=e.backup||{};return!0===t.success?{ok:!0,lines:[$spt.ifc_ok,t.blobBackupUri?$spt.ifc_ok_blob.replace("{0}",t.blobBackupUri):$spt.ifc_ok_noblob]}:{ok:!1,lines:[$spt.ifc_reason[t.reason]||$spt.failed+" ("+(t.reason||"?")+")"]}}})}]},$$spc={init2:$spc.init2,auth:{}};export default $$spc;
|
||||
let $spt={mdl:"Spezialfunktionen",intro:"Versteckte Wartungsfunktionen für Administratoren. Jede Aktion wird protokolliert (fds__admin_activity / Anwendungslog).",run:"Ausführen",working:"Wird ausgeführt…",failed:"Die Aktion ist fehlgeschlagen.",ifc_title:"Rechnungsdatei zurücksetzen (Soft-Delete)",ifc_desc:"Sichert die gespeicherte PDF-Datei einer finalisierten Rechnung (DB-Tabelle fds__invoice_file_backups + Kopie im Blob-Archiv) und entfernt sie aus der Rechnung. Beim nächsten Aufruf des Dokuments wird die PDF neu generiert (ADR 0025/0027).",ifc_id:"Interne Rechnungs-ID",ifc_id_ph:"z.B. W7VAL",ifc_id_note:"Die interne ID (Spalte Id), nicht die Rechnungsnummer R2026-….",ifc_btn:"Datei sichern und entfernen",ifc_confirm:'Die Rechnungsdatei von "{0}" wird gesichert und aus der Rechnung entfernt. Fortfahren?',ifc_ok:"Erledigt: Die Datei wurde gesichert und entfernt. Das Dokument wird beim nächsten Aufruf neu generiert.",ifc_ok_blob:"Blob-Backup: {0}",ifc_ok_noblob:"Kein Blob-Backup angelegt (Blob-Archiv deaktiviert, kein Blob vorhanden oder Kopie fehlgeschlagen — siehe Log).",ifc_reason:{invoice_not_found:"Rechnung nicht gefunden.",not_final:"Die Rechnung ist nicht finalisiert — nur finalisierte Rechnungen können zurückgesetzt werden (Entwürfe würden sonst dauerhaft als Entwurf gespeichert).",external:"Externe (MFR-)Dokumente können nicht neu generiert werden.",no_file:"Es ist keine Datei gespeichert — nichts zu tun.",db_error:"Datenbankfehler — Details im Anwendungslog (CodeReference AdminBackupClearInvoiceFile)."}},$spc={init2:function(){$ocms.getScript([],(function(){$spc.init3()}))},init3:function(){$fis.cf(!0),$fis.lf(!0),$("#activemodule").text($spt.mdl),$("#topbar").ocmsmenu([]);let e=$$.dc("spcfrm",$("#contentframe"));$$.dc("spc_intro",e).text($spt.intro);let t=$$.dc("spc_grid",e);$.each($spc.cards,(function(e,n){n(t)}))},card:function(e,t,n){let i=$$.dc("spc_card",e),r=$$.dc("spc_card_hd",i);$$.s(t).appendTo(r);let c=$$.dc("spc_card_bd",i);return n&&$$.dc("spc_card_desc",c).text(n),{card:i,body:c,form:$("<form/>",{class:"spc_form",novalidate:"novalidate"}).appendTo(c),result:$$.dc("spc_result",c).hide()}},field:function(e,t,n,i){i=i||{};let r=$$.dc("spc_field",e),c="spc_"+t;$$.lbl(n,{for:c}).appendTo(r);let o=$$.i({id:c,name:t,type:i.type||"text",placeholder:i.placeholder||""}).appendTo(r);return i.required&&o.attr("required","required"),i.pattern&&o.attr("pattern",i.pattern),i.note&&$$.dc("spc_field_note",r).text(i.note),o},showResult:function(e,t,n){e.empty().attr("class","spc_result "+(t?"spc_result_ok":"spc_result_err")),$.each([].concat(n||[]),(function(t,n){n&&$$.dc("spc_result_line",e).text(n)})),e.show()},submit:function(e,t){let n=$$.bbtn(t.button,"spc_btn spc_btn_primary").attr("type","submit").appendTo($$.dc("spc_actions",e.form));e.form.on("submit",(function(i){i.preventDefault();let r=e.form[0];if("function"==typeof r.reportValidity&&!r.reportValidity())return;let c=e.form.serializeObject(!0,{typedvalues:!1});null!==c?("function"!=typeof t.confirm||confirm(t.confirm(c)))&&(e.result.hide(),n.prop("disabled",!0).text($spt.working),$ocms.postXT($.extend(t.run(c),{success:function(n){let i=t.report(n||{});$spc.showResult(e.result,i.ok,i.lines)},error:function(t){$spc.showResult(e.result,!1,[$spt.failed,t&&t.internalText||""])},complete:function(){n.prop("disabled",!1).text(t.button)}}))):e.form.rejectInvalid()}))},cards:[function(e){let t=$spc.card(e,$spt.ifc_title,$spt.ifc_desc);$spc.field(t.form,"id",$spt.ifc_id,{required:!0,placeholder:$spt.ifc_id_ph,note:$spt.ifc_id_note,pattern:"[A-Za-z0-9]{1,10}"}),$spc.submit(t,{button:$spt.ifc_btn,confirm:function(e){return $spt.ifc_confirm.replace("{0}",e.id)},run:function(e){return{url:$ocms.url("admin/backupclearinvoicefile/"+encodeURIComponent((e.id||"").trim())),method:"post",data:{}}},report:function(e){let t=e.backup||{};return!0===t.success?{ok:!0,lines:[$spt.ifc_ok,t.blobBackupUri?$spt.ifc_ok_blob.replace("{0}",t.blobBackupUri):$spt.ifc_ok_noblob]}:{ok:!1,lines:[$spt.ifc_reason[t.reason]||$spt.failed+" ("+(t.reason||"?")+")"]}}})}]},$$spc={init2:$spc.init2,auth:{}};export default $$spc;
|
||||
@@ -152,6 +152,7 @@ let $usr = {
|
||||
submit: function (e) {
|
||||
let c = $(this).ldng(1);
|
||||
let qs = c.serializeObject(true, { typedvalues: true });
|
||||
if (qs === null) { c.rejectInvalid(); return; }
|
||||
$ocms.postXT({
|
||||
url: $ocms.url('usr/create'), data: qs, success: function (response) {
|
||||
alert(response.emailed === true ? $uct.create_sent : $uct.create_noemail);
|
||||
@@ -187,6 +188,7 @@ let $usr = {
|
||||
submit: function (e) {
|
||||
let c = $(this).ldng(1);
|
||||
let qs = c.serializeObject(true, { typedvalues: true });
|
||||
if (qs === null) { c.rejectInvalid(); return; }
|
||||
$ocms.postXT({
|
||||
url: $ocms.url('usr/pwdreset'), data: qs, success: function (response) {
|
||||
alert(response.emailed === true ? $uct.pwdreset_sent : $uct.pwdreset_noemail);
|
||||
@@ -208,6 +210,7 @@ let $usr = {
|
||||
submit: function (e) {
|
||||
let c = $(this).ldng(1);
|
||||
let qs = c.serializeObject(true, { typedvalues: true });
|
||||
if (qs === null) { c.rejectInvalid(); return; }
|
||||
$ocms.postXT({
|
||||
url: $ocms.url('usr/email'), data: qs, success: function () {
|
||||
c.trigger('modal_close');
|
||||
|
||||
Vendored
+1
-1
File diff suppressed because one or more lines are too long
@@ -78,6 +78,7 @@ let $ugp = {
|
||||
submit: function (e) {
|
||||
let c = $(this).ldng(1);
|
||||
let qs = c.serializeObject(true, { typedvalues: true });
|
||||
if (qs === null) { c.rejectInvalid(); return; }
|
||||
$ocms.postXT({
|
||||
url: $ocms.url('usrgrp/create'), data: qs, success: function () {
|
||||
c.trigger('modal_close');
|
||||
@@ -99,6 +100,7 @@ let $ugp = {
|
||||
submit: function (e) {
|
||||
let c = $(this).ldng(1);
|
||||
let qs = c.serializeObject(true, { typedvalues: true });
|
||||
if (qs === null) { c.rejectInvalid(); return; }
|
||||
$ocms.postXT({
|
||||
url: $ocms.url('usrgrp/rename'), data: qs, success: function () {
|
||||
c.trigger('modal_close');
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
let $ugt={mdl:"Gruppenverwaltung",rel:"Neu Laden",col_name:"Name",loadfail:"Die Gruppenliste konnte nicht geladen werden.",empty:"Es sind keine Benutzergruppen vorhanden.",newgroup:"Neue Gruppe",newgroup_btn:"Anlegen",name_field:"Gruppenname",rename:"Gruppe umbenennen",rename_btn:"Speichern",delete:"Gruppe löschen",delete_confirm:'Soll die Gruppe "{0}" wirklich gelöscht werden? Die Mitgliedschaft aller Benutzer in dieser Gruppe geht dabei verloren.',err:{save_failed:"Die Gruppe konnte nicht gespeichert werden.",delete_failed:"Die Gruppe konnte nicht gelöscht werden."},err_generic:"Die Änderung konnte nicht gespeichert werden."},$ugp={init2:function(){$ocms.getScript([],(function(){$ugp.init3()}))},init3:function(){$fis.cf(!0),$fis.lf(!0),$("#activemodule").text($ugt.mdl),$ugp.eM(),$ugp.renderLst()},eM:function(e){let n=[{lbl:$ugt.newgroup_btn,fnc:$ugp.createDlg}];return!0===bool(e,!1)&&n.push({lbl:$ugt.rel,fnc:$ugp.renderLst}),$("#topbar").ocmsmenu(n)},iMn:function(e){return $("#topbar").ocmsmenu([{lbl:$ugt.rename,fnc:function(){$ugp.renameDlg(e)}},{lbl:$ugt.delete,fnc:function(){$ugp.deleteGroup(e)}}])},renderLst:function(){let e=$fis.frm_list(!0,!0).ldng(1),n=$$.dc("ugpfrm",e);$ugp.eM(!0),$ocms.postXT({url:$ocms.url("usrgrp/list"),success:function(e){n.empty();let t=$$.dc("ugp_grid",n),r=$$.dc("ugp_row ugp_row_hd",t);$$.dc("ugp_col_name",r).text($ugt.col_name),0!==(e.groups||[]).length?$.each(e.groups||[],(function(e,n){let r=$$.dc("ugp_row",t,{id:"ugp"+n.usergroup_id});$$.dc("ugp_col_name",r).text(n.name||""),r.click((function(){r.toggleClass("selected").siblings().rC("selected"),!0===r.is(".selected")?$ugp.iMn(n):$ugp.eM(!0)}))})):$$.dc("ugp_empty",t).text($ugt.empty)},error:function(){n.empty(),$$.dc("ugp_err",n).text($ugt.loadfail)},complete:function(){e.ldng(0)}})},createDlg:function(){$ocms.dlgform([{name:"name",label:$ugt.name_field,type:"string",required:!0}],{title:$ugt.newgroup,button:$ugt.newgroup_btn,submit:function(e){let n=$(this).ldng(1),t=n.serializeObject(!0,{typedvalues:!0});$ocms.postXT({url:$ocms.url("usrgrp/create"),data:t,success:function(){n.trigger("modal_close")},error:function(e){let n=((e||{}).responseJSON||{}).error;alert($ugt.err[n]||$ugt.err_generic)},complete:function(){n.ldng(0),$ugp.renderLst()}})}})},renameDlg:function(e){$ocms.dlgform([{name:"usergroup_id",type:"hidden",value:e.usergroup_id},{name:"name",label:$ugt.name_field,type:"string",required:!0,value:e.name}],{title:$ugt.rename,button:$ugt.rename_btn,submit:function(e){let n=$(this).ldng(1),t=n.serializeObject(!0,{typedvalues:!0});$ocms.postXT({url:$ocms.url("usrgrp/rename"),data:t,success:function(){n.trigger("modal_close")},error:function(e){let n=((e||{}).responseJSON||{}).error;alert($ugt.err[n]||$ugt.err_generic)},complete:function(){n.ldng(0),$ugp.renderLst()}})}})},deleteGroup:function(e){confirm(string($ugt.delete_confirm,[e.name||""]))&&$ocms.postXT({url:$ocms.url("usrgrp/delete"),data:{usergroup_id:e.usergroup_id},success:function(){$ugp.eM(!0)},error:function(e){let n=((e||{}).responseJSON||{}).error;alert($ugt.err[n]||$ugt.err_generic)},complete:function(){$ugp.renderLst()}})}},$$ugp={init2:$ugp.init2,auth:{}};export default $$ugp;
|
||||
let $ugt={mdl:"Gruppenverwaltung",rel:"Neu Laden",col_name:"Name",loadfail:"Die Gruppenliste konnte nicht geladen werden.",empty:"Es sind keine Benutzergruppen vorhanden.",newgroup:"Neue Gruppe",newgroup_btn:"Anlegen",name_field:"Gruppenname",rename:"Gruppe umbenennen",rename_btn:"Speichern",delete:"Gruppe löschen",delete_confirm:'Soll die Gruppe "{0}" wirklich gelöscht werden? Die Mitgliedschaft aller Benutzer in dieser Gruppe geht dabei verloren.',err:{save_failed:"Die Gruppe konnte nicht gespeichert werden.",delete_failed:"Die Gruppe konnte nicht gelöscht werden."},err_generic:"Die Änderung konnte nicht gespeichert werden."},$ugp={init2:function(){$ocms.getScript([],(function(){$ugp.init3()}))},init3:function(){$fis.cf(!0),$fis.lf(!0),$("#activemodule").text($ugt.mdl),$ugp.eM(),$ugp.renderLst()},eM:function(e){let n=[{lbl:$ugt.newgroup_btn,fnc:$ugp.createDlg}];return!0===bool(e,!1)&&n.push({lbl:$ugt.rel,fnc:$ugp.renderLst}),$("#topbar").ocmsmenu(n)},iMn:function(e){return $("#topbar").ocmsmenu([{lbl:$ugt.rename,fnc:function(){$ugp.renameDlg(e)}},{lbl:$ugt.delete,fnc:function(){$ugp.deleteGroup(e)}}])},renderLst:function(){let e=$fis.frm_list(!0,!0).ldng(1),n=$$.dc("ugpfrm",e);$ugp.eM(!0),$ocms.postXT({url:$ocms.url("usrgrp/list"),success:function(e){n.empty();let t=$$.dc("ugp_grid",n),r=$$.dc("ugp_row ugp_row_hd",t);$$.dc("ugp_col_name",r).text($ugt.col_name),0!==(e.groups||[]).length?$.each(e.groups||[],(function(e,n){let r=$$.dc("ugp_row",t,{id:"ugp"+n.usergroup_id});$$.dc("ugp_col_name",r).text(n.name||""),r.click((function(){r.toggleClass("selected").siblings().rC("selected"),!0===r.is(".selected")?$ugp.iMn(n):$ugp.eM(!0)}))})):$$.dc("ugp_empty",t).text($ugt.empty)},error:function(){n.empty(),$$.dc("ugp_err",n).text($ugt.loadfail)},complete:function(){e.ldng(0)}})},createDlg:function(){$ocms.dlgform([{name:"name",label:$ugt.name_field,type:"string",required:!0}],{title:$ugt.newgroup,button:$ugt.newgroup_btn,submit:function(e){let n=$(this).ldng(1),t=n.serializeObject(!0,{typedvalues:!0});null!==t?$ocms.postXT({url:$ocms.url("usrgrp/create"),data:t,success:function(){n.trigger("modal_close")},error:function(e){let n=((e||{}).responseJSON||{}).error;alert($ugt.err[n]||$ugt.err_generic)},complete:function(){n.ldng(0),$ugp.renderLst()}}):n.rejectInvalid()}})},renameDlg:function(e){$ocms.dlgform([{name:"usergroup_id",type:"hidden",value:e.usergroup_id},{name:"name",label:$ugt.name_field,type:"string",required:!0,value:e.name}],{title:$ugt.rename,button:$ugt.rename_btn,submit:function(e){let n=$(this).ldng(1),t=n.serializeObject(!0,{typedvalues:!0});null!==t?$ocms.postXT({url:$ocms.url("usrgrp/rename"),data:t,success:function(){n.trigger("modal_close")},error:function(e){let n=((e||{}).responseJSON||{}).error;alert($ugt.err[n]||$ugt.err_generic)},complete:function(){n.ldng(0),$ugp.renderLst()}}):n.rejectInvalid()}})},deleteGroup:function(e){confirm(string($ugt.delete_confirm,[e.name||""]))&&$ocms.postXT({url:$ocms.url("usrgrp/delete"),data:{usergroup_id:e.usergroup_id},success:function(){$ugp.eM(!0)},error:function(e){let n=((e||{}).responseJSON||{}).error;alert($ugt.err[n]||$ugt.err_generic)},complete:function(){$ugp.renderLst()}})}},$$ugp={init2:$ugp.init2,auth:{}};export default $$ugp;
|
||||
@@ -542,6 +542,7 @@ $ocms.postXT = function (options) {
|
||||
}
|
||||
if (options.form instanceof jQuery) {
|
||||
options.data = options.form.serializeObject();
|
||||
if (options.data === null) { options.form.rejectInvalid(); return; }
|
||||
options.contentType = 'form-data';
|
||||
} else if (options.lzw instanceof jQuery) {
|
||||
options.data.lzw = $.ccLZW(options.lzw.serializeAnything(true)).join(',');
|
||||
@@ -774,6 +775,13 @@ $ocms.vbl_send = function (ev) {
|
||||
c.toggleClass('invalid', !valid);
|
||||
return valid ? result : null;
|
||||
};
|
||||
/* For a form whose serializeObject() returned null: stop its loading indicator and let the
|
||||
browser point at the offending field, instead of submitting partial data. */
|
||||
$.fn.rejectInvalid = function () {
|
||||
var c = $(this).ldng(0), f = c.closest('form')[0] || c.find('form')[0];
|
||||
if (f && typeof f.reportValidity === 'function') { f.reportValidity(); }
|
||||
return c;
|
||||
};
|
||||
$.fn.sendForm = function (url, success, options) {
|
||||
var form = $(this);
|
||||
options = options || {};
|
||||
@@ -788,11 +796,13 @@ $ocms.vbl_send = function (ev) {
|
||||
if (typeof options.error === 'function') { options.error.call(this, jqXHR); } else {
|
||||
$ocms.failure.call(this, jqXHR);
|
||||
}
|
||||
}, complete: function () {
|
||||
}, complete: function (jqXHR) {
|
||||
form.ldng(0);
|
||||
if (typeof options.complete === 'function') { options.complete.call(this, jqXHR); }
|
||||
}
|
||||
};
|
||||
var formdata = form.serializeObject();
|
||||
if (formdata === null) { form.rejectInvalid(); return; }
|
||||
var fle = form.find('input[type="file"]');
|
||||
postoptions.data = new FormData();
|
||||
if (fle.length > 0) {
|
||||
@@ -801,8 +811,7 @@ $ocms.vbl_send = function (ev) {
|
||||
postoptions.data.append('file_lastmodified', $ocms.isodt(value.lastModifiedDate));
|
||||
});
|
||||
}
|
||||
var formdata = form.serializeObject();
|
||||
$.each(formdata || {}, function (di, dx) {
|
||||
$.each(formdata, function (di, dx) {
|
||||
postoptions.data.append(di, dx);
|
||||
});
|
||||
form.ldng();
|
||||
@@ -835,7 +844,7 @@ $ocms.login = {
|
||||
return false;
|
||||
} else {
|
||||
var qs = f.serializeObject();
|
||||
qs.loginaccount = ne(qs.loginaccount, $ocms.auth.account || $ocms.auth.requestedaccount || '');
|
||||
if (qs === null) { f.rejectInvalid(); return false; }
|
||||
qs.loginaccount = ne(qs.loginaccount, $ocms.auth.account || $ocms.auth.requestedaccount || '');
|
||||
if (ne(qs.loginaccount) === '' && bool($ocms.auth.accountrequired, true) === true ) {
|
||||
alert($t.l16);
|
||||
@@ -894,6 +903,7 @@ $ocms.login = {
|
||||
d.find('form').submit(function (e) {
|
||||
e.preventDefault();
|
||||
var qs = $(this).serializeObject(true), s2 = code === null, u = s2 ?'spwc':'spw';
|
||||
if (qs === null) { $(this).rejectInvalid(); return false; }
|
||||
$ocms.postXT.call(this, {
|
||||
url: $ocms.url(u), data: qs, complete: function () {
|
||||
if (s2) {
|
||||
|
||||
Vendored
+1
-1
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user