lula2 0.5.1-nightly.5 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/_app/immutable/chunks/CayEUOo2.js +3 -0
- package/dist/_app/immutable/chunks/{-QrdrDH3.js → DOBcdfgj.js} +1 -1
- package/dist/_app/immutable/chunks/aIhTG3uO.js +65 -0
- package/dist/_app/immutable/entry/{app.BWZxpS12.js → app.B7_zLkkx.js} +2 -2
- package/dist/_app/immutable/entry/start.CJGnwt1e.js +1 -0
- package/dist/_app/immutable/nodes/{0.BiH4WIws.js → 0.B9CL1cKq.js} +1 -1
- package/dist/_app/immutable/nodes/{1.C_oKiD_Q.js → 1.B5-Ctyqh.js} +1 -1
- package/dist/_app/immutable/nodes/{2.DyvyPU88.js → 2.hJcgnwrH.js} +1 -1
- package/dist/_app/immutable/nodes/{3.0az1kCvx.js → 3.Cln2iH1E.js} +1 -1
- package/dist/_app/immutable/nodes/{4.DdSc8cDv.js → 4.CcGLqOYE.js} +1 -1
- package/dist/_app/version.json +1 -1
- package/dist/cli/commands/crawl.js +2 -52
- package/dist/index.html +6 -6
- package/dist/index.js +2 -51
- package/package.json +21 -20
- package/src/lib/components/controls/ControlsList.svelte +82 -9
- package/src/lib/components/ui/FilterBuilder.svelte +167 -27
- package/src/lib/types.ts +1 -0
- package/src/stores/compliance.ts +13 -0
- package/dist/_app/immutable/chunks/DKTpWYsg.js +0 -65
- package/dist/_app/immutable/chunks/rqvYJuq0.js +0 -3
- package/dist/_app/immutable/entry/start.2E1kShC9.js +0 -1
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import"../chunks/DsnmJJEf.js";import{aR as he,p as U,am as S,d as h,T as L,G as _,h as i,an as X,ao as A,c as r,n as P,r as a,b as p,e as Y,J as O,K as N,aj as le,a as K,f as I,ap as ze,g as ie,a0 as we,u as Ee,aq as Se,b0 as Le,s as $,i as He,o as Ae,b1 as De,b2 as ye}from"../chunks/DTWPdvjs.js";import{l as H,p as C,i as E,a as be,s as ke}from"../chunks/BXUi170M.js";import{g as Pe}from"../chunks/
|
|
1
|
+
import"../chunks/DsnmJJEf.js";import{aR as he,p as U,am as S,d as h,T as L,G as _,h as i,an as X,ao as A,c as r,n as P,r as a,b as p,e as Y,J as O,K as N,aj as le,a as K,f as I,ap as ze,g as ie,a0 as we,u as Ee,aq as Se,b0 as Le,s as $,i as He,o as Ae,b1 as De,b2 as ye}from"../chunks/DTWPdvjs.js";import{l as H,p as C,i as E,a as be,s as ke}from"../chunks/BXUi170M.js";import{g as Pe}from"../chunks/CayEUOo2.js";import{a as je,p as Re,D as Ne}from"../chunks/DOBcdfgj.js";import{i as q}from"../chunks/Cq7PwVfU.js";import{a as ee,f as Ce,e as Te,d as Ve,i as Be,w as ce}from"../chunks/e7OeeeKP.js";he(["change"]);var Oe=A("<title> </title>"),Ue=A('<svg><!><path d="M11.41 26.59L7.83 23 28 23 28 21 7.83 21 11.41 17.41 10 16 4 22 10 28 11.41 26.59zM28 10L22 4 20.59 5.41 24.17 9 4 9 4 11 24.17 11 20.59 14.59 22 16 28 10z"></path></svg>');function Ye(v,t){const e=H(t,["children","$$slots","$$events","$$legacy"]),y=H(e,["size","title"]);U(t,!1);const o=L(),m=L();let g=C(t,"size",8,16),s=C(t,"title",8,void 0);S(()=>(_(e),_(s())),()=>{h(o,e["aria-label"]||e["aria-labelledby"]||s())}),S(()=>(i(o),_(e)),()=>{h(m,{"aria-hidden":i(o)?void 0:!0,role:i(o)?"img":void 0,focusable:Number(e.tabindex)===0?!0:void 0})}),X(),q();var n=Ue();ee(n,()=>({xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 32 32",fill:"currentColor",preserveAspectRatio:"xMidYMid meet",width:g(),height:g(),...i(m),...y}));var l=r(n);{var b=d=>{var c=Oe(),k=r(c,!0);a(c),O(()=>N(k,s())),p(d,c)};E(l,d=>{s()&&d(b)})}P(),a(n),p(v,n),Y()}var Ie=I('<a href="/setup" class="inline-flex items-center gap-2 px-4 py-2 text-sm font-medium text-gray-700 dark:text-gray-300 bg-white dark:bg-gray-800 border border-gray-300 dark:border-gray-600 rounded-lg hover:bg-gray-50 dark:hover:bg-gray-700 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 transition-colors" title="Switch control set"><!> Switch</a>'),Ge=I('<div class="text-sm text-gray-500 dark:text-gray-400">Loading...</div>');function Fe(v,t){U(t,!1);const e=()=>be(Ce,"$appState",y),[y,o]=ke();q();var m=le(),g=K(m);{var s=l=>{var b=Ie(),d=r(b);Ye(d,{size:16}),P(),a(b),p(l,b)},n=l=>{var b=Ge();p(l,b)};E(g,l=>{e().isConnected?l(s):l(n,!1)})}p(v,m),Y(),o()}var Ze=A("<title> </title>"),Je=A('<svg><!><path d="M17.4141 16L24 9.4141 22.5859 8 16 14.5859 9.4143 8 8 9.4141 14.5859 16 8 22.5859 9.4143 24 16 17.4141 22.5859 24 24 22.5859 17.4141 16z"></path></svg>');function Ke(v,t){const e=H(t,["children","$$slots","$$events","$$legacy"]),y=H(e,["size","title"]);U(t,!1);const o=L(),m=L();let g=C(t,"size",8,16),s=C(t,"title",8,void 0);S(()=>(_(e),_(s())),()=>{h(o,e["aria-label"]||e["aria-labelledby"]||s())}),S(()=>(i(o),_(e)),()=>{h(m,{"aria-hidden":i(o)?void 0:!0,role:i(o)?"img":void 0,focusable:Number(e.tabindex)===0?!0:void 0})}),X(),q();var n=Je();ee(n,()=>({xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 32 32",fill:"currentColor",preserveAspectRatio:"xMidYMid meet",width:g(),height:g(),...i(m),...y}));var l=r(n);{var b=d=>{var c=Ze(),k=r(c,!0);a(c),O(()=>N(k,s())),p(d,c)};E(l,d=>{s()&&d(b)})}P(),a(n),p(v,n),Y()}function qe(v,t){v.target===v.currentTarget&&t()}var We=(v,t)=>v.key==="Escape"&&t(),Qe=v=>v.stopPropagation(),Xe=I("<option> </option>"),et=I(`<div class="fixed inset-0 bg-gray-700 dark:bg-gray-900 bg-opacity-50 dark:bg-opacity-75 overflow-y-auto h-full w-full z-50 flex items-center justify-center p-4" role="dialog" aria-modal="true" tabindex="-1"><div class="bg-white dark:bg-gray-800 rounded-lg shadow-xl p-6 w-full max-w-md mx-auto" role="document"><div class="flex items-center justify-between mb-4"><h2 class="text-xl font-semibold text-gray-900 dark:text-white"> </h2> <button class="text-gray-400 dark:text-gray-500 hover:text-gray-600 dark:hover:text-gray-300" aria-label="Close dialog"><!></button></div> <div class="mb-6"><p class="text-sm text-gray-600 dark:text-gray-400 mb-4">Choose which column should contain the mappings data:</p> <div class="space-y-2"><label for="column-select" class="block text-sm font-medium text-gray-700 dark:text-gray-300">Mappings Column</label> <select id="column-select" class="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md shadow-sm bg-white dark:bg-gray-700 text-gray-900 dark:text-white focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500"></select></div> <div class="mt-3 p-3 bg-blue-50 dark:bg-blue-900/20 rounded-md"><p class="text-xs text-blue-600 dark:text-blue-400"><strong>Note:</strong> Mappings data will be formatted as "status: description..." in the
|
|
2
2
|
selected column.</p></div></div> <div class="flex justify-end space-x-3"><button class="px-4 py-2 text-sm font-medium text-gray-700 dark:text-gray-300 bg-white dark:bg-gray-800 border border-gray-300 dark:border-gray-600 rounded-lg hover:bg-gray-50 dark:hover:bg-gray-700 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 transition-colors">Cancel</button> <button class="px-4 py-2 text-sm font-medium text-white bg-blue-600 hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 rounded-lg transition-colors"> </button></div></div></div>`);function tt(v,t){U(t,!0);let e=C(t,"isOpen",15),y=C(t,"columnHeaders",19,()=>[]),o=C(t,"defaultColumn",3,"Mappings");const m=ze();let g=ie(we(o()));Ee(()=>{e()&&h(g,o())});function s(z){return e()&&setTimeout(()=>z.focus(),0),{update(D){D&&setTimeout(()=>z.focus(),0)}}}function n(){m("export",{format:t.format,mappingsColumn:i(g)}),e(!1)}function l(){m("cancel"),e(!1)}function b(z){z.key==="Escape"?l():z.key==="Enter"&&n()}var d=le();Se("keydown",Le,b);var c=K(d);{var k=z=>{var D=et();D.__click=[qe,l],D.__keydown=[We,l];var te=r(D);te.__click=[Qe];var ae=r(te),re=r(ae),ue=r(re);a(re);var f=$(re,2);f.__click=l;var x=r(f);Ke(x,{class:"w-6 h-6"}),a(f),a(ae);var u=$(ae,2),M=$(r(u),2),w=$(r(M),2);Te(w,21,y,Be,(j,G)=>{var F=Xe(),ge=r(F,!0);a(F);var de={};O(()=>{N(ge,i(G).label),de!==(de=i(G).value)&&(F.value=(F.__value=i(G).value)??"")}),p(j,F)}),a(w),je(w,(j,G)=>s?.(j),e),He(()=>Ve(w,()=>i(g),j=>h(g,j))),a(M),P(2),a(u);var T=$(u,2),J=r(T);J.__click=l;var W=$(J,2);W.__click=n;var ve=r(W);a(W),a(T),a(te),a(D),O((j,G)=>{N(ue,`Export as ${j??""}`),N(ve,`Export ${G??""}`)},[()=>t.format.toUpperCase(),()=>t.format.toUpperCase()]),p(z,D)};E(c,z=>{e()&&z(k)})}p(v,d),Y()}he(["click","keydown"]);var at=A("<title> </title>"),rt=A('<svg><!><path d="M31 16L24 23 22.59 21.59 28.17 16 22.59 10.41 24 9 31 16zM1 16L8 9 9.41 10.41 3.83 16 9.41 21.59 8 23 1 16z"></path><path d="M5.91 15H26.080000000000002V17H5.91z" transform="rotate(-75 15.996 16)"></path></svg>');function ot(v,t){const e=H(t,["children","$$slots","$$events","$$legacy"]),y=H(e,["size","title"]);U(t,!1);const o=L(),m=L();let g=C(t,"size",8,16),s=C(t,"title",8,void 0);S(()=>(_(e),_(s())),()=>{h(o,e["aria-label"]||e["aria-labelledby"]||s())}),S(()=>(i(o),_(e)),()=>{h(m,{"aria-hidden":i(o)?void 0:!0,role:i(o)?"img":void 0,focusable:Number(e.tabindex)===0?!0:void 0})}),X(),q();var n=rt();ee(n,()=>({xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 32 32",fill:"currentColor",preserveAspectRatio:"xMidYMid meet",width:g(),height:g(),...i(m),...y}));var l=r(n);{var b=d=>{var c=at(),k=r(c,!0);a(c),O(()=>N(k,s())),p(d,c)};E(l,d=>{s()&&d(b)})}P(2),a(n),p(v,n),Y()}var st=A("<title> </title>"),nt=A('<svg><!><path d="M13 21L26.17 21 23.59 23.59 25 25 30 20 25 15 23.59 16.41 26.17 19 13 19 13 21z"></path><path d="M22,14V10a1,1,0,0,0-.29-.71l-7-7A1,1,0,0,0,14,2H4A2,2,0,0,0,2,4V28a2,2,0,0,0,2,2H20a2,2,0,0,0,2-2V26H20v2H4V4h8v6a2,2,0,0,0,2,2h6v2Zm-8-4V4.41L19.59,10Z"></path></svg>');function it(v,t){const e=H(t,["children","$$slots","$$events","$$legacy"]),y=H(e,["size","title"]);U(t,!1);const o=L(),m=L();let g=C(t,"size",8,16),s=C(t,"title",8,void 0);S(()=>(_(e),_(s())),()=>{h(o,e["aria-label"]||e["aria-labelledby"]||s())}),S(()=>(i(o),_(e)),()=>{h(m,{"aria-hidden":i(o)?void 0:!0,role:i(o)?"img":void 0,focusable:Number(e.tabindex)===0?!0:void 0})}),X(),q();var n=nt();ee(n,()=>({xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 32 32",fill:"currentColor",preserveAspectRatio:"xMidYMid meet",width:g(),height:g(),...i(m),...y}));var l=r(n);{var b=d=>{var c=st(),k=r(c,!0);a(c),O(()=>N(k,s())),p(d,c)};E(l,d=>{s()&&d(b)})}P(2),a(n),p(v,n),Y()}var lt=A("<title> </title>"),dt=A('<svg><!><path d="M26 24v4H6V24H4v4H4a2 2 0 002 2H26a2 2 0 002-2h0V24zM26 14L24.59 12.59 17 20.17 17 2 15 2 15 20.17 7.41 12.59 6 14 16 24 26 14z"></path></svg>');function _e(v,t){const e=H(t,["children","$$slots","$$events","$$legacy"]),y=H(e,["size","title"]);U(t,!1);const o=L(),m=L();let g=C(t,"size",8,16),s=C(t,"title",8,void 0);S(()=>(_(e),_(s())),()=>{h(o,e["aria-label"]||e["aria-labelledby"]||s())}),S(()=>(i(o),_(e)),()=>{h(m,{"aria-hidden":i(o)?void 0:!0,role:i(o)?"img":void 0,focusable:Number(e.tabindex)===0?!0:void 0})}),X(),q();var n=dt();ee(n,()=>({xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 32 32",fill:"currentColor",preserveAspectRatio:"xMidYMid meet",width:g(),height:g(),...i(m),...y}));var l=r(n);{var b=d=>{var c=lt(),k=r(c,!0);a(c),O(()=>N(k,s())),p(d,c)};E(l,d=>{s()&&d(b)})}P(),a(n),p(v,n),Y()}var ct=A("<title> </title>"),ut=A('<svg><!><path fill-rule="evenodd" d="M16,2a14,14,0,0,0-4.43,27.28c.7.13,1-.3,1-.67s0-1.21,0-2.38c-3.89.84-4.71-1.88-4.71-1.88A3.71,3.71,0,0,0,6.24,22.3c-1.27-.86.1-.85.1-.85A2.94,2.94,0,0,1,8.48,22.9a3,3,0,0,0,4.08,1.16,2.93,2.93,0,0,1,.88-1.87c-3.1-.36-6.37-1.56-6.37-6.92a5.4,5.4,0,0,1,1.44-3.76,5,5,0,0,1,.14-3.7s1.17-.38,3.85,1.43a13.3,13.3,0,0,1,7,0c2.67-1.81,3.84-1.43,3.84-1.43a5,5,0,0,1,.14,3.7,5.4,5.4,0,0,1,1.44,3.76c0,5.38-3.27,6.56-6.39,6.91a3.33,3.33,0,0,1,.95,2.59c0,1.87,0,3.38,0,3.84s.25.81,1,.67A14,14,0,0,0,16,2Z"></path></svg>');function vt(v,t){const e=H(t,["children","$$slots","$$events","$$legacy"]),y=H(e,["size","title"]);U(t,!1);const o=L(),m=L();let g=C(t,"size",8,16),s=C(t,"title",8,void 0);S(()=>(_(e),_(s())),()=>{h(o,e["aria-label"]||e["aria-labelledby"]||s())}),S(()=>(i(o),_(e)),()=>{h(m,{"aria-hidden":i(o)?void 0:!0,role:i(o)?"img":void 0,focusable:Number(e.tabindex)===0?!0:void 0})}),X(),q();var n=ut();ee(n,()=>({xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 32 32",fill:"currentColor",preserveAspectRatio:"xMidYMid meet",width:g(),height:g(),...i(m),...y}));var l=r(n);{var b=d=>{var c=ct(),k=r(c,!0);a(c),O(()=>N(k,s())),p(d,c)};E(l,d=>{s()&&d(b)})}P(),a(n),p(v,n),Y()}var gt=(v,t)=>t("csv"),ft=(v,t)=>t("excel"),pt=(v,t)=>t("json"),mt=I('<div class="space-y-1 p-1"><button class="w-full text-left px-3 py-2 text-sm rounded-md transition-colors duration-200 text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700"><div class="flex items-center gap-2"><!> <span>Export as CSV</span></div></button> <button class="w-full text-left px-3 py-2 text-sm rounded-md transition-colors duration-200 text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700"><div class="flex items-center gap-2"><!> <span>Export as Excel</span></div></button> <button class="w-full text-left px-3 py-2 text-sm rounded-md transition-colors duration-200 text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700"><div class="flex items-center gap-2"><!> <span>Export as JSON</span></div></button></div>'),bt=I('<div class="flex-1 flex justify-center items-center"><div class="text-center"><div class="animate-spin rounded-full h-12 w-12 border-b-2 border-blue-600 mx-auto mb-4"></div> <p class="text-gray-500 dark:text-gray-400">Switching control set...</p></div></div>'),ht=I('<div class="flex-1 flex justify-center items-center"><div class="text-center"><div class="animate-spin rounded-full h-12 w-12 border-b-2 border-blue-600 mx-auto mb-4"></div> <p class="text-gray-500 dark:text-gray-400"> </p></div></div>'),xt=I('<header class="bg-white dark:bg-gray-900 shadow-sm border-b border-gray-200 dark:border-gray-700 flex-shrink-0"><div class="w-full px-6 lg:px-8"><div class="flex justify-between items-center h-16"><div class="flex items-center"><a href="/" class="flex items-center space-x-3 hover:opacity-80 transition-opacity"><img src="/lula.png" class="h-8 w-8" alt="Lula Logo"/> <div class="flex flex-col"><span class="text-xl font-bold text-gray-900 dark:text-white">Lula</span> <span class="text-xs text-gray-500 dark:text-gray-400 -mt-1">Gitops for Compliance</span></div></a></div> <div class="flex items-center space-x-4"><!> <!> <a class="p-2 text-gray-500 dark:text-gray-400 hover:text-gray-700 dark:hover:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-800 rounded-lg transition-colors" title="Github" href="https://github.com/defenseunicorns/lula" target="_blank"><!></a></div></div></div></header> <div class="flex-1 flex gap-6 p-6 overflow-hidden"><!></div>',1),yt=I('<div class="h-screen flex flex-col"><!></div> <!>',1);function Et(v,t){U(t,!0);const e=()=>be(Ce,"$appState",o),y=()=>be(Re,"$page",o),[o,m]=ke();let g=!1,s=ie(!1),n=ie("csv"),l=ie(we([])),b=ie("Mappings");async function d(){try{if(!e().currentPath){console.error("No current control set path available"),h(l,[{value:"Mappings",label:"Mappings (Default)"}],!0),h(b,"Mappings");return}const x=await fetch("/api/export-column-headers");if(x.ok){const u=await x.json();h(l,u.columnHeaders||[],!0),h(b,u.defaultColumn||"Mappings",!0)}else console.error("Failed to load column headers"),h(l,[{value:"Mappings",label:"Mappings (Default)"}],!0),h(b,"Mappings")}catch(f){console.error("Error loading column headers:",f),h(l,[{value:"Mappings",label:"Mappings (Default)"}],!0),h(b,"Mappings")}}async function c(f){if(f==="json")try{const x=`/api/export-controls?format=${f}`,u=document.createElement("a");u.href=x,u.download="",document.body.appendChild(u),u.click(),document.body.removeChild(u)}catch(x){console.error("Export failed:",x)}else h(n,f,!0),await d(),h(s,!0)}async function k(f){try{const{format:x,mappingsColumn:u}=f.detail,M=`/api/export-controls?format=${x}&mappingsColumn=${encodeURIComponent(u)}`,w=document.createElement("a");w.href=M,w.download="",document.body.appendChild(w),w.click(),document.body.removeChild(w)}catch(x){console.error("Export failed:",x)}}Ae(()=>{ce.connect();let f=null;const x=async()=>{if(g||y().url.pathname==="/setup"||e().isSwitchingControlSet)return;const u=e();if(u.isConnected){if(g=!0,(!u.name||u.name==="Unknown Control Set"||u.id==="unknown"||u.id==="default")&&(!u.controls||u.controls.length===0)){await ce.scanControlSets();const M=await new Promise(w=>{const T=J=>{window.removeEventListener("control-sets-list",T),w(J.detail)};window.addEventListener("control-sets-list",T),setTimeout(()=>{window.removeEventListener("control-sets-list",T),w(null)},2e3)});M&&Array.isArray(M)&&M.length===1?(console.log("Auto-loading single control set:",M[0].path),await ce.switchControlSet(M[0].path)):Pe("/setup")}}else f=window.setTimeout(x,500)};return f=window.setTimeout(x,100),()=>{f&&clearTimeout(f)}}),De(()=>{ce.disconnect()});var z=yt(),D=K(z),te=r(D);{var ae=f=>{var x=xt(),u=K(x),M=r(u),w=r(M),T=$(r(w),2),J=r(T);Fe(J,{});var W=$(J,2);{var ve=R=>{Ne(R,{buttonLabel:"Export",get buttonIcon(){return _e},buttonClass:"inline-flex items-center px-4 py-2 text-sm font-medium text-gray-700 dark:text-gray-300 bg-white dark:bg-gray-800 border border-gray-300 dark:border-gray-600 rounded-lg hover:bg-gray-50 dark:hover:bg-gray-700 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 transition-colors",dropdownClass:"w-48",children:fe=>{var se=mt(),Q=r(se);Q.__click=[gt,c];var V=r(Q),Z=r(V);it(Z,{class:"w-4 h-4"}),P(2),a(V),a(Q);var B=$(Q,2);B.__click=[ft,c];var ne=r(B),pe=r(ne);_e(pe,{class:"w-4 h-4"}),P(2),a(ne),a(B);var me=$(B,2);me.__click=[pt,c];var xe=r(me),Me=r(xe);ot(Me,{class:"w-4 h-4"}),P(2),a(xe),a(me),a(se),p(fe,se)},$$slots:{default:!0}})};E(W,R=>{e().isConnected&&e().controls&&e().controls.length>0&&R(ve)})}var j=$(W,2),G=r(j);vt(G,{class:"w-5 h-5"}),a(j),a(T),a(w),a(M),a(u);var F=$(u,2),ge=r(F);{var de=R=>{var oe=bt();p(R,oe)},$e=R=>{var oe=le(),fe=K(oe);{var se=V=>{var Z=ht(),B=r(Z),ne=$(r(B),2),pe=r(ne,!0);a(ne),a(B),a(Z),O(()=>N(pe,e().isConnected?e().fieldSchema?"Loading controls...":"Loading schema...":"Connecting...")),p(V,Z)},Q=V=>{var Z=le(),B=K(Z);ye(B,()=>t.children),p(V,Z)};E(fe,V=>{!e().isConnected||!e().controls||e().controls.length===0||!e().fieldSchema?V(se):V(Q,!1)},!0)}p(R,oe)};E(ge,R=>{e().isSwitchingControlSet?R(de):R($e,!1)})}a(F),p(f,x)},re=f=>{var x=le(),u=K(x);ye(u,()=>t.children),p(f,x)};E(te,f=>{y().url.pathname!=="/setup"?f(ae):f(re,!1)})}a(D);var ue=$(D,2);tt(ue,{get format(){return i(n)},get columnHeaders(){return i(l)},get defaultColumn(){return i(b)},get isOpen(){return i(s)},set isOpen(f){h(s,f,!0)},$$events:{export:k,cancel:()=>{}}}),p(v,z),Y(),m()}he(["click"]);export{Et as component};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import"../chunks/DsnmJJEf.js";import{i as u}from"../chunks/Cq7PwVfU.js";import{p as h,f as g,a as l,J as v,b as d,e as _,c as s,r as a,s as x,K as o}from"../chunks/DTWPdvjs.js";import{s as $,p}from"../chunks/
|
|
1
|
+
import"../chunks/DsnmJJEf.js";import{i as u}from"../chunks/Cq7PwVfU.js";import{p as h,f as g,a as l,J as v,b as d,e as _,c as s,r as a,s as x,K as o}from"../chunks/DTWPdvjs.js";import{s as $,p}from"../chunks/CayEUOo2.js";const b={get error(){return p.error},get status(){return p.status}};$.updated.check;const i=b;var k=g("<h1> </h1> <p> </p>",1);function q(m,c){h(c,!1),u();var t=k(),r=l(t),n=s(r,!0);a(r);var e=x(r,2),f=s(e,!0);a(e),v(()=>{o(n,i.status),o(f,i.error?.message)}),d(m,t),_()}export{q as component};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import"../chunks/DsnmJJEf.js";import"../chunks/Cq7PwVfU.js";import{f,a as y,b as n,c as t,r,s as w,n as C}from"../chunks/DTWPdvjs.js";import{i as k,s as $,a as D}from"../chunks/BXUi170M.js";import{C as S,a as j,D as L}from"../chunks/
|
|
1
|
+
import"../chunks/DsnmJJEf.js";import"../chunks/Cq7PwVfU.js";import{f,a as y,b as n,c as t,r,s as w,n as C}from"../chunks/DTWPdvjs.js";import{i as k,s as $,a as D}from"../chunks/BXUi170M.js";import{C as S,a as j,D as L}from"../chunks/aIhTG3uO.js";import{s as N}from"../chunks/DOBcdfgj.js";var P=f('<div class=" h-full flex flex-col"><div class="flex-1 flex items-center justify-center p-8"><div class="text-center text-gray-500 dark:text-gray-400"><!> <h3 class="text-xl font-semibold text-gray-900 dark:text-white mb-2">No Control Selected</h3> <p class="text-gray-600 dark:text-gray-400">Select a control from the list to view and edit its details</p></div></div></div>'),q=f('<div class="w-1/2 flex flex-col"><div class="bg-white dark:bg-gray-900 border border-gray-200 dark:border-gray-700 rounded-lg shadow-sm h-full flex flex-col"><!></div></div> <div class="w-1/2 flex flex-col"><!></div>',1);function H(m){const o=()=>D(N,"$selectedControl",x),[x,g]=$();var l=q(),a=y(l),i=t(a),p=t(i);S(p,{}),r(i),r(a);var d=w(a,2),_=t(d);{var h=e=>{j(e,{get control(){return o()}})},b=e=>{var s=P(),c=t(s),v=t(c),u=t(v);L(u,{class:"mx-auto h-16 w-16 mb-4"}),C(4),r(v),r(c),r(s),n(e,s)};k(_,e=>{o()?e(h):e(b,!1)})}r(d),n(m,l),g()}export{H as component};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import"../chunks/DsnmJJEf.js";import{p as S,u as A,d as x,o as B,f as n,a as F,b as i,e as H,c as s,g as N,r as a,s as h,h as P,n as R}from"../chunks/DTWPdvjs.js";import{a as C,i as b,s as U}from"../chunks/BXUi170M.js";import{g as V}from"../chunks/
|
|
1
|
+
import"../chunks/DsnmJJEf.js";import{p as S,u as A,d as x,o as B,f as n,a as F,b as i,e as H,c as s,g as N,r as a,s as h,h as P,n as R}from"../chunks/DTWPdvjs.js";import{a as C,i as b,s as U}from"../chunks/BXUi170M.js";import{g as V}from"../chunks/CayEUOo2.js";import{p as q,s as _}from"../chunks/DOBcdfgj.js";import{C as G,a as J,D as K}from"../chunks/aIhTG3uO.js";import{w}from"../chunks/e7OeeeKP.js";var O=n('<div class="absolute top-4 right-4 z-10"><div class="w-8 h-8 flex items-center justify-center rounded-full bg-blue-100 dark:bg-blue-900/30" title="Loading control..."><svg class="w-5 h-5 text-blue-600 dark:text-blue-400 animate-spin" fill="none" viewBox="0 0 24 24"><circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle><path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path></svg></div></div>'),Q=n('<div class=" h-full flex flex-col"><div class="flex-1 flex items-center justify-center p-8"><div class="text-center text-gray-500 dark:text-gray-400"><!> <h3 class="text-xl font-semibold text-gray-900 dark:text-white mb-2">No Control Selected</h3> <p class="text-gray-600 dark:text-gray-400">Select a control from the list to view and edit its details</p></div></div></div>'),T=n('<div class="w-1/2 flex flex-col"><div class="bg-white dark:bg-gray-900 border border-gray-200 dark:border-gray-700 rounded-lg shadow-sm h-full flex flex-col"><!></div></div> <div class="w-1/2 flex flex-col relative"><!> <!></div>',1);function se(y,k){S(k,!0);const $=()=>C(q,"$page",c),d=()=>C(_,"$selectedControl",c),[c,D]=U();let v="",r=N(!1);A(()=>{const e=$().params.id;if(!e)return;const t=decodeURIComponent(e);t&&t!==v&&w.isConnected()&&(v=t,x(r,!0),w.getControlDetails(t))}),B(()=>{const e=t=>{const o=t.detail;x(r,!1),o?_.set(o):V("/")};return window.addEventListener("control-details",e),()=>{window.removeEventListener("control-details",e)}});var f=T(),l=F(f),p=s(l),L=s(p);G(L,{}),a(p),a(l);var g=h(l,2),m=s(g);{var I=e=>{var t=O();i(e,t)};b(m,e=>{P(r)&&e(I)})}var z=h(m,2);{var j=e=>{J(e,{get control(){return d()}})},E=e=>{var t=Q(),o=s(t),u=s(o),M=s(u);K(M,{class:"mx-auto h-16 w-16 mb-4"}),R(4),a(u),a(o),a(t),i(e,t)};b(z,e=>{d()?e(j):e(E,!1)})}a(g),i(y,f),H(),D()}export{se as component};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import"../chunks/DsnmJJEf.js";import{i as Je}from"../chunks/Cq7PwVfU.js";import{p as Ye,am as Te,d as o,T as k,G as ge,h as e,an as $r,ao as Ve,c as a,n as _e,r as t,b as d,e as We,J as F,K as E,ap as Lr,f as h,s as i,aq as g,a as ye,ar as mr,aj as Me,a3 as De,ak as hr,al as rr,as as yr,k as de,o as ot,W as lt}from"../chunks/DTWPdvjs.js";import{l as tr,p as Ue,i as M,a as st,s as it}from"../chunks/BXUi170M.js";import{a as Nr,s as se,r as Vr,e as ce,b as qe,c as jr,d as _r,i as Cr,f as Sr,w as wr}from"../chunks/e7OeeeKP.js";import{g as nt}from"../chunks/rqvYJuq0.js";function dt(pe){return function(...q){var z=q[0];return z.stopPropagation(),pe?.apply(this,q)}}var vt=Ve("<title> </title>"),ct=Ve('<svg><!><path d="M11 18L12.41 19.41 15 16.83 15 29 17 29 17 16.83 19.59 19.41 21 18 16 13 11 18z"></path><path d="M23.5,22H23V20h.5a4.5,4.5,0,0,0,.36-9L23,11l-.1-.82a7,7,0,0,0-13.88,0L9,11,8.14,11a4.5,4.5,0,0,0,.36,9H9v2H8.5A6.5,6.5,0,0,1,7.2,9.14a9,9,0,0,1,17.6,0A6.5,6.5,0,0,1,23.5,22Z"></path></svg>');function gt(pe,q){const z=tr(q,["children","$$slots","$$events","$$legacy"]),X=tr(z,["size","title"]);Ye(q,!1);const O=k(),L=k();let N=Ue(q,"size",8,16),f=Ue(q,"title",8,void 0);Te(()=>(ge(z),ge(f())),()=>{o(O,z["aria-label"]||z["aria-labelledby"]||f())}),Te(()=>(e(O),ge(z)),()=>{o(L,{"aria-hidden":e(O)?void 0:!0,role:e(O)?"img":void 0,focusable:Number(z.tabindex)===0?!0:void 0})}),$r(),Je();var S=ct();Nr(S,()=>({xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 32 32",fill:"currentColor",preserveAspectRatio:"xMidYMid meet",width:N(),height:N(),...e(L),...X}));var K=a(S);{var re=P=>{var p=vt(),U=a(p,!0);t(p),F(()=>E(U,f())),d(P,p)};M(K,P=>{f()&&P(re)})}_e(2),t(S),d(pe,S),We()}var pt=Ve("<title> </title>"),ut=Ve('<svg><!><path d="M10 6H14V10H10zM18 6H22V10H18zM10 14H14V18H10zM18 14H22V18H18zM10 22H14V26H10zM18 22H22V26H18z"></path></svg>');function kr(pe,q){const z=tr(q,["children","$$slots","$$events","$$legacy"]),X=tr(z,["size","title"]);Ye(q,!1);const O=k(),L=k();let N=Ue(q,"size",8,16),f=Ue(q,"title",8,void 0);Te(()=>(ge(z),ge(f())),()=>{o(O,z["aria-label"]||z["aria-labelledby"]||f())}),Te(()=>(e(O),ge(z)),()=>{o(L,{"aria-hidden":e(O)?void 0:!0,role:e(O)?"img":void 0,focusable:Number(z.tabindex)===0?!0:void 0})}),$r(),Je();var S=ut();Nr(S,()=>({xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 32 32",fill:"currentColor",preserveAspectRatio:"xMidYMid meet",width:N(),height:N(),...e(L),...X}));var K=a(S);{var re=P=>{var p=pt(),U=a(p,!0);t(p),F(()=>E(U,f())),d(P,p)};M(K,P=>{f()&&P(re)})}_e(),t(S),d(pe,S),We()}var bt=h('<div class="p-4 text-sm text-blue-800 rounded-lg bg-blue-50 dark:bg-gray-800 dark:text-blue-400"><div class="flex items-center"><svg class="flex-shrink-0 inline w-4 h-4 mr-3" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="currentColor" viewBox="0 0 20 20"><path d="M10 .5a9.5 9.5 0 1 0 9.5 9.5A9.51 9.51 0 0 0 10 .5ZM9.5 4a1.5 1.5 0 1 1 0 3 1.5 1.5 0 0 1 0-3ZM12 15H8a1 1 0 0 1 0-2h1v-3H8a1 1 0 0 1 0-2h2a1 1 0 0 1 1 1v4h1a1 1 0 0 1 0 2Z"></path></svg> <div><span class="font-medium">File loaded:</span> <div class="mt-1"><span class="font-medium">Sheets:</span> <span class="font-medium">Fields:</span> <span class="font-medium">Controls found:</span> </div></div></div></div>'),ft=h('<div class="p-4 text-sm text-red-800 rounded-lg bg-red-50 dark:bg-gray-800 dark:text-red-400"><div class="flex items-center"><svg class="flex-shrink-0 inline w-4 h-4 mr-3" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="currentColor" viewBox="0 0 20 20"><path d="M10 .5a9.5 9.5 0 1 0 9.5 9.5A9.51 9.51 0 0 0 10 .5ZM9.5 4a1.5 1.5 0 1 1 0 3 1.5 1.5 0 0 1 0-3ZM12 15H8a1 1 0 0 1 0-2h1v-3H8a1 1 0 0 1 0-2h2a1 1 0 0 1 1 1v4h1a1 1 0 0 1 0 2Z"></path></svg> <span> </span></div></div>'),xt=h('<div class="p-4 text-sm text-green-800 rounded-lg bg-green-50 dark:bg-gray-800 dark:text-green-400"><div class="flex items-center"><svg class="flex-shrink-0 inline w-4 h-4 mr-3" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="currentColor" viewBox="0 0 20 20"><path d="M10 .5a9.5 9.5 0 1 0 9.5 9.5A9.51 9.51 0 0 0 10 .5ZM9.5 4a1.5 1.5 0 1 1 0 3 1.5 1.5 0 0 1 0-3ZM12 15H8a1 1 0 0 1 0-2h1v-3H8a1 1 0 0 1 0-2h2a1 1 0 0 1 1 1v4h1a1 1 0 0 1 0 2Z"></path></svg> <span> </span></div></div>'),mt=h("<option> </option>"),ht=h("<option> </option>"),yt=h("<option> </option>"),_t=h('<span class="ml-auto text-xs text-blue-600 dark:text-blue-400">ID</span>'),wt=h('<div draggable="true" role="button" tabindex="0" class="flex items-center px-3 py-2 bg-gray-100 dark:bg-gray-700 text-gray-500 dark:text-gray-400 rounded text-sm cursor-move hover:bg-gray-200 dark:hover:bg-gray-600 transition-colors opacity-75"><svg class="w-3 h-3 mr-2 flex-shrink-0" fill="currentColor" viewBox="0 0 20 20"><path d="M10 6a2 2 0 110-4 2 2 0 010 4zM10 12a2 2 0 110-4 2 2 0 010 4zM10 18a2 2 0 110-4 2 2 0 010 4z"></path></svg> <span class="truncate line-through"> </span> <!></div>'),kt=h('<p class="text-xs text-gray-400 dark:text-gray-500 text-center py-4">No excluded fields</p>'),Ct=h('<div draggable="true" role="button" tabindex="0"><!> <span class="truncate"> </span></div>'),St=h('<p class="text-xs text-gray-400 dark:text-gray-500 text-center py-4">Drop fields here</p>'),$t=h('<div draggable="true" role="button" tabindex="0"><!> <span class="truncate"> </span></div>'),Dt=h('<p class="text-xs text-gray-400 dark:text-gray-500 text-center py-4">Drop fields here</p>'),Mt=h('<div draggable="true" role="button" tabindex="0"><!> <span class="truncate"> </span></div>'),zt=h('<p class="text-xs text-gray-400 dark:text-gray-500 text-center py-4">Drop fields here</p>'),At=h('<div draggable="false" role="button" tabindex="0" class="flex items-center px-3 py-2 bg-orange-100 dark:bg-orange-900/30 text-orange-800 dark:text-orange-300 rounded text-sm hover:bg-orange-200 dark:hover:bg-orange-800/30 transition-colors"><span class="truncate"> </span> <button class="ml-auto text-gray-400 hover:text-red-500 dark:text-gray-500 dark:hover:text-red-400" title="Remove from mappings">×</button></div>'),Ft=h('<div role="region" aria-label="Justification field drop zone"><p class="text-xs text-gray-400 dark:text-gray-500 text-center py-4">Drop fields here</p></div>'),Ot=h('<th class="px-4 py-2"> </th>'),Pt=h('<td class="px-4 py-2"> </td>'),Ht=h('<tr class="bg-white border-b dark:bg-gray-800 dark:border-gray-700"></tr>'),Et=h('<div class="bg-gradient-to-br from-gray-50 to-gray-100 dark:from-gray-800 dark:to-gray-900 rounded-lg p-4 border border-gray-200 dark:border-gray-700"><h3 class="text-lg font-semibold text-gray-900 dark:text-white mb-4">Sample Data Preview</h3> <div class="overflow-x-auto"><table class="w-full text-sm text-left text-gray-500 dark:text-gray-400"><thead class="text-xs text-gray-700 uppercase bg-gray-100 dark:bg-gray-600 dark:text-gray-400"><tr></tr></thead><tbody></tbody></table></div></div>'),It=h('<span class="flex items-center"><svg class="animate-spin -ml-1 mr-3 h-5 w-5 text-white" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24"><circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle><path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path></svg> Importing...</span>'),Tt=h(`<div class="bg-gradient-to-br from-gray-50 to-gray-100 dark:from-gray-800 dark:to-gray-900 rounded-lg p-4 border border-gray-200 dark:border-gray-700"><h3 class="text-lg font-semibold text-gray-900 dark:text-white mb-4">Import Options</h3> <div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-4"><div><label for="controlSetName" class="block mb-2 text-sm font-medium text-gray-900 dark:text-white">Control Set Name <span class="text-red-500">*</span></label> <input type="text" id="controlSetName" placeholder="e.g., NIST 800-53 Rev 4" class="bg-white border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-600 dark:border-gray-500 dark:text-white" required/> <p class="mt-1 text-xs text-gray-500 dark:text-gray-400">This will be used as the display name and folder name</p></div> <div><label for="controlSetDescription" class="block mb-2 text-sm font-medium text-gray-900 dark:text-white">Description</label> <input type="text" id="controlSetDescription" placeholder="Optional description" class="bg-white border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-600 dark:border-gray-500 dark:text-white"/> <p class="mt-1 text-xs text-gray-500 dark:text-gray-400">Brief description of this control set</p></div></div> <div class="grid grid-cols-1 md:grid-cols-2 gap-4"><div><label for="sheet" class="block mb-2 text-sm font-medium text-gray-900 dark:text-white">Sheet</label> <select id="sheet" class="bg-white border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-600 dark:border-gray-500 dark:text-white"></select> <p class="mt-1 text-xs text-gray-500 dark:text-gray-400">Select which worksheet contains your control data</p></div> <div><label for="headerRow" class="block mb-2 text-sm font-medium text-gray-900 dark:text-white">Select Header Row</label> <select id="headerRow" class="bg-white border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-600 dark:border-gray-500 dark:text-white"></select> <p class="mt-1 text-xs text-gray-500 dark:text-gray-400">Select the row containing column headers</p></div> <div><label for="controlIdField" class="block mb-2 text-sm font-medium text-gray-900 dark:text-white">Control ID Field <span class="text-red-500">*</span></label> <select id="controlIdField" required><option disabled>Select Control ID field</option><!></select> <p class="mt-1 text-xs text-gray-500 dark:text-gray-400">Column containing unique control identifiers (e.g., AC-1, SC-7)</p></div></div></div> <div class="bg-gradient-to-br from-gray-50 to-gray-100 dark:from-gray-800 dark:to-gray-900 rounded-lg p-4 border border-gray-200 dark:border-gray-700"><h3 class="text-lg font-semibold text-gray-900 dark:text-white mb-2">Organize Fields</h3> <p class="text-sm text-gray-600 dark:text-gray-400 mb-4">Drag fields to organize them. <strong>Overview fields</strong> will appear as table columns in
|
|
1
|
+
import"../chunks/DsnmJJEf.js";import{i as Je}from"../chunks/Cq7PwVfU.js";import{p as Ye,am as Te,d as o,T as k,G as ge,h as e,an as $r,ao as Ve,c as a,n as _e,r as t,b as d,e as We,J as F,K as E,ap as Lr,f as h,s as i,aq as g,a as ye,ar as mr,aj as Me,a3 as De,ak as hr,al as rr,as as yr,k as de,o as ot,W as lt}from"../chunks/DTWPdvjs.js";import{l as tr,p as Ue,i as M,a as st,s as it}from"../chunks/BXUi170M.js";import{a as Nr,s as se,r as Vr,e as ce,b as qe,c as jr,d as _r,i as Cr,f as Sr,w as wr}from"../chunks/e7OeeeKP.js";import{g as nt}from"../chunks/CayEUOo2.js";function dt(pe){return function(...q){var z=q[0];return z.stopPropagation(),pe?.apply(this,q)}}var vt=Ve("<title> </title>"),ct=Ve('<svg><!><path d="M11 18L12.41 19.41 15 16.83 15 29 17 29 17 16.83 19.59 19.41 21 18 16 13 11 18z"></path><path d="M23.5,22H23V20h.5a4.5,4.5,0,0,0,.36-9L23,11l-.1-.82a7,7,0,0,0-13.88,0L9,11,8.14,11a4.5,4.5,0,0,0,.36,9H9v2H8.5A6.5,6.5,0,0,1,7.2,9.14a9,9,0,0,1,17.6,0A6.5,6.5,0,0,1,23.5,22Z"></path></svg>');function gt(pe,q){const z=tr(q,["children","$$slots","$$events","$$legacy"]),X=tr(z,["size","title"]);Ye(q,!1);const O=k(),L=k();let N=Ue(q,"size",8,16),f=Ue(q,"title",8,void 0);Te(()=>(ge(z),ge(f())),()=>{o(O,z["aria-label"]||z["aria-labelledby"]||f())}),Te(()=>(e(O),ge(z)),()=>{o(L,{"aria-hidden":e(O)?void 0:!0,role:e(O)?"img":void 0,focusable:Number(z.tabindex)===0?!0:void 0})}),$r(),Je();var S=ct();Nr(S,()=>({xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 32 32",fill:"currentColor",preserveAspectRatio:"xMidYMid meet",width:N(),height:N(),...e(L),...X}));var K=a(S);{var re=P=>{var p=vt(),U=a(p,!0);t(p),F(()=>E(U,f())),d(P,p)};M(K,P=>{f()&&P(re)})}_e(2),t(S),d(pe,S),We()}var pt=Ve("<title> </title>"),ut=Ve('<svg><!><path d="M10 6H14V10H10zM18 6H22V10H18zM10 14H14V18H10zM18 14H22V18H18zM10 22H14V26H10zM18 22H22V26H18z"></path></svg>');function kr(pe,q){const z=tr(q,["children","$$slots","$$events","$$legacy"]),X=tr(z,["size","title"]);Ye(q,!1);const O=k(),L=k();let N=Ue(q,"size",8,16),f=Ue(q,"title",8,void 0);Te(()=>(ge(z),ge(f())),()=>{o(O,z["aria-label"]||z["aria-labelledby"]||f())}),Te(()=>(e(O),ge(z)),()=>{o(L,{"aria-hidden":e(O)?void 0:!0,role:e(O)?"img":void 0,focusable:Number(z.tabindex)===0?!0:void 0})}),$r(),Je();var S=ut();Nr(S,()=>({xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 32 32",fill:"currentColor",preserveAspectRatio:"xMidYMid meet",width:N(),height:N(),...e(L),...X}));var K=a(S);{var re=P=>{var p=pt(),U=a(p,!0);t(p),F(()=>E(U,f())),d(P,p)};M(K,P=>{f()&&P(re)})}_e(),t(S),d(pe,S),We()}var bt=h('<div class="p-4 text-sm text-blue-800 rounded-lg bg-blue-50 dark:bg-gray-800 dark:text-blue-400"><div class="flex items-center"><svg class="flex-shrink-0 inline w-4 h-4 mr-3" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="currentColor" viewBox="0 0 20 20"><path d="M10 .5a9.5 9.5 0 1 0 9.5 9.5A9.51 9.51 0 0 0 10 .5ZM9.5 4a1.5 1.5 0 1 1 0 3 1.5 1.5 0 0 1 0-3ZM12 15H8a1 1 0 0 1 0-2h1v-3H8a1 1 0 0 1 0-2h2a1 1 0 0 1 1 1v4h1a1 1 0 0 1 0 2Z"></path></svg> <div><span class="font-medium">File loaded:</span> <div class="mt-1"><span class="font-medium">Sheets:</span> <span class="font-medium">Fields:</span> <span class="font-medium">Controls found:</span> </div></div></div></div>'),ft=h('<div class="p-4 text-sm text-red-800 rounded-lg bg-red-50 dark:bg-gray-800 dark:text-red-400"><div class="flex items-center"><svg class="flex-shrink-0 inline w-4 h-4 mr-3" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="currentColor" viewBox="0 0 20 20"><path d="M10 .5a9.5 9.5 0 1 0 9.5 9.5A9.51 9.51 0 0 0 10 .5ZM9.5 4a1.5 1.5 0 1 1 0 3 1.5 1.5 0 0 1 0-3ZM12 15H8a1 1 0 0 1 0-2h1v-3H8a1 1 0 0 1 0-2h2a1 1 0 0 1 1 1v4h1a1 1 0 0 1 0 2Z"></path></svg> <span> </span></div></div>'),xt=h('<div class="p-4 text-sm text-green-800 rounded-lg bg-green-50 dark:bg-gray-800 dark:text-green-400"><div class="flex items-center"><svg class="flex-shrink-0 inline w-4 h-4 mr-3" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="currentColor" viewBox="0 0 20 20"><path d="M10 .5a9.5 9.5 0 1 0 9.5 9.5A9.51 9.51 0 0 0 10 .5ZM9.5 4a1.5 1.5 0 1 1 0 3 1.5 1.5 0 0 1 0-3ZM12 15H8a1 1 0 0 1 0-2h1v-3H8a1 1 0 0 1 0-2h2a1 1 0 0 1 1 1v4h1a1 1 0 0 1 0 2Z"></path></svg> <span> </span></div></div>'),mt=h("<option> </option>"),ht=h("<option> </option>"),yt=h("<option> </option>"),_t=h('<span class="ml-auto text-xs text-blue-600 dark:text-blue-400">ID</span>'),wt=h('<div draggable="true" role="button" tabindex="0" class="flex items-center px-3 py-2 bg-gray-100 dark:bg-gray-700 text-gray-500 dark:text-gray-400 rounded text-sm cursor-move hover:bg-gray-200 dark:hover:bg-gray-600 transition-colors opacity-75"><svg class="w-3 h-3 mr-2 flex-shrink-0" fill="currentColor" viewBox="0 0 20 20"><path d="M10 6a2 2 0 110-4 2 2 0 010 4zM10 12a2 2 0 110-4 2 2 0 010 4zM10 18a2 2 0 110-4 2 2 0 010 4z"></path></svg> <span class="truncate line-through"> </span> <!></div>'),kt=h('<p class="text-xs text-gray-400 dark:text-gray-500 text-center py-4">No excluded fields</p>'),Ct=h('<div draggable="true" role="button" tabindex="0"><!> <span class="truncate"> </span></div>'),St=h('<p class="text-xs text-gray-400 dark:text-gray-500 text-center py-4">Drop fields here</p>'),$t=h('<div draggable="true" role="button" tabindex="0"><!> <span class="truncate"> </span></div>'),Dt=h('<p class="text-xs text-gray-400 dark:text-gray-500 text-center py-4">Drop fields here</p>'),Mt=h('<div draggable="true" role="button" tabindex="0"><!> <span class="truncate"> </span></div>'),zt=h('<p class="text-xs text-gray-400 dark:text-gray-500 text-center py-4">Drop fields here</p>'),At=h('<div draggable="false" role="button" tabindex="0" class="flex items-center px-3 py-2 bg-orange-100 dark:bg-orange-900/30 text-orange-800 dark:text-orange-300 rounded text-sm hover:bg-orange-200 dark:hover:bg-orange-800/30 transition-colors"><span class="truncate"> </span> <button class="ml-auto text-gray-400 hover:text-red-500 dark:text-gray-500 dark:hover:text-red-400" title="Remove from mappings">×</button></div>'),Ft=h('<div role="region" aria-label="Justification field drop zone"><p class="text-xs text-gray-400 dark:text-gray-500 text-center py-4">Drop fields here</p></div>'),Ot=h('<th class="px-4 py-2"> </th>'),Pt=h('<td class="px-4 py-2"> </td>'),Ht=h('<tr class="bg-white border-b dark:bg-gray-800 dark:border-gray-700"></tr>'),Et=h('<div class="bg-gradient-to-br from-gray-50 to-gray-100 dark:from-gray-800 dark:to-gray-900 rounded-lg p-4 border border-gray-200 dark:border-gray-700"><h3 class="text-lg font-semibold text-gray-900 dark:text-white mb-4">Sample Data Preview</h3> <div class="overflow-x-auto"><table class="w-full text-sm text-left text-gray-500 dark:text-gray-400"><thead class="text-xs text-gray-700 uppercase bg-gray-100 dark:bg-gray-600 dark:text-gray-400"><tr></tr></thead><tbody></tbody></table></div></div>'),It=h('<span class="flex items-center"><svg class="animate-spin -ml-1 mr-3 h-5 w-5 text-white" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24"><circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle><path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path></svg> Importing...</span>'),Tt=h(`<div class="bg-gradient-to-br from-gray-50 to-gray-100 dark:from-gray-800 dark:to-gray-900 rounded-lg p-4 border border-gray-200 dark:border-gray-700"><h3 class="text-lg font-semibold text-gray-900 dark:text-white mb-4">Import Options</h3> <div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-4"><div><label for="controlSetName" class="block mb-2 text-sm font-medium text-gray-900 dark:text-white">Control Set Name <span class="text-red-500">*</span></label> <input type="text" id="controlSetName" placeholder="e.g., NIST 800-53 Rev 4" class="bg-white border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-600 dark:border-gray-500 dark:text-white" required/> <p class="mt-1 text-xs text-gray-500 dark:text-gray-400">This will be used as the display name and folder name</p></div> <div><label for="controlSetDescription" class="block mb-2 text-sm font-medium text-gray-900 dark:text-white">Description</label> <input type="text" id="controlSetDescription" placeholder="Optional description" class="bg-white border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-600 dark:border-gray-500 dark:text-white"/> <p class="mt-1 text-xs text-gray-500 dark:text-gray-400">Brief description of this control set</p></div></div> <div class="grid grid-cols-1 md:grid-cols-2 gap-4"><div><label for="sheet" class="block mb-2 text-sm font-medium text-gray-900 dark:text-white">Sheet</label> <select id="sheet" class="bg-white border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-600 dark:border-gray-500 dark:text-white"></select> <p class="mt-1 text-xs text-gray-500 dark:text-gray-400">Select which worksheet contains your control data</p></div> <div><label for="headerRow" class="block mb-2 text-sm font-medium text-gray-900 dark:text-white">Select Header Row</label> <select id="headerRow" class="bg-white border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-600 dark:border-gray-500 dark:text-white"></select> <p class="mt-1 text-xs text-gray-500 dark:text-gray-400">Select the row containing column headers</p></div> <div><label for="controlIdField" class="block mb-2 text-sm font-medium text-gray-900 dark:text-white">Control ID Field <span class="text-red-500">*</span></label> <select id="controlIdField" required><option disabled>Select Control ID field</option><!></select> <p class="mt-1 text-xs text-gray-500 dark:text-gray-400">Column containing unique control identifiers (e.g., AC-1, SC-7)</p></div></div></div> <div class="bg-gradient-to-br from-gray-50 to-gray-100 dark:from-gray-800 dark:to-gray-900 rounded-lg p-4 border border-gray-200 dark:border-gray-700"><h3 class="text-lg font-semibold text-gray-900 dark:text-white mb-2">Organize Fields</h3> <p class="text-sm text-gray-600 dark:text-gray-400 mb-4">Drag fields to organize them. <strong>Overview fields</strong> will appear as table columns in
|
|
2
2
|
the controls list.</p> <div class="grid grid-cols-1 lg:grid-cols-5 gap-4"><div class="border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-800"><div class="p-3 border-b border-gray-200 dark:border-gray-700 bg-gray-50 dark:bg-gray-700 rounded-t-lg"><h4 class="text-sm font-semibold text-gray-700 dark:text-gray-300">Excluded Fields</h4> <p class="text-xs text-gray-500 dark:text-gray-400 mt-1">Not imported</p></div> <div role="region" aria-label="Excluded fields drop zone"><!> <!></div></div> <div class="border border-blue-300 dark:border-blue-700 rounded-lg bg-white dark:bg-gray-800"><div class="p-3 border-b border-blue-200 dark:border-blue-800 bg-blue-50 dark:bg-blue-900/20 rounded-t-lg"><h4 class="text-sm font-semibold text-blue-700 dark:text-blue-300">Overview Tab</h4> <p class="text-xs text-blue-600 dark:text-blue-400 mt-1">Shows in details & table columns</p></div> <div role="region" aria-label="Overview tab drop zone"><!> <!></div></div> <div class="border border-green-300 dark:border-green-700 rounded-lg bg-white dark:bg-gray-800"><div class="p-3 border-b border-green-200 dark:border-green-800 bg-green-50 dark:bg-green-900/20 rounded-t-lg"><h4 class="text-sm font-semibold text-green-700 dark:text-green-300">Implementation Tab</h4> <p class="text-xs text-green-600 dark:text-green-400 mt-1">Status & compliance</p></div> <div role="region" aria-label="Implementation tab drop zone"><!> <!></div></div> <div class="border border-purple-300 dark:border-purple-700 rounded-lg bg-white dark:bg-gray-800"><div class="p-3 border-b border-purple-200 dark:border-purple-800 bg-purple-50 dark:bg-purple-900/20 rounded-t-lg"><h4 class="text-sm font-semibold text-purple-700 dark:text-purple-300">Custom Tab</h4> <p class="text-xs text-purple-600 dark:text-purple-400 mt-1">Additional fields</p></div> <div role="region" aria-label="Custom fields drop zone"><!> <!></div></div> <div class="border border-orange-300 dark:border-orange-700 rounded-lg bg-white dark:bg-gray-800"><div class="p-3 border-b border-orange-200 dark:border-orange-800 bg-orange-50 dark:bg-orange-900/20 rounded-t-lg"><h4 class="text-sm font-semibold text-orange-700 dark:text-orange-300">Mappings Tab</h4> <p class="text-xs text-orange-600 dark:text-orange-400 mt-1">Pre-populate justification for a control mapping</p></div> <div role="region" aria-label="Justifications tab drop zone"><div class="space-y-2"><!></div></div></div></div></div> <!> <div class="flex justify-center"><button class="px-5 py-2.5 text-white bg-blue-600 hover:bg-blue-700 focus:ring-4 focus:ring-blue-300 font-medium rounded-lg text-sm disabled:opacity-50 disabled:cursor-not-allowed"><!></button></div>`,1),Vt=h('<div class="space-y-6"><div role="button" tabindex="0" class="relative"><label><div class="flex flex-col items-center justify-center pt-5 pb-6"><!> <p class="mb-2 text-sm text-gray-500 dark:text-gray-400"><span class="font-semibold">Click to upload</span> or drag and drop</p> <p class="text-xs text-gray-500 dark:text-gray-400">XLSX, XLS or CSV files</p></div> <input type="file" class="hidden" accept=".xlsx,.xls,.csv"/></label></div> <!> <!> <!> <!></div>');function jt(pe,q){Ye(q,!1);const z=Lr();let X=k(null),O=k(""),L=k(""),N=k([]),f=k([]),S=k([]),K=k(0),re=k([]),P=k([]),p=k(new Map),U=k(1),V=k(""),fe=k(""),J=k(""),G=k(!1),Q=k(""),ue=k(""),we=k(!1),te=k(!1),$=k(null),B=k(null),ae=k(null);function ke(){o(f,[]),o(S,[]),o(K,0),e(p).clear(),o(p,new Map),o(P,[]),o(V,""),o(Q,""),o(ue,""),o($,null),o(B,null),o(ae,null)}function u(l){l.preventDefault(),o(te,!0)}function b(){o(te,!1)}function D(l){l.preventDefault(),o(te,!1);const n=l.dataTransfer?.files;n&&n.length>0&&I(n[0])}function T(l){const n=l.target;n.files&&n.files.length>0&&I(n.files[0])}async function I(l){ke(),o(O,l.name),o(X,l),o(Q,""),o(G,!0),o(fe,e(O).replace(/\.[^.]+$/,"").replace(/[-_]/g," ")),o(J,`Imported from ${e(O)}`);try{const n=new FormData;n.append("file",l);const y=await fetch("/api/parse-excel",{method:"POST",body:n});if(!y.ok){const w=await y.json();throw new Error(w.error||"Failed to parse file")}const _=await y.json();o(N,_.sheets||[]),o(L,_.selectedSheet||e(N)[0]),o(re,_.rowPreviews||[]),e(re).length>0&&e(U)===1&&o(U,e(re)[0].row),await Z(),o(we,!0)}catch(n){o(Q,"Error reading file: "+n.message)}finally{o(G,!1)}}async function Z(){if(!(!e(X)||!e(L))){o(G,!0),e(p).clear(),o(p,new Map),o(V,"");try{const l=new FormData;l.append("file",e(X)),l.append("sheetName",e(L)),l.append("headerRow",e(U).toString());const n=await fetch("/api/parse-excel-sheet",{method:"POST",body:l});if(!n.ok){const _=await n.json();throw new Error(_.error||"Failed to parse sheet")}const y=await n.json();if(o(f,y.fields||[]),o(S,y.sampleData||[]),o(K,y.controlCount||0),e(f).forEach((_,w)=>{const v=_.toLowerCase();let H="custom",R="text";v.includes("implementation")||v.includes("status")||v.includes("narrative")||v.includes("guidance")?H="implementation":(v.includes("id")||v.includes("title")||v.includes("family")||v.includes("cci")||v.includes("control")||v.includes("acronym"))&&(H="overview"),v.includes("description")||v.includes("narrative")||v.includes("guidance")||v.includes("statement")?R="textarea":v.includes("status")||v.includes("type")||v.includes("designation")?R="select":v.includes("date")?R="date":(v.includes("count")||v.includes("number"))&&(R="number"),e(p).set(_,{originalName:_,tab:H,displayOrder:w,fieldType:R,required:v.includes("id")||v.includes("title")})}),o(p,e(p)),e(V)&&!e(f).includes(e(V))&&o(V,""),!e(V)&&e(f).includes("AP Acronym")){const _=!e(S).length||e(S).every(ee=>!ee["AP Acronym"]||String(ee["AP Acronym"]).length<25),w=e(S).map(ee=>ee["AP Acronym"]).filter(ee=>ee!=null&&ee!==""&&String(ee).trim()!==""),v=new Set(w),H=!w.length||v.size===w.length,R=w.length>0;_&&H&&R&&o(V,"AP Acronym")}}catch(l){o(Q,"Error loading sheet data: "+l.message)}finally{o(G,!1)}}}function ve(l){if(!l)return l;let n=l.trim().replace(/\r?\n/g," ").replace(/\s+/g," ").trim();return je(n)}function je(l){return l.replace(/\W+/g," ").split(/ |\s/).map(n=>n.toLowerCase()).join("-")}function xe(l,n){o($,n),l.dataTransfer&&(l.dataTransfer.effectAllowed="move",l.dataTransfer.setData("text/plain",n))}function oe(){o($,null),o(B,null),o(ae,null)}function C(l,n){l.preventDefault(),o(B,n),l.dataTransfer&&(l.dataTransfer.dropEffect="move")}function ie(){o(B,null)}function ne(l,n,y){if(l.preventDefault(),e($)&&e(p).has(e($))){const _=e(p).get(e($));if(n==="mappings")e(P).includes(e($))||o(P,[...e(P),e($)]);else{if(_.tab=n,y!==void 0&&n!==null){const v=Array.from(e(p).entries()).filter(([H,R])=>R.tab===n).sort((H,R)=>H[1].displayOrder-R[1].displayOrder).filter(([H])=>H!==e($));v.splice(y,0,[e($),_]),v.forEach(([H,R],ee)=>{R.displayOrder=ee,e(p).set(H,R)})}else if(n!==null){const w=Math.max(0,...Array.from(e(p).values()).filter(v=>v.tab===n).map(v=>v.displayOrder));_.displayOrder=w+1}e(p).set(e($),_),o(p,e(p))}}o($,null),o(B,null)}function ze(l,n){l.preventDefault(),l.stopPropagation(),o(ae,n)}function Ce(){o(ae,null)}function Se(l,n,y){if(l.preventDefault(),l.stopPropagation(),e($)&&e($)!==n){const w=Array.from(e(p).entries()).filter(([v,H])=>H.tab===y).sort((v,H)=>v[1].displayOrder-H[1].displayOrder).findIndex(([v])=>v===n);w!==-1&&ne(l,y,w)}o(ae,null)}async function Le(){if(!(!e(X)||!e(O))){if(!e(V)){o(Q,"Please select a Control ID field before importing"),o(ue,"");return}if(!e(fe)||e(fe).trim()===""){o(Q,"Please enter a Control Set Name before importing"),o(ue,"");return}o(G,!0),o(Q,""),o(ue,"");try{const l=new FormData;l.append("file",e(X),e(O)),l.append("controlIdField",e(V)),l.append("startRow",e(U).toString()),l.append("namingConvention","kebab-case"),l.append("skipEmpty","true"),l.append("skipEmptyRows","true"),l.append("controlSetName",e(fe)||e(O).replace(/\.[^.]+$/,"")),l.append("controlSetDescription",e(J)||`Imported from ${e(O)}`);const n=Array.from(e(p).entries()).filter(([w,v])=>v.tab!==null).map(([w,v])=>({fieldName:ve(w),...v}));l.append("fieldSchema",JSON.stringify(n)),l.append("justificationFields",JSON.stringify(e(P).map(w=>ve(w))));const y=await fetch("/api/import-spreadsheet",{method:"POST",body:l});if(!y.ok){const w=await y.json();throw new Error(w.error||"Import failed")}const _=await y.json();o(ue,`Successfully imported ${_.controlCount} controls into ${_.families.length} families`),z("created",{path:_.outputDir})}catch(l){o(Q,"Error importing spreadsheet: "+l.message)}finally{o(G,!1)}}}Je();var Ne=Vt(),me=a(Ne),Be=a(me),Ae=a(Be),ar=a(Ae);gt(ar,{class:"w-8 h-8 mb-4 text-gray-500 dark:text-gray-400"}),_e(4),t(Ae);var Xe=i(Ae,2);t(Be),t(me);var Fe=i(me,2);{var or=l=>{var n=bt(),y=a(n),_=i(a(y),2),w=i(a(_)),v=i(w),H=i(a(v)),R=i(H,2),ee=i(R,2);t(v),t(_),t(y),t(n),F(()=>{E(w,` ${e(O)??""} `),E(H,` ${e(N).length??""} | `),E(R,` ${e(f).length??""} | `),E(ee,` ${e(K)??""}`)}),d(l,n)};M(Fe,l=>{e(O)&&l(or)})}var Ke=i(Fe,2);{var lr=l=>{var n=ft(),y=a(n),_=i(a(y),2),w=a(_,!0);t(_),t(y),t(n),F(()=>E(w,e(Q))),d(l,n)};M(Ke,l=>{e(Q)&&l(lr)})}var Ze=i(Ke,2);{var sr=l=>{var n=xt(),y=a(n),_=i(a(y),2),w=a(_,!0);t(_),t(y),t(n),F(()=>E(w,e(ue))),d(l,n)};M(Ze,l=>{e(ue)&&l(sr)})}var ir=i(Ze,2);{var nr=l=>{var n=Tt(),y=ye(n),_=i(a(y),2),w=a(_),v=i(a(w),2);Vr(v),_e(2),t(w);var H=i(w,2),R=i(a(H),2);Vr(R),_e(2),t(H),t(_);var ee=i(_,2),dr=a(ee),Ge=i(a(dr),2);F(()=>{e(L),mr(()=>{e(N)})}),ce(Ge,5,()=>e(N),r=>r,(r,s)=>{var x=mt(),m=a(x,!0);t(x);var c={};F(()=>{E(m,e(s)),c!==(c=e(s))&&(x.value=(x.__value=e(s))??"")}),d(r,x)}),t(Ge),_e(2),t(dr);var vr=i(dr,2),Qe=i(a(vr),2);F(()=>{e(U),mr(()=>{e(re)})}),ce(Qe,5,()=>e(re),r=>r.row,(r,s)=>{var x=ht(),m=a(x);t(x);var c={};F(()=>{E(m,`Row ${e(s).row??""}: ${e(s).preview??""}`),c!==(c=e(s).row)&&(x.value=(x.__value=e(s).row)??"")}),d(r,x)}),t(Qe),_e(2),t(vr);var Dr=i(vr,2),er=i(a(Dr),2);F(()=>{e(V),mr(()=>{e(f),e(S)})});var cr=a(er);cr.value=cr.__value="";var Br=i(cr);ce(Br,1,()=>e(f),r=>r,(r,s)=>{const x=De(()=>e(S).length>0&&e(S)[0][e(s)]?String(e(S)[0][e(s)]).slice(0,30):""),m=De(()=>!e(S).length||e(S).every(le=>!le[e(s)]||String(le[e(s)]).length<25)),c=De(()=>e(S).map(le=>le[e(s)]).filter(le=>le!=null&&le!==""&&String(le).trim()!=="")),Y=De(()=>new Set(e(c))),W=De(()=>!e(c).length||e(Y).size===e(c).length),j=De(()=>e(c).length>0);var A=Me(),be=ye(A);{var $e=le=>{var he=yt(),xr=a(he);t(he);var Tr={};F(()=>{E(xr,`${e(s)??""}${e(x)?` (e.g., ${e(x)})`:""}`),Tr!==(Tr=e(s))&&(he.value=(he.__value=e(s))??"")}),d(le,he)};M(be,le=>{e(m)&&e(W)&&e(j)&&le($e)})}d(r,A)}),t(er),_e(2),t(Dr),t(ee),t(y);var gr=i(y,2),Mr=i(a(gr),4),pr=a(Mr),Oe=i(a(pr),2),zr=a(Oe);ce(zr,1,()=>e(f).filter(r=>!e(p).get(r)||e(p).get(r)?.tab===null),r=>r,(r,s)=>{var x=wt(),m=i(a(x),2),c=a(m,!0);t(m);var Y=i(m,2);{var W=j=>{var A=_t();d(j,A)};M(Y,j=>{e(s)===e(V)&&j(W)})}t(x),F(()=>{qe(x,"aria-label",`Drag ${e(s)??""} field`),E(c,e(s))}),g("dragstart",x,j=>xe(j,e(s))),g("dragend",x,oe),d(r,x)});var Zr=i(zr,2);{var Rr=r=>{var s=kt();d(r,s)};M(Zr,r=>{e(f).filter(s=>!e(p).get(s)||e(p).get(s)?.tab===null).length===0&&r(Rr)})}t(Oe),t(pr);var ur=i(pr,2),Pe=i(a(ur),2),Ar=a(Pe);ce(Ar,3,()=>Array.from(e(p).entries()).filter(([r,s])=>s.tab==="overview").sort((r,s)=>r[1].displayOrder-s[1].displayOrder),([r,s])=>r,(r,s)=>{var x=hr(()=>yr(e(s),2));let m=()=>e(x)[0];var c=Ct(),Y=a(c);kr(Y,{class:"w-3 h-3 mr-2 flex-shrink-0"});var W=i(Y,2),j=a(W,!0);t(W),t(c),F(()=>{qe(c,"aria-label",`${m()??""} field in Overview tab`),se(c,1,`flex items-center px-3 py-2 bg-blue-100 dark:bg-blue-900/30 text-blue-800 dark:text-blue-300 rounded text-sm cursor-move hover:bg-blue-200 dark:hover:bg-blue-800/30 transition-colors
|
|
3
3
|
${e(ae)===m()&&e($)!==m()?"border-t-2 border-blue-500":""}`),E(j,m())}),g("dragstart",c,A=>xe(A,m())),g("dragend",c,oe),g("dragover",c,A=>ze(A,m())),g("dragleave",c,Ce),g("drop",c,A=>Se(A,m(),"overview")),d(r,c)});var qr=i(Ar,2);{var Ur=r=>{var s=St();d(r,s)};M(qr,r=>{Array.from(e(p).entries()).filter(([s,x])=>x.tab==="overview").length===0&&r(Ur)})}t(Pe),t(ur);var br=i(ur,2),He=i(a(br),2),Fr=a(He);ce(Fr,3,()=>Array.from(e(p).entries()).filter(([r,s])=>s.tab==="implementation").sort((r,s)=>r[1].displayOrder-s[1].displayOrder),([r,s])=>r,(r,s)=>{var x=hr(()=>yr(e(s),2));let m=()=>e(x)[0];var c=$t(),Y=a(c);kr(Y,{class:"w-3 h-3 mr-2 flex-shrink-0"});var W=i(Y,2),j=a(W,!0);t(W),t(c),F(()=>{qe(c,"aria-label",`${m()??""} field in Implementation tab`),se(c,1,`flex items-center px-3 py-2 bg-green-100 dark:bg-green-900/30 text-green-800 dark:text-green-300 rounded text-sm cursor-move hover:bg-green-200 dark:hover:bg-green-800/30 transition-colors
|
|
4
4
|
${e(ae)===m()&&e($)!==m()?"border-t-2 border-green-500":""}`),E(j,m())}),g("dragstart",c,A=>xe(A,m())),g("dragend",c,oe),g("dragover",c,A=>ze(A,m())),g("dragleave",c,Ce),g("drop",c,A=>Se(A,m(),"implementation")),d(r,c)});var Jr=i(Fr,2);{var Yr=r=>{var s=Dt();d(r,s)};M(Jr,r=>{Array.from(e(p).entries()).filter(([s,x])=>x.tab==="implementation").length===0&&r(Yr)})}t(He),t(br);var fr=i(br,2),Ee=i(a(fr),2),Or=a(Ee);ce(Or,3,()=>Array.from(e(p).entries()).filter(([r,s])=>s.tab==="custom").sort((r,s)=>r[1].displayOrder-s[1].displayOrder),([r,s])=>r,(r,s)=>{var x=hr(()=>yr(e(s),2));let m=()=>e(x)[0];var c=Mt(),Y=a(c);kr(Y,{class:"w-3 h-3 mr-2 flex-shrink-0"});var W=i(Y,2),j=a(W,!0);t(W),t(c),F(()=>{qe(c,"aria-label",`${m()??""} field in Custom tab`),se(c,1,`flex items-center px-3 py-2 bg-purple-100 dark:bg-purple-900/30 text-purple-800 dark:text-purple-300 rounded text-sm cursor-move hover:bg-purple-200 dark:hover:bg-purple-800/30 transition-colors
|
package/dist/_app/version.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":"
|
|
1
|
+
{"version":"1759784127347"}
|
|
@@ -107,18 +107,6 @@ function getChangedBlocks(oldText, newText) {
|
|
|
107
107
|
}
|
|
108
108
|
return changed;
|
|
109
109
|
}
|
|
110
|
-
function getRemovedBlocks(oldText, newText) {
|
|
111
|
-
const oldBlocks = extractMapBlocks(oldText);
|
|
112
|
-
const newBlocks = extractMapBlocks(newText);
|
|
113
|
-
const removed = [];
|
|
114
|
-
for (const oldBlock of oldBlocks) {
|
|
115
|
-
const newMatch = newBlocks.find((b) => b.uuid === oldBlock.uuid);
|
|
116
|
-
if (!newMatch) {
|
|
117
|
-
removed.push(oldBlock);
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
return removed;
|
|
121
|
-
}
|
|
122
110
|
function containsLulaAnnotations(text) {
|
|
123
111
|
const lines = text.split("\n");
|
|
124
112
|
return lines.some((line) => line.includes("@lulaStart") || line.includes("@lulaEnd"));
|
|
@@ -199,7 +187,6 @@ Please review whether:
|
|
|
199
187
|
fetchRawFileViaAPI({ octokit, owner, repo, path: file.filename, ref: prBranch })
|
|
200
188
|
]);
|
|
201
189
|
const changedBlocks = getChangedBlocks(oldText, newText);
|
|
202
|
-
const removedBlocks = getRemovedBlocks(oldText, newText);
|
|
203
190
|
for (const block of changedBlocks) {
|
|
204
191
|
console.log(`Commenting regarding \`${file.filename}\`.`);
|
|
205
192
|
leavePost = true;
|
|
@@ -215,43 +202,6 @@ Please review whether:
|
|
|
215
202
|
> **uuid**-\`${block.uuid}\`
|
|
216
203
|
**sha256** \`${blockSha256}\`
|
|
217
204
|
|
|
218
|
-
`;
|
|
219
|
-
}
|
|
220
|
-
if (removedBlocks.length > 0) {
|
|
221
|
-
leavePost = true;
|
|
222
|
-
console.log(`Found removed annotations in \`${file.filename}\`.`);
|
|
223
|
-
commentBody += `
|
|
224
|
-
|
|
225
|
-
**Compliance Warning: Lula annotations were removed from \`${file.filename}\`**
|
|
226
|
-
|
|
227
|
-
`;
|
|
228
|
-
commentBody += `The following compliance annotation blocks were present in the original file but are missing in the updated version:
|
|
229
|
-
|
|
230
|
-
`;
|
|
231
|
-
commentBody += `| File | Original Lines | UUID |
|
|
232
|
-
`;
|
|
233
|
-
commentBody += `| ---- | -------------- | ---- |
|
|
234
|
-
`;
|
|
235
|
-
for (const block of removedBlocks) {
|
|
236
|
-
const oldBlockText = oldText.split("\n").slice(block.startLine, block.endLine).join("\n");
|
|
237
|
-
const blockSha256 = createHash("sha256").update(oldBlockText).digest("hex");
|
|
238
|
-
commentBody += `| \`${file.filename}\` | \`${block.startLine + 1}\u2013${block.endLine}\` | \`${block.uuid}\` |
|
|
239
|
-
`;
|
|
240
|
-
commentBody += `> **sha256** \`${blockSha256}\`
|
|
241
|
-
|
|
242
|
-
`;
|
|
243
|
-
}
|
|
244
|
-
commentBody += `Please review whether:
|
|
245
|
-
`;
|
|
246
|
-
commentBody += `- The removal of these compliance annotations is intentional
|
|
247
|
-
`;
|
|
248
|
-
commentBody += `- Alternative compliance measures have been implemented
|
|
249
|
-
`;
|
|
250
|
-
commentBody += `- The compliance coverage is still adequate
|
|
251
|
-
|
|
252
|
-
`;
|
|
253
|
-
commentBody += `---
|
|
254
|
-
|
|
255
205
|
`;
|
|
256
206
|
}
|
|
257
207
|
} catch (err) {
|
|
@@ -355,7 +305,8 @@ async function dismissOldReviews({
|
|
|
355
305
|
if (!reviews.length) break;
|
|
356
306
|
for (const r of reviews) {
|
|
357
307
|
const hasSignature = (r.body ?? "").includes(LULA_SIGNATURE);
|
|
358
|
-
|
|
308
|
+
const isAlreadyDismissed = r.state === "DISMISSED";
|
|
309
|
+
if (hasSignature && !isAlreadyDismissed) {
|
|
359
310
|
await octokit.pulls.dismissReview({
|
|
360
311
|
owner,
|
|
361
312
|
repo,
|
|
@@ -380,6 +331,5 @@ export {
|
|
|
380
331
|
fetchRawFileViaAPI,
|
|
381
332
|
getChangedBlocks,
|
|
382
333
|
getPRContext,
|
|
383
|
-
getRemovedBlocks,
|
|
384
334
|
postFinding
|
|
385
335
|
};
|
package/dist/index.html
CHANGED
|
@@ -6,10 +6,10 @@
|
|
|
6
6
|
<link rel="icon" href="/lula.png" />
|
|
7
7
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
8
8
|
|
|
9
|
-
<link rel="modulepreload" href="/_app/immutable/entry/start.
|
|
10
|
-
<link rel="modulepreload" href="/_app/immutable/chunks/
|
|
9
|
+
<link rel="modulepreload" href="/_app/immutable/entry/start.CJGnwt1e.js">
|
|
10
|
+
<link rel="modulepreload" href="/_app/immutable/chunks/CayEUOo2.js">
|
|
11
11
|
<link rel="modulepreload" href="/_app/immutable/chunks/DTWPdvjs.js">
|
|
12
|
-
<link rel="modulepreload" href="/_app/immutable/entry/app.
|
|
12
|
+
<link rel="modulepreload" href="/_app/immutable/entry/app.B7_zLkkx.js">
|
|
13
13
|
<link rel="modulepreload" href="/_app/immutable/chunks/DsnmJJEf.js">
|
|
14
14
|
<link rel="modulepreload" href="/_app/immutable/chunks/BXUi170M.js">
|
|
15
15
|
<link rel="modulepreload" href="/_app/immutable/chunks/WlyXjfrM.js">
|
|
@@ -19,15 +19,15 @@
|
|
|
19
19
|
<div style="display: contents">
|
|
20
20
|
<script>
|
|
21
21
|
{
|
|
22
|
-
|
|
22
|
+
__sveltekit_jl6ehc = {
|
|
23
23
|
base: ""
|
|
24
24
|
};
|
|
25
25
|
|
|
26
26
|
const element = document.currentScript.parentElement;
|
|
27
27
|
|
|
28
28
|
Promise.all([
|
|
29
|
-
import("/_app/immutable/entry/start.
|
|
30
|
-
import("/_app/immutable/entry/app.
|
|
29
|
+
import("/_app/immutable/entry/start.CJGnwt1e.js"),
|
|
30
|
+
import("/_app/immutable/entry/app.B7_zLkkx.js")
|
|
31
31
|
]).then(([kit, app]) => {
|
|
32
32
|
kit.start(app, element);
|
|
33
33
|
});
|
package/dist/index.js
CHANGED
|
@@ -5628,18 +5628,6 @@ function getChangedBlocks(oldText, newText) {
|
|
|
5628
5628
|
}
|
|
5629
5629
|
return changed;
|
|
5630
5630
|
}
|
|
5631
|
-
function getRemovedBlocks(oldText, newText) {
|
|
5632
|
-
const oldBlocks = extractMapBlocks(oldText);
|
|
5633
|
-
const newBlocks = extractMapBlocks(newText);
|
|
5634
|
-
const removed = [];
|
|
5635
|
-
for (const oldBlock of oldBlocks) {
|
|
5636
|
-
const newMatch = newBlocks.find((b) => b.uuid === oldBlock.uuid);
|
|
5637
|
-
if (!newMatch) {
|
|
5638
|
-
removed.push(oldBlock);
|
|
5639
|
-
}
|
|
5640
|
-
}
|
|
5641
|
-
return removed;
|
|
5642
|
-
}
|
|
5643
5631
|
function containsLulaAnnotations(text) {
|
|
5644
5632
|
const lines = text.split("\n");
|
|
5645
5633
|
return lines.some((line) => line.includes("@lulaStart") || line.includes("@lulaEnd"));
|
|
@@ -5720,7 +5708,6 @@ Please review whether:
|
|
|
5720
5708
|
fetchRawFileViaAPI({ octokit, owner, repo, path: file.filename, ref: prBranch })
|
|
5721
5709
|
]);
|
|
5722
5710
|
const changedBlocks = getChangedBlocks(oldText, newText);
|
|
5723
|
-
const removedBlocks = getRemovedBlocks(oldText, newText);
|
|
5724
5711
|
for (const block of changedBlocks) {
|
|
5725
5712
|
console.log(`Commenting regarding \`${file.filename}\`.`);
|
|
5726
5713
|
leavePost = true;
|
|
@@ -5736,43 +5723,6 @@ Please review whether:
|
|
|
5736
5723
|
> **uuid**-\`${block.uuid}\`
|
|
5737
5724
|
**sha256** \`${blockSha256}\`
|
|
5738
5725
|
|
|
5739
|
-
`;
|
|
5740
|
-
}
|
|
5741
|
-
if (removedBlocks.length > 0) {
|
|
5742
|
-
leavePost = true;
|
|
5743
|
-
console.log(`Found removed annotations in \`${file.filename}\`.`);
|
|
5744
|
-
commentBody += `
|
|
5745
|
-
|
|
5746
|
-
**Compliance Warning: Lula annotations were removed from \`${file.filename}\`**
|
|
5747
|
-
|
|
5748
|
-
`;
|
|
5749
|
-
commentBody += `The following compliance annotation blocks were present in the original file but are missing in the updated version:
|
|
5750
|
-
|
|
5751
|
-
`;
|
|
5752
|
-
commentBody += `| File | Original Lines | UUID |
|
|
5753
|
-
`;
|
|
5754
|
-
commentBody += `| ---- | -------------- | ---- |
|
|
5755
|
-
`;
|
|
5756
|
-
for (const block of removedBlocks) {
|
|
5757
|
-
const oldBlockText = oldText.split("\n").slice(block.startLine, block.endLine).join("\n");
|
|
5758
|
-
const blockSha256 = createHash2("sha256").update(oldBlockText).digest("hex");
|
|
5759
|
-
commentBody += `| \`${file.filename}\` | \`${block.startLine + 1}\u2013${block.endLine}\` | \`${block.uuid}\` |
|
|
5760
|
-
`;
|
|
5761
|
-
commentBody += `> **sha256** \`${blockSha256}\`
|
|
5762
|
-
|
|
5763
|
-
`;
|
|
5764
|
-
}
|
|
5765
|
-
commentBody += `Please review whether:
|
|
5766
|
-
`;
|
|
5767
|
-
commentBody += `- The removal of these compliance annotations is intentional
|
|
5768
|
-
`;
|
|
5769
|
-
commentBody += `- Alternative compliance measures have been implemented
|
|
5770
|
-
`;
|
|
5771
|
-
commentBody += `- The compliance coverage is still adequate
|
|
5772
|
-
|
|
5773
|
-
`;
|
|
5774
|
-
commentBody += `---
|
|
5775
|
-
|
|
5776
5726
|
`;
|
|
5777
5727
|
}
|
|
5778
5728
|
} catch (err) {
|
|
@@ -5876,7 +5826,8 @@ async function dismissOldReviews({
|
|
|
5876
5826
|
if (!reviews.length) break;
|
|
5877
5827
|
for (const r of reviews) {
|
|
5878
5828
|
const hasSignature = (r.body ?? "").includes(LULA_SIGNATURE);
|
|
5879
|
-
|
|
5829
|
+
const isAlreadyDismissed = r.state === "DISMISSED";
|
|
5830
|
+
if (hasSignature && !isAlreadyDismissed) {
|
|
5880
5831
|
await octokit.pulls.dismissReview({
|
|
5881
5832
|
owner,
|
|
5882
5833
|
repo,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "lula2",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
4
4
|
"description": "A tool for managing compliance as code in your GitHub repositories.",
|
|
5
5
|
"bin": {
|
|
6
6
|
"lula2": "./dist/lula2"
|
|
@@ -33,6 +33,25 @@
|
|
|
33
33
|
"!dist/**/*.test.js*",
|
|
34
34
|
"!dist/**/*.test.d.ts*"
|
|
35
35
|
],
|
|
36
|
+
"scripts": {
|
|
37
|
+
"dev": "vite dev --port 5173",
|
|
38
|
+
"dev:api": "tsx --watch index.ts --debug ui --port 3000 --no-open-browser",
|
|
39
|
+
"dev:full": "concurrently \"npm run dev:api\" \"npm run dev\"",
|
|
40
|
+
"build": "npm run build:svelte && npm run build:cli && npm run postbuild:cli",
|
|
41
|
+
"build:svelte": "vite build",
|
|
42
|
+
"build:cli": "esbuild index.ts cli/**/*.ts --bundle --platform=node --target=node22 --format=esm --outdir=dist --external:express --external:commander --external:js-yaml --external:yaml --external:isomorphic-git --external:glob --external:open --external:ws --external:cors --external:multer --external:@octokit/rest --external:undici --external:exceljs --external:csv-parse",
|
|
43
|
+
"postbuild:cli": "cp cli-wrapper.mjs dist/lula2 && chmod +x dist/lula2",
|
|
44
|
+
"preview": "vite preview",
|
|
45
|
+
"prepare": "svelte-kit sync || echo ''",
|
|
46
|
+
"check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json && tsc --noEmit",
|
|
47
|
+
"check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
|
|
48
|
+
"format": "prettier --write 'src/**/*.{ts,js,svelte}' 'cli/**/*.ts' 'index.ts' 'tests/**/*.ts'",
|
|
49
|
+
"format:check": "prettier --check 'src/**/*.{ts,js,svelte}' 'cli/**/*.ts' 'index.ts' 'tests/**/*.ts'",
|
|
50
|
+
"lint": "prettier --check 'src/**/*.{ts,js,svelte}' 'cli/**/*.ts' 'index.ts' 'tests/**/*.ts' && eslint src cli",
|
|
51
|
+
"test": "npm run test:unit -- --run --coverage",
|
|
52
|
+
"test:integration": "vitest --config integration/vitest.config.integration.ts",
|
|
53
|
+
"test:unit": "vitest"
|
|
54
|
+
},
|
|
36
55
|
"dependencies": {
|
|
37
56
|
"@octokit/rest": "^22.0.0",
|
|
38
57
|
"@types/ws": "^8.18.1",
|
|
@@ -105,23 +124,5 @@
|
|
|
105
124
|
"main",
|
|
106
125
|
"next"
|
|
107
126
|
]
|
|
108
|
-
},
|
|
109
|
-
"scripts": {
|
|
110
|
-
"dev": "vite dev --port 5173",
|
|
111
|
-
"dev:api": "tsx --watch index.ts --debug ui --port 3000 --no-open-browser",
|
|
112
|
-
"dev:full": "concurrently \"npm run dev:api\" \"npm run dev\"",
|
|
113
|
-
"build": "npm run build:svelte && npm run build:cli && npm run postbuild:cli",
|
|
114
|
-
"build:svelte": "vite build",
|
|
115
|
-
"build:cli": "esbuild index.ts cli/**/*.ts --bundle --platform=node --target=node22 --format=esm --outdir=dist --external:express --external:commander --external:js-yaml --external:yaml --external:isomorphic-git --external:glob --external:open --external:ws --external:cors --external:multer --external:@octokit/rest --external:undici --external:exceljs --external:csv-parse",
|
|
116
|
-
"postbuild:cli": "cp cli-wrapper.mjs dist/lula2 && chmod +x dist/lula2",
|
|
117
|
-
"preview": "vite preview",
|
|
118
|
-
"check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json && tsc --noEmit",
|
|
119
|
-
"check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
|
|
120
|
-
"format": "prettier --write 'src/**/*.{ts,js,svelte}' 'cli/**/*.ts' 'index.ts' 'tests/**/*.ts'",
|
|
121
|
-
"format:check": "prettier --check 'src/**/*.{ts,js,svelte}' 'cli/**/*.ts' 'index.ts' 'tests/**/*.ts'",
|
|
122
|
-
"lint": "prettier --check 'src/**/*.{ts,js,svelte}' 'cli/**/*.ts' 'index.ts' 'tests/**/*.ts' && eslint src cli",
|
|
123
|
-
"test": "npm run test:unit -- --run --coverage",
|
|
124
|
-
"test:integration": "vitest --config integration/vitest.config.integration.ts",
|
|
125
|
-
"test:unit": "vitest"
|
|
126
127
|
}
|
|
127
|
-
}
|
|
128
|
+
}
|
|
@@ -119,15 +119,66 @@
|
|
|
119
119
|
results = results.filter((control) => {
|
|
120
120
|
// Control must match all filters
|
|
121
121
|
return $activeFilters.every(filter => {
|
|
122
|
+
// Handle mapping-related fields specially
|
|
123
|
+
if (filter.fieldName === 'has_mappings') {
|
|
124
|
+
const hasMappings = control.mappings && control.mappings.length > 0;
|
|
125
|
+
const filterValue = getFilterValue(filter.value);
|
|
126
|
+
switch (filter.operator) {
|
|
127
|
+
case 'equals':
|
|
128
|
+
return hasMappings === (filterValue === 'true' || filterValue === true);
|
|
129
|
+
case 'not_equals':
|
|
130
|
+
return hasMappings !== (filterValue === 'true' || filterValue === true);
|
|
131
|
+
case 'exists':
|
|
132
|
+
return hasMappings;
|
|
133
|
+
case 'not_exists':
|
|
134
|
+
return !hasMappings;
|
|
135
|
+
default:
|
|
136
|
+
return true;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
if (filter.fieldName === 'mapping_status') {
|
|
141
|
+
if (!control.mappings || control.mappings.length === 0) {
|
|
142
|
+
return filter.operator === 'not_exists';
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
const filterValue = getFilterValue(filter.value);
|
|
146
|
+
const hasStatus = control.mappings.some(mapping => {
|
|
147
|
+
switch (filter.operator) {
|
|
148
|
+
case 'equals':
|
|
149
|
+
return mapping.status === filterValue;
|
|
150
|
+
case 'not_equals':
|
|
151
|
+
return mapping.status !== filterValue;
|
|
152
|
+
case 'includes':
|
|
153
|
+
return (typeof mapping.status === 'string' ? mapping.status.toLowerCase() : '').includes(String(filterValue).toLowerCase());
|
|
154
|
+
case 'not_includes':
|
|
155
|
+
return !(typeof mapping.status === 'string' ? mapping.status.toLowerCase() : '').includes(String(filterValue).toLowerCase());
|
|
156
|
+
default:
|
|
157
|
+
return true;
|
|
158
|
+
}
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
switch (filter.operator) {
|
|
162
|
+
case 'exists':
|
|
163
|
+
return control.mappings.some(m => m.status !== undefined && m.status !== null);
|
|
164
|
+
case 'not_exists':
|
|
165
|
+
return !control.mappings.some(m => m.status !== undefined && m.status !== null);
|
|
166
|
+
default:
|
|
167
|
+
return hasStatus;
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
// Handle regular control fields
|
|
122
172
|
const dynamicControl = control as Record<string, unknown>;
|
|
123
173
|
const fieldValue = dynamicControl[filter.fieldName];
|
|
174
|
+
const filterValue = getFilterValue(filter.value);
|
|
124
175
|
|
|
125
176
|
switch (filter.operator) {
|
|
126
177
|
case 'equals':
|
|
127
|
-
return fieldValue ===
|
|
178
|
+
return fieldValue === filterValue;
|
|
128
179
|
|
|
129
180
|
case 'not_equals':
|
|
130
|
-
return fieldValue !==
|
|
181
|
+
return fieldValue !== filterValue;
|
|
131
182
|
|
|
132
183
|
case 'exists':
|
|
133
184
|
return fieldValue !== undefined && fieldValue !== null && fieldValue !== '';
|
|
@@ -137,20 +188,20 @@
|
|
|
137
188
|
|
|
138
189
|
case 'includes':
|
|
139
190
|
if (typeof fieldValue === 'string') {
|
|
140
|
-
return fieldValue.toLowerCase().includes(String(
|
|
191
|
+
return fieldValue.toLowerCase().includes(String(filterValue).toLowerCase());
|
|
141
192
|
} else if (Array.isArray(fieldValue)) {
|
|
142
193
|
return fieldValue.some(item =>
|
|
143
|
-
String(item).toLowerCase().includes(String(
|
|
194
|
+
String(item).toLowerCase().includes(String(filterValue).toLowerCase())
|
|
144
195
|
);
|
|
145
196
|
}
|
|
146
197
|
return false;
|
|
147
198
|
|
|
148
199
|
case 'not_includes':
|
|
149
200
|
if (typeof fieldValue === 'string') {
|
|
150
|
-
return !fieldValue.toLowerCase().includes(String(
|
|
201
|
+
return !fieldValue.toLowerCase().includes(String(filterValue).toLowerCase());
|
|
151
202
|
} else if (Array.isArray(fieldValue)) {
|
|
152
203
|
return !fieldValue.some(item =>
|
|
153
|
-
String(item).toLowerCase().includes(String(
|
|
204
|
+
String(item).toLowerCase().includes(String(filterValue).toLowerCase())
|
|
154
205
|
);
|
|
155
206
|
}
|
|
156
207
|
return true;
|
|
@@ -198,6 +249,28 @@
|
|
|
198
249
|
return 'No description available';
|
|
199
250
|
}
|
|
200
251
|
|
|
252
|
+
function formatFilterValue(value: any): string {
|
|
253
|
+
if (value === null || value === undefined) {
|
|
254
|
+
return '';
|
|
255
|
+
}
|
|
256
|
+
if (typeof value === 'object') {
|
|
257
|
+
if (Array.isArray(value)) {
|
|
258
|
+
return value.join(', ');
|
|
259
|
+
}
|
|
260
|
+
if ('value' in value) {
|
|
261
|
+
return String((value as any).value);
|
|
262
|
+
}
|
|
263
|
+
return JSON.stringify(value);
|
|
264
|
+
}
|
|
265
|
+
return String(value);
|
|
266
|
+
}
|
|
267
|
+
function getFilterValue(filterValue: any): any {
|
|
268
|
+
if (typeof filterValue === 'object' && filterValue !== null && 'value' in filterValue) {
|
|
269
|
+
return filterValue.value;
|
|
270
|
+
}
|
|
271
|
+
return filterValue;
|
|
272
|
+
}
|
|
273
|
+
|
|
201
274
|
// Get truncation length based on field type
|
|
202
275
|
function getTruncationLength(field: FieldSchema | undefined): number {
|
|
203
276
|
if (field?.ui_type === 'textarea' || field?.ui_type === 'long_text') {
|
|
@@ -258,11 +331,11 @@
|
|
|
258
331
|
{#if filter.operator === 'exists' || filter.operator === 'not_exists'}
|
|
259
332
|
<span>{getOperatorLabel(filter.operator).toLowerCase()}</span>
|
|
260
333
|
{:else if filter.operator === 'equals'}
|
|
261
|
-
<span>= {filter.value}</span>
|
|
334
|
+
<span>= {formatFilterValue(filter.value)}</span>
|
|
262
335
|
{:else if filter.operator === 'not_equals'}
|
|
263
|
-
<span>≠ {filter.value}</span>
|
|
336
|
+
<span>≠ {formatFilterValue(filter.value)}</span>
|
|
264
337
|
{:else}
|
|
265
|
-
<span>{getOperatorLabel(filter.operator).toLowerCase()} "{filter.value}"</span>
|
|
338
|
+
<span>{getOperatorLabel(filter.operator).toLowerCase()} "{formatFilterValue(filter.value)}"</span>
|
|
266
339
|
{/if}
|
|
267
340
|
<button
|
|
268
341
|
onclick={() => complianceStore.removeFilter(index)}
|