web-mojo 2.3.0 → 2.3.1

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 (113) hide show
  1. package/CHANGELOG.md +124 -0
  2. package/dist/admin-models.cjs.js +1 -1
  3. package/dist/admin-models.es.js +1 -1
  4. package/dist/admin.cjs.js +1 -1
  5. package/dist/admin.es.js +1 -1
  6. package/dist/auth.cjs.js +1 -1
  7. package/dist/auth.es.js +1 -1
  8. package/dist/charts.cjs.js +1 -1
  9. package/dist/charts.es.js +1 -1
  10. package/dist/chunks/{AssistantPanelView-BG34Qbfj.js → AssistantPanelView-CE6me7sJ.js} +2 -2
  11. package/dist/chunks/{AssistantPanelView-BG34Qbfj.js.map → AssistantPanelView-CE6me7sJ.js.map} +1 -1
  12. package/dist/chunks/{AssistantPanelView-DCEV6VeI.js → AssistantPanelView-DvsLAAIF.js} +2 -2
  13. package/dist/chunks/{AssistantPanelView-DCEV6VeI.js.map → AssistantPanelView-DvsLAAIF.js.map} +1 -1
  14. package/dist/chunks/{ChatView-B73uox2v.js → ChatView-CXykdAV1.js} +2 -2
  15. package/dist/chunks/{ChatView-B73uox2v.js.map → ChatView-CXykdAV1.js.map} +1 -1
  16. package/dist/chunks/{ChatView-W8daOwIo.js → ChatView-ys5MIiBf.js} +2 -2
  17. package/dist/chunks/{ChatView-W8daOwIo.js.map → ChatView-ys5MIiBf.js.map} +1 -1
  18. package/dist/chunks/{Collection-BZlmtcuL.js → Collection-BpUmNuDZ.js} +2 -2
  19. package/dist/chunks/{Collection-BZlmtcuL.js.map → Collection-BpUmNuDZ.js.map} +1 -1
  20. package/dist/chunks/{Collection-Bwoq6muu.js → Collection-CY6BblFn.js} +2 -2
  21. package/dist/chunks/{Collection-Bwoq6muu.js.map → Collection-CY6BblFn.js.map} +1 -1
  22. package/dist/chunks/{ContextMenu-q76hjQb6.js → ContextMenu-PtN50qH2.js} +2 -2
  23. package/dist/chunks/{ContextMenu-q76hjQb6.js.map → ContextMenu-PtN50qH2.js.map} +1 -1
  24. package/dist/chunks/{ContextMenu-BPPtuqKk.js → ContextMenu-XQVFU0mL.js} +2 -2
  25. package/dist/chunks/{ContextMenu-BPPtuqKk.js.map → ContextMenu-XQVFU0mL.js.map} +1 -1
  26. package/dist/chunks/{DataView-k-7wmk5_.js → DataView-BTi_BZHx.js} +2 -2
  27. package/dist/chunks/{DataView-k-7wmk5_.js.map → DataView-BTi_BZHx.js.map} +1 -1
  28. package/dist/chunks/{DataView-BbrwHMV4.js → DataView-WHRh1o6E.js} +2 -2
  29. package/dist/chunks/{DataView-BbrwHMV4.js.map → DataView-WHRh1o6E.js.map} +1 -1
  30. package/dist/chunks/{FormView-Dcy7XOtC.js → FormView-BzaGMf5_.js} +3 -3
  31. package/dist/chunks/{FormView-Dcy7XOtC.js.map → FormView-BzaGMf5_.js.map} +1 -1
  32. package/dist/chunks/{FormView-DPSuwWMq.js → FormView-DTD-Zy22.js} +3 -3
  33. package/dist/chunks/{FormView-DPSuwWMq.js.map → FormView-DTD-Zy22.js.map} +1 -1
  34. package/dist/chunks/{ListView-iGBsD4a7.js → ListView-BsnnTcmC.js} +2 -2
  35. package/dist/chunks/{ListView-iGBsD4a7.js.map → ListView-BsnnTcmC.js.map} +1 -1
  36. package/dist/chunks/{ListView-DHC-yBIw.js → ListView-Xf7kO6Me.js} +2 -2
  37. package/dist/chunks/{ListView-DHC-yBIw.js.map → ListView-Xf7kO6Me.js.map} +1 -1
  38. package/dist/chunks/{MetricsCountryMapView-CAD9wR_T.js → MetricsCountryMapView-BzGOi1d2.js} +2 -2
  39. package/dist/chunks/{MetricsCountryMapView-CAD9wR_T.js.map → MetricsCountryMapView-BzGOi1d2.js.map} +1 -1
  40. package/dist/chunks/{MetricsCountryMapView-Dzk3Yrzx.js → MetricsCountryMapView-C-S00Wiw.js} +2 -2
  41. package/dist/chunks/{MetricsCountryMapView-Dzk3Yrzx.js.map → MetricsCountryMapView-C-S00Wiw.js.map} +1 -1
  42. package/dist/chunks/{Modal-DuULCMFZ.js → Modal-GWjyfcz5.js} +3 -3
  43. package/dist/chunks/Modal-GWjyfcz5.js.map +1 -0
  44. package/dist/chunks/{Modal-DBJU16cc.js → Modal-wrfWfQhv.js} +3 -3
  45. package/dist/chunks/Modal-wrfWfQhv.js.map +1 -0
  46. package/dist/chunks/{Passkeys-CGRZ8ZMv.js → Passkeys-BviQX3_5.js} +2 -2
  47. package/dist/chunks/{Passkeys-CGRZ8ZMv.js.map → Passkeys-BviQX3_5.js.map} +1 -1
  48. package/dist/chunks/{Passkeys-Dr8-oSm9.js → Passkeys-gXR1Rc6C.js} +2 -2
  49. package/dist/chunks/{Passkeys-Dr8-oSm9.js.map → Passkeys-gXR1Rc6C.js.map} +1 -1
  50. package/dist/chunks/TokenManager-C6aXkRaI.js +2 -0
  51. package/dist/chunks/TokenManager-C6aXkRaI.js.map +1 -0
  52. package/dist/chunks/TokenManager-DgvhhTqN.js +2 -0
  53. package/dist/chunks/TokenManager-DgvhhTqN.js.map +1 -0
  54. package/dist/chunks/{User-Dg7xpYEI.js → User-B_Urf7U7.js} +2 -2
  55. package/dist/chunks/{User-Dg7xpYEI.js.map → User-B_Urf7U7.js.map} +1 -1
  56. package/dist/chunks/{User-DNQhdBtI.js → User-KTBU_5cr.js} +2 -2
  57. package/dist/chunks/{User-DNQhdBtI.js.map → User-KTBU_5cr.js.map} +1 -1
  58. package/dist/chunks/{UserProfileView-Bpz3VZmP.js → UserProfileView-BmduMJ86.js} +2 -2
  59. package/dist/chunks/{UserProfileView-Bpz3VZmP.js.map → UserProfileView-BmduMJ86.js.map} +1 -1
  60. package/dist/chunks/{UserProfileView-B5nczdfw.js → UserProfileView-COxSyPB0.js} +2 -2
  61. package/dist/chunks/{UserProfileView-B5nczdfw.js.map → UserProfileView-COxSyPB0.js.map} +1 -1
  62. package/dist/chunks/{View-Yazho7OL.js → View-C8UWvaSM.js} +2 -2
  63. package/dist/chunks/{View-Yazho7OL.js.map → View-C8UWvaSM.js.map} +1 -1
  64. package/dist/chunks/{View-C5n3sIFi.js → View-Cvs2TY7b.js} +2 -2
  65. package/dist/chunks/{View-C5n3sIFi.js.map → View-Cvs2TY7b.js.map} +1 -1
  66. package/dist/chunks/{WebApp-CeiDNV6L.js → WebApp-DuwanN2O.js} +2 -2
  67. package/dist/chunks/{WebApp-CeiDNV6L.js.map → WebApp-DuwanN2O.js.map} +1 -1
  68. package/dist/chunks/{WebApp-irKlhuFX.js → WebApp-kbRq7dM_.js} +2 -2
  69. package/dist/chunks/{WebApp-irKlhuFX.js.map → WebApp-kbRq7dM_.js.map} +1 -1
  70. package/dist/chunks/{admin-B5tf0zOO.js → admin-CszsTA0T.js} +2 -2
  71. package/dist/chunks/{admin-B5tf0zOO.js.map → admin-CszsTA0T.js.map} +1 -1
  72. package/dist/chunks/{admin-CGoTpXfs.js → admin-vsKDrnpV.js} +2 -2
  73. package/dist/chunks/{admin-CGoTpXfs.js.map → admin-vsKDrnpV.js.map} +1 -1
  74. package/dist/chunks/{exportChart-kQ-we4Cp.js → exportChart-Bkxr7mCe.js} +2 -2
  75. package/dist/chunks/{exportChart-kQ-we4Cp.js.map → exportChart-Bkxr7mCe.js.map} +1 -1
  76. package/dist/chunks/{exportChart-BTJBYkOz.js → exportChart-Dn2pioNl.js} +2 -2
  77. package/dist/chunks/{exportChart-BTJBYkOz.js.map → exportChart-Dn2pioNl.js.map} +1 -1
  78. package/dist/chunks/{index-BNjCQA7q.js → index-BCWkcyOy.js} +2 -2
  79. package/dist/chunks/{index-BNjCQA7q.js.map → index-BCWkcyOy.js.map} +1 -1
  80. package/dist/chunks/{index-DBsIDOAa.js → index-CJeTVskY.js} +2 -2
  81. package/dist/chunks/{index-DBsIDOAa.js.map → index-CJeTVskY.js.map} +1 -1
  82. package/dist/chunks/{version-BURwX10Q.js → version-CRFysUYb.js} +2 -2
  83. package/dist/chunks/{version-BURwX10Q.js.map → version-CRFysUYb.js.map} +1 -1
  84. package/dist/chunks/{version-CYGIXntv.js → version-uUvnEzFR.js} +2 -2
  85. package/dist/chunks/{version-CYGIXntv.js.map → version-uUvnEzFR.js.map} +1 -1
  86. package/dist/core.css +134 -109
  87. package/dist/css/web-mojo.css +1 -1
  88. package/dist/docit.cjs.js +1 -1
  89. package/dist/docit.es.js +1 -1
  90. package/dist/index.cjs.js +1 -1
  91. package/dist/index.cjs.js.map +1 -1
  92. package/dist/index.es.js +1 -1
  93. package/dist/index.es.js.map +1 -1
  94. package/dist/lightbox.cjs.js +1 -1
  95. package/dist/lightbox.es.js +1 -1
  96. package/dist/map.cjs.js +1 -1
  97. package/dist/map.es.js +1 -1
  98. package/dist/portal.css +32 -0
  99. package/dist/timeline.cjs.js +1 -1
  100. package/dist/timeline.es.js +1 -1
  101. package/dist/user-profile.cjs.js +1 -1
  102. package/dist/user-profile.es.js +1 -1
  103. package/dist/web-mojo.lite.iife.js +33 -9
  104. package/dist/web-mojo.lite.iife.js.map +1 -1
  105. package/dist/web-mojo.lite.iife.min.js +5 -5
  106. package/dist/web-mojo.lite.iife.min.js.map +1 -1
  107. package/package.json +1 -1
  108. package/dist/chunks/Modal-DBJU16cc.js.map +0 -1
  109. package/dist/chunks/Modal-DuULCMFZ.js.map +0 -1
  110. package/dist/chunks/TokenManager-CcQFvaFD.js +0 -2
  111. package/dist/chunks/TokenManager-CcQFvaFD.js.map +0 -1
  112. package/dist/chunks/TokenManager-DEWZqbuo.js +0 -2
  113. package/dist/chunks/TokenManager-DEWZqbuo.js.map +0 -1
@@ -12,7 +12,7 @@ var MOJO=(function(A){"use strict";class le{constructor(e={}){this.defaultRoute=
12
12
  ${a}
13
13
  </span>
14
14
  `}nl2br(e){return e==null?"":this.escapeHtml(String(e)).replace(/\r\n|\r|\n/g,"<br>")}code(e,t=""){if(e==null)return"";const s=t?`language-${this.escapeHtml(String(t))}`:"",i=this.escapeHtml(String(e));return`<pre class="bg-light p-2 rounded border"><code class="${s}">${i}</code></pre>`}register(e,t){if(typeof t!="function")throw new Error(`Formatter must be a function, got ${typeof t}`);return this.formatters.set(e.toLowerCase(),t),this}apply(e,t,...s){try{const i=this.formatters.get(e.toLowerCase());return i?i(t,...s):(console.warn(`Formatter '${e}' not found`),t)}catch(i){return console.error(`Error in formatter '${e}':`,i),t}}pipe(e,t,s=null){return t?this.parsePipeString(t,s).reduce((r,a)=>this.apply(a.name,r,...a.args),e):e}parsePipeString(e,t=null){const s=[],i=e.split("|").map(r=>r.trim());for(const r of i){const a=this.parseFormatter(r,t);a&&s.push(a)}return s}parseFormatter(e,t=null){const s=e.match(/^([a-zA-Z_]\w*)\s*\((.*)\)$/);if(s){const[,r,a]=s,n=a?this.parseArguments(a,t):[];return{name:r,args:n}}const i=e.match(/^([a-zA-Z_]\w*)(?::(.+))?$/);if(i){const[,r,a]=i,n=a?this.parseColonArguments(a,t):[];return{name:r,args:n}}return null}parseArguments(e,t=null){const s=[];let i="",r=!1,a=null,n=0;for(let o=0;o<e.length;o++){const l=e[o];!r&&(l==='"'||l==="'")?(r=!0,a=l,i+=l):r&&l===a&&e[o-1]!=="\\"?(r=!1,a=null,i+=l):!r&&l==="{"?(n++,i+=l):!r&&l==="}"?(n--,i+=l):!r&&n===0&&l===","?(s.push(this.parseValue(i.trim(),t)),i=""):i+=l}return i.trim()&&s.push(this.parseValue(i.trim(),t)),s}parseColonArguments(e,t=null){const s=[];let i="",r=!1,a=null;for(let n=0;n<e.length;n++){const o=e[n];!r&&(o==='"'||o==="'")?(r=!0,a=o,i+=o):r&&o===a&&e[n-1]!=="\\"?(r=!1,a=null,i+=o):!r&&o===":"?(s.push(this.parseValue(i.trim(),t)),i=""):i+=o}return i.trim()&&s.push(this.parseValue(i.trim(),t)),s}parseValue(e,t=null){if(e.startsWith('"')&&e.endsWith('"')||e.startsWith("'")&&e.endsWith("'"))return e.slice(1,-1);if(e==="true")return!0;if(e==="false")return!1;if(e==="null")return null;if(e!=="undefined"){if(!isNaN(e)&&e!=="")return Number(e);if(e.startsWith("{")&&e.endsWith("}"))try{return JSON.parse(e)}catch{}if(t&&this.isIdentifier(e)){if(!e.includes(".")&&Object.prototype.hasOwnProperty.call(t,e))return t[e];if(t.get&&typeof t.get=="function"){const s=t.get(e);if(s!==void 0)return s}if(t.getContextValue&&typeof t.getContextValue=="function"){const s=t.getContextValue(e);if(s!==void 0)return s}if(e.includes(".")){const s=window.MOJOUtils||(typeof require<"u"?require("./MOJOUtils.js").default:null);if(s){const i=s.getNestedValue(t,e);if(i!==void 0)return i}}}return e}}isIdentifier(e){return/^[a-zA-Z_$][a-zA-Z0-9_$]*(\.[a-zA-Z_$][a-zA-Z0-9_$]*)*$/.test(e)}date(e,t="MM/DD/YYYY"){if(!e)return"";e=this.normalizeEpoch(e);let s;if(e instanceof Date)s=e;else if(typeof e=="string")if(/^\d{4}-\d{2}-\d{2}$/.test(e)){const[n,o,l]=e.split("-").map(Number);s=new Date(n,o-1,l)}else s=new Date(e);else s=new Date(e);if(isNaN(s.getTime()))return String(e);const i={YYYY:s.getFullYear(),YY:String(s.getFullYear()).slice(-2),MMMM:s.toLocaleDateString("en-US",{month:"long"}),MMM:s.toLocaleDateString("en-US",{month:"short"}),MM:String(s.getMonth()+1).padStart(2,"0"),M:s.getMonth()+1,dddd:s.toLocaleDateString("en-US",{weekday:"long"}),ddd:s.toLocaleDateString("en-US",{weekday:"short"}),DD:String(s.getDate()).padStart(2,"0"),D:s.getDate()};let r=t;const a=new RegExp(`(${Object.keys(i).join("|")})`,"g");return r=r.replace(a,n=>i[n]||n),r}time(e,t="HH:mm:ss"){if(!e)return"";e=this.normalizeEpoch(e);const s=e instanceof Date?e:new Date(e);if(isNaN(s.getTime()))return String(e);const i=s.getHours(),r={HH:String(i).padStart(2,"0"),H:i,hh:String(i%12||12).padStart(2,"0"),h:i%12||12,mm:String(s.getMinutes()).padStart(2,"0"),m:s.getMinutes(),ss:String(s.getSeconds()).padStart(2,"0"),s:s.getSeconds(),A:i>=12?"PM":"AM",a:i>=12?"pm":"am"};let a=t;const n=Object.keys(r).sort((o,l)=>l.length-o.length);for(const o of n)a=a.replace(new RegExp(o,"g"),r[o]);return a}datetime(e,t="MM/DD/YYYY",s="HH:mm:ss"){e=this.normalizeEpoch(e);const i=this.date(e,t),r=this.time(e,s);return i&&r?`${i} ${r}`:""}datetime_tz(e,t="MM/DD/YYYY",s="HH:mm:ss",i={}){if(!e)return"";e=this.normalizeEpoch(e);const r=e instanceof Date?e:new Date(e);if(isNaN(r.getTime()))return String(e);const a=i&&i.locale||"en-US",n=i&&i.timeZone?i.timeZone:void 0,o=()=>{let k="";try{const B=new Intl.DateTimeFormat(a,{hour:"2-digit",minute:"2-digit",timeZoneName:"short",...n?{timeZone:n}:{}}).formatToParts(r).find(P=>P.type==="timeZoneName");if(k=B?B.value:"",k&&/^GMT[+-]/i.test(k))try{const U=new Intl.DateTimeFormat(a,{timeStyle:"short",timeZoneName:"short",...n?{timeZone:n}:{}}).formatToParts(r).find(vt=>vt.type==="timeZoneName");U&&U.value&&!/^GMT[+-]/i.test(U.value)&&(k=U.value)}catch{}if(k&&/\s/.test(k)){const P=k.split(/\s+/).map(U=>U[0]).join("").toUpperCase();P.length>=2&&P.length<=4&&(k=P)}}catch{k=""}return k};if(!n){const k=this.date(r,t),q=this.time(r,s),B=o();return k&&q?`${k} ${q} ${B}`.trim():""}const l=new Intl.DateTimeFormat(a,{timeZone:n,year:"numeric",month:"2-digit",day:"2-digit",hour:"2-digit",minute:"2-digit",second:"2-digit",hourCycle:"h23"}).formatToParts(r),c=k=>{const q=l.find(B=>B.type===k);return q?q.value:""},d=c("year"),u=c("month"),p=c("day"),m=c("hour"),f=c("minute"),g=c("second"),w=u?String(parseInt(u,10)):"",y=p?String(parseInt(p,10)):"",v=m?String(parseInt(m,10)):"",x=m?parseInt(m,10)%12||12:"",E=m?parseInt(m,10)>=12?"PM":"AM":"",D=E?E.toLowerCase():"",L=new Intl.DateTimeFormat(a,{timeZone:n,month:"long"}).format(r),N=new Intl.DateTimeFormat(a,{timeZone:n,month:"short"}).format(r),O=new Intl.DateTimeFormat(a,{timeZone:n,weekday:"long"}).format(r),oe=new Intl.DateTimeFormat(a,{timeZone:n,weekday:"short"}).format(r),Ae={YYYY:d,YY:d?d.slice(-2):"",MMMM:L,MMM:N,MM:u,M:w,dddd:O,ddd:oe,DD:p,D:y},De={HH:m,H:v,hh:x!==""?String(x).padStart(2,"0"):"",h:x!==""?String(x):"",mm:f,m:f?String(parseInt(f,10)):"",ss:g,s:g?String(parseInt(g,10)):"",A:E,a:D},I=(k,q)=>{if(!k)return"";const B=new RegExp(`(${Object.keys(q).sort((P,U)=>U.length-P.length).join("|")})`,"g");return k.replace(B,P=>q[P]??P)},H=I(t,Ae),qe=I(s,De),wt=o();return H&&qe?`${H} ${qe} ${wt}`.trim():""}normalizeEpoch(e){if(e instanceof Date)return e;if(typeof e=="string"){const t=Number(e);if(Number.isFinite(t))e=t;else{const s=Date.parse(e);return Number.isFinite(s)?s:""}}else typeof e!="number"&&(e=Number(e));if(isNaN(e))return"";if(e<1e11)return e*1e3;if(e>1e12&&e<1e13)return e;throw new Error("Value doesn't look like epoch seconds or ms")}date_range(e,t=null,s="MM/DD/YYYY"){if(!e)return"";const i=t||new Date,r=this.date(e,s),a=this.date(i,s);return!r||!a?"":`${r} - ${a}`}datetime_range(e,t=null,s="MM/DD/YYYY",i="HH:mm"){if(!e)return"";const r=t||new Date,a=this.datetime(e,s,i),n=this.datetime(r,s,i);return!a||!n?"":`${a} - ${n}`}relative(e,t=!1){if(!e)return"";e=this.normalizeEpoch(e);const s=e instanceof Date?e:new Date(e);if(isNaN(s.getTime()))return String(e);const r=s-new Date,a=Math.abs(r),n=Math.floor(a/1e3),o=Math.floor(n/60),l=Math.floor(o/60),c=Math.floor(l/24),d=r>0;if(t)return c>365?Math.floor(c/365)+"y":c>30?Math.floor(c/30)+"mo":c>7?Math.floor(c/7)+"w":c>0?c+"d":l>0?l+"h":o>0?o+"m":"now";if(c>365){const u=Math.floor(c/365),p=d?"in ":"",m=d?"":" ago";return p+u+" year"+(u>1?"s":"")+m}if(c>30){const u=Math.floor(c/30),p=d?"in ":"",m=d?"":" ago";return p+u+" month"+(u>1?"s":"")+m}if(c>7){const u=Math.floor(c/7),p=d?"in ":"",m=d?"":" ago";return p+u+" week"+(u>1?"s":"")+m}if(c===1)return d?"tomorrow":"yesterday";if(c>0){const u=d?"in ":"",p=d?"":" ago";return u+c+" days"+p}if(l>0){const u=d?"in ":"",p=d?"":" ago";return u+l+" hour"+(l>1?"s":"")+p}if(o>0){const u=d?"in ":"",p=d?"":" ago";return u+o+" minute"+(o>1?"s":"")+p}if(n>30){const u=d?"in ":"",p=d?"":" ago";return u+n+" seconds"+p}return"just now"}iso(e,t=!1){if(!e)return"";e=this.normalizeEpoch(e);const s=e instanceof Date?e:new Date(e);return isNaN(s.getTime())?String(e):t?s.toISOString().split("T")[0]:s.toISOString()}number(e,t=2,s="en-US"){const i=parseFloat(e);return isNaN(i)?String(e):i.toLocaleString(s,{minimumFractionDigits:t,maximumFractionDigits:t})}currency(e,t="$",s=2){const i=parseInt(e);if(isNaN(i))return String(e);const r=Math.abs(i).toString(),a=i<0?"-":"";let n,o;r.length<=2?(n="0",o=r.padStart(2,"0")):(n=r.slice(0,-2),o=r.slice(-2)),n=n.replace(/\B(?=(\d{3})+(?!\d))/g,",");let l;if(s===0)parseInt(o)>=50&&(n=(parseInt(n.replace(/,/g,""))+1).toString().replace(/\B(?=(\d{3})+(?!\d))/g,",")),l=n;else if(s===2)l=`${n}.${o}`;else{const c=o.slice(0,s).padEnd(s,"0");l=`${n}.${c}`}return a+t+l}percent(e,t=0,s=!0){const i=parseFloat(e);if(isNaN(i))return String(e);const r=s?i*100:i;return this.number(r,t)+"%"}filesize(e,t=!1,s=1){const i=parseInt(e);if(isNaN(i))return String(e);const r=t?["B","KiB","MiB","GiB","TiB"]:["B","KB","MB","GB","TB"],a=t?1024:1e3;let n=i,o=0;for(;n>=a&&o<r.length-1;)n/=a,o++;const l=o===0?0:s;return`${n.toFixed(l)} ${r[o]}`}ordinal(e,t=!1){const s=parseInt(e);if(isNaN(s))return String(e);const i=s%10,r=s%100;let a="th";return i===1&&r!==11?a="st":i===2&&r!==12?a="nd":i===3&&r!==13&&(a="rd"),t?a:s+a}compact(e,t=1){const s=parseFloat(e);if(isNaN(s))return String(e);const i=Math.abs(s),r=s<0?"-":"";return i>=1e9?r+(i/1e9).toFixed(t)+"B":i>=1e6?r+(i/1e6).toFixed(t)+"M":i>=1e3?r+(i/1e3).toFixed(t)+"K":String(s)}add(e,t){const s=parseFloat(e),i=parseFloat(t);return isNaN(s)||isNaN(i)?e:s+i}subtract(e,t){const s=parseFloat(e),i=parseFloat(t);return isNaN(s)||isNaN(i)?e:s-i}multiply(e,t){const s=parseFloat(e),i=parseFloat(t);return isNaN(s)||isNaN(i)?e:s*i}divide(e,t){const s=parseFloat(e),i=parseFloat(t);return isNaN(s)||isNaN(i)||i===0?e:s/i}capitalize(e,t=!0){const s=String(e);return s?t?s.replace(/\b\w/g,i=>i.toUpperCase()):s.charAt(0).toUpperCase()+s.slice(1):""}replace(e,t,s="",i="g"){if(e==null)return"";const r=String(e);if(t==null||t==="")return r;if(t instanceof RegExp)return r.replace(t,String(s));const a=String(t),n=a.match(/^\/(.+)\/([a-z]*)$/i);if(n){const[,o,l]=n;try{return r.replace(new RegExp(o,l),String(s))}catch{}}return String(i).includes("g")?r.split(a).join(String(s)):r.replace(a,String(s))}truncate(e,t=50,s="..."){const i=String(e);return i.length<=t?i:i.substring(0,t)+s}truncate_front(e,t=8,s="..."){const i=String(e);return i.length<=t?i:`${s}${i.slice(-t)}`}truncate_middle(e,t=8,s="***"){const i=String(e);if(i.length<=t)return i;const r=Math.floor(t/2),a=i.substring(0,r),n=i.substring(i.length-r);return`${a}${s}${n}`}slug(e,t="-"){return String(e).toLowerCase().replace(/[^\w\s-]/g,"").replace(/\s+/g,t).replace(new RegExp(`${t}+`,"g"),t).replace(new RegExp(`^${t}|${t}$`,"g"),"")}initials(e,t=2){return String(e).split(/\s+/).filter(r=>r.length>0).slice(0,t).map(r=>r.charAt(0).toUpperCase()).join("")}mask(e,t="*",s=4){const i=String(e);if(i.length<=s)return i;const r=t.repeat(Math.max(0,i.length-s)),a=i.slice(-s);return r+a}email(e,t={}){const s=String(e).trim();if(!s)return"";if(t.link===!1)return s;const i=t.subject?`?subject=${encodeURIComponent(t.subject)}`:"",r=t.body?`&body=${encodeURIComponent(t.body)}`:"",a=t.class?` class="${t.class}"`:"";return`<a href="mailto:${s}${i}${r}"${a}>${s}</a>`}phone(e,t="US",s=!0){let i=String(e).replace(/\D/g,""),r=i;return t==="US"&&(i.length===10?r=`(${i.slice(0,3)}) ${i.slice(3,6)}-${i.slice(6)}`:i.length===11&&i[0]==="1"&&(r=`+1 (${i.slice(1,4)}) ${i.slice(4,7)}-${i.slice(7)}`)),s?`<a href="tel:${i}">${r}</a>`:r}url(e,t=null,s=!0){let i=String(e).trim();return i?(/^https?:\/\//.test(i)||(i="https://"+i),`<a href="${i}"${s?' target="_blank"':""}${s?' rel="noopener noreferrer"':""}>${t||i}</a>`):""}badge(e,t="auto"){if(Array.isArray(e))return e.map(a=>this.badge(a,t)).join(" ");const s=String(e);if(typeof t=="string"&&t.includes("=")){const a=Object.fromEntries(t.split(",").map(l=>l.split("=").map(c=>c.trim()))),n=a[s]||a[s.toLowerCase()]||this.inferBadgeType(s);return`<span class="badge ${n?`bg-${n}`:"bg-secondary"}">${s}</span>`}const i=t==="auto"?this.inferBadgeType(s):t;return`<span class="badge ${i?`bg-${i}`:"bg-secondary"}">${s}</span>`}badgeClass(e,t="auto"){const s=String(e),i=t==="auto"?this.inferBadgeType(s):t;return i?`bg-${i}`:"bg-secondary"}inferBadgeType(e){const t=e.toLowerCase();return["active","pass","success","complete","completed","approved","done","true","on","yes"].includes(t)?"success":["error","failed","fail","rejected","deleted","cancelled","false","off","no","declined"].includes(t)?"danger":["warning","pending","review","processing","uploading"].includes(t)?"warning":["info","new","draft"].includes(t)?"info":(["inactive","disabled","archived","suspended"].includes(t),"secondary")}status(e){return this._status(e)}status_icon(e){return this._status(e,{},{},!1,!0)}status_text(e){return this._status(e,{},{},!0,!1)}_status(e,t={},s={},i=!1,r=!1){const a=String(e).toLowerCase(),n={active:"bi bi-check-circle-fill",approved:"bi bi-check-circle-fill",declined:"bi bi-x-circle-fill",inactive:"bi bi-pause-circle-fill",pending:"bi bi-clock-fill",success:"bi bi-check-circle-fill",error:"bi bi-exclamation-triangle-fill",warning:"bi bi-exclamation-triangle-fill"},o={active:"success",approved:"success",declined:"danger",inactive:"secondary",pending:"warning",success:"success",error:"danger",warning:"warning"},l=t[a]||n[a]||"",c=s[a]||o[a]||"secondary";let d="";!i&&l&&(d=`<i class="${l}"></i>`);let u="";return r||(u=e),`<span class="text-${c}">${d}${d?" ":""}${u}</span>`}boolean(e,t="True",s="False",i=!1){const r=e?t:s;return i?`<span class="text-${e?"success":"danger"}">${r}</span>`:r}bool(e){return e==null||e===0||e===""||e===!1||e==="false"?!1:e===!0||e==="true"?!0:!(Array.isArray(e)&&e.length===0||e&&typeof e=="object"&&e.constructor===Object&&Object.keys(e).length===0)}icon(e,t={}){const s=String(e).toLowerCase(),i=t[s]||"";return i?`<i class="${i}"></i>`:""}yesnoicon(e,t="bi bi-check-circle-fill text-success",s="bi bi-x-circle-fill text-danger"){return e?`<i class="${t}"></i>`:`<i class="${s}"></i>`}image(e,t="thumbnail",s="img-fluid",i=""){const r=this._extractImageUrl(e,t);return r?`<img src="${r}" class="${s}" alt="${i}" />`:""}avatar(e,t="md",s="rounded-circle",i=""){const r=this._extractImageUrl(e,"square_sm")||Be,a={xs:"width: 1.5rem; height: 1.5rem;",sm:"width: 2rem; height: 2rem;",md:"width: 3rem; height: 3rem;",lg:"width: 4rem; height: 4rem;",xl:"width: 5rem; height: 5rem;"},n=a[t]||a.md,l=`object-fit-cover ${s}`.trim();return`<img src="${r}" class="${l}" style="${n}" alt="${i}" />`}tooltip(e,t="",s="top",i=""){if(e==null)return"";const r=String(e),a=i==="html"?t:this.escapeHtml(t);return`<span data-bs-toggle="tooltip" data-bs-placement="${s}" ${i==="html"?'data-bs-html="true"':""} data-bs-title="${a}">${r}</span>`}_extractImageUrl(e,t="thumbnail"){if(!e)return null;if(typeof e=="string")return e;if(typeof e=="object"){if(e.attributes&&(e=e.attributes),t==="thumbnail"&&e.thumbnail&&typeof e.thumbnail=="string")return e.thumbnail;if(e.renditions&&typeof e.renditions=="object"){const s=e.renditions[t];if(s&&s.url)return s.url;const i=Object.values(e.renditions);if(i.length>0&&i[0].url)return i[0].url}if(e.url)return e.url}return null}default(e,t=""){return e==null||e===""?t:e}equals(e,t,s,i=""){return e==t?s:i}plural(e,t,s=null,i=!0){if(e==null||t===null||t===void 0)return i?`${e} ${t}`:t||"";const r=parseInt(e);if(isNaN(r))return i?`${e} ${t}`:t||"";const a=Math.abs(r)===1?t:s||t+"s";return i?`${r} ${a}`:a}formatList(e,t={}){if(!Array.isArray(e))return String(e);const{conjunction:s="and",limit:i=null,moreText:r="others"}=t;if(e.length===0)return"";if(e.length===1)return String(e[0]);let a=e.slice(),n=!1;if(i&&e.length>i&&(a=e.slice(0,i),n=!0),n){const o=e.length-i;return`${a.join(", ")}, ${s} ${o} ${r}`}return a.length===2?`${a[0]} ${s} ${a[1]}`:`${a.slice(0,-1).join(", ")}, ${s} ${a[a.length-1]}`}duration(e,t="ms",s=!1,i=2){if(e==null)return"";const r=parseFloat(e);if(isNaN(r))return String(e);let a;switch(t){case"s":case"sec":case"seconds":a=r*1e3;break;case"m":case"min":case"minutes":a=r*6e4;break;case"h":case"hr":case"hours":a=r*36e5;break;case"d":case"day":case"days":a=r*864e5;break;default:a=r}const n=[{name:"day",short:"d",value:864e5},{name:"hour",short:"h",value:36e5},{name:"minute",short:"m",value:6e4},{name:"second",short:"s",value:1e3}];if(a===0)return s?"0s":"0 seconds";const o=Math.abs(a),l=a<0?"-":"",c=[];let d=o;for(const u of n)if(d>=u.value){const p=Math.floor(d/u.value);d=d%u.value;const m=s?u.short:p===1?u.name:u.name+"s";if(c.push(s?`${p}${m}`:`${p} ${m}`),c.length>=i)break}return c.length===0?s?`${Math.round(o)}ms`:`${Math.round(o)} milliseconds`:l+(s?c.join(""):c.join(" "))}hash(e,t=8,s="",i="..."){if(e==null)return"";const r=String(e);return r.length<=t?s+r:s+r.substring(0,t)+i}stripHtml(e){return e==null?"":String(e).replace(/<[^>]*>/g,"")}highlight(e,t,s="highlight"){if(e==null||!t)return String(e||"");const i=String(t).replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),r=new RegExp(`(${i})`,"gi");return String(e).replace(r,`<mark class="${s}">$1</mark>`)}hex(e,t=!1,s=!1){if(e==null)return"";let i="";const r=a=>Array.from(a).map(n=>n.toString(16).padStart(2,"0")).join("");if(typeof e=="number"){let a=Math.abs(Math.trunc(e)).toString(16);a.length%2&&(a="0"+a),i=a}else if(e instanceof Uint8Array)i=r(e);else if(e instanceof ArrayBuffer)i=r(new Uint8Array(e));else if(Array.isArray(e)&&e.every(a=>typeof a=="number"))i=r(Uint8Array.from(e.map(a=>a&255)));else{const n=new TextEncoder().encode(String(e));i=r(n)}return t&&(i=i.toUpperCase()),(s?"0x":"")+i}unhex(e){if(e==null)return"";let t=String(e).trim();if((t.startsWith("0x")||t.startsWith("0X"))&&(t=t.slice(2)),t=t.replace(/\s+/g,""),t.length===0)return"";t.length%2!==0&&(t="0"+t);const s=new Uint8Array(t.length/2);for(let i=0;i<t.length;i+=2){const r=parseInt(t.slice(i,i+2),16);if(Number.isNaN(r))return String(e);s[i/2]=r}try{return new TextDecoder().decode(s)}catch{let r="";for(const a of s)r+=String.fromCharCode(a);return r}}json(e,t=2){try{return JSON.stringify(e,null,t)}catch{return String(e)}}has(e){return this.formatters.has(e.toLowerCase())}unregister(e){return this.formatters.delete(e.toLowerCase())}listFormatters(){return Array.from(this.formatters.keys()).sort()}iter(e){return e==null?[]:Array.isArray(e)?e:typeof e=="object"?Object.entries(e).map(([t,s])=>({key:t,value:s})):[{key:"0",value:e}]}}const M=new Ue;window.dataFormatter=M;class ${static getContextData(e,t){if(!t||e==null)return;let s=t,i="",r=0,a=-1;for(let o=0;o<t.length;o++){const l=t[o];if(l==="(")r++;else if(l===")")r--;else if(l==="|"&&r===0){a=o;break}}a>-1&&(s=t.substring(0,a).trim(),i=t.substring(a+1).trim());const n=this.getNestedValue(e,s);return i?M.pipe(n,i,e):n}static getNestedValue(e,t){if(!t||e==null)return;if(!t.includes(".")){if(t in e){const r=e[t];return typeof r=="function"?r.call(e):r}return}const s=t.split(".");let i=e;for(let r=0;r<s.length;r++){const a=s[r];if(i==null)return;if(r===0)if(i.hasOwnProperty(a)){const n=i[a];typeof n=="function"?i=n.call(e):i=n}else return;else{if(i&&typeof i.getContextValue=="function"){const n=s.slice(r).join(".");return i.getContextValue(n)}if(Array.isArray(i)&&!isNaN(a))i=i[parseInt(a)];else if(i.hasOwnProperty(a))i=i[a];else if(typeof i[a]=="function")i=i[a].call(i);else return}}return i}static isNullOrUndefined(e){return e==null}static deepClone(e){if(e===null||typeof e!="object")return e;if(e instanceof Date)return new Date(e.getTime());if(e instanceof Array)return e.map(t=>this.deepClone(t));if(e instanceof Object){const t={};for(const s in e)e.hasOwnProperty(s)&&(t[s]=this.deepClone(e[s]));return t}}static deepMerge(e,...t){if(!t.length)return e;const s=t.shift();if(this.isObject(e)&&this.isObject(s))for(const i in s)this.isObject(s[i])?(e[i]||Object.assign(e,{[i]:{}}),this.deepMerge(e[i],s[i])):Object.assign(e,{[i]:s[i]});return this.deepMerge(e,...t)}static isObject(e){return e&&typeof e=="object"&&!Array.isArray(e)}static debounce(e,t){let s;return function(...r){const a=()=>{clearTimeout(s),e(...r)};clearTimeout(s),s=setTimeout(a,t)}}static throttle(e,t){let s;return function(...i){s||(e.apply(this,i),s=!0,setTimeout(()=>s=!1,t))}}static generateId(e=""){const t=Date.now().toString(36),s=Math.random().toString(36).substr(2,9);return e?`${e}_${t}_${s}`:`${t}_${s}`}static escapeHtml(e){const t={"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#39;","/":"&#x2F;","`":"&#x60;","=":"&#x3D;"};return String(e).replace(/[&<>"'`=\/]/g,s=>t[s])}static checkPasswordStrength(e){if(!e||typeof e!="string")return{score:0,strength:"invalid",feedback:["Password must be a non-empty string"],details:{length:0,hasLowercase:!1,hasUppercase:!1,hasNumbers:!1,hasSpecialChars:!1,hasCommonPatterns:!1,isCommonPassword:!1}};const t=[],s={length:e.length,hasLowercase:/[a-z]/.test(e),hasUppercase:/[A-Z]/.test(e),hasNumbers:/[0-9]/.test(e),hasSpecialChars:/[^a-zA-Z0-9]/.test(e),hasCommonPatterns:!1,isCommonPassword:!1};let i=0;e.length<6?t.push("Password should be at least 6 characters long"):e.length<8?(i+=1,t.push("Consider using at least 8 characters for better security")):e.length<12?i+=3:i+=4,s.hasLowercase?i+=1:t.push("Include lowercase letters"),s.hasUppercase?i+=1:t.push("Include uppercase letters"),s.hasNumbers?i+=1:t.push("Include numbers"),s.hasSpecialChars?i+=2:t.push("Include special characters (!@#$%^&* etc.)");const r=[/123/,/abc/i,/qwerty/i,/asdf/i,/(.)\1{2,}/,/password/i,/admin/i,/user/i,/login/i];for(const o of r)if(o.test(e)){s.hasCommonPatterns=!0,i-=1,t.push("Avoid common patterns and dictionary words");break}["123456","password","123456789","12345678","12345","1234567","1234567890","qwerty","abc123","111111","123123","admin","letmein","welcome","monkey","password123","123qwe","qwerty123","000000","dragon","sunshine","princess","azerty","1234","iloveyou","trustno1","superman","shadow","master","jennifer"].includes(e.toLowerCase())&&(s.isCommonPassword=!0,i=Math.max(0,i-3),t.push("This password is too common and easily guessed"));let n;return i<2?n="very-weak":i<4?n="weak":i<6?n="fair":i<8?n="good":n="strong",i>=7&&t.length===0?t.push("Strong password! Consider using a password manager."):i>=5&&t.length<=1&&t.push("Good password strength. Consider adding more variety."),{score:Math.max(0,i),strength:n,feedback:t,details:s}}static generatePassword(e={}){const s={...{length:12,includeLowercase:!0,includeUppercase:!0,includeNumbers:!0,includeSpecialChars:!0,customChars:"",excludeAmbiguous:!1},...e};if(s.length<4)throw new Error("Password length must be at least 4 characters");let i="abcdefghijklmnopqrstuvwxyz",r="ABCDEFGHIJKLMNOPQRSTUVWXYZ",a="0123456789",n="!@#$%^&*()_+-=[]{}|;:,.<>?";s.excludeAmbiguous&&(i=i.replace(/[il]/g,""),r=r.replace(/[IOL]/g,""),a=a.replace(/[01]/g,""),n=n.replace(/[|]/g,""));let o="";const l=[];if(s.customChars?o=s.customChars:(s.includeLowercase&&(o+=i,l.push(i[Math.floor(Math.random()*i.length)])),s.includeUppercase&&(o+=r,l.push(r[Math.floor(Math.random()*r.length)])),s.includeNumbers&&(o+=a,l.push(a[Math.floor(Math.random()*a.length)])),s.includeSpecialChars&&(o+=n,l.push(n[Math.floor(Math.random()*n.length)]))),!o)throw new Error("No character types selected for password generation");let c="";for(const d of l)c+=d;for(let d=c.length;d<s.length;d++)c+=o[Math.floor(Math.random()*o.length)];return c.split("").sort(()=>Math.random()-.5).join("")}static parseQueryString(e){const t={},s=new URLSearchParams(e);for(const[i,r]of s.entries())t[i]=r;return t}static toQueryString(e){return new URLSearchParams(e).toString()}static wrapData(e,t=null,s=3){return!e||typeof e!="object"||e instanceof Date||e instanceof RegExp||e instanceof Error||s<=0||typeof e.getContextValue=="function"?e:Array.isArray(e)?e.map(i=>i&&typeof i=="object"&&!i.getContextValue?new ce(i,t):i):new ce(e,t)}}class ce{constructor(e,t=null){if(Object.defineProperty(this,"_data",{value:e,writable:!1,enumerable:!1,configurable:!1}),Object.defineProperty(this,"_rootContext",{value:t,writable:!1,enumerable:!1,configurable:!1}),e&&typeof e=="object"){for(const s in e)if(e.hasOwnProperty(s)){const i=e[s];this[s]=$.wrapData(i,t)}}}getContextValue(e){let t=e,s="",i=0,r=-1;for(let n=0;n<e.length;n++){const o=e[n];if(o==="(")i++;else if(o===")")i--;else if(o==="|"&&i===0){r=n;break}}r>-1&&(t=e.substring(0,r).trim(),s=e.substring(r+1).trim());let a;return t in this&&t!=="_data"&&t!=="_rootContext"?a=this[t]:a=$.getNestedValue(this._data,t),s&&a!==void 0?M.pipe(a,s,this._rootContext||this._data):a}has(e){return this._data&&this._data.hasOwnProperty(e)}toJSON(){return this._data}}$.DataWrapper=ce,typeof window<"u"&&(window.utils=$);const Ye=Object.prototype.toString,J=Array.isArray||function(h){return Ye.call(h)==="[object Array]"},Q=function(h){return typeof h=="function"},Ie=function(h){return h!==null&&typeof h=="object"};function We(){return typeof window>"u"?null:window.MOJO?.dataFormatter?window.MOJO.dataFormatter:window.dataFormatter?window.dataFormatter:null}const ke=function(h){const e={"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#39;","/":"&#x2F;","`":"&#x60;","=":"&#x3D;"};return String(h).replace(/[&<>"'`=\/]/g,function(t){return e[t]})};class _e{constructor(e){this.string=e,this.tail=e,this.pos=0}eos(){return this.tail===""}scan(e){const t=this.tail.match(e);if(!t||t.index!==0)return"";const s=t[0];return this.tail=this.tail.substring(s.length),this.pos+=s.length,s}scanUntil(e){const t=this.tail.search(e);let s;switch(t){case-1:s=this.tail,this.tail="";break;case 0:s="";break;default:s=this.tail.substring(0,t),this.tail=this.tail.substring(t)}return this.pos+=s.length,s}}class ie{constructor(e,t){this.view=e,this.cache={".":this.view},this.parent=t,this.view?._cacheId||this.view&&typeof this.view=="object"&&(this.view._cacheId=Math.random().toString(36).substring(2))}push(e){return new ie(e,this)}lookup(e){if(this.renderCache&&this.view?._cacheId){const i=`${this.view._cacheId}:${e}`;if(this.renderCache.has(i))return this.renderCache.get(i)}if(e===".")return this.view;if(e&&e.startsWith(".")){let i=e.substring(1),r=!1,a=null;const n=i.indexOf("|");if(n!==-1&&(a=i.substring(n+1).trim(),i=i.substring(0,n).trim()),i.endsWith("|iter")&&(i=i.substring(0,i.length-5),r=!0),this.view&&typeof this.view=="object"){let o;if(typeof this.view.getContextValue=="function")try{o=this.view.getContextValue(i),o!==void 0&&Q(o)&&(o=o.call(this.view))}catch{o=void 0}if(o===void 0&&i in this.view&&(o=this.view[i],Q(o)&&(o=o.call(this.view))),a&&o!==void 0)try{const l=We();l&&typeof l.pipe=="function"&&(o=l.pipe(o,a,this))}catch{}return J(o)?r?o:o.length>0:Ie(o)?r?Object.entries(o).map(([l,c])=>({key:l,value:c})):Object.keys(o).length>0:o}return}const t=this.cache;let s;if(t.hasOwnProperty(e))s=t[e];else{let i=this,r,a,n,o=!1;for(;i;){if(i.view&&typeof i.view.getContextValue=="function")try{r=i.view.getContextValue(e),r!==void 0&&(o=!0)}catch{o=!1}if(!o)if(e.indexOf(".")>0)for(r=i.view,a=e.split("."),n=0;r!=null&&n<a.length;)if(r&&typeof r.getContextValue=="function"&&n<a.length)try{const l=a.slice(n).join(".");r=r.getContextValue(l),n=a.length,r!==void 0&&(o=!0)}catch{n===a.length-1&&(o=de(r,a[n])||Me(r,a[n])),r=r[a[n++]]}else n===a.length-1&&(o=de(r,a[n])||Me(r,a[n])),r=r[a[n++]];else r=i.view[e],o=de(i.view,e);if(o){s=r;break}i=i.parent}t[e]=s}if(Q(s)&&(s=s.call(this.view)),this.renderCache&&this.view?._cacheId){const i=`${this.view._cacheId}:${e}`;this.renderCache.set(i,s)}return s}}function de(h,e){return h!=null&&typeof h=="object"&&e in h}function Me(h,e){return h!=null&&typeof h!="object"&&h.hasOwnProperty&&h.hasOwnProperty(e)}class Ve{constructor(){this.templateCache=new Map}clearCache(){this.templateCache.clear()}parse(e,t){t=t||["{{","}}"];const s=e+":"+t.join(":");let i=this.templateCache.get(s);return i==null&&(i=this.parseTemplate(e,t),this.templateCache.set(s,i)),i}parseTemplate(e,t){if(!e)return[];const s=t[0],i=t[1],r=new _e(e),a=[];let n,o,l,c,d;const u=new RegExp(he(s)+"\\s*"),p=new RegExp("\\s*"+he(i)),m=new RegExp("\\s*"+he("}"+i));for(;!r.eos();){if(n=r.pos,l=r.scanUntil(u),l)for(let f=0;f<l.length;++f)c=l.charAt(f),c===`
15
- `?a.push(["text",c]):a.push(["text",c]);if(!r.scan(u))break;if(o=r.scan(/[#^\/>{&=!]/),o||(o="name"),r.scan(/\s*/),o==="="?(l=r.scanUntil(/\s*=/),r.scan(/\s*=/),r.scanUntil(p)):o==="{"?(l=r.scanUntil(m),r.scan(m),o="&"):l=r.scanUntil(p),r.scan(p),o==="#"||o==="^")d=[o,l,n,r.pos],a.push(d);else if(o==="/"){let f;for(let g=a.length-1;g>=0;--g)if((a[g][0]==="#"||a[g][0]==="^")&&a[g][1]===l){f=a[g];break}f&&f.length===4&&f.push(r.pos),a.push([o,l,n,r.pos])}else a.push([o,l,n,r.pos])}return this.nestSections(this.squashTokens(a))}squashTokens(e){const t=[];let s,i;for(let r=0;r<e.length;++r)s=e[r],s&&(s[0]==="text"&&i&&i[0]==="text"?(i[1]+=s[1],i[3]=s[3]):(t.push(s),i=s));return t}nestSections(e){const t=[];let s=t;const i=[];for(let r=0;r<e.length;++r){const a=e[r];switch(a[0]){case"#":case"^":const n=[a[0],a[1],a[2],a[3],[],a[4]||null];s.push(n),i.push(n),s=n[4];break;case"/":const o=i.pop();o&&(o[5]=a[2],s=i.length>0?i[i.length-1][4]:t);break;default:s.push(a)}}return t}render(e,t,s,i){const r=this.getConfigTags(i)||["{{","}}"],a=this.parse(e,r),n=new Map;return this.renderTokens(a,new ie(t),s,e,i,n)}renderTokens(e,t,s,i,r,a){a&&!t.renderCache&&(t.renderCache=a);let n="";for(let o=0;o<e.length;++o){const l=e[o];let c;switch(l[0]){case"#":if(c=t.lookup(l[1]),!c)continue;const d=l[4];if(!d||!J(d)){console.warn(`MUSTACHE WARNING - Section ${l[1]} has no child tokens:`,l);continue}if(J(c))for(let u=0;u<c.length;++u){const p=t.push(c[u]);t.renderCache&&(p.renderCache=t.renderCache);const m=this.renderTokens(d,p,s,i,r,a);n+=m}else if(typeof c=="object"||typeof c=="string"||typeof c=="number"){const u=t.push(c);t.renderCache&&(u.renderCache=t.renderCache),n+=this.renderTokens(d,u,s,i,r,a)}else if(Q(c)){const u=i==null?null:i.slice(l[3],l[5]);c=c.call(t.view,u,p=>this.render(p,t.view,s,r)),c!=null&&(n+=c)}else c&&(n+=this.renderTokens(d,t,s,i,r,a));break;case"^":if(c=t.lookup(l[1]),!c||J(c)&&c.length===0){const u=l[4];u&&J(u)&&(n+=this.renderTokens(u,t,s,i,r,a))}break;case">":if(!s)continue;c=Q(s)?s(l[1]):s[l[1]],c!=null&&(n+=this.render(c,t.view,s,r));break;case"&":c=t.lookup(l[1]),c!=null&&(n+=c);break;case"name":c=t.lookup(l[1]),c!=null&&(n+=ke(c));break;case"text":n+=l[1];break}}return n}getConfigTags(e){return Ie(e)&&J(e.tags)?e.tags:null}}function he(h){return h.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g,"\\$&")}const ue=new Ve,T={name:"MOJO Mustache",version:"1.0.0",tags:["{{","}}"],Scanner:_e,Context:ie,Writer:Ve,escape:ke,clearCache(){return ue.clearCache()},parse(h,e){return ue.parse(h,e)},render(h,e,t,s){if(typeof h!="string")throw new TypeError('Invalid template! Template should be a "string"');return e&&typeof e=="object"&&!e.getContextValue&&typeof e.toJSON!="function"&&(e=$.wrapData(e)),ue.render(h,e,t,s)}};class Je{constructor(e){this.view=e,this.domListeners=[],this.debounceTimers=new Map}bind(e){if(this.unbind(),!e)return;const t=async n=>{const o=n.target.closest("[data-action]");if(o&&this.shouldHandle(o,n)){const c=o.getAttribute("data-action");if(o.tagName==="A"&&n.preventDefault(),this.hideTooltip(o),await this.dispatch(c,n,o)){n.preventDefault(),n.stopPropagation(),n.handledByChild=!0;return}}const l=n.target.closest("a[href], [data-page]");if(l&&!l.hasAttribute("data-action")&&this.shouldHandle(l,n)){if(n.ctrlKey||n.metaKey||n.shiftKey||n.button===1)return;if(l.tagName==="A"){const c=l.getAttribute("href");if(c&&c!=="#"&&!c.startsWith("#")&&(this.view.isExternalLink(c)||l.hasAttribute("data-external")))return}this.hideTooltip(l),n.preventDefault(),n.stopPropagation(),n.handledByChild=!0,l.hasAttribute("data-page")?await this.view.handlePageNavigation(l):await this.view.handleHrefNavigation(l)}},s=n=>{const o=n.target.closest("[data-change-action]");if(o&&this.shouldHandle(o,n)){const c=o.getAttribute("data-change-action");this.dispatchChange(c,n,o).then(d=>{d&&(n.stopPropagation(),n.handledByChild=!0)});return}const l=n.target.closest("[data-action]");if(l&&this.isFormControl(l)&&this.shouldHandle(l,n)){const c=l.getAttribute("data-action");this.dispatch(c,n,l).then(d=>{d&&(n.stopPropagation(),n.handledByChild=!0)})}},i=n=>{const o=n.target.closest("[data-change-action]");if(o&&this.shouldHandle(o,n)&&n.target.matches('[data-filter="live-search"]')){const p=o.getAttribute("data-change-action"),m=parseInt(o.getAttribute("data-filter-debounce"))||300,f=`change-${p}-${o.getAttribute("data-container")||"default"}`;this.debounceTimers.has(f)&&clearTimeout(this.debounceTimers.get(f));const g=setTimeout(()=>{this.debounceTimers.delete(f),this.dispatchChange(p,n,o).then(w=>{w&&(n.stopPropagation(),n.handledByChild=!0)})},m);this.debounceTimers.set(f,g);return}const l=n.target.closest("[data-action]");if(!l||!this.isFormControl(l)||l.hasAttribute("data-change-action")||!this.shouldHandle(l,n))return;const c=l.getAttribute("data-action"),d=l.getAttribute("data-action-debounce"),u=d!=null&&parseInt(d)||0;if(u>0){const p=`action-${c}-${l.getAttribute("data-container")||"default"}`;this.debounceTimers.has(p)&&clearTimeout(this.debounceTimers.get(p));const m=setTimeout(()=>{this.debounceTimers.delete(p),this.dispatch(c,n,l).then(f=>{f&&(n.stopPropagation(),n.handledByChild=!0)})},u);this.debounceTimers.set(p,m);return}this.dispatch(c,n,l).then(p=>{p&&(n.stopPropagation(),n.handledByChild=!0)})},r=n=>{if(n.target.matches('[data-filter="search"]'))return;const o=n.target.closest("[data-keydown-action]")||n.target.closest("[data-change-action]");if(!o||!this.shouldHandle(o,n))return;let l=["Enter"];if(o.getAttribute("data-change-keys")&&(l=o.getAttribute("data-change-keys").split(",").map(c=>c.trim())),l.includes("*")||l.includes(n.key)){const c=o.getAttribute("data-keydown-action")||o.getAttribute("data-change-action");this.dispatch(c,n,o).then(d=>{d&&(n.preventDefault(),n.stopPropagation(),n.handledByChild=!0)})}},a=n=>{const o=n.target.closest("form[data-action]");if(!o||!this.shouldHandle(o,n))return;n.preventDefault();const l=o.getAttribute("data-action");this.dispatch(l,n,o)};e.addEventListener("click",t),e.addEventListener("change",s),e.addEventListener("input",i),e.addEventListener("keydown",r),e.addEventListener("submit",a),this.domListeners.push({el:e,type:"click",fn:t},{el:e,type:"change",fn:s},{el:e,type:"input",fn:i},{el:e,type:"keydown",fn:r},{el:e,type:"submit",fn:a})}unbind(){for(const{el:e,type:t,fn:s}of this.domListeners)e.removeEventListener(t,s);this.domListeners=[];for(const e of this.debounceTimers.values())clearTimeout(e);this.debounceTimers.clear()}hideDropdown(e){const s=e.closest(".dropdown-menu").closest(".dropdown");if(!s)return;const i=s.querySelector('[data-bs-toggle="dropdown"]');i&&window.bootstrap?.Dropdown&&window.bootstrap.Dropdown.getInstance(i)?.hide()}hideTooltip(e){if(e&&window.bootstrap?.Tooltip){const t=window.bootstrap.Tooltip.getInstance(e);t&&t.dispose()}}hideAllTooltips(){window.bootstrap?.Tooltip&&document.querySelectorAll('[data-bs-toggle="tooltip"]').forEach(t=>{const s=window.bootstrap.Tooltip.getInstance(t);s&&s.hide()})}async dispatch(e,t,s){const i=this.view,r=l=>l.includes("-")?l.split("-").map(c=>c[0].toUpperCase()+c.slice(1)).join(""):l[0].toUpperCase()+l.slice(1),a=`handleAction${r(e)}`;if(typeof i[a]=="function")try{return t.preventDefault(),await i[a](t,s),!0}catch(l){return console.error(`Error in action ${e}:`,l),i.handleActionError(e,l,t,s),!0}const n=`onAction${r(e)}`;if(typeof i[n]=="function")try{return await i[n](t,s)?(s.closest(".dropdown-menu")&&this.hideDropdown(s),t.preventDefault(),t.stopPropagation(),!0):!1}catch(l){return console.error(`Error in action ${e}:`,l),i.handleActionError(e,l,t,s),!0}const o=`onPassThruAction${r(e)}`;if(typeof i[o]=="function")try{return await i[o](t,s),!1}catch(l){return console.error(`Error in action ${e}:`,l),i.handleActionError(e,l,t,s),!0}if(typeof i.onActionDefault=="function")try{return await i.onActionDefault(e,t,s)}catch(l){return console.error(`Error in default action handler for ${e}:`,l),i.handleActionError(e,l,t,s),!0}return i.emit?.(`action:${e}`,{action:e,event:t,element:s}),!1}async dispatchChange(e,t,s){const i=this.view,a=`onChange${(n=>n.includes("-")?n.split("-").map(o=>o[0].toUpperCase()+o.slice(1)).join(""):n[0].toUpperCase()+n.slice(1))(e)}`;if(typeof i[a]=="function")try{return await i[a](t,s),!0}catch(n){return console.error(`Error in onChange ${e}:`,n),i.handleActionError?.(e,n,t,s),!0}return await this.dispatch(e,t,s)}isFormControl(e){if(!e||!e.tagName)return!1;const t=e.tagName;return t==="INPUT"||t==="TEXTAREA"||t==="SELECT"}shouldHandle(e,t){return!!(this.owns(e)||this.contains(e)&&!t.handledByChild)}owns(e){const t=this.view.element;if(!t||!t.contains(e))return!1;for(const s of Object.values(this.view.children))if(s.element&&s.element.contains(e))return!1;return!0}contains(e){return!!this.view.element&&this.view.element.contains(e)}}const pe={on(h,e,t){this._listeners||(this._listeners={}),this._listeners[h]||(this._listeners[h]=[]);const s={callback:e,context:t,fn:t?e.bind(t):e};return this._listeners[h].push(s),this},off(h,e,t){return!this._listeners||!this._listeners[h]?this:(e?(this._listeners[h]=this._listeners[h].filter(s=>s.callback!==e||arguments.length===3&&s.context!==t),this._listeners[h].length===0&&delete this._listeners[h]):delete this._listeners[h],this)},once(h,e,t){const s=(...i)=>{this.off(h,s),(t?e.bind(t):e).apply(t||this,i)};return this.on(h,s),this},emit(h,...e){if(!this._listeners||!this._listeners[h])return this;const t=this._listeners[h].slice();for(const s of t)try{s.fn.apply(s.context||this,e)}catch(i){console&&console.error&&console.error(`Error in ${h} event handler:`,i)}return this}};typeof window<"u"&&(window.Mustache=T);class C{constructor(e={}){this.tagName=e.tagName??"div",this.className=e.className??"mojo-view",this.style=e.style??null,this.id=e.id??C._genId(),this.containerId=e.containerId??null,this.container=e.container??null,typeof this.container=="string"&&(this.containerId=this.container,this.container=null),this.parent=e.parent??null,this.children=e.children??{},this.template=e.template||e.templateUrl||"",this.data=e.data??{},this.isRendering=!1,this.lastRenderTime=0,this.mounted=!1,this.debug=e.debug??!1,this.app=e.app??null,this.cacheTemplate=e.cacheTemplate??!0,this.enableTooltips=e.enableTooltips??!1,this.options={...e},this.element=this._ensureElement(),this.events=new Je(this),e.model&&this.setModel(e.model)}async onInit(){}async onInitView(){this.initialized||(this.initialized=!0,await this.onInit())}async onBeforeRender(){}async onAfterRender(){}async onBeforeMount(){}async onAfterMount(){}async onBeforeUnmount(){}async onAfterUnmount(){}async onBeforeDestroy(){}async onAfterDestroy(){}setModel(e={}){let t=e!==this.model;if(!t)return this;this.model&&this.model.off&&this.model.off("change",this._onModelChange,this),this.model=e,this.model&&this.model.on&&this.model.on("change",this._onModelChange,this);for(const s in this.children){const i=this.children[s];i&&typeof i.setModel=="function"&&i.setModel(e)}return t&&this._onModelChange(),this}_onModelChange(){this.isMounted()&&this.render()}setTemplate(e){return this.template=e??"",this}addChild(e,t){try{if(!e||typeof e!="object")return this;t&&((t.containerId||t.container)&&(e.containerId=t.containerId||t.container),t.id&&(e.id=t.id),t.lazyMount===!0&&(e._lazyMount=!0)),e.parent=this,this.getApp()&&(e.app=this.app),this.children[e.id]=e}catch(s){C._warn("addChild error",s)}return e}removeChild(e){try{const t=typeof e=="string"?e:e&&e.id;if(!t)return this;const s=this.children[t];s&&(Promise.resolve(s.destroy()).catch(i=>C._warn("removeChild destroy error",i)),delete this.children[t])}catch(t){C._warn("removeChild error",t)}return this}getChild(e){return this.children[e]}async updateData(e,t=!1){return Object.assign(this.data,e),t&&this.isMounted()&&await this.render(),this}toggleClass(e,t){return t===void 0&&(t=!this.element.classList.contains(e)),this.element.classList.toggle(e,t),this}addClass(e){return this.element.classList.add(e),this}setClass(e){return this.element.className=e,this}removeClass(e){return this.element.classList.remove(e),this}canRender(){if(this.isRendering)return!1;const e=Date.now();if(this.options.renderCooldown>0&&e-this.lastRenderTime<this.options.renderCooldown)return C._warn(`View ${this.id}: Render called too quickly, cooldown active`),!1;if(this.options.noAppend&&this.parent)if(this.parent.contains(this.containerId||this.container)){if(this.containerId&&!document.getElementById(this.containerId))return!1;if(this.container&&!document.contains(this.container))return!1}else return!1;return!0}async render(e=!0,t=null){const s=Date.now();if(!this.canRender())return this;this.isRendering=!0,this.lastRenderTime=s;try{this.initialized||await this.onInitView(),this.unbindEvents(),await this.onBeforeRender(),this.getViewData&&(this.data=await this.getViewData());const i=await this.renderTemplate();this.element.innerHTML=i,e&&!this.isMounted()&&await this.mount(t),await this._renderChildren(),await this.onAfterRender(),this.bindEvents()}catch(i){C._warn(`Render error in ${this.id}`,i)}finally{this.isRendering=!1}return this}async _renderChildren(){const e=[];for(const t in this.children){const s=this.children[t];if(s){if(s.parent=this,s._lazyMount&&!s._lazyTriggered){e.push(s);continue}await Promise.resolve(s.render()).catch(i=>C._warn(`Child render error (${t})`,i))}}e.length&&this._setupLazyMountObserver(e)}_setupLazyMountObserver(e){if(typeof IntersectionObserver>"u"){e.forEach(t=>{t._lazyTriggered=!0,Promise.resolve(t.render()).catch(s=>C._warn(`Lazy child render error (${t.id})`,s))});return}this._lazyObserver||(this._lazyObserver=new IntersectionObserver((t,s)=>{for(const i of t){if(!i.isIntersecting)continue;const r=i.target.__mojoLazyChild;s.unobserve(i.target),!(!r||r._lazyTriggered)&&(r._lazyTriggered=!0,Promise.resolve(r.render()).catch(a=>C._warn(`Lazy child render error (${r.id})`,a)))}},{rootMargin:"120px 0px",threshold:.01}));for(const t of e){const s=this.getChildElement(t.containerId);s&&(s.__mojoLazyChild=t,s.style.minHeight||(s.classList.add("mojo-lazy-placeholder"),s.style.minHeight="1px"),this._lazyObserver.observe(s),requestAnimationFrame(()=>{if(t._lazyTriggered)return;const i=s.getBoundingClientRect(),r=typeof window<"u"?window.innerHeight:0,a=typeof window<"u"?window.innerWidth:0;i.top<r+120&&i.bottom>-120&&i.left<a&&i.right>0&&(t._lazyTriggered=!0,this._lazyObserver?.unobserve(s),Promise.resolve(t.render()).catch(o=>C._warn(`Lazy child render error (${t.id})`,o)))}))}}async _unmountChildren(){for(const e in this.children){const t=this.children[e];t&&t.unbindEvents()}}isMounted(){return this.element?.isConnected}getChildElementById(e,t=null){const s=e.startsWith("#")?e.substring(1):e;return t?t.querySelector(`#${s}`):this.element.querySelector(`#${s}`)}getChildElement(e){if(e.startsWith("#"))return this.getChildElementById(e);let t=this.element?.querySelector(`[data-container="${e}"]`);return t||this.getChildElementById(e)}getContainer(){return this.replaceById?this.parent?this.parent.getChildElementById(this.id):null:this.containerId?this.parent?this.parent.getChildElement(this.containerId):this.getChildElementById(this.containerId,document.body):null}async mount(e=null){if(await this.onBeforeMount(),e||(e=this.getContainer()),this.containerId&&!e){console.error(`Container not found for ${this.containerId}`);return}e&&this.replaceById?e.replaceWith(this.element):e?e.replaceChildren(this.element):!this.containerId&&this.parent?this.parent.element.appendChild(this.element):!this.containerId&&!this.parent&&this.options.allowAppendToBody?(console.log("APPENDING TO BODY!!!!"),document.body.appendChild(this.element)):console.error(`Container not found for ${this.containerId}`),await this.onAfterMount(),this.mounted=!0}async unmount(){!this.element||!this.element.parentNode||(await this.onBeforeUnmount(),await this._unmountChildren(),this.element.parentNode&&this.element.parentNode.removeChild(this.element),this.events.unbind(),await this.onAfterUnmount(),this.mounted=!1)}async destroy(){try{this.events.unbind(),this._lazyObserver&&(this._lazyObserver.disconnect(),this._lazyObserver=null);for(const e in this.children){const t=this.children[e];t&&await Promise.resolve(t.destroy()).catch(s=>C._warn(`Child destroy error (${e})`,s))}this.mounted=!1,this.element&&this.element.parentNode&&(await this.onBeforeDestroy(),this.element.parentNode&&this.element.parentNode.removeChild(this.element),await this.onAfterDestroy())}catch(e){C._warn(`Destroy error in ${this.id}`,e)}}_ensureElement(){try{if(this.element&&this.element.tagName?.toLowerCase()===this.tagName)return this._syncAttrs(),this.element;const e=document.createElement(this.tagName);return this.element=e,this.el=e,this._syncAttrs(),e}catch(e){C._warn("ensureElement error",e);const t=document.createElement("div");return t.id=this.id||C._genId(),t}}_syncAttrs(){try{if(!this.element)return;this.id&&(this.element.id=this.id),this.element.className=this.className||"",this.style==null?this.element.removeAttribute("style"):this.element.style.cssText=String(this.style)}catch(e){C._warn("_syncAttrs error",e)}}bindEvents(){this.events.bind(this.element),this.enableTooltips&&this.initializeTooltips()}unbindEvents(){this.events.unbind(),this.enableTooltips&&this.disposeTooltips()}async renderTemplate(){const e=await this.getTemplate();if(!e)return"";const t=this.getPartials();return T.render(e,this,t)}renderTemplateString(e,t,s){return T.render(e,t,s)}getPartials(){return{}}async getTemplate(){if(this._templateCache&&this.cacheTemplate)return this._templateCache;const e=this.template||this.templateUrl;if(!e)throw new Error("Template not found");let t="";if(typeof e=="string")if(e.includes("<")||e.includes("{"))t=e;else try{let s=e;this.app||(this.app=this.getApp()),this.app&&this.app.basePath&&!s.startsWith("/")&&!s.startsWith("http://")&&!s.startsWith("https://")&&(s=`${this.app.basePath.endsWith("/")?this.app.basePath.slice(0,-1):this.app.basePath}/${s}`);const i=await fetch(s);if(!i.ok)throw new Error(`HTTP ${i.status}: ${i.statusText}`);t=await i.text()}catch(s){C._warn(`Failed to load template from ${e}: ${s}`),this.showError?.(`Failed to load template from ${e}: ${s.message}`)}else typeof e=="function"&&(t=await this.template(this.data,this.state));return this.cacheTemplate&&t&&(this._templateCache=t),t}getContextValue(e){const t=$.getContextData(this,e);return e&&e.startsWith("data.")&&t&&typeof t=="object"?$.wrapData(t,this):e&&e.startsWith("model.")&&e!=="model"&&t&&typeof t=="object"&&typeof t.getContextValue!="function"?$.wrapData(t,null):t}async handlePageNavigation(e){const t=e.getAttribute("data-page"),s=e.getAttribute("data-params");let i={};if(s)try{i=JSON.parse(s)}catch{console.warn("Invalid JSON in data-params:",s)}const r=this.getApp();if(r){r.showPage(t,i);return}const a=this.findRouter();a&&typeof a.navigateToPage=="function"?await a.navigateToPage(t,i):console.error(`No router found for page navigation to '${t}'`)}async handleHrefNavigation(e){const t=e.getAttribute("href");if(this.isExternalLink(t)||e.hasAttribute("data-external"))return;const s=this.findRouter();if(s){if(s.options&&s.options.mode==="param"&&t.startsWith("?")){const r="/"+t;await s.navigate(r);return}if(s.options&&s.options.mode==="hash"&&t.startsWith("#")){await s.navigate(t);return}const i=this.hrefToRoutePath(t);await s.navigate(i)}else console.warn("No router found for navigation, using default behavior"),window.location.href=t}isExternalLink(e){return e?e.startsWith("/")&&this.getApp()?!e.startsWith(this.findRouter().basePath):e.startsWith("#")||e.startsWith("mailto:")||e.startsWith("tel:")||e.startsWith("http://")||e.startsWith("https://")||e.startsWith("//"):!0}hrefToRoutePath(e){if(e.startsWith("/")){const t=this.findRouter();if(t&&t.options&&t.options.base){const s=t.options.base;if(e.startsWith(s))return e.substring(s.length)||"/"}return e}return e.startsWith("./")?e.substring(2):e}findRouter(){return this.getApp(),this.app?.router||null}getApp(){if(this.app)return this.app;const e=[window.__app__,window.MOJO?.app,window.APP,window.app,window.WebApp,window.matchUUID?window[window.matchUUID]():window[window.matchUUID]];return this.app=e.find(t=>t&&typeof t.showPage=="function")||null,this.app}handleActionError(e,t,s,i){this.showError(`Action '${e}' failed: ${t}`,s,i)}escapeHtml(e){if(typeof e!="string")return e;const t=document.createElement("div");return t.textContent=e,t.innerHTML}contains(e){if(typeof e=="string"){if(!this.element)return!1;e=document.getElementById(e)}return e?this.element.contains(e):!1}initializeTooltips(){if(!this.element||!window.bootstrap?.Tooltip)return;this.disposeTooltips(),[...this.element.querySelectorAll('[data-bs-toggle="tooltip"]')].map(t=>{const s=t.getAttribute("data-tooltip-theme"),i=t.getAttribute("data-tooltip-size");let r="";s&&(r+=`tooltip-${s} `),i&&(r+=`tooltip-${i}`);const a={},n=r.trim();return n&&(a.customClass=n),new window.bootstrap.Tooltip(t,a)})}disposeTooltips(){if(!this.element||!window.bootstrap?.Tooltip)return;this.element.querySelectorAll('[data-bs-toggle="tooltip"]').forEach(t=>{const s=window.bootstrap.Tooltip.getInstance(t);s&&s.dispose()})}async showError(e){console.error(`View ${this.id} error:`,e);const t=this.getApp?this.getApp():this.app||null;if(t&&typeof t.showError=="function"){await t.showError(e);return}alert(`Error: ${e}`)}async showSuccess(e){this.debug&&console.log(`View ${this.id} success:`,e);const t=this.getApp?this.getApp():this.app||null;if(t&&typeof t.showSuccess=="function"){await t.showSuccess(e);return}alert(`Success: ${e}`)}async showInfo(e){console.info(`View ${this.id} info:`,e);const t=this.getApp?this.getApp():this.app||null;if(t&&typeof t.showInfo=="function"){await t.showInfo(e);return}alert(`Info: ${e}`)}async showWarning(e){console.warn(`View ${this.id} warning:`,e);const t=this.getApp?this.getApp():this.app||null;if(t&&typeof t.showWarning=="function"){await t.showWarning(e);return}alert(`Warning: ${e}`)}async onActionCopyToClipboard(e,t){try{const i=(t?.closest("[data-clipboard]")||t)?.getAttribute("data-clipboard")||"";if(!i)return!0;if(navigator.clipboard&&window.isSecureContext)await navigator.clipboard.writeText(i);else{const n=document.createElement("textarea");n.value=i,document.body.appendChild(n),n.select(),document.execCommand("copy"),document.body.removeChild(n)}const r=t.querySelector("i"),a=r&&r.className;return r&&(r.className="bi bi-check",setTimeout(()=>{r.className=a},1e3)),!0}catch(s){return console.warn("Copy to clipboard failed:",s),!0}}static _genId(){return`view_${Math.random().toString(36).substr(2,9)}`}static _warn(e,t){try{t?console.warn(`[View] ${e}:`,t):console.warn(`[View] ${e}`)}catch{}}}Object.assign(C.prototype,pe);class S extends C{static _openDialogs=[];static _baseZIndex={backdrop:1050,modal:1055};static getFullscreenAwareZIndex(){return document.querySelector(".table-fullscreen")?{backdrop:10040,modal:10050}:S._baseZIndex}static fixAllBackdropStacking(){const e=document.querySelectorAll(".modal-backdrop"),t=S._openDialogs;if(e.length===0||t.length===0)return;const s=[...t].sort((a,n)=>(a._dialogZIndex||0)-(n._dialogZIndex||0)),r=document.querySelector(".table-fullscreen")||document.body;e.forEach((a,n)=>{if(n>=s.length)return;const o=s[n];a.style.zIndex=o._dialogZIndex-5,a.parentNode!==r&&r.appendChild(a)})}static updateAllBackdropStacking(){S.fixAllBackdropStacking()}static getMountTarget(){return document.querySelector(".table-fullscreen")||document.body}constructor(e={}){const t=e.id||`modal-${Date.now()}-${Math.random().toString(36).slice(2,7)}`;e.header===!1||e.header,e.headerContent!==void 0&&e.headerContent,super({...e,id:t,tagName:"div",className:`modal ${e.fade!==!1?"fade":""} ${e.className||""}`.trim().replace(/\s+/g," "),attributes:{tabindex:"-1","aria-hidden":"true","aria-labelledby":e.labelledBy||`${t}-label`,"aria-describedby":e.describedBy||null,...e.attributes}}),this.modalId=t,this.title=e.title||"",this.titleId=`${this.modalId}-label`,this.size=e.size||"",this.centered=e.centered!==void 0?e.centered:!1,this.scrollable=e.scrollable!==void 0?e.scrollable:!1,this.autoSize=e.autoSize||e.size==="auto",this.backdrop=e.backdrop!==void 0?e.backdrop:!0,this.keyboard=e.keyboard!==void 0?e.keyboard:!0,this.focus=e.focus!==void 0?e.focus:!0,this.header=e.header!==void 0?e.header:!0,this.headerContent=e.headerContent||null,this.headerView=null,this.closeButton=e.closeButton!==void 0?e.closeButton:!0,this.contextMenu=e.contextMenu||null,this._processHeaderContent(this.headerContent),this.body=e.body??e.view??e.message??e.content??"",this.bodyView=null,this.bodyClass=e.bodyClass||"",this.noBodyPadding=e.noBodyPadding||!1,this.minWidth=e.minWidth||300,this.minHeight=e.minHeight||200,e.maxHeight&&(this.maxHeight=e.maxHeight),this.maxWidthPercent=e.maxWidthPercent||.9,this.maxHeightPercent=e.maxHeightPercent||.8,this._processBodyContent(this.body),this.footer=e.footer||null,this.footerView=null,this.footerClass=e.footerClass||"",this._processFooterContent(this.footer),this.buttons=e.buttons||null,this.onShow=e.onShow||null,this.onShown=e.onShown||null,this.onHide=e.onHide||null,this.onHidden=e.onHidden||null,this.onHidePrevented=e.onHidePrevented||null,this.autoShow=e.autoShow!==void 0?e.autoShow:!1,this.modal=null,this.relatedTarget=e.relatedTarget||null}_processBodyContent(e){if(e instanceof C||e&&typeof e=="object"&&typeof e.render=="function")this.bodyView=e,this.body="",this.addChild(this.bodyView);else if(typeof e=="function")try{const t=e();t instanceof C?(this.bodyView=t,this.body="",this.addChild(this.bodyView)):t instanceof Promise?(this.bodyPromise=t,this.body='<div class="text-center"><div class="spinner-border spinner-border-sm"></div></div>'):this.body=t}catch(t){console.error("ModalView: error processing body function:",t),this.body=e}else this.body=e}_processHeaderContent(e){if(e instanceof C)this.headerView=e,this.headerContent=null,this.addChild(this.headerView);else if(typeof e=="function")try{const t=e();t instanceof C?(this.headerView=t,this.headerContent=null,this.addChild(this.headerView)):t instanceof Promise?(this.headerPromise=t,this.headerContent='<div class="text-center"><div class="spinner-border spinner-border-sm"></div></div>'):this.headerContent=t}catch(t){console.error("ModalView: error processing headerContent function:",t),this.headerContent=e}else this.headerContent=e}_processFooterContent(e){if(e instanceof C)this.footerView=e,this.footer=null,this.addChild(this.footerView);else if(typeof e=="function")try{const t=e();t instanceof C?(this.footerView=t,this.footer=null,this.addChild(this.footerView)):t instanceof Promise?(this.footerPromise=t,this.footer='<div class="text-center"><div class="spinner-border spinner-border-sm"></div></div>'):this.footer=t}catch(t){console.error("ModalView: error processing footer function:",t),this.footer=e}else this.footer=e}async getTemplate(){const e=["modal-dialog"];return this.size&&this.size!=="auto"&&(this.size.startsWith("fullscreen")?e.push(`modal-${this.size}`):["sm","lg","xl","xxl"].includes(this.size)&&(e.push(`modal-${this.size}`),["lg","xl","xxl"].includes(this.size)&&e.push("modal-fullscreen-sm-down"))),this.centered&&e.push("modal-dialog-centered"),this.scrollable&&(this.maxHeight?e.push("overflow-hidden"):e.push("modal-dialog-scrollable")),`
15
+ `?a.push(["text",c]):a.push(["text",c]);if(!r.scan(u))break;if(o=r.scan(/[#^\/>{&=!]/),o||(o="name"),r.scan(/\s*/),o==="="?(l=r.scanUntil(/\s*=/),r.scan(/\s*=/),r.scanUntil(p)):o==="{"?(l=r.scanUntil(m),r.scan(m),o="&"):l=r.scanUntil(p),r.scan(p),o==="#"||o==="^")d=[o,l,n,r.pos],a.push(d);else if(o==="/"){let f;for(let g=a.length-1;g>=0;--g)if((a[g][0]==="#"||a[g][0]==="^")&&a[g][1]===l){f=a[g];break}f&&f.length===4&&f.push(r.pos),a.push([o,l,n,r.pos])}else a.push([o,l,n,r.pos])}return this.nestSections(this.squashTokens(a))}squashTokens(e){const t=[];let s,i;for(let r=0;r<e.length;++r)s=e[r],s&&(s[0]==="text"&&i&&i[0]==="text"?(i[1]+=s[1],i[3]=s[3]):(t.push(s),i=s));return t}nestSections(e){const t=[];let s=t;const i=[];for(let r=0;r<e.length;++r){const a=e[r];switch(a[0]){case"#":case"^":const n=[a[0],a[1],a[2],a[3],[],a[4]||null];s.push(n),i.push(n),s=n[4];break;case"/":const o=i.pop();o&&(o[5]=a[2],s=i.length>0?i[i.length-1][4]:t);break;default:s.push(a)}}return t}render(e,t,s,i){const r=this.getConfigTags(i)||["{{","}}"],a=this.parse(e,r),n=new Map;return this.renderTokens(a,new ie(t),s,e,i,n)}renderTokens(e,t,s,i,r,a){a&&!t.renderCache&&(t.renderCache=a);let n="";for(let o=0;o<e.length;++o){const l=e[o];let c;switch(l[0]){case"#":if(c=t.lookup(l[1]),!c)continue;const d=l[4];if(!d||!J(d)){console.warn(`MUSTACHE WARNING - Section ${l[1]} has no child tokens:`,l);continue}if(J(c))for(let u=0;u<c.length;++u){const p=t.push(c[u]);t.renderCache&&(p.renderCache=t.renderCache);const m=this.renderTokens(d,p,s,i,r,a);n+=m}else if(typeof c=="object"||typeof c=="string"||typeof c=="number"){const u=t.push(c);t.renderCache&&(u.renderCache=t.renderCache),n+=this.renderTokens(d,u,s,i,r,a)}else if(Q(c)){const u=i==null?null:i.slice(l[3],l[5]);c=c.call(t.view,u,p=>this.render(p,t.view,s,r)),c!=null&&(n+=c)}else c&&(n+=this.renderTokens(d,t,s,i,r,a));break;case"^":if(c=t.lookup(l[1]),!c||J(c)&&c.length===0){const u=l[4];u&&J(u)&&(n+=this.renderTokens(u,t,s,i,r,a))}break;case">":if(!s)continue;c=Q(s)?s(l[1]):s[l[1]],c!=null&&(n+=this.render(c,t.view,s,r));break;case"&":c=t.lookup(l[1]),c!=null&&(n+=c);break;case"name":c=t.lookup(l[1]),c!=null&&(n+=ke(c));break;case"text":n+=l[1];break}}return n}getConfigTags(e){return Ie(e)&&J(e.tags)?e.tags:null}}function he(h){return h.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g,"\\$&")}const ue=new Ve,T={name:"MOJO Mustache",version:"1.0.0",tags:["{{","}}"],Scanner:_e,Context:ie,Writer:Ve,escape:ke,clearCache(){return ue.clearCache()},parse(h,e){return ue.parse(h,e)},render(h,e,t,s){if(typeof h!="string")throw new TypeError('Invalid template! Template should be a "string"');return e&&typeof e=="object"&&!e.getContextValue&&typeof e.toJSON!="function"&&(e=$.wrapData(e)),ue.render(h,e,t,s)}};class Je{constructor(e){this.view=e,this.domListeners=[],this.debounceTimers=new Map}bind(e){if(this.unbind(),!e)return;const t=async n=>{const o=n.target.closest("[data-action]");if(o&&this.shouldHandle(o,n)){const c=o.getAttribute("data-action");if(o.tagName==="A"&&n.preventDefault(),this.hideTooltip(o),await this.dispatch(c,n,o)){n.preventDefault(),n.stopPropagation(),n.handledByChild=!0;return}}const l=n.target.closest("a[href], [data-page]");if(l&&!l.hasAttribute("data-action")&&this.shouldHandle(l,n)){if(n.ctrlKey||n.metaKey||n.shiftKey||n.button===1)return;if(l.tagName==="A"){const c=l.getAttribute("href");if(c&&c!=="#"&&!c.startsWith("#")&&(this.view.isExternalLink(c)||l.hasAttribute("data-external")))return}this.hideTooltip(l),n.preventDefault(),n.stopPropagation(),n.handledByChild=!0,l.hasAttribute("data-page")?await this.view.handlePageNavigation(l):await this.view.handleHrefNavigation(l)}},s=n=>{const o=n.target.closest("[data-change-action]");if(o&&this.shouldHandle(o,n)){const c=o.getAttribute("data-change-action");this.dispatchChange(c,n,o).then(d=>{d&&(n.stopPropagation(),n.handledByChild=!0)});return}const l=n.target.closest("[data-action]");if(l&&this.isFormControl(l)&&this.shouldHandle(l,n)){const c=l.getAttribute("data-action");this.dispatch(c,n,l).then(d=>{d&&(n.stopPropagation(),n.handledByChild=!0)})}},i=n=>{const o=n.target.closest("[data-change-action]");if(o&&this.shouldHandle(o,n)&&n.target.matches('[data-filter="live-search"]')){const p=o.getAttribute("data-change-action"),m=parseInt(o.getAttribute("data-filter-debounce"))||300,f=`change-${p}-${o.getAttribute("data-container")||"default"}`;this.debounceTimers.has(f)&&clearTimeout(this.debounceTimers.get(f));const g=setTimeout(()=>{this.debounceTimers.delete(f),this.dispatchChange(p,n,o).then(w=>{w&&(n.stopPropagation(),n.handledByChild=!0)})},m);this.debounceTimers.set(f,g);return}const l=n.target.closest("[data-action]");if(!l||!this.isFormControl(l)||l.hasAttribute("data-change-action")||!this.shouldHandle(l,n))return;const c=l.getAttribute("data-action"),d=l.getAttribute("data-action-debounce"),u=d!=null&&parseInt(d)||0;if(u>0){const p=`action-${c}-${l.getAttribute("data-container")||"default"}`;this.debounceTimers.has(p)&&clearTimeout(this.debounceTimers.get(p));const m=setTimeout(()=>{this.debounceTimers.delete(p),this.dispatch(c,n,l).then(f=>{f&&(n.stopPropagation(),n.handledByChild=!0)})},u);this.debounceTimers.set(p,m);return}this.dispatch(c,n,l).then(p=>{p&&(n.stopPropagation(),n.handledByChild=!0)})},r=n=>{if(n.target.matches('[data-filter="search"]'))return;const o=n.target.closest("[data-keydown-action]")||n.target.closest("[data-change-action]");if(!o||!this.shouldHandle(o,n))return;let l=["Enter"];if(o.getAttribute("data-change-keys")&&(l=o.getAttribute("data-change-keys").split(",").map(c=>c.trim())),l.includes("*")||l.includes(n.key)){const c=o.getAttribute("data-keydown-action")||o.getAttribute("data-change-action");this.dispatch(c,n,o).then(d=>{d&&(n.preventDefault(),n.stopPropagation(),n.handledByChild=!0)})}},a=n=>{const o=n.target.closest("form[data-action]");if(!o||!this.shouldHandle(o,n))return;n.preventDefault();const l=o.getAttribute("data-action");this.dispatch(l,n,o)};e.addEventListener("click",t),e.addEventListener("change",s),e.addEventListener("input",i),e.addEventListener("keydown",r),e.addEventListener("submit",a),this.domListeners.push({el:e,type:"click",fn:t},{el:e,type:"change",fn:s},{el:e,type:"input",fn:i},{el:e,type:"keydown",fn:r},{el:e,type:"submit",fn:a})}unbind(){for(const{el:e,type:t,fn:s}of this.domListeners)e.removeEventListener(t,s);this.domListeners=[];for(const e of this.debounceTimers.values())clearTimeout(e);this.debounceTimers.clear()}hideDropdown(e){const s=e.closest(".dropdown-menu").closest(".dropdown");if(!s)return;const i=s.querySelector('[data-bs-toggle="dropdown"]');i&&window.bootstrap?.Dropdown&&window.bootstrap.Dropdown.getInstance(i)?.hide()}hideTooltip(e){if(e&&window.bootstrap?.Tooltip){const t=window.bootstrap.Tooltip.getInstance(e);t&&t.dispose()}}hideAllTooltips(){window.bootstrap?.Tooltip&&document.querySelectorAll('[data-bs-toggle="tooltip"]').forEach(t=>{const s=window.bootstrap.Tooltip.getInstance(t);s&&s.hide()})}async dispatch(e,t,s){const i=this.view,r=l=>l.includes("-")?l.split("-").map(c=>c[0].toUpperCase()+c.slice(1)).join(""):l[0].toUpperCase()+l.slice(1),a=`handleAction${r(e)}`;if(typeof i[a]=="function")try{return t.preventDefault(),await i[a](t,s),!0}catch(l){return console.error(`Error in action ${e}:`,l),i.handleActionError(e,l,t,s),!0}const n=`onAction${r(e)}`;if(typeof i[n]=="function")try{return await i[n](t,s)?(s.closest(".dropdown-menu")&&this.hideDropdown(s),t.preventDefault(),t.stopPropagation(),!0):!1}catch(l){return console.error(`Error in action ${e}:`,l),i.handleActionError(e,l,t,s),!0}const o=`onPassThruAction${r(e)}`;if(typeof i[o]=="function")try{return await i[o](t,s),!1}catch(l){return console.error(`Error in action ${e}:`,l),i.handleActionError(e,l,t,s),!0}if(typeof i.onActionDefault=="function")try{return await i.onActionDefault(e,t,s)}catch(l){return console.error(`Error in default action handler for ${e}:`,l),i.handleActionError(e,l,t,s),!0}return i.emit?.(`action:${e}`,{action:e,event:t,element:s}),!1}async dispatchChange(e,t,s){const i=this.view,a=`onChange${(n=>n.includes("-")?n.split("-").map(o=>o[0].toUpperCase()+o.slice(1)).join(""):n[0].toUpperCase()+n.slice(1))(e)}`;if(typeof i[a]=="function")try{return await i[a](t,s),!0}catch(n){return console.error(`Error in onChange ${e}:`,n),i.handleActionError?.(e,n,t,s),!0}return await this.dispatch(e,t,s)}isFormControl(e){if(!e||!e.tagName)return!1;const t=e.tagName;return t==="INPUT"||t==="TEXTAREA"||t==="SELECT"}shouldHandle(e,t){return!!(this.owns(e)||this.contains(e)&&!t.handledByChild)}owns(e){const t=this.view.element;if(!t||!t.contains(e))return!1;for(const s of Object.values(this.view.children))if(s.element&&s.element.contains(e))return!1;return!0}contains(e){return!!this.view.element&&this.view.element.contains(e)}}const pe={on(h,e,t){this._listeners||(this._listeners={}),this._listeners[h]||(this._listeners[h]=[]);const s={callback:e,context:t,fn:t?e.bind(t):e};return this._listeners[h].push(s),this},off(h,e,t){return!this._listeners||!this._listeners[h]?this:(e?(this._listeners[h]=this._listeners[h].filter(s=>s.callback!==e||arguments.length===3&&s.context!==t),this._listeners[h].length===0&&delete this._listeners[h]):delete this._listeners[h],this)},once(h,e,t){const s=(...i)=>{this.off(h,s),(t?e.bind(t):e).apply(t||this,i)};return this.on(h,s),this},emit(h,...e){if(!this._listeners||!this._listeners[h])return this;const t=this._listeners[h].slice();for(const s of t)try{s.fn.apply(s.context||this,e)}catch(i){console&&console.error&&console.error(`Error in ${h} event handler:`,i)}return this}};typeof window<"u"&&(window.Mustache=T);class C{constructor(e={}){this.tagName=e.tagName??"div",this.className=e.className??"mojo-view",this.style=e.style??null,this.id=e.id??C._genId(),this.containerId=e.containerId??null,this.container=e.container??null,typeof this.container=="string"&&(this.containerId=this.container,this.container=null),this.parent=e.parent??null,this.children=e.children??{},this.template=e.template||e.templateUrl||"",this.data=e.data??{},this.isRendering=!1,this.lastRenderTime=0,this.mounted=!1,this.debug=e.debug??!1,this.app=e.app??null,this.cacheTemplate=e.cacheTemplate??!0,this.enableTooltips=e.enableTooltips??!1,this.options={...e},this.element=this._ensureElement(),this.events=new Je(this),e.model&&this.setModel(e.model)}async onInit(){}async onInitView(){this.initialized||(this.initialized=!0,await this.onInit())}async onBeforeRender(){}async onAfterRender(){}async onBeforeMount(){}async onAfterMount(){}async onBeforeUnmount(){}async onAfterUnmount(){}async onBeforeDestroy(){}async onAfterDestroy(){}setModel(e={}){let t=e!==this.model;if(!t)return this;this.model&&this.model.off&&this.model.off("change",this._onModelChange,this),this.model=e,this.model&&this.model.on&&this.model.on("change",this._onModelChange,this);for(const s in this.children){const i=this.children[s];i&&typeof i.setModel=="function"&&i.setModel(e)}return t&&this._onModelChange(),this}_onModelChange(){this.isMounted()&&this.render()}setTemplate(e){return this.template=e??"",this}addChild(e,t){try{if(!e||typeof e!="object")return this;t&&((t.containerId||t.container)&&(e.containerId=t.containerId||t.container),t.id&&(e.id=t.id),t.lazyMount===!0&&(e._lazyMount=!0)),e.parent=this,this.getApp()&&(e.app=this.app),this.children[e.id]=e}catch(s){C._warn("addChild error",s)}return e}removeChild(e){try{const t=typeof e=="string"?e:e&&e.id;if(!t)return this;const s=this.children[t];s&&(Promise.resolve(s.destroy()).catch(i=>C._warn("removeChild destroy error",i)),delete this.children[t])}catch(t){C._warn("removeChild error",t)}return this}getChild(e){return this.children[e]}async updateData(e,t=!1){return Object.assign(this.data,e),t&&this.isMounted()&&await this.render(),this}toggleClass(e,t){return t===void 0&&(t=!this.element.classList.contains(e)),this.element.classList.toggle(e,t),this}addClass(e){return this.element.classList.add(e),this}setClass(e){return this.element.className=e,this}removeClass(e){return this.element.classList.remove(e),this}canRender(){if(this.isRendering)return!1;const e=Date.now();if(this.options.renderCooldown>0&&e-this.lastRenderTime<this.options.renderCooldown)return C._warn(`View ${this.id}: Render called too quickly, cooldown active`),!1;if(this.options.noAppend&&this.parent)if(this.parent.contains(this.containerId||this.container)){if(this.containerId&&!document.getElementById(this.containerId))return!1;if(this.container&&!document.contains(this.container))return!1}else return!1;return!0}async render(e=!0,t=null){const s=Date.now();if(!this.canRender())return this;this.isRendering=!0,this.lastRenderTime=s;try{this.initialized||await this.onInitView(),this.unbindEvents(),await this.onBeforeRender(),this.getViewData&&(this.data=await this.getViewData());const i=await this.renderTemplate();this.element.innerHTML=i,e&&!this.isMounted()&&await this.mount(t),await this._renderChildren(),await this.onAfterRender(),this.bindEvents()}catch(i){C._warn(`Render error in ${this.id}`,i)}finally{this.isRendering=!1}return this}async _renderChildren(){const e=[];for(const t in this.children){const s=this.children[t];if(s){if(s.parent=this,s._lazyMount&&!s._lazyTriggered){e.push(s);continue}await Promise.resolve(s.render()).catch(i=>C._warn(`Child render error (${t})`,i))}}e.length&&this._setupLazyMountObserver(e)}_setupLazyMountObserver(e){if(typeof IntersectionObserver>"u"){e.forEach(t=>{t._lazyTriggered=!0,Promise.resolve(t.render()).catch(s=>C._warn(`Lazy child render error (${t.id})`,s))});return}this._lazyObserver||(this._lazyObserver=new IntersectionObserver((t,s)=>{for(const i of t){if(!i.isIntersecting)continue;const r=i.target.__mojoLazyChild;s.unobserve(i.target),!(!r||r._lazyTriggered)&&(r._lazyTriggered=!0,Promise.resolve(r.render()).catch(a=>C._warn(`Lazy child render error (${r.id})`,a)))}},{rootMargin:"120px 0px",threshold:.01}));for(const t of e){const s=this.getChildElement(t.containerId);s&&(s.__mojoLazyChild=t,s.style.minHeight||(s.classList.add("mojo-lazy-placeholder"),s.style.minHeight="1px"),this._lazyObserver.observe(s),requestAnimationFrame(()=>{if(t._lazyTriggered)return;const i=s.getBoundingClientRect(),r=typeof window<"u"?window.innerHeight:0,a=typeof window<"u"?window.innerWidth:0;i.top<r+120&&i.bottom>-120&&i.left<a&&i.right>0&&(t._lazyTriggered=!0,this._lazyObserver?.unobserve(s),Promise.resolve(t.render()).catch(o=>C._warn(`Lazy child render error (${t.id})`,o)))}))}}async _unmountChildren(){for(const e in this.children){const t=this.children[e];t&&t.unbindEvents()}}isMounted(){return this.element?.isConnected}getChildElementById(e,t=null){const s=e.startsWith("#")?e.substring(1):e;return t?t.querySelector(`#${s}`):this.element.querySelector(`#${s}`)}getChildElement(e){if(e.startsWith("#"))return this.getChildElementById(e);let t=this.element?.querySelector(`[data-container="${e}"]`);return t||this.getChildElementById(e)}getContainer(){return this.replaceById?this.parent?this.parent.getChildElementById(this.id):null:this.containerId?this.parent?this.parent.getChildElement(this.containerId):this.getChildElementById(this.containerId,document.body):null}async mount(e=null){if(await this.onBeforeMount(),e||(e=this.getContainer()),this.containerId&&!e){console.error(`Container not found for ${this.containerId}`);return}e&&this.replaceById?e.replaceWith(this.element):e?e.replaceChildren(this.element):!this.containerId&&this.parent?this.parent.element.appendChild(this.element):!this.containerId&&!this.parent&&this.options.allowAppendToBody?(console.log("APPENDING TO BODY!!!!"),document.body.appendChild(this.element)):console.error(`Container not found for ${this.containerId}`),await this.onAfterMount(),this.mounted=!0}async unmount(){!this.element||!this.element.parentNode||(await this.onBeforeUnmount(),await this._unmountChildren(),this.element.parentNode&&this.element.parentNode.removeChild(this.element),this.events.unbind(),await this.onAfterUnmount(),this.mounted=!1)}async destroy(){try{this.events.unbind(),this._lazyObserver&&(this._lazyObserver.disconnect(),this._lazyObserver=null);for(const e in this.children){const t=this.children[e];t&&await Promise.resolve(t.destroy()).catch(s=>C._warn(`Child destroy error (${e})`,s))}this.mounted=!1,this.element&&this.element.parentNode&&(await this.onBeforeDestroy(),this.element.parentNode&&this.element.parentNode.removeChild(this.element),await this.onAfterDestroy())}catch(e){C._warn(`Destroy error in ${this.id}`,e)}}_ensureElement(){try{if(this.element&&this.element.tagName?.toLowerCase()===this.tagName)return this._syncAttrs(),this.element;const e=document.createElement(this.tagName);return this.element=e,this.el=e,this._syncAttrs(),e}catch(e){C._warn("ensureElement error",e);const t=document.createElement("div");return t.id=this.id||C._genId(),t}}_syncAttrs(){try{if(!this.element)return;this.id&&(this.element.id=this.id),this.element.className=this.className||"",this.style==null?this.element.removeAttribute("style"):this.element.style.cssText=String(this.style)}catch(e){C._warn("_syncAttrs error",e)}}bindEvents(){this.events.bind(this.element),this.enableTooltips&&this.initializeTooltips()}unbindEvents(){this.events.unbind(),this.enableTooltips&&this.disposeTooltips()}async renderTemplate(){const e=await this.getTemplate();if(!e)return"";const t=this.getPartials();return T.render(e,this,t)}renderTemplateString(e,t,s){return T.render(e,t,s)}getPartials(){return{}}async getTemplate(){if(this._templateCache&&this.cacheTemplate)return this._templateCache;const e=this.template||this.templateUrl;if(!e)throw new Error("Template not found");let t="";if(typeof e=="string")if(e.includes("<")||e.includes("{"))t=e;else try{let s=e;this.app||(this.app=this.getApp()),this.app&&this.app.basePath&&!s.startsWith("/")&&!s.startsWith("http://")&&!s.startsWith("https://")&&(s=`${this.app.basePath.endsWith("/")?this.app.basePath.slice(0,-1):this.app.basePath}/${s}`);const i=await fetch(s);if(!i.ok)throw new Error(`HTTP ${i.status}: ${i.statusText}`);t=await i.text()}catch(s){C._warn(`Failed to load template from ${e}: ${s}`),this.showError?.(`Failed to load template from ${e}: ${s.message}`)}else typeof e=="function"&&(t=await this.template(this.data,this.state));return this.cacheTemplate&&t&&(this._templateCache=t),t}getContextValue(e){const t=$.getContextData(this,e);return e&&e.startsWith("data.")&&t&&typeof t=="object"?$.wrapData(t,this):e&&e.startsWith("model.")&&e!=="model"&&t&&typeof t=="object"&&typeof t.getContextValue!="function"?$.wrapData(t,null):t}async handlePageNavigation(e){const t=e.getAttribute("data-page"),s=e.getAttribute("data-params");let i={};if(s)try{i=JSON.parse(s)}catch{console.warn("Invalid JSON in data-params:",s)}const r=this.getApp();if(r){r.showPage(t,i);return}const a=this.findRouter();a&&typeof a.navigateToPage=="function"?await a.navigateToPage(t,i):console.error(`No router found for page navigation to '${t}'`)}async handleHrefNavigation(e){const t=e.getAttribute("href");if(this.isExternalLink(t)||e.hasAttribute("data-external"))return;const s=this.findRouter();if(s){if(s.options&&s.options.mode==="param"&&t.startsWith("?")){const r="/"+t;await s.navigate(r);return}if(s.options&&s.options.mode==="hash"&&t.startsWith("#")){await s.navigate(t);return}const i=this.hrefToRoutePath(t);await s.navigate(i)}else console.warn("No router found for navigation, using default behavior"),window.location.href=t}isExternalLink(e){return e?e.startsWith("/")&&this.getApp()?!e.startsWith(this.findRouter().basePath):e.startsWith("#")||e.startsWith("mailto:")||e.startsWith("tel:")||e.startsWith("http://")||e.startsWith("https://")||e.startsWith("//"):!0}hrefToRoutePath(e){if(e.startsWith("/")){const t=this.findRouter();if(t&&t.options&&t.options.base){const s=t.options.base;if(e.startsWith(s))return e.substring(s.length)||"/"}return e}return e.startsWith("./")?e.substring(2):e}findRouter(){return this.getApp(),this.app?.router||null}getApp(){if(this.app)return this.app;const e=[window.__app__,window.MOJO?.app,window.APP,window.app,window.WebApp,window.matchUUID?window[window.matchUUID]():window[window.matchUUID]];return this.app=e.find(t=>t&&typeof t.showPage=="function")||null,this.app}handleActionError(e,t,s,i){this.showError(`Action '${e}' failed: ${t}`,s,i)}escapeHtml(e){if(typeof e!="string")return e;const t=document.createElement("div");return t.textContent=e,t.innerHTML}contains(e){if(typeof e=="string"){if(!this.element)return!1;e=document.getElementById(e)}return e?this.element.contains(e):!1}initializeTooltips(){if(!this.element||!window.bootstrap?.Tooltip)return;this.disposeTooltips(),[...this.element.querySelectorAll('[data-bs-toggle="tooltip"]')].map(t=>{const s=t.getAttribute("data-tooltip-theme"),i=t.getAttribute("data-tooltip-size");let r="";s&&(r+=`tooltip-${s} `),i&&(r+=`tooltip-${i}`);const a={},n=r.trim();return n&&(a.customClass=n),new window.bootstrap.Tooltip(t,a)})}disposeTooltips(){if(!this.element||!window.bootstrap?.Tooltip)return;this.element.querySelectorAll('[data-bs-toggle="tooltip"]').forEach(t=>{const s=window.bootstrap.Tooltip.getInstance(t);s&&s.dispose()})}async showError(e){console.error(`View ${this.id} error:`,e);const t=this.getApp?this.getApp():this.app||null;if(t&&typeof t.showError=="function"){await t.showError(e);return}alert(`Error: ${e}`)}async showSuccess(e){this.debug&&console.log(`View ${this.id} success:`,e);const t=this.getApp?this.getApp():this.app||null;if(t&&typeof t.showSuccess=="function"){await t.showSuccess(e);return}alert(`Success: ${e}`)}async showInfo(e){console.info(`View ${this.id} info:`,e);const t=this.getApp?this.getApp():this.app||null;if(t&&typeof t.showInfo=="function"){await t.showInfo(e);return}alert(`Info: ${e}`)}async showWarning(e){console.warn(`View ${this.id} warning:`,e);const t=this.getApp?this.getApp():this.app||null;if(t&&typeof t.showWarning=="function"){await t.showWarning(e);return}alert(`Warning: ${e}`)}async onActionCopyToClipboard(e,t){try{const i=(t?.closest("[data-clipboard]")||t)?.getAttribute("data-clipboard")||"";if(!i)return!0;if(navigator.clipboard&&window.isSecureContext)await navigator.clipboard.writeText(i);else{const n=document.createElement("textarea");n.value=i,document.body.appendChild(n),n.select(),document.execCommand("copy"),document.body.removeChild(n)}const r=t.querySelector("i"),a=r&&r.className;return r&&(r.className="bi bi-check",setTimeout(()=>{r.className=a},1e3)),!0}catch(s){return console.warn("Copy to clipboard failed:",s),!0}}static _genId(){return`view_${Math.random().toString(36).substr(2,9)}`}static _warn(e,t){try{t?console.warn(`[View] ${e}:`,t):console.warn(`[View] ${e}`)}catch{}}}Object.assign(C.prototype,pe);class S extends C{static _openDialogs=[];static _baseZIndex={backdrop:1050,modal:1055};static getFullscreenAwareZIndex(){return document.querySelector(".table-fullscreen")?{backdrop:10040,modal:10050}:S._baseZIndex}static fixAllBackdropStacking(){const e=document.querySelectorAll(".modal-backdrop"),t=S._openDialogs;if(e.length===0||t.length===0)return;const s=[...t].sort((a,n)=>(a._dialogZIndex||0)-(n._dialogZIndex||0)),r=document.querySelector(".table-fullscreen")||document.body;e.forEach((a,n)=>{if(n>=s.length)return;const o=s[n];a.style.zIndex=o._dialogZIndex-5,a.parentNode!==r&&r.appendChild(a)})}static updateAllBackdropStacking(){S.fixAllBackdropStacking()}static getMountTarget(){return document.querySelector(".table-fullscreen")||document.body}constructor(e={}){const t=e.id||`modal-${Date.now()}-${Math.random().toString(36).slice(2,7)}`;e.header===!1||e.header,e.headerContent!==void 0&&e.headerContent;let s=e.style,i="";if(e.eyebrow===!1||e.eyebrow===null)i="modal-bandless";else if(e.eyebrow){const a=`--mojo-eyebrow: '${String(e.eyebrow).replace(/['"\\]/g,"")}'`;s=[s,a].filter(Boolean).join("; ")}super({...e,id:t,tagName:"div",className:`modal ${e.fade!==!1?"fade":""} ${i} ${e.className||""}`.trim().replace(/\s+/g," "),style:s,attributes:{tabindex:"-1","aria-hidden":"true","aria-labelledby":e.labelledBy||`${t}-label`,"aria-describedby":e.describedBy||null,...e.attributes}}),this.modalId=t,this.title=e.title||"",this.titleId=`${this.modalId}-label`,this.size=e.size||"",this.centered=e.centered!==void 0?e.centered:!1,this.scrollable=e.scrollable!==void 0?e.scrollable:!1,this.autoSize=e.autoSize||e.size==="auto",this.backdrop=e.backdrop!==void 0?e.backdrop:!0,this.keyboard=e.keyboard!==void 0?e.keyboard:!0,this.focus=e.focus!==void 0?e.focus:!0,this.header=e.header!==void 0?e.header:!0,this.headerContent=e.headerContent||null,this.headerView=null,this.closeButton=e.closeButton!==void 0?e.closeButton:!0,this.contextMenu=e.contextMenu||null,this._processHeaderContent(this.headerContent),this.body=e.body??e.view??e.message??e.content??"",this.bodyView=null,this.bodyClass=e.bodyClass||"",this.noBodyPadding=e.noBodyPadding||!1,this.minWidth=e.minWidth||300,this.minHeight=e.minHeight||200,e.maxHeight&&(this.maxHeight=e.maxHeight),this.maxWidthPercent=e.maxWidthPercent||.9,this.maxHeightPercent=e.maxHeightPercent||.8,this._processBodyContent(this.body),this.footer=e.footer||null,this.footerView=null,this.footerClass=e.footerClass||"",this._processFooterContent(this.footer),this.buttons=e.buttons||null,this.onShow=e.onShow||null,this.onShown=e.onShown||null,this.onHide=e.onHide||null,this.onHidden=e.onHidden||null,this.onHidePrevented=e.onHidePrevented||null,this.autoShow=e.autoShow!==void 0?e.autoShow:!1,this.modal=null,this.relatedTarget=e.relatedTarget||null}_processBodyContent(e){if(e instanceof C||e&&typeof e=="object"&&typeof e.render=="function")this.bodyView=e,this.body="",this.addChild(this.bodyView);else if(typeof e=="function")try{const t=e();t instanceof C?(this.bodyView=t,this.body="",this.addChild(this.bodyView)):t instanceof Promise?(this.bodyPromise=t,this.body='<div class="text-center"><div class="spinner-border spinner-border-sm"></div></div>'):this.body=t}catch(t){console.error("ModalView: error processing body function:",t),this.body=e}else this.body=e}_processHeaderContent(e){if(e instanceof C)this.headerView=e,this.headerContent=null,this.addChild(this.headerView);else if(typeof e=="function")try{const t=e();t instanceof C?(this.headerView=t,this.headerContent=null,this.addChild(this.headerView)):t instanceof Promise?(this.headerPromise=t,this.headerContent='<div class="text-center"><div class="spinner-border spinner-border-sm"></div></div>'):this.headerContent=t}catch(t){console.error("ModalView: error processing headerContent function:",t),this.headerContent=e}else this.headerContent=e}_processFooterContent(e){if(e instanceof C)this.footerView=e,this.footer=null,this.addChild(this.footerView);else if(typeof e=="function")try{const t=e();t instanceof C?(this.footerView=t,this.footer=null,this.addChild(this.footerView)):t instanceof Promise?(this.footerPromise=t,this.footer='<div class="text-center"><div class="spinner-border spinner-border-sm"></div></div>'):this.footer=t}catch(t){console.error("ModalView: error processing footer function:",t),this.footer=e}else this.footer=e}async getTemplate(){const e=["modal-dialog"];return this.size&&this.size!=="auto"&&(this.size.startsWith("fullscreen")?e.push(`modal-${this.size}`):["sm","lg","xl","xxl"].includes(this.size)&&(e.push(`modal-${this.size}`),["lg","xl","xxl"].includes(this.size)&&e.push("modal-fullscreen-sm-down"))),this.centered&&e.push("modal-dialog-centered"),this.scrollable&&(this.maxHeight?e.push("overflow-hidden"):e.push("modal-dialog-scrollable")),`
16
16
  <div class="${e.join(" ")}">
17
17
  <div class="modal-content">
18
18
  ${await this.buildHeader()}
@@ -36,9 +36,9 @@ var MOJO=(function(A){"use strict";class le{constructor(e={}){this.defaultRoute=
36
36
  ${i}
37
37
  </ul>
38
38
  </div>
39
- `}async filterContextMenuItems(){if(!this.contextMenu||!this.contextMenu.items)return[];const e=[];for(const t of this.contextMenu.items){if(t.type==="divider"){e.push(t);continue}if(t.permissions)try{const s=this.getApp?.();let i=s?.activeUser||s?.getState?.("activeUser")||null;if(!i&&typeof window<"u"&&window.getApp)try{i=window.getApp()?.activeUser}catch{}if(i?.hasPermission){if(!i.hasPermission(t.permissions))continue}else continue}catch(s){console.warn("ModalView: error checking permissions for context menu item:",s);continue}e.push(t)}return e}async buildBody(){return this.bodyView?(this.bodyView.replaceById=!0,`<div class="${this.noBodyPadding?`modal-body p-0 py-4 ${this.bodyClass}`:`modal-body ${this.bodyClass}`}" data-view-container="body">
39
+ `}async filterContextMenuItems(){if(!this.contextMenu||!this.contextMenu.items)return[];const e=[];for(const t of this.contextMenu.items){if(t.type==="divider"){e.push(t);continue}if(t.permissions)try{const s=this.getApp?.();let i=s?.activeUser||s?.getState?.("activeUser")||null;if(!i&&typeof window<"u"&&window.getApp)try{i=window.getApp()?.activeUser}catch{}if(i?.hasPermission){if(!i.hasPermission(t.permissions))continue}else continue}catch(s){console.warn("ModalView: error checking permissions for context menu item:",s);continue}e.push(t)}return e}async buildBody(){const e=`modal-body ${this.noBodyPadding?"modal-body-flush":""} ${this.bodyClass}`.replace(/\s+/g," ").trim();return this.bodyView?(this.bodyView.replaceById=!0,`<div class="${e}" data-view-container="body">
40
40
  <div id="${this.bodyView.id}"></div>
41
- </div>`):!this.body&&this.body!==""?"":`<div class="${this.noBodyPadding?`modal-body p-0 ${this.bodyClass}`:`modal-body ${this.bodyClass}`}">${this.body}</div>`}async buildFooter(){if(this.footerView)return`<div class="modal-footer ${this.footerClass}" data-view-container="footer"></div>`;if(this.footer!==null&&typeof this.footer=="string")return`<div class="modal-footer ${this.footerClass}">${this.footer}</div>`;if(this.buttons&&this.buttons.length>0){const e=this.buttons.map(t=>{const s=t.dismiss?'data-bs-dismiss="modal"':"",i=t.action?`data-action="${t.action}"`:"",r=t.id?`id="${t.id}"`:"",a=t.disabled?"disabled":"";return`
41
+ </div>`):!this.body&&this.body!==""?"":`<div class="${e}">${this.body}</div>`}async buildFooter(){if(this.footerView)return`<div class="modal-footer ${this.footerClass}" data-view-container="footer"></div>`;if(this.footer!==null&&typeof this.footer=="string")return`<div class="modal-footer ${this.footerClass}">${this.footer}</div>`;if(this.buttons&&this.buttons.length>0){const e=this.buttons.map(t=>{const s=t.dismiss?'data-bs-dismiss="modal"':"",i=t.action?`data-action="${t.action}"`:"",r=t.id?`id="${t.id}"`:"",a=t.disabled?"disabled":"";return`
42
42
  <button type="${t.type||"button"}"
43
43
  class="btn ${t.class||"btn-secondary"}"
44
44
  ${r} ${s} ${i} ${a}>
@@ -199,7 +199,7 @@ var MOJO=(function(A){"use strict";class le{constructor(e={}){this.defaultRoute=
199
199
  </small>
200
200
  </div>
201
201
  </div>
202
- `}updateProgress(e){this.cancelled||this.completed||(this.progress=e.progress,this.percentage=e.percentage,this.loaded=e.loaded,this.total=e.total||this.filesize,this.loadedFormatted=M.pipe(this.loaded,"filesize"),this.totalFormatted=M.pipe(this.total,"filesize"),this.percentage<100?this.status=`Uploading... ${this.percentage}%`:this.status="Finalizing upload...",this.render())}markCompleted(e="Upload completed!"){this.completed=!0,this.progress=1,this.percentage=100,this.status=e,this.render()}markFailed(e="Upload failed"){this.status=e,this.render()}markCancelled(){this.cancelled=!0,this.status="Upload cancelled",this.render()}async onActionCancel(e,t,s){if(!(this.cancelled||this.completed)&&(s.disabled=!0,this.markCancelled(),this.emit("cancel"),typeof this.onCancel=="function"))try{await this.onCancel()}catch(i){console.error("Error in cancel callback:",i)}}setFilename(e){this.filename=e,this.render()}setFilesize(e){this.filesize=e,this.filesizeFormatted=M.pipe(e,"filesize"),this.total=e,this.totalFormatted=this.filesizeFormatted,this.render()}getPercentage(){return this.percentage}isCompleted(){return this.completed}isCancelled(){return this.cancelled}getStats(){return{filename:this.filename,filesize:this.filesize,progress:this.progress,percentage:this.percentage,loaded:this.loaded,total:this.total,cancelled:this.cancelled,completed:this.completed,status:this.status}}}class et{constructor(e,t={}){if(this.fileModel=e,this.options={file:null,name:null,group:null,description:null,onProgress:null,onComplete:null,onError:null,showToast:!0,...t},!this.options.file||!(this.options.file instanceof File))throw new Error("FileUpload requires a valid File object");this.cancelled=!1,this.uploadRequest=null,this.progressToast=null,this.progressView=null,this.toastService=null,this.options.showToast&&(this.toastService=new Xe),this.promise=this._startUpload()}async _startUpload(){try{this.options.showToast&&this._showProgressToast();let e;try{e=await this._initiateUpload()}catch(i){throw new Error(`Failed to initiate upload: ${i.message}`)}if(this.cancelled)throw new Error("Upload cancelled");if(!e||!e.upload_url)throw new Error("Invalid upload response: missing upload URL");let t;if(typeof e.upload_url=="string")t={url:e.upload_url,method:"PUT",fields:null,headers:{}};else if(e.upload_url&&typeof e.upload_url=="object"&&e.upload_url.upload_url)t={url:e.upload_url.upload_url,method:e.upload_url.method||"POST",fields:e.upload_url.fields||null,headers:e.upload_url.headers||{}};else throw new Error(`Invalid upload response: unrecognised upload_url format. Server returned: ${JSON.stringify(e.upload_url)}`);let s;try{s=await this._performUpload(t)}catch(i){throw new Error(`File upload failed: ${i.message}`)}if(this.cancelled)throw new Error("Upload cancelled");try{await this._completeUpload()}catch(i){console.warn("Failed to mark upload as completed:",i)}return this._onComplete(this.fileModel),this.fileModel}catch(e){throw e.message!=="Upload cancelled"&&this._onError(e),e}}async _initiateUpload(){try{const e={filename:this.options.name||this.options.file.name,file_size:this.options.file.size,content_type:this.options.file.type};this.options.group&&(e.group=this.options.group),this.options.description&&(e.description=this.options.description);const t=await this.fileModel.rest.POST("/api/fileman/upload/initiate",e);if(!t)throw new Error("No response from upload initiation API");if(!t.data)throw new Error("Upload initiation response missing data");if(!t.data.status){const s=t.data.error||"Upload initiation failed";throw new Error(s)}if(!t.data.data)throw new Error("Upload initiation response missing data payload");return t.data.data.id&&this.fileModel.set("id",t.data.data.id),t.data.data}catch(e){throw e.message==="Network Error"||e.name==="TypeError"?new Error("Network error during upload initiation. Please check your connection."):e}}async _performUpload(e){return new Promise((t,s)=>{if(!(this.options.file instanceof File)){s(new Error("Only single File objects are supported"));return}const{url:i,method:r,fields:a,headers:n}=e,o=r==="POST"&&a!==null,l=new XMLHttpRequest;this.uploadRequest=l,l.upload.onprogress=u=>{this.cancelled||this._onProgress({progress:u.loaded/u.total,loaded:u.loaded,total:u.total,percentage:Math.round(u.loaded/u.total*100)})},l.onload=()=>{l.status>=200&&l.status<300?t({data:l.response,status:l.status,statusText:l.statusText,xhr:l}):s(new Error(`Upload failed: ${l.status} ${l.statusText}`))},l.onerror=()=>s(new Error("Upload failed: Network error")),l.ontimeout=()=>s(new Error("Upload timed out — file may be too large or connection too slow")),l.onabort=()=>s(new Error("Upload cancelled"));let c=i;i.startsWith("/")&&!i.startsWith("/api/")&&(c="/api"+i);const d=this.fileModel.rest.buildUrl(c);if(l.open(r,d),l.timeout=3e4,o){for(const[p,m]of Object.entries(n||{}))p.toLowerCase()!=="content-type"&&l.setRequestHeader(p,m);const u=new FormData;for(const[p,m]of Object.entries(a))u.append(p,m);u.append("file",this.options.file),l.send(u)}else{l.setRequestHeader("Content-Type",this.options.file.type);for(const[u,p]of Object.entries(n||{}))u.toLowerCase()!=="content-type"&&l.setRequestHeader(u,p);l.send(this.options.file)}})}async _completeUpload(){try{const e=await this.fileModel.save({action:"mark_as_completed"});if(!e)throw new Error("No response from upload completion API");if(e.data&&!e.data.status){const t=e.data.error||"Failed to mark upload as completed";throw new Error(t)}return e}catch(e){throw e.message==="Network Error"||e.name==="TypeError"?new Error("Network error during upload completion. The file may have uploaded successfully."):e}}_onProgress(e){this.progressToast&&this.progressToast.updateProgress&&this.progressToast.updateProgress(e),typeof this.options.onProgress=="function"&&this.options.onProgress(e)}_onComplete(e){this.progressView&&this.progressView.markCompleted("Upload completed successfully!"),this.progressToast&&setTimeout(()=>{try{this.progressToast&&typeof this.progressToast.hide=="function"&&this.progressToast.hide()}catch(t){console.warn("Error hiding progress toast:",t)}},2e3),typeof this.options.onComplete=="function"&&this.options.onComplete(e)}_onError(e){if(this.progressToast)try{this.progressToast.hide()}catch(t){console.warn("Error hiding progress toast on error:",t)}this.toastService&&this.toastService.error(`Upload failed: ${e.message}`),typeof this.options.onError=="function"&&this.options.onError(e)}_showProgressToast(){this.progressView=new fe({filename:this.options.name||this.options.file.name,filesize:this.options.file.size,showCancel:!0,onCancel:()=>this.cancel()}),this.progressToast=this.toastService.showView(this.progressView,"info",{title:"File Upload",autohide:!1,dismissible:!1})}cancel(){return this.cancelled?!1:(this.cancelled=!0,this.uploadRequest&&typeof this.uploadRequest.abort=="function"&&this.uploadRequest.abort(),this.progressView&&this.progressView.markCancelled(),this.progressToast&&setTimeout(()=>{try{this.progressToast&&typeof this.progressToast.hide=="function"&&this.progressToast.hide()}catch(e){console.warn("Error hiding progress toast on cancel:",e)}},1500),!0)}isCancelled(){return this.cancelled}then(e,t){return this.promise.then(e,t)}catch(e){return this.promise.catch(e)}finally(e){return this.promise.finally(e)}getStats(){return{filename:this.options.file.name,size:this.options.file.size,type:this.options.file.type,cancelled:this.cancelled,group:this.options.group,description:this.options.description}}}class K extends W{constructor(e={}){super(e,{endpoint:"/api/group"})}}class ge extends Z{constructor(e={}){super({ModelClass:K,endpoint:"/api/group",size:10,...e})}}const Le={org:"Organization",division:"Division",department:"Department",team:"Team",merchant:"Merchant",partner:"Partner",client:"Client",iso:"ISO",sales:"Sales",reseller:"Reseller",location:"Location",region:"Region",route:"Route",project:"Project",inventory:"Inventory",test:"Testing",misc:"Miscellaneous",qa:"Quality Assurance"},be=Object.entries(Le).map(([h,e])=>({value:h,label:e})),ye={create:{title:"Create Group",fields:[{name:"name",type:"text",label:"Group Name",required:!0,placeholder:"Enter group name"},{name:"kind",type:"select",label:"Group Kind",required:!0,options:be},{type:"collection",name:"parent",label:"Parent Group",Collection:ge,labelField:"name",valueField:"id",maxItems:10,placeholder:"Search groups...",emptyFetch:!1,debounceMs:300}]},edit:{title:"Edit Group",fields:[{name:"name",type:"text",label:"Group Name",required:!0,placeholder:"Enter group name"},{name:"kind",type:"select",label:"Group Kind",required:!0,options:be},{type:"collection",name:"parent",label:"Parent Group",Collection:ge,labelField:"name",valueField:"id",maxItems:10,placeholder:"Search groups...",emptyFetch:!1,debounceMs:300},{name:"metadata.domain",type:"text",label:"Default Domain",placeholder:"Enter Domain"},{name:"metadata.portal",type:"text",label:"Default Portal",placeholder:"Enter Portal URL"},{name:"is_active",type:"switch",label:"Is Active",cols:4}]}};K.EDIT_FORM=ye.edit,K.ADD_FORM=ye.create,K.CREATE_FORM=ye.create,K.GroupKindOptions=be,K.GroupKinds=Le;class F extends W{constructor(e={}){super(e,{endpoint:"/api/user"})}hasPermission(e){if(this.get("is_superuser"))return!0;if(Array.isArray(e))return e.some(i=>this.hasPermission(i));const t=e.startsWith("sys."),s=t?e.substring(4):e;return!!(this._hasPermission(s)||!t&&this.member&&this.member.hasPermission(e))}_hasPermission(e){const t=this.get("permissions");if(!t)return!1;if(t[e]==!0)return!0;const s=F.GRANULAR_TO_CATEGORY[e];return!!(s&&t[s]==!0)}hasPerm(e){return this.hasPermission(e)}}F.CATEGORY_PERMISSIONS=[{name:"view_admin",label:"Admin Panel",tooltip:"Access the admin panel, assistant, and system tools"},{name:"security",label:"Security",tooltip:"Incidents, events, rules, tickets, firewall, bouncer, GeoIP, system logs"},{name:"users",label:"Users",tooltip:"User records, passkeys, TOTP, API keys, OAuth, devices, locations"},{name:"groups",label:"Groups",tooltip:"Groups, members, group API keys, settings"},{name:"comms",label:"Communications",tooltip:"Email, phone, SMS, push notifications, chat, notifications"},{name:"jobs",label:"Jobs",tooltip:"Jobs, job events, job logs, runners, queue control, system stats"},{name:"metrics",label:"Metrics",tooltip:"Metrics recording, fetching, categories, values, permissions"},{name:"files",label:"Files",tooltip:"File managers, files, renditions, vault files, vault data, S3 buckets"},{name:"assistant",label:"AI Assistant",tooltip:"Access to the AI Assistant"},{name:"comms",label:"Communication",tooltip:"Ability to notify users"}],F.GRANULAR_PERMISSION_TABS=[{label:"Account",permissions:[{name:"view_users",label:"View Users"},{name:"manage_users",label:"Manage Users"},{name:"view_groups",label:"View Groups"},{name:"manage_groups",label:"Manage Groups"},{name:"manage_group",label:"Manage Own Group"},{name:"view_members",label:"View Members"},{name:"manage_settings",label:"Manage Settings"}]},{label:"Communication",permissions:[{name:"manage_chat",label:"Manage Chat"},{name:"manage_aws",label:"Manage Email (AWS)"},{name:"view_notifications",label:"View Notifications"},{name:"manage_notifications",label:"Manage Notifications"},{name:"send_notifications",label:"Send Notifications"},{name:"view_devices",label:"View Push Devices"},{name:"manage_devices",label:"Manage Push Devices"},{name:"manage_push_config",label:"Push Config"},{name:"view_phone_numbers",label:"View Phone Numbers"},{name:"manage_phone_numbers",label:"Manage Phone Numbers"},{name:"manage_phone_config",label:"Phone Config"},{name:"view_sms",label:"View SMS"},{name:"manage_sms",label:"Manage SMS"},{name:"send_sms",label:"Send SMS"}]},{label:"Platform",permissions:[{name:"view_security",label:"View Security"},{name:"manage_security",label:"Manage Security"},{name:"admin",label:"Log Admin"},{name:"view_logs",label:"View Logs"},{name:"manage_logs",label:"Manage Logs"},{name:"view_jobs",label:"View Jobs"},{name:"manage_jobs",label:"Manage Jobs"},{name:"view_metrics",label:"View Metrics"},{name:"manage_metrics",label:"Manage Metrics"},{name:"write_metrics",label:"Write Metrics"},{name:"view_fileman",label:"View File Managers"},{name:"manage_files",label:"Manage Files"},{name:"view_vault",label:"View Vault"},{name:"manage_vault",label:"Manage Vault"},{name:"manage_docit",label:"Manage Docs"},{name:"manage_shortlinks",label:"Manage Shortlinks"}]}],F.CATEGORY_GRANULAR_MAP={security:["view_security","manage_security"],users:["view_users","manage_users","view_members"],groups:["view_groups","manage_groups","manage_group"],comms:["manage_chat","manage_aws","view_notifications","manage_notifications","send_notifications","view_devices","manage_devices","manage_push_config","view_phone_numbers","manage_phone_numbers","manage_phone_config","view_sms","manage_sms","send_sms"],jobs:["view_jobs","manage_jobs"],metrics:["view_metrics","manage_metrics","write_metrics"],files:["view_fileman","manage_files","view_vault","manage_vault"]},F.GRANULAR_TO_CATEGORY={};for(const[h,e]of Object.entries(F.CATEGORY_GRANULAR_MAP))for(const t of e)F.GRANULAR_TO_CATEGORY[t]=h;F.APP_CATEGORY_PERMISSIONS=[],F.APP_GRANULAR_PERMISSIONS=[],F.PERMISSIONS=[...F.CATEGORY_PERMISSIONS,...F.GRANULAR_PERMISSION_TABS.flatMap(h=>h.permissions),...F.APP_CATEGORY_PERMISSIONS,...F.APP_GRANULAR_PERMISSIONS],F.PERMISSION_FIELDS=[...F.PERMISSIONS.map(h=>({name:`permissions.${h.name}`,type:"switch",label:h.label,columns:6}))];const re=h=>({name:`permissions.${h.name}`,type:"switch",label:h.label,columns:6,...h.tooltip?{tooltip:h.tooltip}:{}});F.CATEGORY_PERMISSION_FIELDS=(()=>{const h=[{label:"System",fields:F.CATEGORY_PERMISSIONS.map(re)}];return F.APP_CATEGORY_PERMISSIONS.length>0&&h.push({label:"App",fields:F.APP_CATEGORY_PERMISSIONS.map(re)}),[{type:"tabset",tabs:h}]})(),F.GRANULAR_PERMISSION_FIELDS=(()=>{const h=F.GRANULAR_PERMISSION_TABS.map(e=>({label:e.label,fields:e.permissions.map(re)}));return F.APP_GRANULAR_PERMISSIONS.length>0&&h.push({label:"App",fields:F.APP_GRANULAR_PERMISSIONS.map(re)}),[{type:"tabset",tabs:h}]})();const Pe={create:{title:"Create User",fields:[{name:"email",type:"text",label:"Email",required:!0},{name:"phone_number",type:"text",label:"Phone number",columns:12},{name:"display_name",type:"text",label:"Display Name"}]},edit:{title:"Edit User",fields:[{name:"email",type:"email",label:"Email",columns:12},{name:"display_name",type:"text",label:"Display Name",columns:12},{name:"phone_number",type:"text",label:"Phone number",columns:12},{type:"collection",name:"org",label:"Organization",Collection:ge,labelField:"name",valueField:"id",columns:12}]},permissions:{fields:F.PERMISSION_FIELDS}},tt={detailed:{title:"Detailed User Information",columns:2,showEmptyValues:!0,emptyValueText:"Not set",fields:[{name:"id",label:"User ID",type:"number",colSize:3},{name:"display_name",label:"Display Name",type:"text",format:'capitalize|default("Unnamed User")',colSize:9},{name:"username",label:"Username",type:"text",format:"lowercase",colSize:6},{name:"email",label:"Email Address",type:"email",colSize:6},{name:"phone_number",label:"Phone Number",type:"phone",format:'phone|default("Not provided")',colSize:6},{name:"is_active",label:"Account Status",type:"boolean",colSize:6},{name:"last_login",label:"Last Login",type:"datetime",format:"relative",colSize:6},{name:"last_activity",label:"Last Activity",type:"datetime",format:"relative",colSize:6},{name:"avatar.url",label:"Avatar",type:"url",colSize:12},{name:"permissions",label:"User Permissions",type:"dataview",dataViewColumns:2,showEmptyValues:!1},{name:"metadata",label:"User Metadata",type:"dataview",dataViewColumns:1},{name:"avatar",label:"Avatar Details",type:"dataview",dataViewColumns:1}]}};F.DATA_VIEW=tt.detailed,F.EDIT_FORM=Pe.edit,F.ADD_FORM=Pe.create;let st=class extends W{constructor(e={}){super(e,{endpoint:"/api/fileman/file"})}isImage(){return this.get("category")==="image"}getCategory(){return this.get("category")||this._inferCategoryFromContentType()}_inferCategoryFromContentType(){const e=(this.get("content_type")||"").toLowerCase();return e?e.startsWith("image/")?"image":e.startsWith("video/")?"video":e.startsWith("audio/")?"audio":e==="application/pdf"?"pdf":e.startsWith("text/")||e==="application/msword"||e.startsWith("application/vnd.openxmlformats-officedocument.wordprocessingml")||e==="application/vnd.oasis.opendocument.text"?"document":e==="application/vnd.ms-excel"||e.startsWith("application/vnd.openxmlformats-officedocument.spreadsheetml")||e==="application/vnd.oasis.opendocument.spreadsheet"?"spreadsheet":e==="application/vnd.ms-powerpoint"||e.startsWith("application/vnd.openxmlformats-officedocument.presentationml")||e==="application/vnd.oasis.opendocument.presentation"?"presentation":e==="application/zip"||e==="application/x-rar-compressed"||e==="application/x-7z-compressed"||e==="application/x-tar"||e==="application/gzip"?"archive":"other":"other"}hasRenditions(){const e=this.get("renditions");return!!(e&&Object.keys(e).length)}isUploadPending(){const e=this.get("upload_status");return!!(e&&e!=="completed"&&e!=="failed")}regenerateRenditions(e){const t=this.id||this.get("id");if(!t)return Promise.reject(new Error("Cannot regenerate renditions on an unsaved file"));const s=Array.isArray(e)&&e.length?{regenerate_renditions:e}:{regenerate_renditions:!0};return this.rest.POST(`${this.endpoint}/${t}`,s)}share(e=!0){const t=this.id||this.get("id");return t?this.rest.POST(`${this.endpoint}/${t}`,{share:e}):Promise.reject(new Error("Cannot share an unsaved file"))}getRenditions(){const e=this.get("renditions");return e?Object.values(e):[]}getBestImageRendition(){const e=this.getRenditions().filter(t=>t&&typeof t.content_type=="string"&&t.content_type.startsWith("image/"));return e.length?e.reduce((t,s)=>{const i=(parseInt(t.width)||0)*(parseInt(t.height)||0);return(parseInt(s.width)||0)*(parseInt(s.height)||0)>i?s:t}):null}getThumbnailUrl(){const e=this.get("renditions")||{};if(e.thumbnail&&e.thumbnail.url)return e.thumbnail.url;const t=this.getBestImageRendition();return t?t.url:null}upload(e={}){return new et(this,e)}};class b{static _renderAndAwait(e,{buttons:t=null,rejectOnDismiss:s=!1,onAction:i=null,cleanup:r=null}={}){const a=S.getMountTarget();return new Promise((n,o)=>{let l=!1;const c=u=>{l||(l=!0,n(u))},d=u=>{l||(l=!0,o(u))};(async()=>{try{await e.render(!0,a)}catch(u){d(u);return}t&&t.length>0&&e.element&&e.element.querySelectorAll(".modal-footer button").forEach((p,m)=>{const f=t[m];f&&p.addEventListener("click",async g=>{if(l)return;const w=f.value!==void 0?f.value:f.action??m;if(typeof f.handler=="function"){try{const y=await f.handler({dialog:e,button:f,index:m,event:g});if(y===null||y===!1)return;const v=y===!0||y===void 0?w:y;f.dismiss||e.hide(),c(v)}catch(y){console.error("Modal button handler error:",y)}return}if(typeof i=="function"&&f.action){try{const y=await i(f.action,{dialog:e,button:f,index:m,event:g});if(y===null||y===!1)return;const v=y===!0||y===void 0?w:y;f.dismiss||e.hide(),c(v)}catch(y){console.error("Modal onAction error:",y)}return}f.dismiss||e.hide(),c(w)})}),e.on("hidden",()=>{l||(s?d(new Error("Dialog dismissed")):c(null)),setTimeout(async()=>{try{typeof r=="function"&&await r(e)}catch(u){console.error("Modal cleanup error:",u)}try{await e.destroy()}catch(u){console.error("Modal destroy error:",u)}e.element?.parentNode&&e.element.parentNode.removeChild(e.element)},100)}),e.show()})()})}static _resolveEyebrow(e,t){return t===null||t===!1||t===""?"":typeof t=="string"?t:e||""}static _suppressDuplicateTitle(e,t){if(!t||!e)return e;const s=String(e).trim().toUpperCase(),i=String(t).trim().toUpperCase();return s===i?"":e}static _eyebrowStyle(e,t,s){if(t===void 0&&typeof s=="string"&&s.includes("--mojo-eyebrow"))return s;const i=b._resolveEyebrow(e,t),a=`--mojo-eyebrow: '${String(i).replace(/['"\\]/g,"")}'`;return[s,a].filter(Boolean).join("; ")}static async dialog(e={}){if(typeof e=="string"){const v=arguments[0],x=arguments[1]||"Alert";e={...arguments[2]||{},body:v,title:x}}const{title:t="Dialog",content:s,body:i,view:r,message:a,size:n="md",centered:o=!0,buttons:l=[{text:"OK",class:"btn-primary",value:!0}],rejectOnDismiss:c=!1,eyebrow:d,style:u,...p}=e,m=i??r??a??s??"",f=b._resolveEyebrow("",d),g=b._suppressDuplicateTitle(t,f),w=b._eyebrowStyle("",d,u),y=new S({title:g,body:m,size:n,centered:o,buttons:l,style:w,...p});return b._renderAndAwait(y,{buttons:l,rejectOnDismiss:c})}static async drawer(e={}){const{eyebrow:t,title:s,meta:i=[],view:r,body:a,size:n="lg",...o}=e,l=i.length?`
202
+ `}updateProgress(e){this.cancelled||this.completed||(this.progress=e.progress,this.percentage=e.percentage,this.loaded=e.loaded,this.total=e.total||this.filesize,this.loadedFormatted=M.pipe(this.loaded,"filesize"),this.totalFormatted=M.pipe(this.total,"filesize"),this.percentage<100?this.status=`Uploading... ${this.percentage}%`:this.status="Finalizing upload...",this.render())}markCompleted(e="Upload completed!"){this.completed=!0,this.progress=1,this.percentage=100,this.status=e,this.render()}markFailed(e="Upload failed"){this.status=e,this.render()}markCancelled(){this.cancelled=!0,this.status="Upload cancelled",this.render()}async onActionCancel(e,t,s){if(!(this.cancelled||this.completed)&&(s.disabled=!0,this.markCancelled(),this.emit("cancel"),typeof this.onCancel=="function"))try{await this.onCancel()}catch(i){console.error("Error in cancel callback:",i)}}setFilename(e){this.filename=e,this.render()}setFilesize(e){this.filesize=e,this.filesizeFormatted=M.pipe(e,"filesize"),this.total=e,this.totalFormatted=this.filesizeFormatted,this.render()}getPercentage(){return this.percentage}isCompleted(){return this.completed}isCancelled(){return this.cancelled}getStats(){return{filename:this.filename,filesize:this.filesize,progress:this.progress,percentage:this.percentage,loaded:this.loaded,total:this.total,cancelled:this.cancelled,completed:this.completed,status:this.status}}}class et{constructor(e,t={}){if(this.fileModel=e,this.options={file:null,name:null,group:null,description:null,onProgress:null,onComplete:null,onError:null,showToast:!0,...t},!this.options.file||!(this.options.file instanceof File))throw new Error("FileUpload requires a valid File object");this.cancelled=!1,this.uploadRequest=null,this.progressToast=null,this.progressView=null,this.toastService=null,this.options.showToast&&(this.toastService=new Xe),this.promise=this._startUpload()}async _startUpload(){try{this.options.showToast&&this._showProgressToast();let e;try{e=await this._initiateUpload()}catch(i){throw new Error(`Failed to initiate upload: ${i.message}`)}if(this.cancelled)throw new Error("Upload cancelled");if(!e||!e.upload_url)throw new Error("Invalid upload response: missing upload URL");let t;if(typeof e.upload_url=="string")t={url:e.upload_url,method:"PUT",fields:null,headers:{}};else if(e.upload_url&&typeof e.upload_url=="object"&&e.upload_url.upload_url)t={url:e.upload_url.upload_url,method:e.upload_url.method||"POST",fields:e.upload_url.fields||null,headers:e.upload_url.headers||{}};else throw new Error(`Invalid upload response: unrecognised upload_url format. Server returned: ${JSON.stringify(e.upload_url)}`);let s;try{s=await this._performUpload(t)}catch(i){throw new Error(`File upload failed: ${i.message}`)}if(this.cancelled)throw new Error("Upload cancelled");try{await this._completeUpload()}catch(i){console.warn("Failed to mark upload as completed:",i)}return this._onComplete(this.fileModel),this.fileModel}catch(e){throw e.message!=="Upload cancelled"&&this._onError(e),e}}async _initiateUpload(){try{const e={filename:this.options.name||this.options.file.name,file_size:this.options.file.size,content_type:this.options.file.type};this.options.group&&(e.group=this.options.group),this.options.description&&(e.description=this.options.description);const t=await this.fileModel.rest.POST("/api/fileman/upload/initiate",e);if(!t)throw new Error("No response from upload initiation API");if(!t.data)throw new Error("Upload initiation response missing data");if(!t.data.status){const s=t.data.error||"Upload initiation failed";throw new Error(s)}if(!t.data.data)throw new Error("Upload initiation response missing data payload");return t.data.data.id&&this.fileModel.set("id",t.data.data.id),t.data.data}catch(e){throw e.message==="Network Error"||e.name==="TypeError"?new Error("Network error during upload initiation. Please check your connection."):e}}async _performUpload(e){return new Promise((t,s)=>{if(!(this.options.file instanceof File)){s(new Error("Only single File objects are supported"));return}const{url:i,method:r,fields:a,headers:n}=e,o=r==="POST"&&a!==null,l=new XMLHttpRequest;this.uploadRequest=l,l.upload.onprogress=u=>{this.cancelled||this._onProgress({progress:u.loaded/u.total,loaded:u.loaded,total:u.total,percentage:Math.round(u.loaded/u.total*100)})},l.onload=()=>{l.status>=200&&l.status<300?t({data:l.response,status:l.status,statusText:l.statusText,xhr:l}):s(new Error(`Upload failed: ${l.status} ${l.statusText}`))},l.onerror=()=>s(new Error("Upload failed: Network error")),l.ontimeout=()=>s(new Error("Upload timed out — file may be too large or connection too slow")),l.onabort=()=>s(new Error("Upload cancelled"));let c=i;i.startsWith("/")&&!i.startsWith("/api/")&&(c="/api"+i);const d=this.fileModel.rest.buildUrl(c);if(l.open(r,d),l.timeout=3e4,o){for(const[p,m]of Object.entries(n||{}))p.toLowerCase()!=="content-type"&&l.setRequestHeader(p,m);const u=new FormData;for(const[p,m]of Object.entries(a))u.append(p,m);u.append("file",this.options.file),l.send(u)}else{l.setRequestHeader("Content-Type",this.options.file.type);for(const[u,p]of Object.entries(n||{}))u.toLowerCase()!=="content-type"&&l.setRequestHeader(u,p);l.send(this.options.file)}})}async _completeUpload(){try{const e=await this.fileModel.save({action:"mark_as_completed"});if(!e)throw new Error("No response from upload completion API");if(e.data&&!e.data.status){const t=e.data.error||"Failed to mark upload as completed";throw new Error(t)}return e}catch(e){throw e.message==="Network Error"||e.name==="TypeError"?new Error("Network error during upload completion. The file may have uploaded successfully."):e}}_onProgress(e){this.progressToast&&this.progressToast.updateProgress&&this.progressToast.updateProgress(e),typeof this.options.onProgress=="function"&&this.options.onProgress(e)}_onComplete(e){this.progressView&&this.progressView.markCompleted("Upload completed successfully!"),this.progressToast&&setTimeout(()=>{try{this.progressToast&&typeof this.progressToast.hide=="function"&&this.progressToast.hide()}catch(t){console.warn("Error hiding progress toast:",t)}},2e3),typeof this.options.onComplete=="function"&&this.options.onComplete(e)}_onError(e){if(this.progressToast)try{this.progressToast.hide()}catch(t){console.warn("Error hiding progress toast on error:",t)}this.toastService&&this.toastService.error(`Upload failed: ${e.message}`),typeof this.options.onError=="function"&&this.options.onError(e)}_showProgressToast(){this.progressView=new fe({filename:this.options.name||this.options.file.name,filesize:this.options.file.size,showCancel:!0,onCancel:()=>this.cancel()}),this.progressToast=this.toastService.showView(this.progressView,"info",{title:"File Upload",autohide:!1,dismissible:!1})}cancel(){return this.cancelled?!1:(this.cancelled=!0,this.uploadRequest&&typeof this.uploadRequest.abort=="function"&&this.uploadRequest.abort(),this.progressView&&this.progressView.markCancelled(),this.progressToast&&setTimeout(()=>{try{this.progressToast&&typeof this.progressToast.hide=="function"&&this.progressToast.hide()}catch(e){console.warn("Error hiding progress toast on cancel:",e)}},1500),!0)}isCancelled(){return this.cancelled}then(e,t){return this.promise.then(e,t)}catch(e){return this.promise.catch(e)}finally(e){return this.promise.finally(e)}getStats(){return{filename:this.options.file.name,size:this.options.file.size,type:this.options.file.type,cancelled:this.cancelled,group:this.options.group,description:this.options.description}}}class K extends W{constructor(e={}){super(e,{endpoint:"/api/group"})}}class ge extends Z{constructor(e={}){super({ModelClass:K,endpoint:"/api/group",size:10,...e})}}const Le={org:"Organization",division:"Division",department:"Department",team:"Team",merchant:"Merchant",partner:"Partner",client:"Client",iso:"ISO",sales:"Sales",reseller:"Reseller",location:"Location",region:"Region",route:"Route",project:"Project",inventory:"Inventory",test:"Testing",misc:"Miscellaneous",qa:"Quality Assurance"},be=Object.entries(Le).map(([h,e])=>({value:h,label:e})),ye={create:{title:"Create Group",fields:[{name:"name",type:"text",label:"Group Name",required:!0,placeholder:"Enter group name"},{name:"kind",type:"select",label:"Group Kind",required:!0,options:be},{type:"collection",name:"parent",label:"Parent Group",Collection:ge,labelField:"name",valueField:"id",maxItems:10,placeholder:"Search groups...",emptyFetch:!1,debounceMs:300}]},edit:{title:"Edit Group",fields:[{name:"name",type:"text",label:"Group Name",required:!0,placeholder:"Enter group name"},{name:"kind",type:"select",label:"Group Kind",required:!0,options:be},{type:"collection",name:"parent",label:"Parent Group",Collection:ge,labelField:"name",valueField:"id",maxItems:10,placeholder:"Search groups...",emptyFetch:!1,debounceMs:300},{name:"metadata.domain",type:"text",label:"Default Domain",placeholder:"Enter Domain"},{name:"metadata.portal",type:"text",label:"Default Portal",placeholder:"Enter Portal URL"},{name:"is_active",type:"switch",label:"Is Active",cols:4}]}};K.EDIT_FORM=ye.edit,K.ADD_FORM=ye.create,K.CREATE_FORM=ye.create,K.GroupKindOptions=be,K.GroupKinds=Le;class F extends W{constructor(e={}){super(e,{endpoint:"/api/user"})}hasPermission(e){if(this.get("is_superuser"))return!0;if(Array.isArray(e))return e.some(i=>this.hasPermission(i));const t=e.startsWith("sys."),s=t?e.substring(4):e;return!!(this._hasPermission(s)||!t&&this.member&&this.member.hasPermission(e))}_hasPermission(e){const t=this.get("permissions");if(!t)return!1;if(t[e]==!0)return!0;const s=F.GRANULAR_TO_CATEGORY[e];return!!(s&&t[s]==!0)}hasPerm(e){return this.hasPermission(e)}}F.CATEGORY_PERMISSIONS=[{name:"view_admin",label:"Admin Panel",tooltip:"Access the admin panel, assistant, and system tools"},{name:"security",label:"Security",tooltip:"Incidents, events, rules, tickets, firewall, bouncer, GeoIP, system logs"},{name:"users",label:"Users",tooltip:"User records, passkeys, TOTP, API keys, OAuth, devices, locations"},{name:"groups",label:"Groups",tooltip:"Groups, members, group API keys, settings"},{name:"comms",label:"Communications",tooltip:"Email, phone, SMS, push notifications, chat, notifications"},{name:"jobs",label:"Jobs",tooltip:"Jobs, job events, job logs, runners, queue control, system stats"},{name:"metrics",label:"Metrics",tooltip:"Metrics recording, fetching, categories, values, permissions"},{name:"files",label:"Files",tooltip:"File managers, files, renditions, vault files, vault data, S3 buckets"},{name:"assistant",label:"AI Assistant",tooltip:"Access to the AI Assistant"},{name:"comms",label:"Communication",tooltip:"Ability to notify users"}],F.GRANULAR_PERMISSION_TABS=[{label:"Account",permissions:[{name:"view_users",label:"View Users"},{name:"manage_users",label:"Manage Users"},{name:"view_groups",label:"View Groups"},{name:"manage_groups",label:"Manage Groups"},{name:"manage_group",label:"Manage Own Group"},{name:"view_members",label:"View Members"},{name:"manage_settings",label:"Manage Settings"}]},{label:"Communication",permissions:[{name:"manage_chat",label:"Manage Chat"},{name:"manage_aws",label:"Manage Email (AWS)"},{name:"view_notifications",label:"View Notifications"},{name:"manage_notifications",label:"Manage Notifications"},{name:"send_notifications",label:"Send Notifications"},{name:"view_devices",label:"View Push Devices"},{name:"manage_devices",label:"Manage Push Devices"},{name:"manage_push_config",label:"Push Config"},{name:"view_phone_numbers",label:"View Phone Numbers"},{name:"manage_phone_numbers",label:"Manage Phone Numbers"},{name:"manage_phone_config",label:"Phone Config"},{name:"view_sms",label:"View SMS"},{name:"manage_sms",label:"Manage SMS"},{name:"send_sms",label:"Send SMS"}]},{label:"Platform",permissions:[{name:"view_security",label:"View Security"},{name:"manage_security",label:"Manage Security"},{name:"admin",label:"Log Admin"},{name:"view_logs",label:"View Logs"},{name:"manage_logs",label:"Manage Logs"},{name:"view_jobs",label:"View Jobs"},{name:"manage_jobs",label:"Manage Jobs"},{name:"view_metrics",label:"View Metrics"},{name:"manage_metrics",label:"Manage Metrics"},{name:"write_metrics",label:"Write Metrics"},{name:"view_fileman",label:"View File Managers"},{name:"manage_files",label:"Manage Files"},{name:"view_vault",label:"View Vault"},{name:"manage_vault",label:"Manage Vault"},{name:"manage_docit",label:"Manage Docs"},{name:"manage_shortlinks",label:"Manage Shortlinks"}]}],F.CATEGORY_GRANULAR_MAP={security:["view_security","manage_security"],users:["view_users","manage_users","view_members"],groups:["view_groups","manage_groups","manage_group"],comms:["manage_chat","manage_aws","view_notifications","manage_notifications","send_notifications","view_devices","manage_devices","manage_push_config","view_phone_numbers","manage_phone_numbers","manage_phone_config","view_sms","manage_sms","send_sms"],jobs:["view_jobs","manage_jobs"],metrics:["view_metrics","manage_metrics","write_metrics"],files:["view_fileman","manage_files","view_vault","manage_vault"]},F.GRANULAR_TO_CATEGORY={};for(const[h,e]of Object.entries(F.CATEGORY_GRANULAR_MAP))for(const t of e)F.GRANULAR_TO_CATEGORY[t]=h;F.APP_CATEGORY_PERMISSIONS=[],F.APP_GRANULAR_PERMISSIONS=[],F.PERMISSIONS=[...F.CATEGORY_PERMISSIONS,...F.GRANULAR_PERMISSION_TABS.flatMap(h=>h.permissions),...F.APP_CATEGORY_PERMISSIONS,...F.APP_GRANULAR_PERMISSIONS],F.PERMISSION_FIELDS=[...F.PERMISSIONS.map(h=>({name:`permissions.${h.name}`,type:"switch",label:h.label,columns:6}))];const re=h=>({name:`permissions.${h.name}`,type:"switch",label:h.label,columns:6,...h.tooltip?{tooltip:h.tooltip}:{}});F.CATEGORY_PERMISSION_FIELDS=(()=>{const h=[{label:"System",fields:F.CATEGORY_PERMISSIONS.map(re)}];return F.APP_CATEGORY_PERMISSIONS.length>0&&h.push({label:"App",fields:F.APP_CATEGORY_PERMISSIONS.map(re)}),[{type:"tabset",tabs:h}]})(),F.GRANULAR_PERMISSION_FIELDS=(()=>{const h=F.GRANULAR_PERMISSION_TABS.map(e=>({label:e.label,fields:e.permissions.map(re)}));return F.APP_GRANULAR_PERMISSIONS.length>0&&h.push({label:"App",fields:F.APP_GRANULAR_PERMISSIONS.map(re)}),[{type:"tabset",tabs:h}]})();const Pe={create:{title:"Create User",fields:[{name:"email",type:"text",label:"Email",required:!0},{name:"phone_number",type:"text",label:"Phone number",columns:12},{name:"display_name",type:"text",label:"Display Name"}]},edit:{title:"Edit User",fields:[{name:"email",type:"email",label:"Email",columns:12},{name:"display_name",type:"text",label:"Display Name",columns:12},{name:"phone_number",type:"text",label:"Phone number",columns:12},{type:"collection",name:"org",label:"Organization",Collection:ge,labelField:"name",valueField:"id",columns:12}]},permissions:{fields:F.PERMISSION_FIELDS}},tt={detailed:{title:"Detailed User Information",columns:2,showEmptyValues:!0,emptyValueText:"Not set",fields:[{name:"id",label:"User ID",type:"number",colSize:3},{name:"display_name",label:"Display Name",type:"text",format:'capitalize|default("Unnamed User")',colSize:9},{name:"username",label:"Username",type:"text",format:"lowercase",colSize:6},{name:"email",label:"Email Address",type:"email",colSize:6},{name:"phone_number",label:"Phone Number",type:"phone",format:'phone|default("Not provided")',colSize:6},{name:"is_active",label:"Account Status",type:"boolean",colSize:6},{name:"last_login",label:"Last Login",type:"datetime",format:"relative",colSize:6},{name:"last_activity",label:"Last Activity",type:"datetime",format:"relative",colSize:6},{name:"avatar.url",label:"Avatar",type:"url",colSize:12},{name:"permissions",label:"User Permissions",type:"dataview",dataViewColumns:2,showEmptyValues:!1},{name:"metadata",label:"User Metadata",type:"dataview",dataViewColumns:1},{name:"avatar",label:"Avatar Details",type:"dataview",dataViewColumns:1}]}};F.DATA_VIEW=tt.detailed,F.EDIT_FORM=Pe.edit,F.ADD_FORM=Pe.create;let st=class extends W{constructor(e={}){super(e,{endpoint:"/api/fileman/file"})}isImage(){return this.get("category")==="image"}getCategory(){return this.get("category")||this._inferCategoryFromContentType()}_inferCategoryFromContentType(){const e=(this.get("content_type")||"").toLowerCase();return e?e.startsWith("image/")?"image":e.startsWith("video/")?"video":e.startsWith("audio/")?"audio":e==="application/pdf"?"pdf":e.startsWith("text/")||e==="application/msword"||e.startsWith("application/vnd.openxmlformats-officedocument.wordprocessingml")||e==="application/vnd.oasis.opendocument.text"?"document":e==="application/vnd.ms-excel"||e.startsWith("application/vnd.openxmlformats-officedocument.spreadsheetml")||e==="application/vnd.oasis.opendocument.spreadsheet"?"spreadsheet":e==="application/vnd.ms-powerpoint"||e.startsWith("application/vnd.openxmlformats-officedocument.presentationml")||e==="application/vnd.oasis.opendocument.presentation"?"presentation":e==="application/zip"||e==="application/x-rar-compressed"||e==="application/x-7z-compressed"||e==="application/x-tar"||e==="application/gzip"?"archive":"other":"other"}hasRenditions(){const e=this.get("renditions");return!!(e&&Object.keys(e).length)}isUploadPending(){const e=this.get("upload_status");return!!(e&&e!=="completed"&&e!=="failed")}regenerateRenditions(e){const t=this.id||this.get("id");if(!t)return Promise.reject(new Error("Cannot regenerate renditions on an unsaved file"));const s=Array.isArray(e)&&e.length?{regenerate_renditions:e}:{regenerate_renditions:!0};return this.rest.POST(`${this.endpoint}/${t}`,s)}share(e=!0){const t=this.id||this.get("id");return t?this.rest.POST(`${this.endpoint}/${t}`,{share:e}):Promise.reject(new Error("Cannot share an unsaved file"))}getRenditions(){const e=this.get("renditions");return e?Object.values(e):[]}getBestImageRendition(){const e=this.getRenditions().filter(t=>t&&typeof t.content_type=="string"&&t.content_type.startsWith("image/"));return e.length?e.reduce((t,s)=>{const i=(parseInt(t.width)||0)*(parseInt(t.height)||0);return(parseInt(s.width)||0)*(parseInt(s.height)||0)>i?s:t}):null}getThumbnailUrl(){const e=this.get("renditions")||{};if(e.thumbnail&&e.thumbnail.url)return e.thumbnail.url;const t=this.getBestImageRendition();return t?t.url:null}upload(e={}){return new et(this,e)}};class b{static setEyebrowEnabled(e){typeof document>"u"||document.documentElement.classList.toggle("mojo-no-eyebrow",!e)}static isEyebrowEnabled(){return typeof document>"u"?!0:!document.documentElement.classList.contains("mojo-no-eyebrow")}static _renderAndAwait(e,{buttons:t=null,rejectOnDismiss:s=!1,onAction:i=null,cleanup:r=null}={}){const a=S.getMountTarget();return new Promise((n,o)=>{let l=!1;const c=u=>{l||(l=!0,n(u))},d=u=>{l||(l=!0,o(u))};(async()=>{try{await e.render(!0,a)}catch(u){d(u);return}t&&t.length>0&&e.element&&e.element.querySelectorAll(".modal-footer button").forEach((p,m)=>{const f=t[m];f&&p.addEventListener("click",async g=>{if(l)return;const w=f.value!==void 0?f.value:f.action??m;if(typeof f.handler=="function"){try{const y=await f.handler({dialog:e,button:f,index:m,event:g});if(y===null||y===!1)return;const v=y===!0||y===void 0?w:y;f.dismiss||e.hide(),c(v)}catch(y){console.error("Modal button handler error:",y)}return}if(typeof i=="function"&&f.action){try{const y=await i(f.action,{dialog:e,button:f,index:m,event:g});if(y===null||y===!1)return;const v=y===!0||y===void 0?w:y;f.dismiss||e.hide(),c(v)}catch(y){console.error("Modal onAction error:",y)}return}f.dismiss||e.hide(),c(w)})}),e.on("hidden",()=>{l||(s?d(new Error("Dialog dismissed")):c(null)),setTimeout(async()=>{try{typeof r=="function"&&await r(e)}catch(u){console.error("Modal cleanup error:",u)}try{await e.destroy()}catch(u){console.error("Modal destroy error:",u)}e.element?.parentNode&&e.element.parentNode.removeChild(e.element)},100)}),e.show()})()})}static _resolveEyebrow(e,t){return t===null||t===!1||t===""?"":typeof t=="string"?t:e||""}static _suppressDuplicateTitle(e,t){if(!t||!e)return e;const s=String(e).trim().toUpperCase(),i=String(t).trim().toUpperCase();return s===i?"":e}static _eyebrowStyle(e,t,s){if(t===void 0&&typeof s=="string"&&s.includes("--mojo-eyebrow"))return s;const i=b._resolveEyebrow(e,t),a=`--mojo-eyebrow: '${String(i).replace(/['"\\]/g,"")}'`;return[s,a].filter(Boolean).join("; ")}static async dialog(e={}){if(typeof e=="string"){const v=arguments[0],x=arguments[1]||"Alert";e={...arguments[2]||{},body:v,title:x}}const{title:t="Dialog",content:s,body:i,view:r,message:a,size:n="md",centered:o=!0,buttons:l=[{text:"OK",class:"btn-primary",value:!0}],rejectOnDismiss:c=!1,eyebrow:d,style:u,...p}=e,m=i??r??a??s??"",f=b._resolveEyebrow("",d),g=b._suppressDuplicateTitle(t,f),w=b._eyebrowStyle("",d,u),y=new S({title:g,body:m,size:n,centered:o,buttons:l,style:w,...p});return b._renderAndAwait(y,{buttons:l,rejectOnDismiss:c})}static async drawer(e={}){const{eyebrow:t,title:s,meta:i=[],view:r,body:a,size:n="lg",...o}=e,l=i.length?`
203
203
  <div class="modal-drawer-meta">
204
204
  ${i.map(u=>typeof u=="string"?`<span>${b._esc(u)}</span>`:`<span>${u.icon?`<i class="${b._esc(u.icon)} me-1"></i>`:""}${b._esc(u.text||"")}</span>`).join("")}
205
205
  </div>`:"",c=`
@@ -208,7 +208,7 @@ var MOJO=(function(A){"use strict";class le{constructor(e={}){this.defaultRoute=
208
208
  <h2 class="modal-drawer-title">${b._esc(s||"")}</h2>
209
209
  ${l}
210
210
  </div>
211
- `;let d;if(r&&typeof r=="object"&&typeof r.render=="function"){const u=class extends C{async getTemplate(){return`${c}<div class="modal-drawer-body" data-container="drawer-body"></div>`}async onInit(){r.containerId="drawer-body",this.addChild(r)}};d=new u}else d=`${c}<div class="modal-drawer-body">${a||""}</div>`;return b.dialog({header:!1,body:d,size:n,centered:!1,className:`modal-bandless ${o.className||""}`.trim(),buttons:[{text:"Close",class:"btn-secondary",dismiss:!0}],...o})}static _esc(e){const t=typeof document<"u"?document.createElement("div"):null;return t?(t.textContent=String(e??""),t.innerHTML):String(e??"")}static async show(e,t={}){const{eyebrow:s,style:i,...r}=t;return b.dialog({header:t.title!==void 0?!!t.title:!1,title:t.title||void 0,body:e,size:"lg",centered:!1,buttons:[{text:"Close",class:"btn-secondary",dismiss:!0}],style:b._eyebrowStyle("DETAILS",s,i),...r})}static async showModel(e,t={}){const s=e.constructor,i=s?.VIEW_CLASS;if(!i)throw new Error(`Modal.showModel: No VIEW_CLASS defined on ${s?.name||"model"}. Set ${s?.name||"Model"}.VIEW_CLASS = YourView to use this method.`);const r=new i({model:e});return b.show(r,t)}static async showModelById(e,t,s={}){const i=new e({id:t});return await i.fetch(),i.id?b.showModel(i,s):(b.alert({message:`Could not find ${e.name||"record"} with ID: ${t}`,type:"warning"}),null)}static async showModelView(e,t={}){const s=e.constructor,i=s?.VIEW_CLASS;if(!i)throw new Error(`Modal.showModelView: No VIEW_CLASS defined on ${s?.name||"model"}.`);const r=new i({model:e}),{eyebrow:a,style:n,...o}=t;return b.dialog({header:!1,body:r,size:"lg",centered:!1,style:b._eyebrowStyle("DETAILS",a,n),...o})}static async alert(e={},t,s){let i;typeof e=="string"?i={message:e,...t!==void 0?{title:t}:{},...s||{}}:i={...e};const{message:r="",title:a="Alert",type:n="info",eyebrow:o,className:l,style:c,...d}=i,u=n==="danger"?"error":n,m=[`modal-alert modal-alert-${u}`,l].filter(Boolean).join(" "),f={info:"INFORMATION",success:"SUCCESS",warning:"WARNING",error:"ERROR"},g=f[u]??f.info,w=b._resolveEyebrow(g,o),y=b._suppressDuplicateTitle(a,w),v=b._eyebrowStyle(g,o,c),x=y?`<span class="modal-alert-headline">${y}</span>`:"";return b.dialog({title:x,body:`<p class="modal-alert-message">${r}</p>`,size:"sm",centered:!0,className:m,style:v,buttons:[{text:"OK",class:"btn-primary",value:!0}],...d})}static async confirm(e,t="Confirm",s={}){let i;typeof e=="object"&&e!==null?(s=e,i=s.message,t=s.title||t):i=e;const r=[{text:s.cancelText||"Cancel",class:"btn-secondary",dismiss:!0,action:"cancel"},{text:s.confirmText||"Confirm",class:s.confirmClass||"btn-primary",action:"confirm"}],{eyebrow:a,style:n,...o}=s,l=b._resolveEyebrow("CONFIRM",a),c=b._suppressDuplicateTitle(t,l),d=b._eyebrowStyle("CONFIRM",a,n),u=new S({title:c,body:`<p>${i}</p>`,size:s.size||"sm",centered:!0,backdrop:"static",buttons:r,style:d,...o});return await b._renderAndAwait(u,{buttons:r,onAction:async m=>m==="confirm"})===!0}static async prompt(e,t="Input",s={}){const i=`prompt-input-${Date.now()}`,r=s.defaultValue||"",a=s.inputType||"text",n=s.placeholder||"",o=[{text:"Cancel",class:"btn-secondary",dismiss:!0},{text:"OK",class:"btn-primary",action:"ok"}],{eyebrow:l,style:c,...d}=s,u=b._resolveEyebrow("INPUT",l),p=b._suppressDuplicateTitle(t,u),m=b._eyebrowStyle("INPUT",l,c),f=new S({title:p,body:`
211
+ `;let d;if(r&&typeof r=="object"&&typeof r.render=="function"){const u=class extends C{async getTemplate(){return`${c}<div class="modal-drawer-body" data-container="drawer-body"></div>`}async onInit(){r.containerId="drawer-body",this.addChild(r)}};d=new u}else d=`${c}<div class="modal-drawer-body">${a||""}</div>`;return b.dialog({header:!1,body:d,size:n,centered:!1,className:`modal-bandless ${o.className||""}`.trim(),buttons:[{text:"Close",class:"btn-secondary",dismiss:!0}],...o})}static _esc(e){const t=typeof document<"u"?document.createElement("div"):null;return t?(t.textContent=String(e??""),t.innerHTML):String(e??"")}static async show(e,t={}){const{eyebrow:s,style:i,...r}=t;return b.dialog({header:t.title!==void 0?!!t.title:!1,title:t.title||void 0,body:e,size:"lg",centered:!1,buttons:[{text:"Close",class:"btn-secondary",dismiss:!0}],style:b._eyebrowStyle("DETAILS",s,i),...r})}static async showModel(e,t={}){const s=e.constructor,i=s?.VIEW_CLASS;if(!i)throw new Error(`Modal.showModel: No VIEW_CLASS defined on ${s?.name||"model"}. Set ${s?.name||"Model"}.VIEW_CLASS = YourView to use this method.`);const r=new i({model:e});return b.show(r,t)}static async showModelById(e,t,s={}){const i=new e({id:t});return await i.fetch(),i.id?b.showModel(i,s):(b.alert({message:`Could not find ${e.name||"record"} with ID: ${t}`,type:"warning"}),null)}static async showModelView(e,t={}){const s=e.constructor,i=s?.VIEW_CLASS;if(!i)throw new Error(`Modal.showModelView: No VIEW_CLASS defined on ${s?.name||"model"}.`);const r=new i({model:e}),{eyebrow:a,style:n,...o}=t;return b.dialog({header:!1,body:r,size:"lg",centered:!1,style:b._eyebrowStyle("DETAILS",a,n),...o})}static async alert(e={},t,s){let i;typeof e=="string"?i={message:e,...t!==void 0?{title:t}:{},...s||{}}:i={...e};const{message:r="",title:a="Alert",type:n="info",eyebrow:o,className:l,style:c,...d}=i,u=n==="danger"?"error":n,m=[`modal-alert modal-alert-${u}`,l].filter(Boolean).join(" "),f={info:"INFORMATION",success:"SUCCESS",warning:"WARNING",error:"ERROR"},g=f[u]??f.info,w=b._resolveEyebrow(g,o),y=b._suppressDuplicateTitle(a,w),v=b._eyebrowStyle(g,o,c),x=y?`<span class="modal-alert-headline">${y}</span>`:"";return b.dialog({title:x,body:`<p class="modal-alert-message">${r}</p>`,size:"sm",centered:!0,className:m,style:v,buttons:[{text:"OK",class:"btn-primary",value:!0}],...d})}static async confirm(e,t="Confirm",s={}){let i;typeof e=="object"&&e!==null?(s=e,i=s.message,t=s.title||t):i=e;const r=[{text:s.cancelText||"Cancel",class:"btn-secondary",dismiss:!0,action:"cancel"},{text:s.confirmText||"Confirm",class:s.confirmClass||"btn-primary",action:"confirm"}],{eyebrow:a,style:n,...o}=s,l=b._resolveEyebrow("CONFIRM",a),c=b._suppressDuplicateTitle(t,l),d=b._eyebrowStyle("CONFIRM",a,n),u=new S({title:c,body:`<p>${i}</p>`,size:s.size||"sm",centered:!0,backdrop:"static",buttons:r,style:d,...o});return await b._renderAndAwait(u,{buttons:r})==="confirm"}static async prompt(e,t="Input",s={}){const i=`prompt-input-${Date.now()}`,r=s.defaultValue||"",a=s.inputType||"text",n=s.placeholder||"",o=[{text:"Cancel",class:"btn-secondary",dismiss:!0},{text:"OK",class:"btn-primary",action:"ok"}],{eyebrow:l,style:c,...d}=s,u=b._resolveEyebrow("INPUT",l),p=b._suppressDuplicateTitle(t,u),m=b._eyebrowStyle("INPUT",l,c),f=new S({title:p,body:`
212
212
  <p>${e}</p>
213
213
  <input type="${a}"
214
214
  class="form-control"