sdc_client 0.158.8 → 0.159.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. package/CHANGELOG.md +53 -0
  2. package/LICENSE +21 -0
  3. package/dist/index.js +49 -24
  4. package/dist/ugly.index.js +2 -1
  5. package/dist/ugly.index.js.LICENSE.txt +1 -8
  6. package/gulp/gulp.jsx +12 -42
  7. package/package.json +39 -31
  8. package/src/index.js +27 -7
  9. package/src/simpleDomControl/AbstractSDC.js +24 -11
  10. package/src/simpleDomControl/sdc_controller.js +7 -4
  11. package/src/simpleDomControl/sdc_dom_events.js +5 -10
  12. package/src/simpleDomControl/sdc_events.js +3 -3
  13. package/src/simpleDomControl/sdc_main.js +34 -13
  14. package/src/simpleDomControl/sdc_model.js +209 -84
  15. package/src/simpleDomControl/sdc_params.js +0 -3
  16. package/src/simpleDomControl/sdc_server_call.js +21 -4
  17. package/src/simpleDomControl/sdc_test_utils.js +0 -1
  18. package/src/simpleDomControl/sdc_utils.js +59 -7
  19. package/src/simpleDomControl/sdc_view.js +21 -1
  20. package/.github/workflows/node.js.yml +0 -38
  21. package/.idea/inspectionProfiles/Project_Default.xml +0 -17
  22. package/.idea/jsLibraryMappings.xml +0 -6
  23. package/.idea/misc.xml +0 -6
  24. package/.idea/modules.xml +0 -8
  25. package/.idea/vcs.xml +0 -6
  26. package/.idea/workspace.xml +0 -403
  27. package/.readthedocs.yaml +0 -13
  28. package/.tool-versions +0 -1
  29. package/SimpleDomControlClient.iml +0 -12
  30. package/docs/api-reference.rst +0 -225
  31. package/docs/conf.py +0 -11
  32. package/docs/controllers.rst +0 -228
  33. package/docs/events-and-dom.rst +0 -120
  34. package/docs/getting-started.rst +0 -143
  35. package/docs/index.rst +0 -22
  36. package/docs/models.rst +0 -351
  37. package/docs/overview.rst +0 -66
  38. package/docs/requirements.txt +0 -1
  39. package/eslint.config.js +0 -60
  40. package/gulpfile.jsx +0 -25
  41. package/jest.config.mjs +0 -197
  42. package/test/controller.test.js +0 -93
  43. package/test/dist.test.js +0 -127
  44. package/test/model.test.js +0 -330
  45. package/test/models/Author.js +0 -145
  46. package/test/models/Book.js +0 -112
  47. package/test/models/BookContent.js +0 -114
  48. package/test/models/SdcUser.js +0 -75
  49. package/test/models/src.js +0 -8
  50. package/test/sdc_model_dates.ai.test.js +0 -57
  51. package/test/sdc_server_call.ai.test.js +0 -267
  52. package/test/utils.js +0 -88
  53. package/test/view.test.js +0 -159
  54. package/test-setup.js +0 -4
  55. package/webpack.config/webpack.default.config.cjs +0 -22
  56. package/webpack.config/webpack.development.config.cjs +0 -14
  57. package/webpack.config/webpack.production.config.cjs +0 -11
@@ -1 +1,2 @@
1
- var e={};let t;function n(){return new Promise(function(e){e()})}function r(e){return(e=(e=e.replace(/[A-Z]/g,e=>`-${e.toLowerCase()}`)).replace(/[0-9]+/g,e=>`-${e}`)).replace(/^[-]/g,"")}function s(e){return e.replace(/-./g,e=>`${e[1].toUpperCase()}`)}e.d=(t,n)=>{for(var r in n)e.o(n,r)&&!e.o(t,r)&&Object.defineProperty(t,r,{enumerable:!0,get:n[r]})},e.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t);const o=(e,t)=>{let n=t,r=Object.getOwnPropertyNames(e.prototype).concat(Object.getOwnPropertySymbols(e.prototype));for(;""!==n.name;)Object.getOwnPropertyNames(n.prototype).concat(Object.getOwnPropertySymbols(n.prototype)).forEach(t=>{t.match(/^(?:constructor|prototype|arguments|caller|name|bind|call|apply|toString|length)$/)||r.includes(t)||(r.push(t),Object.defineProperty(e.prototype,t,Object.getOwnPropertyDescriptor(n.prototype,t)))}),n=Object.getPrototypeOf(n)};function i(e,t,n){return $.ajax({url:t,type:n||"POST",xhr:function(){var e=$.ajaxSettings.xhr();return e.upload&&e.upload.addEventListener("progress",l,!1),e},data:e,cache:!1,contentType:!1,processData:!1,beforeSend:function(e,t){(function(e){return/^(GET|HEAD|OPTIONS|TRACE)$/.test(e)})(t.type)||this.crossDomain||e.setRequestHeader("X-CSRFToken",window.CSRF_TOKEN)}})}function l(e){if(e.lengthComputable){var t=Math.round(e.loaded/e.total*100),n=$(".progress-container");100===t?n.hide():n.show(),t+="%",n.find(".progress-bar").css({width:t}).text(t)}}function a(e,t=null){return"string"!=typeof e?e:t&&void 0!==t[e]?"function"==typeof t[e]?t[e].bind(t):t[e]:e.match(/^(true|false)$/)?"true"===e:"undefined"!==e?"none"===e.toLowerCase()?null:e.match(/^-?\d+$/)?parseInt(e):e.match(/^-?\d+\.?\d+$/)?parseFloat(e):e.match(/^(['][^']*['])|(["][^"]*["])$/)?e.substr(1,e.length-2):e:void 0}function c(){return([1e7]+-1e3+-4e3+-8e3+-1e11).replace(/[018]/g,e=>(e^crypto.getRandomValues(new Uint8Array(1))[0]&15>>e/4).toString(16))}function u(e){e.find(".has-error").removeClass("has-error").find(".alert-danger").remove(),e.find(".non-field-errors").remove()}function d(e,t){t=$("<div>").append(t),e.find(".has-error").removeClass("has-error").find(".alert-danger").safeRemove(),e.find(".non-field-errors").safeRemove();let n=t.find("input[type=file]").parent();e.find("input[type=file]").parent().each(function(e){$(this).replaceWith(n[e])});let r=0===t.find(".non-field-errors").insertAfter(e.find(".hidden-form-fields")).length;return t.find(".has-error").each(function(){r=!1;let t=$(this),n=t.data("auto-id"),s=e.find(".form-group."+n);s.addClass("has-error"),s.find(".form-input-container").append(t.find(".alert-danger"))}),r}function h(e){let{type:t,name:n}=e;return n&&""!==n?"hidden"===t?(r=$(e).val()).toLowerCase().match(/^(true|false)$/)?"true"===r.toLowerCase():"undefined"!==r?"none"===r.toLowerCase()?null:r.match(/^-?\d+$/)?parseInt(r,10):r.match(/^-?\d+\.?\d+$/)?parseFloat(r):r.match(/^(['][^']*['])|(["][^"]*["])$/)?r.substring(1,r.length-1):r:void 0:"checkbox"===t?e.checked:"file"===t?e.files[0]:$(e).val():null;var r}function m(e,t){let{type:n,name:r}=e;if(r&&""!==r)if("checkbox"===n)e.checked=!!t;else if("file"===n){if(t instanceof File&&"undefined"!=typeof DataTransfer){let n=new DataTransfer;n.items.add(t),e.files=n}}else t instanceof ae?$(e).val(t.id):t instanceof le?$(e).val(`[${t.getIds().join(",")}]`):(null===t&&(t=""),$(e).val(t));return null}function f(e,t=null){return Object.fromEntries(Object.entries(e).filter(([e,t])=>e!==A).map(([e,n])=>{if("string"==typeof n&&n.startsWith("SDC_JSON_MODEL=["))try{const{pk:t,fields:r}=JSON.parse(n.slice(16,-1));return[e,{...r,id:t,id:t}]}catch{}return[e,a(n,t)]}))}function p(e,t=null){return f(e.data(),t)}const y=["onbeforeunload","onunload"],g=Object.keys(window).filter(e=>/^on/.test(e)&&!y.includes(e)).map(e=>e.slice(2));function v(e,t,n){let r;switch(e){case"mouseleave":case"mouseout":case"mouseenter":case"mousein":return r=document.elementFromPoint(t.clientX,t.clientY),n!==r&&!n.contains(r);default:return!0}}function w(e){let t=e.type;e.hasOwnProperty("namespace")&&e.namespace&&e.namespace.length&&(t+=`.${e.namespace}`);let n=$(e.target),r=null,s=!1,o=!1;for(e.stopImmediatePropagation=()=>o=!0,e.stopPropagation=()=>o=s=!0;n.length;){let i=n.attr(`sdc_${t}`);if(i&&v(t,e,n[0])){if(!r&&(r=Q(n),!r))return;for(;r;){if(i.split(" ").forEach(o=>{if(s)return;let i=null;if("function"==typeof o)i=o;else if("function"==typeof r[o])i=r[o];else if("string"==typeof o&&o.startsWith("this.event_")){if(i=r.getEvents()[t],!i)return;if(i=i[o.slice(11)],!i)return}i&&i.call(r,n,e)}),o)return;r=r._parentController}}if(s)return;n=n.parent()}return{res:!0}}function b(e){if(e._isEventsSet)return;const t=e.getEvents();for(let n in t)if(t.hasOwnProperty(n)){let r=t[n];for(let t in r)r.hasOwnProperty(t)&&e.find(t).each(function(){let e=$(this),r=e.attr(`sdc_${n}`)||null;r=r?r.split(" "):[];const s=`this.event_${t}`;-1===r.indexOf(s)&&(r.push(s),e.attr(`sdc_${n}`,r.join(" ")))})}}let R=[],N={};function C(e,t){if(e){let n=s(t._tagName);e._childController[n]||(e._childController[n]=[]),e._childController[n].push(t)}return t._parentController=e}function O(e,t,n,r){let s=[];r=function(e,t){e=(e=e.concat(N[t][1])).filter((e,t,n)=>n.indexOf(e)===t);let n=!0;for(;n;){n=!1;for(let t of e)for(let r of N[t][1])e.includes(r)||(e.push(r),n=!0)}return e}(r,n);for(let e of r)s.push(N[e][0]);let i=new(function(e,...t){let n={[e.name]:class{constructor(...n){let r={};t.forEach(e=>{let t;Object.assign(this,t=new e),t._tagName=e.prototype._tagName,t._isMixin=!0,r[e.name]=t}),Object.assign(this,new e),this._mixins=r}static get name(){return e.name}static className(){return this.name}get mixins(){return this._mixins}}}[e.name];return o(n,e),t.forEach(e=>{o(n,e)}),n}(N[n][0],...s));return i._tagName=n,C(e,i),i.$container=t,function(e,t){!function(e,t,n){e&&"function"==typeof e.onInit&&(e.params=p(t,n._parentController))}(t,e,t)}(t,i),i}function S(e,t,n,r){if(R.includes(n)){let o=s(n);return window[o]||(window[o]=O(e,t,n,r)),window[o].$container=t,window[o]}return O(e,t,n,r)}function F(e,t){const r=function(e){return function(e){let t={args:{}};return e.contentUrl&&(t=V(e),e.contentUrl=t.url),Promise.all([D(e,t.args)]).then(function(e){let t=e[0];if(t)try{return $(t)}catch{return $("<div></div>").append(t)}return null})}(e).then(t=>!e.onLoad||e._onLoadDone?t:(e._onLoadDone=!0,(e.onLoad(t)||n()).then(()=>t)))}(e).then(function(t){return function(e,t){return W(e,t).then(function(t){if(t=t||!0,e.willShow){let n=e.willShow();if(n instanceof Promise)return n.then(function(){return t})}return t})}(e,t)}).then(()=>function(e,t){return X(null,e,t)}(e,t)).catch(function(t){return W(e,t)});return e.load_async?Promise.resolve():r}function E(e){const t=function(e){let t=[];for(;e;)e._isEventsSet=!1,t.unshift(e),e=e._parentController;return t}(e.controller[0]),n=t.concat(e.controller.slice(1));for(let t of n)b(t),t.onRefresh(e.controller[0])}function k(e,t){let n=Boolean(e);return n?e.uuids.has(t._uuid)||(e.uuids.add(t._uuid),e.controller.push(t)):e={uuids:new Set([t._uuid]),controller:[t]},{isRunningProcess:n,refreshProcess:e}}let P={},x={};function L(e,t){return j(e),x.hasOwnProperty(e)?t[x[e]]?void P[e].push(t):console.log("No event handler: "+e,t):console.log("No event: "+e,t)}function j(e,t){t||(t=e),x[e]||(x[e]=t,P[e]=[])}function I(e){for(let t in P)if(P.hasOwnProperty(t))for(let n=P[t].length-1;n>=0;n--)e===P[t][n]&&P[t].splice(n,1)}function q(e){let t=Array.apply(null,arguments);if(e=t.shift(),!P.hasOwnProperty(e)||!x.hasOwnProperty(e))return n();let r=P[e],s=x[e],o=[];for(let e=0;e<r.length;e++){let n=r[e][s].apply(r[e],t);void 0!==n&&o.push(n)}return Promise.all(o)}let T={};const A="_controller_",M="_sdc_controller_";function U(e,t,n){if(!e)return[];let r=e.children(),s=[];return r.each(function(e,r){let o=$(r),i=o.prop("tagName").toLowerCase().split("_");$.inArray(i[0],t)>=0?s.push({tag:i[0],super:i.splice(1)||[],dom:o}):i[0].startsWith("this.")?o.addClass(`_bind_to_update_handler sdc_uuid_${n._uuid}`):s=s.concat(U(o,t,n))}),s}function D(e,t){const{contentUrl:n,_tagName:r,contentReload:s}=e;return n?T[r]?Promise.resolve(T[r]):(t.VERSION=we.VERSION,t._method="content",$.get(n,t).then(function(e){return s||(T[r]=e),e}).catch(function(t){throw 301===t.status&&q("_RedirectOnView",t.responseJSON["url-link"]),"function"==typeof e.confirmPageLoaded&&q("navLoaded",{controller_name:()=>t.status}),`<sdc-error data-code="${t.status}">${t.responseText}</sdc-error>`})):Promise.resolve(!1)}function J(e,t,n=null){return t=t||e.data(A),G(we.tagNames,e,t,n)}function V(e){let t=e.contentUrl;if(e&&0===e._urlParams.length){let n,r=/%\(([^)]+)\)\w/gm;for(e._urlParams=[];n=r.exec(t);)e._urlParams.push(n[1]),e.contentReload=!0}let{args:n,params:r}=function(e,t){const n=p(t,e),[r,s]=Object.entries(n).reduce(([t,n],[r,s])=>(e._urlParams.includes(r)?t[r]=s:n[r]=s,[t,n]),[{},{}]);return{params:r,args:s}}(e,e.$container);return e._urlParams.length&&(t=function(e,t,n){for(let r in e._urlParams)if(e._urlParams.hasOwnProperty(r)){let s=e._urlParams[r],o=RegExp("%\\("+s+"\\)\\w","gm");const i=n[s];i||console.warn(`${s} is not set for controller ${e._tagName}`),t=t.replace(o,i)}return t}(e,t,r)),e.parsedContentUrl=t,{url:t,args:n}}function Q(e){return e.hasClass(M)?e.data(`${A}`):e.closest(`.${M}`).data(`${A}`)}function B(e,t,n,r,s){let o=e.data(A);return o?J(e,o,s):(o=S(r,e,t,n),e.data(A,o),e.addClass(M),F(o,s))}function W(e,t,n=null){if(t&&t.length>0){e.$container.empty(),e.$container.attr(e._tagName,"");for(let t in e._mixins)e.$container.attr(e._mixins[t]._tagName,"");e.$container.append(t)}return J(e.$container,e,n)}function G(e,t,n,r){return new Promise(s=>{let o=U(t,e,n),i=o.length;if(0===i)return s();for(let e=0;e<o.length;e++)B(o[e].dom,o[e].tag,o[e].super,n,r).then(()=>{if(i--,0===i)return s()})})}function z({$element:e,id:t=[],parent:n=null}){t.push(function(e){if(3===e[0].nodeType)return`TEXT__${e[0].nodeValue}`;const t=[e[0].tagName];return"INPUT"===e[0].nodeName&&[["name",""],["type","text"],["id",""]].forEach(([n,r])=>{const s=e.attr(n)??r;s&&t.push(s)}),t.join("__")}(e));const r={$element:e,id:t.join("::"),depth:t.length,idx:0,getRealParent:()=>n,getIdx:function(){return this.idx=Math.max(0,(this.getRealParent()?.getIdx()??-1)+e.index()+1),this.idx},op:null,parent:n};return r.getIdx.bind(r),[r].concat(e.contents().toArray().map(e=>z({$element:$(e),id:t.slice(),parent:r})).flat())}function K(e,t){const n=z({$element:t}),r=z({$element:e});n.map((e,t)=>e.idx=t),r.map((e,t)=>e.idx=t);const s=Math.max(...r.concat(n).map(e=>e.depth)),o=H(n,r,s);let i=[];window.MAIN=t,window.OPS=o,o.forEach((e,t)=>{const{op:n,$element:r,idx:s}=e;if("keep_counterpart"===n.type){if(n.counterpart.getIdx()!==s){const t=e.getBefore();t?n.counterpart.$element.insertAfter(t.$element):e.getRealParent().$element.prepend(n.counterpart.$element)}!function(e,t){const n=e[0].attributes??[],r=t[0].attributes??[];[...n].forEach(n=>{t.is(`[${n.name}]`)||e.removeAttr(n.name)}),[...r].forEach(t=>{t.name.startsWith("data")||e.attr(t.name)===t.value||e.attr(t.name,t.value)}),e.removeData(),Object.entries(t.data()).forEach(([t,n])=>{e.data(t,n)})}(n.counterpart.$element,r),r.hasClass(M)&&(r.data(A).$container=n.counterpart.$element,r.data(A,null)),i.push(r)}else if("delete"===n.type)r.safeRemove();else if("insert"===n.type){const{after:t,target:n}=e.op;t?r.insertAfter(t.$element):n&&n.$element.prepend(r)}}),i.forEach(e=>e.safeRemove())}function H(e,t,n){return t.filter(e=>e.depth===n&&!e.op).forEach(t=>{const n=e.find(e=>!e.op&&e.id===t.id);if(n){const e=(t,n)=>{t.op={type:"keep",idx:n.idx},n.op={type:"keep_counterpart",counterpart:t},t=t.parent,n=n.parent,!t||t.op||n?.op||e(t,n)};e(n,t)}}),n>1?H(e,t,n-1):(e.forEach((t,n)=>{if(!t.op){const r=(e[n-1]?.op.idx??-1)+1;t.op={type:"delete",idx:r}}}),t.forEach((e,n)=>{if(e.getBefore=()=>function(e,n){const r=e.depth;for(;n>=1&&e.depth>=r;)if((e=t[n-=1]).depth===r)return"keep_counterpart"===e.op.type?e.op.counterpart:e;return null}(e,n),e.getRealParent=()=>{return(t=e).parent?"keep_counterpart"===t.parent.op.type?t.parent.op.counterpart:t.parent:null;var t},!e.op){const t=e.getRealParent(),n="insert"===t?.op.type?"insert_ignore":"insert";e.op={type:n,target:t,after:e.getBefore()}}}),[...e,...t].sort((e,t)=>(e.op?.idx??e.idx)-(t.op?.idx??t.idx)))}function X(e,t,n=null){if(t||(t=Q(e)),!t)return Promise.resolve();const{refreshProcess:r,isRunningProcess:s}=k(n,t);return e??=t.$container,G(we.tagNames,e,t,n).then(()=>function(e,t,n){return function(e,t,n){const r=[];return t.find(`._bind_to_update_handler.sdc_uuid_${e._uuid}`).each(function(){const t=$(this);let s;if(t.hasClass("_with_handler"))s=t.data("handler");else{let t=this.tagName.toLowerCase().replace(/^this./,"");e[t]&&(s=e[t])}if("function"==typeof s){const n=f(t.data(),e);s=s.bind(e)(n)}s&&r.push(Promise.resolve(s).then(r=>{let s=$("<div></div>");return s.append(r),""===t.html()&&t.append("<div></div>"),we.reconcile(e,s,t.children(),n)}))}),Promise.all(r)}(e,t??e.$container,n)}(t,e,r).then(()=>{s||E(r)}))}const Y={};function Z(e,t){Y[e]=t}function ee(e){return Y[e]}const te=25e3,ne="_connecting_process",re=e=>Object.assign(Object.create(Object.getPrototypeOf(e)),structuredClone(e));class se extends Error{constructor(e){"string"==typeof e&&(e={msg:e,is_error:!0,header:"Error"}),super(e.msg),this.msg=e.msg,this.header=e.header,this.is_error=e.is_error,this.html=e.html}}class oe{constructor({name:e,url:t}){this.name=e,this.url=t,this.content=null}async load(e=!1){return!e&&this.content||(this.content=await new Promise((e,t)=>{$.get(this.url).then(e).catch(()=>{e("")})})),this.content}async text(){return this.load()}static isValid(e){return!(null===e||"object"!=typeof e||Array.isArray(e)||e instanceof File||"string"!=typeof e.url||"string"!=typeof e.name)}}function ie(e){const t=parseInt(e??-1,10);return Number.isNaN(t)?-1:t}class le{constructor(e,t={}){return this.valuesList=[],this.loaded=!1,this.modelName=e,this.modelQuery=t??{},this._onNoOpenRequests=[],this._isConnected=!1,this._isConnectingProcess=!1,this._autoReconnect=!0,this.socket=null,this.openRequest={},this.modelId=0,this.onUpdate=()=>{},this.onCreate=()=>{},new Proxy(this,{get:(e,t)=>"symbol"==typeof t||isNaN(t)?e[t]:e.valuesList[t],set:(e,t,n)=>isNaN(t)?(e[t]=n,!0):(e.valuesList[t]=n,!0)})}[Symbol.iterator](){let e=-1;return{next:()=>(++e,e<this.valuesList.length?{value:this.valuesList[e],done:!1}:{value:null,done:!0})}}set on_create(e){this.onCreate=e}set on_update(e){this.onUpdate=e}setIds(e){const t=this._setIds(e),n={id__in:t.map(e=>e.id)};return this.setFilter(n),t}cloneObject;_setIds(e){if(null===e||""===e||Array.isArray(e)&&0===e.length)return this.valuesList=[],this.valuesList;if(e instanceof le)return this.valuesList=e.valuesList.map(re),this.valuesList.forEach(e=>e._setQuerySet(this,!0)),this.valuesList;if(e instanceof ae)return this.valuesList=[re(e)],this.valuesList.forEach(e=>e._setQuerySet(this,!0)),this.valuesList;let t,n=Number.NaN;if(Number.isInteger(e))n=e;else if(e instanceof Array){const n=e.map(e=>parseInt(e));n.some(Number.isNaN)||(t=n)}else if("string"==typeof e){const r=e.split(",").map(e=>parseInt(e));r.some(Number.isNaN)?n=parseInt(e):t=r}if(Number.isNaN(n)){if(t){this.valuesList=this.valuesList.filter(e=>t.includes(e.id));const e=this.getIds();t.filter(t=>!e.includes(t)).forEach(e=>{this.valuesList.push(new(ee(this.modelName))({id:e}))})}}else this.valuesList=this.valuesList.filter(e=>n===e.id),0===this.valuesList.length&&(this.new().id=n);return this.valuesList}getIds(){return this.valuesList.map(e=>e.id)}get length(){return this.valuesList.length}byId(e){if(null!==e){const t=ie(e);return this.valuesList.find(e=>e.id===t)??null}return null}setFilter(e){return this.modelQuery=e,this}addFilter(e){return this.modelQuery=Object.assign({},this.modelQuery,e),this}new(e={}){const t=new(ee(this.modelName))(e);return t._setQuerySet(this,!1),this.valuesList.push(t),t}load(e=null){return this.valuesList=[],this.modelQuery=e??this.modelQuery,this._sendLoad()}update({modelQuery:e=null,item:t=null}){this.modelQuery=e??this.modelQuery;let n=t?{id:t.id}:this.modelQuery;return this._sendLoad(n)}delete({pk:e=null,id:t=null,elem:n=null}){if(e??=t,null===(e=n?n.id:e))throw new Error("pk or elem must be set");const r=c();return this.isConnected().then(()=>new Promise((t,n)=>{this.socket.send(JSON.stringify({event:"model",event_type:"delete",event_id:r,args:{model_name:this.modelName,model_query:this.modelQuery,id:e,pk:e}})),this.openRequest[r]=[t,n]}))}_sendLoad(e=null){return this.isConnected().then(()=>{const t=c();return new Promise((n,r)=>{this.socket.send(JSON.stringify({event:"model",event_type:"load",event_id:t,args:{model_name:this.modelName,model_query:e??this.modelQuery}})),this.openRequest[t]=[e=>{this.loaded=!0,n(e)},r]})})}_sendListView({modelQuery:e={},cbResolve:t=null,cbReject:n=null,templateContext:r={}}){return this.view({modelQuery:e,cbResolve:t,cbReject:n,templateContext:r,eventType:"list_view"})}view({viewName:e="html_list_template",modelQuery:t={},cbResolve:n=null,cbReject:r=null,templateContext:s={},eventType:o="named_view"}){let i=$('<div class="container-fluid">');return this.isConnected().then(()=>{const l=c();this.socket.send(JSON.stringify({event:"model",event_type:o,event_id:l,args:{view_name:e,model_name:this.modelName,model_query:t,template_context:s}})),this.openRequest[l]=[e=>{i.append(e.html),we.refresh(i),n&&n(e)},e=>{r&&r(e)}]}),i}_sendDetailView({pk:e=null,id:t=null,cbResolve:n=null,cbReject:r=null,templateContext:s={}}){e??=t,e=ie(e);let o=$('<div class="container-fluid">');return this.isConnected().then(()=>{const t=c();this.socket.send(JSON.stringify({event:"model",event_type:"detail_view",event_id:t,args:{model_name:this.modelName,model_query:this.modelQuery,id:e,pk:e,template_context:s}})),this.openRequest[t]=[e=>{o.append(e.html),we.refresh(o),n&&n(e)},e=>{r&&r(e)}]}),o}getForm({modelObj:e,eventType:t,formName:n,$divForm:r,cbResolve:s,cbReject:o,formId:i}){const l=c(),a=e.id??-1;this.isConnected().then(()=>{this.socket.send(JSON.stringify({event:"model",event_type:t,event_id:l,args:{model_name:this.modelName,id:a,pk:a,form_name:n}}))});const u=null===a||-1===a?"create":"edit";this.openRequest[l]=[t=>{r.append(t.html);let o=r.closest("form").addClass(`sdc-model-${u}-form sdc-model-form ${i}`).data("model",e).data("model_pk",a).data("form_name",n);e.addForm(o),o.length>0&&!o[0].hasAttribute("sdc_submit")&&o.attr("sdc_submit","submitModelFormDistributor"),we.refresh(r).then(()=>null),s&&s(t)},e=>{o&&o(e)}]}async get(e=null,t=!1){if(t){const t=e?.id??this.modelQuery?.id;return e&&this.setFilter(e),this.byId(t)??this.new(e||this.modelQuery)}if(await this.load(e),1!==this.length)throw new Error(`model query returns ${this.length} but only 1 expected.`);return this.addFilter({id:this.valuesList[0].id}),this.valuesList[0]}detailView({pk:e,cbResolve:t=null,cbReject:n=null,templateContext:r={}}){return this._sendDetailView({id:e,cbResolve:t,cbReject:n,templateContext:r})}listView({modelQuery:e={},searchValues:t={},cbResolve:n=null,cbReject:r=null,templateContext:s={}}){return this._sendListView({modelQuery:Object.assign({},this.modelQuery,e,{__search_values:t}),cbResolve:n,cbReject:r,templateContext:s})}save({pk:e=null,id:t=null,formName:n="edit_form",data:r=null}={}){e??=t;const s=ie(e);return this.isConnected().then(()=>{let e;if(s>-1){const t=this.byId(s);if(!t)return Promise.reject(new se(`Element not found with ID: ${s}`));e=[t]}else e=this.valuesList;let t=[];return e.forEach(e=>{const s=c();t.push(new Promise((t,o)=>{this._readFiles(e).then(i=>{const l=r?{...r}:e.serialize();l.id=e.id,this.socket.send(JSON.stringify({event:"model",event_type:"save",event_id:s,args:{form_name:n,model_name:this.modelName,model_query:this.modelQuery,data:l,id:l.id,pk:l.id,files:i}})),this.openRequest[s]=[e=>{let n="string"==typeof e.data.instance?JSON.parse(e.data.instance):e.data.instance;e.data.instance=this._parseServerRes(n),t(e)},o]})}))}),Promise.all(t)})}create({elem:e=null,data:t=null}={}){const n=c();return e||(e=this.new(t)),this.isConnected().then(()=>new Promise((r,s)=>{this._readFiles(e).then(o=>{this.socket.send(JSON.stringify({event:"model",event_type:"create",event_id:n,args:{model_name:this.modelName,model_query:this.modelQuery,data:t??e?.serialize()??{},files:o}})),this.openRequest[n]=[t=>{let n="string"==typeof t.data.instance?JSON.parse(t.data.instance):t.data.instance;e&&(e.id=n[0]?.id||n[0]?.pk),t.data.instance=this._parseServerRes(n)[0],r(t)},s]})}))}isConnected(){return new Promise((e,t)=>{if(this._isConnected)e();else if(this._isConnectingProcess&&this.openRequest[ne]){const[n,r]=this.openRequest[ne];this.openRequest[ne]=[()=>{n(),e()},()=>{r(),t()}]}else this._isConnectingProcess=!0,this.openRequest[ne]=[()=>{},()=>{}],this._connectToServer().then(()=>{e(this._checkConnection())})})}close(){this.socket&&(this._autoReconnect=!1,this.socket.onclose=()=>{},this.socket.close(),delete this.socket),this.valuesList.forEach(e=>{e._onClose()})}_readFiles(e){let t=[],n={};return e?(Object.keys(e.constructor.fields).forEach(r=>{const s=e[r];s instanceof File&&t.push(new Promise(async(e,t)=>{const o=c();this.openRequest[o]=[e,t];const i=await s.arrayBuffer();let l=new Uint8Array(i),a=Math.ceil(l.length/te);n[r]={id:o,file_name:s.name,field_name:r,content_length:s.size};for(let e=0;e<a;++e){const t=Array.from(l.slice(te*e,te*(e+1)));this.socket.send(JSON.stringify({event:"model",event_type:"upload",event_id:o,args:{chunk:t,idx:e,number_of_chunks:a,file_name:s.name,field_name:r,content_length:s.size,content_type:s.type,model_name:this.modelName,model_query:this.modelQuery}}))}}))}),Promise.all(t).then(()=>n)):Promise.resolve(n)}async _onMessage(e){let t=JSON.parse(e.data);if(t.is_error)this.openRequest.hasOwnProperty(t.event_id)&&(this.openRequest[t.event_id][1](new se(t)),this._closeOpenRequest(t.event_id)),(t.msg||t.header)&&q("pushErrorMsg",t.header||"",t.msg||""),"connect"===t.type&&(this.openRequest[ne][1](new se(t)),this._closeOpenRequest(ne),this._autoReconnect=!1,this.socket.close());else{if((t.msg||t.header)&&q("pushMsg",t.header||"",t.msg||""),"connect"===t.type)this._isConnected=!0,this._isConnectingProcess=!1,this.openRequest[ne][0](t),this._closeOpenRequest(ne);else if(["load","named_view","detail_view"].includes(t.type)){const e=JSON.parse(t.args.data);t.args.data=await this._parseServerRes(e)}else if("on_update"===t.type||"on_create"===t.type){const e=JSON.parse(t.args.data);let n,r=await this._parseServerRes(e);n="on_create"===t.type?this.onCreate:this.onUpdate,n(r),t.args.data=r}let e=t.data?.instance;e&&(t.data.instance=JSON.parse(t.data.instance)),this.openRequest.hasOwnProperty(t.event_id)&&(this.openRequest[t.event_id][0](t),this._closeOpenRequest(t.event_id))}}noOpenRequests(){return new Promise(e=>{if(0===Object.keys(this.openRequest).length)return e();this._onNoOpenRequests.push(e)})}_closeOpenRequest(e){delete this.openRequest[e],0===Object.keys(this.openRequest).length&&(this._onNoOpenRequests.forEach(e=>e()),this._onNoOpenRequests=[])}_connectToServer(){return new Promise(e=>{const t=`${this.modelName}`+(this.modelId>0?`/${this.modelId}`:"");"https:"===window.location.protocol?this.socket=new WebSocket(`wss://${window.location.host}/sdc_ws/model/${t}`):this.socket=new WebSocket(`ws://${window.location.host}/sdc_ws/model/${t}`),this.socket.onmessage=this._onMessage.bind(this),this.socket.onclose=e=>{console.error(`SDC Model (${this.modelName}, ${this.modelId}) Socket closed unexpectedly`),this._isConnected=!1;for(const[t,n]of Object.entries(this.openRequest))n[1](e);this.openRequest={},setTimeout(()=>{this._autoReconnect&&this._connectToServer().then(()=>{})},1e3)},this.socket.onerror=e=>{if(console.error(`Model Socket encountered error: ${e} Closing socket`),this._isConnected)try{this.socket.close()}catch(e){}},this.socket.onopen=()=>{e()}})}_checkConnection(){const e=c();return new Promise((t,n)=>{this.socket.send(JSON.stringify({event:"model",event_type:"connect",event_id:e,args:{model_name:this.modelName,model_query:this.modelQuery}})),this.openRequest[e]=[t,n]})}_parseServerRes(e){const t=[];for(const n of e){const e=ee(this.modelName);if(!e)throw new Error(`${this.modelName} is no SdcModel. mybe the models ar not importad.`);const r=new e({id:n.id??n.pk,...n.fields}),s=this.byId(r.id);s?(s.setValues(r),t.push(s)):(this.valuesList.push(r),r._setQuerySet(this,!0),t.push(r))}return this.valuesList.sort((e,t)=>e._id-t._id),t}}class ae{static fields={};constructor(e){this._id=null,this._forms=[],this.loaded=!1,this.formId=c(),this.modelName=e}static querySet(e=null,t=null){return t?t.querySet(this.modeName,e):new le(this.modeName,e)}addForm(e){const t=this._onChange.bind(this);this._forms.push(e),e&&e.on("input.formWatcher change.formWatcher","input, select, textarea",t)}_onChange(e){const{name:t}=e.target;this.constructor.fields[t]&&this[`set${t}`](h(e.target))}_updateForm(e){const t=this;this._forms.forEach(n=>{n.find(`[name="${e}"]`).each(function(){m(this,t[e])})})}setValues(e={}){throw new Error("setValues() must be implemented by subclass")}_setQuerySet(e,t){this._querySet=new WeakRef(e),this.loaded=t}get querySet(){return this._querySet.deref()}save({formName:e="edit_form",data:t=null}={}){return this._querySet.deref().save({pk:this.id,formName:e,data:t})}create({data:e=null}={}){return this._querySet.deref().create({elem:this,data:e})}delete(){return this._querySet.deref().delete({elem:this})}load(){return this._querySet.deref().update({item:this})}update(){return this.load()}get id(){return this._id}set id(e){this._id=e}set pk(e){this.id=e}get pk(){return this._id}close(){return this._querySet.deref().close()}_onClose(){Object.keys(this.constructor.fields).filter(e=>this[`_${e}`]instanceof le).forEach(e=>this[`_${e}`].close())}detailView({cbResolve:e=null,cbReject:t=null,templateContext:n={}}){return this._querySet.deref().detailView({pk:this.id,cbResolve:e,cbReject:t,templateContext:n})}serialize(){return Object.entries(this.constructor.fields).reduce((e,[t,n])=>{const r=this[t];if(r instanceof le)if(n.many_to_many||n.one_to_many)e[t]=r.getIds();else{const n=r.getIds();n.length>0?e[t]=n[0]:e[t]=null}else n.is_relation&&r instanceof ae?e[t]=r.id??null:e[t]=r;return e},{})}toJson(){const e={};for(let t in this.constructor.fields){const n=this[t];n instanceof File?e[t]=n.name:e[t]=n instanceof ae?n.id:n instanceof le?n.getIds():n}return e}syncFormToModel(e){return this.syncForm(e)}_resolveForms(e){return e&&e.hasClass(this.formId)?e:$(`.${this.formId}`)}syncModelToForm(e){e=this._resolveForms(e);const t=this,n=this.constructor.fields;e.each(function(){const e=ie($(this).data("model_pk"));if(t.id===e)for(let e of this.elements){let r=e.name;r&&""!==r&&n[r]&&m(e,t[r])}})}syncForm(e){e=this._resolveForms(e);const t=this,n=this.constructor.fields,r={};function s(e,s){n[e]&&(t[e]=s),r[e]=s}return e.each(function(){const e=ie($(this).data("model_pk"));if(t.id===e||null===t.id&&-1===e){for(let e of this.elements)s(e.name,h(e));return t}}),r}form({cbResolve:e=null,cbReject:t=null}={}){return null===this.id||-1===this.id?this._createForm({cbReject:t,cbResolve:e}):this._editForm({cbReject:t,cbResolve:e})}_createForm({cbResolve:e=null,cbReject:t=null}){let n=$("<div>");return this._querySet.deref().getForm({modelObj:this,eventType:"create_form",formName:null,$divForm:n,cbResolve:e,cbReject:t,formId:this.formId}),n}_editForm({cbResolve:e=null,cbReject:t=null}){let n=$("<div>");return this._querySet.deref().getForm({modelObj:this,eventType:"edit_form",formName:null,$divForm:n,cbResolve:e,cbReject:t,formId:this.formId}),n}namedForm({formName:e,cbResolve:t=null,cbReject:n=null}){let r=$('<div class="container-fluid">');return this._querySet.deref().getForm({modelObj:this,eventType:"named_form",formName:e,$divForm:r,cbResolve:t,cbReject:n,formId:this.formId}),r}validate(e,t){const n=function(e,t){const{type:n,required:r,max_length:s,is_relation:o,many_to_many:i,one_to_many:l,many_to_one:a,one_to_one:c,related_model:u}=t;if(r&&(null==e||""===e))return"This field is required";if(null==e||""===e)return null;if((i||l||a||c)&&(!(e instanceof le)||e.modelName!==u))return"string"==typeof e&&(e=JSON.parse(e)),(i||a)&&Array.isArray(e)&&e.some(e=>!Number.isNaN(parseInt(e)))?null:"object"!=typeof e&&Number.isNaN(parseInt(e))?"Must be object or ID":null;switch(n){case"CharField":case"TextField":if("string"!=typeof e)return"Must be a string";if(s&&e.length>s)return`Max length is ${s}`;break;case"IntegerField":case"AutoField":case"BigIntegerField":if(!isFinite(parseInt(e)))return"Must be an integer";break;case"FloatField":case"DecimalField":if(!isFinite(parseFloat(e)))return"Must be a number";break;case"BooleanField":if("boolean"!=typeof e)return"Must be a boolean";break;case"DateField":case"DateTimeField":if(isNaN(Date.parse(e)))return"Must be a valid date";break;case"EmailField":if("string"!=typeof e||!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(e))return"Invalid email";break;case"URLField":try{new URL(e)}catch{return"Invalid URL"}break;case"UUIDField":if(!/^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/.test(e))return"Invalid UUID";break;case"JSONField":if("object"!=typeof e)return"Must be JSON object";break;case"FileField":if(!(oe.isValid(e)||e instanceof File||e instanceof oe))return"Must be a valid file"}return null}(e,t);if(n)throw new Error(n)}parseValue(e,t){const{type:n,many_to_many:r,one_to_many:s,many_to_one:o,one_to_one:i}=t;if(null===e)return null;if((r||s||o||i)&&e&&"string"==typeof e)return JSON.parse(e);switch(n){case"CharField":case"TeextField":case"UUIDField":case"EmailField":return`${e}`;case"IntegerField":case"AutoField":case"BigIntegerField":return parseInt(e,10);case"FloatField":case"DecimalField":return parseFloat(e);case"BooleanField":return!!e;case"DateField":case"DateTimeField":return Date.parse(e);case"URLField":return new URL(e);case"FileField":if(null==e)return null;if("string"==typeof e)return null;if(oe.isValid(e))return new oe(e);if(e instanceof oe)return new oe(e);if("undefined"!=typeof File&&e instanceof File)return t.max_size&&e.size>t.max_size?`File too large (max ${t.max_size} bytes)`:t.allowed_types&&!t.allowed_types.includes(e.type)?`Invalid file type (${e.type})`:e;break;case"JSONField":if("object"==typeof e)return e;if("string"==typeof e)return JSON.parse(e)}return e}}let ce=!1,ue=!1,de=null,he={};function me(){return window.SERVER_CALL_VIA_WEB_SOCKET?new Promise(e=>ce?e():ue?void setTimeout(()=>{me().then(()=>{e()})},200):e(pe())):Promise.resolve(!0)}function fe(){window.SERVER_CALL_VIA_WEB_SOCKET&&function(){if(ce){ce=!1;try{de.close()}catch(e){}}}()}function pe(){return ue=!0,new Promise(e=>{de="https:"===window.location.protocol?new WebSocket(`wss://${window.location.host}/sdc_ws/ws/`):new WebSocket(`ws://${window.location.host}/sdc_ws/ws/`),de.onmessage=function(e){_e(JSON.parse(e.data))},de.onclose=function(){ce&&console.error("SDC Socket closed unexpectedly"),ce=!1;for(const[e,t]of Object.entries(he))t[1]({}),delete he[e];setTimeout(()=>{pe()},1e3)},de.onerror=function(e){if(console.error("Socket encountered error: ",e.message,"Closing socket"),ce)try{de.close()}catch(e){}},de.onopen=function(){ce=!0,ue=!1,e()}})}function _e(e){if(e||(e={}),e.is_error)(e.msg||e.header)&&q("pushErrorMsg",e.header||"",e.msg||""),e.id&&he[e.id]&&(he[e.id][1](e.data||null),delete he[e.id]);else if((e.msg||e.header)&&q("pushMsg",e.header||"",e.msg||""),e.type&&"sdc_recall"===e.type)e.id&&he[e.id]&&(he[e.id][0](e.data),delete he[e.id]);else if(e.type&&"sdc_event"===e.type){let t=e.event;t&&q(t,e.payload)}else e.type&&"sdc_redirect"===e.type&&q("onNavLink",e.link)}class ye{constructor(){this._uuid=c(),this.contentUrl="",this.contentReload=!1,this.parsedContentUrl=null,this.events=[],this.load_async=!1,this._isEventsSet=!1,this._allEvents=null,this._params={},this._urlParams=[],this._models=[],this._cssUrls=[],this.afterShow=()=>{console.warn("afterShow is deprecated!!")},this._mixins={},this._tagName=Object.getPrototypeOf(this)._tagName??"",this._childController={},this._parentController=null,this._onLoadDone=!1,this.$container=null,this._isMixin=!1}get params(){return this._params}set params(e){this._params=e}_runLifecycle(e,t){we.DEBUG&&!this._isMixin&&console.debug(e,this._tagName);let n=[];if(!this._isMixin){this._isMixin=!0;for(let r in this._mixins){let s=this._mixins[r];"function"==typeof s[e]&&n.push(s[e].apply(this,t))}return Promise.all(n).then(()=>{this._isMixin=!1})}}onInit(){we.DEBUG&&!this._isMixin&&console.debug(Array.apply(null,arguments),this._tagName)}get parentController(){return this._parentController}get childController(){return this._childController}onLoad(){return this._runLifecycle("onLoad",arguments)}willShow(){return this._runLifecycle("willShow",arguments)}onRefresh(){return this._runLifecycle("onRefresh",arguments)}onRemove(){return this._runLifecycle("onRemove",arguments),!0}noOpenModelRequests(){return Promise.all(this._models.map(e=>e.noOpenRequests()))}remove(){for(const e of this._models)e.close();let e=this._childController;for(let t in e)if(e.hasOwnProperty(t))for(let n of e[t])if(!n.remove())return!1;if(!this.onRemove||this.onRemove()){I(this);const e=s(this._tagName);if(this._parentController._childController[e]){let t=this._parentController._childController[e];for(let e=0;e<t.length;e++)t[e]===this&&t.splice(e,1)}return this.$container.remove(),!0}return!1}controller_name(){return this._tagName.replace(/-./g,e=>` ${e[1].toUpperCase()}`).replace(/^./g,e=>`${e.toUpperCase()}`)}addEvent(e,t,n){this.getEvents(),this._allEvents[e]=this._allEvents[e]||{},this._allEvents[e][t]=n}getEvents(){if(this._allEvents)return this._allEvents;let e=[];e=e.concat(this.events);for(let t in this._mixins){let n=this._mixins[t];Array.isArray(n.events)&&(e=e.concat(n.events))}return this._allEvents=_.merge(...e)}post(e,t){return we.post(this,e,t)}get(e,t){return we.get(this,e,t)}submitForm(e,t,n){return we.submitFormAndUpdateView(this,e,t,n)}serverCall(e,t){let n=this.contentUrl.match(/sdc_view\/([^/]+)/i);if(n&&!(n.length<2))return function(e,t,n,r,s){return window.SERVER_CALL_VIA_WEB_SOCKET?function(e,t,n,r){let s=c();return me().then(()=>{de.send(JSON.stringify({event:"sdc_call",id:s,controller:t,app:e,function:n,args:r}))}),new Promise((e,t)=>{he[s]=[e,t]})}(e,t,r,s):function(e,t,n){return"object"!=typeof n&&Array.isArray(n)&&null===n&&(n={arg0:n}),n={data:JSON.stringify(n),_sdc_func_name:t,_method:"sdc_server_call"},$.post({url:e,data:n,beforeSend:function(e,t){e.setRequestHeader("X-CSRFToken",window.CSRF_TOKEN)}}).then(e=>{const t=e._return_data;return _e(t),t}).catch(e=>{const t=e.responseJSON||{};throw t.is_error=!0,_e(t),e})}(n,r,s)}(n[1],this._tagName,this.parsedContentUrl??this.contentUrl,e,t);console.error("To use the serverCall function the contentUrl must be set: "+this.name)}querySet(e,t={}){const n=new le(e,t);return this._models.push(n),n}newModel(e,t={}){return console.warn("newModel is deprecated and will soon be removed. Please use this.querySet(modelName, modelQuery)"),this.querySet(e,t)}find(e){return this.$container.find(e)}refresh(){return we.refresh(this.$container,this)}reload(){return we.reloadController(this)}reconcile(e,t=null){return we.reconcile(this,e,t)}submitModelFormDistributor(e,t){return"function"==typeof this._submitModelForm?this._submitModelForm(e,t):"function"==typeof this.submitModelForm?this.submitModelForm(e,t):this.defaultSubmitModelForm(e,t)}iterateAllChildren(){let e=this._childController,t=[];for(let n in e)if(e.hasOwnProperty(n))for(let r of e[n])t.push(r),t.push(...r.iterateAllChildren());return t}defaultSubmitModelForm(e,t){if(!this._isMixin){t.stopPropagation(),t.preventDefault();let{model:n,form_name:r}=e.data(),s=n.syncForm(e);return new Promise((t,o)=>{let i;i=null!==n.id&&n.id>=0?n.save({formName:r,data:s}):n.create({data:s}),i.then(n=>{u(e),this.submit_model_form_success&&this.submit_model_form_success(n[0]);for(const e of this.iterateAllChildren())e.submit_model_form_success&&e.submit_model_form_success(n[0]);t(n)}).catch(t=>{this.reconcile($(`<div class="container-fluid">${t.html}</div>`),e.find(".container-fluid").first()),this.submit_model_form_error&&this.submit_model_form_error(t);for(const e of this.iterateAllChildren())e.submit_model_form_error&&e.submit_model_form_error(t);o(t)})})}return Promise.resolve()}}const ge={classname:"class"};window.sdcDom=function(e,t,...n){if(!e)return"";const r=function(e,t){let n,r=!1;if("string"==typeof e)n=$(document.createElement(e));else{const t=`this.${e.name}`;n=$(document.createElement(t)),n.data("handler",e),r=!0}return t&&Object.entries(t).forEach(([e,t])=>{e.startsWith("on")?n[0].addEventListener(e.substring(2).toLowerCase(),t):(ge[e.toLowerCase()]&&(e=ge[e.toLowerCase()]),n[0].setAttribute(e,t))}),r&&n.addClass("_bind_to_update_handler _with_handler"),n}(e,t);for(const e of n)r.append(e);return r};let ve,we={CSRF_TOKEN:window.CSRF_TOKEN||"",LANGUAGE_CODE:window.LANGUAGE_CODE||"en",DEBUG:window.DEBUG||!1,VERSION:window.VERSION||"0.0",tagNames:[],Global:R,rootController:null,globalRootController:null,_isInit:!1,_origin_trigger:null,_globalControllerClasses:[],init_sdc:()=>{we._isInit||(we._isInit=!0,we._origin_trigger?fe():(we._origin_trigger=$.fn.trigger,$.fn.trigger=function(e){const t={}.hasOwnProperty.call(e,"type")?e.type:e;return g.includes(t)||(g.push(t),$(window).on(t,w)),we._origin_trigger.call(this,e)},we.updateJquery()),me(),function(){const e=$(window);g.forEach(t=>{e.off(t).on(t,w)})}(),we.rootController=we.rootController||new ye,we.globalRootController=we.globalRootController||new ye),we.tagNames=Object.keys(N);const e=$("<div></div>");R.forEach(t=>{const n=N[t][0];e.append(`<${n.prototype._tagName}></${n.prototype._tagName}>`)});const{refreshProcess:n}=k(null,we.rootController);return G(we.tagNames,e,we.globalRootController,n).then(()=>G(we.tagNames,(t||(t=$("body")),t),we.rootController,n).then(e=>(E(n),e)))},updateJquery:()=>{$.fn.safeReplace=function(e){return we.safeReplace($(this),e)},$.fn.safeEmpty=function(){return we.safeEmpty($(this))},$.fn.safeRemove=function(){return we.safeRemove($(this))}},controllerToTag:e=>r(e.name).replace(/-controller$/,""),registerGlobal:e=>{we.register(e);let t=e.prototype._tagName;R.push(t)},cleanCache:()=>{T={}},register:(e,t=!1)=>{let n=we.controllerToTag(e);return!N[n]||t?(N[n]=[e,[]],e.prototype._tagName=n,{addMixin:(...e)=>{for(let t of e){let e;"string"==typeof t?e=r(t):t&&(e=we.controllerToTag(t)),N[n][1].push(e)}}}):{addMixin:(...e)=>{}}},post:(e,t,n)=>(n||(n={}),n.CSRF_TOKEN=we.CSRF_TOKEN,we.ajax(e,t,n,$.post)),get:(e,t,n)=>we.ajax(e,t,n,$.get),ajax:(e,t,n,r)=>{n||(n={}),n.VERSION=we.VERSION,n._method=n._method||"api";const s=new Promise((o,i)=>r(t,n).then((t,n,r)=>{o(t,n,r),"redirect"===t.status?q("onNavLink",t["url-link"]):s.then(()=>{we.refresh(e.$container)})}).catch(i));return s},submitFormAndUpdateView:(e,t,n,r)=>{let s=new FormData(t);const o=e=>{e["url-link"]?q("onNavLink",e["url-link"]):window.location.href=e.url},l=new Promise((a,c)=>{i(s,n||t.action,r||t.method).then((t,n,r)=>{a(t,n,r),"redirect"===t.status?o(t):l.then(()=>{we.refresh(e.$container,e)})}).catch((e,t,n)=>{301===e.status?(e=e.responseJSON,o(e),a(e,t,n)):c(e,t,n)})});return l},submitForm:(e,t,n)=>{let r=new FormData(e);return new Promise((s,o)=>{i(r,t||e.action,n||e.method).then(s).catch(o)})},getController:e=>Q(e),safeEmpty:e=>(e.children().each(function(e,t){let n=$(t);we.safeRemove(n)}),e),safeReplace:(e,t)=>(t.insertBefore(e),we.safeRemove(e)),safeRemove:e=>(e.each(function(){let e=$(this);e.data(`${A}`)&&e.data(`${A}`).remove()}),e.find(`.${M}`).each(function(){const e=$(this).data(`${A}`);e&&e.remove()}),e.remove()),reloadController:e=>function(e){if(e.contentUrl){let t=V(e);return e.contentUrl=t.url,D(e,t.args)}return new Promise(e=>{e($())})}(e).then(t=>{let n=$(t);return we.reconcile(e,n)}),reconcile:(e,t,n=null,r=null)=>{if(!n){let n=e.$container.clone().empty();n.data(A,null),n.removeClass(M),n.append(t),t=n}n=n??e.$container;const{refreshProcess:s,isRunningProcess:o}=k(r,e);return X(t,e,s).then(()=>{var r;return K(t,n),(r=e)._childController={},r.find(`.${M}`).each(function(){const e=Q($(this));e===r&&C(r,e)}),o||E(s),e})},refresh:(e,t=null)=>X(e,t)},be=[];function $e(){if(!jest)throw new Error("JEST is not defined");0===be.length&&(ve=$.ajax.bind($),be.push(jest.spyOn($,"ajax")),be[0].mockImplementation(function(e){return ve(e).then(e=>e).catch(e=>e)}))}const Re=fe,Ne={get_controller:async function(e,t={},n=""){$e();const r=$("body");we.updateJquery(),r.safeEmpty();const s=$(`<${e}>${n}</${e}>`);for(const[e,n]of Object.entries(t))s.data(e,n);const o=$("<div></div>").append(s);r.append(o),we._isInit=!1,we.cleanCache(),await we.init_sdc();const i=we.getController(s);return i.navControllerPath=[e],i},getCsrfToken:function(){return function(e){if(document.cookie&&""!==document.cookie){const t=document.cookie.split(";");for(let n=0;n<t.length;n++){const r=t[n].trim();if(r.substring(0,10)===e+"=")return decodeURIComponent(r.substring(10))}}return""}("csrftoken")},controllerFromTestHtml:async function(e,t=null){$e();const n=$("body");we.updateJquery(),n.safeEmpty().append(e),we._isInit=!1,we.cleanCache(),await we.init_sdc();let r=we.rootController.iterateAllChildren();if(!t)return r;const s=r[0].onRefresh,o=jest.spyOn(r[0],"onRefresh");return new Promise(e=>{o.mockImplementation(function(){o.mockRestore();const t=s.apply(r[0],arguments);return e(r),t})})}};export{ye as AbstractSDC,ae as SdcModel,le as SdcQuerySet,I as allOff,we as app,a as checkIfParamNumberBoolOrString,u as clearErrorsInForm,S as controllerFactory,L as on,Z as registerModel,F as runControlFlowFunctions,d as setErrorsInForm,j as setEvent,Re as socketReconnect,Ne as test_utils,q as trigger};
1
+ /*! For license information please see ugly.index.js.LICENSE.txt */
2
+ let e;function t(){return new Promise(function(e){e()})}function n(e){return(e=(e=e.replace(/[A-Z]/g,e=>`-${e.toLowerCase()}`)).replace(/[0-9]+/g,e=>`-${e}`)).replace(/^[-]/g,"")}function r(e){return e.replace(/-./g,e=>`${e[1].toUpperCase()}`)}const s=(e,t)=>{let n=t,r=Object.getOwnPropertyNames(e.prototype).concat(Object.getOwnPropertySymbols(e.prototype));for(;""!==n.name;)Object.getOwnPropertyNames(n.prototype).concat(Object.getOwnPropertySymbols(n.prototype)).forEach(t=>{t.match(/^(?:constructor|prototype|arguments|caller|name|bind|call|apply|toString|length)$/)||r.includes(t)||(r.push(t),Object.defineProperty(e.prototype,t,Object.getOwnPropertyDescriptor(n.prototype,t)))}),n=Object.getPrototypeOf(n)};function o(e,t,n){return $.ajax({url:t,type:n||"POST",xhr:function(){var e=$.ajaxSettings.xhr();return e.upload&&e.upload.addEventListener("progress",i,!1),e},data:e,cache:!1,contentType:!1,processData:!1,beforeSend:function(e,t){(function(e){return/^(GET|HEAD|OPTIONS|TRACE)$/.test(e)})(t.type)||this.crossDomain||e.setRequestHeader("X-CSRFToken",window.CSRF_TOKEN)}})}function i(e){if(e.lengthComputable){var t=Math.round(e.loaded/e.total*100),n=$(".progress-container");100===t?n.hide():n.show(),t+="%",n.find(".progress-bar").css({width:t}).text(t)}}function l(e,t=null){return"string"!=typeof e?e:t&&void 0!==t[e]?"function"==typeof t[e]?t[e].bind(t):t[e]:e.match(/^(true|false)$/)?"true"===e:"undefined"!==e?"none"===e.toLowerCase()?null:e.match(/^-?\d+$/)?parseInt(e):e.match(/^-?\d+\.?\d+$/)?parseFloat(e):e.match(/^(['][^']*['])|(["][^"]*["])$/)?e.substr(1,e.length-2):e:void 0}function a(){return([1e7]+-1e3+-4e3+-8e3+-1e11).replace(/[018]/g,e=>(e^crypto.getRandomValues(new Uint8Array(1))[0]&15>>e/4).toString(16))}function c(e){e.find(".has-error").removeClass("has-error").find(".alert-danger").remove(),e.find(".non-field-errors").remove()}function u(e,t){t=$("<div>").append(t),e.find(".has-error").removeClass("has-error").find(".alert-danger").safeRemove(),e.find(".non-field-errors").safeRemove();let n=t.find("input[type=file]").parent();e.find("input[type=file]").parent().each(function(e){$(this).replaceWith(n[e])});let r=0===t.find(".non-field-errors").insertAfter(e.find(".hidden-form-fields")).length;return t.find(".has-error").each(function(){r=!1;let t=$(this),n=t.data("auto-id"),s=e.find(".form-group."+n);s.addClass("has-error"),s.find(".form-input-container").append(t.find(".alert-danger"))}),r}function d(e){let{type:t,name:n}=e;return n&&""!==n?"hidden"===t?(r=$(e).val()).toLowerCase().match(/^(true|false)$/)?"true"===r.toLowerCase():"undefined"!==r?"none"===r.toLowerCase()?null:r.match(/^-?\d+$/)?parseInt(r,10):r.match(/^-?\d+\.?\d+$/)?parseFloat(r):r.match(/^(['][^']*['])|(["][^"]*["])$/)?r.substring(1,r.length-1):r:void 0:"checkbox"===t?e.checked:"file"===t?e.files[0]:$(e).val():null;var r}const h=e=>String(e).padStart(2,"0");function f(e){if(null==e||""===e)return null;let t;if(e instanceof Date)t=e;else if("string"==typeof e&&/^\d{4}-\d{2}-\d{2}$/.test(e)){const[n,r,s]=e.split("-").map(Number);t=new Date(n,r-1,s)}else t=new Date(e);return isNaN(t.getTime())?null:t}function m(e){const t=f(e);return t?`${t.getFullYear()}-${h(t.getMonth()+1)}-${h(t.getDate())}`:""}function p(e,t){let{type:n,name:r}=e;if(r&&""!==r)if("datetime-local"===n)e.value=function(e){const t=f(e);return t?`${m(t)}T${h(t.getHours())}:${h(t.getMinutes())}`:""}(t);else if("date"===n)e.value=m(t);else if("checkbox"===n)e.checked=!!t;else if("file"===n){if(t instanceof File&&"undefined"!=typeof DataTransfer){let n=new DataTransfer;n.items.add(t),e.files=n}}else t instanceof ue?$(e).val(t.id):t instanceof ce?$(e).val(`[${t.getIds().join(",")}]`):(null===t&&(t=""),$(e).val(t));return null}function g(e,t=null){return Object.fromEntries(Object.entries(e).filter(([e,t])=>e!==U).map(([e,n])=>{if("string"==typeof n&&n.startsWith("SDC_JSON_MODEL=["))try{const{pk:t,fields:r}=JSON.parse(n.slice(16,-1));return[e,{...r,id:t}]}catch{}return[e,l(n,t)]}))}function y(e,t=null){return g(e.data(),t)}const v=["onbeforeunload","onunload"],w=Object.keys(window).filter(e=>/^on/.test(e)&&!v.includes(e)).map(e=>e.slice(2));function b(e,t,n){let r;switch(e){case"mouseleave":case"mouseout":case"mouseenter":return r=document.elementFromPoint(t.clientX,t.clientY),n!==r&&!n.contains(r);default:return!0}}function R(e){let t=e.type;Object.hasOwn(e,"namespace")&&e.namespace&&e.namespace.length&&(t+=`.${e.namespace}`);let n=$(e.target),r=null,s=!1,o=!1;for(e.stopImmediatePropagation=()=>o=!0,e.stopPropagation=()=>o=s=!0;n.length;){let i=n.attr(`sdc_${t}`);if(i&&b(t,e,n[0])){if(!r&&(r=W(n),!r))return;for(;r;){if(i.split(" ").forEach(o=>{if(s)return;let i=null;if("function"==typeof o)i=o;else if("function"==typeof r[o])i=r[o];else if("string"==typeof o&&o.startsWith("this.event_")){if(i=r.getEvents()[t],!i)return;if(i=i[o.slice(11)],!i)return}i&&i.call(r,n,e)}),o)return;r=r._parentController}}if(s)return;n=n.parent()}return{res:!0}}function C(e){const t=e.getEvents();for(let n in t)if(Object.hasOwn(t,n)){let r=t[n];for(let t in r)Object.hasOwn(r,t)&&e.find(t).each(function(){let e=$(this),r=e.attr(`sdc_${n}`)||null;r=r?r.split(" "):[];const s=`this.event_${t}`;-1===r.indexOf(s)&&(r.push(s),e.attr(`sdc_${n}`,r.join(" ")))})}}let N=[],O={};function S(e,t){if(e){let n=r(t._tagName);e._childController[n]||(e._childController[n]=[]),e._childController[n].push(t)}return t._parentController=e}function F(e,t,n,r){let o=[];r=function(e,t){e=(e=e.concat(O[t][1])).filter((e,t,n)=>n.indexOf(e)===t);let n=!0;for(;n;){n=!1;for(let t of e)for(let r of O[t][1])e.includes(r)||(e.push(r),n=!0)}return e}(r,n);for(let e of r)o.push(O[e][0]);let i=new(function(e,...t){let n={[e.name]:class{constructor(...n){let r={};t.forEach(e=>{let t;Object.assign(this,t=new e),t._tagName=e.prototype._tagName,t._isMixin=!0,r[e.name]=t}),Object.assign(this,new e),this._mixins=r}static get name(){return e.name}static className(){return this.name}get mixins(){return this._mixins}}}[e.name];return s(n,e),t.forEach(e=>{s(n,e)}),n}(O[n][0],...o));return i._tagName=n,S(e,i),i.$container=t,function(e,t){!function(e,t,n){if(!e)return!1;e.params=y(t,n._parentController)}(t,e,t)}(t,i),i}function k(e,t,n,s){if(N.includes(n)){let o=r(n);return window[o]||(window[o]=F(e,t,n,s)),window[o].$container=t,window[o]}return F(e,t,n,s)}function E(e,n){const r=function(e){return function(e){let t={args:{}};return e.contentUrl&&(t=B(e),e.contentUrl=t.url),Promise.all([V(e,t.args)]).then(function(e){let t=e[0];if(t)try{return $(t)}catch{return $("<div></div>").append(t)}return null})}(e).then(n=>!e.onLoad||e._onLoadDone?n:(e._onLoadDone=!0,(e.onLoad(n)||t()).then(()=>n)))}(e).then(function(t){return function(e,t){return z(e,t).then(function(t){if(t=t||!0,e.willShow){let n=e.willShow();if(n instanceof Promise)return n.then(function(){return t})}return t})}(e,t)}).then(()=>function(e,t){return Z(null,e,t)}(e,n)).catch(function(t){if("string"==typeof t||t instanceof $)return z(e,t);throw t});return e.load_async?Promise.resolve():r}function x(e){const t=function(e){let t=[];for(;e;)t.unshift(e),e=e._parentController;return t}(e.controller[0]),n=t.concat(e.controller.slice(1));for(let t of n)C(t),t.onRefresh(e.controller[0])}function I(e,t){let n=Boolean(e);return n?e.uuids.has(t._uuid)||(e.uuids.add(t._uuid),e.controller.push(t)):e={uuids:new Set([t._uuid]),controller:[t]},{isRunningProcess:n,refreshProcess:e}}let j={},P={};function L(e,t){return q(e),Object.hasOwn(P,e)?t[P[e]]?void j[e].push(t):console.log("No event handler: "+e,t):console.log("No event: "+e,t)}function q(e,t){t||(t=e),P[e]||(P[e]=t,j[e]=[])}function T(e){for(let t in j)if(Object.hasOwn(j,t))for(let n=j[t].length-1;n>=0;n--)e===j[t][n]&&j[t].splice(n,1)}function A(e){let n=Array.apply(null,arguments);if(e=n.shift(),!Object.hasOwn(j,e)||!Object.hasOwn(P,e))return t();let r=j[e],s=P[e],o=[];for(let e=0;e<r.length;e++){let t=r[e][s].apply(r[e],n);void 0!==t&&o.push(t)}return Promise.all(o)}let D={};const U="_controller_",M="_sdc_controller_";function J(e,t,n){if(!e)return[];let r=e.children(),s=[];return r.each(function(e,r){let o=$(r),i=o.prop("tagName").toLowerCase().split("_");$.inArray(i[0],t)>=0?s.push({tag:i[0],super:i.splice(1)||[],dom:o}):i[0].startsWith("this.")?o.addClass(`_bind_to_update_handler sdc_uuid_${n._uuid}`):s=s.concat(J(o,t,n))}),s}function V(e,t){const{contentUrl:n,_tagName:r,contentReload:s}=e;return n?D[r]?Promise.resolve(D[r]):(t.VERSION=$e.VERSION,t._method="content",$.get(n,t).then(function(e){return s||(D[r]=e),e}).catch(function(t){if(301===t.status){const n=t.responseJSON;return A("_RedirectOnView",n["url-link"]),s||(e.autoRedirect=n["url-link"]),"<p>Redirected</p>"}throw e.autoRedirect=null,"function"==typeof e.confirmPageLoaded&&A("navLoaded",{controller_name:()=>t.status}),`<sdc-error data-code="${t.status}">${t.responseText}</sdc-error>`})):Promise.resolve(!1)}function Q(e,t,n=null){return t=t||e.data(U),K($e.tagNames,e,t,n)}function B(e){let t=e.contentUrl;if(e&&0===e._urlParams.length){let n,r=/%\(([^)]+)\)\w/gm;for(e._urlParams=[];n=r.exec(t);)e._urlParams.push(n[1]),e.contentReload=!0}let{args:n,params:r}=function(e,t){const n=y(t,e),[r,s]=Object.entries(n).reduce(([t,n],[r,s])=>(e._urlParams.includes(r)?t[r]=s:n[r]=s,[t,n]),[{},{}]);return{params:r,args:s}}(e,e.$container);return e._urlParams.length&&(t=function(e,t,n){for(let r in e._urlParams)if(Object.hasOwn(e._urlParams,r)){let s=e._urlParams[r],o=RegExp("%\\("+s+"\\)\\w","gm");const i=n[s];i||console.warn(`${s} is not set for controller ${e._tagName}`),t=t.replace(o,i)}return t}(e,t,r)),e.parsedContentUrl=t,{url:t,args:n}}function W(e){return e.hasClass(M)?e.data(`${U}`):e.closest(`.${M}`).data(`${U}`)}function G(e,t,n,r,s){let o=e.data(U);return o?Q(e,o,s):(o=k(r,e,t,n),e.data(U,o),e.addClass(M),E(o,s))}function z(e,t,n=null){if(t&&t.length>0){e.$container.empty(),e.$container.attr(e._tagName,"");for(let t in e._mixins)e.$container.attr(e._mixins[t]._tagName,"");e.$container.append(t)}return Q(e.$container,e,n)}function K(e,t,n,r){return new Promise(s=>{let o=J(t,e,n),i=o.length;if(0===i)return s();for(let e=0;e<o.length;e++)G(o[e].dom,o[e].tag,o[e].super,n,r).then(()=>{if(i--,0===i)return s()})})}function H({$element:e,id:t=[],parent:n=null}){t.push(function(e){if(3===e[0].nodeType)return`TEXT__${e[0].nodeValue}`;const t=[e[0].tagName];return"INPUT"===e[0].nodeName&&[["name",""],["type","text"],["id",""]].forEach(([n,r])=>{const s=e.attr(n)??r;s&&t.push(s)}),t.join("__")}(e));const r={$element:e,id:t.join("::"),depth:t.length,idx:0,getRealParent:()=>n,getIdx:function(){return this.idx=Math.max(0,(this.getRealParent()?.getIdx()??-1)+e.index()+1),this.idx},op:null,parent:n};return r.getIdx.bind(r),[r].concat(e.contents().toArray().map(e=>H({$element:$(e),id:t.slice(),parent:r})).flat())}function X(e,t){const n=H({$element:t}),r=H({$element:e});n.map((e,t)=>e.idx=t),r.map((e,t)=>e.idx=t);const s=Math.max(...r.concat(n).map(e=>e.depth)),o=Y(n,r,s);let i=[];window.MAIN=t,window.OPS=o,o.forEach((e,t)=>{const{op:n,$element:r,idx:s}=e;if("keep_counterpart"===n.type){if(n.counterpart.getIdx()!==s){const t=e.getBefore();t?n.counterpart.$element.insertAfter(t.$element):e.getRealParent().$element.prepend(n.counterpart.$element)}!function(e,t){!function(e,t){if(!e||!t||!e._sdcListeners&&!t._sdcListeners)return;(e._sdcListeners??[]).forEach(([t,n])=>e.removeEventListener(t,n));const n=t._sdcListeners??[];n.forEach(([t,n])=>e.addEventListener(t,n)),e._sdcListeners=n}(e[0],t[0]);const n=e[0].attributes??[],r=t[0].attributes??[];[...n].forEach(n=>{t.is(`[${n.name}]`)||e.removeAttr(n.name)}),[...r].forEach(t=>{t.name.startsWith("data")||e.attr(t.name)===t.value||e.attr(t.name,t.value)}),e.removeData(),Object.entries(t.data()).forEach(([t,n])=>{e.data(t,n)})}(n.counterpart.$element,r),r.hasClass(M)&&(r.data(U).$container=n.counterpart.$element,r.data(U,null)),i.push(r)}else if("delete"===n.type)r.safeRemove();else if("insert"===n.type){const{after:t,target:n}=e.op;t?r.insertAfter(t.$element):n&&n.$element.prepend(r)}}),i.forEach(e=>e.safeRemove())}function Y(e,t,n){return t.filter(e=>e.depth===n&&!e.op).forEach(t=>{const n=e.find(e=>!e.op&&e.id===t.id);if(n){const e=(t,n)=>{t.op={type:"keep",idx:n.idx},n.op={type:"keep_counterpart",counterpart:t},t=t.parent,n=n.parent,!t||t.op||n?.op||e(t,n)};e(n,t)}}),n>1?Y(e,t,n-1):(e.forEach((t,n)=>{if(!t.op){const r=(e[n-1]?.op.idx??-1)+1;t.op={type:"delete",idx:r}}}),t.forEach((e,n)=>{if(e.getBefore=()=>function(e,n){const r=e.depth;for(;n>=1&&e.depth>=r;)if((e=t[n-=1]).depth===r)return"keep_counterpart"===e.op.type?e.op.counterpart:e;return null}(e,n),e.getRealParent=()=>{return(t=e).parent?"keep_counterpart"===t.parent.op.type?t.parent.op.counterpart:t.parent:null;var t},!e.op){const t=e.getRealParent(),n="insert"===t?.op.type?"insert_ignore":"insert";e.op={type:n,target:t,after:e.getBefore()}}}),[...e,...t].sort((e,t)=>(e.op?.idx??e.idx)-(t.op?.idx??t.idx)))}function Z(e,t,n=null){if(t||(t=W(e)),!t)return Promise.resolve();const{refreshProcess:r,isRunningProcess:s}=I(n,t);return e??=t.$container,K($e.tagNames,e,t,n).then(()=>function(e,t,n){return function(e,t,n){const r=[];return t.find(`._bind_to_update_handler.sdc_uuid_${e._uuid}`).each(function(){const t=$(this);let s;if(t.hasClass("_with_handler"))s=t.data("handler");else{let t=this.tagName.toLowerCase().replace(/^this./,"");e[t]&&(s=e[t])}if("function"==typeof s){const n=g(t.data(),e);s=s.bind(e)(n)}s&&r.push(Promise.resolve(s).then(r=>{let s=$("<div></div>");return s.append(r),""===t.html()&&t.append("<div></div>"),$e.reconcile(e,s,t.children(),n)}))}),Promise.all(r)}(e,t??e.$container,n)}(t,e,r).then(()=>{s||x(r)}))}const ee={};function te(e,t){ee[e]=t}function ne(e){return ee[e]}const re=25e3,se="_connecting_process";class oe extends Error{constructor(e){"string"==typeof e&&(e={msg:e,is_error:!0,header:"Error"}),super(e.msg),this.msg=e.msg,this.header=e.header,this.is_error=e.is_error,this.html=e.html}}class ie{constructor({name:e,url:t}){this.name=e,this.url=t,this.content=null}async load(e=!1){return!e&&this.content||(this.content=await new Promise((e,t)=>{$.get(this.url).then(e).catch(()=>{e("")})})),this.content}async text(){return this.load()}static isValid(e){return!(null===e||"object"!=typeof e||Array.isArray(e)||e instanceof File||"string"!=typeof e.url||"string"!=typeof e.name)}}function le(e){const t=parseInt(e??-1,10);return Number.isNaN(t)?-1:t}function ae(e){if(!e||"object"!=typeof e||e instanceof ue)return!1;const t=Object.keys(e);return!(0===t.length||!t.every(e=>"elem"===e||"data"===e)||"elem"in e&&null!==e.elem&&!(e.elem instanceof ue)||"data"in e&&null!==e.data&&"object"!=typeof e.data)}class ce{constructor(e,t={}){return this.valuesList=[],this.loaded=!1,this.modelName=e,this.modelQuery=t??{},this._onNoOpenRequests=[],this._isConnected=!1,this._isConnectingProcess=!1,this._autoReconnect=!0,this.socket=null,this.openRequest={},this.modelId=0,this.onUpdate=()=>{},this.onCreate=()=>{},this.onDelete=null,new Proxy(this,{get:(e,t)=>"symbol"==typeof t||isNaN(t)?e[t]:e.valuesList[t],set:(e,t,n)=>isNaN(t)?(e[t]=n,!0):(e.valuesList[t]=n,!0)})}[Symbol.iterator](){let e=-1;return{next:()=>(++e,e<this.valuesList.length?{value:this.valuesList[e],done:!1}:{value:null,done:!0})}}set on_create(e){this.onCreate=e}set on_update(e){this.onUpdate=e}set on_delete(e){this.onDelete=e}_removeIds(e){const t=this.valuesList.filter(t=>e.includes(t.id));return this.valuesList=this.valuesList.filter(t=>!e.includes(t.id)),t}setIds(e){const t=this._setIds(e),n={id__in:t.map(e=>e.id)};return this.setFilter(n),t}_setIds(e){if(null===e||""===e||Array.isArray(e)&&0===e.length)return this.valuesList=[],this.valuesList;if(e instanceof ce||e instanceof ue){const t=e instanceof ue?[e]:e.valuesList;return this.valuesList=t.map(e=>{const t=null!==e.id?this.byId(e.id):null;if(t)return t;const n=(e=>{const t=new e.constructor({});return t.setValues(e.serialize()),t})(e);return n._setQuerySet(this,!0),n}),this.valuesList}let t,n=Number.NaN;if(Number.isInteger(e))n=e;else if(e instanceof Array){const n=e.map(e=>parseInt(e));n.some(Number.isNaN)||(t=n)}else if("string"==typeof e){const r=e.split(",").map(e=>parseInt(e));r.some(Number.isNaN)?n=parseInt(e):t=r}if(Number.isNaN(n)){if(t){this.valuesList=this.valuesList.filter(e=>t.includes(e.id));const e=this.getIds();t.filter(t=>!e.includes(t)).forEach(e=>{this.valuesList.push(new(ne(this.modelName))({id:e}))})}}else this.valuesList=this.valuesList.filter(e=>n===e.id),0===this.valuesList.length&&(this.new().id=n);return this.valuesList}getIds(){return this.valuesList.map(e=>e.id)}get length(){return this.valuesList.length}byId(e){if(null!==e){const t=le(e);return this.valuesList.find(e=>e.id===t)??null}return null}setFilter(e){return this.modelQuery=e,this}addFilter(e){return this.modelQuery=Object.assign({},this.modelQuery,e),this}new(e={}){const t=new(ne(this.modelName))(e);return t._setQuerySet(this,!1),this.valuesList.push(t),t}load(e=null){return this.valuesList=[],this.modelQuery=e??this.modelQuery,this._sendLoad()}update({modelQuery:e=null,item:t=null}){this.modelQuery=e??this.modelQuery;let n=t?{id:t.id}:this.modelQuery;return this._sendLoad(n)}delete({pk:e=null,id:t=null,elem:n=null}){if(e??=t,null===(e=n?n.id:e))throw new Error("pk or elem must be set");const r=a();return this.isConnected().then(()=>new Promise((t,n)=>{this.socket.send(JSON.stringify({event:"model",event_type:"delete",event_id:r,args:{model_name:this.modelName,model_query:this.modelQuery,id:e,pk:e}})),this.openRequest[r]=[n=>{this._removeIds([le(e)]),t(n)},n]}))}_sendLoad(e=null){return this.isConnected().then(()=>{const t=a();return new Promise((n,r)=>{this.socket.send(JSON.stringify({event:"model",event_type:"load",event_id:t,args:{model_name:this.modelName,model_query:e??this.modelQuery}})),this.openRequest[t]=[e=>{this.loaded=!0,n(e)},r]})})}_sendListView({modelQuery:e={},cbResolve:t=null,cbReject:n=null,templateContext:r={}}){return this.view({modelQuery:e,cbResolve:t,cbReject:n,templateContext:r,eventType:"list_view"})}view({viewName:e="html_list_template",modelQuery:t={},cbResolve:n=null,cbReject:r=null,templateContext:s={},eventType:o="named_view"}){let i=$('<div class="container-fluid">');return this.isConnected().then(()=>{const l=a();this.socket.send(JSON.stringify({event:"model",event_type:o,event_id:l,args:{view_name:e,model_name:this.modelName,model_query:t,template_context:s}})),this.openRequest[l]=[e=>{i.append(e.html),$e.refresh(i),n&&n(e)},e=>{r&&r(e)}]}),i}_sendDetailView({pk:e=null,id:t=null,cbResolve:n=null,cbReject:r=null,templateContext:s={}}){e??=t,e=le(e);let o=$('<div class="container-fluid">');return this.isConnected().then(()=>{const t=a();this.socket.send(JSON.stringify({event:"model",event_type:"detail_view",event_id:t,args:{model_name:this.modelName,model_query:this.modelQuery,id:e,pk:e,template_context:s}})),this.openRequest[t]=[e=>{o.append(e.html),$e.refresh(o),n&&n(e)},e=>{r&&r(e)}]}),o}getForm({modelObj:e,eventType:t,formName:n,$divForm:r,cbResolve:s,cbReject:o,formId:i}){const l=a(),c=e.id??-1;this.isConnected().then(()=>{this.socket.send(JSON.stringify({event:"model",event_type:t,event_id:l,args:{model_name:this.modelName,id:c,pk:c,form_name:n}}))});const u=null===c||-1===c?"create":"edit";this.openRequest[l]=[t=>{r.append(t.html);let o=r.closest("form").addClass(`sdc-model-${u}-form sdc-model-form ${i}`).data("model",e).data("model_pk",c).data("form_name",n);e.addForm(o),o.length>0&&!o[0].hasAttribute("sdc_submit")&&o.attr("sdc_submit","submitModelFormDistributor"),$e.refresh(r).then(()=>null),s&&s(t)},e=>{o&&o(e)}]}async get(e=null,t=!1){if(t){const t=e?.id??this.modelQuery?.id;return e&&this.setFilter(e),this.byId(t)??this.new(e||this.modelQuery)}if(await this.load(e),1!==this.length)throw new Error(`model query returns ${this.length} but only 1 expected.`);return this.addFilter({id:this.valuesList[0].id}),this.valuesList[0]}detailView({pk:e,cbResolve:t=null,cbReject:n=null,templateContext:r={}}){return this._sendDetailView({id:e,cbResolve:t,cbReject:n,templateContext:r})}listView({modelQuery:e={},searchValues:t={},cbResolve:n=null,cbReject:r=null,templateContext:s={}}){return this._sendListView({modelQuery:Object.assign({},this.modelQuery,e,{__search_values:t}),cbResolve:n,cbReject:r,templateContext:s})}save({pk:e=null,id:t=null,formName:n="edit_form",data:r=null}={}){e??=t;const s=le(e);return this.isConnected().then(()=>{let e;if(s>-1){const t=this.byId(s);if(!t)return Promise.reject(new oe(`Element not found with ID: ${s}`));e=[t]}else e=this.valuesList;let t=[];return e.forEach(e=>{const s=a();t.push(new Promise((t,o)=>{this._readFiles(e).then(i=>{const l=r?{...r}:e.serialize();l.id=e.id,this.socket.send(JSON.stringify({event:"model",event_type:"save",event_id:s,args:{form_name:n,model_name:this.modelName,model_query:this.modelQuery,data:l,id:l.id,pk:l.id,files:i}})),this.openRequest[s]=[e=>{let n="string"==typeof e.data.instance?JSON.parse(e.data.instance):e.data.instance;e.data.instance=this._parseServerRes(n),t(e)},o]})}))}),Promise.all(t)})}create(e=null){let{elem:t=null,data:n=null}=ae(e)?e:{data:e};n&&"object"==typeof n&&0===Object.keys(n).length&&(n=null);const r=a();return t||(t=this.new(n)),this.isConnected().then(()=>new Promise((e,s)=>{this._readFiles(t).then(o=>{this.socket.send(JSON.stringify({event:"model",event_type:"create",event_id:r,args:{model_name:this.modelName,model_query:this.modelQuery,data:n??t?.serialize()??{},files:o}})),this.openRequest[r]=[n=>{let r="string"==typeof n.data.instance?JSON.parse(n.data.instance):n.data.instance;t&&(t.id=r[0]?.id||r[0]?.pk),n.data.instance=this._parseServerRes(r)[0],e(n)},s]})}))}isConnected(){return new Promise((e,t)=>{if(this._isConnected)e();else if(this._isConnectingProcess&&this.openRequest[se]){const[n,r]=this.openRequest[se];this.openRequest[se]=[()=>{n(),e()},()=>{r(),t()}]}else this._isConnectingProcess=!0,this.openRequest[se]=[()=>{},()=>{}],this._connectToServer().then(()=>{e(this._checkConnection())})})}close(){this.socket&&(this._autoReconnect=!1,this.socket.onclose=()=>{},this.socket.close(),delete this.socket),this.valuesList.forEach(e=>{e._onClose()})}_readFiles(e){let t=[],n={};return e?(Object.keys(e.constructor.fields).forEach(r=>{const s=e[r];s instanceof File&&t.push(new Promise((e,t)=>{const o=a();this.openRequest[o]=[e,t],s.arrayBuffer().then(e=>{let t=new Uint8Array(e),i=Math.ceil(t.length/re);n[r]={id:o,file_name:s.name,field_name:r,content_length:s.size};for(let e=0;e<i;++e){const n=Array.from(t.slice(re*e,re*(e+1)));this.socket.send(JSON.stringify({event:"model",event_type:"upload",event_id:o,args:{chunk:n,idx:e,number_of_chunks:i,file_name:s.name,field_name:r,content_length:s.size,content_type:s.type,model_name:this.modelName,model_query:this.modelQuery}}))}}).catch(e=>{this._closeOpenRequest(o),t(e)})}))}),Promise.all(t).then(()=>n)):Promise.resolve(n)}async _onMessage(e){let t=JSON.parse(e.data);if(t.is_error)Object.hasOwn(this.openRequest,t.event_id)&&(this.openRequest[t.event_id][1](new oe(t)),this._closeOpenRequest(t.event_id)),(t.msg||t.header)&&A("pushErrorMsg",t.header||"",t.msg||""),"connect"===t.type&&(this.openRequest[se][1](new oe(t)),this._closeOpenRequest(se),this._autoReconnect=!1,this.socket.close());else{if((t.msg||t.header)&&A("pushMsg",t.header||"",t.msg||""),"connect"===t.type)this._isConnected=!0,this._isConnectingProcess=!1,this.openRequest[se][0](t),this._closeOpenRequest(se);else if(["load","list_view","named_view","detail_view"].includes(t.type)){const e=JSON.parse(t.args.data);t.args.data=await this._parseServerRes(e)}else if("on_update"===t.type||"on_create"===t.type){const e=JSON.parse(t.args.data);let n,r=await this._parseServerRes(e);n="on_create"===t.type?this.onCreate:this.onUpdate,n(r),t.args.data=r}else if("on_delete"===t.type){const e=JSON.parse(t.args.data).map(e=>le(e.id??e.pk)),n=this._removeIds(e);(this.onDelete??this.onUpdate)(n),t.args.data=n}let e=t.data?.instance;e&&(t.data.instance=JSON.parse(t.data.instance)),Object.hasOwn(this.openRequest,t.event_id)&&(this.openRequest[t.event_id][0](t),this._closeOpenRequest(t.event_id))}}noOpenRequests(){return new Promise(e=>{if(0===Object.keys(this.openRequest).length)return e();this._onNoOpenRequests.push(e)})}_closeOpenRequest(e){delete this.openRequest[e],0===Object.keys(this.openRequest).length&&(this._onNoOpenRequests.forEach(e=>e()),this._onNoOpenRequests=[])}_connectToServer(){return new Promise(e=>{const t=`${this.modelName}`+(this.modelId>0?`/${this.modelId}`:"");"https:"===window.location.protocol?this.socket=new WebSocket(`wss://${window.location.host}/sdc_ws/model/${t}`):this.socket=new WebSocket(`ws://${window.location.host}/sdc_ws/model/${t}`),this.socket.onmessage=this._onMessage.bind(this),this.socket.onclose=e=>{console.error(`SDC Model (${this.modelName}, ${this.modelId}) Socket closed unexpectedly`),this._isConnected=!1;for(const t of Object.values(this.openRequest))t[1](e);this.openRequest={},this._isConnectingProcess=!1,setTimeout(()=>{this._autoReconnect&&!this._isConnected&&this.isConnected().catch(()=>{})},1e3)},this.socket.onerror=e=>{if(console.error(`Model Socket encountered error: ${e} Closing socket`),this._isConnected)try{this.socket.close()}catch(e){}},this.socket.onopen=()=>{e()}})}_checkConnection(){const e=a();return new Promise((t,n)=>{this.socket.send(JSON.stringify({event:"model",event_type:"connect",event_id:e,args:{model_name:this.modelName,model_query:this.modelQuery}})),this.openRequest[e]=[t,n]})}_parseServerRes(e){const t=[];for(const n of e){const e=ne(this.modelName);if(!e)throw new Error(`${this.modelName} is no SdcModel. mybe the models ar not importad.`);const r=new e({id:n.id??n.pk,...n.fields}),s=this.byId(r.id);s?(s.setValues(r),t.push(s)):(this.valuesList.push(r),r._setQuerySet(this,!0),t.push(r))}return this.valuesList.sort((e,t)=>e._id-t._id),t}}class ue{static fields={};constructor(e){this._id=null,this._forms=[],this.loaded=!1,this.formId=a(),this.modelName=e}static querySet(e=null,t=null){const{modelName:n}=new this({});return t?t.querySet(n,e):new ce(n,e)}addForm(e){const t=this._onChange.bind(this);this._forms.push(e),e&&e.on("input.formWatcher change.formWatcher","input, select, textarea",t)}_onChange(e){const{name:t}=e.target;if(this.constructor.fields[t]){try{this[`set${t}`](d(e.target))}catch{return}this._updateForm(t,e.target)}}_updateForm(e,t=null){const n=this;this._forms.forEach(r=>{r.find(`[name="${e}"]`).each(function(){this!==t&&p(this,n[e])})})}setValues(e={}){throw new Error("setValues() must be implemented by subclass")}_setQuerySet(e,t){this._querySet=new WeakRef(e),this.loaded=t}get querySet(){return this._querySet.deref()}save({formName:e="edit_form",data:t=null}={}){return this._querySet.deref().save({pk:this.id,formName:e,data:t})}create(e=null){const t=ae(e)?e.data??null:e;return this._querySet.deref().create({elem:this,data:t})}delete(){return this._querySet.deref().delete({elem:this})}load(){return this._querySet.deref().update({item:this})}update(){return this.load()}get id(){return this._id}set id(e){this._id=e}set pk(e){this.id=e}get pk(){return this._id}close(){return this._querySet.deref().close()}_onClose(){Object.keys(this.constructor.fields).filter(e=>this[`_${e}`]instanceof ce).forEach(e=>this[`_${e}`].close())}detailView({cbResolve:e=null,cbReject:t=null,templateContext:n={}}){return this._querySet.deref().detailView({pk:this.id,cbResolve:e,cbReject:t,templateContext:n})}serialize(){return Object.entries(this.constructor.fields).reduce((e,[t,n])=>{const r=this[t];if(r instanceof ce)if(n.many_to_many||n.one_to_many)e[t]=r.getIds();else{const n=r.getIds();n.length>0?e[t]=n[0]:e[t]=null}else n.is_relation&&r instanceof ue?e[t]=r.id??null:r instanceof Date?e[t]="DateField"===n.type?m(r):r.toISOString():e[t]=r;return e},{})}toJson(){const e={};for(let t in this.constructor.fields){const n=this[t];n instanceof File?e[t]=n.name:e[t]=n instanceof ue?n.id:n instanceof ce?n.getIds():n}return e}syncFormToModel(e){return this.syncForm(e)}_resolveForms(e){return e&&e.hasClass(this.formId)?e:$(`.${this.formId}`)}syncModelToForm(e){e=this._resolveForms(e);const t=this,{fields:n}=this.constructor;e.each(function(){const e=le($(this).data("model_pk"));if(le(t.id)===e)for(let e of this.elements){let{name:r}=e;r&&""!==r&&n[r]&&p(e,t[r])}})}syncForm(e){e=this._resolveForms(e);const t=this,{fields:n}=this.constructor,r={};function s(e,s){if(n[e])try{t[e]=s}catch{}r[e]=s}return e.each(function(){const e=le($(this).data("model_pk"));if(t.id===e||null===t.id&&-1===e){for(let e of this.elements)s(e.name,d(e));return t}}),r}form({cbResolve:e=null,cbReject:t=null}={}){return null===this.id||-1===this.id?this._createForm({cbReject:t,cbResolve:e}):this._editForm({cbReject:t,cbResolve:e})}_createForm({cbResolve:e=null,cbReject:t=null}){let n=$("<div>");return this._querySet.deref().getForm({modelObj:this,eventType:"create_form",formName:null,$divForm:n,cbResolve:e,cbReject:t,formId:this.formId}),n}_editForm({cbResolve:e=null,cbReject:t=null}){let n=$("<div>");return this._querySet.deref().getForm({modelObj:this,eventType:"edit_form",formName:null,$divForm:n,cbResolve:e,cbReject:t,formId:this.formId}),n}namedForm({formName:e,cbResolve:t=null,cbReject:n=null}){let r=$('<div class="container-fluid">');return this._querySet.deref().getForm({modelObj:this,eventType:"named_form",formName:e,$divForm:r,cbResolve:t,cbReject:n,formId:this.formId}),r}validate(e,t){const n=function(e,t){const{type:n,required:r,max_length:s,is_relation:o,many_to_many:i,one_to_many:l,many_to_one:a,one_to_one:c,related_model:u}=t;if(r&&(null==e||""===e))return"This field is required";if(null==e||""===e)return null;if((i||l||a||c)&&(!(e instanceof ce)||e.modelName!==u))return"string"==typeof e&&(e=JSON.parse(e)),(i||a)&&Array.isArray(e)&&e.some(e=>!Number.isNaN(parseInt(e)))?null:"object"!=typeof e&&Number.isNaN(parseInt(e))?"Must be object or ID":null;switch(n){case"CharField":case"TextField":if("string"!=typeof e)return"Must be a string";if(s&&e.length>s)return`Max length is ${s}`;break;case"IntegerField":case"SmallIntegerField":case"BigIntegerField":case"PositiveIntegerField":case"PositiveSmallIntegerField":case"PositiveBigIntegerField":case"AutoField":case"SmallAutoField":case"BigAutoField":if(!isFinite(parseInt(e)))return"Must be an integer";break;case"FloatField":case"DecimalField":if(!isFinite(parseFloat(e)))return"Must be a number";break;case"BooleanField":if("boolean"!=typeof e)return"Must be a boolean";break;case"DateField":case"DateTimeField":if(isNaN(Date.parse(e)))return"Must be a valid date";break;case"EmailField":if("string"!=typeof e||!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(e))return"Invalid email";break;case"URLField":try{new URL(e)}catch{return"Invalid URL"}break;case"UUIDField":if(!/^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/.test(e))return"Invalid UUID";break;case"JSONField":if("string"==typeof e)try{JSON.parse(e)}catch{return"Must be valid JSON"}break;case"FileField":if(!(ie.isValid(e)||e instanceof File||e instanceof ie))return"Must be a valid file";if("undefined"!=typeof File&&e instanceof File){if(t.max_size&&e.size>t.max_size)return`File too large (max ${t.max_size} bytes)`;if(t.allowed_types&&!t.allowed_types.includes(e.type))return`Invalid file type (${e.type})`}}return null}(e,t);if(n)throw new Error(n)}parseValue(e,t){const{type:n,many_to_many:r,one_to_many:s,many_to_one:o,one_to_one:i}=t;if(null===e)return null;if((r||s||o||i)&&e&&"string"==typeof e)return JSON.parse(e);switch(n){case"CharField":case"TextField":case"SlugField":case"UUIDField":case"EmailField":return`${e}`;case"IntegerField":case"SmallIntegerField":case"BigIntegerField":case"PositiveIntegerField":case"PositiveSmallIntegerField":case"PositiveBigIntegerField":case"AutoField":case"SmallAutoField":case"BigAutoField":return parseInt(e,10);case"FloatField":case"DecimalField":return parseFloat(e);case"BooleanField":return!!e;case"DateField":case"DateTimeField":return f(e);case"URLField":return new URL(e);case"FileField":if(null==e)return null;if("string"==typeof e)return null;if(ie.isValid(e))return new ie(e);if(e instanceof ie)return new ie(e);if("undefined"!=typeof File&&e instanceof File)return e;break;case"JSONField":if("object"==typeof e)return e;if("string"==typeof e)return JSON.parse(e)}return e}}let de=!1,he=!1,fe=null,me={};function pe(){return window.SERVER_CALL_VIA_WEB_SOCKET?new Promise(e=>de?e():he?void setTimeout(()=>{pe().then(()=>{e()})},200):e(ge())):Promise.resolve(!0)}function _e(){window.SERVER_CALL_VIA_WEB_SOCKET&&function(){if(de){de=!1;try{fe.close()}catch(e){}}}()}function ge(){return he=!0,new Promise(e=>{fe="https:"===window.location.protocol?new WebSocket(`wss://${window.location.host}/sdc_ws/ws/`):new WebSocket(`ws://${window.location.host}/sdc_ws/ws/`),fe.onmessage=function(e){ye(JSON.parse(e.data))},fe.onclose=function(){de&&console.error("SDC Socket closed unexpectedly"),de=!1;for(const[e,t]of Object.entries(me))t[1]({}),delete me[e];setTimeout(()=>{ge()},1e3)},fe.onerror=function(e){if(console.error("Socket encountered error: ",e.message,"Closing socket"),de)try{fe.close()}catch(e){}},fe.onopen=function(){de=!0,he=!1,e()}})}function ye(e){if(e||(e={}),e.is_error)(e.msg||e.header)&&A("pushErrorMsg",e.header||"",e.msg||""),e.id&&me[e.id]&&(me[e.id][1](e.data||null),delete me[e.id]);else if((e.msg||e.header)&&A("pushMsg",e.header||"",e.msg||""),e.type&&"sdc_recall"===e.type){const{data:t}=e;t&&"object"==typeof t&&(t.msg||t.header)&&A("pushMsg",t.header||"",t.msg||""),e.id&&me[e.id]&&(me[e.id][0](e.data),delete me[e.id])}else if(e.type&&"sdc_event"===e.type){let{event:t}=e;t&&A(t,e.payload)}else e.type&&"sdc_redirect"===e.type&&A("onNavLink",e.link)}class ve{constructor(){this._uuid=a(),this.contentUrl="",this.contentReload=!1,this.parsedContentUrl=null,this.events=[],this.load_async=!1,this._allEvents=null,this._autoRedirect=null,this._params={},this._urlParams=[],this._models=[],this._cssUrls=[],this.afterShow=()=>{console.warn("afterShow is deprecated!!")},this._mixins={},this._tagName=Object.getPrototypeOf(this)._tagName??"",this._childController={},this._parentController=null,this._onLoadDone=!1,this.$container=null,this._isMixin=!1}get params(){return this._params}set params(e){this._params=e}_runLifecycle(e,t){$e.DEBUG&&!this._isMixin&&console.debug(e,this._tagName);let n=[];if(!this._isMixin){this._isMixin=!0;for(let r in this._mixins){let s=this._mixins[r];"function"==typeof s[e]&&n.push(s[e].apply(this,t))}return Promise.all(n).then(()=>{this._isMixin=!1})}}onInit(){$e.DEBUG&&!this._isMixin&&console.debug(Array.apply(null,arguments),this._tagName)}set autoRedirect(e){this._autoRedirect=e}get autoRedirect(){return this._autoRedirect}get parentController(){return this._parentController}get childController(){return this._childController}onLoad(){return this._runLifecycle("onLoad",arguments)}willShow(){return this._runLifecycle("willShow",arguments)}onRefresh(){return this._runLifecycle("onRefresh",arguments)}onRemove(){return this._runLifecycle("onRemove",arguments),!0}noOpenModelRequests(){return Promise.all(this._models.map(e=>e.noOpenRequests()))}remove(){for(const e of this._models)e.close();const{_childController:e}=this;for(let t in e)if(Object.hasOwn(e,t))for(let n of e[t])if(!n.remove())return!1;if(!this.onRemove||this.onRemove()){T(this);const e=r(this._tagName);if(this._parentController._childController[e]){let t=this._parentController._childController[e];for(let e=0;e<t.length;e++)t[e]===this&&t.splice(e,1)}return this.$container.remove(),!0}return!1}controller_name(){return this._tagName.replace(/-./g,e=>` ${e[1].toUpperCase()}`).replace(/^./g,e=>`${e.toUpperCase()}`)}addEvent(e,t,n){this.getEvents(),this._allEvents[e]=this._allEvents[e]||{},this._allEvents[e][t]=n}getEvents(){if(this._allEvents)return this._allEvents;let e=[];e=e.concat(this.events);for(let t in this._mixins){let n=this._mixins[t];Array.isArray(n.events)&&(e=e.concat(n.events))}return this._allEvents=_.merge({},...e)}post(e,t){return $e.post(this,e,t)}get(e,t){return $e.get(this,e,t)}submitForm(e,t,n){return $e.submitFormAndUpdateView(this,e,t,n)}serverCall(e,t){let n=this.contentUrl.match(/sdc_view\/([^/]+)/i);if(n&&!(n.length<2))return function(e,t,n,r,s){return s=function(e){return null==e?{}:"object"!=typeof e||Array.isArray(e)?{arg0:e}:e}(s),window.SERVER_CALL_VIA_WEB_SOCKET?function(e,t,n,r){let s=a();return pe().then(()=>{fe.send(JSON.stringify({event:"sdc_call",id:s,controller:t,app:e,function:n,args:r}))}),new Promise((e,t)=>{me[s]=[e,t]})}(e,t,r,s):function(e,t,n){return n={data:JSON.stringify(n),_sdc_func_name:t,_method:"sdc_server_call"},$.post({url:e,data:n,beforeSend:function(e,t){e.setRequestHeader("X-CSRFToken",window.CSRF_TOKEN)}}).then(e=>{const t=e._return_data;return ye(t),t}).catch(e=>{const t=e.responseJSON||{};throw t.is_error=!0,ye(t),e})}(n,r,s)}(n[1],this._tagName,this.parsedContentUrl??this.contentUrl,e,t);console.error("To use the serverCall function the contentUrl must contain sdc_view/<app>: "+this._tagName)}querySet(e,t={}){const n=new ce(e,t);return this._models.push(n),n}newModel(e,t={}){return console.warn("newModel is deprecated and will soon be removed. Please use this.querySet(modelName, modelQuery)"),this.querySet(e,t)}find(e){return this.$container.find(e)}refresh(){return $e.refresh(this.$container,this)}reload(){return $e.reloadController(this)}reconcile(e,t=null){return $e.reconcile(this,e,t)}submitModelFormDistributor(e,t){return"function"==typeof this._submitModelForm?this._submitModelForm(e,t):"function"==typeof this.submitModelForm?this.submitModelForm(e,t):this.defaultSubmitModelForm(e,t)}iterateAllChildren(){const{_childController:e}=this;let t=[];for(let n in e)if(Object.hasOwn(e,n))for(let r of e[n])t.push(r),t.push(...r.iterateAllChildren());return t}defaultSubmitModelForm(e,t){if(!this._isMixin){t.stopPropagation(),t.preventDefault();let{model:n,form_name:r}=e.data(),s=n.syncForm(e);return new Promise((t,o)=>{let i;i=null!==n.id&&n.id>=0?n.save({formName:r,data:s}):n.create({data:s}),i.then(n=>{c(e);const r=Array.isArray(n)?n[0]:n;this.submit_model_form_success&&this.submit_model_form_success(r);for(const e of this.iterateAllChildren())e.submit_model_form_success&&e.submit_model_form_success(r);t(n)}).catch(t=>{this.reconcile($(`<div class="container-fluid">${t.html}</div>`),e.find(".container-fluid").first()),this.submit_model_form_error&&this.submit_model_form_error(t);for(const e of this.iterateAllChildren())e.submit_model_form_error&&e.submit_model_form_error(t);o(t)})})}return Promise.resolve()}}const we={classname:"class"};window.sdcDom=function(e,t,...n){if(!e)return"";const r=function(e,t){let n,r=!1;if("string"==typeof e)n=$(document.createElement(e));else{const t=`this.${e.name}`;n=$(document.createElement(t)),n.data("handler",e),r=!0}return t&&Object.entries(t).forEach(([e,t])=>{if(e.startsWith("on")){const r=e.substring(2).toLowerCase();n[0].addEventListener(r,t),(n[0]._sdcListeners??=[]).push([r,t])}else we[e.toLowerCase()]&&(e=we[e.toLowerCase()]),n[0].setAttribute(e,t)}),r&&n.addClass("_bind_to_update_handler _with_handler"),n}(e,t);for(const e of n)r.append(e);return r};const be=e=>{e["url-link"]?A("onNavLink",e["url-link"]):window.location.href=e.url};let $e={CSRF_TOKEN:window.CSRF_TOKEN||"",LANGUAGE_CODE:window.LANGUAGE_CODE||"en",DEBUG:window.DEBUG||!1,VERSION:window.VERSION||"0.0",tagNames:[],Global:N,rootController:null,globalRootController:null,_isInit:!1,_origin_trigger:null,_globalControllerClasses:[],_createdGlobals:[],init_sdc:()=>{$e._isInit||($e._isInit=!0,$e._origin_trigger?_e():($e._origin_trigger=$.fn.trigger,$.fn.trigger=function(e){const t={}.hasOwnProperty.call(e,"type")?e.type:e;return w.includes(t)||(w.push(t),$(window).on(t,R)),$e._origin_trigger.call(this,e)},$e.updateJquery()),pe(),function(){const e=$(window);w.forEach(t=>{e.off(t).on(t,R)})}(),$e.rootController=$e.rootController||new ve,$e.globalRootController=$e.globalRootController||new ve),$e.tagNames=Object.keys(O);const t=N.filter(e=>!$e._createdGlobals.includes(e));$e._createdGlobals.push(...t);const n=$("<div></div>");t.forEach(e=>{const t=O[e][0];n.append(`<${t.prototype._tagName}></${t.prototype._tagName}>`)});const{refreshProcess:r}=I(null,$e.rootController);return K($e.tagNames,n,$e.globalRootController,r).then(()=>K($e.tagNames,(e||(e=$("body")),e),$e.rootController,r).then(e=>(x(r),e)))},updateJquery:()=>{$.fn.safeReplace=function(e){return $e.safeReplace($(this),e)},$.fn.safeEmpty=function(){return $e.safeEmpty($(this))},$.fn.safeRemove=function(){return $e.safeRemove($(this))}},controllerToTag:e=>n(e.name).replace(/-controller$/,""),registerGlobal:e=>{const t=$e.register(e);let n=e.prototype._tagName;return N.includes(n)||N.push(n),t},cleanCache:()=>{D={}},register:(e,t=!1)=>{let r=$e.controllerToTag(e);return!O[r]||t?(O[r]=[e,[]],e.prototype._tagName=r,{addMixin:(...e)=>{for(let t of e){let e;"string"==typeof t?e=n(t):t&&(e=$e.controllerToTag(t)),O[r][1].push(e)}}}):{addMixin:(...e)=>{}}},post:(e,t,n)=>(n||(n={}),n.CSRF_TOKEN=$e.CSRF_TOKEN,$e.ajax(e,t,n,$.post)),get:(e,t,n)=>$e.ajax(e,t,n,$.get),ajax:(e,t,n,r)=>{n||(n={}),n.VERSION=$e.VERSION,n._method=n._method||"api";const s=new Promise((o,i)=>r(t,n).then((t,n,r)=>{o(t,n,r),"redirect"===t.status?be(t):s.then(()=>{$e.refresh(e.$container)})}).catch((e,t,n)=>{301===e.status&&e.responseJSON?(e=e.responseJSON,be(e),o(e,t,n)):i(e,t,n)}));return s},submitFormAndUpdateView:(e,t,n,r)=>{let s=new FormData(t);const i=new Promise((l,a)=>{o(s,n||t.action,r||t.method).then((t,n,r)=>{l(t,n,r),"redirect"===t.status?be(t):i.then(()=>{$e.refresh(e.$container,e)})}).catch((e,t,n)=>{301===e.status?(e=e.responseJSON,be(e),l(e,t,n)):a(e,t,n)})});return i},submitForm:(e,t,n)=>{let r=new FormData(e);return new Promise((s,i)=>{o(r,t||e.action,n||e.method).then(s).catch(i)})},getController:e=>W(e),safeEmpty:e=>(e.children().each(function(e,t){let n=$(t);$e.safeRemove(n)}),e),safeReplace:(e,t)=>(t.insertBefore(e),$e.safeRemove(e)),safeRemove:e=>(e.each(function(){let e=$(this);e.data(`${U}`)&&e.data(`${U}`).remove()}),e.find(`.${M}`).each(function(){const e=$(this).data(`${U}`);e&&e.remove()}),e.remove()),reloadController:e=>function(e){if(e.contentUrl){let t=B(e);return e.contentUrl=t.url,V(e,t.args)}return new Promise(e=>{e($())})}(e).then(t=>{let n=$(t);return $e.reconcile(e,n)}),reconcile:(e,t,n=null,r=null)=>{if(!n){let n=e.$container.clone().empty();n.data(U,null),n.removeClass(M),n.append(t),t=n}n=n??e.$container;const{refreshProcess:s,isRunningProcess:o}=I(r,e);return Z(t,e,s).then(()=>{var r;return X(t,n),(r=e)._childController={},r.find(`.${M}`).each(function(){const e=$(this),t=W(e);t&&W(e.parent())===r&&S(r,t)}),o||x(s),e})},refresh:(e,t=null)=>Z(e,t)};function Re(e){for(var t=1;t<arguments.length;t++){var n=arguments[t];for(var r in n)"__proto__"!==r&&(e[r]=n[r])}return e}var Ce=function e(t,n){function r(e,r,s){if("undefined"!=typeof document){"number"==typeof(s=Re({},n,s)).expires&&(s.expires=new Date(Date.now()+864e5*s.expires)),s.expires&&(s.expires=s.expires.toUTCString()),e=encodeURIComponent(e).replace(/%(2[346B]|5E|60|7C)/g,decodeURIComponent).replace(/[()]/g,escape);var o="";for(var i in s)s[i]&&(o+="; "+i,!0!==s[i]&&(o+="="+s[i].split(";")[0]));return document.cookie=e+"="+t.write(r,e)+o}}return Object.create({set:r,get:function(e){if("undefined"!=typeof document&&(!arguments.length||e)){for(var n=document.cookie?document.cookie.split("; "):[],r={},s=0;s<n.length;s++){var o=n[s].split("="),i=o.slice(1).join("=");try{var l=decodeURIComponent(o[0]);if(l in r||(r[l]=t.read(i,l)),e===l)break}catch(e){}}return e?r[e]:r}},remove:function(e,t){r(e,"",Re({},t,{expires:-1}))},withAttributes:function(t){return e(this.converter,Re({},this.attributes,t))},withConverter:function(t){return e(Re({},this.converter,t),this.attributes)}},{attributes:{value:Object.freeze(n)},converter:{value:Object.freeze(t)}})}({read:function(e){return'"'===e[0]&&(e=e.slice(1,-1)),e.replace(/(%[\dA-F]{2})+/gi,decodeURIComponent)},write:function(e){return encodeURIComponent(e).replace(/%(2[346BF]|3[AC-F]|40|5[BDE]|60|7[BCD])/g,decodeURIComponent)}},{path:"/"});let Ne,Oe=[];function Se(){if(!jest)throw new Error("JEST is not defined");0===Oe.length&&(Ne=$.ajax.bind($),Oe.push(jest.spyOn($,"ajax")),Oe[0].mockImplementation(function(e){return Ne(e).then(e=>e).catch(e=>e)}))}const Fe=_e,ke={get_controller:async function(e,t={},n=""){Se();const r=$("body");$e.updateJquery(),r.safeEmpty();const s=$(`<${e}>${n}</${e}>`);for(const[e,n]of Object.entries(t))s.data(e,n);const o=$("<div></div>").append(s);r.append(o),$e._isInit=!1,$e.cleanCache(),await $e.init_sdc();const i=$e.getController(s);return i.navControllerPath=[e],i},getCsrfToken:function(){return function(e){if(document.cookie&&""!==document.cookie){const t=document.cookie.split(";");for(let n=0;n<t.length;n++){const r=t[n].trim();if(r.substring(0,10)===e+"=")return decodeURIComponent(r.substring(10))}}return""}("csrftoken")},controllerFromTestHtml:async function(e,t=null){Se();const n=$("body");$e.updateJquery(),n.safeEmpty().append(e),$e._isInit=!1,$e.cleanCache(),await $e.init_sdc();let r=$e.rootController.iterateAllChildren();if(!t)return r;const s=r[0].onRefresh,o=jest.spyOn(r[0],"onRefresh");return new Promise(e=>{o.mockImplementation(function(){o.mockRestore();const t=s.apply(r[0],arguments);return e(r),t})})},logout:()=>{Ce.remove("sessionid"),console.log("Logged out")},login:e=>{const t=globalThis.SDC_TEST_USER?.[e];return t?(Ce.set("sessionid",t),console.log(`Logged in as ${e}`),!0):(Ce.remove("sessionid"),console.warn(`Unknown test user: ${e}`),!1)}};export{ve as AbstractSDC,ue as SdcModel,ce as SdcQuerySet,T as allOff,$e as app,l as checkIfParamNumberBoolOrString,c as clearErrorsInForm,k as controllerFactory,L as on,te as registerModel,E as runControlFlowFunctions,u as setErrorsInForm,q as setEvent,Fe as socketReconnect,ke as test_utils,A as trigger};
@@ -1,8 +1 @@
1
- /**
2
- * @license
3
- * Lodash <https://lodash.com/>
4
- * Copyright OpenJS Foundation and other contributors <https://openjsf.org/>
5
- * Released under MIT license <https://lodash.com/license>
6
- * Based on Underscore.js 1.8.3 <http://underscorejs.org/LICENSE>
7
- * Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
8
- */
1
+ /*! js-cookie v3.0.8 | MIT */
package/gulp/gulp.jsx CHANGED
@@ -1,7 +1,5 @@
1
1
  const sass = require('gulp-sass')(require('sass'));
2
- const through = require('through2');
3
2
  const {src, dest, series, parallel} = require('gulp');
4
- const gclean = require('gulp-clean');
5
3
  const fs = require('fs');
6
4
  const exec = require('gulp-exec');
7
5
  const dotenv = require("dotenv");
@@ -18,52 +16,19 @@ function scss(bundle_mode = false) {
18
16
  }
19
17
 
20
18
  /**
21
- * Precompiler presets properties of the sdc controller.
22
- * Sets on_init argument names as _on_init_params names list
23
- * as prototype property to the controller
19
+ * Copies the client sources (following the linked app directories) to ./_build,
20
+ * which the bundle tasks use as input.
24
21
  *
25
22
  * @returns {*}
26
23
  */
27
24
  function pre_compile_javascript() {
28
25
  let fileExtensions = process.env.JS_CILENT_FILE_EXTENTIONS?.split(',') || ['.js', '.json'];
29
26
  return src(fileExtensions.map((x) => `./src/**/*${x}`), {follow: true})
30
- .pipe(through.obj(function (obj, enc, next) {
31
- let srcFile = obj.path
32
- if (!obj.isNull() && !obj.isDirectory() && obj.isBuffer() && /.js$/.test(srcFile)) {
33
- let file_content = obj.contents.toString().split('\n');
34
- let controller_name = null;
35
- let on_init_p_name = null;
36
- file_content.forEach((element) => {
37
- if (!controller_name) {
38
- let a = element.match(/class (.*)\s+extends\s*AbstractSDC /);
39
- if (a) controller_name = a[1];
40
- }
41
- if (!on_init_p_name) {
42
- let fnStr = element.match(/^\s*(async)?\s*onInit\s*\((.*)\)\s*\{/);
43
- if (fnStr) {
44
- on_init_p_name = fnStr[2].match(/(?<=^|,\s?)[^=\s,]+/g);
45
- }
46
- }
47
-
48
-
49
- });
50
- if (file_content && controller_name && on_init_p_name) {
51
- file_content.push(`${controller_name}.prototype._on_init_params = function() {return ["${on_init_p_name.join('", "')}"]; };`);
52
- obj.contents = Buffer.from(file_content.join('\n'));
53
- }
54
-
55
- }
56
- next(null, obj);
57
- }))
58
27
  .pipe(dest('./_build'));
59
28
  }
60
29
 
61
30
  function clean(done) {
62
- if (fs.existsSync('./_build')) {
63
- return src('./_build').pipe(gclean());
64
- } else {
65
- done()
66
- }
31
+ fs.rm('./_build', {recursive: true, force: true}, done);
67
32
  }
68
33
 
69
34
  function link_files(cb) {
@@ -100,10 +65,14 @@ function link_files(cb) {
100
65
  }
101
66
 
102
67
 
68
+ // File events that trigger a rebuild in the develop watchers.
69
+ const WATCH_EVENTS = ['add', 'change', 'unlink'];
70
+
103
71
  exports.sdc_watch_scss = function () {
104
72
  const watcher = gulp.watch('./src/**/*.scss', {followSymlinks: true});
105
- watcher.on('change', (a) => {
106
- console.log(`${a} has changed! SCSS is recompiling...`);
73
+ watcher.on('all', (event, a) => {
74
+ if (!WATCH_EVENTS.includes(event)) return;
75
+ console.log(`${a}: ${event}! SCSS is recompiling...`);
107
76
  scss()().on('end', () => {
108
77
  console.log(`... recompiling done!`);
109
78
  });
@@ -126,8 +95,9 @@ exports.sdc_watch_webpack_factory = (webpack_task, cb) => {
126
95
  usePolling: false, // optional
127
96
  ignored: /node_modules/,
128
97
  })
129
- watcher.on('change', (a) => {
130
- console.log(`${a} has changed! javascript is recompiling...`);
98
+ watcher.on('all', (event, a) => {
99
+ if (!WATCH_EVENTS.includes(event)) return;
100
+ console.log(`${a}: ${event}! javascript is recompiling...`);
131
101
  webpack_series_factory(webpack_task)();
132
102
  cb && cb();
133
103
  });
package/package.json CHANGED
@@ -1,12 +1,20 @@
1
1
  {
2
2
  "name": "sdc_client",
3
- "version": "0.158.8",
3
+ "version": "0.159.0",
4
4
  "description": "Simple Dom Control",
5
5
  "main": "dist/ugly.index.js",
6
+ "files": [
7
+ "dist",
8
+ "src",
9
+ "gulp",
10
+ "README.md",
11
+ "CHANGELOG.md"
12
+ ],
6
13
  "type": "module",
14
+ "packageManager": "yarn@4.18.0",
7
15
  "scripts": {
8
- "build": "gulp development & gulp build",
9
- "test": "gulp development & NODE_OPTIONS=--experimental-vm-modules jest",
16
+ "build": "gulp development && gulp build",
17
+ "test": "gulp development && NODE_OPTIONS=--experimental-vm-modules jest",
10
18
  "format": "prettier --write \"src/**/*.{js,jsx,scss,css,html,json}\"",
11
19
  "format:js": "eslint --fix \"src/**/*.js\"",
12
20
  "lint:js": "eslint \"src/**/*.js\""
@@ -26,43 +34,43 @@
26
34
  "author": "Martin Starman",
27
35
  "license": "MIT",
28
36
  "devDependencies": {
29
- "@babel/core": "^7.26.10",
30
- "@babel/eslint-parser": "^7.27.1",
31
- "@babel/plugin-transform-runtime": "^7.26.10",
32
- "@babel/preset-env": "^7.26.9",
33
- "@babel/preset-react": "^7.26.3",
34
- "@babel/register": "^7.25.9",
35
- "@eslint/js": "^9.19.0",
36
- "babel-loader": "^10.0.0",
37
+ "@eslint/js": "^10.0.1",
37
38
  "baseline-browser-mapping": "^2.9.19",
38
- "dotenv": "^16.4.7",
39
- "eslint": "^9.19.0",
40
- "eslint-plugin-no-relative-import-paths": "^1.6.1",
41
- "eslint-plugin-react": "^7.37.5",
39
+ "eslint": "^10.8.1",
42
40
  "glob-parent": "^6.0.2",
43
41
  "globals": "^15.14.0",
44
42
  "gulp": "^5.0.1",
45
- "gulp-clean": "^0.4.0",
46
- "gulp-exec": "^5.0.0",
47
- "gulp-sass": "^6.0.1",
48
- "jest": "^29.7.0",
49
- "jest-environment-jsdom": "^29.7.0",
43
+ "jest": "^30.4.2",
44
+ "jest-environment-jsdom": "^30.4.1",
45
+ "jquery": "^3.7.1",
46
+ "lodash": "4.17.23",
50
47
  "micromatch": "^4.0.8",
51
48
  "prettier": "^3.8.1",
52
- "sass": "^1.85.1",
53
- "through2": "^4.0.2",
54
- "vinyl-named": "^1.1.0",
55
- "webpack": "^5.104.1",
56
- "webpack-stream": "^7.0.0"
49
+ "webpack": "^5.104.1"
57
50
  },
58
51
  "overrides": {
59
- "glob-parent": "$glob-parent"
52
+ "glob": "^13.0.6",
53
+ "glob-parent": "$glob-parent",
54
+ "jsdom": "^29.1.1",
55
+ "test-exclude": "^8.0.0"
56
+ },
57
+ "resolutions": {
58
+ "glob": "^13.0.6",
59
+ "glob-parent": "^6.0.2",
60
+ "jsdom": "^29.1.1",
61
+ "test-exclude": "^8.0.0"
60
62
  },
61
63
  "dependencies": {
62
- "@popperjs/core": "^2.11.8",
63
- "bootstrap": "^5.3.2",
64
- "esm": "^3.2.25",
65
- "jquery": "^3.7.1",
66
- "lodash": "4.17.23"
64
+ "dotenv": "^16.4.7",
65
+ "gulp-exec": "^5.0.0",
66
+ "gulp-sass": "^6.0.1",
67
+ "js-cookie": "^3.0.8",
68
+ "sass": "^1.85.1",
69
+ "through2": "^4.0.2"
70
+ },
71
+ "peerDependencies": {
72
+ "gulp": "^5.0.0",
73
+ "jquery": "^3.7.0",
74
+ "lodash": "^4.17.21"
67
75
  }
68
76
  }
package/src/index.js CHANGED
@@ -1,7 +1,8 @@
1
- import {app} from "./simpleDomControl/sdc_main.js";
2
- import {AbstractSDC} from "./simpleDomControl/AbstractSDC.js";
3
- import SdcModel, {SdcQuerySet} from "./simpleDomControl/sdc_model.js";
4
- import {registerModel} from "./simpleDomControl/sdc_socket.js";
1
+ import { app } from "./simpleDomControl/sdc_main.js";
2
+ import { AbstractSDC } from "./simpleDomControl/AbstractSDC.js";
3
+ import SdcModel, { SdcQuerySet } from "./simpleDomControl/sdc_model.js";
4
+ import { registerModel } from "./simpleDomControl/sdc_socket.js";
5
+ import Cookies from "js-cookie";
5
6
  import {
6
7
  on,
7
8
  trigger,
@@ -18,7 +19,7 @@ import {
18
19
  controllerFactory,
19
20
  runControlFlowFunctions,
20
21
  } from "./simpleDomControl/sdc_controller.js";
21
- import {close} from "./simpleDomControl/sdc_server_call.js";
22
+ import { close } from "./simpleDomControl/sdc_server_call.js";
22
23
  import {
23
24
  get_controller,
24
25
  getCsrfToken,
@@ -26,7 +27,26 @@ import {
26
27
  } from "./simpleDomControl/sdc_test_utils.js";
27
28
 
28
29
  const socketReconnect = close;
29
- const test_utils = {get_controller, getCsrfToken, controllerFromTestHtml};
30
+ const test_utils = {
31
+ get_controller,
32
+ getCsrfToken,
33
+ controllerFromTestHtml,
34
+ logout: () => {
35
+ Cookies.remove("sessionid");
36
+ console.log("Logged out");
37
+ },
38
+ login: (user) => {
39
+ const sessionId = globalThis.SDC_TEST_USER?.[user];
40
+ if (!sessionId) {
41
+ Cookies.remove("sessionid");
42
+ console.warn(`Unknown test user: ${user}`);
43
+ return false;
44
+ }
45
+ Cookies.set("sessionid", sessionId);
46
+ console.log(`Logged in as ${user}`);
47
+ return true;
48
+ },
49
+ };
30
50
 
31
51
  export {
32
52
  app,
@@ -44,5 +64,5 @@ export {
44
64
  test_utils,
45
65
  SdcModel,
46
66
  SdcQuerySet,
47
- registerModel
67
+ registerModel,
48
68
  };
@@ -17,8 +17,8 @@ export class AbstractSDC {
17
17
  this.parsedContentUrl = null;
18
18
  this.events = [];
19
19
  this.load_async = false;
20
- this._isEventsSet = false;
21
20
  this._allEvents = null;
21
+ this._autoRedirect = null;
22
22
  this._params = {};
23
23
 
24
24
  this._urlParams = [];
@@ -106,6 +106,8 @@ export class AbstractSDC {
106
106
  }
107
107
 
108
108
  /**
109
+ * @deprecated Not called by the runtime since 0.158.7. Read the data-*
110
+ * attributes from ``this.params`` in ``onLoad()`` instead.
109
111
  *
110
112
  * @return {Promise<*>|*}
111
113
  */
@@ -115,6 +117,14 @@ export class AbstractSDC {
115
117
  }
116
118
  }
117
119
 
120
+ set autoRedirect(url){
121
+ this._autoRedirect = url;
122
+ }
123
+
124
+ get autoRedirect() {
125
+ return this._autoRedirect;
126
+ }
127
+
118
128
  get parentController() {
119
129
  return this._parentController;
120
130
  }
@@ -148,9 +158,9 @@ export class AbstractSDC {
148
158
  for (const model of this._models) {
149
159
  model.close();
150
160
  }
151
- let _childController = this._childController;
161
+ const { _childController } = this;
152
162
  for (let i in _childController) {
153
- if (_childController.hasOwnProperty(i)) {
163
+ if (Object.hasOwn(_childController, i)) {
154
164
  for (let cc of _childController[i]) {
155
165
  if (!cc.remove()) {
156
166
  return false;
@@ -172,7 +182,6 @@ export class AbstractSDC {
172
182
  }
173
183
 
174
184
  this.$container.remove();
175
- delete this;
176
185
  return true;
177
186
  }
178
187
 
@@ -200,7 +209,9 @@ export class AbstractSDC {
200
209
  }
201
210
  }
202
211
 
203
- return (this._allEvents = _.merge(...allEvents));
212
+ // Merge into a new object: the event maps of the controller and its mixins
213
+ // may be shared between instances and must not be changed.
214
+ return (this._allEvents = _.merge({}, ...allEvents));
204
215
  }
205
216
 
206
217
  post(url, args) {
@@ -220,8 +231,8 @@ export class AbstractSDC {
220
231
  let app = this.contentUrl.match(re);
221
232
  if (!app || app.length < 2) {
222
233
  console.error(
223
- "To use the serverCall function the contentUrl must be set: " +
224
- this.name,
234
+ "To use the serverCall function the contentUrl must contain sdc_view/<app>: " +
235
+ this._tagName,
225
236
  );
226
237
  return;
227
238
  }
@@ -283,10 +294,10 @@ export class AbstractSDC {
283
294
  }
284
295
 
285
296
  iterateAllChildren() {
286
- let _childController = this._childController;
297
+ const { _childController } = this;
287
298
  let res = [];
288
299
  for (let i in _childController) {
289
- if (_childController.hasOwnProperty(i)) {
300
+ if (Object.hasOwn(_childController, i)) {
290
301
  for (let cc of _childController[i]) {
291
302
  res.push(cc);
292
303
  res.push(...cc.iterateAllChildren());
@@ -316,11 +327,13 @@ export class AbstractSDC {
316
327
  prom
317
328
  .then((res) => {
318
329
  clearErrorsInForm($form);
330
+ // save() resolves with a list of responses, create() with one response.
331
+ const response = Array.isArray(res) ? res[0] : res;
319
332
  this.submit_model_form_success &&
320
- this.submit_model_form_success(res[0]);
333
+ this.submit_model_form_success(response);
321
334
  for (const controller of this.iterateAllChildren()) {
322
335
  controller.submit_model_form_success &&
323
- controller.submit_model_form_success(res[0]);
336
+ controller.submit_model_form_success(response);
324
337
  }
325
338
 
326
339
  resolve(res);
@@ -13,7 +13,7 @@ import {
13
13
 
14
14
  import { runOnInitWithParameter } from "./sdc_params.js";
15
15
  import { setControllerEvents } from "./sdc_dom_events.js";
16
- import { app } from "./sdc_main.js";
16
+ import "./sdc_main.js";
17
17
 
18
18
  export let Global = [];
19
19
  export let controllerList = {};
@@ -74,7 +74,8 @@ export function resetChildren(parentController) {
74
74
  parentController.find(`.${CONTROLLER_CLASS}`).each(function () {
75
75
  const $this = $(this);
76
76
  const cController = getController($this);
77
- if (cController === parentController) {
77
+ // Direct children only: the closest controller around the child element is the parent.
78
+ if (cController && getController($this.parent()) === parentController) {
78
79
  setParentController(parentController, cController);
79
80
  }
80
81
  });
@@ -229,7 +230,10 @@ export function runControlFlowFunctions(controller, process) {
229
230
  return runRefresh(controller, process);
230
231
  })
231
232
  .catch(function ($html) {
232
- return runControllerFillContent(controller, $html);
233
+ if (typeof $html === 'string' || $html instanceof $) {
234
+ return runControllerFillContent(controller, $html);
235
+ }
236
+ throw $html;
233
237
  });
234
238
 
235
239
  if (controller.load_async) {
@@ -251,7 +255,6 @@ export function runRefresh(controller, process) {
251
255
  function getParentList(controller) {
252
256
  let controllerList = [];
253
257
  while (controller) {
254
- controller._isEventsSet = false;
255
258
  controllerList.unshift(controller);
256
259
  controller = controller._parentController;
257
260
  }