mirror of
https://github.com/bunny-lab-io/Borealis.git
synced 2026-02-06 08:40:32 -07:00
417 lines
397 KiB
JavaScript
417 lines
397 KiB
JavaScript
import{r as s,j as e,a as es}from"./react-CcTm0Ooe.js";import{a as Oo}from"./react-dom-BH-0RoFc.js";/* empty css *//* empty css *//* empty css */import{u as dt,a as mt,H as De,P as ze,b as zn,c as Po,d as Eo,R as lo,B as Mo,e as Do}from"./@reactflow-Cn6m1kzj.js";/* empty css */import{I as nt,S as zo,T as st,a as co,B as Z,b as Fo,D as Ze,c as et,d as rt,e as $t,f as tt,g as Ie,M as Et,h as fe,i as m,A as as,j as is,k as $,E as ls,l as cs,m as Lo,n as $o,K as uo,o as Ys,p as Uo,J as Wo,C as Vo,F as Ho,G as Go,q as qo,r as po,U as Jo,s as Yo,L as Ko,t as tn,u as Us,v as ps,w as ts,x as Fs,P as Xo,y as fo,z as Qo,R as Zo,H as Fn,W as kn,N as Ln,O as ho,Q as er,V as tr,X as sr,Y as nr,Z as or,_ as In,$ as Qe,a0 as mo,a1 as Rt,a2 as Bt,a3 as Ue,a4 as Q,a5 as At,a6 as Tt,a7 as Rn,a8 as Nt,a9 as Ls,aa as bs,ab as Ht,ac as Gt,ad as wt,ae as Mt,af as vs,ag as ys,ah as Nn,ai as Tn,aj as on,ak as rr,al as ar,am as ir,an as lr,ao as cr,ap as dr,aq as ur,ar as Ss,as as $s,at as xo,au as pr,av as fr,aw as os,ax as go,ay as hr,az as mr,aA as xr,aB as gr,aC as br,aD as yr,aE as jr,aF as wr,aG as vr,aH as Ks,aI as Sr,aJ as Cr,aK as _r,aL as kr,aM as Ir,aN as Rr,aO as Nr,aP as Tr,aQ as ds,aR as rn,aS as bo,aT as yo,aU as Ar,aV as Br,aW as Or,aX as Pr,aY as $n,aZ as Un,a_ as Er,a$ as Mr,b0 as Dr,b1 as zr,b2 as Fr,b3 as Lr,b4 as $r,b5 as Ur,b6 as Wr,b7 as Vr}from"./@mui-DuExnnZV.js";import{P as qt}from"./prismjs-DnVqcinS.js";import{R as Hr}from"./react-resizable-Dz87KGdU.js";import"./reactflow-CapO1AcK.js";import{S as jo}from"./react-color-Cj5ADBFD.js";import"./tinycolor2-Begke6kS.js";import{R as Gr}from"./react-markdown-DU1c7IVQ.js";import{A as An}from"./ag-grid-react-CI8oSmtp.js";import{M as Bn,y as On,z as Pn}from"./ag-grid-community-3ngxp7D-.js";import{_ as En}from"./react-simple-code-editor-VgXKD24u.js";import{d as Xs}from"./dayjs-DS_BHG0d.js";import{l as qr}from"./socket.io-client-CDVIIGn8.js";import"./@icons-BDZNmjFP.js";import"./scheduler-BmyE5rk0.js";import"./d3-transition-CT0P4Hy_.js";import"./d3-dispatch-kxCwF96_.js";import"./d3-timer-DdKHrDhs.js";import"./d3-interpolate-B6xYU604.js";import"./d3-color-9lF95FHy.js";import"./d3-selection-DSeOx27A.js";import"./d3-ease-DRPgKoYJ.js";import"./d3-zoom-C9ulvfG5.js";import"./d3-drag-CKshNLwO.js";import"./classcat-RvS1aOr8.js";import"./zustand-C9Nr5JuV.js";import"./use-sync-external-store-iOpSvWgw.js";import"./clsx-ZPAKJJud.js";import"./@emotion-DhAReQXH.js";import"./hoist-non-react-statics-DQogQWOa.js";import"./@babel-BtohYyOd.js";import"./stylis-DDa9OTMq.js";import"./reselect-CSPtcQt5.js";import"./react-transition-group-Ds4sJYaS.js";import"./dom-helpers-D0mFdbeO.js";import"./react-is-D_P3mdcN.js";import"./prop-types-CWaErGoZ.js";import"./@popperjs-CMBiYTiD.js";import"./reactcss-DwOrawQG.js";import"./lodash-BBjvixB0.js";import"./lodash-es-DN0AVw_E.js";import"./material-colors-7R66pBqW.js";import"./property-information-CI8MXcm-.js";import"./unist-util-visit-SwKB2sUE.js";import"./unist-util-visit-parents-MnEmTlHn.js";import"./unist-util-is-DiTsIWAy.js";import"./hast-util-whitespace-D1ONPEmv.js";import"./space-separated-tokens-DD3iYX1K.js";import"./comma-separated-tokens-xMQ5YY98.js";import"./style-to-object-pmhRd-Nr.js";import"./inline-style-parser-D--Rb2MU.js";import"./unified-DVSGJAo0.js";import"./bail-FqpXQuLt.js";import"./is-buffer-Boa4a7IC.js";import"./extend-B7yenLig.js";import"./is-plain-obj-C1gvLhAf.js";import"./trough-B_b8ryxu.js";import"./vfile-BlpNzP9y.js";import"./vfile-message-BOGBuebs.js";import"./unist-util-stringify-position-Ch_qCilz.js";import"./remark-parse-CQxuRO-h.js";import"./mdast-util-from-markdown-CLAsVoWb.js";import"./micromark-CTBPIv-_.js";import"./micromark-util-combine-extensions-Bka6Sc1c.js";import"./micromark-util-chunked-DrRIdSP-.js";import"./micromark-factory-space-x2vfxbz5.js";import"./micromark-util-character-Bcm1tP9o.js";import"./micromark-core-commonmark-AH8VCgT7.js";import"./micromark-util-classify-character-Cq7Fg3xE.js";import"./micromark-util-resolve-all-PQCKh0dx.js";import"./decode-named-character-reference-C3-224fz.js";import"./micromark-util-subtokenize-QwsxNXk2.js";import"./micromark-factory-destination-CypD_wgM.js";import"./micromark-factory-label-CRHH4ZHP.js";import"./micromark-factory-title-B7kCBvC9.js";import"./micromark-factory-whitespace-B322EA6O.js";import"./micromark-util-normalize-identifier-C9ANKk3v.js";import"./micromark-util-html-tag-name-DbKNfynz.js";import"./micromark-util-decode-numeric-character-reference-DRnCnno4.js";import"./micromark-util-decode-string-DJl8Y_PO.js";import"./mdast-util-to-string-C_aolqmU.js";import"./remark-rehype-BJ4RwZvz.js";import"./mdast-util-to-hast-Dxh8Xa5R.js";import"./micromark-util-sanitize-uri-nvkIJkgW.js";import"./unist-util-position-KiAvrw8y.js";import"./trim-lines-D8znQY54.js";import"./mdast-util-definitions-CfSXY7bG.js";import"./unist-util-generated-CMz5gPdA.js";import"./engine.io-client-C44f3zIw.js";import"./engine.io-parser-BiEtp6m2.js";import"./@socket.io-Dkula2eQ.js";import"./socket.io-parser-BBkuslX-.js";(function(){const t=document.createElement("link").relList;if(t&&t.supports&&t.supports("modulepreload"))return;for(const d of document.querySelectorAll('link[rel="modulepreload"]'))a(d);new MutationObserver(d=>{for(const u of d)if(u.type==="childList")for(const r of u.addedNodes)r.tagName==="LINK"&&r.rel==="modulepreload"&&a(r)}).observe(document,{childList:!0,subtree:!0});function o(d){const u={};return d.integrity&&(u.integrity=d.integrity),d.referrerPolicy&&(u.referrerPolicy=d.referrerPolicy),d.crossOrigin==="use-credentials"?u.credentials="include":d.crossOrigin==="anonymous"?u.credentials="omit":u.credentials="same-origin",u}function a(d){if(d.ep)return;d.ep=!0;const u=o(d);fetch(d.href,u)}})();const Jr=({id:n,data:t})=>{const{getNodes:o,setNodes:a}=dt(),d=mt(w=>w.edges),[u,r]=s.useState({}),[i,c]=s.useState([]),[p,l]=s.useState(!1),[h,f]=s.useState({}),y=s.useRef([]),C=s.useRef({host:"",mode:"",agentId:"",siteId:""}),I=t!=null&&t.agent_site_id?String(t.agent_site_id):"",k=(t==null?void 0:t.agent_host)||"",v=((t==null?void 0:t.agent_mode)||"currentuser").toString().toLowerCase()==="system"?"system":"currentuser",j=(t==null?void 0:t.agent_id)||"",B=s.useMemo(()=>{if(!u||typeof u!="object")return{};const w={};return Object.entries(u).forEach(([W,F])=>{if(!F||typeof F!="object"||(F.status||"").toString().toLowerCase()==="offline")return;const ee=(F.hostname||F.agent_hostname||"").trim()||"unknown",Re=(F.service_mode||"").toString().toLowerCase()==="system"?"system":"currentuser";w[ee]||(w[ee]={currentuser:null,system:null}),w[ee][Re]={agent_id:W,status:F.status||"offline",last_seen:F.last_seen||0,info:F}}),w},[u]),R=s.useMemo(()=>new Intl.Collator(void 0,{sensitivity:"base",numeric:!0}),[]),x=s.useMemo(()=>Object.entries(B).map(([W,F])=>{const te=[F.currentuser,F.system].filter(Boolean);if(!te.length)return null;const ee=W,be=Math.max(...te.map(Re=>Re.last_seen||0));return{host:W,label:ee,contexts:F,latest:be}}).filter(Boolean).sort((W,F)=>R.compare(W.host,F.host)),[B,R]);s.useEffect(()=>{const w=()=>{fetch("/api/agents").then(F=>F.json()).then(r).catch(()=>{})};w();const W=setInterval(w,1e4);return()=>clearInterval(W)},[]),s.useEffect(()=>{(()=>{fetch("/api/sites").then(W=>W.json()).then(W=>{const F=Array.isArray(W==null?void 0:W.sites)?W.sites:[];c(F)}).catch(()=>c([]))})()},[]),s.useEffect(()=>{const w=x.map(({host:F})=>F).filter(Boolean);if(!w.length){f({});return}const W=w.map(encodeURIComponent).join(",");fetch(`/api/sites/device_map?hostnames=${W}`).then(F=>F.json()).then(F=>{const te=F!=null&&F.mapping&&typeof F.mapping=="object"?F.mapping:{};f(te)}).catch(()=>f({}))},[x]);const S=s.useMemo(()=>I?x.filter(({host:w})=>{const W=h[w];return!W||typeof W.site_id>"u"||W.site_id===null?!1:String(W.site_id)===I}):x,[x,I,h]);s.useEffect(()=>{if(I||!k)return;const w=h[k];if(!w||typeof w.site_id>"u"||w.site_id===null)return;const W=String(w.site_id);a(F=>F.map(te=>te.id===n?{...te,data:{...te.data,agent_site_id:W}}:te))},[k,I,h,n,a]),s.useEffect(()=>{if(!(!k||S.some(W=>W.host===k))){if(j&&u[j]){const W=u[j],F=((W==null?void 0:W.hostname)||(W==null?void 0:W.agent_hostname)||"").trim()||"unknown";if(S.some(ee=>ee.host===F)&&F&&F!==k){a(ee=>ee.map(be=>be.id===n?{...be,data:{...be.data,agent_host:F}}:be));return}}a(W=>W.map(F=>F.id===n?{...F,data:{...F.data,agent_host:"",agent_id:"",agent_mode:"currentuser"}}:F))}},[S,k,j,u,n,a]);const z=s.useMemo(()=>{const w=Array.isArray(i)?[...i]:[];w.sort((F,te)=>((F==null?void 0:F.name)||"").localeCompare((te==null?void 0:te.name)||"",void 0,{sensitivity:"base"}));const W=w.map(F=>({value:String(F.id),label:F.name||`Site ${F.id}`}));return[{value:"",label:"All Sites"},...W]},[i]),E=s.useMemo(()=>{const w=S.map(({host:W,label:F})=>({value:W,label:F}));return[{value:"",label:"-- Select --"},...w]},[S]),U=k?B[k]:null,X=s.useMemo(()=>[{value:"currentuser",label:"CURRENTUSER (Screen Capture / Macros)",disabled:!(U!=null&&U.currentuser)},{value:"system",label:"SYSTEM (Scripts)",disabled:!(U!=null&&U.system)}],[U]);s.useEffect(()=>{a(w=>w.map(W=>W.id===n?{...W,data:{...W.data,siteOptions:z,hostOptions:E,modeOptions:X}}:W))},[n,a,z,E,X]),s.useEffect(()=>{var F,te;if(!k){(j||v!=="currentuser")&&a(ee=>ee.map(be=>be.id===n?{...be,data:{...be.data,agent_id:"",agent_mode:"currentuser"}}:be));return}const w=B[k];if(!w){(j||v!=="currentuser")&&a(ee=>ee.map(be=>be.id===n?{...be,data:{...be.data,agent_id:"",agent_mode:"currentuser"}}:be));return}if(!w[v]){const ee=w.currentuser?"currentuser":w.system?"system":"currentuser",be=((F=w[ee])==null?void 0:F.agent_id)||"";(ee!==v||be!==j)&&a(Re=>Re.map(Ae=>Ae.id===n?{...Ae,data:{...Ae.data,agent_mode:ee,agent_id:be}}:Ae));return}const W=((te=w[v])==null?void 0:te.agent_id)||"";W!==j&&a(ee=>ee.map(be=>be.id===n?{...be,data:{...be.data,agent_id:W}}:be))},[k,v,B,j,n,a]),s.useEffect(()=>{const w=C.current;if(!(w.host!==k||w.mode!==v||w.agentId!==j||w.siteId!==I))return;w.agentId&&(w.agentId!==j||w.host!==k||w.mode!==v)&&(l(!1),y.current=[]),C.current={host:k,mode:v,agentId:j,siteId:I}},[k,v,j,I]);const ue=s.useMemo(()=>d.filter(w=>w.source===n&&w.sourceHandle==="provisioner").map(w=>w.target),[d,n]),Se=s.useCallback(()=>(o(),ue.map(w=>{var F;const W=(F=window.__BorealisInstructionNodes)==null?void 0:F[w];return typeof W=="function"?W():null}).filter(w=>w)),[ue,o]),ce=s.useCallback(w=>{j&&fetch("/api/agent/provision",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({agent_id:j,roles:w})}).then(()=>{l(!0),y.current=w}).catch(()=>{})},[j]),de=s.useCallback(()=>{const w=Se();ce(w)},[Se,ce]),me=s.useCallback(()=>{j&&fetch("/api/agent/provision",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({agent_id:j,roles:[]})}).then(()=>{l(!1),y.current=[]}).catch(()=>{})},[j]);return s.useEffect(()=>{const w=Se(),W=JSON.stringify(y.current||[]),F=JSON.stringify(w);p&&F!==W&&ce(w)},[ue,p,Se,ce]),s.useMemo(()=>{if(!k)return"Unassigned";const w=B[k];if(!w)return"Offline";const W=w[v];if(!j||!W)return"Unavailable";const F=(W.status||"").toString().toLowerCase();return F==="provisioned"?"Connected":F==="orphaned"||!F?"Available":F.charAt(0).toUpperCase()+F.slice(1)},[B,k,v,j]),e.jsxs("div",{className:"borealis-node",children:[e.jsx(De,{type:"source",position:ze.Bottom,id:"provisioner",className:"borealis-handle",style:{top:"100%",background:"#58a6ff"}}),e.jsx("div",{className:"borealis-node-header",children:"Device Agent"}),e.jsxs("div",{className:"borealis-node-content",style:{fontSize:"9px",display:"flex",flexDirection:"column",alignItems:"center",justifyContent:"center",textAlign:"center",minHeight:"80px",gap:"8px"},children:[e.jsx("div",{style:{fontSize:"8px",color:"#666"},children:"Right-Click to Configure Agent"}),e.jsx("button",{onClick:p?me:de,style:{padding:"6px 14px",fontSize:"10px",background:p?"#3a3a3a":"#0475c2",color:"#fff",border:"1px solid #0475c2",borderRadius:"4px",cursor:j?"pointer":"not-allowed",opacity:j?1:.5,minWidth:"150px"},disabled:!j,children:p?"Disconnect":"Connect to Device"}),e.jsx("div",{style:{fontSize:"8px",color:"#777"},children:k?`${k} · ${v.toUpperCase()}`:"No device selected"})]})]})},Yr={type:"Borealis_Agent",label:"Device Agent",description:`
|
||
Select and connect to a remote Borealis Agent.
|
||
- Assign roles to agent dynamically by connecting "Agent Role" nodes.
|
||
- Auto-provisions agent as role assignments change.
|
||
- See live agent status and re-connect/disconnect easily.
|
||
- Choose between CURRENTUSER and SYSTEM contexts for each device.
|
||
`.trim(),content:"Select and manage an Agent with dynamic roles",component:Jr,config:[{key:"agent_site_id",label:"Site",type:"select",optionsKey:"siteOptions",defaultValue:""},{key:"agent_host",label:"Device",type:"select",optionsKey:"hostOptions",defaultValue:""},{key:"agent_mode",label:"Agent Context",type:"select",optionsKey:"modeOptions",defaultValue:"currentuser"},{key:"agent_id",label:"Agent ID",type:"text",readOnly:!0,defaultValue:""}],usage_documentation:`
|
||
### Borealis Agent Node
|
||
|
||
This node allows you to establish a connection with a device running a Borealis "Agent", so you can instruct the agent to do things from your workflow.
|
||
|
||
#### Features
|
||
- **Select** a site, then a device, then finally an agent context (CURRENTUSER vs SYSTEM).
|
||
- **Connect/Disconnect** from the agent at any time.
|
||
- **Attach roles** (by connecting "Agent Role" nodes to this node's output handle) to assign behaviors dynamically.
|
||
|
||
#### How to Use
|
||
1. **Drag and drop in a Borealis Agent node.**
|
||
2. **Pick an agent** from the dropdown list (auto-populates from API backend).
|
||
3. **Click "Connect to Agent"**.
|
||
4. **Attach Agent Role Nodes** (e.g., Screenshot, Macro Keypress) to the "provisioner" output handle to define what the agent should do.
|
||
5. Agent will automatically update its roles as you change connected Role Nodes.
|
||
|
||
#### Good to Know
|
||
- If an agent disconnects or goes offline, its status will show "Reconnecting..." until it returns.
|
||
- **Roles update LIVE**: Any time you change attached roles, the agent gets updated instantly.
|
||
|
||
`.trim()},Kr=Object.freeze(Object.defineProperty({__proto__:null,default:Yr},Symbol.toStringTag,{value:"Module"})),Xr=4e3;window.BorealisValueBus||(window.BorealisValueBus={});window.BorealisUpdateRate||(window.BorealisUpdateRate=100);const Qr="Continuous",Zr=["Run Once","Continuous","Trigger-Once","Trigger-Continuous"],fn={idle:"#333",running:"#00d18c",error:"#ff4f4f"},ea=({id:n,data:t})=>{const{setNodes:o,getNodes:a}=dt(),d=mt(B=>B.edges),[u,r]=s.useState([]),[i,c]=s.useState({state:"idle",message:""}),p=s.useRef(null),l=d.find(B=>B.target===n&&B.targetHandle==="agent"),h=l&&a().find(B=>B.id===l.source),f=!!(h&&h.data&&h.data.agent_id),y=h&&h.data&&h.data.agent_id,C=(t==null?void 0:t.active)===!0||(t==null?void 0:t.active)==="true",[I,k]=s.useState({success:!0,message:"",timestamp:null});s.useEffect(()=>{if(!window.BorealisSocket)return;const B=window.BorealisSocket;p.current=B;function R(x){x&&x.agent_id===y&&x.node_id===n&&(k({success:!!x.success,message:x.message||"",timestamp:x.timestamp||Date.now()}),c({state:x.success?"success":"error",message:x.message||(x.success?"Success":"Error")}))}return B.on("macro_status",R),()=>{B.off("macro_status",R)}},[y,n]),s.useEffect(()=>{let B=null;async function R(){window.BorealisSocket&&f&&window.BorealisSocket.emit("list_agent_windows",{agent_id:y})}R(),B=setInterval(R,Xr);function x(S){(S==null?void 0:S.agent_id)===y&&Array.isArray(S.windows)&&(r(S.windows),o(z=>z.map(E=>E.id===n?{...E,data:{...E.data,windowList:S.windows}}:E)))}return window.BorealisSocket&&window.BorealisSocket.on("agent_window_list",x),()=>{clearInterval(B),window.BorealisSocket&&window.BorealisSocket.off("agent_window_list",x)}},[y,f,o,n]);const v=()=>{o(B=>B.map(R=>{var x,S;return R.id===n?{...R,data:{...R.data,active:((x=R.data)==null?void 0:x.active)===!0||((S=R.data)==null?void 0:S.active)==="true"?"false":"true"}}:R}))},j=(u||[]).find(B=>String(B.handle)===String(t==null?void 0:t.window_handle));return e.jsxs("div",{className:"borealis-node",style:{minWidth:280,position:"relative"},children:[e.jsx("div",{style:{position:"absolute",left:-30,top:26,fontSize:"8px",color:"#6ef9fb",letterSpacing:.5,pointerEvents:"none"},children:"Agent"}),e.jsx(De,{type:"target",position:ze.Left,id:"agent",style:{top:25},className:"borealis-handle"}),e.jsx("div",{style:{position:"absolute",left:-34,top:70,fontSize:"8px",color:"#6ef9fb",letterSpacing:.5,pointerEvents:"none"},children:"Trigger"}),e.jsx(De,{type:"target",position:ze.Left,id:"trigger",style:{top:68},className:"borealis-handle"}),e.jsxs("div",{className:"borealis-node-header",style:{position:"relative"},children:["Agent Role: Macro",e.jsx("div",{style:{position:"absolute",top:"50%",right:"8px",width:"10px",transform:"translateY(-50%)",height:"10px",borderRadius:"50%",backgroundColor:i.state==="error"?fn.error:C?fn.running:fn.idle,border:"1px solid #222"}})]}),e.jsxs("div",{className:"borealis-node-content",children:[e.jsx("strong",{children:"Status"}),":"," ",i.state==="error"?e.jsxs("span",{style:{color:"#ff4f4f"},children:["Error",I.message?`: ${I.message}`:""]}):C?e.jsxs("span",{style:{color:"#00d18c"},children:["Running",I.message?` (${I.message})`:""]}):"Idle",e.jsx("br",{}),e.jsx("strong",{children:"Agent Connection"}),": ",f?"Connected":"Not Connected",e.jsx("br",{}),e.jsx("strong",{children:"Target Window"}),":"," ",j?`${j.title} (${j.handle})`:t!=null&&t.window_handle?`Handle: ${t.window_handle}`:e.jsx("span",{style:{color:"#888"},children:"Not set"}),e.jsx("br",{}),e.jsx("strong",{children:"Mode"}),": ",(t==null?void 0:t.operation_mode)||Qr,e.jsx("br",{}),e.jsx("strong",{children:"Macro Type"}),": ",(t==null?void 0:t.macro_type)||"keypress",e.jsx("br",{}),e.jsx("button",{onClick:v,style:{marginTop:8,padding:"4px 10px",background:C?"#3a3a3a":"#0475c2",color:"#fff",border:"1px solid #0475c2",borderRadius:3,fontSize:"11px",cursor:"pointer"},children:C?"Pause Macro":"Start Macro"}),e.jsx("br",{}),e.jsx("span",{style:{fontSize:"9px",color:"#aaa"},children:I.timestamp?`Last event: ${new Date(I.timestamp).toLocaleTimeString()}`:""})]})]})},ta={type:"Macro_KeyPress",label:"Agent Role: Macro",description:`
|
||
Send automated key presses or typed text to any open application window on the connected agent.
|
||
Supports manual, continuous, trigger, and one-shot modes for automation and event-driven workflows.
|
||
`,content:"Send Key Press or Typed Text to Window via Agent",component:ea,config:[{key:"window_handle",label:"Target Window",type:"select",dynamicOptions:!0,defaultValue:""},{key:"macro_type",label:"Macro Type",type:"select",options:["keypress","typed_text"],defaultValue:"keypress"},{key:"key",label:"Key",type:"text",defaultValue:""},{key:"text",label:"Typed Text",type:"text",defaultValue:""},{key:"interval_ms",label:"Interval (ms)",type:"text",defaultValue:"1000"},{key:"randomize_interval",label:"Randomize Interval",type:"select",options:["true","false"],defaultValue:"false"},{key:"random_min",label:"Random Min (ms)",type:"text",defaultValue:"750"},{key:"random_max",label:"Random Max (ms)",type:"text",defaultValue:"950"},{key:"operation_mode",label:"Operation Mode",type:"select",options:Zr,defaultValue:"Continuous"},{key:"active",label:"Macro Enabled",type:"select",options:["true","false"],defaultValue:"false"},{key:"trigger",label:"Trigger Value",type:"text",defaultValue:"0"}],usage_documentation:`
|
||
### Agent Role: Macro
|
||
|
||
**Modes:**
|
||
- **Continuous**: Macro sends input non-stop when started by button.
|
||
- **Trigger-Continuous**: Macro sends input as long as upstream trigger is "1".
|
||
- **Trigger-Once**: Macro fires once per upstream "1" (one-shot edge).
|
||
- **Run Once**: Macro runs only once when started by button.
|
||
|
||
**Macro Types:**
|
||
- **Single Keypress**: Press a single key.
|
||
- **Typed Text**: Types out a string.
|
||
|
||
**Window Target:**
|
||
- Dropdown of live windows from agent, stays updated.
|
||
|
||
**Event-Driven Support:**
|
||
- Chain with other Borealis nodes (text recognition, event triggers, etc).
|
||
|
||
**Live Status:**
|
||
- Displays last agent macro event and error feedback in node.
|
||
|
||
---
|
||
`.trim()},sa=Object.freeze(Object.defineProperty({__proto__:null,default:ta},Symbol.toStringTag,{value:"Module"}));window.BorealisValueBus||(window.BorealisValueBus={});window.BorealisUpdateRate||(window.BorealisUpdateRate=100);const na=({id:n,data:t})=>{const{setNodes:o,getNodes:a}=dt(),d=mt(k=>k.edges),u=s.useCallback(()=>{try{const k=d.find(j=>j.target===n&&j.sourceHandle==="provisioner"),v=a().find(j=>j.id===(k==null?void 0:k.source));return(v==null?void 0:v.data)||null}catch{return null}},[d,a,n]),r=parseInt((t==null?void 0:t.interval)||1e3,10)||1e3,i={x:parseInt((t==null?void 0:t.x)??250,10),y:parseInt((t==null?void 0:t.y)??100,10),w:parseInt((t==null?void 0:t.w)??300,10),h:parseInt((t==null?void 0:t.h)??200,10)},c=((t==null?void 0:t.visible)??"true")==="true",p=(t==null?void 0:t.alias)||"",[l,h]=s.useState((t==null?void 0:t.value)||""),f=u(),y=((f==null?void 0:f.agent_mode)||"").toString().toLowerCase()==="system"?"SYSTEM Agent":"CURRENTUSER Agent",C=((f==null?void 0:f.agent_host)||"").toString();s.useEffect(()=>{const k=setInterval(()=>{l&&(window.BorealisValueBus[n]=l,o(v=>v.map(j=>j.id===n?{...j,data:{...j.data,value:l}}:j)))},window.BorealisUpdateRate||100);return()=>clearInterval(k)},[n,l,o]),s.useEffect(()=>{const k=window.BorealisSocket;if(!k)return;const v=j=>{if((j==null?void 0:j.node_id)!==n)return;const B=u(),R=B==null?void 0:B.agent_id;if(!R||(j==null?void 0:j.agent_id)!==R)return;j.image_base64&&(h(j.image_base64),window.BorealisValueBus[n]=j.image_base64);const{x,y:S,w:z,h:E}=j;x!==void 0&&S!==void 0&&z!==void 0&&E!==void 0&&o(U=>U.map(X=>X.id===n?{...X,data:{...X.data,x,y:S,w:z,h:E}}:X))};return k.on("agent_screenshot_task",v),()=>k.off("agent_screenshot_task",v)},[n,o,u]),window.__BorealisInstructionNodes=window.__BorealisInstructionNodes||{},window.__BorealisInstructionNodes[n]=()=>{const k=u()||{},j=(k.agent_mode||"").toString().toLowerCase()==="system"?"system":"currentuser";return{node_id:n,role:"screenshot",interval:r,visible:c,alias:p,target_agent_mode:j,target_agent_host:k.agent_host||"",...i}};const I=()=>{const k=u(),v=k==null?void 0:k.agent_id;if(!v){alert("No valid agent connection found.");return}const j=`${window.location.origin}/api/agent/${v}/node/${n}/screenshot/live`;navigator.clipboard.writeText(j).then(()=>console.log(`[Clipboard] Live View URL copied: ${j}`)).catch(B=>console.error("Clipboard copy failed:",B))};return e.jsxs("div",{className:"borealis-node",style:{position:"relative"},children:[e.jsx(De,{type:"target",position:ze.Left,className:"borealis-handle"}),e.jsx(De,{type:"source",position:ze.Right,className:"borealis-handle"}),e.jsx("div",{className:"borealis-node-header",children:(t==null?void 0:t.label)||"Agent Role: Screenshot"}),e.jsxs("div",{className:"borealis-node-content",style:{fontSize:"9px"},children:[e.jsxs("div",{children:[e.jsx("b",{children:"Region:"})," X:",i.x," Y:",i.y," W:",i.w," H:",i.h]}),e.jsxs("div",{children:[e.jsx("b",{children:"Interval:"})," ",r," ms"]}),e.jsxs("div",{children:[e.jsx("b",{children:"Agent Context:"})," ",y]}),e.jsxs("div",{children:[e.jsx("b",{children:"Target Host:"})," ",C||e.jsx("span",{style:{color:"#666"},children:"unknown"})]}),e.jsxs("div",{children:[e.jsx("b",{children:"Overlay:"})," ",c?"Yes":"No"]}),e.jsxs("div",{children:[e.jsx("b",{children:"Label:"})," ",p||e.jsx("span",{style:{color:"#666"},children:"none"})]}),e.jsx("div",{style:{textAlign:"center",fontSize:"8px",color:"#aaa"},children:l?`Last image: ${Math.round(l.length/1024)} KB`:"Awaiting Screenshot Data..."})]}),e.jsx("div",{style:{position:"absolute",top:4,right:4},children:e.jsx(nt,{size:"small",onClick:I,children:e.jsx(zo,{style:{fontSize:14}})})})]})},oa={type:"Agent_Role_Screenshot",label:"Agent Role: Screenshot",description:`
|
||
Capture a live screenshot of a defined region from a remote Borealis Agent.
|
||
|
||
- Define region (X, Y, Width, Height)
|
||
- Select update interval (ms)
|
||
- Optionally show a visual overlay with a label
|
||
- Pushes base64 PNG stream to downstream nodes
|
||
- Use copy button to share live view URL
|
||
- Targets the CURRENTUSER or SYSTEM agent context selected upstream
|
||
`.trim(),content:"Capture screenshot region via agent",component:na,config:[{key:"interval",label:"Update Interval (ms)",type:"text",defaultValue:"1000"},{key:"x",label:"Region X",type:"text",defaultValue:"250"},{key:"y",label:"Region Y",type:"text",defaultValue:"100"},{key:"w",label:"Region Width",type:"text",defaultValue:"300"},{key:"h",label:"Region Height",type:"text",defaultValue:"200"},{key:"visible",label:"Show Overlay on Agent",type:"select",options:["true","false"],defaultValue:"true"},{key:"alias",label:"Overlay Label",type:"text",defaultValue:""}],usage_documentation:`
|
||
### Agent Role: Screenshot Node
|
||
|
||
This node defines a screenshot-capture role for a Borealis Agent.
|
||
|
||
**How It Works**
|
||
- The region (X, Y, W, H) is sent to the Agent for real-time screenshot capture.
|
||
- The interval determines how often the Agent captures and pushes new images.
|
||
- Optionally, an overlay with a label can be displayed on the Agent's screen for visual feedback.
|
||
- The captured screenshot (as a base64 PNG) is available to downstream nodes.
|
||
- Use the share button to copy a live viewing URL for the screenshot stream.
|
||
|
||
**Configuration**
|
||
- All fields are edited via the right sidebar.
|
||
- Coordinates update live if region is changed from the Agent.
|
||
|
||
**Warning**
|
||
- Changing region from the Agent UI will update this node's coordinates.
|
||
- Do not remove the bi-directional region write-back: if the region moves, this node updates immediately.
|
||
|
||
**Example Use Cases**
|
||
- Automated visual QA (comparing regions of apps)
|
||
- OCR on live application windows
|
||
- Remote monitoring dashboards
|
||
|
||
`.trim()},ra=Object.freeze(Object.defineProperty({__proto__:null,default:oa},Symbol.toStringTag,{value:"Module"}));window.BorealisValueBus||(window.BorealisValueBus={});window.BorealisUpdateRate||(window.BorealisUpdateRate=100);const aa=({id:n,data:t})=>{const o=mt(j=>j.edges),{setNodes:a}=dt(),[d,u]=s.useState((t==null?void 0:t.alertType)||"Once"),[r,i]=s.useState((t==null?void 0:t.interval)||1e3),[c,p]=s.useState("0"),[l,h]=s.useState((t==null?void 0:t.audio)||null),[f,y]=s.useState("0"),C=s.useRef(null),I=()=>{if(C.current){console.log(`[Alert Node ${n}] Attempting to play sound`);try{C.current.pause(),C.current.currentTime=0,C.current.load(),C.current.play().then(()=>{console.log(`[Alert Node ${n}] Sound played successfully`)}).catch(j=>{console.warn(`[Alert Node ${n}] Audio play blocked or errored:`,j)})}catch(j){console.error(`[Alert Node ${n}] Failed to play sound:`,j)}}else console.warn(`[Alert Node ${n}] No audioRef loaded`)},k=j=>{const B=j.target.files[0];if(!B)return;if(console.log(`[Alert Node ${n}] File selected:`,B.name,B.type),!["audio/wav","audio/mp3","audio/mpeg","audio/ogg"].includes(B.type)){console.warn(`[Alert Node ${n}] Unsupported audio type: ${B.type}`);return}const x=new FileReader;x.onload=S=>{const z=S.target.result,E=B.type||"audio/mpeg",U=z.startsWith("data:")?z:`data:${E};base64,${z}`;C.current&&(C.current.pause(),C.current.src="",C.current.load(),C.current=null);const X=new Audio;X.src=U;let ue=!1;X.addEventListener("canplaythrough",()=>{ue||(ue=!0,console.log(`[Alert Node ${n}] Audio is decodable and ready: ${B.name}`),h(U),C.current=X,X.load(),a(Se=>Se.map(ce=>ce.id===n?{...ce,data:{...ce.data,audio:U}}:ce)))}),setTimeout(()=>{ue||console.warn(`[Alert Node ${n}] WARNING: Audio not marked ready in time. May fail silently.`)},2e3)},x.onerror=S=>{console.error(`[Alert Node ${n}] File read error:`,S)},x.readAsDataURL(B)};s.useEffect(()=>{if(l){console.log(`[Alert Node ${n}] Loading embedded audio from workflow`),C.current&&(C.current.pause(),C.current.src="",C.current.load(),C.current=null);const j=new Audio(l);j.addEventListener("canplaythrough",()=>{console.log(`[Alert Node ${n}] Embedded audio ready`)}),C.current=j,j.load()}else console.log(`[Alert Node ${n}] No custom audio, using fallback silent wav`),C.current=new Audio("data:audio/wav;base64,UklGRiQAAABXQVZFZm10IBAAAAABAAEAESsAACJWAAACABAAZGF0YRAAAAAA"),C.current.load()},[l]),s.useEffect(()=>{let j=window.BorealisUpdateRate,B=null;const R=()=>{const z=o.find(X=>X.target===n),E=(z==null?void 0:z.source)||null,U=E&&window.BorealisValueBus[E]||"0";y(U),d==="Once"&&U==="1"&&c!=="1"&&(console.log(`[Alert Node ${n}] Triggered ONCE playback`),I()),p(U)},x=()=>{d==="Constant"?B=setInterval(()=>{const z=o.find(X=>X.target===n),E=(z==null?void 0:z.source)||null,U=E&&window.BorealisValueBus[E]||"0";y(U),String(U)==="1"&&(console.log(`[Alert Node ${n}] Triggered CONSTANT playback`),I())},r):B=setInterval(R,j)};x();const S=setInterval(()=>{const z=window.BorealisUpdateRate;z!==j&&d==="Once"&&(j=z,clearInterval(B),x())},250);return()=>{clearInterval(B),clearInterval(S)}},[o,d,r,c]);const v=f==="1"?"#ff4444":"#44ff44";return e.jsxs("div",{className:"borealis-node",style:{position:"relative"},children:[e.jsx(De,{type:"target",position:ze.Left,className:"borealis-handle"}),e.jsxs("div",{className:"borealis-node-header",style:{position:"relative"},children:[(t==null?void 0:t.label)||"Alert Sound",e.jsx("div",{style:{position:"absolute",top:"50%",right:"8px",transform:"translateY(-50%)",width:"10px",height:"10px",borderRadius:"50%",backgroundColor:v,border:"1px solid #222"}})]}),e.jsxs("div",{className:"borealis-node-content",children:[e.jsx("div",{style:{marginBottom:"8px",fontSize:"9px",color:"#ccc"},children:'Play a sound alert when input is "1"'}),e.jsx("label",{style:{fontSize:"9px",display:"block",marginBottom:"4px"},children:"Alerting Type:"}),e.jsxs("select",{value:d,onChange:j=>u(j.target.value),style:ia,children:[e.jsx("option",{value:"Once",children:"Once"}),e.jsx("option",{value:"Constant",children:"Constant"})]}),e.jsx("label",{style:{fontSize:"9px",display:"block",marginBottom:"4px"},children:"Alert Interval (ms):"}),e.jsx("input",{type:"number",min:"100",step:"100",value:r,onChange:j=>i(parseInt(j.target.value)),disabled:d==="Once",style:{...Wn,background:d==="Once"?"#2a2a2a":"#1e1e1e"}}),e.jsx("label",{style:{fontSize:"9px",display:"block",marginTop:"6px",marginBottom:"4px"},children:"Custom Sound:"}),e.jsxs("div",{style:{display:"flex",gap:"4px"},children:[e.jsx("input",{type:"file",accept:".wav,.mp3,.mpeg,.ogg",onChange:k,style:{...Wn,marginBottom:0,flex:1}}),e.jsx("button",{style:{fontSize:"9px",padding:"4px 8px",backgroundColor:"#1e1e1e",color:"#ccc",border:"1px solid #444",borderRadius:"2px",cursor:"pointer"},onClick:I,title:"Test playback",children:"Test"})]})]})]})},ia={fontSize:"9px",padding:"4px",background:"#1e1e1e",color:"#ccc",border:"1px solid #444",borderRadius:"2px",width:"100%",marginBottom:"8px"},Wn={fontSize:"9px",padding:"4px",color:"#ccc",border:"1px solid #444",borderRadius:"2px",width:"100%",marginBottom:"8px"},la={type:"AlertSoundNode",label:"Alert Sound",description:`
|
||
Plays a sound alert when input = "1"
|
||
|
||
- "Once" = Only when 0 -> 1 transition
|
||
- "Constant" = Repeats every X ms while input stays 1
|
||
- Custom audio supported (MP3/WAV/OGG)
|
||
- Base64 audio embedded in workflow and restored
|
||
- Visual status indicator (green = 0, red = 1)
|
||
- Manual "Test" button for validation
|
||
`.trim(),content:"Sound alert when input value = 1",component:aa},ca=Object.freeze(Object.defineProperty({__proto__:null,default:la},Symbol.toStringTag,{value:"Module"}));window.BorealisValueBus||(window.BorealisValueBus={});window.BorealisUpdateRate||(window.BorealisUpdateRate=100);const da=({id:n,data:t})=>{const o=mt(c=>c.edges),{setNodes:a}=dt(),[d,u]=s.useState("Line Does Not Exist"),r=s.useRef(d),i=parseInt(t==null?void 0:t.lineNumber,10)||1;return s.useEffect(()=>{let c=null,p=window.BorealisUpdateRate;const l=()=>{const f=o.find(k=>k.target===n);if(!f){r.current="Line Does Not Exist",u("Line Does Not Exist"),window.BorealisValueBus[n]="Line Does Not Exist";return}const y=window.BorealisValueBus[f.source];if(!Array.isArray(y)){r.current="Line Does Not Exist",u("Line Does Not Exist"),window.BorealisValueBus[n]="Line Does Not Exist";return}const C=Math.max(0,i-1),I=y[C]??"Line Does Not Exist";I!==r.current&&(r.current=I,u(I),window.BorealisValueBus[n]=I)};c=setInterval(l,p);const h=setInterval(()=>{const f=window.BorealisUpdateRate;f!==p&&(clearInterval(c),p=f,c=setInterval(l,p))},300);return()=>{clearInterval(c),clearInterval(h)}},[n,o,i]),e.jsxs("div",{className:"borealis-node",children:[e.jsx(De,{type:"target",position:ze.Left,className:"borealis-handle"}),e.jsx("div",{className:"borealis-node-header",children:(t==null?void 0:t.label)||"Array Index Extractor"}),e.jsxs("div",{className:"borealis-node-content",style:{fontSize:"9px"},children:[e.jsx("div",{style:{marginBottom:"6px",color:"#ccc"},children:"Output a specific line from an upstream array."}),e.jsxs("div",{style:{color:"#888",marginBottom:4},children:["Line Number: ",e.jsx("b",{children:i})]}),e.jsx("label",{style:{display:"block",marginBottom:"2px"},children:"Output:"}),e.jsx("input",{type:"text",value:d,disabled:!0,style:{width:"100%",fontSize:"9px",background:"#2a2a2a",color:"#ccc",border:"1px solid #444",borderRadius:"2px",padding:"3px"}})]}),e.jsx(De,{type:"source",position:ze.Right,className:"borealis-handle"})]})},ua={type:"ArrayIndexExtractor",label:"Array Index Extractor",description:`
|
||
Outputs a specific line from an upstream array, such as the result of OCR multi-line extraction.
|
||
|
||
- Specify the **line number** (1 = first line)
|
||
- Outputs the value at that index if present
|
||
- If index is out of bounds, outputs "Line Does Not Exist"
|
||
`.trim(),content:"Output a Specific Array Index's Value",component:da,config:[{key:"lineNumber",label:"Line Number (1 = First Line)",type:"text",defaultValue:"1"}],usage_documentation:`
|
||
### Array Index Extractor Node
|
||
|
||
This node allows you to extract a specific line or item from an upstream array value.
|
||
|
||
**Typical Use:**
|
||
- Used after OCR or any node that outputs an array of lines or items.
|
||
- Set the **Line Number** (1-based, so "1" = first line).
|
||
|
||
**Behavior:**
|
||
- If the line exists, outputs the value at that position.
|
||
- If not, outputs: \`Line Does Not Exist\`.
|
||
|
||
**Input:**
|
||
- Connect an upstream node that outputs an array (such as OCR Text Extraction).
|
||
|
||
**Sidebar Config:**
|
||
- Set the desired line number from the configuration sidebar for live updates.
|
||
|
||
---
|
||
`.trim()},pa=Object.freeze(Object.defineProperty({__proto__:null,default:ua},Symbol.toStringTag,{value:"Module"})),fa=({id:n,data:t})=>{const{setNodes:o}=dt(),a=mt(B=>B.edges),d=s.useRef(null),u=s.useRef(!1),r=s.useRef({x:0,y:0}),i=s.useRef({width:0,height:0}),[c,p]=s.useState((t==null?void 0:t.jsonData)||{}),l=parseInt((t==null?void 0:t.width)||"300",10),h=parseInt((t==null?void 0:t.height)||"150",10),[f,y]=s.useState({width:l,height:h}),C=s.useRef(c),I=s.useCallback(()=>{const B=`${Math.round(f.width)}px`,R=`${Math.round(f.height)}px`;o(x=>x.map(S=>S.id===n?{...S,data:{...S.data,width:B,height:R}}:S))},[f,n,o]);s.useEffect(()=>{const B=x=>{if(!u.current)return;const S=x.clientX-r.current.x,z=x.clientY-r.current.y;y({width:Math.max(100,i.current.width+S),height:Math.max(60,i.current.height+z)})},R=()=>{u.current&&(u.current=!1,I())};return window.addEventListener("mousemove",B),window.addEventListener("mouseup",R),()=>{window.removeEventListener("mousemove",B),window.removeEventListener("mouseup",R)}},[I]);const k=B=>{B.stopPropagation(),u.current=!0,r.current={x:B.clientX,y:B.clientY},i.current={...f}};s.useEffect(()=>{let B=window.BorealisUpdateRate;const x=setInterval(()=>{const z=a.find(E=>E.target===n);if(z&&z.source){const E=window.BorealisValueBus[z.source];typeof E=="object"&&JSON.stringify(E)!==JSON.stringify(C.current)&&(C.current=E,p(E),window.BorealisValueBus[n]=E,o(U=>U.map(X=>X.id===n?{...X,data:{...X.data,jsonData:E}}:X)))}else window.BorealisValueBus[n]=C.current},B),S=setInterval(()=>{window.BorealisUpdateRate!==B&&(clearInterval(x),clearInterval(S))},200);return()=>{clearInterval(x),clearInterval(S)}},[n,a,o]);const v=JSON.stringify(c,null,2),j=qt.highlight(v,qt.languages.json,"json");return e.jsxs("div",{ref:d,className:"borealis-node",style:{display:"flex",flexDirection:"column",width:f.width,height:f.height,overflow:"visible",position:"relative",boxSizing:"border-box"},children:[e.jsx(De,{type:"target",position:ze.Left,className:"borealis-handle"}),e.jsx(De,{type:"source",position:ze.Right,className:"borealis-handle"}),e.jsx("div",{className:"borealis-node-header",children:"Display JSON Data"}),e.jsxs("div",{className:"borealis-node-content",style:{flex:1,padding:"4px",fontSize:"9px",color:"#ccc",display:"flex",flexDirection:"column",overflow:"hidden"},children:[e.jsx("div",{style:{marginBottom:"4px"},children:"Display prettified JSON from upstream."}),e.jsx("div",{style:{flex:1,width:"100%",background:"#1e1e1e",border:"1px solid #444",borderRadius:"2px",padding:"4px",overflowY:"auto",fontFamily:"monospace",fontSize:"9px"},children:e.jsx("pre",{dangerouslySetInnerHTML:{__html:j},style:{margin:0}})})]}),e.jsx("div",{onMouseDown:k,style:{position:"absolute",width:"20px",height:"20px",right:"-4px",bottom:"-4px",cursor:"nwse-resize",background:"transparent",zIndex:10}})]})},ha={type:"Node_JSON_Pretty_Display",label:"Display JSON Data",description:"Display upstream JSON object as prettified JSON with syntax highlighting.",content:"Display prettified multi-line JSON from upstream node.",component:fa},ma=Object.freeze(Object.defineProperty({__proto__:null,default:ha},Symbol.toStringTag,{value:"Module"})),xa=({id:n,data:t})=>{const{setNodes:o,getEdges:a}=dt(),[d,u]=s.useState((t==null?void 0:t.keyName)||""),[r,i]=s.useState((t==null?void 0:t.result)||""),c=p=>{const l=p.target.value;u(l),o(h=>h.map(f=>f.id===n?{...f,data:{...f.data,keyName:l}}:f))};return s.useEffect(()=>{let p=window.BorealisUpdateRate,l;const h=()=>{var v;const I=(v=a().filter(j=>j.target===n)[0])==null?void 0:v.source;let k="Key Not Found";if(I&&window.BorealisValueBus[I]!==void 0){let j=window.BorealisValueBus[I];if(j&&typeof j=="object"&&d){const B=d.split(".");let R=j;for(let x of B)if(R!=null&&(typeof R=="object"||Array.isArray(R))&&x in R)R=R[x];else{R=void 0;break}R!==void 0&&(k=String(R))}}k!==r&&(i(k),window.BorealisValueBus[n]=k,o(j=>j.map(B=>B.id===n?{...B,data:{...B.data,result:k}}:B)))};h(),l=setInterval(h,p);const f=setInterval(()=>{const y=window.BorealisUpdateRate;y!==p&&(clearInterval(l),p=y,l=setInterval(h,p))},250);return()=>{clearInterval(l),clearInterval(f)}},[d,n,o,a,r]),e.jsxs("div",{className:"borealis-node",children:[e.jsx("div",{className:"borealis-node-header",children:"JSON Value Extractor"}),e.jsxs("div",{className:"borealis-node-content",children:[e.jsx("label",{style:{fontSize:"9px",display:"block",marginBottom:"4px"},children:"Key:"}),e.jsx("input",{type:"text",value:d,onChange:c,placeholder:"e.g. name.en",style:{fontSize:"9px",padding:"4px",width:"100%",background:"#1e1e1e",color:"#ccc",border:"1px solid #444",borderRadius:"2px"}}),e.jsx("label",{style:{fontSize:"9px",display:"block",margin:"8px 0 4px"},children:"Value:"}),e.jsx("textarea",{readOnly:!0,value:r,rows:2,style:{fontSize:"9px",padding:"4px",width:"100%",background:"#1e1e1e",color:"#ccc",border:"1px solid #444",borderRadius:"2px",resize:"none"}})]}),e.jsx(De,{type:"target",position:ze.Left,className:"borealis-handle"}),e.jsx(De,{type:"source",position:ze.Right,className:"borealis-handle"})]})},ga={type:"JSON_Value_Extractor",label:"JSON Value Extractor",description:"Extract a nested value by dot-delimited path from upstream JSON data.",content:"Provide a dot-separated key path (e.g. 'name.en'); outputs the extracted string or 'Key Not Found'.",component:xa},ba=Object.freeze(Object.defineProperty({__proto__:null,default:ga},Symbol.toStringTag,{value:"Module"})),ya=(n="")=>{let t=0;for(let o=0;o<n.length;o+=101){const a=n.charCodeAt(o);t=(t<<5)-t+a,t|=0}return Math.abs(t)};window.BorealisValueBus||(window.BorealisValueBus={});window.BorealisUpdateRate||(window.BorealisUpdateRate=100);const ja=({id:n,data:t})=>{const o=mt(j=>j.edges),{setNodes:a}=dt(),[d,u]=s.useState(""),r=s.useRef(""),i=s.useRef({engine:"",backend:"",dataType:""}),c=s.useRef(0),p=s.useRef(0),l=(t==null?void 0:t.engine)||"None",h=(t==null?void 0:t.backend)||"CPU",f=(t==null?void 0:t.dataType)||"Mixed",y=(t==null?void 0:t.customRateEnabled)??!0,C=(t==null?void 0:t.customRateMs)||1e3,I=(t==null?void 0:t.changeThreshold)||0,k=async j=>{const B=j.replace(/^data:image\/[a-zA-Z]+;base64,/,"");try{const R=await fetch("/api/ocr",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({image_base64:B,engine:l,backend:h})}),x=await R.json();return R.ok&&Array.isArray(x.lines)?x.lines:[`[ERROR] ${x.error||"Invalid OCR response."}`]}catch(R){return[`[ERROR] OCR API request failed: ${R.message}`]}},v=j=>f==="Numerical"?j.map(B=>B.replace(/[^\d.%\s]/g,"").replace(/\s+/g," ").trim()).filter(Boolean):f==="String"?j.map(B=>B.replace(/[^a-zA-Z\s]/g,"").replace(/\s+/g," ").trim()).filter(Boolean):j;return s.useEffect(()=>{let j=null,B=window.BorealisUpdateRate||100;const R=async()=>{const S=o.find(W=>W.target===n);if(!S){window.BorealisValueBus[n]=[],u("");return}const z=window.BorealisValueBus[S.source]||"",E=Date.now(),U=y?C:window.BorealisUpdateRate||100,X=i.current.engine!==l||i.current.backend!==h||i.current.dataType!==f,ue=ya(z),Se=Math.abs(ue-p.current),ce=I/100*1e9,de=Se>ce;if(!X&&(!de||E-c.current<U))return;i.current={engine:l,backend:h,dataType:f},c.current=E,p.current=ue,r.current=z;const me=await k(z),w=v(me);u(w.join(`
|
||
`)),window.BorealisValueBus[n]=w};j=setInterval(R,B);const x=setInterval(()=>{const S=window.BorealisUpdateRate||100;S!==B&&(clearInterval(j),j=setInterval(R,S),B=S)},300);return()=>{clearInterval(j),clearInterval(x)}},[n,l,h,f,y,C,I,o]),e.jsxs("div",{className:"borealis-node",style:{minWidth:"200px"},children:[e.jsx(De,{type:"target",position:ze.Left,className:"borealis-handle"}),e.jsx("div",{className:"borealis-node-header",children:"OCR-Based Text Extraction"}),e.jsxs("div",{className:"borealis-node-content",children:[e.jsx("div",{style:{fontSize:"9px",marginBottom:"8px",color:"#ccc"},children:"Extract Multi-Line Text from Upstream Image Node"}),e.jsx("label",{style:wa,children:"OCR Output:"}),e.jsx("textarea",{readOnly:!0,value:d,rows:6,style:{width:"100%",fontSize:"9px",background:"#1e1e1e",color:"#ccc",border:"1px solid #444",borderRadius:"2px",padding:"4px",resize:"vertical"}})]}),e.jsx(De,{type:"source",position:ze.Right,className:"borealis-handle"})]})},wa={fontSize:"9px",display:"block",marginTop:"6px",marginBottom:"2px"},va={type:"OCR_Text_Extraction",label:"OCR Text Extraction",description:"Extract text from upstream image using backend OCR engine via API. Includes rate limiting and sensitivity detection for smart processing.",content:"Extract Multi-Line Text from Upstream Image Node",component:ja,config:[{key:"engine",label:"OCR Engine",type:"select",options:["None","TesseractOCR","EasyOCR"],defaultValue:"None"},{key:"backend",label:"Compute Backend",type:"select",options:["CPU","GPU"],defaultValue:"CPU"},{key:"dataType",label:"Data Type Filter",type:"select",options:["Mixed","Numerical","String"],defaultValue:"Mixed"},{key:"customRateEnabled",label:"Custom API Rate Limit Enabled",type:"select",options:["true","false"],defaultValue:"true"},{key:"customRateMs",label:"Custom API Rate Limit (ms)",type:"text",defaultValue:"1000"},{key:"changeThreshold",label:"Change Detection Sensitivity (0-100)",type:"text",defaultValue:"0"}],usage_documentation:`
|
||
### OCR Text Extraction Node
|
||
|
||
Extracts text (lines) from an **upstream image node** using a selectable backend OCR engine (Tesseract or EasyOCR). Designed for screenshots, scanned forms, and live image data pipelines.
|
||
|
||
**Features:**
|
||
- **Engine:** Select between None, TesseractOCR, or EasyOCR
|
||
- **Backend:** Choose CPU or GPU (if supported)
|
||
- **Data Type Filter:** Post-processes recognized lines for numerical-only or string-only content
|
||
- **Custom API Rate Limit:** When enabled, you can set a custom polling rate for OCR requests (in ms)
|
||
- **Change Detection Sensitivity:** Node will only re-OCR if the input image changes significantly (hash-based, 0 disables)
|
||
|
||
**Outputs:**
|
||
- Array of recognized lines, pushed to downstream nodes
|
||
- Output is displayed in the node (read-only)
|
||
|
||
**Usage:**
|
||
- Connect an image node (base64 output) to this node's input
|
||
- Configure OCR engine and options in the sidebar
|
||
- Useful for extracting values from screen regions, live screenshots, PDF scans, etc.
|
||
|
||
**Notes:**
|
||
- Setting Engine to 'None' disables OCR
|
||
- Use numerical/string filter for precise downstream parsing
|
||
- Polling rate too fast may cause backend overload
|
||
- Change threshold is a 0-100 scale (0 = always run, 100 = image must change completely)
|
||
|
||
`.trim()},Sa=Object.freeze(Object.defineProperty({__proto__:null,default:va},Symbol.toStringTag,{value:"Module"}));window.BorealisValueBus||(window.BorealisValueBus={});window.BorealisUpdateRate||(window.BorealisUpdateRate=100);const Ca=({id:n,data:t})=>{const o=mt(p=>p.edges),{setNodes:a}=dt(),[d,u]=s.useState(""),[r,i]=s.useState(""),c=s.useRef("");return s.useEffect(()=>{let p=null,l=window.BorealisUpdateRate;const h=()=>{const y=o.find(k=>k.target===n),C=y&&window.BorealisValueBus[y.source]||"";i(C);let I=C;try{if(((t==null?void 0:t.enabled)??!0)&&(t!=null&&t.pattern)){const k=new RegExp(t.pattern,t.flags||"g");let v=(t.replacement??"").trim();v.startsWith('"')&&v.endsWith('"')&&(v=v.slice(1,-1)),I=C.replace(k,v)}}catch(k){I=`[Error] ${k.message}`}I!==c.current&&(c.current=I,u(I),window.BorealisValueBus[n]=I)};p=setInterval(h,l);const f=setInterval(()=>{const y=window.BorealisUpdateRate;y!==l&&(clearInterval(p),p=setInterval(h,y),l=y)},300);return()=>{clearInterval(p),clearInterval(f)}},[n,o,t==null?void 0:t.pattern,t==null?void 0:t.replacement,t==null?void 0:t.flags,t==null?void 0:t.enabled]),e.jsxs("div",{className:"borealis-node",children:[e.jsx(De,{type:"target",position:ze.Left,className:"borealis-handle"}),e.jsx("div",{className:"borealis-node-header",children:(t==null?void 0:t.label)||"Regex Replace"}),e.jsxs("div",{className:"borealis-node-content",children:[e.jsx("div",{style:{marginBottom:"6px",fontSize:"9px",color:"#ccc"},children:"Performs live regex-based find/replace on incoming string value."}),e.jsxs("div",{style:{fontSize:"9px",color:"#ccc",marginBottom:2},children:[e.jsx("b",{children:"Pattern:"})," ",(t==null?void 0:t.pattern)||e.jsx("i",{children:"(not set)"}),e.jsx("br",{}),e.jsx("b",{children:"Flags:"})," ",(t==null?void 0:t.flags)||"g",e.jsx("br",{}),e.jsx("b",{children:"Enabled:"})," ",(t==null?void 0:t.enabled)??!0?"Yes":"No"]}),e.jsx("label",{style:{fontSize:"8px",color:"#888"},children:"Original:"}),e.jsx("textarea",{readOnly:!0,value:r,rows:2,style:{width:"100%",fontSize:"9px",background:"#222",color:"#ccc",border:"1px solid #444",borderRadius:"2px",padding:"3px",resize:"vertical",marginBottom:"6px"}}),e.jsx("label",{style:{fontSize:"8px",color:"#888"},children:"Output:"}),e.jsx("textarea",{readOnly:!0,value:d,rows:2,style:{width:"100%",fontSize:"9px",background:"#2a2a2a",color:"#ccc",border:"1px solid #444",borderRadius:"2px",padding:"3px",resize:"vertical"}})]}),e.jsx(De,{type:"source",position:ze.Right,className:"borealis-handle"})]})},_a={type:"RegexReplace",label:"Regex Replace",description:`
|
||
Live regex-based string find/replace node.
|
||
|
||
- Runs a JavaScript regular expression on every input update.
|
||
- Useful for cleanup, format fixes, redacting, token extraction.
|
||
- Configurable flags, replacement text, and enable toggle.
|
||
- Handles errors gracefully, shows live preview in the sidebar.
|
||
`.trim(),content:"Perform regex replacement on incoming string",component:Ca,config:[{key:"pattern",label:"Regex Pattern",type:"text",defaultValue:"\\d+"},{key:"replacement",label:"Replacement",type:"text",defaultValue:""},{key:"flags",label:"Regex Flags",type:"text",defaultValue:"g"},{key:"enabled",label:"Enable Replacement",type:"select",options:["true","false"],defaultValue:"true"}],usage_documentation:`
|
||
### Regex Replace Node
|
||
|
||
**Purpose:**
|
||
Perform flexible find-and-replace on strings using JavaScript-style regular expressions.
|
||
|
||
#### Typical Use Cases
|
||
- Clean up text, numbers, or IDs in a data stream
|
||
- Mask or redact sensitive info (emails, credit cards, etc)
|
||
- Extract tokens, words, or reformat content
|
||
|
||
#### Configuration (see "Config" tab):
|
||
- **Regex Pattern**: The search pattern (supports capture groups)
|
||
- **Replacement**: The replacement string. You can use \`$1, $2\` for capture groups.
|
||
- **Regex Flags**: Default \`g\` (global). Add \`i\` (case-insensitive), \`m\` (multiline), etc.
|
||
- **Enable Replacement**: On/Off toggle (for easy debugging)
|
||
|
||
#### Behavior
|
||
- Upstream value is live-updated.
|
||
- When enabled, node applies the regex and emits the result downstream.
|
||
- Shows both input and output in the sidebar for debugging.
|
||
- If the regex is invalid, error is displayed as output.
|
||
|
||
#### Output
|
||
- Emits the transformed string to all downstream nodes.
|
||
- Updates in real time at the global Borealis update rate.
|
||
|
||
#### Example
|
||
Pattern: \`(\\d+)\`
|
||
Replacement: \`[number:$1]\`
|
||
Input: \`abc 123 def 456\`
|
||
Output: \`abc [number:123] def [number:456]\`
|
||
|
||
---
|
||
**Tips:**
|
||
- Use double backslashes (\\) in patterns when needed (e.g. \`\\\\d+\`).
|
||
- Flags can be any combination (e.g. \`gi\`).
|
||
|
||
`.trim()},ka=Object.freeze(Object.defineProperty({__proto__:null,default:_a},Symbol.toStringTag,{value:"Module"}));window.BorealisValueBus||(window.BorealisValueBus={});window.BorealisUpdateRate||(window.BorealisUpdateRate=100);const Ia=({id:n,data:t})=>{const{setNodes:o}=dt(),a=mt(p=>p.edges),d=(t==null?void 0:t.pattern)??"",u=(t==null?void 0:t.flags)??"i",r=s.useRef("0"),[i,c]=s.useState("0");return s.useEffect(()=>{let p=null,l=window.BorealisUpdateRate;const h=()=>{const y=a.find(v=>v.target===n),C=y&&window.BorealisValueBus[y.source]||"";let I=!1;try{d&&(I=new RegExp(d,u).test(C))}catch{I=!1}const k=I?"1":"0";k!==r.current&&(r.current=k,c(k),window.BorealisValueBus[n]=k,o(v=>v.map(j=>j.id===n?{...j,data:{...j.data,match:k}}:j)))};p=setInterval(h,l);const f=setInterval(()=>{const y=window.BorealisUpdateRate;y!==l&&(clearInterval(p),p=setInterval(h,y),l=y)},300);return()=>{clearInterval(p),clearInterval(f)}},[n,a,d,u,o]),e.jsxs("div",{className:"borealis-node",children:[e.jsx(De,{type:"target",position:ze.Left,className:"borealis-handle"}),e.jsx("div",{className:"borealis-node-header",children:(t==null?void 0:t.label)||"Regex Search"}),e.jsxs("div",{className:"borealis-node-content",style:{fontSize:"9px",color:"#ccc"},children:["Match: ",i]}),e.jsx(De,{type:"source",position:ze.Right,className:"borealis-handle"})]})},Ra={type:"RegexSearch",label:"Regex Search",description:`
|
||
Test for text matches with a regular expression pattern.
|
||
|
||
- Accepts a regex pattern and flags (e.g. "i", "g", "m")
|
||
- Connect any node to the input to test its value.
|
||
- Outputs "1" if the regex matches, otherwise "0".
|
||
- Useful for input validation, filtering, or text triggers.
|
||
`.trim(),content:"Outputs '1' if regex matches input, otherwise '0'",component:Ia,config:[{key:"pattern",label:"Regex Pattern",type:"text",defaultValue:"",placeholder:"e.g. World"},{key:"flags",label:"Regex Flags",type:"text",defaultValue:"i",placeholder:"e.g. i"}],usage_documentation:`
|
||
### Regex Search Node
|
||
|
||
This node tests its input value against a user-supplied regular expression pattern.
|
||
|
||
**Configuration (Sidebar):**
|
||
- **Regex Pattern**: Standard JavaScript regex pattern.
|
||
- **Regex Flags**: Any combination of \`i\` (ignore case), \`g\` (global), \`m\` (multiline), etc.
|
||
|
||
**Input:**
|
||
- Accepts a string from any upstream node.
|
||
|
||
**Output:**
|
||
- Emits "1" if the pattern matches the input string.
|
||
- Emits "0" if there is no match or the pattern/flags are invalid.
|
||
|
||
**Common Uses:**
|
||
- Search for words/phrases in extracted text.
|
||
- Filter values using custom patterns.
|
||
- Create triggers based on input structure (e.g. validate an email, detect phone numbers, etc).
|
||
|
||
#### Example:
|
||
- **Pattern:** \`World\`
|
||
- **Flags:** \`i\`
|
||
- **Input:** \`Hello world!\`
|
||
- **Output:** \`1\` (matched, case-insensitive)
|
||
`.trim()},Na=Object.freeze(Object.defineProperty({__proto__:null,default:Ra},Symbol.toStringTag,{value:"Module"})),Ta=({id:n,data:t})=>{const{setNodes:o}=dt(),a=mt(v=>v.edges),d=s.useRef(null),u=s.useRef(!1),r=s.useRef({x:0,y:0}),i=s.useRef({width:0,height:0}),[c,p]=s.useState((t==null?void 0:t.lines)||[]),l=s.useRef(c),h=parseInt((t==null?void 0:t.width)||"300",10),f=parseInt((t==null?void 0:t.height)||"150",10),[y,C]=s.useState({width:h,height:f}),I=s.useCallback(()=>{const v=`${Math.round(y.width)}px`,j=`${Math.round(y.height)}px`;o(B=>B.map(R=>R.id===n?{...R,data:{...R.data,width:v,height:j}}:R))},[y,n,o]);s.useEffect(()=>{const v=B=>{if(!u.current)return;const R=B.clientX-r.current.x,x=B.clientY-r.current.y;C({width:Math.max(100,i.current.width+R),height:Math.max(60,i.current.height+x)})},j=()=>{u.current&&(u.current=!1,I())};return window.addEventListener("mousemove",v),window.addEventListener("mouseup",j),()=>{window.removeEventListener("mousemove",v),window.removeEventListener("mouseup",j)}},[I]);const k=v=>{v.stopPropagation(),u.current=!0,r.current={x:v.clientX,y:v.clientY},i.current={...y}};return s.useEffect(()=>{let v=window.BorealisUpdateRate;const B=setInterval(()=>{const x=a.find(S=>S.target===n);if(x&&x.source){const S=window.BorealisValueBus[x.source]||[];JSON.stringify(S)!==JSON.stringify(l.current)&&(l.current=S,p(S),window.BorealisValueBus[n]=S,o(z=>z.map(E=>E.id===n?{...E,data:{...E.data,lines:S}}:E)))}else window.BorealisValueBus[n]=l.current},v),R=setInterval(()=>{window.BorealisUpdateRate!==v&&(clearInterval(B),clearInterval(R))},200);return()=>{clearInterval(B),clearInterval(R)}},[n,a,o]),e.jsxs("div",{ref:d,className:"borealis-node",style:{display:"flex",flexDirection:"column",width:y.width,height:y.height,overflow:"visible",position:"relative",boxSizing:"border-box"},children:[e.jsx(De,{type:"target",position:ze.Left,className:"borealis-handle"}),e.jsx(De,{type:"source",position:ze.Right,className:"borealis-handle"}),e.jsx("div",{className:"borealis-node-header",children:(t==null?void 0:t.label)||"Display Multi-Line Array"}),e.jsxs("div",{className:"borealis-node-content",style:{flex:1,padding:"4px",fontSize:"9px",color:"#ccc",display:"flex",flexDirection:"column",overflow:"hidden"},children:[e.jsx("div",{style:{marginBottom:"4px"},children:(t==null?void 0:t.content)||"Display upstream multi-line text arrays."}),e.jsx("label",{style:{marginBottom:"4px"},children:"Upstream Text Data:"}),e.jsx("textarea",{value:c.join(`
|
||
`),readOnly:!0,style:{flex:1,width:"100%",fontSize:"9px",background:"#1e1e1e",color:"#ccc",border:"1px solid #444",borderRadius:"2px",padding:"4px",resize:"none",overflowY:"auto",boxSizing:"border-box"}})]}),e.jsx("div",{onMouseDown:k,style:{position:"absolute",width:"20px",height:"20px",right:"-4px",bottom:"-4px",cursor:"nwse-resize",background:"transparent",zIndex:10}})]})},Aa={type:"Node_TextArray_Display",label:"Display Multi-Line Array",description:"Display upstream multi-line text arrays.",content:"Display upstream multi-line text arrays.",component:Ta},Ba=Object.freeze(Object.defineProperty({__proto__:null,default:Aa},Symbol.toStringTag,{value:"Module"})),Oa=({id:n,data:t})=>{const{setNodes:o}=dt(),a=mt(k=>k.edges);window.BorealisValueBus||(window.BorealisValueBus={});const d=(t==null?void 0:t.url)||"http://localhost:5000/health",u=((t==null?void 0:t.useProxy)??"true")==="true",r=(t==null?void 0:t.body)||"",i=parseInt((t==null?void 0:t.intervalSec)||"10",10)||10,[c,p]=s.useState(null),[l,h]=s.useState(null),[f,y]=s.useState(""),C=s.useRef(null);s.useEffect(()=>{let k=!1;const v=async()=>{try{p(null);const R=a.find(Se=>Se.target===n),S=(R?window.BorealisValueBus[R.source]:null)||d;let z=u?`/api/proxy?url=${encodeURIComponent(S)}`:S;const E={};r.trim()&&(E.method="POST",E.headers={"Content-Type":"application/json"},E.body=r);const U=await fetch(z,E);if(h(U.status),y(U.statusText),!U.ok)throw C.current=null,window.BorealisValueBus[n]=void 0,o(Se=>Se.map(ce=>ce.id===n?{...ce,data:{...ce.data,result:void 0}}:ce)),new Error(`HTTP ${U.status}`);const X=await U.json(),ue=JSON.stringify(X,null,2);!k&&C.current!==ue&&(C.current=ue,window.BorealisValueBus[n]=X,o(Se=>Se.map(ce=>ce.id===n?{...ce,data:{...ce.data,result:ue}}:ce)))}catch(R){console.error("API Request node fetch error:",R),p(R.message)}};v();const j=Math.max(i,1)*1e3,B=setInterval(v,j);return()=>{k=!0,clearInterval(B)}},[d,r,i,u,n,o,a]);const I=a.find(k=>k.target===n);return I&&I.source,e.jsxs("div",{className:"borealis-node",children:[e.jsx(De,{type:"target",position:ze.Left,className:"borealis-handle"}),e.jsx("div",{className:"borealis-node-header",children:(t==null?void 0:t.label)||"API Request"}),e.jsxs("div",{className:"borealis-node-content",style:{fontSize:"9px",color:"#ccc"},children:[e.jsxs("div",{children:[e.jsx("b",{children:"Status:"})," ",c?e.jsx("span",{style:{color:"#f66"},children:c}):l!==null?e.jsxs("span",{style:{color:"#6f6"},children:[l," ",f]}):"N/A"]}),e.jsxs("div",{style:{marginTop:"4px"},children:[e.jsx("b",{children:"Result:"}),e.jsx("pre",{style:{background:"#181818",color:"#b6ffb4",fontSize:"8px",maxHeight:62,overflow:"auto",margin:0,padding:"4px",borderRadius:"2px"},children:t!=null&&t.result?String(t.result).slice(0,350):"No data"})]})]}),e.jsx(De,{type:"source",position:ze.Right,className:"borealis-handle"})]})},Pa={type:"API_Request",label:"API Request",description:"Fetch JSON from an API endpoint with optional POST body, polling, and proxy toggle. Accepts URL from upstream.",content:"Fetch JSON from HTTP or remote API endpoint, with CORS proxy option.",component:Oa,config:[{key:"url",label:"Request URL",type:"text",defaultValue:"http://localhost:5000/health"},{key:"useProxy",label:"Use Proxy (bypass CORS)",type:"select",options:["true","false"],defaultValue:"true"},{key:"body",label:"Request Body (JSON)",type:"textarea",defaultValue:""},{key:"intervalSec",label:"Polling Interval (sec)",type:"text",defaultValue:"10"}],usage_documentation:`
|
||
### API Request Node
|
||
|
||
Fetches JSON from an HTTP or HTTPS API endpoint, with an option to POST a JSON body and control polling interval.
|
||
|
||
**Features:**
|
||
- **URL**: You can set a static URL, or connect an upstream node to dynamically control the API endpoint.
|
||
- **Use Proxy**: When enabled, requests route through the Borealis backend proxy to bypass CORS/browser restrictions.
|
||
- **Request Body**: POST JSON data (leave blank for GET).
|
||
- **Polling Interval**: Set how often (in seconds) to re-fetch the API.
|
||
|
||
**Outputs:**
|
||
- The downstream value is the parsed JSON object from the API response.
|
||
|
||
**Typical Use Cases:**
|
||
- Poll external APIs (weather, status, data, etc)
|
||
- Connect to local/internal REST endpoints
|
||
- Build data pipelines with API triggers
|
||
|
||
**Input & UI Behavior:**
|
||
- If an upstream node is connected, its output value will override the Request URL.
|
||
- All config is handled in the right sidebar (Node Properties).
|
||
|
||
**Error Handling:**
|
||
- If the fetch fails, the node displays the error in the UI.
|
||
- Only 2xx status codes are considered successful.
|
||
|
||
**Security Note:**
|
||
- Use Proxy mode for APIs requiring CORS bypass or additional privacy.
|
||
|
||
`.trim()},Ea=Object.freeze(Object.defineProperty({__proto__:null,default:Pa},Symbol.toStringTag,{value:"Module"})),Ma=({id:n,data:t})=>{const{setNodes:o}=dt();mt(l=>l.edges);const a=(t==null?void 0:t.lines)||[],[d,u]=s.useState(a),r=s.useRef(a),i=s.useRef(null),c=l=>{const h=l.target.files&&l.target.files[0];h&&h.text().then(f=>{const y=f.split(/\r\n|\n/);r.current=y,u(y),window.BorealisValueBus[n]=y,o(C=>C.map(I=>I.id===n?{...I,data:{...I.data,lines:y}}:I))})},p=()=>{var l;(l=i.current)==null||l.click()};return s.useEffect(()=>{let l=window.BorealisUpdateRate;const h=setInterval(()=>{window.BorealisValueBus[n]=r.current},l),f=setInterval(()=>{window.BorealisUpdateRate!==l&&(clearInterval(h),clearInterval(f))},250);return()=>{clearInterval(h),clearInterval(f)}},[n]),e.jsxs("div",{className:"borealis-node",children:[e.jsx("div",{className:"borealis-node-header",children:(t==null?void 0:t.label)||"Upload Text File"}),e.jsxs("div",{className:"borealis-node-content",children:[e.jsx("div",{style:{marginBottom:"8px",fontSize:"9px",color:"#ccc"},children:(t==null?void 0:t.content)||"Upload a text-based file, output a multi-line string array."}),e.jsx("button",{onClick:p,style:{width:"100%",padding:"6px",fontSize:"9px",background:"#1e1e1e",color:"#ccc",border:"1px solid #444",borderRadius:"2px",cursor:"pointer"},children:"Select File..."}),e.jsx("input",{type:"file",accept:".txt,.log,.ini,text/*",style:{display:"none"},ref:i,onChange:c})]}),e.jsx(De,{type:"source",position:ze.Right,className:"borealis-handle"})]})},Da={type:"Upload_Text_File",label:"Upload Text File",description:"A node to upload a text file (TXT/LOG/INI/ETC) and store it as a multi-line text array.",content:"Upload a text-based file, output a multi-line string array.",component:Ma},za=Object.freeze(Object.defineProperty({__proto__:null,default:Da},Symbol.toStringTag,{value:"Module"}));window.BorealisValueBus||(window.BorealisValueBus={});window.BorealisUpdateRate||(window.BorealisUpdateRate=100);const Fa=({id:n,data:t})=>{const{setNodes:o}=dt(),a=mt(l=>l.edges),[d,u]=s.useState(typeof(t==null?void 0:t.enabled)=="boolean"?t.enabled:(t==null?void 0:t.enabled)==="false"?!1:(t==null?void 0:t.enabled)==="true"?!0:(t==null?void 0:t.enabled)!==void 0?!!t.enabled:!0),[r,i]=s.useState(typeof(t==null?void 0:t.value)<"u"?t.value:void 0),c=s.useRef(r);s.useEffect(()=>{o(l=>l.map(h=>h.id===n?{...h,data:{...h.data,enabled:d}}:h))},[d,n,o]),s.useEffect(()=>{typeof(t==null?void 0:t.value)<"u"&&(window.BorealisValueBus[n]=t.value,i(t.value),c.current=t.value)},[n,t==null?void 0:t.value]),s.useEffect(()=>{let l=null,h=window.BorealisUpdateRate||100;const f=()=>{const C=a.find(k=>k.target===n),I=!!(C&&C.source);if(d&&I){const k=window.BorealisValueBus[C.source];k!==c.current&&(c.current=k,i(k),window.BorealisValueBus[n]=k,o(v=>v.map(j=>j.id===n?{...j,data:{...j.data,value:k}}:j)))}else d||c.current!==0&&(c.current=0,i(0),window.BorealisValueBus[n]=0,o(k=>k.map(v=>v.id===n?{...v,data:{...v.data,value:0}}:v)))};l=setInterval(f,h);const y=setInterval(()=>{const C=window.BorealisUpdateRate;C!==h&&(clearInterval(l),h=C,l=setInterval(f,h))},250);return()=>{clearInterval(l),clearInterval(y)}},[n,a,d,o]);const p=a.find(l=>l.target===n);return p&&p.source,e.jsxs("div",{className:"borealis-node",children:[e.jsx(De,{type:"target",position:ze.Left,className:"borealis-handle"}),e.jsx("div",{className:"borealis-node-header",children:(t==null?void 0:t.label)||"Edge Toggle"}),e.jsx("div",{className:"borealis-node-content",children:e.jsxs("div",{style:{display:"flex",alignItems:"center",gap:8},children:[e.jsx(st,{title:d?"Turn Off / Send Zero":"Turn On / Allow Data",arrow:!0,children:e.jsx(co,{checked:d,size:"small",onChange:()=>u(l=>!l),sx:{"& .MuiSwitch-switchBase.Mui-checked":{color:"#58a6ff"},"& .MuiSwitch-switchBase.Mui-checked + .MuiSwitch-track":{backgroundColor:"#58a6ff"}}})}),e.jsx("span",{style:{fontSize:9,color:d?"#00d18c":"#ff4f4f",fontWeight:"bold",marginLeft:4,userSelect:"none"},children:d?"Flow Enabled":"Flow Disabled"})]})}),e.jsx(De,{type:"source",position:ze.Right,className:"borealis-handle"})]})},La={type:"Edge_Toggle",label:"Edge Toggle",description:`
|
||
Toggles edge data flow ON/OFF using a switch.
|
||
- When enabled, passes upstream value to downstream.
|
||
- When disabled, sends zero (0) so downstream always sees a cleared value.
|
||
- Use to quickly enable/disable parts of your workflow without unlinking edges.
|
||
`.trim(),content:"Toggle ON/OFF to allow or send zero downstream",component:Fa,config:[{key:"enabled",label:"Toggle Enabled",type:"select",options:["true","false"],defaultValue:"true"}],usage_documentation:`
|
||
### Edge Toggle Node
|
||
|
||
**Purpose:**
|
||
Allows you to control data flow along a workflow edge without disconnecting the wire.
|
||
|
||
**Behavior:**
|
||
- When **Enabled**: passes upstream value downstream as usual.
|
||
- When **Disabled**: pushes \`0\` (zero) so that downstream logic always sees a cleared value (acts as an instant "mute" switch).
|
||
|
||
**Persistence:**
|
||
- Toggle state is saved in the workflow and restored on load/import.
|
||
|
||
**Tips:**
|
||
- Use for debug toggling, feature gating, or for rapid workflow prototyping.
|
||
|
||
---
|
||
`.trim()},$a=Object.freeze(Object.defineProperty({__proto__:null,default:La},Symbol.toStringTag,{value:"Module"}));window.BorealisValueBus||(window.BorealisValueBus={});window.BorealisUpdateRate||(window.BorealisUpdateRate=100);const Ua=({id:n,data:t})=>{const{setNodes:o}=dt(),a=mt(i=>i.edges),[d,u]=s.useState((t==null?void 0:t.value)||""),r=s.useRef(d);return s.useEffect(()=>{r.current=(t==null?void 0:t.value)||"",u(r.current),window.BorealisValueBus[n]=r.current},[t==null?void 0:t.value,n]),s.useEffect(()=>{let i=window.BorealisUpdateRate||100,c=null;const p=()=>{const h=a.find(y=>(y==null?void 0:y.target)===n);if(!!(h!=null&&h.source)){const y=window.BorealisValueBus[h.source]??"";y!==r.current&&(r.current=y,u(y),window.BorealisValueBus[n]=y,o(C=>C.map(I=>I.id===n?{...I,data:{...I.data,value:y}}:I)))}else window.BorealisValueBus[n]=r.current};c=setInterval(p,i);const l=setInterval(()=>{const h=window.BorealisUpdateRate||100;h!==i&&(clearInterval(c),i=h,c=setInterval(p,i))},250);return()=>{clearInterval(c),clearInterval(l)}},[n,o,a]),e.jsxs("div",{className:"borealis-node",children:[e.jsx(De,{type:"target",position:ze.Left,className:"borealis-handle"}),e.jsx("div",{className:"borealis-node-header",style:{display:"flex",justifyContent:"space-between",alignItems:"center"},children:e.jsx("span",{children:(t==null?void 0:t.label)||"Data Node"})}),e.jsxs("div",{className:"borealis-node-content",style:{fontSize:"9px",color:"#ccc",marginTop:4},children:["Value: ",d]}),e.jsx(De,{type:"source",position:ze.Right,className:"borealis-handle"})]})},Wa={type:"DataNode",label:"String / Number",description:`Foundational node for live value propagation.
|
||
|
||
- Accepts input or manual value
|
||
- Pushes downstream
|
||
- Uses shared memory`,content:"Store a String or Number",component:Ua,config:[{key:"value",label:"Value",type:"text"}],usage_documentation:`
|
||
### Description:
|
||
This node acts as a basic live data emitter. When connected to an upstream node, it inherits its value, otherwise it accepts user-defined input of either a number or a string.
|
||
|
||
**Acceptable Inputs**:
|
||
- **Static Value** (*Number or String*)
|
||
|
||
**Behavior**:
|
||
- **Pass-through Conduit** (*If Upstream Node is Connected*) > Value cannot be manually changed while connected to an upstream node.
|
||
- Uses global Borealis "**Update Rate**" for updating value if connected to an upstream node.
|
||
`.trim()},Va=Object.freeze(Object.defineProperty({__proto__:null,default:Wa},Symbol.toStringTag,{value:"Module"}));window.BorealisValueBus||(window.BorealisValueBus={});window.BorealisUpdateRate||(window.BorealisUpdateRate=100);const Ha=({id:n,data:t})=>{const{setNodes:o}=dt(),a=mt(i=>i.edges),[d,u]=s.useState("0"),r=s.useRef("0");return s.useEffect(()=>{let i=window.BorealisUpdateRate,c=null;const p=()=>{let h=(t==null?void 0:t.inputType)||"Number",f=(t==null?void 0:t.operator)||"Equal (==)",y=t==null?void 0:t.rangeStart,C=t==null?void 0:t.rangeEnd;h==="String"&&!["Equal (==)","Not Equal (!=)"].includes(f)&&(f="Equal (==)",o(x=>x.map(S=>S.id===n?{...S,data:{...S.data,operator:f}}:S)));const I=a.filter(x=>(x==null?void 0:x.target)===n&&x.targetHandle==="a"),k=a.filter(x=>(x==null?void 0:x.target)===n&&x.targetHandle==="b"),v=x=>{const S=x.map(z=>window.BorealisValueBus[z.source]).filter(z=>z!==void 0);return h==="Number"?S.reduce((z,E)=>z+(parseFloat(E)||0),0):S.join("")},j=v(I),B=v(k);let R="0";if(f==="Within Range"){const x=parseFloat(j),S=parseFloat(y),z=parseFloat(C);!isNaN(x)&&!isNaN(S)&&!isNaN(z)&&S<=z?R=x>=S&&x<=z?"1":"0":R="0"}else R={"Equal (==)":j===B,"Not Equal (!=)":j!==B,"Greater Than (>)":j>B,"Less Than (<)":j<B,"Greater Than or Equal (>=)":j>=B,"Less Than or Equal (<=)":j<=B}[f]?"1":"0";r.current=R,u(R),window.BorealisValueBus[n]=R,o(x=>x.map(S=>S.id===n?{...S,data:{...S.data,value:R}}:S))};c=setInterval(p,i);const l=setInterval(()=>{const h=window.BorealisUpdateRate;h!==i&&(clearInterval(c),i=h,c=setInterval(p,i))},250);return()=>{clearInterval(c),clearInterval(l)}},[n,a,t==null?void 0:t.inputType,t==null?void 0:t.operator,t==null?void 0:t.rangeStart,t==null?void 0:t.rangeEnd,o]),e.jsxs("div",{className:"borealis-node",children:[e.jsx("div",{style:{position:"absolute",left:-16,top:12,fontSize:"8px",color:"#ccc"},children:"A"}),e.jsx("div",{style:{position:"absolute",left:-16,top:50,fontSize:"8px",color:"#ccc"},children:"B"}),e.jsx(De,{type:"target",position:ze.Left,id:"a",style:{top:12},className:"borealis-handle"}),e.jsx(De,{type:"target",position:ze.Left,id:"b",style:{top:50},className:"borealis-handle"}),e.jsx("div",{className:"borealis-node-header",style:{display:"flex",justifyContent:"space-between",alignItems:"center"},children:e.jsx("span",{children:(t==null?void 0:t.label)||"Logic Comparison"})}),e.jsxs("div",{className:"borealis-node-content",style:{fontSize:"9px",color:"#ccc",marginTop:4},children:["Result: ",d]}),e.jsx(De,{type:"source",position:ze.Right,className:"borealis-handle"})]})},Ga={type:"ComparisonNode",label:"Logic Comparison",description:"Compare A vs B using logic operators, with range support.",content:"Compare A and B using Logic, with new range operator.",component:Ha,config:[{key:"inputType",label:"Input Type",type:"select",options:["Number","String"]},{key:"operator",label:"Operator",type:"select",options:["Equal (==)","Not Equal (!=)","Greater Than (>)","Less Than (<)","Greater Than or Equal (>=)","Less Than or Equal (<=)","Within Range"]},{key:"rangeStart",label:"Range Start",type:"text"},{key:"rangeEnd",label:"Range End",type:"text"}],usage_documentation:`
|
||
### Logic Comparison Node
|
||
|
||
This node compares two inputs (A and B) using the selected operator, including a numeric range.
|
||
|
||
**Modes:**
|
||
- **Number**: Sums all connected inputs and compares.
|
||
- **String**: Concatenates all inputs for comparison.
|
||
- Only **Equal (==)** and **Not Equal (!=)** are valid for strings.
|
||
- **Within Range**: If operator is "Within Range", compares if input A is within [Range Start, Range End] (inclusive).
|
||
|
||
**Output:**
|
||
- Returns \`1\` if comparison is true.
|
||
- Returns \`0\` if comparison is false.
|
||
|
||
**Input Notes:**
|
||
- A and B can each have multiple inputs.
|
||
- Input order matters for strings (concatenation).
|
||
- Input handles:
|
||
- **A** = Top left
|
||
- **B** = Middle left
|
||
|
||
**"Within Range" Operator:**
|
||
- Only works for **Number** input type.
|
||
- Enter "Range Start" and "Range End" in the right sidebar.
|
||
- The result is \`1\` if A >= Range Start AND A <= Range End (inclusive).
|
||
- Result is \`0\` if out of range or values are invalid.
|
||
|
||
**Example:**
|
||
- Range Start: 33
|
||
- Range End: 77
|
||
- A: 44 -> 1 (true, in range)
|
||
- A: 88 -> 0 (false, out of range)
|
||
`.trim()},qa=Object.freeze(Object.defineProperty({__proto__:null,default:Ga},Symbol.toStringTag,{value:"Module"}));window.BorealisValueBus||(window.BorealisValueBus={});window.BorealisUpdateRate||(window.BorealisUpdateRate=100);const Ja=({id:n,data:t})=>{const{setNodes:o}=dt(),a=mt(i=>i.edges),[d,u]=s.useState((t==null?void 0:t.value)||"0"),r=s.useRef(d);return s.useEffect(()=>{let i=null,c=window.BorealisUpdateRate;const p=()=>{const h=(t==null?void 0:t.operator)||"Add",f=a.filter(j=>j.target===n&&j.targetHandle==="a"),y=a.filter(j=>j.target===n&&j.targetHandle==="b"),C=j=>j.map(B=>parseFloat(window.BorealisValueBus[B.source])||0).reduce((B,R)=>B+R,0),I=C(f),k=C(y);let v=0;switch(h){case"Add":v=I+k;break;case"Subtract":v=I-k;break;case"Multiply":v=I*k;break;case"Divide":v=k!==0?I/k:0;break;case"Average":const j=f.length+y.length,B=I+k;v=j>0?B/j:0;break}r.current=v,u(v.toString()),window.BorealisValueBus[n]=v.toString(),o(j=>j.map(B=>B.id===n?{...B,data:{...B.data,value:v.toString()}}:B))};i=setInterval(p,c);const l=setInterval(()=>{const h=window.BorealisUpdateRate;h!==c&&(clearInterval(i),c=h,i=setInterval(p,c))},250);return()=>{clearInterval(i),clearInterval(l)}},[n,a,o,t==null?void 0:t.operator]),e.jsxs("div",{className:"borealis-node",children:[e.jsx("div",{style:{position:"absolute",left:-16,top:12,fontSize:"8px",color:"#ccc"},children:"A"}),e.jsx("div",{style:{position:"absolute",left:-16,top:50,fontSize:"8px",color:"#ccc"},children:"B"}),e.jsx(De,{type:"target",position:ze.Left,id:"a",style:{top:12},className:"borealis-handle"}),e.jsx(De,{type:"target",position:ze.Left,id:"b",style:{top:50},className:"borealis-handle"}),e.jsx("div",{className:"borealis-node-header",style:{display:"flex",justifyContent:"space-between",alignItems:"center"},children:e.jsx("span",{children:(t==null?void 0:t.label)||"Math Operation"})}),e.jsxs("div",{className:"borealis-node-content",style:{fontSize:"9px",color:"#ccc",marginTop:4},children:["Result: ",d]}),e.jsx(De,{type:"source",position:ze.Right,className:"borealis-handle"})]})},Ya={type:"MathNode",label:"Math Operation",description:`
|
||
Live math node for computing on two grouped inputs.
|
||
|
||
- Sums all A and B handle inputs separately
|
||
- Performs selected math operation: Add, Subtract, Multiply, Divide, Average
|
||
- Emits result as string via BorealisValueBus
|
||
- Updates at the global update rate
|
||
|
||
**Common Uses:**
|
||
Live dashboard math, sensor fusion, calculation chains, dynamic thresholds
|
||
`.trim(),content:"Perform Math Operations",component:Ja,config:[{key:"operator",label:"Operator",type:"select",options:["Add","Subtract","Multiply","Divide","Average"]}],usage_documentation:`
|
||
### Math Operation Node
|
||
|
||
Performs live math between two groups of inputs (**A** and **B**).
|
||
|
||
#### Usage
|
||
|
||
- Connect any number of nodes to the **A** and **B** input handles.
|
||
- The node **sums all values** from A and from B before applying the operator.
|
||
- Select the math operator in the sidebar config:
|
||
- **Add**: A + B
|
||
- **Subtract**: A - B
|
||
- **Multiply**: A * B
|
||
- **Divide**: A / B (0 if B=0)
|
||
- **Average**: (A + B) / total number of inputs
|
||
|
||
#### Output
|
||
|
||
- The computed result is pushed as a string to downstream nodes every update tick.
|
||
|
||
#### Input Handles
|
||
|
||
- **A** (Top Left)
|
||
- **B** (Middle Left)
|
||
|
||
#### Example
|
||
|
||
If three nodes outputting 5, 10, 15 are connected to A,
|
||
and one node outputs 2 is connected to B,
|
||
and operator is Multiply:
|
||
|
||
- **A** = 5 + 10 + 15 = 30
|
||
- **B** = 2
|
||
- **Result** = 30 * 2 = 60
|
||
|
||
`.trim()},Ka=Object.freeze(Object.defineProperty({__proto__:null,default:Ya},Symbol.toStringTag,{value:"Module"}));window.BorealisValueBus||(window.BorealisValueBus={});window.BorealisUpdateRate||(window.BorealisUpdateRate=100);const Xa=({id:n})=>{const t=mt(c=>c.edges),[o,a]=s.useState(100),d=s.useRef(""),[u,r]=s.useState(""),i=(c,p)=>new Promise(l=>{const h=new Image;h.crossOrigin="anonymous",h.onload=()=>{const f=document.createElement("canvas");f.width=h.width,f.height=h.height;const y=f.getContext("2d");y.drawImage(h,0,0);const C=y.getImageData(0,0,f.width,f.height),I=C.data,k=259*(p+255)/(255*(259-p));for(let v=0;v<I.length;v+=4)I[v]=k*(I[v]-128)+128,I[v+1]=k*(I[v+1]-128)+128,I[v+2]=k*(I[v+2]-128)+128;y.putImageData(C,0,0),l(f.toDataURL("image/png").replace(/^data:image\/png;base64,/,""))},h.onerror=()=>l(c),h.src=`data:image/png;base64,${c}`});return s.useEffect(()=>{const c=t.find(l=>l.target===n);if(!(c!=null&&c.source))return;const p=window.BorealisValueBus[c.source]??"";p&&i(p,o).then(l=>{r(l),window.BorealisValueBus[n]=l})},[o,t,n]),s.useEffect(()=>{let c=null;return c=setInterval(async()=>{const l=t.find(f=>f.target===n),h=l?window.BorealisValueBus[l.source]:"";if(h&&h!==d.current){const f=await i(h,o);d.current=h,r(f),window.BorealisValueBus[n]=f}},window.BorealisUpdateRate),()=>clearInterval(c)},[n,o,t]),e.jsxs("div",{className:"borealis-node",children:[e.jsx(De,{type:"target",position:ze.Left,className:"borealis-handle"}),e.jsx("div",{className:"borealis-node-header",children:"Adjust Contrast"}),e.jsxs("div",{className:"borealis-node-content",style:{fontSize:"9px"},children:[e.jsx("label",{children:"Contrast (1–255):"}),e.jsx("input",{type:"number",min:"1",max:"255",value:o,onChange:c=>a(parseInt(c.target.value)||100),style:{width:"100%",fontSize:"9px",padding:"4px",background:"#1e1e1e",color:"#ccc",border:"1px solid #444",borderRadius:"2px",marginTop:"4px"}})]}),e.jsx(De,{type:"source",position:ze.Right,className:"borealis-handle"})]})},Qa={type:"ContrastNode",label:"Adjust Contrast",description:"Modify contrast of base64 image using a contrast multiplier.",content:"Adjusts contrast of image using canvas pixel transform.",component:Xa},Za=Object.freeze(Object.defineProperty({__proto__:null,default:Qa},Symbol.toStringTag,{value:"Module"}));window.BorealisValueBus||(window.BorealisValueBus={});window.BorealisUpdateRate||(window.BorealisUpdateRate=100);const ei=({id:n,data:t})=>{const o=mt(f=>f.edges),a=parseInt(t==null?void 0:t.value,10),[d,u]=s.useState(isNaN(a)?128:a),[r,i]=s.useState(""),c=s.useRef(""),p=s.useRef("");s.useEffect(()=>{const f=parseInt(t==null?void 0:t.value,10);isNaN(f)||u(f)},[t==null?void 0:t.value]);const l=f=>{let y=parseInt(f.target.value,10);isNaN(y)&&(y=128),y=Math.max(0,Math.min(255,y)),t.value=y,u(y),window.BorealisValueBus[n]=y},h=async(f,y)=>!f||typeof f!="string"?"":new Promise(C=>{const I=new Image;I.crossOrigin="anonymous",I.onload=()=>{const k=document.createElement("canvas");k.width=I.width,k.height=I.height;const v=k.getContext("2d");v.drawImage(I,0,0);const j=v.getImageData(0,0,k.width,k.height),B=j.data;for(let R=0;R<B.length;R+=4){const S=(B[R]+B[R+1]+B[R+2])/3<y?0:255;B[R]=S,B[R+1]=S,B[R+2]=S}v.putImageData(j,0,0),C(k.toDataURL("image/png").replace(/^data:image\/png;base64,/,""))},I.onerror=()=>C(f),I.src="data:image/png;base64,"+f});return s.useEffect(()=>{let f=window.BorealisUpdateRate,y=null;const C=async()=>{const k=o.find(v=>v.target===n);if(k!=null&&k.source){const v=window.BorealisValueBus[k.source]??"";if(v!==p.current){const j=await h(v,d);p.current=v,c.current=j,i(j),window.BorealisValueBus[n]=j}}else p.current="",c.current="",i(""),window.BorealisValueBus[n]=""};y=setInterval(C,f);const I=setInterval(()=>{const k=window.BorealisUpdateRate;k!==f&&(clearInterval(y),f=k,y=setInterval(C,f))},250);return()=>{clearInterval(y),clearInterval(I)}},[n,o,d]),s.useEffect(()=>{const f=o.find(C=>C.target===n);if(!(f!=null&&f.source))return;const y=window.BorealisValueBus[f.source]??"";y&&h(y,d).then(C=>{c.current=C,i(C),window.BorealisValueBus[n]=C})},[d,o,n]),e.jsxs("div",{className:"borealis-node",children:[e.jsx(De,{type:"target",position:ze.Left,className:"borealis-handle"}),e.jsx("div",{className:"borealis-node-header",children:"BW Threshold"}),e.jsxs("div",{className:"borealis-node-content",style:{fontSize:"9px"},children:[e.jsx("div",{style:{marginBottom:"6px",color:"#ccc"},children:"Threshold Strength (0–255):"}),e.jsx("input",{type:"number",min:"0",max:"255",value:d,onChange:l,style:{width:"100%",fontSize:"9px",padding:"4px",background:"#1e1e1e",color:"#ccc",border:"1px solid #444",borderRadius:"2px",marginBottom:"6px"}})]}),e.jsx(De,{type:"source",position:ze.Right,className:"borealis-handle"})]})},ti={type:"BWThresholdNode",label:"BW Threshold",description:`
|
||
Black & White Threshold (Stateless)
|
||
|
||
- Converts a base64 image to black & white using a user-defined threshold value
|
||
- Reapplies threshold when the number changes, even if image stays the same
|
||
- Outputs a new base64 PNG with BW transformation
|
||
`.trim(),content:"Applies black & white threshold to base64 image input.",component:ei},si=Object.freeze(Object.defineProperty({__proto__:null,default:ti},Symbol.toStringTag,{value:"Module"}));window.BorealisValueBus||(window.BorealisValueBus={});window.BorealisUpdateRate||(window.BorealisUpdateRate=100);const ni=({id:n})=>{const t=mt(p=>p.edges),[o,a]=s.useState(100),[d,u]=s.useState(""),r=s.useRef(""),i=(p,l)=>new Promise(h=>{const f=new Image;f.crossOrigin="anonymous",f.onload=()=>{const y=document.createElement("canvas");y.width=f.width,y.height=f.height;const C=y.getContext("2d");C.drawImage(f,0,0);const I=C.getImageData(0,0,y.width,y.height),k=I.data,v=l/100;for(let j=0;j<k.length;j+=4){const B=k[j],R=k[j+1],x=k[j+2],S=(B+R+x)/3;k[j]=B*(1-v)+S*v,k[j+1]=R*(1-v)+S*v,k[j+2]=x*(1-v)+S*v}C.putImageData(I,0,0),h(y.toDataURL("image/png").replace(/^data:image\/png;base64,/,""))},f.onerror=()=>h(p),f.src=`data:image/png;base64,${p}`});s.useEffect(()=>{const p=t.find(h=>h.target===n);if(!(p!=null&&p.source))return;const l=window.BorealisValueBus[p.source]??"";l&&i(l,o).then(h=>{r.current=l,u(h),window.BorealisValueBus[n]=h})},[o,t,n]),s.useEffect(()=>{let p=null;return p=setInterval(async()=>{const h=t.find(y=>y.target===n),f=h?window.BorealisValueBus[h.source]:"";if(f&&f!==r.current){const y=await i(f,o);r.current=f,u(y),window.BorealisValueBus[n]=y}},window.BorealisUpdateRate),()=>clearInterval(p)},[n,t,o]);const c=p=>{let l=parseInt(p.target.value,10);isNaN(l)&&(l=100),l=Math.min(100,Math.max(0,l)),a(l)};return e.jsxs("div",{className:"borealis-node",children:[e.jsx(De,{type:"target",position:ze.Left,className:"borealis-handle"}),e.jsx("div",{className:"borealis-node-header",children:"Convert to Grayscale"}),e.jsxs("div",{className:"borealis-node-content",style:{fontSize:"9px"},children:[e.jsx("label",{style:{display:"block",marginBottom:"4px"},children:"Grayscale Intensity (0–100):"}),e.jsx("input",{type:"number",min:"0",max:"100",step:"1",value:o,onChange:c,style:{width:"100%",fontSize:"9px",padding:"4px",background:"#1e1e1e",color:"#ccc",border:"1px solid #444",borderRadius:"2px"}})]}),e.jsx(De,{type:"source",position:ze.Right,className:"borealis-handle"})]})},oi={type:"GrayscaleNode",label:"Convert to Grayscale",description:`
|
||
Adjustable Grayscale Conversion
|
||
|
||
- Accepts base64 image input
|
||
- Applies grayscale effect using a % level
|
||
- 0% = no change, 100% = full grayscale
|
||
- Outputs result downstream as base64
|
||
`.trim(),content:"Convert image to grayscale with adjustable intensity.",component:ni},ri=Object.freeze(Object.defineProperty({__proto__:null,default:oi},Symbol.toStringTag,{value:"Module"})),ai=({id:n})=>{const{getEdges:t}=dt(),[o,a]=s.useState("");s.useEffect(()=>{const u=setInterval(()=>{var c;const i=t().find(p=>p.target===n);if(i){const p=(c=window.BorealisValueBus)==null?void 0:c[i.source];typeof p=="string"&&a(p)}},1e3);return()=>clearInterval(u)},[n,t]);const d=async()=>{const u=await(async()=>await(await fetch(`data:image/png;base64,${o}`)).blob())();if(window.showSaveFilePicker)try{const i=await(await window.showSaveFilePicker({suggestedName:"image.png",types:[{description:"PNG Image",accept:{"image/png":[".png"]}}]})).createWritable();await i.write(u),await i.close()}catch(r){console.warn("Save cancelled:",r)}else{const r=document.createElement("a");r.href=URL.createObjectURL(u),r.download="image.png",r.style.display="none",document.body.appendChild(r),r.click(),URL.revokeObjectURL(r.href),document.body.removeChild(r)}};return e.jsxs("div",{className:"borealis-node",children:[e.jsx(De,{type:"target",position:ze.Left,className:"borealis-handle"}),e.jsx("div",{className:"borealis-node-header",children:"Export Image"}),e.jsxs("div",{className:"borealis-node-content",style:{fontSize:"9px"},children:["Export upstream base64-encoded image data as a PNG on-disk.",e.jsx("button",{style:{marginTop:"6px",width:"100%",fontSize:"9px",padding:"4px",background:"#1e1e1e",color:"#ccc",border:"1px solid #444",borderRadius:"2px"},onClick:d,disabled:!o,children:"Download PNG"})]})]})},ii={type:"ExportImageNode",label:"Export Image",description:"Lets the user download the base64 PNG image to disk.",content:"Save base64 PNG to disk as a file.",component:ai},li=Object.freeze(Object.defineProperty({__proto__:null,default:ii},Symbol.toStringTag,{value:"Module"}));window.BorealisValueBus||(window.BorealisValueBus={});window.BorealisUpdateRate||(window.BorealisUpdateRate=100);const ci=({id:n})=>{const{getEdges:t}=dt(),[o,a]=s.useState(""),d=s.useRef(null),u=s.useRef(null),[r,i]=s.useState(!1);s.useEffect(()=>{const p=setInterval(()=>{const h=t().find(f=>f.target===n);if(h){const f=window.BorealisValueBus[h.source]||"";a(f),window.BorealisValueBus[n]=f}else a(""),window.BorealisValueBus[n]=""},window.BorealisUpdateRate);return()=>clearInterval(p)},[t,n]),s.useEffect(()=>{const p=d.current;if(!p)return;const l=p.getContext("2d");if(o){const h=new Image;h.onload=()=>{p.width=h.width,p.height=h.height,l.clearRect(0,0,p.width,p.height),l.drawImage(h,0,0)},h.src="data:image/png;base64,"+o}else l.clearRect(0,0,p.width,p.height)},[o]),s.useEffect(()=>{if(!r||!o)return;const p=document.createElement("div");u.current=p,Object.assign(p.style,{position:"fixed",top:"0",left:"0",width:"100%",height:"100%",backgroundColor:"rgba(0,0,0,0.8)",display:"flex",alignItems:"center",justifyContent:"center",zIndex:"1000",cursor:"zoom-out",transition:"opacity 0.3s ease"});const l=()=>i(!1);p.addEventListener("click",l);const h=document.createElement("canvas"),f=h.getContext("2d"),y=new Image;return y.onload=()=>{let C=y.width,I=y.height;const k=window.innerWidth*.8,v=window.innerHeight*.8,j=Math.min(1,k/C,v/I);h.width=C,h.height=I,f.clearRect(0,0,C,I),f.drawImage(y,0,0),h.style.width=`${C*j}px`,h.style.height=`${I*j}px`,h.style.transition="transform 0.3s ease"},y.src="data:image/png;base64,"+o,p.appendChild(h),document.body.appendChild(p),()=>{p.removeEventListener("click",l),u.current&&(document.body.removeChild(u.current),u.current=null)}},[r,o]);const c=()=>{o&&i(p=>!p)};return e.jsxs("div",{className:"borealis-node",children:[e.jsx(De,{type:"target",position:ze.Left,className:"borealis-handle"}),e.jsx("div",{className:"borealis-node-header",children:"Image Viewer"}),e.jsx("div",{className:"borealis-node-content",style:{cursor:o?"zoom-in":"default"},children:o?e.jsx("canvas",{ref:d,onClick:c,style:{width:"100%",border:"1px solid #333",marginTop:"6px",marginBottom:"6px"}}):e.jsx("div",{style:{fontSize:"9px",color:"#888",marginTop:"6px"},children:"Waiting for image..."})}),e.jsx(De,{type:"source",position:ze.Right,className:"borealis-handle"})]})},di={type:"Image_Viewer",label:"Image Viewer",description:`
|
||
Displays base64 image via canvas for high performance
|
||
|
||
- Accepts upstream base64 image
|
||
- Renders with canvas for speed
|
||
- Click to zoom/unzoom overlay with smooth transition
|
||
`.trim(),content:"Visual preview of base64 image with zoom overlay.",component:ci},ui=Object.freeze(Object.defineProperty({__proto__:null,default:di},Symbol.toStringTag,{value:"Module"}));window.BorealisValueBus||(window.BorealisValueBus={});window.BorealisUpdateRate||(window.BorealisUpdateRate=100);const pi=({id:n,data:t})=>{const{setNodes:o}=dt(),[a,d]=s.useState((t==null?void 0:t.value)||""),u=s.useRef(a),r=i=>{console.log("handleFileUpload triggered for node:",n);const c=i.target.files||i.currentTarget.files;if(!c||c.length===0){console.log("No files selected or files array is empty");return}const p=c[0];if(!p){console.log("File object not found");return}if(console.log("Selected file:",p.name,p.type,p.size),!["image/jpeg","image/png"].includes(p.type)){console.warn("Unsupported file type in node:",n,p.type);return}const h=new FileReader;h.onload=f=>{var I;console.log("FileReader onload in node:",n);const C=(((I=f==null?void 0:f.target)==null?void 0:I.result)||"").replace(/^data:image\/[a-zA-Z]+;base64,/,"");console.log("Raw Base64 (truncated):",C.substring(0,50)),u.current=C,d(C),window.BorealisValueBus[n]=C,o(k=>k.map(v=>v.id===n?{...v,data:{...v.data,value:C}}:v))},h.onerror=f=>{console.error("FileReader error in node:",n,f)},h.readAsDataURL(p)};return s.useEffect(()=>{let i=window.BorealisUpdateRate||100,c=null;const p=()=>{window.BorealisValueBus[n]=u.current},l=()=>{c=setInterval(p,i)};l();const h=setInterval(()=>{const f=window.BorealisUpdateRate||100;f!==i&&(i=f,clearInterval(c),l())},250);return()=>{clearInterval(c),clearInterval(h)}},[n,o]),e.jsxs("div",{className:"borealis-node",style:{minWidth:"160px"},children:[e.jsx("div",{className:"borealis-node-header",children:(t==null?void 0:t.label)||"Raw Base64 Image Upload"}),e.jsxs("div",{className:"borealis-node-content",children:[e.jsx("div",{style:{marginBottom:"8px",fontSize:"9px",color:"#ccc"},children:(t==null?void 0:t.content)||"Upload a JPG/PNG, store only the raw base64 in ValueBus."}),e.jsx("label",{style:{fontSize:"9px",display:"block",marginBottom:"4px"},children:"Upload Image File"}),e.jsx("input",{type:"file",accept:".jpg,.jpeg,.png",onChange:r,style:{fontSize:"9px",padding:"4px",background:"#1e1e1e",color:"#ccc",border:"1px solid #444",borderRadius:"2px",width:"100%",marginBottom:"8px"}})]}),e.jsx(De,{type:"source",position:ze.Right,className:"borealis-handle"})]})},fi={type:"ImageUploadNode_RawBase64",label:"Upload Image",description:`
|
||
A node to upload an image (JPG/PNG) and store it in base64 format for later use downstream.
|
||
`.trim(),content:"Upload an image, output only the raw base64 string.",component:pi},hi=Object.freeze(Object.defineProperty({__proto__:null,default:fi},Symbol.toStringTag,{value:"Module"})),mi=({id:n,data:t})=>{const[o,a]=s.useState((t==null?void 0:t.label)||"Backdrop Group Box"),[d,u]=s.useState(!1),r=s.useRef(null);s.useEffect(()=>{d&&r.current&&r.current.focus()},[d]);const i=l=>{l.stopPropagation(),u(!0)},c=l=>{const h=l.target.value;a(h),window.BorealisValueBus[n]=h},p=()=>{u(!1)};return e.jsx("div",{style:{pointerEvents:"auto"},children:e.jsxs(Hr,{width:200,height:120,minConstraints:[120,80],maxConstraints:[600,600],resizeHandles:["se"],className:"borealis-node",handle:l=>e.jsx("span",{className:`react-resizable-handle react-resizable-handle-${l}`,style:{pointerEvents:"auto"},onMouseDown:h=>h.stopPropagation(),onClick:h=>h.stopPropagation()}),onClick:l=>l.stopPropagation(),style:{backgroundColor:"rgba(44, 44, 44, 0.5)",border:"1px solid #3a3a3a",borderRadius:"4px",boxShadow:"0 0 5px rgba(88, 166, 255, 0.15)",overflow:"hidden",position:"relative",zIndex:0},children:[e.jsx("div",{onClick:i,style:{backgroundColor:"rgba(35, 35, 35, 0.5)",padding:"6px 10px",fontWeight:"bold",fontSize:"10px",cursor:"pointer",userSelect:"none"},children:d?e.jsx("input",{ref:r,type:"text",value:o,onChange:c,onBlur:p,onClick:l=>l.stopPropagation(),onMouseDown:l=>l.stopPropagation(),style:{fontSize:"10px",padding:"2px",background:"#1e1e1e",color:"#ccc",border:"1px solid #444",borderRadius:"2px",width:"100%"}}):e.jsx("span",{children:o})}),e.jsx("div",{style:{padding:"10px",fontSize:"9px",height:"100%"}})]})})},xi={type:"BackdropGroupBoxNode",label:"Backdrop Group Box",description:`
|
||
Resizable Grouping Node
|
||
|
||
- Purely cosmetic, for grouping related nodes
|
||
- Resizable by dragging bottom-right corner
|
||
- Rename by clicking on title bar
|
||
`.trim(),content:"Use as a visual group label",component:mi},gi=Object.freeze(Object.defineProperty({__proto__:null,default:xi},Symbol.toStringTag,{value:"Module"})),bi=({data:n})=>{const[t,o]=s.useState(""),[a,d]=s.useState(!1),[u,r]=s.useState(!1),i=s.useRef(null),c=()=>r(!0),p=()=>r(!1),l=async()=>{var f;if(window.showDirectoryPicker)try{const y=await window.showDirectoryPicker();o(y.name||"Selected Directory")}catch(y){console.warn("Directory Selection Cancelled:",y)}else(f=i.current)==null||f.click()},h=f=>{var C;const y=f.target.files;if(y.length>0){const I=(C=y[0].webkitRelativePath)==null?void 0:C.split("/")[0];o(I||"Selected Folder")}};return e.jsxs("div",{className:"borealis-node",children:[e.jsx(De,{type:"target",position:ze.Left,className:"borealis-handle"}),e.jsx("div",{className:"borealis-node-header",children:n.label}),e.jsxs("div",{className:"borealis-node-content",children:[e.jsx("div",{style:{marginBottom:"8px"},children:n.content}),e.jsx("label",{style:{fontSize:"9px",display:"block",marginTop:"6px"},children:"Export Path:"}),e.jsxs("div",{style:{display:"flex",gap:"4px",alignItems:"center",marginBottom:"6px"},children:[e.jsx("input",{type:"text",readOnly:!0,value:t,placeholder:"Click to Select Folder",onClick:l,style:{flex:1,fontSize:"9px",padding:"3px",background:"#1e1e1e",color:"#ccc",border:"1px solid #444",borderRadius:"2px",cursor:"pointer"}}),e.jsx(Z,{variant:"outlined",size:"small",onClick:c,sx:{fontSize:"9px",padding:"2px 8px",minWidth:"unset",borderColor:"#58a6ff",color:"#58a6ff"},children:"Export"})]}),e.jsxs("label",{style:{fontSize:"9px",display:"block",marginTop:"4px"},children:[e.jsx("input",{type:"checkbox",checked:a,onChange:f=>d(f.target.checked),style:{marginRight:"4px"}}),"Append CSV Data if Headers Match"]})]}),e.jsx("input",{ref:i,type:"file",webkitdirectory:"true",directory:"",multiple:!0,style:{display:"none"},onChange:h}),e.jsx(Fo,{open:u,autoHideDuration:1e3,onClose:p,message:"Feature Coming Soon...",anchorOrigin:{vertical:"bottom",horizontal:"center"}})]})},yi={type:"ExportToCSVNode",label:"Export to CSV",description:`
|
||
Reporting Node
|
||
This node lets the user choose a folder to export CSV data to disk.
|
||
|
||
When the "Export" button is clicked, CSV content (from upstream logic) is intended to be saved
|
||
to the selected directory. This is a placeholder for future file system interaction.
|
||
|
||
Inputs:
|
||
- Structured Table Data (via upstream node)
|
||
|
||
Outputs:
|
||
- None (writes directly to disk in future)
|
||
`.trim(),content:"Export Input Data to CSV File",component:bi},ji=Object.freeze(Object.defineProperty({__proto__:null,default:yi},Symbol.toStringTag,{value:"Module"})),wi=({id:n,data:t})=>{const{setNodes:o}=dt(),a=mt(l=>l.edges),[d,u]=s.useState((t==null?void 0:t.value)||"/Data/Server/WebUI/src/Nodes/Templates/Node_Template.jsx"),r=s.useRef(d),i=l=>{const h=l.target.value;r.current=h,u(h),window.BorealisValueBus[n]=h,o(f=>f.map(y=>y.id===n?{...y,data:{...y.data,value:h}}:y))};s.useEffect(()=>{let l=window.BorealisUpdateRate,h;const f=()=>{const C=a.find(k=>k.target===n);if(!!(C&&C.source)){const k=window.BorealisValueBus[C.source]||"";k!==r.current&&(r.current=k,u(k),window.BorealisValueBus[n]=k,o(v=>v.map(j=>j.id===n?{...j,data:{...j.data,value:k}}:j)))}else window.BorealisValueBus[n]=r.current};h=setInterval(f,l);const y=setInterval(()=>{const C=window.BorealisUpdateRate;C!==l&&(clearInterval(h),l=C,h=setInterval(f,l))},250);return()=>{clearInterval(h),clearInterval(y)}},[n,a,o]);const c=a.find(l=>l.target===n),p=!!(c&&c.source);return e.jsxs("div",{className:"borealis-node",children:[e.jsx(De,{type:"target",position:ze.Left,className:"borealis-handle"}),e.jsx("div",{className:"borealis-node-header",children:(t==null?void 0:t.label)||"Node Template"}),e.jsxs("div",{className:"borealis-node-content",children:[e.jsx("div",{style:{marginBottom:"8px",fontSize:"9px",color:"#ccc"},children:(t==null?void 0:t.content)||"Template acting as a design scaffold for designing nodes for Borealis."}),e.jsx("label",{style:{fontSize:"9px",display:"block",marginBottom:"4px"},children:"Template Location:"}),e.jsx("input",{type:"text",value:d,onChange:i,disabled:p,style:{fontSize:"9px",padding:"4px",background:p?"#2a2a2a":"#1e1e1e",color:"#ccc",border:"1px solid #444",borderRadius:"2px",width:"100%"}})]}),e.jsx(De,{type:"source",position:ze.Right,className:"borealis-handle"})]})},vi={type:"Node_Template",label:"Node Template",description:"Node structure template to be used as a scaffold when building new nodes for Borealis.",content:"Template acting as a design scaffold for designing nodes for Borealis.",component:wi},Si=Object.freeze(Object.defineProperty({__proto__:null,default:vi},Symbol.toStringTag,{value:"Module"}));function Ci({open:n,onClose:t,onConfirm:o}){return e.jsxs(Ze,{open:n,onClose:t,PaperProps:{sx:{bgcolor:"#121212",color:"#fff"}},children:[e.jsx(et,{children:"Close All Flow Tabs?"}),e.jsx(rt,{children:e.jsx($t,{sx:{color:"#ccc"},children:"This will remove all existing flow tabs and create a fresh tab named Flow 1."})}),e.jsxs(tt,{children:[e.jsx(Z,{onClick:t,sx:{color:"#58a6ff"},children:"Cancel"}),e.jsx(Z,{onClick:o,sx:{color:"#ff4f4f"},children:"Close All"})]})]})}function _i({open:n,onClose:t}){return e.jsxs(Ze,{open:n,onClose:t,PaperProps:{sx:{bgcolor:"#121212",color:"#fff"}},children:[e.jsx(et,{children:"Not Authorized"}),e.jsx(rt,{children:e.jsx($t,{sx:{color:"#ccc"},children:"You are not authorized to access this section."})}),e.jsx(tt,{children:e.jsx(Z,{onClick:t,sx:{color:"#58a6ff"},children:"OK"})})]})}function ki({open:n,onClose:t}){return e.jsxs(Ze,{open:n,onClose:t,PaperProps:{sx:{bgcolor:"#121212",color:"#fff"}},children:[e.jsxs(rt,{sx:{textAlign:"center",pt:3},children:[e.jsx("img",{src:"/Borealis_Logo.png",alt:"Borealis Logo",style:{width:"120px",marginBottom:"12px"}}),e.jsx(et,{sx:{p:0,mb:1},children:"Borealis - Automation Platform"}),e.jsxs($t,{sx:{color:"#ccc"},children:["Designed by Nicole Rappe @"," ",e.jsx("a",{href:"https://bunny-lab.io",target:"_blank",rel:"noopener noreferrer",style:{color:"#58a6ff",textDecoration:"none"},children:"Bunny Lab"})]})]}),e.jsx(tt,{children:e.jsx(Z,{onClick:t,sx:{color:"#58a6ff"},children:"Close"})})]})}function Ii({open:n,value:t,onChange:o,onCancel:a,onSave:d}){return e.jsxs(Ze,{open:n,onClose:a,PaperProps:{sx:{bgcolor:"#121212",color:"#fff"}},children:[e.jsx(et,{children:"Rename Tab"}),e.jsx(rt,{children:e.jsx(Ie,{autoFocus:!0,margin:"dense",label:"Tab Name",fullWidth:!0,variant:"outlined",value:t,onChange:u=>o(u.target.value),sx:{"& .MuiOutlinedInput-root":{backgroundColor:"#2a2a2a",color:"#ccc","& fieldset":{borderColor:"#444"},"&:hover fieldset":{borderColor:"#666"}},label:{color:"#aaa"},mt:1}})}),e.jsxs(tt,{children:[e.jsx(Z,{onClick:a,sx:{color:"#58a6ff"},children:"Cancel"}),e.jsx(Z,{onClick:d,sx:{color:"#58a6ff"},children:"Save"})]})]})}function Ri({open:n,value:t,onChange:o,onCancel:a,onSave:d}){return e.jsxs(Ze,{open:n,onClose:a,PaperProps:{sx:{bgcolor:"#121212",color:"#fff"}},children:[e.jsx(et,{children:"Rename Workflow"}),e.jsx(rt,{children:e.jsx(Ie,{autoFocus:!0,margin:"dense",label:"Workflow Name",fullWidth:!0,variant:"outlined",value:t,onChange:u=>o(u.target.value),sx:{"& .MuiOutlinedInput-root":{backgroundColor:"#2a2a2a",color:"#ccc","& fieldset":{borderColor:"#444"},"&:hover fieldset":{borderColor:"#666"}},label:{color:"#aaa"},mt:1}})}),e.jsxs(tt,{children:[e.jsx(Z,{onClick:a,sx:{color:"#58a6ff"},children:"Cancel"}),e.jsx(Z,{onClick:d,sx:{color:"#58a6ff"},children:"Save"})]})]})}function wo({open:n,value:t,onChange:o,onCancel:a,onSave:d,title:u="Folder Name",confirmText:r="Save"}){return e.jsxs(Ze,{open:n,onClose:a,PaperProps:{sx:{bgcolor:"#121212",color:"#fff"}},children:[e.jsx(et,{children:u}),e.jsx(rt,{children:e.jsx(Ie,{autoFocus:!0,margin:"dense",label:"Folder Name",fullWidth:!0,variant:"outlined",value:t,onChange:i=>o(i.target.value),sx:{"& .MuiOutlinedInput-root":{backgroundColor:"#2a2a2a",color:"#ccc","& fieldset":{borderColor:"#444"},"&:hover fieldset":{borderColor:"#666"}},label:{color:"#aaa"},mt:1}})}),e.jsxs(tt,{children:[e.jsx(Z,{onClick:a,sx:{color:"#58a6ff"},children:"Cancel"}),e.jsx(Z,{onClick:d,sx:{color:"#58a6ff"},children:r})]})]})}function Ni({open:n,value:t,onChange:o,onCancel:a,onCreate:d}){return e.jsxs(Ze,{open:n,onClose:a,PaperProps:{sx:{bgcolor:"#121212",color:"#fff"}},children:[e.jsx(et,{children:"New Workflow"}),e.jsx(rt,{children:e.jsx(Ie,{autoFocus:!0,margin:"dense",label:"Workflow Name",fullWidth:!0,variant:"outlined",value:t,onChange:u=>o(u.target.value),sx:{"& .MuiOutlinedInput-root":{backgroundColor:"#2a2a2a",color:"#ccc","& fieldset":{borderColor:"#444"},"&:hover fieldset":{borderColor:"#666"}},label:{color:"#aaa"},mt:1}})}),e.jsxs(tt,{children:[e.jsx(Z,{onClick:a,sx:{color:"#58a6ff"},children:"Cancel"}),e.jsx(Z,{onClick:d,sx:{color:"#58a6ff"},children:"Create"})]})]})}function Ti({open:n,onCancel:t,onConfirm:o}){return e.jsxs(Ze,{open:n,onClose:t,PaperProps:{sx:{bgcolor:"#121212",color:"#fff"}},children:[e.jsx(et,{children:"Clear Device Activity"}),e.jsx(rt,{children:e.jsx($t,{sx:{color:"#ccc"},children:"All device activity history will be cleared, are you sure?"})}),e.jsxs(tt,{children:[e.jsx(Z,{onClick:t,sx:{color:"#58a6ff"},children:"Cancel"}),e.jsx(Z,{onClick:o,sx:{color:"#ff4f4f"},children:"Clear"})]})]})}function Ai({open:n,value:t,onChange:o,onCancel:a,onSave:d}){return e.jsxs(Ze,{open:n,onClose:a,PaperProps:{sx:{bgcolor:"#121212",color:"#fff"}},children:[e.jsx(et,{children:"Save Workflow"}),e.jsx(rt,{children:e.jsx(Ie,{autoFocus:!0,margin:"dense",label:"Workflow Name",fullWidth:!0,variant:"outlined",value:t,onChange:u=>o(u.target.value),sx:{"& .MuiOutlinedInput-root":{backgroundColor:"#2a2a2a",color:"#ccc","& fieldset":{borderColor:"#444"},"&:hover fieldset":{borderColor:"#666"}},label:{color:"#aaa"},mt:1}})}),e.jsxs(tt,{children:[e.jsx(Z,{onClick:a,sx:{color:"#58a6ff"},children:"Cancel"}),e.jsx(Z,{onClick:d,sx:{color:"#58a6ff"},children:"Save"})]})]})}function Zt({open:n,message:t,onCancel:o,onConfirm:a}){return e.jsxs(Ze,{open:n,onClose:o,PaperProps:{sx:{bgcolor:"#121212",color:"#fff"}},children:[e.jsx(et,{children:"Confirm Delete"}),e.jsx(rt,{children:e.jsx($t,{sx:{color:"#ccc"},children:t})}),e.jsxs(tt,{children:[e.jsx(Z,{onClick:o,sx:{color:"#58a6ff"},children:"Cancel"}),e.jsx(Z,{onClick:a,sx:{color:"#58a6ff"},children:"Confirm"})]})]})}function Bi({open:n,onCancel:t,onConfirm:o}){return e.jsxs(Ze,{open:n,onClose:t,PaperProps:{sx:{bgcolor:"#121212",color:"#fff"}},children:[e.jsx(et,{children:"Remove Device"}),e.jsx(rt,{children:e.jsx($t,{sx:{color:"#ccc"},children:"Are you sure you want to remove this device? If the agent is still running, it will automatically re-enroll the device."})}),e.jsxs(tt,{children:[e.jsx(Z,{onClick:t,sx:{color:"#58a6ff"},children:"Cancel"}),e.jsx(Z,{onClick:o,sx:{bgcolor:"#ff4f4f",color:"#fff","&:hover":{bgcolor:"#e04444"}},children:"Remove"})]})]})}function Oi({anchor:n,onClose:t,onRename:o,onCloseTab:a}){return e.jsxs(Et,{open:!!n,onClose:t,anchorReference:"anchorPosition",anchorPosition:n?{top:n.y,left:n.x}:void 0,PaperProps:{sx:{bgcolor:"#1e1e1e",color:"#fff",fontSize:"13px"}},children:[e.jsx(fe,{onClick:o,children:"Rename"}),e.jsx(fe,{onClick:a,children:"Close Workflow"})]})}function Pi({open:n,value:t,onChange:o,onCancel:a,onSave:d}){return e.jsxs(Ze,{open:n,onClose:a,PaperProps:{sx:{bgcolor:"#121212",color:"#fff"}},children:[e.jsx(et,{children:"Create a New Custom View"}),e.jsxs(rt,{children:[e.jsx($t,{sx:{color:"#ccc",mb:1},children:"Saving a view will save column order, visibility, and filters."}),e.jsx(Ie,{autoFocus:!0,fullWidth:!0,margin:"dense",label:"View Name",variant:"outlined",value:t,onChange:u=>o(u.target.value),placeholder:"Add a name for this custom view",sx:{"& .MuiOutlinedInput-root":{backgroundColor:"#2a2a2a",color:"#ccc","& fieldset":{borderColor:"#444"},"&:hover fieldset":{borderColor:"#666"}},label:{color:"#aaa"},mt:1}})]}),e.jsxs(tt,{children:[e.jsx(Z,{onClick:a,sx:{color:"#58a6ff"},children:"Cancel"}),e.jsx(Z,{onClick:d,sx:{color:"#58a6ff"},children:"Save"})]})]})}function Ei({open:n,value:t,onChange:o,onCancel:a,onSave:d}){return e.jsxs(Ze,{open:n,onClose:a,PaperProps:{sx:{bgcolor:"#121212",color:"#fff"}},children:[e.jsx(et,{children:"Rename Custom View"}),e.jsx(rt,{children:e.jsx(Ie,{autoFocus:!0,fullWidth:!0,margin:"dense",label:"View Name",variant:"outlined",value:t,onChange:u=>o(u.target.value),sx:{"& .MuiOutlinedInput-root":{backgroundColor:"#2a2a2a",color:"#ccc","& fieldset":{borderColor:"#444"},"&:hover fieldset":{borderColor:"#666"}},label:{color:"#aaa"},mt:1}})}),e.jsxs(tt,{children:[e.jsx(Z,{onClick:a,sx:{color:"#58a6ff"},children:"Cancel"}),e.jsx(Z,{onClick:d,sx:{color:"#58a6ff"},children:"Save"})]})]})}function Mi({open:n,onCancel:t,onCreate:o}){const[a,d]=es.useState(""),[u,r]=es.useState("");return es.useEffect(()=>{n&&(d(""),r(""))},[n]),e.jsxs(Ze,{open:n,onClose:t,PaperProps:{sx:{bgcolor:"#121212",color:"#fff"}},children:[e.jsx(et,{children:"Create Site"}),e.jsxs(rt,{children:[e.jsx($t,{sx:{color:"#ccc",mb:1},children:"Create a new site and optionally add a description."}),e.jsx(Ie,{autoFocus:!0,fullWidth:!0,margin:"dense",label:"Site Name",variant:"outlined",value:a,onChange:i=>d(i.target.value),sx:{"& .MuiOutlinedInput-root":{backgroundColor:"#2a2a2a",color:"#ccc","& fieldset":{borderColor:"#444"},"&:hover fieldset":{borderColor:"#666"}},label:{color:"#aaa"},mt:1}}),e.jsx(Ie,{fullWidth:!0,multiline:!0,minRows:3,margin:"dense",label:"Description",variant:"outlined",value:u,onChange:i=>r(i.target.value),sx:{"& .MuiOutlinedInput-root":{backgroundColor:"#2a2a2a",color:"#ccc","& fieldset":{borderColor:"#444"},"&:hover fieldset":{borderColor:"#666"}},label:{color:"#aaa"},mt:2}})]}),e.jsxs(tt,{children:[e.jsx(Z,{onClick:t,sx:{color:"#58a6ff"},children:"Cancel"}),e.jsx(Z,{onClick:()=>{const i=(a||"").trim();i&&o&&o(i,u||"")},sx:{color:"#58a6ff"},children:"Create"})]})]})}function Di({open:n,value:t,onChange:o,onCancel:a,onSave:d}){return e.jsxs(Ze,{open:n,onClose:a,PaperProps:{sx:{bgcolor:"#121212",color:"#fff"}},children:[e.jsx(et,{children:"Rename Site"}),e.jsx(rt,{children:e.jsx(Ie,{autoFocus:!0,fullWidth:!0,margin:"dense",label:"Site Name",variant:"outlined",value:t,onChange:u=>o(u.target.value),sx:{"& .MuiOutlinedInput-root":{backgroundColor:"#2a2a2a",color:"#ccc","& fieldset":{borderColor:"#444"},"&:hover fieldset":{borderColor:"#666"}},label:{color:"#aaa"},mt:1}})}),e.jsxs(tt,{children:[e.jsx(Z,{onClick:a,sx:{color:"#58a6ff"},children:"Cancel"}),e.jsx(Z,{onClick:d,sx:{color:"#58a6ff"},children:"Save"})]})]})}function zi({currentPage:n,onNavigate:t,isAdmin:o=!1}){const[a,d]=s.useState({sites:!0,devices:!0,automation:!0,filters:!0,access:!0,admin:!0}),u=({icon:r,label:i,pageKey:c,indent:p=0})=>{const l=n===c;return e.jsxs(Ko,{onClick:()=>t(c),sx:{pl:p?4:2,py:1,color:l?"#e6f2ff":"#ccc",position:"relative",background:l?"linear-gradient(90deg, rgba(88,166,255,0.10) 0%, rgba(88,166,255,0.03) 60%, rgba(88,166,255,0.00) 100%)":"transparent",borderTopRightRadius:0,borderBottomRightRadius:0,boxShadow:l?"inset 0 0 0 1px rgba(88,166,255,0.25)":"none",transition:"background 160ms ease, box-shadow 160ms ease, color 160ms ease","&:hover":{background:l?"linear-gradient(90deg, rgba(88,166,255,0.14) 0%, rgba(88,166,255,0.06) 60%, rgba(88,166,255,0.00) 100%)":"#2c2c2c"}},selected:l,children:[e.jsx(m,{sx:{position:"absolute",left:0,top:0,bottom:0,width:l?3:0,bgcolor:"#58a6ff",borderTopRightRadius:2,borderBottomRightRadius:2,boxShadow:l?"0 0 6px rgba(88,166,255,0.35)":"none",transition:"width 180ms ease, box-shadow 200ms ease"}}),r&&e.jsx(m,{sx:{mr:1,display:"flex",alignItems:"center",color:l?"#7db7ff":"#58a6ff",transition:"color 160ms ease"},children:r}),e.jsx(tn,{primary:i,primaryTypographyProps:{fontSize:"0.75rem",fontWeight:l?600:400}})]})};return e.jsx(m,{sx:{width:260,bgcolor:"#121212",borderRight:"1px solid #333",display:"flex",flexDirection:"column",overflow:"hidden"},children:e.jsxs(m,{sx:{flex:1,overflowY:"auto"},children:[(()=>{const r=n==="sites";return e.jsxs(as,{expanded:a.sites,onChange:(i,c)=>d(p=>({...p,sites:c})),square:!0,disableGutters:!0,sx:{"&:before":{display:"none"},margin:0,border:0},children:[e.jsx(is,{expandIcon:e.jsx(ls,{}),sx:{position:"relative",background:r?"linear-gradient(90deg, rgba(88,166,255,0.08) 0%, rgba(88,166,255,0.00) 100%)":"#2c2c2c",minHeight:"36px","& .MuiAccordionSummary-content":{margin:0},"&::before":{content:'""',position:"absolute",left:0,top:0,bottom:0,width:r?3:0,bgcolor:"#58a6ff",borderTopRightRadius:2,borderBottomRightRadius:2,transition:"width 160ms ease"}},children:e.jsx($,{sx:{fontSize:"0.85rem",color:"#58a6ff"},children:e.jsx("b",{children:"Sites"})})}),e.jsx(cs,{sx:{p:0,bgcolor:"#232323"},children:e.jsx(u,{icon:e.jsx(Lo,{fontSize:"small"}),label:"All Sites",pageKey:"sites"})})]})})(),(()=>{const r=["devices","ssh_devices","winrm_devices","agent_devices"].includes(n);return e.jsxs(as,{expanded:a.devices,onChange:(i,c)=>d(p=>({...p,devices:c})),square:!0,disableGutters:!0,sx:{"&:before":{display:"none"},margin:0,border:0},children:[e.jsx(is,{expandIcon:e.jsx(ls,{}),sx:{position:"relative",background:r?"linear-gradient(90deg, rgba(88,166,255,0.08) 0%, rgba(88,166,255,0.00) 100%)":"#2c2c2c",minHeight:"36px","& .MuiAccordionSummary-content":{margin:0},"&::before":{content:'""',position:"absolute",left:0,top:0,bottom:0,width:r?3:0,bgcolor:"#58a6ff",borderTopRightRadius:2,borderBottomRightRadius:2,transition:"width 160ms ease"}},children:e.jsx($,{sx:{fontSize:"0.85rem",color:"#58a6ff"},children:e.jsx("b",{children:"Inventory"})})}),e.jsxs(cs,{sx:{p:0,bgcolor:"#232323"},children:[e.jsx(u,{icon:e.jsx($o,{fontSize:"small"}),label:"Device Approvals",pageKey:"admin_device_approvals"}),e.jsx(u,{icon:e.jsx(uo,{fontSize:"small"}),label:"Enrollment Codes",pageKey:"admin_enrollment_codes",indent:!0}),e.jsx(u,{icon:e.jsx(Ys,{fontSize:"small"}),label:"Devices",pageKey:"devices"}),e.jsx(u,{icon:e.jsx(Ys,{fontSize:"small"}),label:"Agent Devices",pageKey:"agent_devices",indent:!0}),e.jsx(u,{icon:e.jsx(Ys,{fontSize:"small"}),label:"SSH Devices",pageKey:"ssh_devices",indent:!0}),e.jsx(u,{icon:e.jsx(Ys,{fontSize:"small"}),label:"WinRM Devices",pageKey:"winrm_devices",indent:!0})]})]})})(),(()=>{const r=["jobs","assemblies","community"].includes(n);return e.jsxs(as,{expanded:a.automation,onChange:(i,c)=>d(p=>({...p,automation:c})),square:!0,disableGutters:!0,sx:{"&:before":{display:"none"},margin:0,border:0},children:[e.jsx(is,{expandIcon:e.jsx(ls,{}),sx:{position:"relative",background:r?"linear-gradient(90deg, rgba(88,166,255,0.08) 0%, rgba(88,166,255,0.00) 100%)":"#2c2c2c",minHeight:"36px","& .MuiAccordionSummary-content":{margin:0},"&::before":{content:'""',position:"absolute",left:0,top:0,bottom:0,width:r?3:0,bgcolor:"#58a6ff",borderTopRightRadius:2,borderBottomRightRadius:2,transition:"width 160ms ease"}},children:e.jsx($,{sx:{fontSize:"0.85rem",color:"#58a6ff"},children:e.jsx("b",{children:"Automation"})})}),e.jsxs(cs,{sx:{p:0,bgcolor:"#232323"},children:[e.jsx(u,{icon:e.jsx(Uo,{fontSize:"small"}),label:"Assemblies",pageKey:"assemblies"}),e.jsx(u,{icon:e.jsx(Wo,{fontSize:"small"}),label:"Scheduled Jobs",pageKey:"jobs"}),e.jsx(u,{icon:e.jsx(Vo,{fontSize:"small"}),label:"Community Content",pageKey:"community"})]})]})})(),(()=>{const r=n==="filters"||n==="groups";return e.jsxs(as,{expanded:a.filters,onChange:(i,c)=>d(p=>({...p,filters:c})),square:!0,disableGutters:!0,sx:{"&:before":{display:"none"},margin:0,border:0},children:[e.jsx(is,{expandIcon:e.jsx(ls,{}),sx:{position:"relative",background:r?"linear-gradient(90deg, rgba(88,166,255,0.08) 0%, rgba(88,166,255,0.00) 100%)":"#2c2c2c",minHeight:"36px","& .MuiAccordionSummary-content":{margin:0},"&::before":{content:'""',position:"absolute",left:0,top:0,bottom:0,width:r?3:0,bgcolor:"#58a6ff",borderTopRightRadius:2,borderBottomRightRadius:2,transition:"width 160ms ease"}},children:e.jsx($,{sx:{fontSize:"0.85rem",color:"#58a6ff"},children:e.jsx("b",{children:"Filters & Groups"})})}),e.jsxs(cs,{sx:{p:0,bgcolor:"#232323"},children:[e.jsx(u,{icon:e.jsx(Ho,{fontSize:"small"}),label:"Filters",pageKey:"filters"}),e.jsx(u,{icon:e.jsx(Go,{fontSize:"small"}),label:"Groups",pageKey:"groups"})]})]})})(),(()=>{if(!o)return null;const r=n==="access_credentials"||n==="access_users"||n==="access_github_token";return e.jsxs(as,{expanded:a.access,onChange:(i,c)=>d(p=>({...p,access:c})),square:!0,disableGutters:!0,sx:{"&:before":{display:"none"},margin:0,border:0},children:[e.jsx(is,{expandIcon:e.jsx(ls,{}),sx:{position:"relative",background:r?"linear-gradient(90deg, rgba(88,166,255,0.08) 0%, rgba(88,166,255,0.00) 100%)":"#2c2c2c",minHeight:"36px","& .MuiAccordionSummary-content":{margin:0},"&::before":{content:'""',position:"absolute",left:0,top:0,bottom:0,width:r?3:0,bgcolor:"#58a6ff",borderTopRightRadius:2,borderBottomRightRadius:2,transition:"width 160ms ease"}},children:e.jsx($,{sx:{fontSize:"0.85rem",color:"#58a6ff"},children:e.jsx("b",{children:"Access Management"})})}),e.jsxs(cs,{sx:{p:0,bgcolor:"#232323"},children:[e.jsx(u,{icon:e.jsx(qo,{fontSize:"small"}),label:"Credentials",pageKey:"access_credentials"}),e.jsx(u,{icon:e.jsx(po,{fontSize:"small"}),label:"GitHub API Token",pageKey:"access_github_token"}),e.jsx(u,{icon:e.jsx(Jo,{fontSize:"small"}),label:"Users",pageKey:"access_users"})]})]})})(),(()=>{if(!o)return null;const r=n==="server_info"||n==="admin_enrollment_codes"||n==="admin_device_approvals";return e.jsxs(as,{expanded:a.admin,onChange:(i,c)=>d(p=>({...p,admin:c})),square:!0,disableGutters:!0,sx:{"&:before":{display:"none"},margin:0,border:0},children:[e.jsx(is,{expandIcon:e.jsx(ls,{}),sx:{position:"relative",background:r?"linear-gradient(90deg, rgba(88,166,255,0.08) 0%, rgba(88,166,255,0.00) 100%)":"#2c2c2c",minHeight:"36px","& .MuiAccordionSummary-content":{margin:0},"&::before":{content:'""',position:"absolute",left:0,top:0,bottom:0,width:r?3:0,bgcolor:"#58a6ff",borderTopRightRadius:2,borderBottomRightRadius:2,transition:"width 160ms ease"}},children:e.jsx($,{sx:{fontSize:"0.85rem",color:"#58a6ff"},children:e.jsx("b",{children:"Admin Settings"})})}),e.jsx(cs,{sx:{p:0,bgcolor:"#232323"},children:e.jsx(u,{icon:e.jsx(Yo,{fontSize:"small"}),label:"Server Info",pageKey:"server_info"})})]})})()]})})}const Fi=es.memo(zi);function Li({tabs:n,activeTabId:t,onTabChange:o,onAddTab:a,onTabRightClick:d}){const u=(()=>{const i=n.findIndex(c=>c.id===t);return i>=0?i:0})(),r=(i,c)=>{if(c==="__addtab__")a();else{const p=n[c];p&&o(p.id)}};return e.jsx(m,{sx:{display:"flex",alignItems:"center",backgroundColor:"#232323",borderBottom:"1px solid #333",height:"36px"},children:e.jsxs(Us,{value:u,onChange:r,variant:"scrollable",scrollButtons:"auto",textColor:"inherit",TabIndicatorProps:{style:{backgroundColor:"#58a6ff"}},sx:{minHeight:"36px",height:"36px",flexGrow:1},children:[n.map((i,c)=>e.jsx(ps,{label:i.tab_name,value:c,onContextMenu:p=>d(p,i.id),sx:{minHeight:"36px",height:"36px",textTransform:"none",backgroundColor:i.id===t?"#2C2C2C":"transparent",color:"#58a6ff"}},i.id)),e.jsx(st,{title:"Create a New Concurrent Tab",arrow:!0,children:e.jsx(ps,{icon:e.jsx(ts,{}),value:"__addtab__",sx:{minHeight:"36px",height:"36px",color:"#58a6ff",textTransform:"none"}})})]})})}function Vn(n,t=.7){if(!/^#[0-9A-Fa-f]{6}$/.test(n))return n;let o=parseInt(n.slice(1,3),16),a=parseInt(n.slice(3,5),16),d=parseInt(n.slice(5,7),16);return o=Math.round(o*t),a=Math.round(a*t),d=Math.round(d*t),`#${o.toString(16).padStart(2,"0")}${a.toString(16).padStart(2,"0")}${d.toString(16).padStart(2,"0")}`}function $i({drawerOpen:n,setDrawerOpen:t,title:o,nodeData:a,setNodes:d,selectedNode:u}){var R;const[r,i]=s.useState(0),c=dt().setNodes,p=d||c,l=(x,S)=>i(S),[h,f]=s.useState(!1),[y,C]=s.useState(o||""),[I,k]=s.useState(!1),v=((R=u==null?void 0:u.data)==null?void 0:R.accentColor)||"#58a6ff",j=()=>{const x=(a==null?void 0:a.config)||[],S=a==null?void 0:a.nodeId,z=(E=[])=>E.map(U=>{if(typeof U=="string")return{value:U,label:U,disabled:!1};if(U&&typeof U=="object"){const X=U.value??U.id??U.handle??(typeof U.label=="string"?U.label:""),ue=U.label??U.name??U.title??(typeof X<"u"?String(X):"");return{value:typeof X>"u"?"":String(X),label:typeof ue>"u"?"":String(ue),disabled:!!U.disabled}}return{value:String(U??""),label:String(U??""),disabled:!1}});return x.map((E,U)=>{const X=(a==null?void 0:a[E.key])??"",ue=!!E.readOnly;if(E.type==="select"){let Se=E.options||[];return E.optionsKey&&Array.isArray(a==null?void 0:a[E.optionsKey])?Se=a[E.optionsKey]:E.dynamicOptions&&(a!=null&&a.windowList)&&Array.isArray(a.windowList)&&(Se=a.windowList.map(ce=>({value:String(ce.handle),label:`${ce.title} (${ce.handle})`})).sort((ce,de)=>ce.label.localeCompare(de.label,void 0,{sensitivity:"base"}))),Se=z(Se),E.dynamicOptions&&(!(a!=null&&a.windowList)||!Array.isArray(a.windowList))&&(Se=[]),e.jsxs(m,{sx:{mb:2},children:[e.jsx($,{variant:"body2",sx:{color:"#ccc",mb:.5},children:E.label||E.key}),e.jsx(Ie,{select:!0,fullWidth:!0,size:"small",value:X,onChange:ce=>{if(ue)return;const de=ce.target.value;S&&(p(me=>me.map(w=>w.id===S?{...w,data:{...w.data,[E.key]:de}}:w)),window.BorealisValueBus[S]=de)},SelectProps:{MenuProps:{PaperProps:{sx:{bgcolor:"#1e1e1e",color:"#ccc",border:"1px solid #58a6ff","& .MuiMenuItem-root":{color:"#ccc",fontSize:"0.85rem","&:hover":{backgroundColor:"#2a2a2a"},"&.Mui-selected":{backgroundColor:"#2c2c2c !important",color:"#58a6ff"},"&.Mui-selected:hover":{backgroundColor:"#2a2a2a !important"}}}}}},sx:{"& .MuiOutlinedInput-root":{backgroundColor:"#1e1e1e",color:"#ccc",fontSize:"0.85rem","& fieldset":{borderColor:"#444"},"&:hover fieldset":{borderColor:"#58a6ff"},"&.Mui-focused fieldset":{borderColor:"#58a6ff"}},"& .MuiSelect-select":{backgroundColor:"#1e1e1e"}},children:Se.length===0?e.jsx(fe,{disabled:!0,value:"",children:E.label==="Target Window"?"No windows detected":"No options"}):Se.map((ce,de)=>e.jsx(fe,{value:ce.value,disabled:ce.disabled,children:ce.label},de))})]},U)}return e.jsxs(m,{sx:{mb:2},children:[e.jsx($,{variant:"body2",sx:{color:"#ccc",mb:.5},children:E.label||E.key}),e.jsx(Ie,{variant:"outlined",size:"small",fullWidth:!0,value:X,disabled:ue,InputProps:{readOnly:ue,sx:{color:"#ccc",backgroundColor:"#1e1e1e","& fieldset":{borderColor:"#444"},"&:hover fieldset":{borderColor:"#666"},"&.Mui-focused fieldset":{borderColor:"#58a6ff"}}},onChange:Se=>{if(ue)return;const ce=Se.target.value;S&&(p(de=>de.map(me=>me.id===S?{...me,data:{...me.data,[E.key]:ce}}:me)),window.BorealisValueBus[S]=ce)}})]},U)})},B=()=>e.jsx(st,{title:"Override Node Header/Accent Color",children:e.jsx(nt,{size:"small","aria-label":"Override Node Color",onClick:()=>k(!0),sx:{ml:1,border:"1px solid #58a6ff",background:v,color:"#222",width:28,height:28,p:0},children:e.jsx(Xo,{fontSize:"small"})})});return e.jsxs(e.Fragment,{children:[e.jsx(m,{onClick:()=>t(!1),sx:{position:"absolute",top:0,left:0,right:0,bottom:0,backgroundColor:"rgba(0, 0, 0, 0.3)",opacity:n?1:0,pointerEvents:n?"auto":"none",transition:"opacity 0.6s ease",zIndex:10}}),e.jsxs(m,{sx:{position:"absolute",top:0,right:0,bottom:0,width:400,bgcolor:"#2C2C2C",color:"#ccc",borderLeft:"1px solid #333",padding:0,zIndex:11,overflowY:"auto",transform:n?"translateX(0)":"translateX(100%)",transition:"transform 0.3s ease"},onClick:x=>x.stopPropagation(),children:[e.jsxs(m,{sx:{backgroundColor:"#232323",borderBottom:"1px solid #333"},children:[e.jsx(m,{sx:{padding:"12px 16px"},children:e.jsxs(m,{sx:{display:"flex",alignItems:"center",justifyContent:"space-between"},children:[e.jsx($,{variant:"h7",sx:{color:"#0475c2",fontWeight:"bold"},children:"Edit "+(o||"Node")}),e.jsxs(m,{sx:{display:"flex",alignItems:"center"},children:[e.jsx(nt,{size:"small","aria-label":"Rename Node",onClick:()=>{C(o||""),f(!0)},sx:{ml:1,color:"#58a6ff"},children:e.jsx(Fs,{fontSize:"small"})}),B()]})]})}),e.jsxs(Us,{value:r,onChange:l,variant:"fullWidth",textColor:"inherit",TabIndicatorProps:{style:{backgroundColor:"#ccc"}},sx:{borderTop:"1px solid #333",borderBottom:"1px solid #333",minHeight:"36px",height:"36px"},children:[e.jsx(ps,{label:"Config",sx:{color:"#ccc","&.Mui-selected":{color:"#ccc"},minHeight:"36px",height:"36px",textTransform:"none"}}),e.jsx(ps,{label:"Usage Docs",sx:{color:"#ccc","&.Mui-selected":{color:"#ccc"},minHeight:"36px",height:"36px",textTransform:"none"}})]})]}),e.jsxs(m,{sx:{padding:2},children:[r===0&&j(),r===1&&e.jsx(m,{sx:{fontSize:"0.85rem",color:"#aaa"},children:e.jsx(Gr,{children:(a==null?void 0:a.usage_documentation)||"No usage documentation provided for this node.",components:{h3:({node:x,...S})=>e.jsx($,{variant:"h6",sx:{color:"#58a6ff",mb:1},...S}),p:({node:x,...S})=>e.jsx($,{paragraph:!0,sx:{mb:1.5},...S}),ul:({node:x,...S})=>e.jsx("ul",{style:{marginBottom:"1em",paddingLeft:"1.2em"},...S}),li:({node:x,...S})=>e.jsx("li",{style:{marginBottom:"0.5em"},...S})}})})]})]}),e.jsxs(Ze,{open:h,onClose:()=>f(!1),PaperProps:{sx:{bgcolor:"#232323"}},children:[e.jsx(et,{children:"Rename Node"}),e.jsx(rt,{children:e.jsx(Ie,{autoFocus:!0,fullWidth:!0,variant:"outlined",label:"Node Title",value:y,onChange:x=>C(x.target.value),sx:{mt:1,bgcolor:"#1e1e1e","& .MuiOutlinedInput-root":{color:"#ccc",backgroundColor:"#1e1e1e","& fieldset":{borderColor:"#444"}},label:{color:"#aaa"}}})}),e.jsxs(tt,{children:[e.jsx(Z,{sx:{color:"#aaa"},onClick:()=>f(!1),children:"Cancel"}),e.jsx(Z,{sx:{color:"#58a6ff"},onClick:()=>{const x=(u==null?void 0:u.id)||(a==null?void 0:a.nodeId);if(!x){f(!1);return}p(S=>S.map(z=>z.id===x?{...z,data:{...z.data,label:y}}:z)),f(!1)},children:"Save"})]})]}),e.jsxs(Ze,{open:I,onClose:()=>k(!1),PaperProps:{sx:{bgcolor:"#232323"}},children:[e.jsx(et,{children:"Pick Node Header/Accent Color"}),e.jsxs(rt,{children:[e.jsx(jo,{color:v,onChangeComplete:x=>{const S=(u==null?void 0:u.id)||(a==null?void 0:a.nodeId);if(!S)return;const z=x.hex,E=Vn(z,.7);p(U=>U.map(X=>X.id===S?{...X,data:{...X.data,accentColor:z},style:{...X.style,"--borealis-accent":z,"--borealis-accent-dark":E,"--borealis-title":z}}:X))},disableAlpha:!0,presetColors:["#58a6ff","#0475c2","#00d18c","#ff4f4f","#ff8c00","#6b21a8","#0e7490","#888","#fff","#000"]}),e.jsxs(m,{sx:{mt:2},children:[e.jsxs($,{variant:"body2",children:["The node's header text and accent gradient will use your selected color.",e.jsx("br",{}),"The accent gradient fades to a slightly darker version."]}),e.jsxs(m,{sx:{mt:2,display:"flex",alignItems:"center"},children:[e.jsx("span",{style:{display:"inline-block",width:48,height:22,borderRadius:4,border:"1px solid #888",background:`linear-gradient(to bottom, ${v} 0%, ${Vn(v,.7)} 100%)`}}),e.jsx("span",{style:{marginLeft:10,color:v,fontWeight:"bold"},children:v})]})]})]}),e.jsx(tt,{children:e.jsx(Z,{onClick:()=>k(!1),sx:{color:"#aaa"},children:"Close"})})]})]})}const Hn=400,Gn={type:"bezier",animated:!0,style:{strokeDasharray:"6 3",stroke:"#58a6ff",strokeWidth:1},label:"",labelStyle:{fill:"#fff",fontWeight:"bold"},labelBgStyle:{fill:"#2c2c2c",fillOpacity:.85,rx:16,ry:16},labelBgPadding:[8,4]};let Qs=null;function Os(n){return JSON.parse(JSON.stringify(n))}function Ui({open:n,onClose:t,edge:o,updateEdge:a}){const[d,u]=s.useState(0),[r,i]=s.useState(()=>o?Os(o):{}),[c,p]=s.useState({field:null,anchor:null});s.useEffect(()=>{o&&o.id!==r.id&&i(Os(o))},[o]);const l=(R,x)=>{i(S=>{const z={...S};return R==="label"?z.label=x:R==="labelStyle.fill"?z.labelStyle={...z.labelStyle,fill:x}:R==="labelBgStyle.fill"?z.labelBgStyle={...z.labelBgStyle,fill:x}:R==="labelBgStyle.rx"?z.labelBgStyle={...z.labelBgStyle,rx:x,ry:x}:R==="labelBgPadding"?z.labelBgPadding=x:R==="labelBgStyle.fillOpacity"?z.labelBgStyle={...z.labelBgStyle,fillOpacity:x}:R==="type"?z.type=x:R==="animated"?z.animated=x:R==="style.stroke"?z.style={...z.style,stroke:x}:R==="style.strokeDasharray"?z.style={...z.style,strokeDasharray:x}:R==="style.strokeWidth"?z.style={...z.style,strokeWidth:x}:R==="labelStyle.fontWeight"?z.labelStyle={...z.labelStyle,fontWeight:x}:z[R]=x,R==="style.strokeDasharray"&&(x===""?(z.animated=!1,z.style={...z.style,strokeDasharray:""}):(z.animated=!0,z.style={...z.style,strokeDasharray:x})),a({...z,id:S.id}),z})},h=(R,x)=>{p({field:R,anchor:x.currentTarget})},f=()=>{p({field:null,anchor:null})},y=R=>{l(c.field,R.hex),f()},C=()=>{i(Os({...Gn,id:o.id})),a({...Gn,id:o.id})},I=()=>{Qs=Os(r)},k=()=>{Qs&&(i(Os({...Qs,id:o.id})),a({...Qs,id:o.id}))},v=(R,x,S)=>e.jsxs("span",{style:{display:"inline-block",verticalAlign:"middle",position:"relative"},children:[e.jsx(Z,{variant:"outlined",size:"small",onClick:z=>h(x,z),sx:{ml:1,borderColor:"#444",color:"#ccc",minWidth:0,width:32,height:24,p:0,bgcolor:"#232323"},children:e.jsx("span",{style:{display:"inline-block",width:20,height:16,background:S,borderRadius:3,border:"1px solid #888"}})}),c.field===x&&e.jsx(m,{sx:{position:"absolute",top:"32px",right:0,zIndex:1302,boxShadow:"0 2px 16px rgba(0,0,0,0.24)"},children:e.jsx(jo,{color:S,onChange:y,disableAlpha:!0,presetColors:["#fff","#000","#58a6ff","#ff4f4f","#2c2c2c","#00d18c","#e3e3e3","#0475c2","#ff8c00","#6b21a8","#0e7490"]})})]}),j=()=>{var R,x,S,z,E;return e.jsxs(m,{sx:{px:2,pt:1,pb:2},children:[e.jsx(m,{sx:{display:"flex",alignItems:"center",mb:1},children:e.jsx($,{variant:"body2",sx:{color:"#ccc",flex:1},children:"Label"})}),e.jsx(Ie,{fullWidth:!0,size:"small",variant:"outlined",value:r.label||"",onChange:U=>l("label",U.target.value),sx:{mb:2,input:{color:"#fff",bgcolor:"#1e1e1e",fontSize:"0.95rem"},"& fieldset":{borderColor:"#444"}}}),e.jsxs(m,{sx:{display:"flex",alignItems:"center",mb:1},children:[e.jsx($,{variant:"body2",sx:{color:"#ccc",flex:1},children:"Text Color"}),v("Label Text Color","labelStyle.fill",((R=r.labelStyle)==null?void 0:R.fill)||"#fff")]}),e.jsxs(m,{sx:{display:"flex",alignItems:"center",mb:1},children:[e.jsx($,{variant:"body2",sx:{color:"#ccc",flex:1},children:"Background"}),v("Label Background Color","labelBgStyle.fill",((x=r.labelBgStyle)==null?void 0:x.fill)||"#2c2c2c")]}),e.jsxs(m,{sx:{display:"flex",alignItems:"center",mb:2},children:[e.jsx($,{variant:"body2",sx:{color:"#ccc",flex:1},children:"Padding"}),e.jsx(Ie,{size:"small",type:"text",value:r.labelBgPadding?r.labelBgPadding.join(","):"8,4",onChange:U=>{const X=U.target.value.split(",").map(ue=>parseInt(ue.trim())).filter(ue=>!isNaN(ue));X.length===2&&l("labelBgPadding",X)},sx:{width:80,input:{color:"#fff",bgcolor:"#1e1e1e",fontSize:"0.95rem"}}})]}),e.jsxs(m,{sx:{display:"flex",alignItems:"center",mb:2},children:[e.jsx($,{variant:"body2",sx:{color:"#ccc",flex:1},children:"Background Style"}),e.jsxs(Ie,{select:!0,size:"small",value:(((S=r.labelBgStyle)==null?void 0:S.rx)??11)>=11?"rounded":"square",onChange:U=>{l("labelBgStyle.rx",U.target.value==="rounded"?11:0)},sx:{width:150,bgcolor:"#1e1e1e","& .MuiSelect-select":{color:"#fff"}},children:[e.jsx(fe,{value:"rounded",children:"Rounded"}),e.jsx(fe,{value:"square",children:"Square"})]})]}),e.jsxs(m,{sx:{display:"flex",alignItems:"center",mb:2},children:[e.jsx($,{variant:"body2",sx:{color:"#ccc",flex:1},children:"Background Opacity"}),e.jsx(Fn,{value:((z=r.labelBgStyle)==null?void 0:z.fillOpacity)??.85,min:0,max:1,step:.05,onChange:(U,X)=>l("labelBgStyle.fillOpacity",X),sx:{width:100,ml:2}}),e.jsx(Ie,{size:"small",type:"number",value:((E=r.labelBgStyle)==null?void 0:E.fillOpacity)??.85,onChange:U=>l("labelBgStyle.fillOpacity",parseFloat(U.target.value)||0),sx:{width:60,ml:2,input:{color:"#fff",bgcolor:"#1e1e1e",fontSize:"0.95rem"}}})]})]})},B=()=>{var R,x,S,z,E;return e.jsxs(m,{sx:{px:2,pt:1,pb:2},children:[e.jsxs(m,{sx:{display:"flex",alignItems:"center",mb:2},children:[e.jsx($,{variant:"body2",sx:{color:"#ccc",flex:1},children:"Edge Style"}),e.jsxs(Ie,{select:!0,size:"small",value:r.type||"bezier",onChange:U=>l("type",U.target.value),sx:{width:200,bgcolor:"#1e1e1e","& .MuiSelect-select":{color:"#fff"}},children:[e.jsx(fe,{value:"step",children:"Step"}),e.jsx(fe,{value:"bezier",children:"Curved (Bezier)"}),e.jsx(fe,{value:"straight",children:"Straight"}),e.jsx(fe,{value:"smoothstep",children:"Smoothstep"})]})]}),e.jsxs(m,{sx:{display:"flex",alignItems:"center",mb:2},children:[e.jsx($,{variant:"body2",sx:{color:"#ccc",flex:1},children:"Edge Animation"}),e.jsxs(Ie,{select:!0,size:"small",value:((R=r.style)==null?void 0:R.strokeDasharray)==="6 3"?"dashes":((x=r.style)==null?void 0:x.strokeDasharray)==="2 4"?"dots":"solid",onChange:U=>{const X=U.target.value;l("style.strokeDasharray",X==="dashes"?"6 3":X==="dots"?"2 4":"")},sx:{width:200,bgcolor:"#1e1e1e","& .MuiSelect-select":{color:"#fff"}},children:[e.jsx(fe,{value:"dashes",children:"Dashes"}),e.jsx(fe,{value:"dots",children:"Dots"}),e.jsx(fe,{value:"solid",children:"Solid"})]})]}),e.jsxs(m,{sx:{display:"flex",alignItems:"center",mb:2},children:[e.jsx($,{variant:"body2",sx:{color:"#ccc",flex:1},children:"Color"}),v("Edge Color","style.stroke",((S=r.style)==null?void 0:S.stroke)||"#58a6ff")]}),e.jsxs(m,{sx:{display:"flex",alignItems:"center",mb:2},children:[e.jsx($,{variant:"body2",sx:{color:"#ccc",flex:1},children:"Edge Width"}),e.jsx(Fn,{value:((z=r.style)==null?void 0:z.strokeWidth)??2,min:1,max:10,step:1,onChange:(U,X)=>l("style.strokeWidth",X),sx:{width:100,ml:2}}),e.jsx(Ie,{size:"small",type:"number",value:((E=r.style)==null?void 0:E.strokeWidth)??2,onChange:U=>l("style.strokeWidth",parseInt(U.target.value)||1),sx:{width:60,ml:2,input:{color:"#fff",bgcolor:"#1e1e1e",fontSize:"0.95rem"}}})]})]})};return o?e.jsxs(e.Fragment,{children:[e.jsx(m,{onClick:t,sx:{position:"absolute",top:0,left:0,right:0,bottom:0,backgroundColor:"rgba(0, 0, 0, 0.3)",opacity:n?1:0,pointerEvents:n?"auto":"none",transition:"opacity 0.6s ease",zIndex:10}}),e.jsxs(m,{sx:{position:"absolute",top:0,right:0,bottom:0,width:Hn,bgcolor:"#2C2C2C",color:"#ccc",borderLeft:"1px solid #333",padding:0,zIndex:11,display:"flex",flexDirection:"column",height:"100%",transform:n?"translateX(0)":`translateX(${Hn}px)`,transition:"transform 0.3s cubic-bezier(.77,0,.18,1)"},onClick:R=>R.stopPropagation(),children:[e.jsxs(m,{sx:{backgroundColor:"#232323",borderBottom:"1px solid #333"},children:[e.jsx(m,{sx:{padding:"12px 16px",display:"flex",alignItems:"center"},children:e.jsx($,{variant:"h7",sx:{color:"#0475c2",fontWeight:"bold",flex:1},children:"Edit Edge Properties"})}),e.jsxs(Us,{value:d,onChange:(R,x)=>u(x),variant:"fullWidth",textColor:"inherit",TabIndicatorProps:{style:{backgroundColor:"#ccc"}},sx:{borderTop:"1px solid #333",borderBottom:"1px solid #333",minHeight:"36px",height:"36px"},children:[e.jsx(ps,{label:"Label",sx:{color:"#ccc","&.Mui-selected":{color:"#ccc"},minHeight:"36px",height:"36px",textTransform:"none"}}),e.jsx(ps,{label:"Style",sx:{color:"#ccc","&.Mui-selected":{color:"#ccc"},minHeight:"36px",height:"36px",textTransform:"none"}})]})]}),e.jsxs(m,{sx:{flex:1,overflowY:"auto"},children:[d===0&&j(),d===1&&B()]}),e.jsxs(m,{sx:{display:"flex",alignItems:"center",justifyContent:"space-between",px:2,py:1,borderTop:"1px solid #333",backgroundColor:"#232323",flexShrink:0},children:[e.jsxs(m,{children:[e.jsx(st,{title:"Copy Style",children:e.jsx(nt,{onClick:I,children:e.jsx(fo,{})})}),e.jsx(st,{title:"Paste Style",children:e.jsx(nt,{onClick:k,children:e.jsx(Qo,{})})})]}),e.jsx(m,{children:e.jsx(st,{title:"Reset to Default",children:e.jsx(Z,{variant:"outlined",size:"small",startIcon:e.jsx(Zo,{}),onClick:C,sx:{color:"#58a6ff",borderColor:"#58a6ff",textTransform:"none"},children:"Reset to Default"})})})]})]})]}):null}function Wi({flowId:n,nodes:t,edges:o,setNodes:a,setEdges:d,nodeTypes:u,categorizedNodes:r}){var M;const[i,c]=s.useState(!1),[p,l]=s.useState(null),[h,f]=s.useState(!1),[y,C]=s.useState(null),[I,k]=s.useState(null),[v,j]=s.useState(null),B=s.useRef(null),{project:R}=dt(),[x,S]=s.useState([]),[z,E]=s.useState([]),U=s.useRef({width:0,height:0}),X=t.find(g=>g.id===p),ue=o.find(g=>g.id===y),Se=(g,L)=>{g.preventDefault(),k({mouseX:g.clientX+2,mouseY:g.clientY-6,nodeId:L.id})},ce=(g,L)=>{g.preventDefault(),j({mouseX:g.clientX+2,mouseY:g.clientY-6,edgeId:L.id})},de=g=>{d(L=>L.filter(we=>we.source!==g&&we.target!==g)),k(null)},me=g=>{a(L=>L.filter(we=>we.id!==g)),d(L=>L.filter(we=>we.source!==g&&we.target!==g)),k(null)},w=g=>{l(g),c(!0),k(null)},W=g=>{d(L=>L.filter(we=>we.id!==g)),j(null)},F=g=>{C(g),f(!0),j(null)},te=()=>{f(!1),C(null)},ee=g=>{d(L=>L.map(we=>we.id===g.id?{...we,...g}:we))},be=s.useCallback(g=>{if(!B.current)return;const L=B.current.getBoundingClientRect(),we=B.current.querySelector(`.react-flow__node[data-id="${g.id}"]`);if(we){const G=we.getBoundingClientRect(),ie=G.left-L.left,Ce=G.top-L.top,Ee=ie+G.width,Ne=Ce+G.height,Ke=R({x:ie,y:Ce}),at=R({x:Ee,y:Ce}),ut=R({x:ie,y:Ne});U.current={width:at.x-Ke.x,height:ut.y-Ke.y}}const T=[];t.forEach(G=>{if(G.id===g.id)return;const ie=B.current.querySelector(`.react-flow__node[data-id="${G.id}"]`);if(!ie)return;const Ce=ie.getBoundingClientRect(),Ee=Ce.left-L.left,Ne=Ce.top-L.top,Ke=Ee+Ce.width,at=Ne+Ce.height,ut=R({x:Ee,y:Ne}),Pe=R({x:Ke,y:Ne}),gt=R({x:Ee,y:at});T.push({xFlow:ut.x,xPx:Ee}),T.push({xFlow:Pe.x,xPx:Ke}),T.push({yFlow:ut.y,yPx:Ne}),T.push({yFlow:gt.y,yPx:at})}),S(T)},[t,R]),Re=s.useCallback((g,L)=>{let T=null,G=null;const ie=[],{width:Ce,height:Ee}=U.current;x.forEach(Ne=>{Ne.xFlow!=null&&(Math.abs(L.position.x-Ne.xFlow)<5?(T=Ne.xFlow,ie.push({xPx:Ne.xPx})):Math.abs(L.position.x+Ce-Ne.xFlow)<5&&(T=Ne.xFlow-Ce,ie.push({xPx:Ne.xPx}))),Ne.yFlow!=null&&(Math.abs(L.position.y-Ne.yFlow)<5?(G=Ne.yFlow,ie.push({yPx:Ne.yPx})):Math.abs(L.position.y+Ee-Ne.yFlow)<5&&(G=Ne.yFlow-Ee,ie.push({yPx:Ne.yPx})))}),T!==null||G!==null?(a(Ne=>zn([{id:L.id,type:"position",position:{x:T!==null?T:L.position.x,y:G!==null?G:L.position.y}}],Ne)),E(ie)):E([])},[x,a]),Ae=s.useCallback(g=>{g.preventDefault();const L=g.dataTransfer.getData("application/reactflow");if(!L)return;const we=B.current.getBoundingClientRect(),T=R({x:g.clientX-we.left,y:g.clientY-we.top}),G="node-"+Date.now(),ie=Object.values(r).flat().find(Ne=>Ne.type===L),Ce={};((ie==null?void 0:ie.config)||[]).forEach(Ne=>{Ne.defaultValue!==void 0&&(Ce[Ne.key]=Ne.defaultValue)});const Ee={id:G,type:L,position:T,data:{label:(ie==null?void 0:ie.label)||L,content:ie==null?void 0:ie.content,...Ce},dragHandle:".borealis-node-header"};a(Ne=>[...Ne,Ee])},[R,a,r]),Le=s.useCallback(g=>{g.preventDefault(),g.dataTransfer.dropEffect="move"},[]),Fe=s.useCallback(g=>{d(L=>Po({...g,type:"bezier",animated:!0,style:{strokeDasharray:"6 3",stroke:"#58a6ff"}},L))},[d]),je=s.useCallback(g=>{a(L=>zn(g,L))},[a]),V=s.useCallback(g=>{d(L=>Eo(g,L))},[d]);s.useEffect(()=>{const g=document.getElementById("nodeCount");g&&(g.innerText=t.length)},[t]);const O=X?Object.values(r).flat().find(g=>g.type===X.type):null;return e.jsxs("div",{className:"flow-editor-container",ref:B,style:{position:"relative"},children:[e.jsx($i,{drawerOpen:i,setDrawerOpen:c,title:X?((M=X.data)==null?void 0:M.label)||X.id:"",nodeData:X&&O?{config:O.config,usage_documentation:O.usage_documentation,...X.data,nodeId:X.id}:null,setNodes:a,selectedNode:X}),e.jsx(Ui,{open:h,onClose:te,edge:ue?{...ue}:null,updateEdge:g=>{!g.id&&y&&(g.id=y),ee(g)}}),e.jsx(lo,{nodes:t,edges:o,nodeTypes:u,onNodesChange:je,onEdgesChange:V,onConnect:Fe,onDrop:Ae,onDragOver:Le,onNodeContextMenu:Se,onEdgeContextMenu:ce,defaultViewport:{x:0,y:0,zoom:1.5},edgeOptions:{type:"bezier",animated:!0,style:{strokeDasharray:"6 3",stroke:"#58a6ff"}},proOptions:{hideAttribution:!0},onNodeDragStart:(g,L)=>be(L),onNodeDrag:Re,onNodeDragStop:()=>{S([]),E([])},children:e.jsx(Mo,{id:n,variant:"lines",gap:65,size:1,color:"rgba(255,255,255,0.2)"})}),z.map((g,L)=>g.xPx!=null?e.jsx("div",{className:"helper-line helper-line-vertical",style:{left:g.xPx+"px",top:0}},L):e.jsx("div",{className:"helper-line helper-line-horizontal",style:{top:g.yPx+"px",left:0}},L)),e.jsxs(Et,{open:!!I,onClose:()=>k(null),anchorReference:"anchorPosition",anchorPosition:I?{top:I.mouseY,left:I.mouseX}:void 0,PaperProps:{sx:{bgcolor:"#1e1e1e",color:"#fff",fontSize:"13px"}},children:[e.jsxs(fe,{onClick:()=>w(I.nodeId),children:[e.jsx(Fs,{sx:{fontSize:18,color:"#58a6ff",mr:1}}),"Edit Properties"]}),e.jsxs(fe,{onClick:()=>de(I.nodeId),children:[e.jsx(kn,{sx:{fontSize:18,color:"#58a6ff",mr:1}}),"Disconnect All Edges"]}),e.jsxs(fe,{onClick:()=>me(I.nodeId),children:[e.jsx(Ln,{sx:{fontSize:18,color:"#ff4f4f",mr:1}}),"Remove Node"]})]}),e.jsxs(Et,{open:!!v,onClose:()=>j(null),anchorReference:"anchorPosition",anchorPosition:v?{top:v.mouseY,left:v.mouseX}:void 0,PaperProps:{sx:{bgcolor:"#1e1e1e",color:"#fff",fontSize:"13px"}},children:[e.jsxs(fe,{onClick:()=>F(v.edgeId),children:[e.jsx(Fs,{sx:{fontSize:18,color:"#58a6ff",mr:1}}),"Edit Properties"]}),e.jsxs(fe,{onClick:()=>W(v.edgeId),children:[e.jsx(Ln,{sx:{fontSize:18,color:"#ff4f4f",mr:1}}),"Unlink Edge"]})]})]})}function Vi({categorizedNodes:n,handleExportFlow:t,handleImportFlow:o,handleSaveFlow:a,handleOpenCloseAllDialog:d,fileInputRef:u,onFileInputChange:r,currentTabName:i}){const[c,p]=s.useState(null),[l,h]=s.useState(!1),[f,y]=s.useState(!1),[C,I]=s.useState(""),k=v=>(j,B)=>{p(B?v:null)};return e.jsxs("div",{style:{width:l?40:300,backgroundColor:"#121212",borderRight:"1px solid #333",overflow:"hidden",display:"flex",flexDirection:"column",height:"100%"},children:[e.jsx("div",{style:{flex:1,overflowY:"auto"},children:!l&&e.jsxs(e.Fragment,{children:[e.jsxs(as,{defaultExpanded:!0,square:!0,disableGutters:!0,sx:{"&:before":{display:"none"},margin:0,border:0},children:[e.jsx(is,{expandIcon:e.jsx(ls,{}),sx:{backgroundColor:"#2c2c2c",minHeight:"36px","& .MuiAccordionSummary-content":{margin:0}},children:e.jsx($,{sx:{fontSize:"0.9rem",color:"#0475c2"},children:e.jsx("b",{children:"Workflows"})})}),e.jsxs(cs,{sx:{p:0,bgcolor:"#232323"},children:[e.jsx(st,{title:"Save Current Flow to Workflows Folder",placement:"right",arrow:!0,children:e.jsx(Z,{fullWidth:!0,startIcon:e.jsx(ho,{}),onClick:()=>{I(i||"workflow"),y(!0)},sx:hn,children:"Save Workflow"})}),e.jsx(st,{title:"Import JSON File into New Flow Tab",placement:"right",arrow:!0,children:e.jsx(Z,{fullWidth:!0,startIcon:e.jsx(er,{}),onClick:o,sx:hn,children:"Import Workflow (JSON)"})}),e.jsx(st,{title:"Export Current Tab to a JSON File",placement:"right",arrow:!0,children:e.jsx(Z,{fullWidth:!0,startIcon:e.jsx(tr,{}),onClick:t,sx:hn,children:"Export Workflow (JSON)"})})]})]}),e.jsxs(as,{defaultExpanded:!0,square:!0,disableGutters:!0,sx:{"&:before":{display:"none"},margin:0,border:0},children:[e.jsx(is,{expandIcon:e.jsx(ls,{}),sx:{backgroundColor:"#2c2c2c",minHeight:"36px","& .MuiAccordionSummary-content":{margin:0}},children:e.jsx($,{sx:{fontSize:"0.9rem",color:"#0475c2"},children:e.jsx("b",{children:"Nodes"})})}),e.jsx(cs,{sx:{p:0},children:Object.entries(n).map(([v,j])=>e.jsxs(as,{square:!0,expanded:c===v,onChange:k(v),disableGutters:!0,sx:{bgcolor:"#232323","&:before":{display:"none"},margin:0,border:0},children:[e.jsx(is,{expandIcon:e.jsx(ls,{}),sx:{bgcolor:"#1e1e1e",px:2,minHeight:"32px","& .MuiAccordionSummary-content":{margin:0}},children:e.jsx($,{sx:{color:"#888",fontSize:"0.75rem"},children:v})}),e.jsx(cs,{sx:{px:1,py:0},children:j.map(B=>e.jsx(st,{title:e.jsx("span",{style:{whiteSpace:"pre-line",wordWrap:"break-word",maxWidth:220},children:B.description||"Drag & Drop into Editor"}),placement:"right",arrow:!0,children:e.jsxs(Z,{fullWidth:!0,sx:Hi,draggable:!0,onDragStart:R=>{R.dataTransfer.setData("application/reactflow",B.type),R.dataTransfer.effectAllowed="move"},startIcon:e.jsx(sr,{sx:{color:"#666",fontSize:18}}),children:[e.jsx("span",{style:{flexGrow:1,textAlign:"left"},children:B.label}),e.jsx(kn,{sx:{color:"#58a6ff",fontSize:18,ml:1}})]})},`${v}-${B.type}`))})]},v))})]}),e.jsx("input",{type:"file",accept:".json,application/json",style:{display:"none"},ref:u,onChange:r})]})}),e.jsx(st,{title:l?"Expand Sidebar":"Collapse Sidebar",placement:"left",children:e.jsx(m,{onClick:()=>h(!l),sx:{height:"36px",borderTop:"1px solid #333",cursor:"pointer",display:"flex",alignItems:"center",justifyContent:"center",color:"#888",backgroundColor:"#121212",transition:"background-color 0.2s ease","&:hover":{backgroundColor:"#1e1e1e"},"&:active":{backgroundColor:"#2a2a2a"}},children:l?e.jsx(nr,{}):e.jsx(or,{})})}),e.jsx(Ai,{open:f,value:C,onChange:I,onCancel:()=>y(!1),onSave:()=>{y(!1),a(C)}})]})}const hn={color:"#ccc",backgroundColor:"#232323",justifyContent:"flex-start",pl:2,fontSize:"0.9rem",textTransform:"none","&:hover":{backgroundColor:"#2a2a2a"}},Hi={color:"#ccc",backgroundColor:"#232323",justifyContent:"space-between",pl:2,pr:1,fontSize:"0.9rem",textTransform:"none","&:hover":{backgroundColor:"#2a2a2a"}};function Gi(){const[n,t]=s.useState("checking");s.useEffect(()=>{fetch("/health").then(a=>a.ok?t("online"):t("offline")).catch(()=>t("offline"))},[]);const o=()=>{var d;const a=parseInt((d=document.getElementById("updateRateInput"))==null?void 0:d.value);!isNaN(a)&&a>=50?(window.BorealisUpdateRate=a,console.log("Global update rate set to",a+"ms")):alert("Please enter a valid number (min 50).")};return e.jsxs(m,{component:"footer",sx:{bgcolor:"#1e1e1e",color:"white",px:2,py:1,display:"flex",alignItems:"center",justifyContent:"space-between"},children:[e.jsxs(m,{sx:{display:"flex",alignItems:"center",gap:2},children:[e.jsx("b",{children:"Nodes"}),": ",e.jsx("span",{id:"nodeCount",children:"0"}),e.jsx(In,{orientation:"vertical",flexItem:!0,sx:{borderColor:"#444"}}),e.jsx("b",{children:"Update Rate (ms):"}),e.jsx("input",{id:"updateRateInput",type:"number",min:"50",step:"50",defaultValue:window.BorealisUpdateRate,style:{width:"80px",background:"#121212",color:"#fff",border:"1px solid #444",borderRadius:"3px",padding:"3px",fontSize:"0.8rem"}}),e.jsx(Z,{variant:"outlined",size:"small",onClick:o,sx:{color:"#58a6ff",borderColor:"#58a6ff",fontSize:"0.75rem",textTransform:"none",px:1.5},children:"Apply Rate"})]}),e.jsxs(m,{sx:{fontSize:"1.0rem",display:"flex",alignItems:"center",gap:1},children:[e.jsx("strong",{style:{color:"#58a6ff"},children:"Backend API Server"}),":",e.jsx("a",{href:"http://localhost:5000/health",target:"_blank",rel:"noopener noreferrer",style:{color:n==="online"?"#00d18c":"#ff4f4f",textDecoration:"none",fontWeight:"bold"},children:n==="checking"?"...":n.charAt(0).toUpperCase()+n.slice(1)})]})]})}function qi({onLogin:n}){const[t,o]=s.useState("admin"),[a,d]=s.useState(""),[u,r]=s.useState(""),[i,c]=s.useState(!1),[p,l]=s.useState("credentials"),[h,f]=s.useState(""),[y,C]=s.useState(null),[I,k]=s.useState(""),[v,j]=s.useState(""),[B,R]=s.useState(""),[x,S]=s.useState(""),z=s.useMemo(()=>v?v.replace(/(.{4})/g,"$1 ").trim():"",[v]),E=async me=>{try{if(window.crypto&&window.crypto.subtle&&window.isSecureContext){const W=new TextEncoder().encode(me),F=await window.crypto.subtle.digest("SHA-512",W);return Array.from(new Uint8Array(F)).map(ee=>ee.toString(16).padStart(2,"0")).join("")}}catch{}return null},U=()=>{l("credentials"),f(""),C(null),k(""),j(""),R(""),S("")},X=async me=>{me.preventDefault(),c(!0),r("");try{const w=await E(a),F=await fetch("/api/auth/login",{method:"POST",headers:{"Content-Type":"application/json"},credentials:"include",body:JSON.stringify(w?{username:t,password_sha512:w}:{username:t,password:a})}),te=await F.json();if(!F.ok)throw new Error((te==null?void 0:te.error)||"Invalid username or password");if((te==null?void 0:te.status)==="mfa_required"){f(te.pending_token||""),C(te.stage||"verify"),l("mfa"),k(""),j(te.secret||""),R(te.qr_image||""),S(te.otpauth_url||""),r(""),d("");return}if(te!=null&&te.token)try{document.cookie=`borealis_auth=${te.token}; Path=/; SameSite=Lax`}catch{}n({username:te.username,role:te.role})}catch(w){const W=(w==null?void 0:w.message)||"Unable to log in";r(W),U()}finally{c(!1)}},ue=async me=>{if(me.preventDefault(),!h){r("Your MFA session expired. Please log in again."),U();return}if(!I||I.trim().length<6){r("Enter the 6-digit code from your authenticator app.");return}c(!0),r("");try{const w=await fetch("/api/auth/mfa/verify",{method:"POST",headers:{"Content-Type":"application/json"},credentials:"include",body:JSON.stringify({pending_token:h,code:I})}),W=await w.json();if(!w.ok){const F=W==null?void 0:W.error;if(F==="expired"||F==="invalid_session"||F==="mfa_pending"){r("Your MFA session expired. Please log in again."),U();return}r({invalid_code:"Incorrect code. Please try again.",mfa_not_configured:"MFA is not configured for this account."}[F]||(W==null?void 0:W.error)||"Failed to verify code.");return}if(W!=null&&W.token)try{document.cookie=`borealis_auth=${W.token}; Path=/; SameSite=Lax`}catch{}r(""),n({username:W.username,role:W.role})}catch{r("Failed to verify code.")}finally{c(!1)}},Se=()=>{U(),d(""),r("")},ce=me=>{const W=(me.target.value||"").replace(/\D/g,"").slice(0,6);k(W)},de=p==="mfa"?"Multi-Factor Authentication":"Borealis - Automation Platform";return e.jsx(m,{sx:{display:"flex",justifyContent:"center",alignItems:"center",height:"100vh",backgroundColor:"#2b2b2b"},children:e.jsxs(m,{component:"form",onSubmit:p==="mfa"?ue:X,sx:{display:"flex",flexDirection:"column",alignItems:"center",width:320},children:[e.jsx("img",{src:"/Borealis_Logo.png",alt:"Borealis Logo",style:{width:"120px",marginBottom:"16px"}}),e.jsx($,{variant:"h6",sx:{mb:2,textAlign:"center"},children:de}),p==="credentials"?e.jsxs(e.Fragment,{children:[e.jsx(Ie,{label:"Username",variant:"outlined",fullWidth:!0,value:t,disabled:i,onChange:me=>o(me.target.value),margin:"normal"}),e.jsx(Ie,{label:"Password",type:"password",variant:"outlined",fullWidth:!0,value:a,disabled:i,onChange:me=>d(me.target.value),margin:"normal"}),u&&e.jsx($,{color:"error",sx:{mt:1},children:u}),e.jsx(Z,{type:"submit",variant:"contained",fullWidth:!0,disabled:i,sx:{mt:2,bgcolor:"#58a6ff","&:hover":{bgcolor:"#1d82d3"}},children:i?"Signing In...":"Login"})]}):e.jsxs(e.Fragment,{children:[y==="setup"?e.jsxs(e.Fragment,{children:[e.jsxs($,{variant:"body2",sx:{color:"#ccc",textAlign:"center",mb:2},children:["Scan the QR code with your authenticator app, then enter the 6-digit code to complete setup for ",t,"."]}),B?e.jsx("img",{src:B,alt:"MFA enrollment QR code",style:{width:"180px",height:"180px",marginBottom:"12px"}}):null,z?e.jsxs(m,{sx:{bgcolor:"#1d1d1d",borderRadius:1,px:2,py:1,mb:1.5,width:"100%"},children:[e.jsx($,{variant:"caption",sx:{color:"#999"},children:"Manual code"}),e.jsx($,{variant:"body1",sx:{fontFamily:"monospace",letterSpacing:"0.3rem",color:"#fff",mt:.5,textAlign:"center",wordBreak:"break-word"},children:z})]}):null,x?e.jsx($,{variant:"caption",sx:{color:"#888",mb:2,wordBreak:"break-all",textAlign:"center"},children:x}):null]}):e.jsxs($,{variant:"body2",sx:{color:"#ccc",textAlign:"center",mb:2},children:["Enter the 6-digit code from your authenticator app for ",t,"."]}),e.jsx(Ie,{label:"6-digit code",variant:"outlined",fullWidth:!0,value:I,onChange:ce,disabled:i,margin:"normal",inputProps:{inputMode:"numeric",pattern:"[0-9]*",maxLength:6,style:{letterSpacing:"0.4rem",textAlign:"center",fontSize:"1.2rem"}},autoComplete:"one-time-code"}),u&&e.jsx($,{color:"error",sx:{mt:1,textAlign:"center"},children:u}),e.jsx(Z,{type:"submit",variant:"contained",fullWidth:!0,disabled:i||I.length<6,sx:{mt:2,bgcolor:"#58a6ff","&:hover":{bgcolor:"#1d82d3"}},children:i?"Verifying...":"Verify Code"}),e.jsx(Z,{type:"button",variant:"text",fullWidth:!0,disabled:i,onClick:Se,sx:{mt:1,color:"#58a6ff"},children:"Use a different account"})]})]})})}function Ji({onOpenDevicesForSite:n}){var je;const[t,o]=s.useState([]),[a,d]=s.useState("name"),[u,r]=s.useState("asc"),[i,c]=s.useState(()=>new Set),p=s.useMemo(()=>({name:"Name",description:"Description",device_count:"Devices"}),[]),l=s.useMemo(()=>[{id:"name",label:p.name},{id:"description",label:p.description},{id:"device_count",label:p.device_count}],[p]),[h,f]=s.useState(l),y=s.useRef(null),[C,I]=s.useState(null),[k,v]=s.useState({}),[j,B]=s.useState(null),[R,x]=s.useState(!1),[S,z]=s.useState(!1),[E,U]=s.useState(!1),[X,ue]=s.useState(""),Se=s.useCallback(async()=>{try{const O=await(await fetch("/api/sites")).json();o(Array.isArray(O==null?void 0:O.sites)?O.sites:[])}catch{o([])}},[]);s.useEffect(()=>{Se()},[Se]),s.useEffect(()=>{try{const V=localStorage.getItem("site_list_initial_filters");if(V){const O=JSON.parse(V);O&&typeof O=="object"&&v(M=>({...M,...O})),localStorage.removeItem("site_list_initial_filters")}}catch{}},[]);const ce=V=>{a===V?r(u==="asc"?"desc":"asc"):(d(V),r("asc"))},de=s.useMemo(()=>!k||Object.keys(k).length===0?t:t.filter(V=>Object.entries(k).every(([O,M])=>{const g=String(M||"").toLowerCase();return g?String(V[O]??"").toLowerCase().includes(g):!0})),[t,k]),me=s.useMemo(()=>{const V=u==="asc"?1:-1,O=[...de];return O.sort((M,g)=>a==="device_count"?((M.device_count||0)-(g.device_count||0))*V:String(M[a]??"").localeCompare(String(g[a]??""))*V),O},[de,a,u]),w=V=>O=>{y.current=V;try{O.dataTransfer.setData("text/plain",V)}catch{}},W=V=>{V.preventDefault()},F=V=>O=>{O.preventDefault();const M=y.current;!M||M===V||(f(g=>{const L=[...g],we=L.findIndex(ie=>ie.id===M),T=L.findIndex(ie=>ie.id===V);if(we<0||T<0)return g;const[G]=L.splice(we,1);return L.splice(T,0,G),L}),y.current=null)},te=V=>O=>B({id:V,anchorEl:O.currentTarget}),ee=()=>B(null),be=V=>O=>v(M=>({...M,[V]:O.target.value})),Re=me.length>0&&me.every(V=>i.has(V.id)),Ae=i.size>0&&!Re,Le=V=>{const O=V.target.checked;c(M=>{const g=new Set(M);return O?me.forEach(L=>g.add(L.id)):g.clear(),g})},Fe=V=>O=>{const M=O.target.checked;c(g=>{const L=new Set(g);return M?L.add(V):L.delete(V),L})};return e.jsxs(Qe,{sx:{m:2,p:0,bgcolor:"#1e1e1e"},elevation:2,children:[e.jsxs(m,{sx:{p:2,pb:1,display:"flex",alignItems:"center",justifyContent:"space-between"},children:[e.jsx($,{variant:"h6",sx:{color:"#58a6ff",mb:0},children:"Sites"}),e.jsxs(m,{sx:{display:"flex",alignItems:"center",gap:1},children:[e.jsx(Z,{variant:"outlined",size:"small",startIcon:e.jsx(Fs,{}),disabled:i.size!==1,onClick:()=>{const V=i.size===1?Array.from(i)[0]:null;if(V!=null){const O=t.find(M=>M.id===V);ue((O==null?void 0:O.name)||""),U(!0)}},sx:{color:i.size===1?"#58a6ff":"#666",borderColor:i.size===1?"#58a6ff":"#333",textTransform:"none"},children:"Rename"}),e.jsx(Z,{variant:"outlined",size:"small",startIcon:e.jsx(mo,{}),disabled:i.size===0,onClick:()=>z(!0),sx:{color:i.size?"#ff8a8a":"#666",borderColor:i.size?"#ff4f4f":"#333",textTransform:"none"},children:"Delete"}),e.jsx(Z,{variant:"outlined",size:"small",startIcon:e.jsx(ts,{}),onClick:()=>x(!0),sx:{color:"#58a6ff",borderColor:"#58a6ff",textTransform:"none"},children:"Create Site"})]})]}),e.jsxs(Rt,{size:"small",sx:{minWidth:700},children:[e.jsx(Bt,{children:e.jsxs(Ue,{children:[e.jsx(Q,{padding:"checkbox",children:e.jsx(At,{indeterminate:Ae,checked:Re,onChange:Le,sx:{color:"#777"}})}),h.map(V=>e.jsx(Q,{sortDirection:a===V.id?u:!1,draggable:!0,onDragStart:w(V.id),onDragOver:W,onDrop:F(V.id),children:e.jsxs(m,{sx:{display:"flex",alignItems:"center",gap:1},children:[e.jsx(Tt,{active:a===V.id,direction:a===V.id?u:"asc",onClick:()=>ce(V.id),children:V.label}),e.jsx(nt,{size:"small",onClick:te(V.id),sx:{color:k[V.id]?"#58a6ff":"#888"},children:e.jsx(Rn,{fontSize:"inherit"})})]})},V.id))]})}),e.jsxs(Nt,{children:[me.map(V=>e.jsxs(Ue,{hover:!0,children:[e.jsx(Q,{padding:"checkbox",onClick:O=>O.stopPropagation(),children:e.jsx(At,{checked:i.has(V.id),onChange:Fe(V.id),sx:{color:"#777"}})}),h.map(O=>{switch(O.id){case"name":return e.jsx(Q,{onClick:()=>{n&&n(V.name)},sx:{color:"#58a6ff","&:hover":{cursor:"pointer",textDecoration:"underline"}},children:V.name},O.id);case"description":return e.jsx(Q,{children:V.description||""},O.id);case"device_count":return e.jsx(Q,{children:V.device_count??0},O.id);default:return e.jsx(Q,{},O.id)}})]},V.id)),me.length===0&&e.jsx(Ue,{children:e.jsx(Q,{colSpan:h.length+1,sx:{color:"#888"},children:"No sites defined."})})]})]}),e.jsx(Ls,{open:!!C,anchorEl:C,onClose:()=>I(null),anchorOrigin:{vertical:"bottom",horizontal:"right"},PaperProps:{sx:{bgcolor:"#1e1e1e",color:"#fff",p:1}},children:e.jsxs(m,{sx:{display:"flex",flexDirection:"column",gap:.5,p:1},children:[[{id:"name",label:"Name"},{id:"description",label:"Description"},{id:"device_count",label:"Devices"}].map(V=>e.jsxs(fe,{disableRipple:!0,onClick:O=>O.stopPropagation(),sx:{gap:1},children:[e.jsx(At,{size:"small",checked:h.some(O=>O.id===V.id),onChange:O=>{const M=O.target.checked;f(g=>{const L=g.some(we=>we.id===V.id);return M?L?g:[...g,{id:V.id,label:V.label}]:g.filter(we=>we.id!==V.id)})},sx:{p:.3,color:"#bbb"}}),e.jsx($,{variant:"body2",sx:{color:"#ddd"},children:V.label})]},V.id)),e.jsx(m,{sx:{display:"flex",gap:1,pt:.5},children:e.jsx(Z,{size:"small",variant:"outlined",onClick:()=>f(l),sx:{textTransform:"none",borderColor:"#555",color:"#bbb"},children:"Reset Default"})})]})}),e.jsx(Ls,{open:!!j,anchorEl:(j==null?void 0:j.anchorEl)||null,onClose:ee,anchorOrigin:{vertical:"bottom",horizontal:"left"},PaperProps:{sx:{bgcolor:"#1e1e1e",p:1}},children:j&&e.jsxs(m,{sx:{display:"flex",gap:1,alignItems:"center"},children:[e.jsx(Ie,{autoFocus:!0,size:"small",placeholder:`Filter ${((je=h.find(V=>V.id===j.id))==null?void 0:je.label)||""}`,value:k[j.id]||"",onChange:be(j.id),onKeyDown:V=>{V.key==="Escape"&&ee()},sx:{input:{color:"#fff"},minWidth:220,"& .MuiOutlinedInput-root":{"& fieldset":{borderColor:"#555"},"&:hover fieldset":{borderColor:"#888"}}}}),e.jsx(Z,{variant:"outlined",size:"small",onClick:()=>{v(V=>({...V,[j.id]:""})),ee()},sx:{textTransform:"none",borderColor:"#555",color:"#bbb"},children:"Clear"})]})}),e.jsx(Mi,{open:R,onCancel:()=>x(!1),onCreate:async(V,O)=>{try{if(!(await fetch("/api/sites",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({name:V,description:O})})).ok)return;x(!1),await Se()}catch{}}}),e.jsx(Zt,{open:S,message:`Delete ${i.size} selected site(s)? This cannot be undone.`,onCancel:()=>z(!1),onConfirm:async()=>{try{const V=Array.from(i);await fetch("/api/sites/delete",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({ids:V})})}catch{}z(!1),c(new Set),await Se()}}),e.jsx(Di,{open:E,value:X,onChange:ue,onCancel:()=>U(!1),onSave:async()=>{const V=(X||"").trim();if(!V)return;const O=i.size===1?Array.from(i)[0]:null;if(O!=null)try{const M=await fetch("/api/sites/rename",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({id:O,new_name:V})});if(!M.ok){try{const g=await M.json();console.warn("Rename failed",g)}catch{}return}U(!1),await Se()}catch(M){console.warn("Rename error",M)}}})]})}function Yi(n,t,o="Scripts"){const a={},d={id:"root",label:o,path:"",isFolder:!0,children:[]};return a[d.id]=d,(t||[]).forEach(u=>{const r=(u||"").split("/");let i=d.children,c="";r.forEach(p=>{const l=c?`${c}/${p}`:p;let h=i.find(f=>f.id===l);h||(h={id:l,label:p,path:l,isFolder:!0,children:[]},i.push(h),a[l]=h),i=h.children,c=l})}),(n||[]).forEach(u=>{const r=(u.rel_path||"").split("/");let i=d.children,c="";r.forEach((p,l)=>{const h=c?`${c}/${p}`:p,f=l===r.length-1;let y=i.find(C=>C.id===h);y||(y={id:h,label:f&&(u.name||u.file_name)||p,path:h,isFolder:!f,fileName:u.file_name,script:f?u:null,children:[]},i.push(y),a[h]=y),f||(i=y.children,c=h)})}),{root:[d],map:a}}function vo({open:n,onClose:t,hostnames:o=[]}){const[a,d]=s.useState([]),[u,r]=s.useState({}),[i,c]=s.useState(""),[p,l]=s.useState(!1),[h,f]=s.useState(""),[y,C]=s.useState(!1),[I,k]=s.useState("scripts"),[v,j]=s.useState([]),[B,R]=s.useState(!1),[x,S]=s.useState(""),[z,E]=s.useState(""),[U,X]=s.useState(!0),[ue,Se]=s.useState([]),[ce,de]=s.useState({}),[me,w]=s.useState({}),[W,F]=s.useState({loading:!1,error:""}),te=s.useCallback(async()=>{try{const g=await fetch(`/api/assembly/list?island=${I==="ansible"?"ansible":"scripts"}`);if(!g.ok)throw new Error(`HTTP ${g.status}`);const L=await g.json(),{root:we,map:T}=Yi(L.items||[],L.folders||[],I==="ansible"?"Ansible Playbooks":"Scripts");d(we),r(T)}catch(M){console.error("Failed to load scripts:",M),d([]),r({})}},[I]);s.useEffect(()=>{n&&(c(""),f(""),Se([]),de({}),w({}),F({loading:!1,error:""}),X(!0),E(""),te())},[n,te]),s.useEffect(()=>{if(!n||I!=="ansible")return;let M=!1;return R(!0),S(""),(async()=>{try{const g=await fetch("/api/credentials");if(!g.ok)throw new Error(`HTTP ${g.status}`);const L=await g.json();if(M)return;const we=Array.isArray(L==null?void 0:L.credentials)?L.credentials.filter(T=>{const G=String(T.connection_type||"").toLowerCase();return G==="ssh"||G==="winrm"}):[];we.sort((T,G)=>String((T==null?void 0:T.name)||"").localeCompare(String((G==null?void 0:G.name)||""))),j(we)}catch(g){M||(j([]),S(String(g.message||g)))}finally{M||R(!1)}})(),()=>{M=!0}},[n,I]),s.useEffect(()=>{n||E("")},[n]),s.useEffect(()=>{if(!(I!=="ansible"||U)){if(!v.length){E("");return}(!z||!v.some(M=>String(M.id)===String(z)))&&E(String(v[0].id))}},[I,v,z,U]);const ee=(M=[])=>M.map(g=>e.jsx(ys,{itemId:g.id,label:e.jsxs(m,{sx:{display:"flex",alignItems:"center"},children:[g.isFolder?e.jsx(Nn,{fontSize:"small",sx:{mr:1,color:"#ccc"}}):e.jsx(Tn,{fontSize:"small",sx:{mr:1,color:"#ccc"}}),e.jsx($,{variant:"body2",sx:{color:"#e6edf3"},children:g.label})]}),children:g.children&&g.children.length?ee(g.children):null},g.id)),be=(M,g)=>{const L=u[g];L&&!L.isFolder&&(c(L.path),f(""),w({}))},Re=M=>Array.isArray(M)?M.map(g=>{if(!g||typeof g!="object")return null;const L=typeof g.name=="string"?g.name.trim():typeof g.key=="string"?g.key.trim():"";if(!L)return null;const we=typeof g.type=="string"?g.type.toLowerCase():"string",T=typeof g.label=="string"&&g.label.trim()?g.label.trim():L,G=typeof g.description=="string"?g.description:"",ie=!!g.required,Ce=g.hasOwnProperty("default")?g.default:g.hasOwnProperty("defaultValue")?g.defaultValue:g.hasOwnProperty("default_value")?g.default_value:"";return{name:L,label:T,type:we,description:G,required:ie,default:Ce}}).filter(Boolean):[],Ae=M=>{const{type:g,default:L}=M;if(g==="boolean"){if(typeof L=="boolean")return L;if(L==null)return!1;const we=String(L).trim().toLowerCase();return we?["true","1","yes","on"].includes(we):!1}if(g==="number"){if(L==null||L==="")return"";if(typeof L=="number"&&Number.isFinite(L))return String(L);const we=Number(L);return Number.isFinite(we)?String(we):""}return L==null?"":String(L)};s.useEffect(()=>{if(!i){Se([]),de({}),w({}),F({loading:!1,error:""});return}let M=!1;return(async()=>{var L;F({loading:!0,error:""});try{const we=I==="ansible"?"ansible":"scripts",T=(i||"").replace(/\\/g,"/").replace(/^\/+/,"").trim();if(!T){Se([]),de({}),w({}),F({loading:!1,error:""});return}let G=T;we==="scripts"&&G.toLowerCase().startsWith("scripts/")?G=G.slice(8):we==="ansible"&&G.toLowerCase().startsWith("ansible_playbooks/")&&(G=G.slice(18));const ie=await fetch(`/api/assembly/load?island=${we}&path=${encodeURIComponent(G)}`);if(!ie.ok)throw new Error(`Failed to load assembly (HTTP ${ie.status})`);const Ce=await ie.json(),Ee=Re(((L=Ce==null?void 0:Ce.assembly)==null?void 0:L.variables)||[]);if(!M){Se(Ee);const Ne={};Ee.forEach(Ke=>{Ne[Ke.name]=Ae(Ke)}),de(Ne),w({}),F({loading:!1,error:""})}}catch(we){M||(Se([]),de({}),w({}),F({loading:!1,error:(we==null?void 0:we.message)||String(we)}))}})(),()=>{M=!0}},[i,I]);const Le=(M,g)=>{const{name:L,type:we}=M;L&&(de(T=>({...T,[L]:we==="boolean"?!!g:g})),w(T=>{if(!T[L])return T;const G={...T};return delete G[L],G}))},Fe=()=>{const M={};return ue.forEach(g=>{if(!(g!=null&&g.name))return;const{name:L,type:we}=g,G=Object.prototype.hasOwnProperty.call(ce,L)?ce[L]:Ae(g);if(we==="boolean")M[L]=!!G;else if(we==="number")if(G===""||G===null||G===void 0)M[L]="";else{const ie=Number(G);M[L]=Number.isFinite(ie)?ie:""}else M[L]=G==null?"":String(G)}),M},je=async()=>{if(!i){f(I==="ansible"?"Please choose a playbook to run.":"Please choose a script to run.");return}if(I==="ansible"&&!U&&!z){f("Select a credential to run this playbook.");return}if(ue.length){const M={};if(ue.forEach(g=>{if(!g||!g.required||g.type==="boolean")return;const we=Object.prototype.hasOwnProperty.call(ce,g.name)?ce[g.name]:Ae(g);(we==null||we==="")&&(M[g.name]="Required")}),Object.keys(M).length){w(M),f("Please fill in all required variable values.");return}}l(!0),f("");try{let M;const g=Fe();if(I==="ansible")M=await fetch("/api/ansible/quick_run",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({playbook_path:i,hostnames:o,variable_values:g,credential_id:!U&&z?Number(z):null,use_service_account:!!U})});else{const we=i.startsWith("Scripts/")?i:`Scripts/${i}`;M=await fetch("/api/scripts/quick_run",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({script_path:we,hostnames:o,run_mode:y?"current_user":"system",variable_values:g})})}const L=await M.json();if(!M.ok)throw new Error(L.error||`HTTP ${M.status}`);t&&t()}catch(M){f(String(M.message||M))}finally{l(!1)}},O=p||!i||I==="ansible"&&!U&&(!z||!v.length);return e.jsxs(Ze,{open:n,onClose:p?void 0:t,fullWidth:!0,maxWidth:"md",PaperProps:{sx:{bgcolor:"#121212",color:"#fff"}},children:[e.jsx(et,{children:"Quick Job"}),e.jsxs(rt,{children:[e.jsxs(m,{sx:{display:"flex",alignItems:"center",gap:1,mb:1},children:[e.jsx(Z,{size:"small",variant:I==="scripts"?"outlined":"text",onClick:()=>k("scripts"),sx:{textTransform:"none",color:"#58a6ff",borderColor:"#58a6ff"},children:"Scripts"}),e.jsx(Z,{size:"small",variant:I==="ansible"?"outlined":"text",onClick:()=>k("ansible"),sx:{textTransform:"none",color:"#58a6ff",borderColor:"#58a6ff"},children:"Ansible"})]}),e.jsxs($,{variant:"body2",sx:{color:"#aaa",mb:1},children:["Select a ",I==="ansible"?"playbook":"script"," to run on ",o.length," device",o.length!==1?"s":"","."]}),I==="ansible"&&e.jsxs(m,{sx:{display:"flex",alignItems:"center",gap:1.5,flexWrap:"wrap",mb:2},children:[e.jsx(bs,{control:e.jsx(At,{checked:U,onChange:M=>{const g=M.target.checked;X(g),g?E(""):!z&&v.length&&E(String(v[0].id))},size:"small"}),label:"Use Configured svcBorealis Account",sx:{mr:2}}),e.jsxs(Ht,{size:"small",sx:{minWidth:260},disabled:U||B||!v.length,children:[e.jsx(Gt,{sx:{color:"#aaa"},children:"Credential"}),e.jsx(wt,{value:z,label:"Credential",onChange:M=>E(M.target.value),sx:{bgcolor:"#1f1f1f",color:"#fff"},children:v.map(M=>{const g=String(M.connection_type||"").toUpperCase();return e.jsxs(fe,{value:String(M.id),children:[M.name,g?` (${g})`:""]},M.id)})})]}),U&&e.jsx($,{variant:"body2",sx:{color:"#aaa"},children:"Runs with the agent's svcBorealis account."}),B&&e.jsx(Mt,{size:18,sx:{color:"#58a6ff"}}),!B&&x&&e.jsx($,{variant:"body2",sx:{color:"#ff8080"},children:x}),!U&&!B&&!x&&!v.length&&e.jsx($,{variant:"body2",sx:{color:"#ff8080"},children:"No SSH or WinRM credentials available. Create one under Access Management."})]}),e.jsxs(m,{sx:{display:"flex",gap:2},children:[e.jsx(Qe,{sx:{flex:1,p:1,bgcolor:"#1e1e1e",maxHeight:400,overflow:"auto"},children:e.jsx(vs,{sx:{color:"#e6edf3"},onItemSelectionToggle:be,children:a.length?ee(a):e.jsx($,{variant:"body2",sx:{color:"#888",p:1},children:I==="ansible"?"No playbooks found.":"No scripts found."})})}),e.jsxs(m,{sx:{width:320},children:[e.jsx($,{variant:"subtitle2",sx:{color:"#ccc",mb:1},children:"Selection"}),e.jsx($,{variant:"body2",sx:{color:i?"#e6edf3":"#888"},children:i||(I==="ansible"?"No playbook selected":"No script selected")}),e.jsx(m,{sx:{mt:2},children:I!=="ansible"&&e.jsxs(e.Fragment,{children:[e.jsx(bs,{control:e.jsx(At,{size:"small",checked:y,onChange:M=>C(M.target.checked)}),label:e.jsx($,{variant:"body2",children:"Run as currently logged-in user"})}),e.jsx($,{variant:"caption",sx:{color:"#888"},children:"Unchecked = Run-As BUILTIN\\SYSTEM"})]})}),e.jsxs(m,{sx:{mt:3},children:[e.jsx($,{variant:"subtitle2",sx:{color:"#ccc",mb:1},children:"Variables"}),W.loading?e.jsx($,{variant:"body2",sx:{color:"#888"},children:"Loading variables…"}):W.error?e.jsx($,{variant:"body2",sx:{color:"#ff4f4f"},children:W.error}):ue.length?e.jsx(m,{sx:{display:"flex",flexDirection:"column",gap:1.5},children:ue.map(M=>e.jsxs(m,{children:[M.type==="boolean"?e.jsx(bs,{control:e.jsx(At,{size:"small",checked:!!ce[M.name],onChange:g=>Le(M,g.target.checked)}),label:e.jsxs($,{variant:"body2",children:[M.label,M.required?" *":""]})}):e.jsx(Ie,{fullWidth:!0,size:"small",label:`${M.label}${M.required?" *":""}`,type:M.type==="number"?"number":M.type==="credential"?"password":"text",value:ce[M.name]??"",onChange:g=>Le(M,g.target.value),InputLabelProps:{shrink:!0},sx:{"& .MuiOutlinedInput-root":{bgcolor:"#1b1b1b",color:"#e6edf3"},"& .MuiInputBase-input":{color:"#e6edf3"}},error:!!me[M.name],helperText:me[M.name]||M.description||""}),M.type==="boolean"&&M.description?e.jsx($,{variant:"caption",sx:{color:"#888",ml:3},children:M.description}):null]},M.name))}):e.jsx($,{variant:"body2",sx:{color:"#888"},children:"No variables defined for this assembly."})]}),h&&e.jsx($,{variant:"body2",sx:{color:"#ff4f4f",mt:1},children:h})]})]})]}),e.jsxs(tt,{children:[e.jsx(Z,{onClick:t,disabled:p,sx:{color:"#58a6ff"},children:"Cancel"}),e.jsx(Z,{onClick:je,disabled:O,sx:{color:O?"#666":"#58a6ff"},children:"Run"})]})]})}const mn=[{value:"ssh",label:"SSH"},{value:"winrm",label:"WinRM"}],qn={hostname:"",address:"",description:"",operating_system:""};function So({open:n,onClose:t,defaultType:o=null,onCreated:a}){const[d,u]=s.useState(o||"ssh"),[r,i]=s.useState(qn),[c,p]=s.useState(!1),[l,h]=s.useState("");s.useEffect(()=>{n&&(u(o||"ssh"),i(qn),h(""))},[n,o]);const f=()=>{c||t&&t()},y=v=>j=>{const B=j.target.value;i(R=>({...R,[v]:B}))},C=async()=>{if(c)return;const v=r.hostname.trim(),j=r.address.trim();if(!v){h("Hostname is required.");return}if(!d){h("Select a device type.");return}if(!j){h("Address is required.");return}p(!0),h("");const B={hostname:v,address:j,description:r.description.trim(),operating_system:r.operating_system.trim()},R=d==="winrm"?"/api/winrm_devices":"/api/ssh_devices";try{const x=await fetch(R,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(B)}),S=await x.json().catch(()=>({}));if(!x.ok)throw new Error((S==null?void 0:S.error)||`HTTP ${x.status}`);a&&a(S.device||null),t&&t()}catch(x){h(String(x.message||x))}finally{p(!1)}},I=o?`Add ${o.toUpperCase()} Device`:"Add Device",k=(mn.find(v=>v.value===d)||mn[0]).label;return e.jsxs(Ze,{open:n,onClose:f,fullWidth:!0,maxWidth:"sm",PaperProps:{sx:{bgcolor:"#121212",color:"#fff"}},children:[e.jsx(et,{children:I}),e.jsxs(rt,{sx:{display:"flex",flexDirection:"column",gap:2,mt:1},children:[!o&&e.jsx(Ie,{select:!0,label:"Device Type",size:"small",value:d,onChange:v=>u(v.target.value),sx:{"& .MuiOutlinedInput-root":{backgroundColor:"#1f1f1f",color:"#fff","& fieldset":{borderColor:"#555"},"&:hover fieldset":{borderColor:"#888"}},"& .MuiInputLabel-root":{color:"#aaa"}},children:mn.map(v=>e.jsx(fe,{value:v.value,children:v.label},v.value))}),e.jsx(Ie,{label:"Hostname",value:r.hostname,onChange:y("hostname"),size:"small",sx:{"& .MuiOutlinedInput-root":{backgroundColor:"#1f1f1f",color:"#fff","& fieldset":{borderColor:"#555"},"&:hover fieldset":{borderColor:"#888"}},"& .MuiInputLabel-root":{color:"#aaa"}},helperText:"Name used inside Borealis."}),e.jsx(Ie,{label:`${k} Address`,value:r.address,onChange:y("address"),size:"small",sx:{"& .MuiOutlinedInput-root":{backgroundColor:"#1f1f1f",color:"#fff","& fieldset":{borderColor:"#555"},"&:hover fieldset":{borderColor:"#888"}},"& .MuiInputLabel-root":{color:"#aaa"}},helperText:"IP or FQDN reachable from the Borealis server."}),e.jsx(Ie,{label:"Description",value:r.description,onChange:y("description"),size:"small",sx:{"& .MuiOutlinedInput-root":{backgroundColor:"#1f1f1f",color:"#fff","& fieldset":{borderColor:"#555"},"&:hover fieldset":{borderColor:"#888"}},"& .MuiInputLabel-root":{color:"#aaa"}}}),e.jsx(Ie,{label:"Operating System",value:r.operating_system,onChange:y("operating_system"),size:"small",sx:{"& .MuiOutlinedInput-root":{backgroundColor:"#1f1f1f",color:"#fff","& fieldset":{borderColor:"#555"},"&:hover fieldset":{borderColor:"#888"}},"& .MuiInputLabel-root":{color:"#aaa"}}}),l&&e.jsx($,{variant:"body2",sx:{color:"#ff8080"},children:l})]}),e.jsxs(tt,{sx:{px:3,pb:2},children:[e.jsx(Z,{onClick:f,sx:{color:"#58a6ff"},disabled:c,children:"Cancel"}),e.jsx(Z,{onClick:C,variant:"outlined",sx:{color:"#58a6ff",borderColor:"#58a6ff"},disabled:c,children:c?"Saving...":"Save"})]})]})}Bn.registerModules([On]);const Co=Pn.withParams({accentColor:"#FFA6FF",backgroundColor:"#1f2836",browserColorScheme:"dark",chromeBackgroundColor:{ref:"foregroundColor",mix:.07,onto:"backgroundColor"},fontFamily:{googleFont:"IBM Plex Sans"},foregroundColor:"#FFF",headerFontSize:14}),Ki=Co.themeName||"ag-theme-quartz",Qt='"IBM Plex Sans", "Helvetica Neue", Arial, sans-serif',xn='"Quartz Regular"',Xi=n=>{const t=(n||"").toString().toLowerCase();return t?t.includes("mac")||t.includes("os x")||t.includes("darwin")?"fa-brands fa-apple":t.includes("win")?"fa-brands fa-windows":t.includes("linux")||t.includes("ubuntu")||t.includes("debian")||t.includes("fedora")||t.includes("red hat")||t.includes("centos")||t.includes("suse")||t.includes("rhel")?"fa-brands fa-linux":"":""},Qi=es.memo(function(t){const{value:o,data:a,onSaveDescription:d,fontFamily:u}=t,r=typeof o=="string"?o:o==null?"":String(o),[i,c]=s.useState(r),[p,l]=s.useState(!1),[h,f]=s.useState(!1),[y,C]=s.useState("");s.useEffect(()=>{!p&&!h&&c(r)},[r,p,h]);const I=s.useCallback(x=>{x.stopPropagation(),l(!0),C("")},[]),k=s.useCallback(x=>{c(x.target.value)},[]),v=s.useCallback(async x=>{if(x.stopPropagation(),x.key==="Enter"){x.preventDefault();const S=(i||"").trim();if(S===r.trim()){l(!1),c(r),C("");return}if(typeof d!="function"||!a){l(!1),C("");return}f(!0),C("");const z=await d(a,S);f(!1),z?l(!1):C("Failed to save description")}else x.key==="Escape"&&(x.preventDefault(),c(r),l(!1),C(""))},[a,i,d,r]),j=s.useCallback(x=>{x.stopPropagation(),!h&&(l(!1),c(r),C(""))},[h,r]),B=s.useCallback(x=>{x.stopPropagation()},[]),R=h?"rgba(255,255,255,0.04)":p?"rgba(255,255,255,0.16)":"rgba(255,255,255,0.02)";return e.jsx(Ie,{value:i,onFocus:I,onChange:k,onKeyDown:v,onBlur:j,onClick:B,onMouseDown:B,variant:"outlined",size:"small",fullWidth:!0,disabled:h,error:!!y,helperText:y||void 0,FormHelperTextProps:y?{sx:{minHeight:18,fontSize:"0.75rem"}}:{sx:{display:"none"}},sx:{mt:.5,mb:.5,"& .MuiOutlinedInput-root":{backgroundColor:R,transition:"background-color 0.2s ease, border-color 0.2s ease",color:"rgba(255,255,255,0.85)",fontFamily:u||Qt,fontSize:"0.875rem",height:34,py:0,pr:0,"& fieldset":{borderColor:p?"#FFA6FF":"rgba(255,255,255,0.25)"},"&:hover fieldset":{borderColor:"#FFA6FF"},"&.Mui-focused fieldset":{borderColor:"#FFA6FF"},"&.Mui-disabled":{backgroundColor:"rgba(255,255,255,0.08)"}},"& .MuiOutlinedInput-input":{color:"rgba(255,255,255,0.85)",py:.75,px:1.5},"& .MuiFormHelperText-root":{color:"#ff7b7b",mt:.25}},inputProps:{sx:{textOverflow:"ellipsis"}}})});function Jn(n,t=300){if(!n)return"unknown";if(Date.now()/1e3-n<=t)return"Currently Online";const a=new Date(n*1e3),d=a.toLocaleDateString("en-US",{month:"2-digit",day:"2-digit",year:"numeric"}),u=a.toLocaleTimeString("en-US",{hour:"numeric",minute:"2-digit"});return`${d} @ ${u}`}function Zi(n,t=300){return n&&Date.now()/1e3-n<=t?"Online":"Offline"}function Yn(n){const t=Number(n);if(!Number.isFinite(t)||t<=0)return"";const o=[],a=Math.floor(t/86400);a&&o.push(`${a}d`);const d=Math.floor(t%86400/3600);d&&o.push(`${d}h`);const u=Math.floor(t%3600/60);u&&o.push(`${u}m`);const r=Math.floor(t%60);return!o.length&&r&&o.push(`${r}s`),o.join(" ")}function _o({onSelectDevice:n,filterMode:t="all",title:o,showAddButton:a,addButtonLabel:d,defaultAddType:u}){const[r,i]=s.useState([]),[c,p]=s.useState(null),[l,h]=s.useState(null),[f,y]=s.useState(!1),[C,I]=s.useState(()=>new Set),[k,v]=s.useState(!1),[j,B]=s.useState(!1),[R,x]=s.useState(null),S=s.useMemo(()=>{if(o)return o;switch(t){case"agent":return"Agent Devices";case"ssh":return"SSH Devices";case"winrm":return"WinRM Devices";default:return"Device Inventory"}},[t,o]),z=s.useMemo(()=>u!==void 0?u:t==="ssh"||t==="winrm"?t:null,[u,t]),E=s.useMemo(()=>d||(t==="ssh"?"Add SSH Device":t==="winrm"?"Add WinRM Device":"Add Device"),[d,t]),U=s.useMemo(()=>typeof a=="boolean"?a:t!=="agent",[a,t]),[X,ue]=s.useState([]),[Se,ce]=s.useState("default"),[de,me]=s.useState(!1),[w,W]=s.useState(""),[F,te]=s.useState(!1),[ee,be]=s.useState(""),[Re,Ae]=s.useState(null),[Le,Fe]=s.useState(null),[je,V]=s.useState(null),O=s.useMemo(()=>({status:"Status",agentVersion:"Agent Version",site:"Site",hostname:"Hostname",description:"Description",lastUser:"Last User",type:"Type",os:"OS",internalIp:"Internal IP",externalIp:"External IP",lastReboot:"Last Reboot",created:"Created",lastSeen:"Last Seen",agentId:"Agent ID",agentHash:"Agent Hash",agentGuid:"Agent GUID",domain:"Domain",uptime:"Uptime",memory:"Memory",network:"Network",software:"Software",storage:"Storage",cpu:"CPU",siteDescription:"Site Description"}),[]),M=s.useMemo(()=>[{id:"status",label:O.status},{id:"agentVersion",label:O.agentVersion},{id:"site",label:O.site},{id:"hostname",label:O.hostname},{id:"description",label:O.description},{id:"lastUser",label:O.lastUser},{id:"type",label:O.type},{id:"os",label:O.os}],[O]),[g,L]=s.useState(M),[we,T]=s.useState(null),G=s.useRef(null),[ie,Ce]=s.useState({}),Ee=s.useCallback(N=>{if(!N||typeof N!="object")return{};const H={};return Object.entries(N).forEach(([Y,se])=>{if(typeof se=="string"){const ye=se.trim();ye&&(H[Y]={filterType:"text",type:"contains",filter:ye});return}if(!se||typeof se!="object")return;const ne=JSON.parse(JSON.stringify(se));ne.filterType||(ne.filterType="text"),!(ne.filterType==="text"&&(typeof ne.filter=="string"&&(ne.filter=ne.filter.trim()),Array.isArray(ne.conditions)&&(ne.conditions=ne.conditions.map(ye=>{if(!ye||typeof ye!="object")return null;const ve={...ye};return typeof ve.filter=="string"&&(ve.filter=ve.filter.trim()),!ve.filter&&!["blank","notBlank"].includes(ve.type??"")?null:ve}).filter(Boolean),ne.conditions.length||delete ne.conditions),!ne.filter&&!ne.conditions&&!["blank","notBlank"].includes(ne.type??"")))&&(H[Y]=ne)}),H},[]),Ne=s.useCallback((N,H)=>JSON.stringify(N??{})===JSON.stringify(H??{}),[]),Ke=s.useCallback(N=>{const H=N&&typeof N=="object"?Ee(N):{};Ce(Y=>Ne(Y,H)?Y:H)},[Ne,Ee]),at=s.useCallback(N=>{if(!N||typeof N!="object")return;const H=Ee(N);Object.keys(H).length&&Ce(Y=>{const se=Y||{},ne={...se};let ye=!1;return Object.entries(H).forEach(([ve,ge])=>{ge&&(!ne[ve]||!Ne(ne[ve],ge))&&(ne[ve]=ge,ye=!0)}),ye?ne:se})},[Ne,Ee]),ut=ie,[Pe,gt]=s.useState([]),[bt,vt]=s.useState(!1),[Ut,It]=s.useState(null),[yt,pt]=s.useState([]),[St,ct]=s.useState(null),oe=s.useRef(0),_e=Ki,$e=s.useCallback(async(N={})=>{const{force:H=!1}=N||{},Y=Date.now(),se=Y-oe.current;if(!H&&St&&se>=0&&se<6e4)return St;try{const ne=new URLSearchParams({repo:"bunny-lab-io/Borealis",branch:"main"});H&&ne.set("refresh","1");const ye=await fetch(`/api/repo/current_hash?${ne.toString()}`),ve=await ye.json(),ge=((ve==null?void 0:ve.sha)||"").trim();if(!ye.ok||!ge){const Me=new Error(`Latest hash status ${ye.status}${ve!=null&&ve.error?` - ${ve.error}`:""}`);throw Me.response=ve,Me}return oe.current=Y,ct(Me=>ge||Me||null),ge||null}catch(ne){return console.warn("Failed to fetch repository hash",ne),!H&&St?St:(oe.current=Y,ct(ye=>ye||null),null)}},[St]),Xe=s.useCallback((N,H)=>{const Y=(N||"").trim(),se=(H||"").trim();return se?Y&&Y===se?"Up-to-Date":"Needs Updated":"Unknown"},[]),We=s.useCallback(async(N={})=>{const{refreshRepo:H=!1}=N||{};let Y=St;if(H||!Y){const ve=await $e({force:H});ve&&(Y=ve)}const se=new Map,ne=new Map,ye=new Map;try{const ve=await fetch("/api/agent/hash_list");if(ve.ok){const ge=await ve.json();(Array.isArray(ge==null?void 0:ge.agents)?ge.agents:[]).forEach(Ve=>{if(!Ve||typeof Ve!="object")return;const it=(Ve.agent_hash||"").trim();if(!it)return;const J=(Ve.agent_id||"").trim(),Te=(Ve.agent_guid||"").trim().toLowerCase(),Ge=(Ve.hostname||"").trim().toLowerCase(),He=(Ve.source||"").trim()==="memory";J&&(!se.has(J)||He)&&se.set(J,it),Te&&(!ne.has(Te)||He)&&ne.set(Te,it),Ge&&(!ye.has(Ge)||He)&&ye.set(Ge,it)})}}catch(ve){console.warn("Failed to fetch agent hash list",ve)}try{const ve=await fetch("/api/devices");if(!ve.ok){const Te=new Error(`Failed to fetch devices (${ve.status})`);try{Te.response=await ve.json()}catch{}throw Te}const ge=await ve.json(),Me=Array.isArray(ge==null?void 0:ge.devices)?ge.devices:[],Ve=Te=>{if(!Te)return"";try{return JSON.stringify(Te)}catch{return""}},it=Me.map((Te,Ge)=>{const He=Te&&typeof Te.summary=="object"?{...Te.summary}:{},fs=(Te.hostname||He.hostname||"").trim()||`device-${Ge+1}`,zt=(Te.agent_id||He.agent_id||"").trim(),Ft=(Te.agent_guid||He.agent_guid||"").trim(),kt=Ft.toLowerCase(),qe=Ft||zt||fs||`device-${Ge+1}`;let xt=(Te.agent_hash||He.agent_hash||"").trim();zt&&se.has(zt)&&(xt=se.get(zt)||xt),!xt&&kt&&ne.has(kt)&&(xt=ne.get(kt)||xt);const ns=fs.trim().toLowerCase();!xt&&ns&&ye.has(ns)&&(xt=ye.get(ns)||xt);const hs=Number(Te.last_seen||He.last_seen||0)||0,Cs=Te.status||Zi(hs);Ft&&!He.agent_guid&&(He.agent_guid=Ft);let ms=Number(Te.created_at||0)||0,Kt=He.created||"";if(!ms&&Kt){const xs=Date.parse(Kt.replace(" ","T"));Number.isNaN(xs)||(ms=Math.floor(xs/1e3))}if(!Kt&&Te.created_at_iso)try{Kt=new Date(Te.created_at_iso).toLocaleString()}catch{}const Ws=Te.operating_system||He.operating_system||He.agent_operating_system||"-",Vs=(Te.device_type||He.device_type||"").trim(),Hs=(Te.last_user||He.last_user||"").trim(),_s=(Te.domain||He.domain||"").trim(),an=(Te.internal_ip||He.internal_ip||"").trim(),ks=(Te.external_ip||He.external_ip||"").trim(),Gs=(Te.last_reboot||He.last_reboot||"").trim(),Is=Number(Te.uptime||He.uptime_sec||He.uptime_seconds||He.uptime||0)||0,js=(Te.connection_type||He.connection_type||"").trim().toLowerCase(),Xt=js==="ssh"?"SSH":js==="winrm"?"WinRM":"",ln=(Te.connection_endpoint||He.connection_endpoint||"").trim(),Vt=Array.isArray(Te.memory)?Te.memory:[],Rs=Array.isArray(Te.network)?Te.network:[],Ns=Array.isArray(Te.software)?Te.software:[],Ts=Array.isArray(Te.storage)?Te.storage:[],As=Te.cpu&&typeof Te.cpu=="object"&&Te.cpu||(He.cpu&&typeof He.cpu=="object"?He.cpu:{}),cn=Vt.length?`${Vt.length} module(s)`:"",qs=Rs.length?Rs.map(xs=>xs.adapter||xs.name||"").filter(Boolean).join(", "):"",Js=Ns.length?`${Ns.length} item(s)`:"",dn=Ts.length?`${Ts.length} volume(s)`:"",un=As.name||He.processor||"";return{id:qe,hostname:fs,status:Cs,lastSeen:hs,lastSeenDisplay:Jn(hs),os:Ws,lastUser:Hs,type:Vs||Xt||"",site:Te.site_name||"Not Configured",siteId:Te.site_id||null,siteDescription:Te.site_description||"",description:(Te.description||He.description||"").trim(),created:Kt,createdTs:ms,createdIso:Te.created_at_iso||"",agentGuid:Ft,agentHash:xt,agentVersion:Xe(xt,Y),agentId:zt,domain:_s,internalIp:an,externalIp:ks,lastReboot:Gs,uptime:Is,uptimeDisplay:Yn(Is),memory:cn,memoryRaw:Ve(Vt),network:qs,networkRaw:Ve(Rs),software:Js,softwareRaw:Ve(Ns),storage:dn,storageRaw:Ve(Ts),cpu:un,cpuRaw:Ve(As),summary:He,details:Te.details||{},connectionType:js,connectionLabel:Xt,connectionEndpoint:ln,isRemote:!!Xt}});let J=it;t==="agent"?J=it.filter(Te=>!Te.connectionType):t==="ssh"?J=it.filter(Te=>Te.connectionType==="ssh"):t==="winrm"&&(J=it.filter(Te=>Te.connectionType==="winrm")),i(J)}catch(ve){console.warn("Failed to load devices:",ve),i([])}},[St,$e,Xe,t]),Je=s.useCallback(async()=>{try{const H=await(await fetch("/api/device_list_views")).json();H&&Array.isArray(H.views)?ue(H.views):ue([])}catch{ue([])}},[]);s.useEffect(()=>{We({refreshRepo:!0})},[We]),s.useEffect(()=>{Je()},[Je]);const ft=s.useCallback(async()=>{try{const H=await(await fetch("/api/sites")).json();gt(Array.isArray(H==null?void 0:H.sites)?H.sites:[])}catch{gt([])}},[]);s.useEffect(()=>{try{const N=localStorage.getItem("device_list_initial_filters");if(N){const Y=JSON.parse(N);Y&&typeof Y=="object"&&(at(Y),Y.site&&L(se=>{if(se.some(ge=>ge.id==="site"))return se;const ne=se.some(ge=>ge.id==="agentVersion"),ye=se.filter(ge=>!["status","agentVersion"].includes(ge.id)),ve=[{id:"status",label:O.status},...ne?[{id:"agentVersion",label:O.agentVersion}]:[],{id:"site",label:O.site}];return ne?[...ve,...ye]:ve.concat(se.filter(ge=>ge.id!=="status"))})),localStorage.removeItem("device_list_initial_filters")}const H=localStorage.getItem("device_list_initial_site_filter");H&&H.trim()&&(L(Y=>{if(Y.some(ge=>ge.id==="site"))return Y;const ne=[...Y],ye=ne.findIndex(ge=>ge.id==="agentVersion"),ve=ye>=0?ye+1:1;return ne.splice(ve,0,{id:"site",label:O.site}),ne}),at({site:H}),localStorage.removeItem("device_list_initial_site_filter"))}catch{}},[O.site,at]);const ht=s.useCallback(N=>{if(!N||N.id==="default"){L(M),Ke({});return}try{const se=["status",...(Array.isArray(N.columns)?N.columns:[]).filter(ne=>ne!=="status")].filter(ne=>O[ne]).map(ne=>({id:ne,label:O[ne]}));L(se.length?se:M),Ke(N.filters&&typeof N.filters=="object"?N.filters:{})}catch{L(M),Ke({})}},[O,M,Ke]),Jt=s.useMemo(()=>({Online:{text:"#00d18c",background:"rgba(0, 209, 140, 0.16)",border:"1px solid rgba(0, 209, 140, 0.45)",dot:"#00d18c"},Offline:{text:"#b0b8c8",background:"rgba(176, 184, 200, 0.14)",border:"1px solid rgba(176, 184, 200, 0.35)",dot:"#c3cada"},default:{text:"#e2e6f0",background:"rgba(226, 230, 240, 0.12)",border:"1px solid rgba(226, 230, 240, 0.25)",dot:"#e2e6f0"}}),[]),Ct=s.useCallback((N,H)=>{if(H){const Y=new Date(H*1e3),se=String(Y.getMonth()+1).padStart(2,"0"),ne=String(Y.getDate()).padStart(2,"0"),ye=Y.getFullYear(),ve=Y.getHours()%12||12,ge=String(Y.getMinutes()).padStart(2,"0"),Me=Y.getHours()>=12?"PM":"AM";return`${se}/${ne}/${ye} @ ${ve}:${ge} ${Me}`}return N||""},[]),Wt=s.useMemo(()=>JSON.parse(JSON.stringify(ut||{})),[ut]);s.useEffect(()=>{var N;(N=G.current)!=null&&N.api&&G.current.api.setFilterModel(Wt)},[Wt]);const lt=s.useCallback(N=>{const H=N.api.getFilterModel()||{};Ke(H)},[Ke]),Dt=s.useCallback(()=>{var se;const N=(se=G.current)==null?void 0:se.api;if(!N)return;const Y=N.getSelectedNodes().map(ne=>{var ye;return(ye=ne.data)==null?void 0:ye.id}).filter(ne=>ne!=null);I(new Set(Y))},[]),Ot=s.useCallback((N,H)=>{p(N.currentTarget),h(H)},[]),_t=s.useCallback(()=>p(null),[]),Yt=s.useCallback(()=>{_t(),y(!0)},[_t]),ss=s.useCallback(async()=>{var H;if(!l)return;const N=l.agentId||((H=l.summary)==null?void 0:H.agent_id)||l.id;try{N&&await fetch(`/api/agent/${encodeURIComponent(N)}`,{method:"DELETE"})}catch(Y){console.warn("Failed to remove agent",Y)}i(Y=>Y.filter(se=>se.id!==l.id)),I(Y=>{if(!Y.has(l.id))return Y;const se=new Set(Y);return se.delete(l.id),se}),y(!1),h(null)},[l]),A=s.useCallback(N=>{const H=N.data;if(!H)return null;const Y=ve=>{ve.preventDefault(),ve.stopPropagation(),n&&n(H)},se=H.connectionLabel||"";let ne="#2d3042",ye="#a4c7ff";return se==="SSH"?(ne="#2a3b28",ye="#7cffc4"):se==="WinRM"&&(ne="#352e3b",ye="#ffb6ff"),e.jsxs(m,{component:"span",sx:{display:"flex",alignItems:"center",gap:1},children:[se?e.jsx(m,{component:"span",sx:{display:"inline-flex",alignItems:"center",px:.75,py:.1,borderRadius:999,bgcolor:ne,color:ye,fontSize:"11px",fontWeight:600,textTransform:"uppercase"},children:se}):null,e.jsx("a",{href:"#",onClick:Y,style:{color:"#58a6ff",textDecoration:"none",fontWeight:500},children:H.hostname||""})]})},[n]),q=s.useCallback(N=>{const H=N.value||"";if(!H)return null;const Y=Jt[H]||Jt.default;return e.jsxs(m,{component:"span",sx:{display:"inline-flex",alignItems:"center",justifyContent:"center",minWidth:76,px:1.5,py:.4,borderRadius:999,backgroundColor:Y.background,border:Y.border,color:Y.text,fontWeight:600,fontSize:"13px",lineHeight:1,fontFamily:Qt,textTransform:"capitalize",gap:.75},children:[e.jsx(m,{component:"span",sx:{width:8,height:8,borderRadius:"50%",backgroundColor:Y.dot,boxShadow:"0 0 0 2px rgba(0, 0, 0, 0.22)"}}),H]})},[Jt,Qt]),le=s.useCallback(N=>{const H=N.value,Y=typeof H=="string"?H:H==null?"":String(H),se=Y.trim()||"-",ne=Xi(Y);return e.jsxs(m,{component:"span",sx:{display:"inline-flex",alignItems:"center",gap:1,color:"rgba(255,255,255,0.85)",fontFamily:Qt},children:[ne?e.jsx(m,{component:"i",className:ne,"aria-hidden":"true",sx:{fontSize:"1rem",width:"1.5rem",textAlign:"center",color:"rgba(255,255,255,0.75)"}}):null,e.jsx(m,{component:"span",sx:{lineHeight:1.3},children:se})]})},[]),he=s.useCallback(N=>{const H=N.data;if(!H)return null;const Y=se=>{se.stopPropagation(),Ot(se,H)};return e.jsx(nt,{size:"small",onClick:Y,sx:{color:"#ccc"},children:e.jsx(on,{fontSize:"small"})})},[Ot]),_=s.useCallback(async(N,H)=>{var ne;if(!N)return!1;const Y=(H||"").trim(),se=(N.hostname||((ne=N.summary)==null?void 0:ne.hostname)||"").trim();if(!se)return!1;try{const ye=await fetch(`/api/device/description/${se}`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({description:Y})});if(!ye.ok)throw new Error(`HTTP ${ye.status}`);const ve=N.id||N.agentGuid||N.hostname||se;return i(ge=>ge.map(Me=>{if((Me.id||Me.agentGuid||Me.hostname||"")!==ve)return Me;const it={...Me,description:Y,summary:{...Me.summary||{},description:Y}};return Me.details&&(it.details={...Me.details,description:Y}),it})),h(ge=>{if(!ge||(ge.id||ge.agentGuid||ge.hostname||"")!==ve)return ge;const Ve={...ge,description:Y,summary:{...ge.summary||{},description:Y}};return ge.details&&(Ve.details={...ge.details,description:Y}),Ve}),!0}catch(ye){return console.warn("Failed to save description",ye),!1}},[i,h]),K=s.useMemo(()=>{const N=g.map(H=>{switch(H.id){case"status":return{field:"status",headerName:H.label,cellRenderer:q,cellClass:"status-pill-cell",width:112,minWidth:112,flex:0};case"agentVersion":return{field:"agentVersion",headerName:H.label,width:140,minWidth:150,flex:0};case"site":return{field:"site",headerName:H.label,valueGetter:Y=>{var se;return((se=Y.data)==null?void 0:se.site)||"Not Configured"},width:140,minWidth:140,flex:0};case"hostname":return{field:"hostname",headerName:H.label,cellRenderer:A,width:210,minWidth:210,flex:0};case"description":return{field:"description",headerName:H.label,width:280,minWidth:280,flex:0,cellRenderer:Qi,cellRendererParams:{onSaveDescription:_,fontFamily:Qt}};case"lastUser":return{field:"lastUser",headerName:H.label,width:220,minWidth:220,flex:0};case"type":return{field:"type",headerName:H.label,width:170,minWidth:170,flex:0};case"os":return{field:"os",headerName:H.label,width:410,minWidth:410,flex:1,cellRenderer:le};case"internalIp":return{field:"internalIp",headerName:H.label,width:140,minWidth:140,flex:0};case"externalIp":return{field:"externalIp",headerName:H.label,width:140,minWidth:140,flex:0};case"lastReboot":return{field:"lastReboot",headerName:H.label,width:180,minWidth:180,flex:0};case"created":return{field:"created",headerName:H.label,valueGetter:Y=>{var se,ne;return Ct((se=Y.data)==null?void 0:se.created,(ne=Y.data)==null?void 0:ne.createdTs)},comparator:(Y,se,ne,ye)=>{var ve,ge;return(((ve=ne==null?void 0:ne.data)==null?void 0:ve.createdTs)||0)-(((ge=ye==null?void 0:ye.data)==null?void 0:ge.createdTs)||0)},width:200,minWidth:200,flex:0};case"lastSeen":return{field:"lastSeen",headerName:H.label,valueGetter:Y=>{var se;return Jn((se=Y.data)==null?void 0:se.lastSeen)},comparator:(Y,se,ne,ye)=>{var ve,ge;return(((ve=ne==null?void 0:ne.data)==null?void 0:ve.lastSeen)||0)-(((ge=ye==null?void 0:ye.data)==null?void 0:ge.lastSeen)||0)},width:200,minWidth:200,flex:0};case"agentId":return{field:"agentId",headerName:H.label,width:290,minWidth:290,flex:0};case"agentHash":return{field:"agentHash",headerName:H.label,width:365,minWidth:365,flex:0};case"agentGuid":return{field:"agentGuid",headerName:H.label,width:345,minWidth:345,flex:0};case"domain":return{field:"domain",headerName:H.label,width:160,minWidth:160,flex:0};case"uptime":return{field:"uptime",headerName:H.label,valueGetter:Y=>{var se,ne;return((se=Y.data)==null?void 0:se.uptimeDisplay)||Yn(((ne=Y.data)==null?void 0:ne.uptime)||0)},comparator:(Y,se,ne,ye)=>{var ve,ge;return(((ve=ne==null?void 0:ne.data)==null?void 0:ve.uptime)||0)-(((ge=ye==null?void 0:ye.data)==null?void 0:ge.uptime)||0)},width:140,minWidth:140,flex:0};case"memory":case"network":case"software":case"storage":case"cpu":case"siteDescription":return{field:H.id,headerName:H.label,minWidth:200};default:return{field:H.id,headerName:H.label}}});return[{headerName:"",field:"__select__",width:52,maxWidth:52,checkboxSelection:!0,headerCheckboxSelection:!0,resizable:!1,sortable:!1,suppressMenu:!0,filter:!1,pinned:"left",lockPosition:!0},...N,{headerName:"",field:"__actions__",width:64,maxWidth:64,resizable:!1,sortable:!1,suppressMenu:!0,filter:!1,cellRenderer:he,pinned:"right"}]},[g,he,Ct,_,A,q]),pe=s.useMemo(()=>({sortable:!0,filter:"agTextColumnFilter",resizable:!0,flex:1,minWidth:160}),[]),re=s.useCallback(N=>{N.api.setFilterModel(Wt)},[Wt]),ke=s.useCallback(N=>{var H,Y,se;return((H=N.data)==null?void 0:H.id)||((Y=N.data)==null?void 0:Y.agentGuid)||((se=N.data)==null?void 0:se.hostname)||String(N.rowIndex??"")},[]);return e.jsxs(Qe,{sx:{m:2,p:0,bgcolor:"#1e1e1e",fontFamily:Qt,color:"#f5f7fa",display:"flex",flexDirection:"column",flexGrow:1,minWidth:0,height:"100%"},elevation:2,children:[e.jsxs(m,{sx:{p:2,pb:1,display:"flex",flexDirection:"column",gap:1},children:[e.jsxs(m,{sx:{display:"flex",alignItems:"center",justifyContent:"space-between"},children:[e.jsx($,{variant:"h6",sx:{color:"#58a6ff",mb:0},children:S}),e.jsxs(m,{sx:{display:"flex",alignItems:"center"},children:[e.jsxs(m,{sx:{display:"flex",alignItems:"center",mr:1},children:[e.jsxs(Ie,{select:!0,size:"small",value:Se,onChange:N=>{const H=N.target.value;if(ce(H),H==="default")ht({id:"default"});else{const Y=X.find(se=>String(se.id)===String(H));Y&&ht(Y)}},sx:{minWidth:220,mr:0,"& .MuiOutlinedInput-root":{height:32,pr:0,borderTopRightRadius:0,borderBottomRightRadius:0,"& fieldset":{borderColor:"#555",borderRight:"1px solid #555"},"&:hover fieldset":{borderColor:"#888"}},"& .MuiSelect-select":{display:"flex",alignItems:"center",py:0}},SelectProps:{MenuProps:{PaperProps:{sx:{bgcolor:"#1e1e1e",color:"#fff"}}},renderValue:N=>{if(N==="default")return"Default View";const H=X.find(Y=>String(Y.id)===String(N));return H?H.name:"Default View"}},children:[e.jsx(fe,{value:"default",children:"Default View"}),X.map(N=>e.jsx(fe,{value:N.id,disableRipple:!0,children:e.jsxs(m,{sx:{display:"flex",alignItems:"center",justifyContent:"space-between",width:"100%"},children:[e.jsx("span",{children:N.name}),e.jsx(nt,{size:"small",onClick:H=>{H.stopPropagation(),Fe(H.currentTarget),V(N)},sx:{color:"#ccc"},children:e.jsx(on,{fontSize:"small"})})]})},N.id))]}),e.jsx(nt,{size:"small",onClick:()=>{W(""),me(!0)},sx:{ml:"-1px",border:"1px solid #555",borderLeft:"1px solid #555",borderRadius:"0 4px 4px 0",color:"#bbb",height:32,width:32},children:e.jsx(ts,{fontSize:"small"})})]}),e.jsx(st,{title:"Refresh Devices to Detect Changes",children:e.jsx(nt,{size:"small",onClick:()=>We({refreshRepo:!0}),sx:{color:"#bbb",mr:1},children:e.jsx(rr,{fontSize:"small"})})}),e.jsx(st,{title:"Column Chooser",children:e.jsx(nt,{size:"small",onClick:N=>T(N.currentTarget),sx:{color:"#bbb",mr:1},children:e.jsx(ar,{fontSize:"small"})})}),U&&e.jsx(Z,{variant:"contained",size:"small",startIcon:e.jsx(ts,{}),sx:{bgcolor:"#58a6ff",color:"#0b0f19"},onClick:()=>{x(z??null),B(!0)},children:E})]})]}),e.jsx(m,{sx:{display:"flex",gap:1},children:e.jsx(Z,{variant:"outlined",size:"small",disabled:C.size===0,onClick:()=>v(!0),sx:{color:C.size===0?"#666":"#58a6ff",borderColor:C.size===0?"#333":"#58a6ff",textTransform:"none"},children:"Quick Job"})})]}),e.jsx(m,{sx:{mt:"10px",px:2,pb:2,flexGrow:1,minHeight:0,display:"flex",flexDirection:"column"},children:e.jsx(m,{className:_e,sx:{width:"100%",flexGrow:1,minHeight:0,height:"100%",fontFamily:Qt,"--ag-font-family":Qt,"--ag-icon-font-family":xn,"& .ag-root-wrapper":{borderRadius:1,minHeight:400},"& .ag-root, & .ag-header, & .ag-center-cols-container, & .ag-paging-panel":{fontFamily:Qt},"& .ag-icon":{fontFamily:xn},"& .status-pill-cell":{display:"flex",alignItems:"center"},"& .status-pill-cell .ag-cell-wrapper":{width:"100%",display:"flex",alignItems:"center",justifyContent:"center",height:"100%",paddingTop:0,paddingBottom:0,lineHeight:"normal"},"& .status-pill-cell .ag-cell-value":{width:"100%",display:"flex",justifyContent:"center",alignItems:"center",height:"100%"},"& .status-pill-cell .ag-cell-value > span":{margin:0}},children:e.jsx(An,{ref:G,rowData:r,columnDefs:K,defaultColDef:pe,rowSelection:"multiple",rowMultiSelectWithClick:!0,pagination:!0,paginationPageSize:25,animateRows:!0,onSelectionChanged:Dt,onFilterChanged:lt,onGridReady:re,getRowId:ke,theme:Co,style:{width:"100%",height:"100%",fontFamily:Qt,"--ag-icon-font-family":xn}})})}),e.jsxs(Et,{anchorEl:Le,open:!!Le,onClose:()=>{Fe(null),V(null)},PaperProps:{sx:{bgcolor:"#1e1e1e",color:"#fff",fontSize:"13px"}},children:[e.jsx(fe,{onClick:()=>{const N=je;Fe(null),N&&(Ae(N),be(N.name||""),te(!0))},children:"Rename"}),e.jsx(fe,{sx:{color:"#ff4f4f"},onClick:async()=>{const N=je;if(Fe(null),!!N){try{await fetch(`/api/device_list_views/${encodeURIComponent(N.id)}`,{method:"DELETE"})}catch{}ue(H=>H.filter(Y=>String(Y.id)!==String(N.id))),String(Se)===String(N.id)&&(ce("default"),ht({id:"default"}))}},children:"Delete"})]}),e.jsx(Pi,{open:de,value:w,onChange:W,onCancel:()=>me(!1),onSave:async()=>{const N=(w||"").trim();if(!N)return;const H=(g||[]).map(se=>se.id),Y={name:N,columns:H,filters:ut};try{const se=await fetch("/api/device_list_views",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(Y)});if(se.ok){const ne=await se.json();ue(ye=>[...ye,ne].sort((ve,ge)=>String(ve.name).localeCompare(String(ge.name)))),ce(String(ne.id)),me(!1),W("")}}catch{}}}),e.jsx(Ei,{open:F,value:ee,onChange:be,onCancel:()=>te(!1),onSave:async()=>{const N=Re,H=(ee||"").trim();if(!(!N||!H))try{const Y=await fetch(`/api/device_list_views/${encodeURIComponent(N.id)}`,{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify({name:H})});if(Y.ok){const se=await Y.json();ue(ne=>ne.map(ye=>String(ye.id)===String(N.id)?se:ye)),te(!1),be(""),Ae(null)}}catch{}}}),e.jsx(Ls,{open:!!we,anchorEl:we,onClose:()=>T(null),anchorOrigin:{vertical:"bottom",horizontal:"right"},PaperProps:{sx:{bgcolor:"#1e1e1e",color:"#fff",p:1}},children:e.jsxs(m,{sx:{display:"flex",flexDirection:"column",gap:.5,p:1},children:[Object.entries(O).filter(([N])=>N!=="status").map(([N,H])=>e.jsxs(fe,{disableRipple:!0,onClick:Y=>Y.stopPropagation(),sx:{gap:1},children:[e.jsx(At,{size:"small",checked:g.some(Y=>Y.id===N),onChange:Y=>{const se=Y.target.checked;L(ne=>{const ye=ne.some(ve=>ve.id===N);if(se){if(ye)return ne;const ve=O[N]||H||N;return[...ne,{id:N,label:ve}]}return ne.filter(ve=>ve.id!==N)})},sx:{p:.3,color:"#bbb"}}),e.jsx($,{variant:"body2",sx:{color:"#ddd"},children:H||N})]},N)),e.jsx(m,{sx:{display:"flex",gap:1,pt:.5},children:e.jsx(Z,{size:"small",variant:"outlined",onClick:()=>L(M),sx:{textTransform:"none",borderColor:"#555",color:"#bbb"},children:"Reset Default"})})]})}),e.jsxs(Et,{anchorEl:c,open:!!c,onClose:_t,PaperProps:{sx:{bgcolor:"#1e1e1e",color:"#fff",fontSize:"13px"}},children:[e.jsx(fe,{onClick:async()=>{_t(),await ft();const N=new Set(C);l&&!N.has(l.id)&&N.add(l.id);const H=new Map(r.map(se=>[se.id,se.hostname])),Y=Array.from(N).map(se=>H.get(se)).filter(Boolean);pt(Y),It(null),vt(!0)},children:"Add to Site"}),e.jsx(fe,{onClick:async()=>{_t(),await ft();const N=new Set(C);l&&!N.has(l.id)&&N.add(l.id);const H=new Map(r.map(se=>[se.id,se.hostname])),Y=Array.from(N).map(se=>H.get(se)).filter(Boolean);pt(Y),It(null),vt(!0)},children:"Move to Another Site"}),e.jsx(fe,{onClick:Yt,sx:{color:"#ff8a8a"},children:"Delete"})]}),e.jsx(Bi,{open:f,onCancel:()=>y(!1),onConfirm:ss}),k&&e.jsx(vo,{open:k,onClose:()=>v(!1),hostnames:r.filter(N=>C.has(N.id)).map(N=>N.hostname)}),bt&&e.jsx(Ls,{open:bt,onClose:()=>vt(!1),anchorReference:"anchorPosition",anchorPosition:{top:Math.max(Math.floor(window.innerHeight*.5),200),left:Math.max(Math.floor(window.innerWidth*.5),300)},PaperProps:{sx:{bgcolor:"#1e1e1e",color:"#fff",p:2,minWidth:360}},children:e.jsxs(m,{sx:{display:"flex",flexDirection:"column",gap:1},children:[e.jsxs($,{variant:"subtitle1",children:["Assign ",yt.length," device(s) to a site"]}),e.jsx(Ie,{select:!0,size:"small",label:"Select Site",value:Ut??"",onChange:N=>It(Number(N.target.value)),sx:{"& .MuiOutlinedInput-root":{"& fieldset":{borderColor:"#444"},"&:hover fieldset":{borderColor:"#666"}},label:{color:"#aaa"}},children:Pe.map(N=>e.jsx(fe,{value:N.id,children:N.name},N.id))}),e.jsxs(m,{sx:{display:"flex",justifyContent:"flex-end",gap:1},children:[e.jsx(Z,{variant:"outlined",size:"small",onClick:()=>vt(!1),sx:{textTransform:"none",borderColor:"#555",color:"#bbb"},children:"Cancel"}),e.jsx(Z,{variant:"outlined",size:"small",disabled:!Ut||yt.length===0,onClick:async()=>{try{await fetch("/api/sites/assign",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({site_id:Ut,hostnames:yt})})}catch{}vt(!1);try{const N=r.map(ne=>ne.hostname).filter(Boolean).map(encodeURIComponent).join(","),Y=await(await fetch(`/api/sites/device_map?hostnames=${N}`)).json(),se=(Y==null?void 0:Y.mapping)||{};setSiteMapping(se),i(ne=>ne.map(ye=>{var ve;return{...ye,site:((ve=se[ye.hostname])==null?void 0:ve.site_name)||"Not Configured"}}))}catch{}},sx:{textTransform:"none",borderColor:"#58a6ff",color:"#58a6ff"},children:"Assign"})]})]})}),e.jsx(So,{open:j,defaultType:R,onClose:()=>{B(!1),x(z??null)},onCreated:()=>{B(!1),x(z??null),We({refreshRepo:!0})}})]})}function el({device:n,onBack:t}){const[o,a]=s.useState(0),[d,u]=s.useState(n||{}),[r,i]=s.useState({}),[c,p]=s.useState({}),[l,h]=s.useState("name"),[f,y]=s.useState("asc"),[C,I]=s.useState(""),[k,v]=s.useState(""),[j,B]=s.useState(""),[R,x]=s.useState(""),[S,z]=s.useState(""),[E,U]=s.useState(!1),[X,ue]=s.useState(""),[Se,ce]=s.useState(""),[de,me]=s.useState([]),[w,W]=s.useState("ran_at"),[F,te]=s.useState("desc"),[ee,be]=s.useState(!1),[Re,Ae]=s.useState(""),[Le,Fe]=s.useState(""),[je,V]=s.useState("powershell"),[O,M]=s.useState(!1),[g,L]=s.useState(null),[we,T]=s.useState(!1),[G,ie]=s.useState({}),[Ce,Ee]=s.useState(()=>{if(n!=null&&n.status)return n.status;const _=n==null?void 0:n.lastSeen;return _&&Date.now()/1e3-_<=300?"Online":"Offline"});s.useEffect(()=>{ce("")},[S]),s.useEffect(()=>{j!=="ssh"&&(ue(""),ce(""))},[j]),s.useEffect(()=>{let _=!1;return(async()=>{const pe={},re=(N,H,Y="")=>{const se=typeof H=="string"?H.trim():"";if(!se)return;const ne=String(N||"").replace(/\\/g,"/").replace(/^\/+/,"").trim(),ye=new Set;if(ne&&(ye.add(ne),Y)){const ge=`${Y}/${ne}`.replace(/\/+/g,"/");ye.add(ge)}const ve=ne&&ne.split("/").pop()||"";if(ve){ye.add(ve);const ge=ve.lastIndexOf(".");ge>0&&ye.add(ve.slice(0,ge))}ye.forEach(ge=>{ge&&!pe[ge]&&(pe[ge]=se)})},ke=async(N,H="")=>{try{const Y=await fetch(`/api/assembly/list?island=${N}`);if(!Y.ok)return;const se=await Y.json();(Array.isArray(se.items)?se.items:[]).forEach(ye=>{if(!ye||typeof ye!="object")return;const ve=ye.rel_path||ye.path||ye.file_name||ye.playbook_path||"",ge=(ye.name||ye.tab_name||ye.display_name||ye.file_name||"").trim();re(ve,ge,H)})}catch{}};await ke("scripts","Scripts"),await ke("workflows","Workflows"),await ke("ansible","Ansible_Playbooks"),_||ie(pe)})(),()=>{_=!0}},[]);const Ne=(_,K=300)=>_&&Date.now()/1e3-_<=K?"Online":"Offline",Ke=_=>_==="Online"?"#00d18c":"#ff4f4f",at=s.useCallback((_,K)=>{const pe=String(K||"").replace(/\\/g,"/").trim(),re=pe&&pe.split("/").pop()||"",ke=re&&re.includes(".")?re.slice(0,re.lastIndexOf(".")):re;return G[pe]||(re?G[re]:"")||(ke?G[ke]:"")||_||re||K||""},[G]),ut=(_,K=120)=>{if(!_)return"unknown";if(Date.now()/1e3-_<=K)return"Currently Online";const re=new Date(_*1e3),ke=re.toLocaleDateString("en-US",{month:"2-digit",day:"2-digit",year:"numeric"}),N=re.toLocaleTimeString("en-US",{hour:"numeric",minute:"2-digit"});return`${ke} @ ${N}`};s.useEffect(()=>{var ke,N,H;n&&Ee(n.status||Ne(n.lastSeen));const _=(n==null?void 0:n.agent_guid)||(n==null?void 0:n.guid)||(n==null?void 0:n.agentGuid)||((ke=n==null?void 0:n.summary)==null?void 0:ke.agent_guid),K=(n==null?void 0:n.agentId)||((N=n==null?void 0:n.summary)==null?void 0:N.agent_id)||(n==null?void 0:n.id),pe=(n==null?void 0:n.hostname)||((H=n==null?void 0:n.summary)==null?void 0:H.hostname);if(!n||!_&&!pe)return;(async()=>{var Y,se,ne,ye,ve,ge;try{const Me=fetch("/api/agents").catch(()=>null);let Ve=null;if(_)try{Ve=await fetch(`/api/devices/${encodeURIComponent(_)}`)}catch{Ve=null}if((!Ve||!Ve.ok)&&pe)try{Ve=await fetch(`/api/device/details/${encodeURIComponent(pe)}`)}catch{Ve=null}if(!Ve||!Ve.ok)throw new Error(`Failed to load device record (${Ve?Ve.status:"no response"})`);const[it,J]=await Promise.all([Me==null?void 0:Me.then(qe=>qe?qe.json():{}).catch(()=>({})),Ve.json()]);it&&K&&it[K]&&u({id:K,...it[K]});const Ge={...(J!=null&&J.summary&&typeof J.summary=="object"?J.summary:((Y=J==null?void 0:J.details)==null?void 0:Y.summary)||{})||{}};J!=null&&J.description&&(Ge.description=J.description);const He=(Ge.connection_type||Ge.remote_type||"").toLowerCase(),us=Ge.connection_endpoint||Ge.connection_address||(J==null?void 0:J.connection_endpoint)||"";B(He),x(us),z(us),ue(""),ce("");const fs={summary:Ge,memory:Array.isArray(J==null?void 0:J.memory)?J.memory:Array.isArray((se=J==null?void 0:J.details)==null?void 0:se.memory)?J.details.memory:[],network:Array.isArray(J==null?void 0:J.network)?J.network:Array.isArray((ne=J==null?void 0:J.details)==null?void 0:ne.network)?J.details.network:[],software:Array.isArray(J==null?void 0:J.software)?J.software:Array.isArray((ye=J==null?void 0:J.details)==null?void 0:ye.software)?J.details.software:[],storage:Array.isArray(J==null?void 0:J.storage)?J.storage:Array.isArray((ve=J==null?void 0:J.details)==null?void 0:ve.storage)?J.details.storage:[],cpu:(J==null?void 0:J.cpu)||((ge=J==null?void 0:J.details)==null?void 0:ge.cpu)||{}};i(fs);const zt=qe=>{if(!qe||Number.isNaN(qe.getTime()))return"";const xt=ns=>String(ns).padStart(2,"0");return`${qe.getUTCFullYear()}-${xt(qe.getUTCMonth()+1)}-${xt(qe.getUTCDate())} ${xt(qe.getUTCHours())}:${xt(qe.getUTCMinutes())}:${xt(qe.getUTCSeconds())}`};let Ft=Ge.created||"";Ft||(J!=null&&J.created_at&&Number(J.created_at)?Ft=zt(new Date(Number(J.created_at)*1e3)):J!=null&&J.created_at_iso&&(Ft=zt(new Date(J.created_at_iso))));const kt={hostname:(J==null?void 0:J.hostname)||Ge.hostname||pe||"",lastUser:(J==null?void 0:J.last_user)||Ge.last_user||"",deviceType:(J==null?void 0:J.device_type)||Ge.device_type||"",created:Ft,createdAtIso:(J==null?void 0:J.created_at_iso)||"",lastSeen:(J==null?void 0:J.last_seen)||Ge.last_seen||0,lastReboot:(J==null?void 0:J.last_reboot)||Ge.last_reboot||"",operatingSystem:(J==null?void 0:J.operating_system)||Ge.operating_system||Ge.agent_operating_system||"",agentId:(J==null?void 0:J.agent_id)||Ge.agent_id||K||"",agentGuid:(J==null?void 0:J.agent_guid)||Ge.agent_guid||_||"",agentHash:(J==null?void 0:J.agent_hash)||Ge.agent_hash||"",internalIp:(J==null?void 0:J.internal_ip)||Ge.internal_ip||"",externalIp:(J==null?void 0:J.external_ip)||Ge.external_ip||"",siteId:J==null?void 0:J.site_id,siteName:(J==null?void 0:J.site_name)||"",siteDescription:(J==null?void 0:J.site_description)||"",status:(J==null?void 0:J.status)||"",connectionType:He,connectionEndpoint:us};p(kt),v(Ge.description||(J==null?void 0:J.description)||""),u(qe=>({...qe||{},id:K||(qe==null?void 0:qe.id),hostname:kt.hostname||(qe==null?void 0:qe.hostname),agent_hash:kt.agentHash||(qe==null?void 0:qe.agent_hash),agent_operating_system:kt.operatingSystem||(qe==null?void 0:qe.agent_operating_system),device_type:kt.deviceType||(qe==null?void 0:qe.device_type),last_seen:kt.lastSeen||(qe==null?void 0:qe.last_seen)})),kt.status?Ee(kt.status):kt.lastSeen&&Ee(Ne(kt.lastSeen))}catch(Me){console.warn("Failed to load device info",Me),p({})}})()},[n]);const Pe=s.useMemo(()=>((c==null?void 0:c.hostname)||(d==null?void 0:d.hostname)||(n==null?void 0:n.hostname)||"").trim(),[c==null?void 0:c.hostname,d==null?void 0:d.hostname,n==null?void 0:n.hostname]),gt=s.useCallback(async()=>{var pe;if(j!=="ssh")return;const _=Pe;if(!_)return;const K=S.trim();if(!K){ce("Address is required.");return}if(K===R.trim()){ue("No changes to save.");return}U(!0),ce(""),ue("");try{const re=await fetch(`/api/ssh_devices/${encodeURIComponent(_)}`,{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify({address:K})}),ke=await re.json().catch(()=>({}));if(!re.ok)throw new Error((ke==null?void 0:ke.error)||`HTTP ${re.status}`);const N=((pe=ke==null?void 0:ke.device)==null?void 0:pe.connection_endpoint)||K;x(N),z(N),p(H=>({...H||{},connectionEndpoint:N})),ue("SSH endpoint updated."),setTimeout(()=>ue(""),3e3)}catch(re){ce(String(re.message||re))}finally{U(!1)}},[j,S,R,Pe]),bt=s.useCallback(async()=>{if(Pe)try{const _=await fetch(`/api/device/activity/${encodeURIComponent(Pe)}`);if(!_.ok)throw new Error(`HTTP ${_.status}`);const K=await _.json();me(K.history||[])}catch(_){console.warn("Failed to load activity history",_),me([])}},[Pe]);s.useEffect(()=>{bt()},[bt]),s.useEffect(()=>{const _=typeof window<"u"?window.BorealisSocket:null;if(!_||!Pe)return;let K=null;const pe=Pe.toLowerCase(),re=(N=200)=>{K&&clearTimeout(K),K=setTimeout(()=>{K=null,bt()},N)},ke=(N={})=>{const H=String((N==null?void 0:N.hostname)||"").trim().toLowerCase();if(H&&H===pe){const Y=(N==null?void 0:N.change)==="updated"?150:0;re(Y)}};return _.on("device_activity_changed",ke),()=>{K&&clearTimeout(K),_.off("device_activity_changed",ke)}},[Pe,bt]);const vt=async()=>{if(Pe)try{const _=await fetch(`/api/device/activity/${encodeURIComponent(Pe)}`,{method:"DELETE"});if(!_.ok)throw new Error(`HTTP ${_.status}`);me([])}catch(_){console.warn("Failed to clear activity history",_)}},Ut=async()=>{var K;const _=c.hostname||((K=r.summary)==null?void 0:K.hostname);if(_)try{await fetch(`/api/device/description/${_}`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({description:k})}),i(pe=>({...pe,summary:{...pe.summary||{},description:k}})),p(pe=>({...pe||{},hostname:_}))}catch(pe){console.warn("Failed to save description",pe)}},It=_=>{if(!_)return"unknown";try{const[K,pe]=_.split(" "),[re,ke,N]=K.split("-").map(Number);let[H,Y,se]=pe.split(":").map(Number);const ne=H>=12?"PM":"AM";return H=H%12||12,`${ke.toString().padStart(2,"0")}/${N.toString().padStart(2,"0")}/${re} @ ${H}:${Y.toString().padStart(2,"0")} ${ne}`}catch{return _}},yt=_=>_?_.replace(/-/g,":").toUpperCase():"unknown",pt=_=>{if(_==null||_==="unknown")return"unknown";let K=Number(_);const pe=["B","KB","MB","GB","TB"];let re=0;for(;K>=1024&&re<pe.length-1;)K/=1024,re++;return`${K.toFixed(1)} ${pe[re]}`},St=_=>{const K=Number(_||0);if(!K)return"unknown";const pe=new Date(K*1e3),re=String(pe.getMonth()+1).padStart(2,"0"),ke=String(pe.getDate()).padStart(2,"0"),N=pe.getFullYear();let H=pe.getHours();const Y=H>=12?"PM":"AM";H=H%12||12;const se=String(pe.getMinutes()).padStart(2,"0");return`${re}/${ke}/${N} @ ${H}:${se} ${Y}`},ct=_=>{l===_?y(f==="asc"?"desc":"asc"):(h(_),y("asc"))},oe=s.useMemo(()=>{const K=(r.software||[]).filter(re=>re.name.toLowerCase().includes(C.toLowerCase())),pe=f==="asc"?1:-1;return[...K].sort((re,ke)=>{const N=re[l]||"",H=ke[l]||"";return String(N).localeCompare(String(H))*pe})},[r.software,C,l,f]),_e=r.summary||{},$e=s.useMemo(()=>{const _=r.cpu||_e.cpu||{},K=_.logical_cores||_.cores||_.physical_cores;let pe=_.base_clock_ghz;if(!pe&&typeof(_e.processor||"")=="string"){const H=String(_e.processor).match(/\(([^)]*?)ghz\)/i);if(H&&H[1]){const Y=parseFloat(H[1]);Number.isNaN(Y)||(pe=Y)}}const re=(_.name||"").trim(),N=(_e.processor||"").trim()||[re,pe?`(${Number(pe).toFixed(1)}GHz)`:null,K?`@ ${K} Cores`:null].filter(Boolean).join(" ");return{cores:K,ghz:pe,name:re,display:N}},[_e]),Xe=[{label:"Hostname",value:c.hostname||_e.hostname||d.hostname||(n==null?void 0:n.hostname)||"unknown"},{label:"Last User",value:e.jsxs(m,{sx:{display:"flex",alignItems:"center",gap:1},children:[e.jsx(m,{component:"span",sx:{display:"inline-block",width:10,height:10,borderRadius:10,bgcolor:d!=null&&d.collector_active?"#00d18c":"#ff4f4f"}}),e.jsx("span",{children:c.lastUser||_e.last_user||"unknown"})]})},{label:"Device Type",value:c.deviceType||_e.device_type||"unknown"},{label:"Created",value:c.created?It(c.created):_e.created?It(_e.created):"unknown"},{label:"Last Seen",value:ut(c.lastSeen||d.last_seen||(n==null?void 0:n.lastSeen))},{label:"Last Reboot",value:c.lastReboot?It(c.lastReboot):_e.last_reboot?It(_e.last_reboot):"unknown"},{label:"Operating System",value:c.operatingSystem||_e.operating_system||d.agent_operating_system||"unknown"},{label:"Agent ID",value:c.agentId||_e.agent_id||"unknown"},{label:"Agent GUID",value:c.agentGuid||_e.agent_guid||"unknown"},{label:"Agent Hash",value:c.agentHash||_e.agent_hash||"unknown"}],We=({icon:_,title:K,main:pe,sub:re,color:ke})=>{const N=ke||"#232323",H=ne=>{const ye=String(ne||"").replace("#",""),ve=parseInt(ye.length===3?ye.split("").map(ge=>ge+ge).join(""):ye,16);return{r:ve>>16&255,g:ve>>8&255,b:ve&255}},Y=(ne,ye=1)=>{try{const{r:ve,g:ge,b:Me}=H(ne);return`rgba(${ve}, ${ge}, ${Me}, ${ye})`}catch{return`rgba(88,166,255, ${ye})`}},se=(ne,ye=.5,ve=1)=>{try{const{r:ge,g:Me,b:Ve}=H(ne),it=He=>Math.round(He+(255-He)*ye),J=it(ge),Te=it(Me),Ge=it(Ve);return`rgba(${J}, ${Te}, ${Ge}, ${ve})`}catch{return Y("#58a6ff",ve)}};return e.jsxs(Qe,{elevation:0,sx:{px:2,py:1.5,borderRadius:2,position:"relative",color:"#fff",minWidth:260,border:"1px solid #2f2f2f",background:`linear-gradient(90deg, rgba(88,166,255,0.12) 0%, rgba(88,166,255,0.06) 55%, rgba(88,166,255,0) 100%), ${N}`,boxShadow:`inset 0 0 0 1px ${se(N,.35,.6)}`},children:[e.jsxs(m,{sx:{display:"flex",alignItems:"center",gap:1,mb:1},children:[_,e.jsx($,{variant:"caption",sx:{opacity:.95,fontWeight:700},children:K})]}),e.jsx($,{variant:"h6",sx:{lineHeight:1.2,mb:1},children:pe}),e.jsx(m,{sx:{flexGrow:1,minHeight:12}}),e.jsx(m,{sx:{minHeight:8}}),re?e.jsx($,{variant:"body2",sx:{opacity:.85},children:re}):null]})},Je=({title:_,children:K,sx:pe})=>e.jsxs(Qe,{elevation:0,sx:{p:1.5,borderRadius:2,bgcolor:"#1c1c1c",border:"1px solid #2a2a2a",mb:1.5,...pe||{}},children:[e.jsx($,{variant:"caption",sx:{color:"#58a6ff",fontWeight:400,fontSize:"14px",letterSpacing:.2,display:"block",mb:1},children:_}),K]}),ft=()=>{const _=($e.name||_e.processor||""||"").split(`
|
||
`)[0]||"Unknown CPU",K=$e.ghz||$e.cores?e.jsxs("span",{children:[$e.ghz?`${Number($e.ghz).toFixed(2)}GHz `:"",$e.cores?e.jsxs("span",{style:{opacity:.75},children:["(",$e.cores,"-Cores)"]}):null]}):"";let pe=_e.total_ram;if(!pe&&Array.isArray(r.memory))try{pe=r.memory.reduce((ge,Me)=>ge+(Number(Me.capacity||0)||0),0)}catch{}const re=pe?`${pt(pe)}`:"Unknown";let ke="";try{const ge=(r.memory||[]).map(Me=>parseInt(String(Me.speed||"").replace(/[^0-9]/g,""),10)).filter(Me=>!Number.isNaN(Me)&&Me>0);ge.length&&(ke=`Speed: ${Math.max(...ge)} MT/s`)}catch{}let N=null;Array.isArray(r.storage)&&(N=r.storage.find(ge=>String(ge.drive||"").toUpperCase().startsWith("C:"))||r.storage[0]||null);const H=N&&N.total!=null?`${pt(N.total)}`:"Unknown",Y=N&&N.used!=null&&N.total!=null?`${pt(N.used)} of ${pt(N.total)} used`:N&&N.free!=null&&N.total!=null?`${pt(N.total-N.free)} of ${pt(N.total)} used`:"",se=(_e.internal_ip||"").trim();let ne=null;Array.isArray(r.network)&&(ne=r.network.find(ge=>(ge.ips||[]).includes(se))||r.network[0]||null);function ye(ge){const Me=String(ge||"").trim();if(!Me)return"unknown";const Ve=Me.toLowerCase();if(Ve.includes("gbps")||Ve.includes("mbps"))return Me;const it=Ve.match(/(\d+\.?\d*)\s*([gmk]?)(bps)/);if(!it)return Me;let J=parseFloat(it[1]);const Te=it[2];return Te==="g"?`${J} Gbps`:Te==="m"?`${J} Mbps`:Te==="k"?`${(J/1e3).toFixed(1)} Mbps`:J>=1e9?`${(J/1e9).toFixed(1)} Gbps`:J>=1e6?`${(J/1e6).toFixed(0)} Mbps`:Me}const ve=ne?ye(ne.link_speed||ne.speed):"Unknown";return e.jsxs(m,{children:[e.jsxs(m,{sx:{display:"grid",gridTemplateColumns:"repeat( auto-fit, minmax(260px, 1fr) )",gap:1.5,mb:2},children:[e.jsx(We,{icon:e.jsx(lr,{sx:{fontSize:32,opacity:.95}}),title:"Processor",main:_,sub:K,color:"#132332"}),e.jsx(We,{icon:e.jsx(cr,{sx:{fontSize:32,opacity:.95}}),title:"Installed RAM",main:re,sub:ke||" ",color:"#291a2e"}),e.jsx(We,{icon:e.jsx(dr,{sx:{fontSize:32,opacity:.95}}),title:"Storage",main:H,sub:Y||" ",color:"#142616"}),e.jsx(We,{icon:e.jsx(ur,{sx:{fontSize:32,opacity:.95}}),title:"Network",main:ve,sub:ne&&ne.adapter?ne.adapter:" ",color:"#2b1a18"})]}),e.jsxs(m,{sx:{display:"grid",gridTemplateColumns:{xs:"1fr",md:"1.2fr 1fr 1fr"},gap:2},children:[e.jsx(Je,{title:"Device Summary",children:e.jsx(m,{children:e.jsx(Rt,{size:"small",children:e.jsxs(Nt,{children:[e.jsxs(Ue,{children:[e.jsx(Q,{sx:{fontWeight:500},children:"Description"}),e.jsx(Q,{children:e.jsx(Ie,{size:"small",value:k,onChange:ge=>v(ge.target.value),onBlur:Ut,placeholder:"Enter description",sx:{input:{color:"#fff"},"& .MuiOutlinedInput-root":{"& fieldset":{borderColor:"#555"},"&:hover fieldset":{borderColor:"#888"}}}})})]}),j==="ssh"&&e.jsxs(Ue,{children:[e.jsx(Q,{sx:{fontWeight:500},children:"SSH Endpoint"}),e.jsxs(Q,{children:[e.jsxs(m,{sx:{display:"flex",alignItems:"center",gap:1.5},children:[e.jsx(Ie,{size:"small",value:S,onChange:ge=>z(ge.target.value),placeholder:"user@host or host",sx:{maxWidth:300,input:{color:"#fff"},"& .MuiOutlinedInput-root":{"& fieldset":{borderColor:"#555"},"&:hover fieldset":{borderColor:"#888"}}}}),e.jsx(Z,{size:"small",variant:"outlined",sx:{color:"#58a6ff",borderColor:"#58a6ff"},onClick:gt,disabled:E||S.trim()===R.trim(),children:E?"Saving...":"Save"})]}),X&&e.jsx($,{variant:"caption",sx:{color:"#7db7ff"},children:X}),Se&&e.jsx($,{variant:"caption",sx:{color:"#ff8080"},children:Se})]})]}),Xe.map(ge=>e.jsxs(Ue,{children:[e.jsx(Q,{sx:{fontWeight:500},children:ge.label}),e.jsx(Q,{children:ge.value})]},ge.label))]})})})}),e.jsx(Je,{title:"Storage",children:Wt()}),e.jsxs(m,{children:[e.jsx(Je,{title:"Memory",children:Ct()}),e.jsx(Je,{title:"Network",children:lt()})]})]})]})},ht=_=>e.jsx(m,{children:e.jsxs(Rt,{size:"small",children:[e.jsx(Bt,{children:e.jsx(Ue,{children:_.map(K=>e.jsx(Q,{children:K},K))})}),e.jsx(Nt,{children:e.jsx(Ue,{children:e.jsx(Q,{colSpan:_.length,sx:{color:"#888"},children:"No data available."})})})]})}),Jt=()=>oe.length?e.jsxs(m,{sx:{width:"100%"},children:[e.jsx(m,{sx:{mb:1,width:"100%"},children:e.jsx(Ie,{size:"small",placeholder:"Search software...",value:C,onChange:_=>I(_.target.value),sx:{input:{color:"#fff"},"& .MuiOutlinedInput-root":{"& fieldset":{borderColor:"#555"},"&:hover fieldset":{borderColor:"#888"}}}})}),e.jsx(m,{sx:{width:"100%",maxHeight:"calc(100vh - 320px)",overflow:"auto",pr:1},children:e.jsxs(Rt,{size:"small",sx:{width:"100%"},children:[e.jsx(Bt,{children:e.jsxs(Ue,{children:[e.jsx(Q,{sortDirection:l==="name"?f:!1,children:e.jsx(Tt,{active:l==="name",direction:l==="name"?f:"asc",onClick:()=>ct("name"),children:"Software Name"})}),e.jsx(Q,{sortDirection:l==="version"?f:!1,children:e.jsx(Tt,{active:l==="version",direction:l==="version"?f:"asc",onClick:()=>ct("version"),children:"Version"})}),e.jsx(Q,{children:"Action"})]})}),e.jsx(Nt,{children:oe.map((_,K)=>e.jsxs(Ue,{children:[e.jsx(Q,{children:_.name}),e.jsx(Q,{children:_.version}),e.jsx(Q,{})]},`${_.name}-${K}`))})]})})]}):ht(["Software Name","Version","Action"]),Ct=()=>{const _=r.memory||[];return _.length?e.jsx(m,{children:e.jsxs(Rt,{size:"small",children:[e.jsx(Bt,{children:e.jsxs(Ue,{children:[e.jsx(Q,{children:"Slot"}),e.jsx(Q,{children:"Speed"}),e.jsx(Q,{children:"Serial Number"}),e.jsx(Q,{children:"Capacity"})]})}),e.jsx(Nt,{children:_.map((K,pe)=>e.jsxs(Ue,{children:[e.jsx(Q,{children:K.slot}),e.jsx(Q,{children:K.speed}),e.jsx(Q,{children:K.serial}),e.jsx(Q,{children:pt(K.capacity)})]},`${K.slot}-${pe}`))})]})}):ht(["Slot","Speed","Serial Number","Capacity"])},Wt=()=>{const _=re=>{if(re==null)return;if(typeof re=="number")return Number.isNaN(re)?void 0:re;const ke=parseFloat(String(re).replace(/[^0-9.]+/g,""));return Number.isNaN(ke)?void 0:ke},K=(r.storage||[]).map(re=>{const ke=_(re.total);let N=_(re.usage),H=_(re.used),Y=_(re.free),se;return N!==void 0&&(N<=1&&(N*=100),se=100-N),H===void 0&&ke!==void 0&&N!==void 0&&(H=N/100*ke),Y===void 0&&ke!==void 0&&H!==void 0&&(Y=ke-H),se===void 0&&ke!==void 0&&Y!==void 0&&(se=Y/ke*100),N===void 0&&se!==void 0&&(N=100-se),{drive:re.drive,disk_type:re.disk_type,used:H,freePct:se,freeBytes:Y,total:ke,usage:N}});if(!K.length)return ht(["Drive","Type","Capacity"]);const pe=re=>re!==void 0&&!Number.isNaN(re)?`${re.toFixed(0)}%`:"unknown";return e.jsx(m,{children:K.map((re,ke)=>{const N=re.usage??(re.total?(re.used||0)/re.total*100:0),H=re.used,Y=re.freeBytes,se=re.total;return e.jsxs(m,{sx:{p:1,borderBottom:"1px solid #2a2a2a","&:last-child":{borderBottom:"none"}},children:[e.jsxs(m,{sx:{display:"flex",alignItems:"center",justifyContent:"space-between",mb:1},children:[e.jsxs(m,{sx:{display:"flex",alignItems:"center",gap:1.2},children:[e.jsx(m,{sx:{width:8,height:8,bgcolor:"#58a6ff",borderRadius:.5}}),e.jsx($,{variant:"body2",sx:{fontWeight:600},children:`Drive ${String(re.drive||"").replace("\\","")}`}),e.jsx($,{variant:"caption",sx:{opacity:.7},children:re.disk_type||"Fixed Disk"})]}),e.jsx($,{variant:"body2",sx:{opacity:.9},children:se!==void 0?pt(se):"unknown"})]}),e.jsx(m,{sx:{position:"relative",height:8,borderRadius:1,bgcolor:"#2b2b2b",background:"linear-gradient(180deg, #323232 0%, #2a2a2a 100%)",boxShadow:"inset 0 0 0 1px #3a3a3a, inset 0 1px 0 rgba(255,255,255,0.06)"},children:e.jsx(m,{sx:{position:"absolute",left:0,top:0,bottom:0,width:`${Math.max(0,Math.min(100,N||0)).toFixed(0)}%`,borderRadius:1,background:"linear-gradient(90deg, rgba(0,209,140,0.95) 0%, rgba(0,209,140,0.80) 45%, rgba(0,209,140,0.70) 100%)",boxShadow:"inset 0 0 0 1px rgba(255,255,255,0.15), 0 0 6px rgba(0,209,140,0.25)"}})}),e.jsxs(m,{sx:{display:"flex",justifyContent:"space-between",mt:.75},children:[e.jsx($,{variant:"caption",sx:{opacity:.85},children:H!==void 0?`${pt(H)} - ${pe(N)} in use`:"unknown"}),e.jsx($,{variant:"caption",sx:{opacity:.85},children:Y!==void 0&&se!==void 0?`${pt(Y)} - ${pe(100-(N||0))} remaining`:""})]})]},`${re.drive}-${ke}`)})})},lt=()=>{const _=r.network||[],K=c.internalIp||_e.internal_ip||"unknown",pe=c.externalIp||_e.external_ip||"unknown",re=e.jsxs(m,{sx:{mb:_.length?1.5:1},children:[e.jsxs($,{variant:"body2",sx:{display:"block",opacity:.9},children:["Internal IP: ",K]}),e.jsxs($,{variant:"body2",sx:{display:"block",opacity:.9},children:["External IP: ",pe]})]});return _.length?e.jsxs(m,{children:[re,e.jsxs(Rt,{size:"small",children:[e.jsx(Bt,{children:e.jsxs(Ue,{children:[e.jsx(Q,{children:"Adapter"}),e.jsx(Q,{children:"IP Address"}),e.jsx(Q,{children:"MAC Address"})]})}),e.jsx(Nt,{children:_.map((ke,N)=>e.jsxs(Ue,{children:[e.jsx(Q,{children:ke.adapter}),e.jsx(Q,{children:(ke.ips||[]).join(", ")}),e.jsx(Q,{children:yt(ke.mac)})]},`${ke.adapter}-${N}`))})]})]}):e.jsxs(m,{children:[re,ht(["Adapter","IP Address","MAC Address"])]})},Dt=_=>{const K=String(_||"").toLowerCase();return K==="running"?"#58a6ff":K==="success"?"#00d18c":K==="failed"?"#ff4f4f":"#666"},Ot=(_,K)=>{try{return qt.highlight(_??"",qt.languages[K]||qt.languages.markup,K)}catch{return String(_||"")}},_t=s.useCallback(async(_,K)=>{if(!(!_||!_.id))try{const pe=await fetch(`/api/device/activity/job/${_.id}`);if(!pe.ok)throw new Error(`HTTP ${pe.status}`);const re=await pe.json(),ke=(re.script_path||"").toLowerCase().endsWith(".ps1")?"powershell":(re.script_path||"").toLowerCase().endsWith(".bat")?"batch":(re.script_path||"").toLowerCase().endsWith(".sh")?"bash":(re.script_path||"").toLowerCase().endsWith(".yml")?"yaml":"powershell";V(ke);const N=at(re.script_name,re.script_path);Ae(`${K==="stderr"?"StdErr":"StdOut"} - ${N}`),Fe(K==="stderr"?re.stderr||"":re.stdout||""),be(!0)}catch(pe){console.warn("Failed to load output",pe)}},[at]),Yt=_=>{w===_?te(F==="asc"?"desc":"asc"):(W(_),te("asc"))},ss=s.useMemo(()=>(de||[]).map(_=>({..._,script_display_name:at(_.script_name,_.script_path)})),[de,at]),A=s.useMemo(()=>{const _=F==="asc"?1:-1,K=w==="script_name"?"script_display_name":w;return[...ss].sort((pe,re)=>{const ke=pe[K],N=re[K];return K==="ran_at"?((ke||0)-(N||0))*_:String(ke??"").localeCompare(String(N??""))*_})},[ss,w,F]),q=()=>e.jsx(m,{children:e.jsxs(Rt,{size:"small",children:[e.jsx(Bt,{children:e.jsxs(Ue,{children:[e.jsx(Q,{children:"Assembly"}),e.jsx(Q,{sortDirection:w==="script_name"?F:!1,children:e.jsx(Tt,{active:w==="script_name",direction:w==="script_name"?F:"asc",onClick:()=>Yt("script_name"),children:"Task"})}),e.jsx(Q,{sortDirection:w==="ran_at"?F:!1,children:e.jsx(Tt,{active:w==="ran_at",direction:w==="ran_at"?F:"asc",onClick:()=>Yt("ran_at"),children:"Ran On"})}),e.jsx(Q,{sortDirection:w==="status"?F:!1,children:e.jsx(Tt,{active:w==="status",direction:w==="status"?F:"asc",onClick:()=>Yt("status"),children:"Job Status"})}),e.jsx(Q,{children:"StdOut / StdErr"})]})}),e.jsxs(Nt,{children:[A.map(_=>e.jsxs(Ue,{children:[e.jsx(Q,{children:(_.script_type||"").toLowerCase()==="ansible"?"Ansible Playbook":"Script"}),e.jsx(Q,{children:_.script_display_name||_.script_name}),e.jsx(Q,{children:St(_.ran_at)}),e.jsx(Q,{children:e.jsx(m,{sx:{display:"inline-block",px:1.2,py:.25,borderRadius:999,bgcolor:Dt(_.status),color:"#fff",fontWeight:600,fontSize:"12px"},children:_.status})}),e.jsx(Q,{children:e.jsxs(m,{sx:{display:"flex",gap:1},children:[String(_.script_type||"").toLowerCase()==="ansible"&&String(_.status||"")==="Running"?e.jsx(Z,{size:"small",sx:{color:"#ff6666",textTransform:"none",minWidth:0,p:0},onClick:async()=>{try{const K=await fetch(`/api/ansible/run_for_activity/${encodeURIComponent(_.id)}`),pe=await K.json();if(!K.ok)throw new Error(pe.error||`HTTP ${K.status}`);const re=pe.run_id;if(re)try{const ke=window.BorealisSocket;ke&&ke.emit("ansible_playbook_cancel",{run_id:re})}catch{}else alert("Unable to locate run id for this playbook run.")}catch(K){alert(String(K.message||K))}},children:"Cancel"}):null,_.has_stdout?e.jsx(Z,{size:"small",onClick:()=>_t(_,"stdout"),sx:{color:"#58a6ff",textTransform:"none",minWidth:0,p:0},children:"StdOut"}):null,_.has_stderr?e.jsx(Z,{size:"small",onClick:()=>_t(_,"stderr"),sx:{color:"#ff4f4f",textTransform:"none",minWidth:0,p:0},children:"StdErr"}):null]})})]},_.id)),A.length===0&&e.jsx(Ue,{children:e.jsx(Q,{colSpan:5,sx:{color:"#888"},children:"No activity yet."})})]})]})}),le=[{label:"Summary",content:ft()},{label:"Installed Software",content:Jt()},{label:"Activity History",content:q()}],he=Ce||Ne(d.last_seen||(n==null?void 0:n.lastSeen));return e.jsxs(Qe,{sx:{m:2,p:2,bgcolor:"#1e1e1e"},elevation:2,children:[e.jsxs(m,{sx:{mb:2,display:"flex",alignItems:"center",justifyContent:"space-between"},children:[e.jsxs(m,{sx:{display:"flex",alignItems:"center"},children:[t&&e.jsx(Z,{variant:"outlined",size:"small",onClick:t,sx:{mr:2},children:"Back"}),e.jsxs($,{variant:"h6",sx:{color:"#58a6ff",display:"flex",alignItems:"center"},children:[e.jsx("span",{style:{display:"inline-block",width:10,height:10,borderRadius:10,background:Ke(he),marginRight:8}}),d.hostname||"Device Details"]})]}),e.jsxs(m,{children:[e.jsx(nt,{size:"small",disabled:!(d!=null&&d.hostname||n!=null&&n.hostname),onClick:_=>L(_.currentTarget),sx:{color:d!=null&&d.hostname||n!=null&&n.hostname?"#58a6ff":"#666",borderColor:d!=null&&d.hostname||n!=null&&n.hostname?"#58a6ff":"#333",border:"1px solid",borderRadius:1,width:32,height:32},children:e.jsx(ir,{fontSize:"small"})}),e.jsxs(Et,{anchorEl:g,open:!!g,onClose:()=>L(null),children:[e.jsx(fe,{onClick:()=>{L(null),M(!0)},children:"Quick Job"}),e.jsx(fe,{onClick:()=>{L(null),T(!0)},children:"Clear Device Activity"})]})]})]}),e.jsx(Us,{value:o,onChange:(_,K)=>a(K),sx:{borderBottom:1,borderColor:"#333"},children:le.map(_=>e.jsx(ps,{label:_.label},_.label))}),e.jsx(m,{sx:{mt:2},children:le[o].content}),e.jsxs(Ze,{open:ee,onClose:()=>be(!1),fullWidth:!0,maxWidth:"md",PaperProps:{sx:{bgcolor:"#121212",color:"#fff"}},children:[e.jsx(et,{children:Re}),e.jsx(rt,{children:e.jsx(m,{sx:{border:"1px solid #333",borderRadius:1,bgcolor:"#1e1e1e",maxHeight:500,overflow:"auto"},children:e.jsx(En,{value:Le,onValueChange:()=>{},highlight:_=>Ot(_,je),padding:12,style:{fontFamily:'ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace',fontSize:12,color:"#e6edf3",minHeight:200},textareaProps:{readOnly:!0}})})}),e.jsx(tt,{children:e.jsx(Z,{onClick:()=>be(!1),sx:{color:"#58a6ff"},children:"Close"})})]}),e.jsx(Ti,{open:we,onCancel:()=>T(!1),onConfirm:()=>{vt(),T(!1)}}),O&&e.jsx(vo,{open:O,onClose:()=>M(!1),hostnames:[(d==null?void 0:d.hostname)||(n==null?void 0:n.hostname)].filter(Boolean)})]})}function tl(n){return e.jsx(_o,{...n,filterMode:"agent",title:"Agent Devices",showAddButton:!1})}const sl={"& th, & td":{color:"#ddd",borderColor:"#2a2a2a",fontSize:13,py:.75},"& th":{fontWeight:600},"& th .MuiTableSortLabel-root":{color:"#ddd"},"& th .MuiTableSortLabel-root.Mui-active":{color:"#ddd"}},gn={hostname:"",address:"",description:"",operating_system:""};function ko({type:n="ssh"}){const t=n==="winrm"?"WinRM":"SSH",o=n==="winrm"?"/api/winrm_devices":"/api/ssh_devices",a=`${t} Devices`,d=`Add ${t} Device`,u=`${t} Address`,r=`Loading ${t} devices…`,i=`No ${t} devices have been added yet.`,c=n==="winrm"?"Manage remote endpoints reachable via WinRM for playbook execution.":"Manage remote endpoints reachable via SSH for playbook execution.",p=`Edit ${t} Device`,l=`New ${t} Device`,[h,f]=s.useState([]),[y,C]=s.useState("hostname"),[I,k]=s.useState("asc"),[v,j]=s.useState(!0),[B,R]=s.useState(""),[x,S]=s.useState(!1),[z,E]=s.useState(gn),[U,X]=s.useState(""),[ue,Se]=s.useState(!1),[ce,de]=s.useState(null),[me,w]=s.useState(null),[W,F]=s.useState(!1),[te,ee]=s.useState(!1),be=!!ce,Re=s.useCallback(async()=>{j(!0),R("");try{const g=await fetch(o);if(!g.ok){const T=await g.json().catch(()=>({}));throw new Error((T==null?void 0:T.error)||`HTTP ${g.status}`)}const L=await g.json(),we=Array.isArray(L==null?void 0:L.devices)?L.devices:[];f(we)}catch(g){R(String(g.message||g)),f([])}finally{j(!1)}},[o]);s.useEffect(()=>{Re()},[Re]);const Ae=s.useMemo(()=>{const g=[...h];return g.sort((L,we)=>{const T=Ce=>{switch(y){case"created_at":return Number(Ce.created_at||0);case"address":return(Ce.connection_endpoint||"").toLowerCase();case"description":return(Ce.description||"").toLowerCase();default:return(Ce.hostname||"").toLowerCase()}},G=T(L),ie=T(we);return G<ie?I==="asc"?-1:1:G>ie?I==="asc"?1:-1:0}),g},[h,I,y]),Le=g=>()=>{y===g?k(L=>L==="asc"?"desc":"asc"):(C(g),k("asc"))},Fe=()=>{ee(!0),X("")},je=g=>{var L;de(g),E({hostname:g.hostname||"",address:g.connection_endpoint||"",description:g.description||"",operating_system:((L=g.summary)==null?void 0:L.operating_system)||""}),S(!0),X("")},V=()=>{ue||(S(!1),E(gn),de(null),X(""))},O=async()=>{if(ue)return;const g={hostname:z.hostname.trim(),address:z.address.trim(),description:z.description.trim(),operating_system:z.operating_system.trim()};if(!g.hostname){X("Hostname is required.");return}if(!g.address){X("Address is required.");return}Se(!0),X("");try{const L=be?`${o}/${encodeURIComponent(ce.hostname)}`:o,we=await fetch(L,{method:be?"PUT":"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(g)}),T=await we.json().catch(()=>({}));if(!we.ok)throw new Error((T==null?void 0:T.error)||`HTTP ${we.status}`);S(!1),E(gn),de(null),X(""),f(G=>{const ie=[...G];if(T!=null&&T.device){const Ce=ie.findIndex(Ee=>Ee.hostname===T.device.hostname);return Ce>=0?ie[Ce]=T.device:ie.push(T.device),ie}return G}),Re()}catch(L){X(String(L.message||L))}finally{Se(!1)}},M=async()=>{if(me){F(!0);try{const g=await fetch(`${o}/${encodeURIComponent(me.hostname)}`,{method:"DELETE"}),L=await g.json().catch(()=>({}));if(!g.ok)throw new Error((L==null?void 0:L.error)||`HTTP ${g.status}`);f(we=>we.filter(T=>T.hostname!==me.hostname)),w(null)}catch(g){R(String(g.message||g))}finally{F(!1)}}};return e.jsxs(Qe,{sx:{m:2,p:0,bgcolor:"#1e1e1e"},elevation:2,children:[e.jsxs(m,{sx:{display:"flex",alignItems:"center",justifyContent:"space-between",p:2,borderBottom:"1px solid #2a2a2a"},children:[e.jsxs(m,{children:[e.jsx($,{variant:"h6",sx:{color:"#58a6ff",mb:0},children:a}),e.jsx($,{variant:"body2",sx:{color:"#aaa"},children:c})]}),e.jsxs(m,{sx:{display:"flex",alignItems:"center",gap:1},children:[e.jsx(Z,{size:"small",variant:"outlined",startIcon:e.jsx(Ss,{}),sx:{color:"#58a6ff",borderColor:"#58a6ff"},onClick:Re,disabled:v,children:"Refresh"}),e.jsx(Z,{size:"small",variant:"contained",startIcon:e.jsx(ts,{}),sx:{bgcolor:"#58a6ff",color:"#0b0f19"},onClick:Fe,children:d})]})]}),B&&e.jsx(m,{sx:{px:2,py:1.5,color:"#ff8080"},children:e.jsx($,{variant:"body2",children:B})}),v&&e.jsxs(m,{sx:{px:2,py:1.5,display:"flex",alignItems:"center",gap:1,color:"#7db7ff"},children:[e.jsx(Mt,{size:18,sx:{color:"#58a6ff"}}),e.jsx($,{variant:"body2",children:r})]}),e.jsxs(Rt,{size:"small",sx:sl,children:[e.jsx(Bt,{children:e.jsxs(Ue,{children:[e.jsx(Q,{sortDirection:y==="hostname"?I:!1,children:e.jsx(Tt,{active:y==="hostname",direction:y==="hostname"?I:"asc",onClick:Le("hostname"),children:"Hostname"})}),e.jsx(Q,{sortDirection:y==="address"?I:!1,children:e.jsx(Tt,{active:y==="address",direction:y==="address"?I:"asc",onClick:Le("address"),children:u})}),e.jsx(Q,{sortDirection:y==="description"?I:!1,children:e.jsx(Tt,{active:y==="description",direction:y==="description"?I:"asc",onClick:Le("description"),children:"Description"})}),e.jsx(Q,{sortDirection:y==="created_at"?I:!1,children:e.jsx(Tt,{active:y==="created_at",direction:y==="created_at"?I:"asc",onClick:Le("created_at"),children:"Added"})}),e.jsx(Q,{align:"right",children:"Actions"})]})}),e.jsxs(Nt,{children:[Ae.map(g=>{var T;const L=Number(g.created_at||0)*1e3,we=L?new Date(L).toLocaleString():((T=g.summary)==null?void 0:T.created)||"";return e.jsxs(Ue,{children:[e.jsx(Q,{children:g.hostname}),e.jsx(Q,{children:g.connection_endpoint||""}),e.jsx(Q,{children:g.description||""}),e.jsx(Q,{children:we}),e.jsxs(Q,{align:"right",children:[e.jsx(nt,{size:"small",sx:{color:"#7db7ff"},onClick:()=>je(g),children:e.jsx(Fs,{fontSize:"small"})}),e.jsx(nt,{size:"small",sx:{color:"#ff8080"},onClick:()=>w(g),children:e.jsx($s,{fontSize:"small"})})]})]},g.hostname)}),!Ae.length&&!v&&e.jsx(Ue,{children:e.jsx(Q,{colSpan:5,sx:{textAlign:"center",color:"#888"},children:i})})]})]}),e.jsxs(Ze,{open:x,onClose:V,fullWidth:!0,maxWidth:"sm",PaperProps:{sx:{bgcolor:"#121212",color:"#fff"}},children:[e.jsx(et,{children:be?p:l}),e.jsxs(rt,{sx:{display:"flex",flexDirection:"column",gap:2,mt:1},children:[e.jsx(Ie,{label:"Hostname",value:z.hostname,disabled:be,onChange:g=>E(L=>({...L,hostname:g.target.value})),fullWidth:!0,size:"small",sx:{"& .MuiOutlinedInput-root":{backgroundColor:"#1f1f1f",color:"#fff","& fieldset":{borderColor:"#555"},"&:hover fieldset":{borderColor:"#888"}},"& .MuiInputLabel-root":{color:"#aaa"}},helperText:"Hostname used within Borealis (unique)."}),e.jsx(Ie,{label:u,value:z.address,onChange:g=>E(L=>({...L,address:g.target.value})),fullWidth:!0,size:"small",sx:{"& .MuiOutlinedInput-root":{backgroundColor:"#1f1f1f",color:"#fff","& fieldset":{borderColor:"#555"},"&:hover fieldset":{borderColor:"#888"}},"& .MuiInputLabel-root":{color:"#aaa"}},helperText:`IP or FQDN Borealis can reach over ${t}.`}),e.jsx(Ie,{label:"Description",value:z.description,onChange:g=>E(L=>({...L,description:g.target.value})),fullWidth:!0,size:"small",sx:{"& .MuiOutlinedInput-root":{backgroundColor:"#1f1f1f",color:"#fff","& fieldset":{borderColor:"#555"},"&:hover fieldset":{borderColor:"#888"}},"& .MuiInputLabel-root":{color:"#aaa"}}}),e.jsx(Ie,{label:"Operating System",value:z.operating_system,onChange:g=>E(L=>({...L,operating_system:g.target.value})),fullWidth:!0,size:"small",sx:{"& .MuiOutlinedInput-root":{backgroundColor:"#1f1f1f",color:"#fff","& fieldset":{borderColor:"#555"},"&:hover fieldset":{borderColor:"#888"}},"& .MuiInputLabel-root":{color:"#aaa"}}}),B&&e.jsx($,{variant:"body2",sx:{color:"#ff8080"},children:B})]}),e.jsxs(tt,{sx:{px:3,pb:2},children:[e.jsx(Z,{onClick:V,sx:{color:"#58a6ff"},disabled:ue,children:"Cancel"}),e.jsx(Z,{onClick:O,variant:"outlined",sx:{color:"#58a6ff",borderColor:"#58a6ff"},disabled:ue,children:ue?"Saving...":"Save"})]})]}),e.jsx(Zt,{open:!!me,message:me?`Remove ${t} device '${me.hostname}' from inventory?`:"",onCancel:()=>w(null),onConfirm:M,confirmDisabled:W}),e.jsx(So,{open:te,defaultType:n,onClose:()=>ee(!1),onCreated:()=>{ee(!1),Re()}})]})}function nl(n){return e.jsx(ko,{...n,type:"winrm"})}const Io=({title:n,description:t,icon:o,actions:a,children:d,sx:u})=>e.jsxs(Qe,{elevation:0,sx:{p:1.5,borderRadius:2,bgcolor:"#1c1c1c",border:"1px solid #2a2a2a",mb:1.5,...u||{}},children:[e.jsxs(m,{sx:{display:"flex",alignItems:"flex-start",justifyContent:"space-between",mb:1},children:[e.jsxs(m,{sx:{display:"flex",alignItems:"center"},children:[o?e.jsx(m,{sx:{color:"#58a6ff",display:"flex",alignItems:"center",justifyContent:"center",minWidth:48,mr:1},children:o}):null,e.jsxs(m,{children:[e.jsx($,{variant:"caption",sx:{color:"#58a6ff",fontWeight:400,fontSize:"14px",letterSpacing:.2},children:n}),t?e.jsx($,{variant:"body2",sx:{color:"#aaa"},children:t}):null]})]}),a?e.jsx(m,{sx:{display:"flex",alignItems:"center",gap:1},children:a}):null]}),d]}),Mn=n=>{!n||!Array.isArray(n.children)||(n.children.sort((t,o)=>{const a=!!t.isFolder,d=!!o.isFolder;return a!==d?a?-1:1:String(t.label||"").localeCompare(String(o.label||""),void 0,{sensitivity:"base"})}),n.children.forEach(Mn))};function ol(n,t){const o={},a={id:"root",label:"Workflows",path:"",isFolder:!0,children:[]};return o[a.id]=a,(t||[]).forEach(d=>{const u=(d||"").split("/");let r=a.children,i="";u.forEach(c=>{const p=i?`${i}/${c}`:c;let l=r.find(h=>h.id===p);l||(l={id:p,label:c,path:p,isFolder:!0,children:[]},r.push(l),o[p]=l),r=l.children,i=p})}),(n||[]).forEach(d=>{const u=(d.rel_path||"").split("/");let r=a.children,i="";u.forEach((c,p)=>{const l=i?`${i}/${c}`:c,h=p===u.length-1;let f=r.find(y=>y.id===l);f||(f={id:l,label:h?d.tab_name&&d.tab_name.trim()||d.file_name:c,path:l,isFolder:!h,fileName:d.file_name,workflow:h?d:null,children:[]},r.push(f),o[l]=f),h||(r=f.children,i=l)})}),Mn(a),{root:[a],map:o}}function rl({onOpenWorkflow:n}){var Le,Fe;const[t,o]=s.useState([]),[a,d]=s.useState({}),[u,r]=s.useState(null),[i,c]=s.useState(null),[p,l]=s.useState(""),[h,f]=s.useState(!1),[y,C]=s.useState(!1),[I,k]=s.useState("rename"),[v,j]=s.useState(!1),[B,R]=s.useState(""),[x,S]=s.useState(!1),z=xo(),[E,U]=s.useState(null),X=async je=>{if(!E||!je.isFolder)return;if(E.path===je.path||je.path.startsWith(`${E.path}/`)){U(null);return}const V=je.path?`${je.path}/${E.fileName}`:E.fileName;try{await fetch("/api/assembly/move",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({island:"workflows",kind:"file",path:E.path,new_path:V})}),ue()}catch(O){console.error("Failed to move workflow:",O)}U(null)},ue=s.useCallback(async()=>{try{const je=await fetch("/api/assembly/list?island=workflows");if(!je.ok)throw new Error(`HTTP ${je.status}`);const V=await je.json(),{root:O,map:M}=ol(V.items||[],V.folders||[]);o(O),d(M)}catch(je){console.error("Failed to load workflows:",je),o([]),d({})}},[]);s.useEffect(()=>{ue()},[ue]);const Se=(je,V)=>{je.preventDefault(),c(V),r(u===null?{mouseX:je.clientX-2,mouseY:je.clientY-4}:null)},ce=()=>{r(null),i&&(l(i.label),i.isFolder?(k("rename"),C(!0)):f(!0))},de=()=>{r(null),i&&!i.isFolder&&n&&n(i.workflow)},me=()=>{r(null),i&&S(!0)},w=()=>{i&&(r(null),k("create"),l(""),C(!0))},W=()=>{i&&(r(null),R(""),j(!0))},F=async()=>{if(i){try{await fetch("/api/assembly/rename",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({island:"workflows",kind:"file",path:i.path,new_name:p})}),ue()}catch(je){console.error("Failed to rename workflow:",je)}f(!1)}},te=async()=>{try{if(I==="rename"&&i)await fetch("/api/assembly/rename",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({island:"workflows",kind:"folder",path:i.path,new_name:p})});else{const je=i?i.path:"",V=je?`${je}/${p}`:p;await fetch("/api/assembly/create",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({island:"workflows",kind:"folder",path:V})})}ue()}catch(je){console.error("Folder operation failed:",je)}C(!1)},ee=(je,V)=>{const O=a[V];O&&!O.isFolder&&n&&n(O.workflow)},be=async()=>{if(i){try{i.isFolder?await fetch("/api/assembly/delete",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({island:"workflows",kind:"folder",path:i.path})}):await fetch("/api/assembly/delete",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({island:"workflows",kind:"file",path:i.path})}),ue()}catch(je){console.error("Failed to delete:",je)}S(!1)}},Re=je=>(je||[]).map(V=>e.jsx(ys,{itemId:V.id,label:e.jsxs(m,{sx:{display:"flex",alignItems:"center"},draggable:!V.isFolder,onDragStart:()=>!V.isFolder&&U(V),onDragOver:O=>{E&&V.isFolder&&O.preventDefault()},onDrop:O=>{O.preventDefault(),X(V)},onContextMenu:O=>Se(O,V),children:[V.isFolder?e.jsx(Nn,{sx:{mr:1,color:"#0475c2"}}):e.jsx(Tn,{sx:{mr:1,color:"#0475c2"}}),e.jsx($,{sx:{flexGrow:1,color:"#e6edf3"},children:V.label})]}),children:V.children&&V.children.length>0?Re(V.children):null},V.id)),Ae=((Fe=(Le=t[0])==null?void 0:Le.children)==null?void 0:Fe.map(je=>je.id))||[];return e.jsxs(Io,{title:"Workflows",description:"Node-Based Automation Pipelines",icon:e.jsx(kn,{sx:{fontSize:40}}),actions:e.jsx(Z,{size:"small",variant:"outlined",onClick:()=>{c({id:"root",path:"",isFolder:!0}),R(""),j(!0)},sx:{color:"#58a6ff",borderColor:"#2f81f7",textTransform:"none","&:hover":{borderColor:"#58a6ff"}},children:"New Workflow"}),children:[e.jsx(m,{sx:{p:1},onDragOver:je=>{E&&je.preventDefault()},onDrop:je=>{je.preventDefault(),X({path:"",isFolder:!0})},children:e.jsx(vs,{sx:{color:"#e6edf3"},onNodeSelect:ee,apiRef:z,defaultExpandedItems:["root",...Ae],children:Re(t)},Ae.join(","))}),e.jsxs(Et,{open:u!==null,onClose:()=>r(null),anchorReference:"anchorPosition",anchorPosition:u?{top:u.mouseY,left:u.mouseX}:void 0,PaperProps:{sx:{bgcolor:"#1e1e1e",color:"#fff",fontSize:"13px"}},children:[(i==null?void 0:i.isFolder)&&e.jsxs(e.Fragment,{children:[e.jsx(fe,{onClick:W,children:"New Workflow"}),e.jsx(fe,{onClick:w,children:"New Subfolder"}),i.id!=="root"&&e.jsx(fe,{onClick:ce,children:"Rename"}),i.id!=="root"&&e.jsx(fe,{onClick:me,children:"Delete"})]}),!(i!=null&&i.isFolder)&&e.jsxs(e.Fragment,{children:[e.jsx(fe,{onClick:de,children:"Edit"}),e.jsx(fe,{onClick:ce,children:"Rename"}),e.jsx(fe,{onClick:me,children:"Delete"})]})]}),e.jsx(Ri,{open:h,value:p,onChange:l,onCancel:()=>f(!1),onSave:F}),e.jsx(wo,{open:y,value:p,onChange:l,onCancel:()=>C(!1),onSave:te,title:I==="rename"?"Rename Folder":"New Folder",confirmText:I==="rename"?"Save":"Create"}),e.jsx(Ni,{open:v,value:B,onChange:R,onCancel:()=>j(!1),onCreate:()=>{j(!1),n&&n(null,(i==null?void 0:i.path)||"",B)}}),e.jsx(Zt,{open:x,message:"If you delete this, there is no undo button, are you sure you want to proceed?",onCancel:()=>S(!1),onConfirm:be})]})}function al(n,t,o){const a=r=>{const i=[String(n||"").trim(),String(n||"").replace(/\s+/g,"_")].filter(Boolean),c=String(r||"").replace(/\\/g,"/").split("/").filter(Boolean);return c.length&&i.includes(c[0])&&c.shift(),c},d={},u={id:"root",label:n,path:"",isFolder:!0,children:[]};return d[u.id]=u,(o||[]).forEach(r=>{const i=a(r);let c=u.children,p="";i.forEach(l=>{const h=p?`${p}/${l}`:l;let f=c.find(y=>y.id===h);f||(f={id:h,label:l,path:h,isFolder:!0,children:[]},c.push(f),d[h]=f),c=f.children,p=h})}),(t||[]).forEach(r=>{const i=a(r==null?void 0:r.rel_path);let c=u.children,p="";i.forEach((l,h)=>{const f=p?`${p}/${l}`:l,y=h===i.length-1;let C=c.find(I=>I.id===f);C||(C={id:f,label:y&&(r.name||r.display_name||r.file_name)||l,path:f,isFolder:!y,fileName:r.file_name,meta:y?r:null,children:[]},c.push(C),d[f]=C),y||(c=C.children,p=f)})}),Mn(u),{root:[u],map:d}}function Kn({title:n,description:t,rootLabel:o,baseApi:a,newItemLabel:d="New Script",onEdit:u}){var je,V;const[r,i]=s.useState([]),[c,p]=s.useState({}),[l,h]=s.useState(null),[f,y]=s.useState(null),[C,I]=s.useState(""),[k,v]=s.useState(!1),[j,B]=s.useState(!1),[R,x]=s.useState("rename"),[S,z]=s.useState(!1),[E,U]=s.useState(""),[X,ue]=s.useState(!1),Se=xo(),[ce,de]=s.useState(null),me=es.useMemo(()=>String(a||"").toLowerCase().endsWith("/api/ansible")?"ansible":"scripts",[a]),w=s.useCallback(async()=>{try{const O=await fetch(`/api/assembly/list?island=${encodeURIComponent(me)}`);if(!O.ok)throw new Error(`HTTP ${O.status}`);const M=await O.json(),{root:g,map:L}=al(o,M.items||[],M.folders||[]);i(g),p(L)}catch(O){console.error(`Failed to load ${n}:`,O),i([]),p({})}},[me,n,o]);s.useEffect(()=>{w()},[w]);const W=(O,M)=>{O.preventDefault(),y(M),h(l===null?{mouseX:O.clientX-2,mouseY:O.clientY-4}:null)},F=async O=>{if(!ce||!O.isFolder)return;if(ce.path===O.path||O.path.startsWith(`${ce.path}/`)){de(null);return}const M=O.path?`${O.path}/${ce.fileName}`:ce.fileName;try{await fetch("/api/assembly/move",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({island:me,kind:"file",path:ce.path,new_path:M})}),w()}catch(g){console.error("Failed to move:",g)}de(null)},te=async(O,M)=>{const g=c[M];g&&!g.isFolder&&(h(null),u&&u(g.path))},ee=async()=>{var O;try{const M={island:me,kind:"file",path:f.path,new_name:C};(O=f==null?void 0:f.meta)!=null&&O.type&&(M.type=f.meta.type);const g=await fetch("/api/assembly/rename",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(M)}),L=await g.json();if(!g.ok)throw new Error((L==null?void 0:L.error)||`HTTP ${g.status}`);v(!1),w()}catch(M){console.error("Failed to rename file:",M),v(!1)}},be=async()=>{try{if(R==="rename"&&f)await fetch("/api/assembly/rename",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({island:me,kind:"folder",path:f.path,new_name:C})});else{const O=f?f.path:"",M=O?`${O}/${C}`:C;await fetch("/api/assembly/create",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({island:me,kind:"folder",path:M})})}B(!1),w()}catch(O){console.error("Folder operation failed:",O),B(!1)}},Re=async()=>{if(f)try{f.isFolder?await fetch("/api/assembly/delete",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({island:me,kind:"folder",path:f.path})}):await fetch("/api/assembly/delete",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({island:me,kind:"file",path:f.path})}),ue(!1),w()}catch(O){console.error("Failed to delete:",O),ue(!1)}},Ae=()=>{var L;const O=(E||"").trim(),g={folder:f!=null&&f.isFolder?f.path:((L=f==null?void 0:f.path)==null?void 0:L.split("/").slice(0,-1).join("/"))||"",suggestedFileName:O,defaultType:me==="ansible"?"ansible":"powershell",type:me==="ansible"?"ansible":"powershell",category:me==="ansible"?"application":"script"};z(!1),U(""),u&&u(null,g)},Le=O=>(O||[]).map(M=>e.jsx(ys,{itemId:M.id,label:e.jsxs(m,{sx:{display:"flex",alignItems:"center"},draggable:!M.isFolder,onDragStart:()=>!M.isFolder&&de(M),onDragOver:g=>{ce&&M.isFolder&&g.preventDefault()},onDrop:g=>{g.preventDefault(),F(M)},onContextMenu:g=>W(g,M),onDoubleClick:()=>{M.isFolder||u&&u(M.path)},children:[M.isFolder?e.jsx(Nn,{sx:{mr:1,color:"#0475c2"}}):e.jsx(Tn,{sx:{mr:1,color:"#0475c2"}}),e.jsx($,{sx:{flexGrow:1,color:"#e6edf3"},children:M.label})]}),children:M.children&&M.children.length>0?Le(M.children):null},M.id)),Fe=((V=(je=r[0])==null?void 0:je.children)==null?void 0:V.map(O=>O.id))||[];return e.jsxs(Io,{title:n,description:t,icon:n==="Scripts"?e.jsx(pr,{sx:{fontSize:40}}):e.jsx(fr,{sx:{fontSize:40}}),actions:e.jsx(Z,{size:"small",variant:"outlined",onClick:()=>{U(""),z(!0)},sx:{color:"#58a6ff",borderColor:"#2f81f7",textTransform:"none","&:hover":{borderColor:"#58a6ff"}},children:d}),children:[e.jsx(m,{sx:{p:1},onDragOver:O=>{ce&&O.preventDefault()},onDrop:O=>{O.preventDefault(),F({path:"",isFolder:!0})},children:e.jsx(vs,{sx:{color:"#e6edf3"},onNodeSelect:te,apiRef:Se,defaultExpandedItems:["root",...Fe],children:Le(r)},Fe.join(","))}),e.jsxs(Et,{open:l!==null,onClose:()=>h(null),anchorReference:"anchorPosition",anchorPosition:l?{top:l.mouseY,left:l.mouseX}:void 0,PaperProps:{sx:{bgcolor:"#1e1e1e",color:"#fff",fontSize:"13px"}},children:[(f==null?void 0:f.isFolder)&&e.jsxs(e.Fragment,{children:[e.jsx(fe,{onClick:()=>{h(null),z(!0)},children:d}),e.jsx(fe,{onClick:()=>{h(null),x("create"),I(""),B(!0)},children:"New Subfolder"}),f.id!=="root"&&e.jsx(fe,{onClick:()=>{h(null),I(f.label),v(!0)},children:"Rename"}),f.id!=="root"&&e.jsx(fe,{onClick:()=>{h(null),ue(!0)},children:"Delete"})]}),!(f!=null&&f.isFolder)&&e.jsxs(e.Fragment,{children:[e.jsx(fe,{onClick:()=>{h(null),u&&u(f.path)},children:"Edit"}),e.jsx(fe,{onClick:()=>{h(null),I(f.label),v(!0)},children:"Rename"}),e.jsx(fe,{onClick:()=>{h(null),ue(!0)},children:"Delete"})]})]}),e.jsx(wo,{open:j,value:C,onChange:I,onCancel:()=>B(!1),onSave:be,title:R==="rename"?"Rename Folder":"New Folder",confirmText:R==="rename"?"Save":"Create"}),e.jsx(Qe,{component:O=>e.jsx("div",{...O}),sx:{display:k?"block":"none"},children:e.jsx("div",{style:{position:"fixed",inset:0,background:"rgba(0,0,0,0.4)",display:"flex",alignItems:"center",justifyContent:"center",zIndex:9999},children:e.jsxs(Qe,{sx:{bgcolor:"#121212",color:"#fff",p:2,minWidth:360},children:[e.jsx($,{variant:"h6",sx:{mb:1},children:"Rename"}),e.jsx("input",{autoFocus:!0,value:C,onChange:O=>I(O.target.value),style:{width:"100%",padding:8,background:"#2a2a2a",color:"#ccc",border:"1px solid #444",borderRadius:4}}),e.jsxs(m,{sx:{display:"flex",justifyContent:"flex-end",mt:2},children:[e.jsx(Z,{onClick:()=>v(!1),sx:{color:"#58a6ff"},children:"Cancel"}),e.jsx(Z,{onClick:ee,sx:{color:"#58a6ff"},children:"Save"})]})]})})}),e.jsx(Qe,{component:O=>e.jsx("div",{...O}),sx:{display:S?"block":"none"},children:e.jsx("div",{style:{position:"fixed",inset:0,background:"rgba(0,0,0,0.4)",display:"flex",alignItems:"center",justifyContent:"center",zIndex:9999},children:e.jsxs(Qe,{sx:{bgcolor:"#121212",color:"#fff",p:2,minWidth:360},children:[e.jsx($,{variant:"h6",sx:{mb:1},children:d}),e.jsx("input",{autoFocus:!0,value:E,onChange:O=>U(O.target.value),placeholder:"Name",style:{width:"100%",padding:8,background:"#2a2a2a",color:"#ccc",border:"1px solid #444",borderRadius:4}}),e.jsxs(m,{sx:{display:"flex",justifyContent:"flex-end",mt:2},children:[e.jsx(Z,{onClick:()=>z(!1),sx:{color:"#58a6ff"},children:"Cancel"}),e.jsx(Z,{onClick:Ae,sx:{color:"#58a6ff"},children:"Create"})]})]})})}),e.jsx(Zt,{open:X,message:"If you delete this, there is no undo button, are you sure you want to proceed?",onCancel:()=>ue(!1),onConfirm:Re})]})}function Xn({onOpenWorkflow:n,onOpenScript:t}){return e.jsxs(Qe,{sx:{m:2,p:0,bgcolor:"#1e1e1e"},elevation:2,children:[e.jsxs(m,{sx:{p:2,pb:1},children:[e.jsx($,{variant:"h6",sx:{color:"#58a6ff",mb:0},children:"Assemblies"}),e.jsx($,{variant:"body2",sx:{color:"#aaa"},children:"Collections of various types of components used to perform various automations upon targeted devices."})]}),e.jsx(m,{sx:{px:2,pb:2},children:e.jsxs(m,{sx:{display:"grid",gridTemplateColumns:{xs:"1fr",md:"1.2fr 1fr 1fr"},gap:2},children:[e.jsx(rl,{onOpenWorkflow:n}),e.jsx(Kn,{title:"Scripts",description:"Powershell, Batch, and Bash Scripts",rootLabel:"Scripts",baseApi:"/api/scripts",newItemLabel:"New Script",onEdit:(o,a)=>t&&t(o,"scripts",a)}),e.jsx(Kn,{title:"Ansible Playbooks",description:"Declarative Instructions for Consistent Automation",rootLabel:"Ansible Playbooks",baseApi:"/api/ansible",newItemLabel:"New Playbook",onEdit:(o,a)=>t&&t(o,"ansible",a)})]})})]})}const _n=[{key:"ansible",label:"Ansible Playbook",prism:"yaml"},{key:"powershell",label:"PowerShell Script",prism:"powershell"},{key:"batch",label:"Batch Script",prism:"batch"},{key:"bash",label:"Bash Script",prism:"bash"}],il=[{key:"script",label:"Script"},{key:"application",label:"Application"}],ll=[{key:"string",label:"String"},{key:"number",label:"Number"},{key:"boolean",label:"Boolean"},{key:"credential",label:"Credential"}],Pt={field:"#1C1C1C",sectionCard:"#2E2E2E",menuSelected:"rgba(88,166,255,0.16)",menuSelectedHover:"rgba(88,166,255,0.24)",primaryActionSaving:"rgba(88,166,255,0.12)",primaryActionHover:"rgba(88,166,255,0.18)",dialog:"#1a1f27"},rs={"& .MuiOutlinedInput-root":{bgcolor:Pt.field,color:"#e6edf3",borderRadius:1,minHeight:40,"& fieldset":{borderColor:"#2b3544"},"&:hover fieldset":{borderColor:"#3a4657"},"&.Mui-focused fieldset":{borderColor:"#58a6ff"}},"& .MuiOutlinedInput-input":{padding:"9px 12px",fontSize:"0.95rem",lineHeight:1.4},"& .MuiOutlinedInput-inputMultiline":{padding:"9px 12px"},"& .MuiInputLabel-root":{color:"#9ba3b4",transform:"translate(12px, 11px) scale(0.8)"},"& .MuiInputLabel-root.Mui-focused":{color:"#58a6ff"},"& .MuiInputLabel-root.MuiInputLabel-shrink":{transform:"translate(12px, -6px) scale(0.75)"},"& input[type=number]":{MozAppearance:"textfield"},"& input[type=number]::-webkit-outer-spin-button":{WebkitAppearance:"none",margin:0},"& input[type=number]::-webkit-inner-spin-button":{WebkitAppearance:"none",margin:0}},Ps={...rs,"& .MuiSelect-select":{padding:"10px 12px !important",display:"flex",alignItems:"center"}},Zs={color:"#58a6ff",fontWeight:400,fontSize:"14px",letterSpacing:.2},cl={bgcolor:Pt.sectionCard,borderRadius:2,border:"1px solid #262f3d"},Es={PaperProps:{sx:{bgcolor:Pt.field,color:"#e6edf3",border:"1px solid #2b3544","& .MuiMenuItem-root.Mui-selected":{bgcolor:Pt.menuSelected},"& .MuiMenuItem-root.Mui-selected:hover":{bgcolor:Pt.menuSelectedHover}}}};function dl(n){return Object.fromEntries(n.map(t=>[t.key,t]))}const ul=dl(_n),pl="#0d1117";function fl(n,t){try{const o=qt.languages[t]||qt.languages.markup;return qt.highlight(n??"",o,t)}catch{return(n??"").replace(/[&<>]/g,o=>({"&":"&","<":"<",">":">"})[o])}}function bn(n=""){const t=n.trim().replace(/[^a-zA-Z0-9._-]+/g,"_")||"assembly";return t.endsWith(".json")?t:`${t}.json`}function Ms(n=""){return n?n.replace(/\\/g,"/").replace(/^\/+|\/+$/g,"").replace(/\/+/g,"/"):""}function hl(n){if(!n||Number.isNaN(n))return"0 B";if(n<1024)return`${n} B`;const t=["KB","MB","GB","TB"];let o=-1,a=n;for(;a>=1024&&o<t.length-1;)a/=1024,o+=1;return`${a.toFixed(1)} ${t[o]}`}function sn(n="powershell"){return{name:"",description:"",category:n==="ansible"?"application":"script",type:n,script:"",timeoutSeconds:3600,sites:{mode:"all",values:[]},variables:[],files:[]}}function ml(n=[]){return(Array.isArray(n)?n:[]).map((t,o)=>({id:`${Date.now()}_${o}_${Math.random().toString(36).slice(2,8)}`,name:(t==null?void 0:t.name)||(t==null?void 0:t.key)||"",label:(t==null?void 0:t.label)||"",type:(t==null?void 0:t.type)||"string",defaultValue:(t==null?void 0:t.default)??(t==null?void 0:t.default_value)??"",required:!!(t!=null&&t.required),description:(t==null?void 0:t.description)||""}))}function Qn(n=""){if(typeof n!="string")return{success:!1,value:""};const t=n.trim();if(!t)return{success:!0,value:""};const o=t.replace(/\s+/g,"");try{if(typeof window<"u"&&typeof window.atob=="function"){const a=window.atob(o);if(typeof TextDecoder<"u")try{return{success:!0,value:new TextDecoder("utf-8",{fatal:!1}).decode(Uint8Array.from(a,r=>r.charCodeAt(0)))}}catch{}let d="";for(let u=0;u<a.length;u+=1)d+=String.fromCharCode(a.charCodeAt(u));try{return{success:!0,value:decodeURIComponent(escape(d))}}catch{return{success:!0,value:d}}}}catch{}try{if(typeof Buffer<"u")return{success:!0,value:Buffer.from(o,"base64").toString("utf-8")}}catch{}return{success:!1,value:""}}function xl(n=""){if(typeof n!="string"&&(n=n==null?"":String(n)),!n)return"";try{if(typeof TextEncoder<"u"&&typeof window<"u"&&typeof window.btoa=="function"){const o=new TextEncoder().encode(n);let a="";return o.forEach(d=>{a+=String.fromCharCode(d)}),window.btoa(a)}}catch{}try{if(typeof Buffer<"u")return Buffer.from(n,"utf-8").toString("base64")}catch{}return""}function gl(n=[]){return(Array.isArray(n)?n:[]).map((t,o)=>({id:`${Date.now()}_${o}_${Math.random().toString(36).slice(2,8)}`,fileName:(t==null?void 0:t.file_name)||(t==null?void 0:t.name)||"file.bin",size:(t==null?void 0:t.size)||0,mimeType:(t==null?void 0:t.mime_type)||(t==null?void 0:t.mimeType)||"",data:(t==null?void 0:t.data)||""}))}function bl(n={},t="powershell"){const o=sn(t);if(n&&typeof n=="object"){o.name=n.name||n.display_name||o.name,o.description=n.description||"",o.category=n.category||o.category,o.type=n.type||o.type;const a=Array.isArray(n.script_lines)?n.script_lines.map(i=>i==null?"":String(i)).join(`
|
||
`):"",d=n.script??n.content??a;if(typeof d=="string"){const i=(n.script_encoding||n.scriptEncoding||"").toLowerCase();if(["base64","b64","base-64"].includes(i)){const c=Qn(d);o.script=c.success?c.value:d}else if(i)o.script=d;else{const c=Qn(d);o.script=c.success?c.value:d}}else o.script=a;const u=n.timeout_seconds??n.timeout??o.timeoutSeconds;o.timeoutSeconds=Number.isFinite(Number(u))?Number(u):o.timeoutSeconds;const r=n.sites||{};o.sites={mode:r.mode||(Array.isArray(r.values)&&r.values.length?"specific":"all"),values:Array.isArray(r.values)?r.values:[]},o.variables=ml(n.variables),o.files=gl(n.files)}return o}function yl(n){var u,r,i;const t=typeof n.script=="string"?n.script.replace(/\r\n/g,`
|
||
`):"",o=Number(n.timeoutSeconds),a=Number.isFinite(o)?Math.max(0,Math.round(o)):3600,d=xl(t);return{version:1,name:((u=n.name)==null?void 0:u.trim())||"",description:n.description||"",category:n.category||"script",type:n.type||"powershell",script:d,script_encoding:"base64",timeout_seconds:a,sites:{mode:((r=n.sites)==null?void 0:r.mode)==="specific"?"specific":"all",values:Array.isArray((i=n.sites)==null?void 0:i.values)?n.sites.values.filter(c=>c&&c.trim()).map(c=>c.trim()):[]},variables:(n.variables||[]).map(c=>{var p;return{name:((p=c.name)==null?void 0:p.trim())||"",label:c.label||"",type:c.type||"string",default:c.defaultValue??"",required:!!c.required,description:c.description||""}}),files:(n.files||[]).map(c=>({file_name:c.fileName||"file.bin",size:c.size||0,mime_type:c.mimeType||"",data:c.data||""}))}}function jl({open:n,value:t,onChange:o,onCancel:a,onSave:d}){return e.jsxs(Ze,{open:n,onClose:a,PaperProps:{sx:{bgcolor:Pt.dialog,color:"#fff"}},children:[e.jsx(et,{children:"Rename Assembly File"}),e.jsx(rt,{children:e.jsx(Ie,{autoFocus:!0,margin:"dense",label:"File Name",fullWidth:!0,variant:"outlined",value:t,onChange:u=>o(u.target.value),sx:rs})}),e.jsxs(tt,{children:[e.jsx(Z,{onClick:a,sx:{color:"#58a6ff"},children:"Cancel"}),e.jsx(Z,{onClick:d,sx:{color:"#58a6ff"},children:"Save"})]})]})}function Zn({mode:n="scripts",initialPath:t="",initialContext:o=null,onConsumeInitialData:a,onSaved:d}){var g,L,we;const u=n==="ansible",r=u?"ansible":"powershell",[i,c]=s.useState(()=>sn(r)),[p,l]=s.useState(""),[h,f]=s.useState(""),[y,C]=s.useState(()=>Ms((o==null?void 0:o.folder)||"")),[I,k]=s.useState(!1),[v,j]=s.useState(""),[B,R]=s.useState(!1),[x,S]=s.useState(!1),[z,E]=s.useState([]),[U,X]=s.useState(!1),ue=s.useRef(null),Se=s.useMemo(()=>u?_n.filter(T=>T.key==="ansible"):_n.filter(T=>T.key!=="ansible"),[u]),ce=s.useMemo(()=>{const T=new Map;return z.forEach(G=>{if(!G)return;const ie=G.id!=null?String(G.id):"";ie&&T.set(ie,G)}),T},[z]),de=u?"ansible":"scripts";s.useEffect(()=>{if(!t)return;let T=!1;return(async()=>{try{const G=await fetch(`/api/assembly/load?island=${encodeURIComponent(de)}&path=${encodeURIComponent(t)}`);if(!G.ok)throw new Error(`HTTP ${G.status}`);const ie=await G.json();if(T)return;const Ce=ie.rel_path||t;l(Ce),C(Ms(Ce.split("/").slice(0,-1).join("/"))),f(ie.file_name||Ce.split("/").pop()||"");const Ee=bl(ie.assembly||ie,r);c(Ee)}catch(G){console.error("Failed to load assembly:",G)}finally{!T&&a&&a()}})(),()=>{T=!0}},[t,de]),s.useEffect(()=>{const T=o;if(!T||!T.nonce||ue.current===T.nonce)return;ue.current=T.nonce;const G=sn(T.defaultType||r);T.name&&(G.name=T.name),T.description&&(G.description=T.description),T.category&&(G.category=T.category),T.type&&(G.type=T.type),c(G),l("");const ie=T.suggestedFileName||T.name||"";f(ie?bn(ie):""),C(Ms(T.folder||"")),a&&a()},[o==null?void 0:o.nonce]),s.useEffect(()=>{let T=!1;return(async()=>{try{X(!0);const ie=await fetch("/api/sites");if(!ie.ok)throw new Error(`HTTP ${ie.status}`);const Ce=await ie.json();if(T)return;const Ee=Array.isArray(Ce==null?void 0:Ce.sites)?Ce.sites:[];E(Ee.map(Ne=>({...Ne,id:(Ne==null?void 0:Ne.id)!=null?String(Ne.id):""})).filter(Ne=>Ne.id))}catch(ie){T||(console.error("Failed to load sites:",ie),E([]))}finally{T||X(!1)}})(),()=>{T=!0}},[]);const me=((g=ul[i.type])==null?void 0:g.prism)||"powershell",w=T=>{c(G=>({...G,...T}))},W=T=>{c(G=>({...G,sites:{mode:T,values:T==="specific"?G.sites.values||[]:[]}}))},F=T=>{const G=Array.isArray(T)?T:typeof T=="string"?T.split(",").map(ie=>ie.trim()).filter(Boolean):[];c(ie=>({...ie,sites:{mode:"specific",values:G.map(Ce=>String(Ce))}}))},te=()=>{c(T=>({...T,variables:[...T.variables,{id:`${Date.now()}_${Math.random().toString(36).slice(2,8)}`,name:"",label:"",type:"string",defaultValue:"",required:!1,description:""}]}))},ee=(T,G)=>{c(ie=>({...ie,variables:ie.variables.map(Ce=>Ce.id===T?{...Ce,...G}:Ce)}))},be=T=>{c(G=>({...G,variables:G.variables.filter(ie=>ie.id!==T)}))},Re=async T=>{const G=Array.from(T.target.files||[]);if(!G.length)return;const ie=G.map(Ee=>new Promise(Ne=>{const Ke=new FileReader;Ke.onload=()=>{const at=Ke.result||"",ut=typeof at=="string"&&at.includes(",")?at.split(",",2)[1]:at;Ne({id:`${Date.now()}_${Math.random().toString(36).slice(2,8)}`,fileName:Ee.name,size:Ee.size,mimeType:Ee.type,data:ut})},Ke.onerror=()=>Ne(null),Ke.readAsDataURL(Ee)})),Ce=(await Promise.all(ie)).filter(Boolean);Ce.length&&c(Ee=>({...Ee,files:[...Ee.files,...Ce]})),T.target.value=""},Ae=T=>{c(G=>({...G,files:G.files.filter(ie=>ie.id!==T)}))},Le=()=>{if(p)return p;const T=bn(h||i.name||(u?"playbook":"assembly")),G=Ms(y);return G?`${G}/${T}`:T},Fe=async()=>{if(!i.name.trim()){alert("Assembly Name is required.");return}const T=yl(i);T.type=i.type;const G=Le();if(!G){alert("Unable to determine file path.");return}S(!0);try{if(p){const ie=await fetch("/api/assembly/edit",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({island:de,path:p,content:T})}),Ce=await ie.json().catch(()=>({}));if(!ie.ok)throw new Error((Ce==null?void 0:Ce.error)||`HTTP ${ie.status}`);Ce!=null&&Ce.rel_path&&(l(Ce.rel_path),C(Ms(Ce.rel_path.split("/").slice(0,-1).join("/"))),f(Ce.rel_path.split("/").pop()||h))}else{const ie=await fetch("/api/assembly/create",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({island:de,kind:"file",path:G,content:T,type:i.type})}),Ce=await ie.json();if(!ie.ok)throw new Error((Ce==null?void 0:Ce.error)||`HTTP ${ie.status}`);Ce.rel_path?(l(Ce.rel_path),C(Ce.rel_path.split("/").slice(0,-1).join("/")),f(Ce.rel_path.split("/").pop()||"")):(l(G),f(G.split("/").pop()||""))}d&&d()}catch(ie){console.error("Failed to save assembly:",ie),alert(ie.message||"Failed to save assembly")}finally{S(!1)}},je=async()=>{try{const T=bn(v||h||i.name),G=await fetch("/api/assembly/rename",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({island:de,kind:"file",path:p,new_name:T,type:i.type})}),ie=await G.json();if(!G.ok)throw new Error((ie==null?void 0:ie.error)||`HTTP ${G.status}`);const Ce=ie.rel_path||p;l(Ce),C(Ce.split("/").slice(0,-1).join("/")),f(Ce.split("/").pop()||T),k(!1)}catch(T){console.error("Failed to rename assembly:",T),alert(T.message||"Failed to rename"),k(!1)}},V=async()=>{if(!p){R(!1);return}try{const T=await fetch("/api/assembly/delete",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({island:de,kind:"file",path:p})});if(!T.ok){const G=await T.json().catch(()=>({}));throw new Error((G==null?void 0:G.error)||`HTTP ${T.status}`)}R(!1),c(sn(r)),l(""),f(""),d&&d()}catch(T){console.error("Failed to delete assembly:",T),alert(T.message||"Failed to delete assembly"),R(!1)}},O=((L=i.sites)==null?void 0:L.mode)==="specific"?"specific":"all",M=Array.isArray((we=i.sites)==null?void 0:we.values)?i.sites.values.map(T=>String(T)):[];return e.jsxs(m,{sx:{display:"flex",flexDirection:"column",flex:1,height:"100%",overflow:"hidden",ml:-.95,mt:-.95,bgcolor:pl},children:[e.jsx(m,{sx:{flex:1,overflow:"auto",p:{xs:2,md:3}},children:e.jsxs(Qe,{sx:{p:{xs:2.5,md:3},...cl,minHeight:"100%"},elevation:0,children:[e.jsxs(os,{container:!0,alignItems:"center",justifyContent:"space-between",sx:{mb:3},children:[e.jsx(os,{item:!0,xs:12,sm:6,children:e.jsxs(m,{children:[e.jsx($,{variant:"h6",sx:{color:"#58a6ff",mb:0},children:"Assembly Editor"}),e.jsx($,{variant:"body2",sx:{color:"#aaa"},children:"Create and edit variables, scripts, and other fields related to assemblies."})]})}),e.jsx(os,{item:!0,xs:12,sm:6,children:e.jsxs(m,{sx:{display:"flex",alignItems:"center",gap:1.5,flexWrap:"wrap",justifyContent:{xs:"flex-start",sm:"flex-end"},mt:{xs:2,sm:0}},children:[p?e.jsx(st,{title:"Rename File",children:e.jsx(Z,{size:"small",onClick:()=>{j(h),k(!0)},sx:{color:"#58a6ff",textTransform:"none"},children:"Rename"})}):null,p?e.jsx(st,{title:"Delete Assembly",children:e.jsx(Z,{size:"small",onClick:()=>R(!0),sx:{color:"#ff6b6b",textTransform:"none"},children:"Delete"})}):null,e.jsx(Z,{variant:"outlined",onClick:Fe,disabled:x,sx:{color:"#58a6ff",borderColor:"#58a6ff",textTransform:"none",backgroundColor:x?Pt.primaryActionSaving:Pt.field,"&:hover":{borderColor:"#7db7ff",backgroundColor:Pt.primaryActionHover},"&.Mui-disabled":{color:"#3c4452",borderColor:"#2b3544"}},children:x?"Saving...":"Save Assembly"})]})})]}),e.jsx(m,{sx:{display:"flex",alignItems:"flex-start",justifyContent:"space-between",gap:2,mb:0,flexWrap:"wrap"},children:e.jsx(m,{sx:{flex:"1 1 auto",minWidth:120},children:e.jsx($,{variant:"caption",sx:Zs,children:"Overview"})})}),e.jsxs(os,{container:!0,spacing:2,children:[e.jsxs(os,{item:!0,xs:12,md:6,children:[e.jsx(Ie,{label:"Assembly Name",value:i.name,onChange:T=>w({name:T.target.value}),fullWidth:!0,variant:"outlined",sx:{...rs,mb:2}}),e.jsx(Ie,{label:"Description",value:i.description,onChange:T=>w({description:T.target.value}),multiline:!0,minRows:2,maxRows:8,fullWidth:!0,variant:"outlined",sx:{...rs,"& .MuiOutlinedInput-inputMultiline":{padding:"6px 12px",lineHeight:1.4}}})]}),e.jsxs(os,{item:!0,xs:12,md:6,children:[e.jsx(Ie,{select:!0,fullWidth:!0,label:"Category",value:i.category,onChange:T=>w({category:T.target.value}),sx:{...Ps,mb:2},SelectProps:{MenuProps:Es},children:il.map(T=>e.jsx(fe,{value:T.key,children:T.label},T.key))}),e.jsx(Ie,{select:!0,fullWidth:!0,label:"Type",value:i.type,onChange:T=>w({type:T.target.value}),sx:Ps,SelectProps:{MenuProps:Es},children:Se.map(T=>e.jsx(fe,{value:T.key,children:T.label},T.key))})]})]}),e.jsxs(m,{sx:{mt:3},children:[e.jsx($,{variant:"caption",sx:{...Zs,mb:1},children:"Script Content"}),e.jsx(m,{sx:{border:"1px solid #2b3544",borderRadius:1,background:Pt.field},children:e.jsx(En,{value:i.script,onValueChange:T=>w({script:T}),highlight:T=>fl(T,me),padding:12,placeholder:p?`Editing: ${p}`:"Start typing your script...",style:{fontFamily:'ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace',fontSize:14,color:"#e6edf3",background:Pt.field,outline:"none",minHeight:320,lineHeight:1.45,caretColor:"#58a6ff"}})})]}),e.jsxs(os,{container:!0,spacing:2,sx:{mt:4},children:[e.jsx(os,{item:!0,xs:12,md:6,children:e.jsx(Ie,{label:"Timeout (seconds)",type:"text",inputMode:"numeric",value:i.timeoutSeconds,onChange:T=>{const G=T.target.value.replace(/[^0-9]/g,"");w({timeoutSeconds:G?Number(G):0})},fullWidth:!0,variant:"outlined",sx:rs,helperText:"Timeout this script if not completed within X seconds"})}),e.jsx(os,{item:!0,xs:12,md:6,children:e.jsxs(m,{sx:{display:"flex",flexDirection:{xs:"column",sm:"row"},gap:2,alignItems:"flex-start"},children:[e.jsxs(Ie,{select:!0,fullWidth:!0,label:"Site Scope",value:O,onChange:T=>W(T.target.value),sx:{...Ps,width:{xs:"100%",sm:320,lg:360}},SelectProps:{MenuProps:Es},children:[e.jsx(fe,{value:"all",children:"All Sites"}),e.jsx(fe,{value:"specific",children:"Specific Sites"})]}),O==="specific"?e.jsx(Ie,{select:!0,fullWidth:!0,label:"Allowed Sites",value:M,onChange:T=>F(Array.isArray(T.target.value)?T.target.value:[]),sx:{...Ps,width:{xs:"100%",sm:360,lg:420}},SelectProps:{multiple:!0,renderValue:T=>!T||T.length===0?e.jsx($,{sx:{color:"#6b7687"},children:"Select sites"}):T.map(ie=>{var Ce;return((Ce=ce.get(String(ie)))==null?void 0:Ce.name)||String(ie)}).join(", "),MenuProps:Es},children:U?e.jsx(fe,{disabled:!0,children:e.jsx(tn,{primary:"Loading sites..."})}):z.length?z.map(T=>{const G=String(T.id),ie=M.includes(G);return e.jsxs(fe,{value:G,sx:{display:"flex",alignItems:"flex-start",gap:1},children:[e.jsx(At,{checked:ie,sx:{color:"#58a6ff",mr:1}}),e.jsx(tn,{primary:T.name,secondary:T.description?T.description:void 0,primaryTypographyProps:{sx:{color:"#e6edf3"}},secondaryTypographyProps:{sx:{color:"#7f8794"}}})]},G)}):e.jsx(fe,{disabled:!0,children:e.jsx(tn,{primary:"No sites available"})})}):null]})})]}),e.jsxs(m,{sx:{mt:3},children:[e.jsx($,{variant:"caption",sx:{...Zs,mb:1},children:"Environment Variables"}),e.jsxs($,{variant:"body2",sx:{color:"#9ba3b4",mb:2},children:["Variables are dynamically passed into the script as environment variables at runtime. They are written like ",e.jsx("b",{children:"$env:variableName"})," in the script editor."]}),(i.variables||[]).length?e.jsx(m,{sx:{display:"flex",flexDirection:"column",gap:2},children:i.variables.map(T=>e.jsx(Qe,{sx:{p:2,bgcolor:Pt.field,border:"1px solid #2b3544",borderRadius:1},children:e.jsxs(m,{sx:{display:"flex",flexDirection:"column",gap:{xs:2,lg:1.5}},children:[e.jsxs(m,{sx:{display:"flex",flexWrap:"wrap",alignItems:"center",gap:{xs:2,lg:1.5},pt:.5},children:[e.jsx(m,{sx:{flex:{xs:"1 1 100%",lg:"0 1 28%"},minWidth:{lg:220}},children:e.jsx(st,{title:"This is the name of the variable you will be referencing inside of the script via $env:<variable>.",arrow:!0,placement:"top-start",children:e.jsx(Ie,{label:"Variable",value:T.name,onChange:G=>ee(T.id,{name:G.target.value}),fullWidth:!0,variant:"outlined",sx:rs})})}),e.jsx(m,{sx:{flex:{xs:"1 1 100%",lg:"0 1 22%"},minWidth:{lg:180}},children:e.jsx(st,{title:"This is the name that will be given to the variable and seen by Borealis server operators.",arrow:!0,placement:"top-start",children:e.jsx(Ie,{label:"Display Label",value:T.label,onChange:G=>ee(T.id,{label:G.target.value}),fullWidth:!0,variant:"outlined",sx:rs})})}),e.jsx(m,{sx:{flex:{xs:"1 1 100%",lg:"0 1 18%"},minWidth:{lg:160}},children:e.jsx(st,{title:"This defines the type of variable data the script should expect.",arrow:!0,placement:"top-start",children:e.jsx(Ie,{select:!0,fullWidth:!0,label:"Type",value:T.type,onChange:G=>ee(T.id,{type:G.target.value}),sx:Ps,SelectProps:{MenuProps:Es},children:ll.map(G=>e.jsx(fe,{value:G.key,children:G.label},G.key))})})}),e.jsx(m,{sx:{flex:{xs:"1 1 100%",lg:"0 1 24%"},minWidth:{lg:220},display:"flex",alignItems:"center"},children:T.type==="boolean"?e.jsx(st,{title:"This is the value that will be pre-populated in the assembly when ran. Use a sensible default value.",arrow:!0,placement:"top-start",children:e.jsx(bs,{control:e.jsx(At,{checked:!!T.defaultValue,onChange:G=>ee(T.id,{defaultValue:G.target.checked}),sx:{color:"#58a6ff"}}),label:"Default Value",sx:{color:"#9ba3b4",m:0,"& .MuiFormControlLabel-label":{fontSize:"0.95rem"}}})}):e.jsx(st,{title:"This is the value that will be pre-populated in the assembly when ran. Use a sensible default value.",arrow:!0,placement:"top-start",children:e.jsx(Ie,{label:"Default Value",value:T.defaultValue??"",onChange:G=>ee(T.id,{defaultValue:G.target.value}),fullWidth:!0,variant:"outlined",sx:rs})})}),e.jsx(m,{sx:{flex:{xs:"1 1 100%",lg:"0 1 28%"},minWidth:{lg:220}},children:e.jsx(st,{title:"Instruct the operator in why this variable exists and how to set it appropriately.",arrow:!0,placement:"top-start",children:e.jsx(Ie,{label:"Description",value:T.description,onChange:G=>ee(T.id,{description:G.target.value}),fullWidth:!0,variant:"outlined",sx:rs})})}),e.jsx(m,{sx:{flex:{xs:"1 1 100%",lg:"0 0 auto"},display:"flex",justifyContent:"flex-end",alignItems:"center",ml:{lg:"auto"}},children:e.jsx(st,{title:"Remove this Variable.",arrow:!0,children:e.jsx(nt,{onClick:()=>be(T.id),sx:{color:"#ff6b6b"},children:e.jsx($s,{})})})})]}),e.jsx(m,{sx:{display:"flex",flexWrap:"wrap",gap:{xs:2,lg:1.5}},children:e.jsxs(m,{sx:{flex:{xs:"1 1 100%",lg:"0 1 50%"},minWidth:{lg:220},display:"flex",alignItems:"center",gap:1.5},children:[e.jsx($,{variant:"caption",sx:{color:"#9ba3b4",fontSize:"0.75rem",ml:.5},children:"Required"}),e.jsx(At,{checked:!!T.required,onChange:G=>ee(T.id,{required:G.target.checked}),sx:{color:"#58a6ff",p:.5},inputProps:{"aria-label":"Required"}})]})})]})},T.id))}):e.jsx($,{variant:"body2",sx:{color:"#787f8b",mb:1},children:"No variables have been defined."}),e.jsx(Z,{startIcon:e.jsx(ts,{}),onClick:te,sx:{mt:2,color:"#58a6ff",textTransform:"none"},children:"Add Variable"})]}),e.jsxs(m,{sx:{mt:4},children:[e.jsx($,{variant:"caption",sx:{...Zs,mb:1},children:"Files"}),e.jsx($,{variant:"body2",sx:{color:"#9ba3b4",mb:2},children:"Upload supporting files. They will be embedded as Base64 and available to the assembly at runtime."}),(i.files||[]).length?e.jsx(m,{sx:{display:"flex",flexDirection:"column",gap:1.5},children:i.files.map(T=>e.jsxs(Qe,{sx:{p:1.5,bgcolor:Pt.field,border:"1px solid #2b3544",display:"flex",alignItems:"center",justifyContent:"space-between"},children:[e.jsxs(m,{children:[e.jsx($,{variant:"body2",sx:{color:"#e6edf3"},children:T.fileName}),e.jsxs($,{variant:"caption",sx:{color:"#7f8794"},children:[hl(T.size),T.mimeType?` • ${T.mimeType}`:""]})]}),e.jsx(nt,{onClick:()=>Ae(T.id),sx:{color:"#ff6b6b"},children:e.jsx($s,{})})]},T.id))}):e.jsx($,{variant:"body2",sx:{color:"#787f8b",mb:1},children:"No files uploaded yet."}),e.jsxs(Z,{component:"label",startIcon:e.jsx(go,{}),sx:{mt:2,color:"#58a6ff",textTransform:"none"},children:["Upload File",e.jsx("input",{type:"file",hidden:!0,multiple:!0,onChange:Re})]})]})]})}),e.jsx(jl,{open:I,value:v,onChange:j,onCancel:()=>k(!1),onSave:je}),e.jsx(Zt,{open:B,message:"Deleting this assembly cannot be undone. Continue?",onCancel:()=>R(!1),onConfirm:V})]})}Bn.registerModules([On]);const Ro=Pn.withParams({accentColor:"#FFA6FF",backgroundColor:"#1f2836",browserColorScheme:"dark",chromeBackgroundColor:{ref:"foregroundColor",mix:.07,onto:"backgroundColor"},fontFamily:{googleFont:"IBM Plex Sans"},foregroundColor:"#FFF",headerFontSize:14}),wl=Ro.themeName||"ag-theme-quartz",Lt='"IBM Plex Sans", "Helvetica Neue", Arial, sans-serif',yn='"Quartz Regular"';function vl({counts:n}){const t=Math.max(1,Number((n==null?void 0:n.total_targets)||0)),o=[{key:"success",color:"#00d18c"},{key:"running",color:"#58a6ff"},{key:"failed",color:"#ff4f4f"},{key:"timed_out",color:"#b36ae2"},{key:"expired",color:"#777777"},{key:"pending",color:"#999999"}],a=u=>u==="pending"?"Scheduled":u.replace(/_/g," ").replace(/^./,r=>r.toUpperCase()),d=o.filter(u=>u.key!=="pending").some(u=>Number((n==null?void 0:n[u.key])||0)>0);return e.jsxs(m,{sx:{display:"flex",flexDirection:"column",gap:.25,lineHeight:1.7,fontFamily:Lt},children:[e.jsx(m,{sx:{display:"flex",borderRadius:1,overflow:"hidden",width:220,height:6},children:o.map(u=>{const r=Number((n==null?void 0:n[u.key])||0);if(!r)return null;const i=`${Math.round(r/t*100)}%`;return e.jsx(m,{component:"span",sx:{display:"block",height:"100%",width:i,backgroundColor:u.color}},u.key)})}),e.jsx(m,{sx:{display:"flex",flexWrap:"wrap",columnGap:.75,rowGap:.25,color:"#aaa",fontSize:11,fontFamily:Lt},children:!d&&Number((n==null?void 0:n.pending)||0)>0?e.jsx(m,{component:"span",children:"Scheduled"}):o.filter(u=>Number((n==null?void 0:n[u.key])||0)>0).map(u=>e.jsxs(m,{component:"span",sx:{display:"inline-flex",alignItems:"center",gap:.5},children:[e.jsx(m,{component:"span",sx:{width:6,height:6,borderRadius:1,backgroundColor:u.color}}),n==null?void 0:n[u.key]," ",a(u.key)]},u.key))})]})}function Sl({onCreateJob:n,onEditJob:t,refreshToken:o}){const[a,d]=s.useState([]),[u,r]=s.useState(!1),[i,c]=s.useState(""),[p,l]=s.useState(!1),[h,f]=s.useState(()=>new Set),y=s.useRef(null),C=s.useCallback(async({showLoading:E=!1}={})=>{E&&(r(!0),c(""));try{const U=await fetch("/api/scheduled_jobs"),X=await U.json().catch(()=>({}));if(!U.ok)throw new Error((X==null?void 0:X.error)||`HTTP ${U.status}`);const ue=de=>{const me=String(de||"").toLowerCase(),w={immediately:"Immediately",once:"Once",every_5_minutes:"Every 5 Minutes",every_10_minutes:"Every 10 Minutes",every_15_minutes:"Every 15 Minutes",every_30_minutes:"Every 30 Minutes",every_hour:"Every Hour",daily:"Daily",weekly:"Weekly",monthly:"Monthly",yearly:"Yearly"};if(w[me])return w[me];try{return me.replace(/_/g," ").replace(/^./,W=>W.toUpperCase())}catch{return String(de||"")}},Se=de=>{if(!de)return"";try{const me=new Date(Number(de)*1e3);return Number.isNaN(me==null?void 0:me.getTime())?"":me.toLocaleString(void 0,{year:"numeric",month:"2-digit",day:"2-digit",hour:"numeric",minute:"2-digit"})}catch{return""}},ce=((X==null?void 0:X.jobs)||[]).map(de=>{var te;const me=Array.isArray(de.components)&&((te=de.components[0])==null?void 0:te.name)||"Demonstration Component",w=Array.isArray(de.targets)?`${de.targets.length} device${de.targets.length!==1?"s":""}`:"",W=ue(de.schedule_type||"immediately"),F={total_targets:Array.isArray(de.targets)?de.targets.length:0,pending:Array.isArray(de.targets)?de.targets.length:0,...de.result_counts||{}};return F&&F.total_targets==null&&(F.total_targets=Array.isArray(de.targets)?de.targets.length:0),{id:de.id,name:de.name,scriptWorkflow:me,target:w,occurrence:W,lastRun:Se(de.last_run_ts),nextRun:Se(de.next_run_ts||de.start_ts),result:de.last_status||(de.next_run_ts?"Scheduled":""),resultsCounts:F,enabled:!!de.enabled,raw:de}});d(ce),c(""),f(de=>{if(!de.size)return de;const me=new Set(ce.map((F,te)=>F.id??F.name??String(te)));let w=!1;const W=new Set;return de.forEach(F=>{me.has(F)?W.add(F):w=!0}),w?W:de})}catch(U){d([]),f(()=>new Set),c(String((U==null?void 0:U.message)||U||"Failed to load scheduled jobs"))}finally{E&&r(!1)}},[]);s.useEffect(()=>{let E,U=!0;return(async()=>U&&await C({showLoading:!0}))(),E=setInterval(()=>{C()},5e3),()=>{U=!1,E&&clearInterval(E)}},[C,o]);const I=s.useCallback(E=>{y.current=E.api},[]);s.useEffect(()=>{const E=y.current;E&&(u?E.showLoadingOverlay():a.length?E.hideOverlay():E.showNoRowsOverlay())},[u,a]),s.useEffect(()=>{const E=y.current;E&&E.forEachNode(U=>{const X=h.has(U.id);U.isSelected()!==X&&U.setSelected(X)})},[a,h]);const k=h.size>0,v=s.useCallback(()=>{const E=y.current;if(!E)return;const U=E.getSelectedNodes(),X=new Set;U.forEach(ue=>{(ue==null?void 0:ue.id)!=null&&X.add(String(ue.id))}),f(X)},[]),j=s.useCallback(E=>{var U,X;return((U=E==null?void 0:E.data)==null?void 0:U.id)??((X=E==null?void 0:E.data)==null?void 0:X.name)??String((E==null?void 0:E.rowIndex)??"")},[]),B=s.useCallback(E=>{const U=E.data;if(!U)return null;const X=ue=>{ue.preventDefault(),ue.stopPropagation(),typeof t=="function"&&t(U.raw)};return e.jsx(Z,{onClick:X,sx:{color:"#58a6ff",textTransform:"none",p:0,minWidth:0,fontFamily:Lt},children:U.name||"-"})},[t]),R=s.useCallback(E=>{var U;return e.jsx(vl,{counts:(U=E==null?void 0:E.data)==null?void 0:U.resultsCounts})},[]),x=s.useCallback(E=>{const U=E.data;if(!U)return null;const X=async ue=>{ue.stopPropagation();const Se=ue.target.checked;try{await fetch(`/api/scheduled_jobs/${U.id}/toggle`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({enabled:Se})})}catch{}d(ce=>ce.map(de=>{if((de.id??de.name)===(U.id??U.name)){const me={...de.raw||{},enabled:Se};return{...de,enabled:Se,raw:me}}return de}))};return e.jsx(co,{size:"small",checked:!!U.enabled,onChange:X,onClick:ue=>ue.stopPropagation(),sx:{"& .MuiSwitch-switchBase.Mui-checked":{color:"#58a6ff"},"& .MuiSwitch-switchBase.Mui-checked + .MuiSwitch-track":{bgcolor:"#58a6ff"}}})},[]),S=s.useMemo(()=>[{headerName:"",field:"__checkbox__",checkboxSelection:!0,headerCheckboxSelection:!0,maxWidth:60,minWidth:60,sortable:!1,filter:!1,resizable:!1,suppressMenu:!0,pinned:!1},{headerName:"Name",field:"name",cellRenderer:B,sort:"asc"},{headerName:"Assembly(s)",field:"scriptWorkflow",valueGetter:E=>{var U;return((U=E.data)==null?void 0:U.scriptWorkflow)||"Demonstration Component"}},{headerName:"Target",field:"target"},{headerName:"Recurrence",field:"occurrence"},{headerName:"Last Run",field:"lastRun"},{headerName:"Next Run",field:"nextRun"},{headerName:"Results",field:"resultsCounts",minWidth:280,cellRenderer:R,sortable:!1,filter:!1},{headerName:"Enabled",field:"enabled",minWidth:140,maxWidth:160,cellRenderer:x,sortable:!1,filter:!1,resizable:!1,suppressMenu:!0}],[x,B,R]),z=s.useMemo(()=>({sortable:!0,filter:"agTextColumnFilter",resizable:!0,flex:1,minWidth:140,cellStyle:{display:"flex",alignItems:"center",color:"#f5f7fa",fontFamily:Lt,fontSize:"13px"},headerClass:"scheduled-jobs-grid-header"}),[]);return e.jsxs(Qe,{sx:{m:2,p:0,bgcolor:"#1e1e1e",color:"#f5f7fa",fontFamily:Lt,display:"flex",flexDirection:"column",flexGrow:1,minWidth:0,minHeight:420},elevation:2,children:[e.jsxs(m,{sx:{display:"flex",alignItems:"center",justifyContent:"space-between",p:2,borderBottom:"1px solid #2a2a2a"},children:[e.jsxs(m,{children:[e.jsx($,{variant:"h6",sx:{color:"#58a6ff",mb:.3},children:"Scheduled Jobs"}),e.jsx($,{variant:"body2",sx:{color:"#aaa"},children:"List of automation jobs with schedules, results, and actions."})]}),e.jsxs(m,{sx:{display:"flex",gap:1,alignItems:"center"},children:[e.jsx(Z,{variant:"outlined",size:"small",disabled:!k,sx:{color:k?"#ff8080":"#666",borderColor:k?"#ff8080":"#333",textTransform:"none",fontFamily:Lt,"&:hover":{borderColor:k?"#ff8080":"#333"}},onClick:()=>l(!0),children:"Delete Job"}),e.jsx(Z,{variant:"contained",size:"small",sx:{bgcolor:"#58a6ff",color:"#0b0f19",textTransform:"none",fontFamily:Lt,"&:hover":{bgcolor:"#7db7ff"}},onClick:()=>n&&n(),children:"Create Job"})]})]}),u&&e.jsxs(m,{sx:{display:"flex",alignItems:"center",gap:1,color:"#7db7ff",px:2,py:1.5,borderBottom:"1px solid #2a2a2a"},children:[e.jsx(Mt,{size:18,sx:{color:"#58a6ff"}}),e.jsx($,{variant:"body2",children:"Loading scheduled jobs…"})]}),i&&e.jsx(m,{sx:{px:2,py:1.5,color:"#ff8080",borderBottom:"1px solid #2a2a2a"},children:e.jsx($,{variant:"body2",children:i})}),e.jsx(m,{sx:{flexGrow:1,minHeight:0,display:"flex",flexDirection:"column",mt:"10px",px:2,pb:2},children:e.jsx(m,{className:wl,sx:{width:"100%",height:"100%",flexGrow:1,fontFamily:Lt,"--ag-font-family":Lt,"--ag-icon-font-family":yn,"--ag-row-border-style":"solid","--ag-row-border-color":"#2a2a2a","--ag-row-border-width":"1px","& .ag-root-wrapper":{borderRadius:1,minHeight:320},"& .ag-root, & .ag-header, & .ag-center-cols-container, & .ag-paging-panel":{fontFamily:Lt},"& .ag-icon":{fontFamily:yn},"& .scheduled-jobs-grid-header":{fontFamily:Lt,fontWeight:600,color:"#f5f7fa"}},children:e.jsx(An,{rowData:a,columnDefs:S,defaultColDef:z,animateRows:!0,rowHeight:46,headerHeight:44,suppressCellFocus:!0,rowSelection:"multiple",rowMultiSelectWithClick:!0,suppressRowClickSelection:!0,getRowId:j,overlayNoRowsTemplate:"<span class='ag-overlay-no-rows-center'>No scheduled jobs found.</span>",onGridReady:I,onSelectionChanged:v,theme:Ro,style:{width:"100%",height:"100%",fontFamily:Lt,"--ag-icon-font-family":yn}})})}),e.jsxs(Ze,{open:p,onClose:()=>l(!1),PaperProps:{sx:{bgcolor:"#121212",color:"#fff"}},children:[e.jsx(et,{children:"Are you sure you want to delete this job(s)?"}),e.jsxs(tt,{children:[e.jsx(Z,{onClick:()=>l(!1),sx:{color:"#58a6ff"},children:"Cancel"}),e.jsx(Z,{onClick:async()=>{try{const E=Array.from(h),U=new Set(E);await Promise.allSettled(E.map(X=>fetch(`/api/scheduled_jobs/${X}`,{method:"DELETE"}))),d(X=>X.filter((ue,Se)=>{const ce=j({data:ue,rowIndex:Se});return!U.has(ce)})),f(()=>new Set)}catch{}l(!1),await C({showLoading:!0})},variant:"outlined",sx:{color:"#58a6ff",borderColor:"#58a6ff"},children:"Confirm"})]})]})]})}const en={width:12,height:12,border:"none",background:"transparent",opacity:0,pointerEvents:"none"},jt={pending:{label:"Pending",color:"#aab2bf",Icon:hr},running:{label:"Running",color:"#58a6ff",Icon:mr},expired:{label:"Expired",color:"#aab2bf",Icon:xr},success:{label:"Success",color:"#00d18c",Icon:gr},failed:{label:"Failed",color:"#ff4f4f",Icon:br}},Cl=[{key:"hostname",label:"Hostname"},{key:"online",label:"Status"},{key:"site",label:"Site"},{key:"ran_on",label:"Ran On"},{key:"job_status",label:"Job Status"},{key:"output",label:"StdOut / StdErr"}];function _l({data:n}){const{label:t,color:o,count:a,onClick:d,isActive:u,Icon:r}=n||{},i=Number.isFinite(a)?a:Number(a)||0,c=o||"#333",p=o?`${o}55`:"rgba(88,166,255,0.35)",l=s.useCallback(h=>{h==null||h.preventDefault(),h==null||h.stopPropagation(),d&&d()},[d]);return e.jsxs(m,{onClick:l,sx:{px:5.4,py:3.8,backgroundColor:"#1f1f1f",borderRadius:1.5,border:`1px solid ${c}`,boxShadow:u?`0 0 0 2px ${p}`:"none",cursor:"pointer",minWidth:324,textAlign:"left",transition:"border-color 0.2s ease, box-shadow 0.2s ease, transform 0.2s ease",transform:u?"translateY(-2px)":"none",display:"flex",alignItems:"flex-start",justifyContent:"flex-start"},children:[e.jsx(De,{type:"target",position:ze.Left,id:"left-top",style:{...en,top:"32%",transform:"translateY(-50%)"},isConnectable:!1}),e.jsx(De,{type:"target",position:ze.Left,id:"left-bottom",style:{...en,top:"68%",transform:"translateY(-50%)"},isConnectable:!1}),e.jsx(De,{type:"source",position:ze.Right,id:"right-top",style:{...en,top:"32%",transform:"translateY(-50%)"},isConnectable:!1}),e.jsx(De,{type:"source",position:ze.Right,id:"right-bottom",style:{...en,top:"68%",transform:"translateY(-50%)"},isConnectable:!1}),e.jsxs(m,{sx:{display:"flex",alignItems:"center",gap:1.2},children:[r?e.jsx(r,{sx:{color:o||"#e6edf3",fontSize:32}}):null,e.jsx($,{variant:"subtitle2",sx:{fontWeight:600,color:o||"#e6edf3",userSelect:"none",fontSize:"1.3rem"},children:`${i} ${t||""}`})]})]})}function ws({title:n,action:t}){return e.jsxs(m,{sx:{mt:2,mb:1,display:"flex",alignItems:"center",justifyContent:"space-between"},children:[e.jsx($,{variant:"subtitle1",sx:{color:"#7db7ff"},children:n}),t||null]})}function nn(n=[],t={}){return n.map(o=>e.jsx(ys,{itemId:o.id,label:o.label,children:o.children&&o.children.length?nn(o.children,t):null},o.id))}function No(n,t){const o={},a={id:"root_s",label:"Scripts",path:"",isFolder:!0,children:[]};return o[a.id]=a,(t||[]).forEach(d=>{const u=(d||"").split("/");let r=a.children,i="";u.forEach(c=>{const p=i?`${i}/${c}`:c;let l=r.find(h=>h.id===p);l||(l={id:p,label:c,path:p,isFolder:!0,children:[]},r.push(l),o[p]=l),r=l.children,i=p})}),(n||[]).forEach(d=>{const u=(d.rel_path||"").split("/");let r=a.children,i="";u.forEach((c,p)=>{const l=i?`${i}/${c}`:c,h=p===u.length-1;let f=r.find(y=>y.id===l);f||(f={id:l,label:h&&(d.name||d.file_name)||c,path:l,isFolder:!h,fileName:d.file_name,script:h?d:null,children:[]},r.push(f),o[l]=f),h||(r=f.children,i=l)})}),{root:[a],map:o}}function kl(n,t){return No(n,t)}function Il(n,t){const o={},a={id:"root_w",label:"Workflows",path:"",isFolder:!0,children:[]};return o[a.id]=a,(t||[]).forEach(d=>{const u=(d||"").split("/");let r=a.children,i="";u.forEach(c=>{const p=i?`${i}/${c}`:c;let l=r.find(h=>h.id===p);l||(l={id:p,label:c,path:p,isFolder:!0,children:[]},r.push(l),o[p]=l),r=l.children,i=p})}),(n||[]).forEach(d=>{const u=(d.rel_path||"").split("/");let r=a.children,i="";u.forEach((c,p)=>{var y;const l=i?`${i}/${c}`:c,h=p===u.length-1;let f=r.find(C=>C.id===l);f||(f={id:l,label:h?((y=d.tab_name)==null?void 0:y.trim())||d.file_name:c,path:l,isFolder:!h,fileName:d.file_name,workflow:h?d:null,children:[]},r.push(f),o[l]=f),h||(r=f.children,i=l)})}),{root:[a],map:o}}function Rl(n=[]){return(Array.isArray(n)?n:[]).map(t=>{if(!t||typeof t!="object")return null;const o=typeof t.name=="string"?t.name.trim():typeof t.key=="string"?t.key.trim():"";if(!o)return null;const a=typeof t.label=="string"&&t.label.trim()?t.label.trim():o,d=typeof t.type=="string"?t.type.toLowerCase():"string",u=!!t.required,r=typeof t.description=="string"?t.description:"";let i="";return Object.prototype.hasOwnProperty.call(t,"default")?i=t.default:Object.prototype.hasOwnProperty.call(t,"defaultValue")?i=t.defaultValue:Object.prototype.hasOwnProperty.call(t,"default_value")&&(i=t.default_value),{name:o,label:a,type:d,required:u,description:r,default:i}}).filter(Boolean)}function Ds(n,t){if(n==="boolean"){if(typeof t=="boolean")return t;if(typeof t=="number")return t!==0;if(t==null)return!1;const o=String(t).trim().toLowerCase();return o?["true","1","yes","on"].includes(o):!1}if(n==="number"){if(t==null||t==="")return"";if(typeof t=="number"&&Number.isFinite(t))return String(t);const o=Number(t);return Number.isFinite(o)?String(o):""}return t==null?"":String(t)}function eo(n=[],t=[],o={}){const a=Rl(n),d={},u={};(Array.isArray(t)?t:[]).forEach(c=>{if(!c||typeof c!="object")return;const p=typeof c.name=="string"?c.name.trim():"";p&&(Object.prototype.hasOwnProperty.call(c,"value")?d[p]=c.value:Object.prototype.hasOwnProperty.call(c,"default")&&(d[p]=c.default),u[p]={label:typeof c.label=="string"&&c.label.trim()?c.label.trim():p,type:typeof c.type=="string"?c.type.toLowerCase():void 0,required:!!c.required,description:typeof c.description=="string"?c.description:"",default:Object.prototype.hasOwnProperty.call(c,"default")?c.default:""})}),o&&typeof o=="object"&&Object.entries(o).forEach(([c,p])=>{const l=typeof c=="string"?c.trim():"";l&&(d[l]=p)});const r=new Set,i=a.map(c=>{const p=Object.prototype.hasOwnProperty.call(d,c.name)?d[c.name]:void 0;return r.add(c.name),{...c,value:p!==void 0?Ds(c.type,p):Ds(c.type,c.default)}});return(Array.isArray(t)?t:[]).forEach(c=>{if(!c||typeof c!="object")return;const p=typeof c.name=="string"?c.name.trim():"";if(!p||r.has(p))return;const l=u[p]||{},h=l.type||(typeof d[p]=="boolean"?"boolean":typeof d[p]=="number"?"number":"string"),f=Object.prototype.hasOwnProperty.call(l,"default")?l.default:"",y=Object.prototype.hasOwnProperty.call(d,p)?d[p]:Object.prototype.hasOwnProperty.call(c,"value")?c.value:f;i.push({name:p,label:l.label||p,type:h,required:!!l.required,description:l.description||"",default:f,value:Ds(h,y)}),r.add(p)}),Object.entries(d).forEach(([c,p])=>{const l=typeof c=="string"?c.trim():"";if(!l||r.has(l))return;const h=typeof p=="boolean"?"boolean":typeof p=="number"?"number":"string";i.push({name:l,label:l,type:h,required:!1,description:"",default:"",value:Ds(h,p)}),r.add(l)}),i}function Nl({comp:n,onRemove:t,onVariableChange:o,errors:a={}}){const d=Array.isArray(n.variables)?n.variables.filter(r=>r&&typeof r.name=="string"&&r.name):[],u=n.description||n.path||"";return e.jsx(Qe,{sx:{bgcolor:"#2a2a2a",border:"1px solid #3a3a3a",p:1.2,mb:1.2,borderRadius:1},children:e.jsxs(m,{sx:{display:"flex",gap:2},children:[e.jsxs(m,{sx:{flex:1},children:[e.jsx($,{variant:"subtitle2",sx:{color:"#e6edf3"},children:(n.type==="script",n.name)}),e.jsx($,{variant:"body2",sx:{color:"#aaa"},children:u})]}),e.jsx(In,{orientation:"vertical",flexItem:!0,sx:{borderColor:"#333"}}),e.jsxs(m,{sx:{flex:1},children:[e.jsx($,{variant:"subtitle2",sx:{color:"#ccc",mb:1},children:"Variables"}),d.length?e.jsx(m,{sx:{display:"flex",flexDirection:"column",gap:1.5},children:d.map(r=>e.jsx(m,{children:r.type==="boolean"?e.jsxs(e.Fragment,{children:[e.jsx(bs,{control:e.jsx(At,{size:"small",checked:!!r.value,onChange:i=>o(n.localId,r.name,i.target.checked)}),label:e.jsxs($,{variant:"body2",children:[r.label,r.required?" *":""]})}),r.description?e.jsx($,{variant:"caption",sx:{color:"#888",ml:3},children:r.description}):null]}):e.jsx(Ie,{fullWidth:!0,size:"small",label:`${r.label}${r.required?" *":""}`,type:r.type==="number"?"number":r.type==="credential"?"password":"text",value:r.value??"",onChange:i=>o(n.localId,r.name,i.target.value),InputLabelProps:{shrink:!0},sx:{"& .MuiOutlinedInput-root":{bgcolor:"#1b1b1b",color:"#e6edf3"},"& .MuiInputBase-input":{color:"#e6edf3"}},error:!!a[r.name],helperText:a[r.name]||r.description||""})},r.name))}):e.jsx($,{variant:"body2",sx:{color:"#888"},children:"No variables defined for this assembly."})]}),e.jsx(m,{children:e.jsx(nt,{onClick:()=>t(n.localId),size:"small",sx:{color:"#ff6666"},children:e.jsx($s,{fontSize:"small"})})})]})})}function Tl({onCancel:n,onCreated:t,initialJob:o=null}){const[a,d]=s.useState(0),[u,r]=s.useState(""),[i,c]=s.useState(""),[p,l]=s.useState([]),[h,f]=s.useState([]),[y,C]=s.useState("immediately"),[I,k]=s.useState(()=>Xs().add(5,"minute").second(0)),[v,j]=s.useState(!1),[B,R]=s.useState("no_expire"),[x,S]=s.useState("system"),[z,E]=s.useState([]),[U,X]=s.useState(!1),[ue,Se]=s.useState(""),[ce,de]=s.useState(""),[me,w]=s.useState(!0),W=s.useCallback(async()=>{X(!0),Se("");try{const b=await fetch("/api/credentials");if(!b.ok)throw new Error(`HTTP ${b.status}`);const P=await b.json(),D=Array.isArray(P==null?void 0:P.credentials)?P.credentials:[];D.sort((ae,xe)=>String((ae==null?void 0:ae.name)||"").localeCompare(String((xe==null?void 0:xe.name)||""))),E(D)}catch(b){E([]),Se(String(b.message||b))}finally{X(!1)}},[]);s.useEffect(()=>{W()},[W]);const F=s.useMemo(()=>x==="ssh"||x==="winrm",[x]),te=s.useCallback(b=>{const P=String(b||"system").toLowerCase();S(P),P==="winrm"?(w(!0),de("")):w(!1)},[]),ee=s.useMemo(()=>{if(!F)return z;const b=x==="winrm"?"winrm":"ssh";return z.filter(P=>String(P.connection_type||"").toLowerCase()===b)},[z,F,x]);s.useEffect(()=>{if(F){if(x==="winrm"&&me){de("");return}if(!ee.length){de("");return}(!ce||!ee.some(b=>String(b.id)===String(ce)))&&de(String(ee[0].id))}},[F,ee,ce,x,me]);const[be,Re]=s.useState(!1),[Ae,Le]=s.useState("scripts"),[Fe,je]=s.useState([]),[V,O]=s.useState({}),[M,g]=s.useState([]),[L,we]=s.useState({}),[T,G]=s.useState([]),[ie,Ce]=s.useState({}),[Ee,Ne]=s.useState(""),[Ke,at]=s.useState(!1),[ut,Pe]=s.useState([]),[gt,bt]=s.useState({}),[vt,Ut]=s.useState(""),[It,yt]=s.useState({}),[pt,St]=s.useState([]),[ct,oe]=s.useState(null),[_e,$e]=s.useState("hostname"),[Xe,We]=s.useState("asc"),[Je,ft]=s.useState({}),[ht,Jt]=s.useState(null),[Ct,Wt]=s.useState(null),[lt,Dt]=s.useState(""),Ot=s.useCallback(()=>`${Date.now()}_${Math.random().toString(36).slice(2,8)}`,[]),_t=s.useCallback(b=>["online","job_status","output"].includes(b)?"all":"",[]),Yt=s.useCallback(b=>{if(!Je||typeof Je!="object")return!1;const P=Je[b];if(P==null)return!1;if(typeof P=="string"){const D=P.trim();return!(!D||D==="all")}return!0},[Je]),ss=s.useCallback((b,P)=>{Wt(P),Dt(Je[P]??_t(P)),Jt(b.currentTarget)},[Je,_t]),A=s.useCallback(()=>{Jt(null),Wt(null)},[]),q=s.useCallback(()=>{if(!Ct){A();return}const b=lt;ft(P=>{const D={...P||{}};return!b||b==="all"||typeof b=="string"&&!b.trim()?delete D[Ct]:D[Ct]=b,D}),A()},[Ct,lt,A]),le=s.useCallback(()=>{if(!Ct){A();return}ft(b=>{const P={...b||{}};return delete P[Ct],P}),Dt(_t(Ct)),A()},[Ct,A,_t]),he=()=>{const b=Ct;if(!b)return null;if(b==="online")return e.jsxs(wt,{size:"small",fullWidth:!0,value:typeof lt=="string"&<?lt:"all",onChange:ae=>Dt(ae.target.value),children:[e.jsx(fe,{value:"all",children:"All Statuses"}),e.jsx(fe,{value:"online",children:"Online"}),e.jsx(fe,{value:"offline",children:"Offline"})]});if(b==="job_status"){const ae=["success","failed","running","pending","expired","timed out"];return e.jsxs(wt,{size:"small",fullWidth:!0,value:typeof lt=="string"&<?lt:"all",onChange:xe=>Dt(xe.target.value),children:[e.jsx(fe,{value:"all",children:"All Results"}),ae.map(xe=>e.jsx(fe,{value:xe,children:xe.replace(/\b\w/g,Be=>Be.toUpperCase())},xe))]})}if(b==="output")return e.jsxs(wt,{size:"small",fullWidth:!0,value:typeof lt=="string"&<?lt:"all",onChange:ae=>Dt(ae.target.value),children:[e.jsx(fe,{value:"all",children:"All Output"}),e.jsx(fe,{value:"stdout",children:"StdOut Only"}),e.jsx(fe,{value:"stderr",children:"StdErr Only"}),e.jsx(fe,{value:"both",children:"StdOut & StdErr"}),e.jsx(fe,{value:"none",children:"No Output"})]});const P={hostname:"Filter hostname",site:"Filter site",ran_on:"Filter date/time"},D=typeof lt=="string"?lt:"";return e.jsx(Ie,{size:"small",autoFocus:!0,fullWidth:!0,placeholder:P[b]||"Filter value",value:D,onChange:ae=>Dt(ae.target.value),onKeyDown:ae=>{ae.key==="Enter"&&(ae.preventDefault(),q())}})},_=s.useCallback(b=>{$e(P=>P===b?(We(D=>D==="asc"?"desc":"asc"),P):(We(b==="ran_on"?"desc":"asc"),b))},[]),K=s.useCallback(b=>{if(!b)return"";try{return new Date(Number(b)*1e3).toLocaleString(void 0,{year:"numeric",month:"2-digit",day:"2-digit",hour:"numeric",minute:"2-digit"})}catch{return""}},[]),pe=s.useMemo(()=>{const b=(P,D)=>D==="pending"?P==="pending"||P==="scheduled"||P==="queued"||P==="":D==="running"?P==="running":D==="success"?P==="success":D==="failed"?P==="failed"||P==="failure"||P==="timed out"||P==="timed_out"||P==="warning":D==="expired"?P==="expired":!0;return pt.filter(P=>{const D=String((P==null?void 0:P.job_status)||"").trim().toLowerCase();if(ct&&!b(D,ct))return!1;if(Je&&typeof Je=="object"){for(const[ae,xe]of Object.entries(Je))if(xe!=null){if(typeof xe=="string"){const Be=xe.trim();if(!Be||Be==="all")continue}if(ae==="hostname"){const Be=String(xe||"").toLowerCase();if(!String((P==null?void 0:P.hostname)||"").toLowerCase().includes(Be))return!1}else if(ae==="online"){if(xe==="online"&&!(P!=null&&P.online)||xe==="offline"&&(P!=null&&P.online))return!1}else if(ae==="site"){const Be=String(xe||"").toLowerCase();if(!String((P==null?void 0:P.site)||"").toLowerCase().includes(Be))return!1}else if(ae==="ran_on"){const Be=String(xe||"").toLowerCase();if(!K(P==null?void 0:P.ran_on).toLowerCase().includes(Be))return!1}else if(ae==="job_status"){const Be=String(xe||"").toLowerCase();if(!D.includes(Be))return!1}else if(ae==="output"&&(xe==="stdout"&&!(P!=null&&P.has_stdout)||xe==="stderr"&&!(P!=null&&P.has_stderr)||xe==="both"&&(!(P!=null&&P.has_stdout)||!(P!=null&&P.has_stderr))||xe==="none"&&(P!=null&&P.has_stdout||P!=null&&P.has_stderr)))return!1}}return!0})},[pt,ct,Je,K]),re=s.useMemo(()=>{const b=[...pe],P=Xe==="asc"?1:-1;return b.sort((D,ae)=>{let xe=0;switch(_e){case"hostname":xe=String((D==null?void 0:D.hostname)||"").localeCompare(String((ae==null?void 0:ae.hostname)||""));break;case"online":xe=(D!=null&&D.online?1:0)-(ae!=null&&ae.online?1:0);break;case"site":xe=String((D==null?void 0:D.site)||"").localeCompare(String((ae==null?void 0:ae.site)||""));break;case"ran_on":xe=Number((D==null?void 0:D.ran_on)||0)-Number((ae==null?void 0:ae.ran_on)||0);break;case"job_status":xe=String((D==null?void 0:D.job_status)||"").localeCompare(String((ae==null?void 0:ae.job_status)||""));break;case"output":{const Be=Oe=>(Oe!=null&&Oe.has_stdout?2:0)+(Oe!=null&&Oe.has_stderr?1:0);xe=Be(D)-Be(ae);break}default:xe=0}return xe===0&&(xe=String((D==null?void 0:D.hostname)||"").localeCompare(String((ae==null?void 0:ae.hostname)||""))),xe*P}),b},[pe,Xe,_e]),ke=s.useCallback((b,P)=>{const D=(P||"").replace(/\\/g,"/").replace(/^\/+/,"").trim();return D?b==="script"?D.startsWith("Scripts/")?D:`Scripts/${D}`:D:""},[]),N=s.useCallback(async(b,P)=>{const D=ke(b,P);if(!D)return{doc:null,normalizedPath:""};const ae=D.replace(/\\/g,"/").replace(/^\/+/,"").trim();if(!ae)return{doc:null,normalizedPath:""};let xe=ae;if(b==="script"&&xe.toLowerCase().startsWith("scripts/")?xe=xe.slice(8):b==="ansible"&&xe.toLowerCase().startsWith("ansible_playbooks/")&&(xe=xe.slice(18)),!xe)return{doc:null,normalizedPath:D};try{const Oe=await fetch(`/api/assembly/load?island=${b==="ansible"?"ansible":"scripts"}&path=${encodeURIComponent(xe)}`);return Oe.ok?{doc:await Oe.json(),normalizedPath:D}:{doc:null,normalizedPath:D}}catch{return{doc:null,normalizedPath:D}}},[ke]),H=s.useCallback(async(b=[])=>{const P=[];for(const D of b){if(!D||typeof D!="object")continue;const ae=D.type||D.component_type||"script";if(ae==="workflow"){P.push({...D,type:"workflow",variables:Array.isArray(D.variables)?D.variables:[],localId:Ot()});continue}const xe=ae==="ansible"?"ansible":"script",Be=D.path||D.script_path||D.rel_path||"",{doc:Oe,normalizedPath:Ye}=await N(xe,Be),ot=(Oe==null?void 0:Oe.assembly)||{},Bs=(ot==null?void 0:ot.variables)||(Oe==null?void 0:Oe.variables)||[],pn=eo(Bs,D.variables,D.variable_values);P.push({...D,type:xe,path:Ye||Be,name:D.name||(ot==null?void 0:ot.name)||D.file_name||D.tab_name||Ye||Be,description:D.description||(ot==null?void 0:ot.description)||Ye||Be,variables:pn,localId:Ot()})}return P},[N,Ot]),Y=s.useCallback(b=>(Array.isArray(b)?b:[]).map(P=>{if(!P||typeof P!="object")return P;const{localId:D,...ae}=P,xe={...ae};if(Array.isArray(P.variables)){const Be={};xe.variables=P.variables.filter(Oe=>Oe&&typeof Oe.name=="string"&&Oe.name).map(Oe=>{const Ye={name:Oe.name,label:Oe.label||Oe.name,type:Oe.type||"string",required:!!Oe.required,description:Oe.description||""};return Object.prototype.hasOwnProperty.call(Oe,"default")&&(Ye.default=Oe.default),Object.prototype.hasOwnProperty.call(Oe,"value")&&(Ye.value=Oe.value,Be[Oe.name]=Oe.value),Ye}),xe.variables.length||(xe.variables=[]),Object.keys(Be).length?xe.variable_values=Be:delete xe.variable_values}return xe}),[]),se=s.useCallback((b,P,D)=>{!b||!P||(l(ae=>ae.map(xe=>{if(!xe||xe.localId!==b)return xe;const Oe=(Array.isArray(xe.variables)?xe.variables:[]).map(Ye=>!Ye||Ye.name!==P?Ye:{...Ye,value:Ds(Ye.type||"string",D)});return{...xe,variables:Oe}})),yt(ae=>{if(!ae[b]||!ae[b][P])return ae;const xe={...ae},Be={...xe[b]};return delete Be[P],Object.keys(Be).length?xe[b]=Be:delete xe[b],xe}))},[]),ne=s.useCallback(b=>{l(P=>P.filter(D=>D.localId!==b)),yt(P=>{if(!P[b])return P;const D={...P};return delete D[b],D})},[]),ye=s.useMemo(()=>!(u.trim().length>0&&p.length>0&&h.length>0)||F&&!(x==="winrm"&&me)&&!ce?!1:y!=="immediately"?!!I:!0,[u,p.length,h.length,y,I,F,ce,x,me]),[ve,ge]=s.useState(!1),Me=!!(o&&o.id),[Ve,it]=s.useState([]),[J,Te]=s.useState("started_ts"),[Ge,He]=s.useState("desc"),us=s.useRef(new Map),[fs,zt]=s.useState(!1),[Ft,kt]=s.useState(""),[qe,xt]=s.useState([]),[ns,hs]=s.useState(!1),[Cs,ms]=s.useState(""),Kt=s.useCallback(async()=>{if(Me)try{const[b,P,D]=await Promise.all([fetch(`/api/scheduled_jobs/${o.id}/runs?days=30`),fetch(`/api/scheduled_jobs/${o.id}`),fetch(`/api/scheduled_jobs/${o.id}/devices`)]),ae=await b.json(),xe=await P.json(),Be=await D.json();if(!b.ok)throw new Error(ae.error||`HTTP ${b.status}`);if(!P.ok)throw new Error(xe.error||`HTTP ${P.status}`);if(!D.ok)throw new Error(Be.error||`HTTP ${D.status}`);it(Array.isArray(ae.runs)?ae.runs:[]),Gs(xe.job||{});const Oe=Array.isArray(Be.devices)?Be.devices.map(Ye=>({...Ye,activities:Array.isArray(Ye.activities)?Ye.activities:[]})):[];St(Oe)}catch{it([]),Gs({}),St([])}},[Me,o==null?void 0:o.id]);s.useEffect(()=>{if(!Me)return;let b;return(async()=>{try{await Kt()}catch{}})(),b=setInterval(Kt,1e4),()=>{b&&clearInterval(b)}},[Me,Kt]);const Ws=b=>{const D={Success:{bg:"#00d18c",fg:"#000"},Running:{bg:"#58a6ff",fg:"#000"},Scheduled:{bg:"#999999",fg:"#fff"},Expired:{bg:"#777777",fg:"#fff"},Failed:{bg:"#ff4f4f",fg:"#fff"},Warning:{bg:"#ff8c00",fg:"#000"}}[b]||{bg:"#aaa",fg:"#000"};return e.jsx("span",{style:{display:"inline-block",padding:"2px 8px",borderRadius:999,background:D.bg,color:D.fg,fontWeight:600,fontSize:12},children:b||""})},Vs=s.useMemo(()=>{if(!Array.isArray(Ve)||Ve.length===0)return[];const b=new Map;Ve.forEach(D=>{const ae=(D==null?void 0:D.scheduled_ts)||(D==null?void 0:D.started_ts)||(D==null?void 0:D.finished_ts)||(D==null?void 0:D.id);if(!ae)return;const xe=String(ae),Be=b.get(xe)||{key:xe,scheduled_ts:(D==null?void 0:D.scheduled_ts)||null,started_ts:null,finished_ts:null,statuses:new Set};!Be.scheduled_ts&&(D!=null&&D.scheduled_ts)&&(Be.scheduled_ts=D.scheduled_ts),D!=null&&D.started_ts&&(Be.started_ts=Be.started_ts==null?D.started_ts:Math.min(Be.started_ts,D.started_ts)),D!=null&&D.finished_ts&&(Be.finished_ts=Be.finished_ts==null?D.finished_ts:Math.max(Be.finished_ts,D.finished_ts)),D!=null&&D.status&&Be.statuses.add(String(D.status)),b.set(xe,Be)});const P=[];return b.forEach(D=>{const ae=Array.from(D.statuses).map(ot=>String(ot||"").trim().toLowerCase()).filter(Boolean);if(!ae.length||ae.some(ot=>ot==="running"||ot==="pending"||ot==="scheduled"))return;const Be=ae.some(ot=>["failed","failure","expired","timed out","timed_out","warning"].includes(ot)),Oe=ae.every(ot=>ot==="success"),Ye=Be?"Failed":Oe?"Success":"Failed";P.push({key:D.key,scheduled_ts:D.scheduled_ts,started_ts:D.started_ts,finished_ts:D.finished_ts,status:Ye})}),P},[Ve]),Hs=s.useMemo(()=>{const b=Ge==="asc"?1:-1,P=J;return[...Vs].sort((D,ae)=>{const xe=Ye=>P==="scheduled_ts"||P==="started_ts"||P==="finished_ts"?Number((Ye==null?void 0:Ye[P])||0):String((Ye==null?void 0:Ye[P])||""),Be=xe(D),Oe=xe(ae);return typeof Be=="number"&&typeof Oe=="number"?(Be-Oe)*b:String(Be).localeCompare(String(Oe))*b})},[Vs,J,Ge]),_s=b=>{J===b?He(Ge==="asc"?"desc":"asc"):(Te(b),He("asc"))},an=()=>e.jsx(m,{sx:{maxHeight:400,overflowY:"auto"},children:e.jsxs(Rt,{size:"small",children:[e.jsx(Bt,{children:e.jsxs(Ue,{children:[e.jsx(Q,{sortDirection:J==="scheduled_ts"?Ge:!1,children:e.jsx(Tt,{active:J==="scheduled_ts",direction:J==="scheduled_ts"?Ge:"asc",onClick:()=>_s("scheduled_ts"),children:"Scheduled"})}),e.jsx(Q,{sortDirection:J==="started_ts"?Ge:!1,children:e.jsx(Tt,{active:J==="started_ts",direction:J==="started_ts"?Ge:"asc",onClick:()=>_s("started_ts"),children:"Started"})}),e.jsx(Q,{sortDirection:J==="finished_ts"?Ge:!1,children:e.jsx(Tt,{active:J==="finished_ts",direction:J==="finished_ts"?Ge:"asc",onClick:()=>_s("finished_ts"),children:"Finished"})}),e.jsx(Q,{children:"Status"})]})}),e.jsxs(Nt,{children:[Hs.map(b=>e.jsxs(Ue,{children:[e.jsx(Q,{children:K(b.scheduled_ts)}),e.jsx(Q,{children:K(b.started_ts)}),e.jsx(Q,{children:K(b.finished_ts)}),e.jsx(Q,{children:Ws(b.status)})]},b.key)),Hs.length===0&&e.jsx(Ue,{children:e.jsx(Q,{colSpan:4,sx:{color:"#888"},children:"No runs in the last 30 days."})})]})]})}),[ks,Gs]=s.useState({}),Is=(ks==null?void 0:ks.result_counts)||{},js=s.useMemo(()=>{const b={pending:0,running:0,success:0,failed:0,expired:0};return pt.forEach(P=>{const D=String((P==null?void 0:P.job_status)||"").trim().toLowerCase();!D||D==="pending"||D==="scheduled"||D==="queued"?b.pending+=1:D==="running"?b.running+=1:D==="success"?b.success+=1:D==="expired"?b.expired+=1:D==="failed"||D==="failure"||D==="timed out"||D==="timed_out"||D==="warning"?b.failed+=1:b.pending+=1}),b},[pt]),Xt=s.useMemo(()=>{const b={pending:0,running:0,success:0,failed:0,expired:0};return Object.keys(b).forEach(P=>{const D=Number((Is||{})[P]??0),ae=js[P]??0;b[P]=D>0?D:ae}),b},[Is,js]),ln=s.useMemo(()=>({statusNode:_l}),[]),Vt=s.useCallback(b=>{oe(P=>P===b?null:b)},[]),Rs=s.useMemo(()=>[{id:"pending",type:"statusNode",position:{x:-420,y:170},data:{label:jt.pending.label,color:jt.pending.color,count:Xt.pending,Icon:jt.pending.Icon,onClick:()=>Vt("pending"),isActive:ct==="pending"},draggable:!1,selectable:!1},{id:"running",type:"statusNode",position:{x:0,y:0},data:{label:jt.running.label,color:jt.running.color,count:Xt.running,Icon:jt.running.Icon,onClick:()=>Vt("running"),isActive:ct==="running"},draggable:!1,selectable:!1},{id:"expired",type:"statusNode",position:{x:0,y:340},data:{label:jt.expired.label,color:jt.expired.color,count:Xt.expired,Icon:jt.expired.Icon,onClick:()=>Vt("expired"),isActive:ct==="expired"},draggable:!1,selectable:!1},{id:"success",type:"statusNode",position:{x:420,y:0},data:{label:jt.success.label,color:jt.success.color,count:Xt.success,Icon:jt.success.Icon,onClick:()=>Vt("success"),isActive:ct==="success"},draggable:!1,selectable:!1},{id:"failed",type:"statusNode",position:{x:420,y:340},data:{label:jt.failed.label,color:jt.failed.color,count:Xt.failed,Icon:jt.failed.Icon,onClick:()=>Vt("failed"),isActive:ct==="failed"},draggable:!1,selectable:!1}],[Xt,Vt,ct]),Ns=s.useMemo(()=>[{id:"pending-running",source:"pending",target:"running",sourceHandle:"right-top",targetHandle:"left-top",type:"smoothstep",animated:!0,className:"status-flow-edge"},{id:"pending-expired",source:"pending",target:"expired",sourceHandle:"right-bottom",targetHandle:"left-bottom",type:"smoothstep",animated:!0,className:"status-flow-edge"},{id:"running-success",source:"running",target:"success",sourceHandle:"right-top",targetHandle:"left-top",type:"smoothstep",animated:!0,className:"status-flow-edge"},{id:"running-failed",source:"running",target:"failed",sourceHandle:"right-bottom",targetHandle:"left-bottom",type:"smoothstep",animated:!0,className:"status-flow-edge"}],[]),Ts=()=>{var b;return e.jsxs(m,{sx:{bgcolor:"#2e2e2e",border:"1px solid #2a2a2a",borderRadius:1,mb:2},children:[e.jsx(vr,{styles:{"@keyframes statusFlowDash":{"0%":{strokeDashoffset:0},"100%":{strokeDashoffset:-24}},".status-flow-edge .react-flow__edge-path":{strokeDasharray:"10 6",animation:"statusFlowDash 1.2s linear infinite",strokeWidth:2,stroke:"#58a6ff"}}}),e.jsx(m,{sx:{height:380,p:3},children:e.jsx(lo,{nodes:Rs,edges:Ns,nodeTypes:ln,fitView:!0,fitViewOptions:{padding:.2},nodesDraggable:!1,nodesConnectable:!1,elementsSelectable:!1,panOnDrag:!1,zoomOnScroll:!1,zoomOnPinch:!1,panOnScroll:!1,zoomOnDoubleClick:!1,preventScrolling:!1,onNodeClick:(P,D)=>{D!=null&&D.id&&jt[D.id]&&Vt(D.id)},selectionOnDrag:!1,proOptions:{hideAttribution:!0},style:{background:"transparent"}})}),ct?e.jsxs(m,{sx:{mt:1,px:3,pb:3,display:"flex",alignItems:"center",gap:1.5},children:[e.jsxs($,{variant:"caption",sx:{color:"#aaa"},children:["Showing devices with ",((b=jt[ct])==null?void 0:b.label)||ct," results"]}),e.jsx(Z,{size:"small",sx:{color:"#58a6ff",textTransform:"none",p:0},onClick:()=>oe(null),children:"Clear Filter"})]}):null]})},As=s.useCallback((b="")=>{const P=String(b||"").toLowerCase();return P.endsWith(".ps1")?"powershell":P.endsWith(".bat")?"batch":P.endsWith(".sh")?"bash":P.endsWith(".yml")||P.endsWith(".yaml")?"yaml":"powershell"},[]),cn=s.useCallback((b,P)=>{try{return qt.highlight(b??"",qt.languages[P]||qt.languages.markup,P)}catch{return String(b||"")}},[]),qs=s.useCallback(async b=>{const P=Number(b||0);if(!P)return null;if(us.current.has(P))return us.current.get(P);try{const D=await fetch(`/api/device/activity/job/${P}`);if(!D.ok)throw new Error(`HTTP ${D.status}`);const ae=await D.json();return us.current.set(P,ae),ae}catch{return null}},[]),Js=s.useCallback(async(b,P="stdout")=>{if(!b)return;const D=P==="stderr"?"StdErr":"StdOut",xe=(Array.isArray(b.activities)?b.activities:[]).filter(Oe=>P==="stderr"?Oe.has_stderr:Oe.has_stdout);if(kt(`${D} - ${b.hostname||""}`),xt([]),ms(""),hs(!0),zt(!0),!xe.length){ms(`No ${D} available for this device.`),hs(!1);return}const Be=[];for(const Oe of xe){const Ye=Number(Oe.activity_id||Oe.id||0);if(!Ye)continue;const ot=await qs(Ye);if(!ot)continue;const Bs=P==="stderr"?ot.stderr||"":ot.stdout||"",pn=Oe.component_name||ot.script_name||ot.script_path||`Activity ${Ye}`;Be.push({key:`${Ye}-${P}`,title:pn,path:ot.script_path||"",lang:As(ot.script_path||""),content:Bs})}Be.length||ms(`No ${D} available for this device.`),xt(Be),hs(!1)},[As,qs]);s.useEffect(()=>{let b=!1;return(async()=>{var D,ae;if(o&&o.id){r(o.name||""),c(typeof o.name=="string"?o.name.trim():""),f(Array.isArray(o.targets)?o.targets:[]),C(o.schedule_type||((D=o.schedule)==null?void 0:D.type)||"immediately"),k(o.start_ts?Xs(Number(o.start_ts)*1e3).second(0):(ae=o.schedule)!=null&&ae.start?Xs(o.schedule.start).second(0):Xs().add(5,"minute").second(0)),j(!!o.duration_stop_enabled),R(o.expiration||"no_expire"),S(o.execution_context||"system"),de(o.credential_id?String(o.credential_id):""),(o.execution_context||"").toLowerCase()==="winrm"?w(o.use_service_account!==!1):w(!1);const xe=Array.isArray(o.components)?o.components:[],Be=await H(xe);b||(l(Be),yt({}))}else o||(c(""),l([]),yt({}),de(""),w(!0))})(),()=>{b=!0}},[o,H]);const dn=async()=>{Re(!0);try{const b=await fetch("/api/assembly/list?island=scripts");if(b.ok){const P=await b.json(),{root:D,map:ae}=No(P.items||[],P.folders||[]);je(D),O(ae)}else je([]),O({})}catch{je([]),O({})}try{const b=await fetch("/api/assembly/list?island=workflows");if(b.ok){const P=await b.json(),{root:D,map:ae}=Il(P.items||[],P.folders||[]);g(D),we(ae)}else g([]),we({})}catch{g([]),we({})}try{const b=await fetch("/api/assembly/list?island=ansible");if(b.ok){const P=await b.json(),{root:D,map:ae}=kl(P.items||[],P.folders||[]);G(D),Ce(ae)}else G([]),Ce({})}catch{G([]),Ce({})}},un=s.useCallback(async()=>{const P=(Ae==="scripts"?V:Ae==="ansible"?ie:L)[Ee];if(!P||P.isFolder)return!1;if(Ae==="workflows"&&P.workflow)return alert("Workflows within Scheduled Jobs are not supported yet"),!1;if(Ae==="scripts"||Ae==="ansible"){const D=Ae==="scripts"?"script":"ansible",ae=P.path||P.id||"",{doc:xe,normalizedPath:Be}=await N(D,ae),Oe=(xe==null?void 0:xe.assembly)||{},Ye=(Oe==null?void 0:Oe.variables)||(xe==null?void 0:xe.variables)||[],ot=eo(Ye,[],{});return l(Bs=>[...Bs,{type:D,path:Be||ae,name:(Oe==null?void 0:Oe.name)||P.fileName||P.label,description:(Oe==null?void 0:Oe.description)||Be||ae,variables:ot,localId:Ot()}]),Ne(""),!0}return Ne(""),!1},[Ae,V,ie,L,Ee,N,Ot]),xs=async()=>{at(!0),bt({});try{const b=await fetch("/api/agents");if(b.ok){const P=await b.json(),D=Object.values(P||{}).map(ae=>({hostname:ae.hostname||ae.agent_hostname||ae.id||"unknown",display:ae.hostname||ae.agent_hostname||ae.id||"unknown",online:!!ae.collector_active}));D.sort((ae,xe)=>ae.display.localeCompare(xe.display)),Pe(D)}else Pe([])}catch{Pe([])}},Bo=async()=>{if(F&&!(x==="winrm"&&me)&&!ce){alert("Please select a credential for this execution context.");return}const b={};if(p.forEach(ae=>{!ae||!ae.localId||(Array.isArray(ae.variables)?ae.variables:[]).forEach(xe=>{if(!xe||!xe.name||!xe.required||(xe.type||"string")==="boolean")return;const Be=xe.value;(Be==null||Be==="")&&(b[ae.localId]||(b[ae.localId]={}),b[ae.localId][xe.name]="Required")})}),Object.keys(b).length){yt(b),d(1),alert("Please fill in all required variable values.");return}yt({});const P=Y(p),D={name:u,components:P,targets:h,schedule:{type:y,start:y!=="immediately"?(()=>{var ae;try{const xe=((ae=I==null?void 0:I.toDate)==null?void 0:ae.call(I))||new Date(I);return xe.setSeconds(0,0),xe.toISOString()}catch{return I}})():null},duration:{stopAfterEnabled:v,expiration:B},execution_context:x,credential_id:F&&!me&&ce?Number(ce):null,use_service_account:x==="winrm"?!!me:!1};try{const ae=await fetch(o&&o.id?`/api/scheduled_jobs/${o.id}`:"/api/scheduled_jobs",{method:o&&o.id?"PUT":"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(D)}),xe=await ae.json();if(!ae.ok)throw new Error(xe.error||`HTTP ${ae.status}`);t&&t(xe.job||D),n&&n()}catch(ae){alert(String(ae.message||ae))}},Dn=s.useMemo(()=>{const b=[{key:"name",label:"Job Name"},{key:"components",label:"Assemblies"},{key:"targets",label:"Targets"},{key:"schedule",label:"Schedule"},{key:"context",label:"Execution Context"}];return Me&&b.push({key:"history",label:"Job History"}),b},[Me]);return e.jsxs(Qe,{sx:{m:2,p:0,bgcolor:"#1e1e1e",overflow:"auto"},elevation:2,children:[e.jsxs(m,{sx:{p:2,pb:1},children:[e.jsxs($,{variant:"h6",sx:{color:"#58a6ff",mb:0},children:["Create a Scheduled Job",i&&e.jsx(m,{component:"span",sx:{color:"#aaa",fontSize:"inherit",fontWeight:400},children:`: "${i}"`})]}),e.jsx($,{variant:"body2",sx:{color:"#aaa"},children:"Configure advanced schedulable automation jobs for one or more devices."})]}),e.jsxs(m,{sx:{display:"flex",alignItems:"center",justifyContent:"space-between",borderBottom:"1px solid #333",px:2},children:[e.jsx(Us,{value:a,onChange:(b,P)=>d(P),sx:{minHeight:36},children:Dn.map((b,P)=>e.jsx(ps,{label:b.label,sx:{minHeight:36}},b.key))}),e.jsxs(m,{sx:{display:"flex",alignItems:"center",gap:1,mb:1},children:[e.jsx(Z,{onClick:n,sx:{color:"#58a6ff",textTransform:"none"},children:"Cancel"}),e.jsx(Z,{variant:"outlined",onClick:()=>ye?ge(!0):null,startIcon:e.jsx(ts,{}),disabled:!ye,sx:{color:ye?"#58a6ff":"#666",borderColor:ye?"#58a6ff":"#444",textTransform:"none"},children:o&&o.id?"Save Changes":"Create Job"})]})]}),e.jsxs(m,{sx:{p:2},children:[a===0&&e.jsxs(m,{children:[e.jsx(ws,{title:"Name"}),e.jsx(Ie,{fullWidth:!1,sx:{width:{xs:"100%",sm:"60%",md:"50%"},"& .MuiOutlinedInput-root":{bgcolor:"#1b1b1b"},"& .MuiInputBase-input":{color:"#e6edf3"}},placeholder:"Example Job Name",value:u,onChange:b=>r(b.target.value),onBlur:b=>c(b.target.value.trim()),InputLabelProps:{shrink:!0},error:u.trim().length===0,helperText:u.trim().length===0?"Job name is required":""})]}),a===1&&e.jsxs(m,{children:[e.jsx(ws,{title:"Assemblies",action:e.jsx(Z,{size:"small",startIcon:e.jsx(ts,{}),onClick:dn,sx:{color:"#58a6ff",borderColor:"#58a6ff"},variant:"outlined",children:"Add Assembly"})}),p.length===0&&e.jsx($,{variant:"body2",sx:{color:"#888"},children:"No assemblies added yet."}),p.map(b=>e.jsx(Nl,{comp:b,onRemove:ne,onVariableChange:se,errors:It[b.localId]||{}},b.localId||`${b.type}-${b.path}`)),p.length===0&&e.jsx($,{variant:"caption",sx:{color:"#ff6666"},children:"At least one assembly is required."})]}),a===2&&e.jsxs(m,{children:[e.jsx(ws,{title:"Targets",action:e.jsx(Z,{size:"small",startIcon:e.jsx(ts,{}),onClick:xs,sx:{color:"#58a6ff",borderColor:"#58a6ff"},variant:"outlined",children:"Add Target"})}),e.jsxs(Rt,{size:"small",children:[e.jsx(Bt,{children:e.jsxs(Ue,{children:[e.jsx(Q,{children:"Name"}),e.jsx(Q,{children:"Status"}),e.jsx(Q,{align:"right",children:"Actions"})]})}),e.jsxs(Nt,{children:[h.map(b=>e.jsxs(Ue,{hover:!0,children:[e.jsx(Q,{children:b}),e.jsx(Q,{children:"—"}),e.jsx(Q,{align:"right",children:e.jsx(nt,{size:"small",onClick:()=>f(P=>P.filter(D=>D!==b)),sx:{color:"#ff6666"},children:e.jsx($s,{fontSize:"small"})})})]},b)),h.length===0&&e.jsx(Ue,{children:e.jsx(Q,{colSpan:3,sx:{color:"#888"},children:"No targets selected."})})]})]}),h.length===0&&e.jsx($,{variant:"caption",sx:{color:"#ff6666"},children:"At least one target is required."})]}),a===3&&e.jsxs(m,{children:[e.jsx(ws,{title:"Schedule"}),e.jsxs(m,{sx:{display:"flex",gap:2,flexWrap:"wrap"},children:[e.jsxs(m,{sx:{minWidth:260},children:[e.jsx($,{variant:"subtitle2",sx:{color:"#ccc",mb:.5},children:"Recurrence"}),e.jsxs(wt,{size:"small",fullWidth:!0,value:y,onChange:b=>C(b.target.value),children:[e.jsx(fe,{value:"immediately",children:"Immediately"}),e.jsx(fe,{value:"once",children:"At selected date and time"}),e.jsx(fe,{value:"every_5_minutes",children:"Every 5 Minutes"}),e.jsx(fe,{value:"every_10_minutes",children:"Every 10 Minutes"}),e.jsx(fe,{value:"every_15_minutes",children:"Every 15 Minutes"}),e.jsx(fe,{value:"every_30_minutes",children:"Every 30 Minutes"}),e.jsx(fe,{value:"every_hour",children:"Every Hour"}),e.jsx(fe,{value:"daily",children:"Daily"}),e.jsx(fe,{value:"weekly",children:"Weekly"}),e.jsx(fe,{value:"monthly",children:"Monthly"}),e.jsx(fe,{value:"yearly",children:"Yearly"})]})]}),y!=="immediately"&&e.jsxs(m,{sx:{minWidth:280},children:[e.jsx($,{variant:"subtitle2",sx:{color:"#ccc",mb:.5},children:"Start date and execution time"}),e.jsx(yr,{dateAdapter:jr,children:e.jsx(wr,{value:I,onChange:b=>k(b!=null&&b.second?b.second(0):b),views:["year","month","day","hours","minutes"],format:"YYYY-MM-DD hh:mm A",slotProps:{textField:{size:"small"}}})})]})]}),e.jsx(In,{sx:{my:2,borderColor:"#333"}}),e.jsx(ws,{title:"Duration"}),e.jsx(bs,{control:e.jsx(At,{checked:v,onChange:b=>j(b.target.checked)}),label:e.jsx($,{variant:"body2",children:"Stop running this job after"})}),e.jsxs(m,{sx:{mt:1,minWidth:260,width:260},children:[e.jsx($,{variant:"subtitle2",sx:{color:"#ccc",mb:.5},children:"Expiration"}),e.jsxs(wt,{size:"small",fullWidth:!0,value:B,onChange:b=>R(b.target.value),children:[e.jsx(fe,{value:"no_expire",children:"Does not Expire"}),e.jsx(fe,{value:"30m",children:"30 Minutes"}),e.jsx(fe,{value:"1h",children:"1 Hour"}),e.jsx(fe,{value:"2h",children:"2 Hours"}),e.jsx(fe,{value:"6h",children:"6 Hours"}),e.jsx(fe,{value:"12h",children:"12 Hours"}),e.jsx(fe,{value:"1d",children:"1 Day"}),e.jsx(fe,{value:"2d",children:"2 Days"}),e.jsx(fe,{value:"3d",children:"3 Days"})]})]})]}),a===4&&e.jsxs(m,{children:[e.jsx(ws,{title:"Execution Context"}),e.jsxs(wt,{size:"small",value:x,onChange:b=>te(b.target.value),sx:{minWidth:320},children:[e.jsx(fe,{value:"system",children:"Run on agent as SYSTEM (device-local)"}),e.jsx(fe,{value:"current_user",children:"Run on agent as logged-in user (device-local)"}),e.jsx(fe,{value:"ssh",children:"Run from server via SSH (remote)"}),e.jsx(fe,{value:"winrm",children:"Run from server via WinRM (remote)"})]}),F&&e.jsxs(m,{sx:{mt:2,display:"flex",alignItems:"center",gap:1.5,flexWrap:"wrap"},children:[x==="winrm"&&e.jsx(bs,{control:e.jsx(At,{checked:me,onChange:b=>{const P=b.target.checked;w(P),P?de(""):!ce&&ee.length&&de(String(ee[0].id))}}),label:"Use Configured svcBorealis Account"}),e.jsxs(Ht,{size:"small",sx:{minWidth:320},disabled:U||!ee.length||x==="winrm"&&me,children:[e.jsx(Gt,{sx:{color:"#aaa"},children:"Credential"}),e.jsx(wt,{value:ce,label:"Credential",onChange:b=>de(b.target.value),sx:{bgcolor:"#1f1f1f",color:"#fff"},children:ee.map(b=>e.jsx(fe,{value:String(b.id),children:b.name},b.id))})]}),e.jsx(Z,{size:"small",variant:"outlined",startIcon:e.jsx(Ss,{fontSize:"small"}),onClick:W,disabled:U,sx:{color:"#58a6ff",borderColor:"#58a6ff"},children:"Refresh"}),U&&e.jsx(Mt,{size:18,sx:{color:"#58a6ff"}}),!U&&ue&&e.jsx($,{variant:"body2",sx:{color:"#ff8080"},children:ue}),x==="winrm"&&me&&e.jsx($,{variant:"body2",sx:{color:"#aaa"},children:"Runs with the agent's svcBorealis account."}),!U&&!ue&&!ee.length&&!(x==="winrm"&&me)&&e.jsxs($,{variant:"body2",sx:{color:"#ff8080"},children:["No ",x==="winrm"?"WinRM":"SSH"," credentials available. Create one under Access Management > Credentials."]})]})]}),Me&&a===Dn.findIndex(b=>b.key==="history")&&e.jsxs(m,{children:[e.jsxs(m,{sx:{display:"flex",justifyContent:"space-between",alignItems:"center"},children:[e.jsx($,{variant:"h6",sx:{color:"#58a6ff"},children:"Job History"}),e.jsx(Z,{size:"small",variant:"outlined",sx:{color:"#ff6666",borderColor:"#ff6666",textTransform:"none"},onClick:async()=>{try{await fetch(`/api/scheduled_jobs/${o.id}/runs`,{method:"DELETE"}),await Kt()}catch{}},children:"Clear Job History"})]}),e.jsx($,{variant:"caption",sx:{color:"#aaa"},children:"Showing the last 30 days of runs."}),e.jsx(m,{sx:{mt:2},children:e.jsx(Ts,{})}),e.jsxs(m,{sx:{mt:2},children:[e.jsx($,{variant:"subtitle1",sx:{color:"#7db7ff",mb:.5},children:"Devices"}),e.jsx($,{variant:"caption",sx:{color:"#aaa"},children:"Devices targeted by this scheduled job. Individual job history is listed here."}),e.jsxs(Rt,{size:"small",children:[e.jsx(Bt,{children:e.jsx(Ue,{children:Cl.map(b=>e.jsx(Q,{children:e.jsxs(m,{sx:{display:"flex",alignItems:"center",gap:.5},children:[e.jsx(Tt,{active:_e===b.key,direction:_e===b.key?Xe:"asc",onClick:()=>_(b.key),children:b.label}),e.jsx(nt,{size:"small",onClick:P=>ss(P,b.key),sx:{color:Yt(b.key)?"#58a6ff":"#666"},children:e.jsx(Rn,{fontSize:"inherit"})})]})},b.key))})}),e.jsxs(Nt,{children:[re.map((b,P)=>e.jsxs(Ue,{hover:!0,children:[e.jsx(Q,{children:b.hostname}),e.jsxs(Q,{children:[e.jsx("span",{style:{display:"inline-block",width:10,height:10,borderRadius:10,background:b.online?"#00d18c":"#ff4f4f",marginRight:8,verticalAlign:"middle"}}),b.online?"Online":"Offline"]}),e.jsx(Q,{children:b.site||""}),e.jsx(Q,{children:K(b.ran_on)}),e.jsx(Q,{children:Ws(b.job_status)}),e.jsx(Q,{children:e.jsxs(m,{sx:{display:"flex",gap:1},children:[b.has_stdout?e.jsx(Z,{size:"small",sx:{color:"#58a6ff",textTransform:"none",minWidth:0,p:0},onClick:D=>{D.stopPropagation(),Js(b,"stdout")},children:"StdOut"}):null,b.has_stderr?e.jsx(Z,{size:"small",sx:{color:"#ff4f4f",textTransform:"none",minWidth:0,p:0},onClick:D=>{D.stopPropagation(),Js(b,"stderr")},children:"StdErr"}):null]})})]},`${b.hostname}-${P}`)),re.length===0&&e.jsx(Ue,{children:e.jsx(Q,{colSpan:6,sx:{color:"#888"},children:"No targets found for this job."})})]})]}),e.jsx(Et,{anchorEl:ht,open:!!ht,onClose:A,disableAutoFocusItem:!0,PaperProps:{sx:{bgcolor:"#1e1e1e",color:"#e6edf3",minWidth:240}},children:e.jsxs(m,{sx:{p:1.5,display:"flex",flexDirection:"column",gap:1},children:[he(),e.jsxs(m,{sx:{display:"flex",justifyContent:"space-between",gap:1},children:[e.jsx(Z,{size:"small",sx:{color:"#ff6666",textTransform:"none"},onClick:le,children:"Clear"}),e.jsx(Z,{size:"small",sx:{color:"#58a6ff",textTransform:"none"},onClick:q,children:"Apply"})]})]})})]}),e.jsxs(m,{sx:{mt:2},children:[e.jsx($,{variant:"subtitle1",sx:{color:"#7db7ff",mb:.5},children:"Past Job History"}),e.jsx($,{variant:"caption",sx:{color:"#aaa"},children:"Historical job history summaries. Detailed job history is not recorded."}),e.jsx(m,{sx:{mt:1},children:an()})]})]})]}),e.jsxs(Ze,{open:fs,onClose:()=>zt(!1),fullWidth:!0,maxWidth:"md",PaperProps:{sx:{bgcolor:"#121212",color:"#fff"}},children:[e.jsx(et,{children:Ft}),e.jsxs(rt,{dividers:!0,children:[ns?e.jsx($,{variant:"body2",sx:{color:"#888"},children:"Loading output…"}):null,!ns&&Cs?e.jsx($,{variant:"body2",sx:{color:"#888"},children:Cs}):null,!ns&&!Cs?qe.map(b=>e.jsxs(m,{sx:{mb:2},children:[e.jsx($,{variant:"subtitle2",sx:{color:"#7db7ff"},children:b.title}),b.path?e.jsx($,{variant:"caption",sx:{color:"#888",display:"block",mb:.5},children:b.path}):null,e.jsx(m,{sx:{border:"1px solid #333",borderRadius:1,bgcolor:"#1e1e1e"},children:e.jsx(En,{value:b.content??"",onValueChange:()=>{},highlight:P=>cn(P,b.lang),padding:12,style:{fontFamily:'ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace',fontSize:12,color:"#e6edf3",minHeight:160},textareaProps:{readOnly:!0}})})]},b.key)):null]}),e.jsx(tt,{children:e.jsx(Z,{onClick:()=>zt(!1),sx:{color:"#58a6ff"},children:"Close"})})]}),e.jsxs(Ze,{open:be,onClose:()=>Re(!1),fullWidth:!0,maxWidth:"md",PaperProps:{sx:{bgcolor:"#121212",color:"#fff"}},children:[e.jsx(et,{children:"Select an Assembly"}),e.jsxs(rt,{children:[e.jsxs(m,{sx:{display:"flex",gap:2,mb:1},children:[e.jsx(Z,{size:"small",variant:Ae==="scripts"?"outlined":"text",onClick:()=>Le("scripts"),sx:{textTransform:"none",color:"#58a6ff",borderColor:"#58a6ff"},children:"Scripts"}),e.jsx(Z,{size:"small",variant:Ae==="ansible"?"outlined":"text",onClick:()=>Le("ansible"),sx:{textTransform:"none",color:"#58a6ff",borderColor:"#58a6ff"},children:"Ansible"}),e.jsx(Z,{size:"small",variant:Ae==="workflows"?"outlined":"text",onClick:()=>Le("workflows"),sx:{textTransform:"none",color:"#58a6ff",borderColor:"#58a6ff"},children:"Workflows"})]}),Ae==="scripts"&&e.jsx(Qe,{sx:{p:1,bgcolor:"#1e1e1e",maxHeight:400,overflow:"auto"},children:e.jsx(vs,{onItemSelectionToggle:(b,P)=>{const D=V[P];D&&!D.isFolder&&Ne(P)},children:Fe.length?Fe.map(b=>e.jsx(ys,{itemId:b.id,label:b.label,children:b.children&&b.children.length?nn(b.children,V):null},b.id)):e.jsx($,{variant:"body2",sx:{color:"#888",p:1},children:"No scripts found."})})}),Ae==="workflows"&&e.jsx(Qe,{sx:{p:1,bgcolor:"#1e1e1e",maxHeight:400,overflow:"auto"},children:e.jsx(vs,{onItemSelectionToggle:(b,P)=>{const D=L[P];D&&!D.isFolder&&Ne(P)},children:M.length?M.map(b=>e.jsx(ys,{itemId:b.id,label:b.label,children:b.children&&b.children.length?nn(b.children,L):null},b.id)):e.jsx($,{variant:"body2",sx:{color:"#888",p:1},children:"No workflows found."})})}),Ae==="ansible"&&e.jsx(Qe,{sx:{p:1,bgcolor:"#1e1e1e",maxHeight:400,overflow:"auto"},children:e.jsx(vs,{onItemSelectionToggle:(b,P)=>{const D=ie[P];D&&!D.isFolder&&Ne(P)},children:T.length?T.map(b=>e.jsx(ys,{itemId:b.id,label:b.label,children:b.children&&b.children.length?nn(b.children,ie):null},b.id)):e.jsx($,{variant:"body2",sx:{color:"#888",p:1},children:"No playbooks found."})})})]}),e.jsxs(tt,{children:[e.jsx(Z,{onClick:()=>Re(!1),sx:{color:"#58a6ff"},children:"Close"}),e.jsx(Z,{onClick:async()=>{await un()&&Re(!1)},sx:{color:"#58a6ff"},disabled:!Ee,children:"Add"})]})]}),e.jsxs(Ze,{open:Ke,onClose:()=>at(!1),fullWidth:!0,maxWidth:"md",PaperProps:{sx:{bgcolor:"#121212",color:"#fff"}},children:[e.jsx(et,{children:"Select Targets"}),e.jsxs(rt,{children:[e.jsx(m,{sx:{mb:2,display:"flex",gap:2},children:e.jsx(Ie,{size:"small",placeholder:"Search devices...",value:vt,onChange:b=>Ut(b.target.value),sx:{flex:1,"& .MuiOutlinedInput-root":{bgcolor:"#1b1b1b"},"& .MuiInputBase-input":{color:"#e6edf3"}}})}),e.jsxs(Rt,{size:"small",children:[e.jsx(Bt,{children:e.jsxs(Ue,{children:[e.jsx(Q,{width:40}),e.jsx(Q,{children:"Name"}),e.jsx(Q,{children:"Status"})]})}),e.jsxs(Nt,{children:[ut.filter(b=>b.display.toLowerCase().includes(vt.toLowerCase())).map(b=>e.jsxs(Ue,{hover:!0,onClick:()=>bt(P=>({...P,[b.hostname]:!P[b.hostname]})),children:[e.jsx(Q,{children:e.jsx(At,{size:"small",checked:!!gt[b.hostname],onChange:P=>bt(D=>({...D,[b.hostname]:P.target.checked}))})}),e.jsx(Q,{children:b.display}),e.jsxs(Q,{children:[e.jsx("span",{style:{display:"inline-block",width:10,height:10,borderRadius:10,background:b.online?"#00d18c":"#ff4f4f",marginRight:8,verticalAlign:"middle"}}),b.online?"Online":"Offline"]})]},b.hostname)),ut.length===0&&e.jsx(Ue,{children:e.jsx(Q,{colSpan:3,sx:{color:"#888"},children:"No devices available."})})]})]})]}),e.jsxs(tt,{children:[e.jsx(Z,{onClick:()=>at(!1),sx:{color:"#58a6ff"},children:"Cancel"}),e.jsx(Z,{onClick:()=>{const b=Object.keys(gt).filter(P=>gt[P]);f(P=>Array.from(new Set([...P,...b]))),at(!1)},sx:{color:"#58a6ff"},children:"Add Selected"})]})]}),e.jsxs(Ze,{open:ve,onClose:()=>ge(!1),PaperProps:{sx:{bgcolor:"#121212",color:"#fff"}},children:[e.jsx(et,{sx:{pb:0},children:o&&o.id?"Are you sure you wish to save changes?":"Are you sure you wish to create this Job?"}),e.jsxs(tt,{sx:{p:2},children:[e.jsx(Z,{onClick:()=>ge(!1),sx:{color:"#58a6ff"},children:"Cancel"}),e.jsx(Z,{onClick:()=>{ge(!1),Bo()},variant:"outlined",sx:{color:"#58a6ff",borderColor:"#58a6ff"},children:"Confirm"})]})]})]})}const Al=[{value:"machine",label:"Machine"},{value:"domain",label:"Domain"},{value:"token",label:"Token"}],Bl=[{value:"ssh",label:"SSH"},{value:"winrm",label:"WinRM"}],Ol=[{value:"",label:"None"},{value:"sudo",label:"sudo"},{value:"su",label:"su"},{value:"runas",label:"runas"},{value:"enable",label:"enable"}];function jn(){return{name:"",description:"",site_id:"",credential_type:"machine",connection_type:"ssh",username:"",password:"",private_key:"",private_key_passphrase:"",become_method:"",become_username:"",become_password:""}}function to(n){if(n===null||typeof n>"u"||n==="")return"";const t=Number(n);return Number.isNaN(t)?"":String(t)}function Pl({open:n,mode:t="create",credential:o,onClose:a,onSaved:d}){const u=t==="edit"&&o&&o.id,[r,i]=s.useState(jn),[c,p]=s.useState([]),[l,h]=s.useState(!1),[f,y]=s.useState(""),[C,I]=s.useState(!1),[k,v]=s.useState(!1),[j,B]=s.useState(!1),[R,x]=s.useState(!1),[S,z]=s.useState(!1),[E,U]=s.useState(!1),[X,ue]=s.useState(!1),[Se,ce]=s.useState(!1),[de,me]=s.useState(!1),w=o==null?void 0:o.id;s.useEffect(()=>{if(!n)return;let V=!1;return(async()=>{try{const O=await fetch("/api/sites");if(!O.ok)return;const M=await O.json();if(V)return;const g=Array.isArray(M==null?void 0:M.sites)?M.sites.filter(L=>L&&L.id).map(L=>({id:L.id,name:L.name||`Site ${L.id}`})):[];g.sort((L,we)=>String(L.name||"").localeCompare(String(we.name||""))),p(g)}catch{V||p([])}})(),()=>{V=!0}},[n]),s.useEffect(()=>{if(n)if(y(""),I(!1),v(!1),B(!1),x(!1),z(!1),U(!1),ue(!1),ce(!1),u&&w){const V=O=>{const M=jn();M.name=(O==null?void 0:O.name)||"",M.description=(O==null?void 0:O.description)||"",M.site_id=to(O==null?void 0:O.site_id),M.credential_type=((O==null?void 0:O.credential_type)||"machine").toLowerCase(),M.connection_type=((O==null?void 0:O.connection_type)||"ssh").toLowerCase(),M.username=(O==null?void 0:O.username)||"",M.become_method=((O==null?void 0:O.become_method)||"").toLowerCase(),M.become_username=(O==null?void 0:O.become_username)||"",i(M)};o!=null&&o.name?V(o):(me(!0),(async()=>{try{const O=await fetch(`/api/credentials/${w}`);if(O.ok){const M=await O.json();V((M==null?void 0:M.credential)||{})}}catch{}finally{me(!1)}})())}else i(jn())},[n,u,w,o]);const W=s.useMemo(()=>({hasPassword:!!(o!=null&&o.has_password),hasPrivateKey:!!(o!=null&&o.has_private_key),hasPrivateKeyPassphrase:!!(o!=null&&o.has_private_key_passphrase),hasBecomePassword:!!(o!=null&&o.has_become_password)}),[o]),F=l||de,te=V=>O=>{var g;const M=((g=O==null?void 0:O.target)==null?void 0:g.value)??"";i(L=>({...L,[V]:M})),V==="password"?(I(!0),z(!1)):V==="private_key"?(v(!0),U(!1)):V==="private_key_passphrase"?(B(!0),ue(!1)):V==="become_password"&&(x(!0),ce(!1))},ee=async V=>{var M;const O=(M=V.target.files)==null?void 0:M[0];if(O)try{const g=await O.text();i(L=>({...L,private_key:g})),v(!0),U(!1)}catch{y("Unable to read private key file.")}finally{V.target.value=""}},be=()=>{l||a&&a()},Re=()=>r.name.trim()?(y(""),!0):(y("Credential name is required."),!1),Ae=()=>{const V={name:r.name.trim(),description:r.description.trim(),credential_type:(r.credential_type||"machine").toLowerCase(),connection_type:(r.connection_type||"ssh").toLowerCase(),username:r.username.trim(),become_method:r.become_method.trim(),become_username:r.become_username.trim()},O=to(r.site_id);return O?V.site_id=Number(O):V.site_id=null,C&&(V.password=r.password),k&&(V.private_key=r.private_key),j&&(V.private_key_passphrase=r.private_key_passphrase),R&&(V.become_password=r.become_password),S&&(V.clear_password=!0),E&&(V.clear_private_key=!0),X&&(V.clear_private_key_passphrase=!0),Se&&(V.clear_become_password=!0),V},Le=async()=>{if(!Re())return;h(!0),y("");const V=Ae();try{const O=await fetch(u?`/api/credentials/${w}`:"/api/credentials",{method:u?"PUT":"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(V)}),M=await O.json();if(!O.ok)throw new Error((M==null?void 0:M.error)||`Request failed (${O.status})`);d&&d((M==null?void 0:M.credential)||null)}catch(O){y(String(O.message||O))}finally{h(!1)}},Fe=u?"Edit Credential":"Create Credential",je={fontSize:12,color:"#8a8a8a",mt:.5};return e.jsxs(Ze,{open:n,onClose:be,maxWidth:"md",fullWidth:!0,PaperProps:{sx:{bgcolor:"#121212",color:"#fff"}},children:[e.jsx(et,{sx:{pb:1},children:Fe}),e.jsxs(rt,{dividers:!0,sx:{display:"flex",flexDirection:"column",gap:2},children:[de&&e.jsxs(m,{sx:{display:"flex",alignItems:"center",gap:1,color:"#aaa"},children:[e.jsx(Mt,{size:18,sx:{color:"#58a6ff"}}),e.jsx($,{variant:"body2",children:"Loading credential details…"})]}),f&&e.jsx(m,{sx:{bgcolor:"#2c1c1c",border:"1px solid #663939",borderRadius:1,p:1},children:e.jsx($,{variant:"body2",sx:{color:"#ff8080"},children:f})}),e.jsx(Ie,{label:"Name",value:r.name,onChange:te("name"),required:!0,disabled:F,sx:{"& .MuiInputBase-root":{bgcolor:"#1f1f1f",color:"#fff"},"& label":{color:"#888"}}}),e.jsx(Ie,{label:"Description",value:r.description,onChange:te("description"),disabled:F,multiline:!0,minRows:2,sx:{"& .MuiInputBase-root":{bgcolor:"#1f1f1f",color:"#fff"},"& label":{color:"#888"}}}),e.jsxs(m,{sx:{display:"flex",flexWrap:"wrap",gap:2},children:[e.jsxs(Ht,{sx:{minWidth:220},size:"small",disabled:F,children:[e.jsx(Gt,{sx:{color:"#aaa"},children:"Site"}),e.jsxs(wt,{value:r.site_id,label:"Site",onChange:te("site_id"),sx:{bgcolor:"#1f1f1f",color:"#fff"},children:[e.jsx(fe,{value:"",children:"(None)"}),c.map(V=>e.jsx(fe,{value:String(V.id),children:V.name},V.id))]})]}),e.jsxs(Ht,{sx:{minWidth:180},size:"small",disabled:F,children:[e.jsx(Gt,{sx:{color:"#aaa"},children:"Credential Type"}),e.jsx(wt,{value:r.credential_type,label:"Credential Type",onChange:te("credential_type"),sx:{bgcolor:"#1f1f1f",color:"#fff"},children:Al.map(V=>e.jsx(fe,{value:V.value,children:V.label},V.value))})]}),e.jsxs(Ht,{sx:{minWidth:180},size:"small",disabled:F,children:[e.jsx(Gt,{sx:{color:"#aaa"},children:"Connection"}),e.jsx(wt,{value:r.connection_type,label:"Connection",onChange:te("connection_type"),sx:{bgcolor:"#1f1f1f",color:"#fff"},children:Bl.map(V=>e.jsx(fe,{value:V.value,children:V.label},V.value))})]})]}),e.jsx(Ie,{label:"Username",value:r.username,onChange:te("username"),disabled:F,sx:{"& .MuiInputBase-root":{bgcolor:"#1f1f1f",color:"#fff"},"& label":{color:"#888"}}}),e.jsxs(m,{sx:{display:"flex",alignItems:"center",gap:1},children:[e.jsx(Ie,{label:"Password",type:"password",value:r.password,onChange:te("password"),disabled:F,sx:{flex:1,"& .MuiInputBase-root":{bgcolor:"#1f1f1f",color:"#fff"},"& label":{color:"#888"}}}),u&&W.hasPassword&&!C&&!S&&e.jsx(st,{title:"Clear stored password",children:e.jsx(nt,{size:"small",onClick:()=>z(!0),sx:{color:"#ff8080"},children:e.jsx(Ks,{fontSize:"small"})})})]}),u&&W.hasPassword&&!C&&!S&&e.jsx($,{sx:je,children:"Stored password will remain unless you change or clear it."}),S&&e.jsx($,{sx:{...je,color:"#ffaaaa"},children:"Password will be removed when saving."}),e.jsxs(m,{sx:{display:"flex",gap:1,alignItems:"flex-start"},children:[e.jsx(Ie,{label:"SSH Private Key",value:r.private_key,onChange:te("private_key"),disabled:F,multiline:!0,minRows:4,maxRows:12,sx:{flex:1,"& .MuiInputBase-root":{bgcolor:"#1f1f1f",color:"#fff",fontFamily:"monospace"},"& label":{color:"#888"}}}),e.jsxs(Z,{variant:"outlined",component:"label",startIcon:e.jsx(go,{}),disabled:F,sx:{alignSelf:"center",borderColor:"#58a6ff",color:"#58a6ff"},children:["Upload",e.jsx("input",{type:"file",hidden:!0,accept:".pem,.key,.txt",onChange:ee})]}),u&&W.hasPrivateKey&&!k&&!E&&e.jsx(st,{title:"Clear stored private key",children:e.jsx(nt,{size:"small",onClick:()=>U(!0),sx:{color:"#ff8080"},children:e.jsx(Ks,{fontSize:"small"})})})]}),u&&W.hasPrivateKey&&!k&&!E&&e.jsx($,{sx:je,children:"Private key is stored. Upload or paste a new one to replace, or clear it."}),E&&e.jsx($,{sx:{...je,color:"#ffaaaa"},children:"Private key will be removed when saving."}),e.jsxs(m,{sx:{display:"flex",alignItems:"center",gap:1},children:[e.jsx(Ie,{label:"Private Key Passphrase",type:"password",value:r.private_key_passphrase,onChange:te("private_key_passphrase"),disabled:F,sx:{flex:1,"& .MuiInputBase-root":{bgcolor:"#1f1f1f",color:"#fff"},"& label":{color:"#888"}}}),u&&W.hasPrivateKeyPassphrase&&!j&&!X&&e.jsx(st,{title:"Clear stored passphrase",children:e.jsx(nt,{size:"small",onClick:()=>ue(!0),sx:{color:"#ff8080"},children:e.jsx(Ks,{fontSize:"small"})})})]}),u&&W.hasPrivateKeyPassphrase&&!j&&!X&&e.jsx($,{sx:je,children:"A passphrase is stored for this key."}),X&&e.jsx($,{sx:{...je,color:"#ffaaaa"},children:"Key passphrase will be removed when saving."}),e.jsxs(m,{sx:{display:"flex",gap:2,flexWrap:"wrap"},children:[e.jsxs(Ht,{sx:{minWidth:180},size:"small",disabled:F,children:[e.jsx(Gt,{sx:{color:"#aaa"},children:"Privilege Escalation"}),e.jsx(wt,{value:r.become_method,label:"Privilege Escalation",onChange:te("become_method"),sx:{bgcolor:"#1f1f1f",color:"#fff"},children:Ol.map(V=>e.jsx(fe,{value:V.value,children:V.label},V.value||"none"))})]}),e.jsx(Ie,{label:"Escalation Username",value:r.become_username,onChange:te("become_username"),disabled:F,sx:{flex:1,minWidth:200,"& .MuiInputBase-root":{bgcolor:"#1f1f1f",color:"#fff"},"& label":{color:"#888"}}})]}),e.jsxs(m,{sx:{display:"flex",alignItems:"center",gap:1},children:[e.jsx(Ie,{label:"Escalation Password",type:"password",value:r.become_password,onChange:te("become_password"),disabled:F,sx:{flex:1,"& .MuiInputBase-root":{bgcolor:"#1f1f1f",color:"#fff"},"& label":{color:"#888"}}}),u&&W.hasBecomePassword&&!R&&!Se&&e.jsx(st,{title:"Clear stored escalation password",children:e.jsx(nt,{size:"small",onClick:()=>ce(!0),sx:{color:"#ff8080"},children:e.jsx(Ks,{fontSize:"small"})})})]}),u&&W.hasBecomePassword&&!R&&!Se&&e.jsx($,{sx:je,children:"Escalation password is stored."}),Se&&e.jsx($,{sx:{...je,color:"#ffaaaa"},children:"Escalation password will be removed when saving."})]}),e.jsxs(tt,{sx:{px:3,py:2},children:[e.jsx(Z,{onClick:be,sx:{color:"#58a6ff"},disabled:l,children:"Cancel"}),e.jsx(Z,{onClick:Le,variant:"outlined",sx:{color:"#58a6ff",borderColor:"#58a6ff"},disabled:F,children:l?e.jsx(Mt,{size:18,sx:{color:"#58a6ff"}}):"Save"})]})]})}Bn.registerModules([On]);const To=Pn.withParams({accentColor:"#FFA6FF",backgroundColor:"#1f2836",browserColorScheme:"dark",chromeBackgroundColor:{ref:"foregroundColor",mix:.07,onto:"backgroundColor"},fontFamily:{googleFont:"IBM Plex Sans"},foregroundColor:"#FFF",headerFontSize:14}),El=To.themeName||"ag-theme-quartz",gs='"IBM Plex Sans", "Helvetica Neue", Arial, sans-serif',wn='"Quartz Regular"';function Ml(n){if(!n)return"-";const t=new Date(Number(n)*1e3);return Number.isNaN(t==null?void 0:t.getTime())?"-":`${t.toLocaleDateString()} ${t.toLocaleTimeString([],{hour:"2-digit",minute:"2-digit"})}`}function so(n){return n?String(n).toLowerCase().replace(/(^|\s)\w/g,o=>o.toUpperCase()):"-"}function Dl(n){const t=(n||"").toLowerCase();return t==="ssh"?e.jsx(Sr,{fontSize:"small",sx:{mr:.6,color:"#58a6ff"}}):t==="winrm"?e.jsx(Cr,{fontSize:"small",sx:{mr:.6,color:"#58a6ff"}}):e.jsx(_r,{fontSize:"small",sx:{mr:.6,color:"#58a6ff"}})}function zl({isAdmin:n=!1}){const[t,o]=s.useState([]),[a,d]=s.useState(!1),[u,r]=s.useState(""),[i,c]=s.useState(null),[p,l]=s.useState(null),[h,f]=s.useState(!1),[y,C]=s.useState("create"),[I,k]=s.useState(null),[v,j]=s.useState(null),[B,R]=s.useState(!1),x=s.useRef(null),S=s.useCallback((ee,be)=>{c(ee.currentTarget),l(be)},[]),z=s.useCallback(()=>{c(null),l(null)},[]),E=s.useCallback(ee=>{const be=ee.data||{},Re=so(be.connection_type);return e.jsxs(m,{sx:{display:"flex",alignItems:"center",fontFamily:gs},children:[Dl(be.connection_type),e.jsx(m,{component:"span",sx:{color:"#f5f7fa"},children:Re})]})},[]),U=s.useCallback(ee=>{const be=ee.data;if(!be)return null;const Re=Ae=>{Ae.preventDefault(),Ae.stopPropagation(),S(Ae,be)};return e.jsx(nt,{size:"small",onClick:Re,sx:{color:"#7db7ff"},children:e.jsx(on,{fontSize:"small"})})},[S]),X=s.useMemo(()=>[{headerName:"Name",field:"name",sort:"asc",cellRenderer:ee=>ee.value||"-"},{headerName:"Credential Type",field:"credential_type",valueGetter:ee=>{var be;return so((be=ee.data)==null?void 0:be.credential_type)}},{headerName:"Connection",field:"connection_type",cellRenderer:E},{headerName:"Site",field:"site_name",cellRenderer:ee=>ee.value||"-"},{headerName:"Username",field:"username",cellRenderer:ee=>ee.value||"-"},{headerName:"Updated",field:"updated_at",valueGetter:ee=>{var be,Re;return Ml(((be=ee.data)==null?void 0:be.updated_at)||((Re=ee.data)==null?void 0:Re.created_at))}},{headerName:"",field:"__actions__",minWidth:70,maxWidth:80,sortable:!1,filter:!1,resizable:!1,suppressMenu:!0,cellRenderer:U,pinned:"right"}],[U,E]),ue=s.useMemo(()=>({sortable:!0,filter:"agTextColumnFilter",resizable:!0,flex:1,minWidth:140,cellStyle:{display:"flex",alignItems:"center",color:"#f5f7fa",fontFamily:gs,fontSize:"13px"},headerClass:"credential-grid-header"}),[]),Se=s.useCallback(ee=>{var be,Re,Ae;return((be=ee.data)==null?void 0:be.id)||((Re=ee.data)==null?void 0:Re.name)||((Ae=ee.data)==null?void 0:Ae.username)||String(ee.rowIndex??"")},[]),ce=s.useCallback(async()=>{d(!0),r("");try{const ee=await fetch("/api/credentials");if(!ee.ok)throw new Error(`HTTP ${ee.status}`);const be=await ee.json(),Re=Array.isArray(be==null?void 0:be.credentials)?be.credentials:[];Re.sort((Ae,Le)=>String((Ae==null?void 0:Ae.name)||"").localeCompare(String((Le==null?void 0:Le.name)||""))),o(Re)}catch(ee){o([]),r(String(ee.message||ee))}finally{d(!1)}},[]);s.useEffect(()=>{ce()},[ce]);const de=()=>{C("create"),k(null),f(!0)},me=ee=>{z(),C("edit"),k(ee),f(!0)},w=ee=>{z(),j(ee)},W=async()=>{if(v!=null&&v.id){R(!0);try{const ee=await fetch(`/api/credentials/${v.id}`,{method:"DELETE"});if(!ee.ok){const be=await ee.json().catch(()=>({}));throw new Error((be==null?void 0:be.error)||`HTTP ${ee.status}`)}j(null),await ce()}catch(ee){r(String(ee.message||ee))}finally{R(!1)}}},F=async()=>{f(!1),k(null),await ce()},te=s.useCallback(ee=>{x.current=ee.api},[]);return s.useEffect(()=>{const ee=x.current;ee&&(a?ee.showLoadingOverlay():t.length?ee.hideOverlay():ee.showNoRowsOverlay())},[a,t]),n?e.jsxs(e.Fragment,{children:[e.jsxs(Qe,{sx:{m:2,p:0,bgcolor:"#1e1e1e",fontFamily:gs,color:"#f5f7fa",display:"flex",flexDirection:"column",flexGrow:1,minWidth:0,minHeight:420},elevation:2,children:[e.jsxs(m,{sx:{display:"flex",alignItems:"center",justifyContent:"space-between",p:2,borderBottom:"1px solid #2a2a2a"},children:[e.jsxs(m,{children:[e.jsx($,{variant:"h6",sx:{color:"#58a6ff",mb:.3},children:"Credentials"}),e.jsx($,{variant:"body2",sx:{color:"#aaa"},children:"Stored credentials for remote automation tasks and Ansible playbook runs."})]}),e.jsxs(m,{sx:{display:"flex",gap:1},children:[e.jsx(Z,{variant:"outlined",size:"small",startIcon:e.jsx(Ss,{}),sx:{borderColor:"#58a6ff",color:"#58a6ff"},onClick:ce,disabled:a,children:"Refresh"}),e.jsx(Z,{variant:"contained",size:"small",startIcon:e.jsx(ts,{}),sx:{bgcolor:"#58a6ff",color:"#0b0f19"},onClick:de,children:"New Credential"})]})]}),a&&e.jsxs(m,{sx:{display:"flex",alignItems:"center",gap:1,color:"#7db7ff",px:2,py:1.5,borderBottom:"1px solid #2a2a2a"},children:[e.jsx(Mt,{size:18,sx:{color:"#58a6ff"}}),e.jsx($,{variant:"body2",children:"Loading credentials…"})]}),u&&e.jsx(m,{sx:{px:2,py:1.5,color:"#ff8080",borderBottom:"1px solid #2a2a2a"},children:e.jsx($,{variant:"body2",children:u})}),e.jsx(m,{sx:{flexGrow:1,minHeight:0,display:"flex",flexDirection:"column",mt:"10px",px:2,pb:2},children:e.jsx(m,{className:El,sx:{width:"100%",height:"100%",flexGrow:1,fontFamily:gs,"--ag-font-family":gs,"--ag-icon-font-family":wn,"--ag-row-border-style":"solid","--ag-row-border-color":"#2a2a2a","--ag-row-border-width":"1px","& .ag-root-wrapper":{borderRadius:1,minHeight:320},"& .ag-root, & .ag-header, & .ag-center-cols-container, & .ag-paging-panel":{fontFamily:gs},"& .ag-icon":{fontFamily:wn}},style:{color:"#f5f7fa"},children:e.jsx(An,{rowData:t,columnDefs:X,defaultColDef:ue,animateRows:!0,rowHeight:46,headerHeight:44,getRowId:Se,overlayNoRowsTemplate:"<span class='ag-overlay-no-rows-center'>No credentials have been created yet.</span>",onGridReady:te,suppressCellFocus:!0,theme:To,style:{width:"100%",height:"100%",fontFamily:gs,"--ag-icon-font-family":wn}})})})]}),e.jsxs(Et,{anchorEl:i,open:!!i,onClose:z,elevation:2,PaperProps:{sx:{bgcolor:"#1f1f1f",color:"#f5f5f5"}},children:[e.jsx(fe,{onClick:()=>me(p),children:"Edit"}),e.jsx(fe,{onClick:()=>w(p),sx:{color:"#ff8080"},children:"Delete"})]}),e.jsx(Pl,{open:h,mode:y,credential:I,onClose:()=>{f(!1),k(null)},onSaved:F}),e.jsx(Zt,{open:!!v,onCancel:()=>j(null),onConfirm:W,confirmDisabled:B,message:v?`Delete credential '${v.name||""}'? Any jobs referencing it will require an update.`:""})]}):e.jsxs(Qe,{sx:{m:2,p:3,bgcolor:"#1e1e1e"},children:[e.jsx($,{variant:"h6",sx:{color:"#ff8080"},children:"Access denied"}),e.jsx($,{variant:"body2",sx:{color:"#bbb"},children:"You do not have permission to manage credentials."})]})}const Fl={m:2,p:0,bgcolor:"#1e1e1e"},Ll={minWidth:820,"& th, & td":{color:"#ddd",borderColor:"#2a2a2a",fontSize:13,py:.75},"& th .MuiTableSortLabel-root":{color:"#ddd"},"& th .MuiTableSortLabel-root.Mui-active":{color:"#ddd"}},$l={bgcolor:"#1e1e1e",color:"#fff",fontSize:"13px"},Ul={input:{color:"#fff"},minWidth:220,"& .MuiOutlinedInput-root":{"& fieldset":{borderColor:"#555"},"&:hover fieldset":{borderColor:"#888"}}};function no(n){if(!n)return"-";const t=new Date((n||0)*1e3),o=t.toLocaleDateString("en-US",{month:"2-digit",day:"2-digit",year:"numeric"}),a=t.toLocaleTimeString("en-US",{hour:"numeric",minute:"2-digit"});return`${o} @ ${a}`}async function oo(n){const o=new TextEncoder().encode(n||""),a=await crypto.subtle.digest("SHA-512",o);return Array.from(new Uint8Array(a)).map(u=>u.toString(16).padStart(2,"0")).join("")}function Wl({isAdmin:n=!1}){var ct;const[t,o]=s.useState([]),[a,d]=s.useState("username"),[u,r]=s.useState("asc"),[i,c]=s.useState(null),[p,l]=s.useState(null),[h,f]=s.useState(!1),[y,C]=s.useState(null),[I,k]=s.useState(""),[v,j]=s.useState(!1),[B,R]=s.useState({username:"",display_name:"",password:"",role:"User"}),[x,S]=s.useState(!1),[z,E]=s.useState(null),[U,X]=s.useState(!1),[ue,Se]=s.useState(null),[ce,de]=s.useState(null),[me,w]=s.useState(!1),[W,F]=s.useState(""),[te,ee]=s.useState(null),[be,Re]=s.useState(null),[Ae,Le]=s.useState(!1),[Fe,je]=s.useState(null),V=s.useMemo(()=>[{id:"display_name",label:"Display Name"},{id:"username",label:"User Name"},{id:"last_login",label:"Last Login"},{id:"role",label:"User Role"},{id:"mfa_enabled",label:"MFA"},{id:"actions",label:""}],[]),[O,M]=s.useState({}),[g,L]=s.useState(null),we=oe=>_e=>L({id:oe,anchorEl:_e.currentTarget}),T=()=>L(null),G=oe=>_e=>M($e=>({...$e,[oe]:_e.target.value})),ie=s.useCallback(async()=>{try{const _e=await(await fetch("/api/users",{credentials:"include"})).json();Array.isArray(_e==null?void 0:_e.users)?o(_e.users.map($e=>({...$e,mfa_enabled:$e&&typeof $e.mfa_enabled<"u"&&$e.mfa_enabled?1:0}))):o([])}catch{o([])}},[]);s.useEffect(()=>{n&&((async()=>{try{const oe=await fetch("/api/auth/me",{credentials:"include"});if(oe.ok){const _e=await oe.json();ee(_e)}}catch{}})(),ie())},[ie,n]);const Ce=oe=>{a===oe?r(u==="asc"?"desc":"asc"):(d(oe),r("asc"))},Ee=s.useMemo(()=>{const oe=Xe=>{for(const[We,Je]of Object.entries(O||{})){if(!Je)continue;const ft=String(Je).toLowerCase();let ht="";if(We==="last_login"?ht=String(no(Xe.last_login)):ht=String(Xe[We]??""),!ht.toLowerCase().includes(ft))return!1}return!0},_e=u==="asc"?1:-1,$e=t.filter(oe);return $e.sort((Xe,We)=>a==="last_login"?((Xe.last_login||0)-(We.last_login||0))*_e:a==="mfa_enabled"?((Xe.mfa_enabled?1:0)-(We.mfa_enabled?1:0))*_e:String(Xe[a]??"").toLowerCase().localeCompare(String(We[a]??"").toLowerCase())*_e),$e},[t,O,a,u]),Ne=(oe,_e)=>{c({mouseX:oe.clientX,mouseY:oe.clientY,anchorEl:oe.currentTarget}),l(_e)},Ke=()=>{c(null),l(null)},at=oe=>{if(oe){if(te&&oe.username&&String(te.username).toLowerCase()===String(oe.username).toLowerCase()){F("You cannot delete the user you are currently logged in as."),w(!0);return}E(oe),S(!0)}},ut=async()=>{const oe=z;if(S(!1),!!oe)try{const _e=await fetch(`/api/users/${encodeURIComponent(oe.username)}`,{method:"DELETE",credentials:"include"}),$e=await _e.json();if(!_e.ok){F(($e==null?void 0:$e.error)||"Failed to delete user"),w(!0);return}await ie()}catch(_e){console.error(_e),F("Failed to delete user"),w(!0)}},Pe=oe=>{if(!oe)return;if(te&&oe.username&&String(te.username).toLowerCase()===String(oe.username).toLowerCase()){F("You cannot change your own role."),w(!0);return}const _e=String(oe.role||"User").toLowerCase()==="admin"?"User":"Admin";Se(oe),de(_e),X(!0)},gt=async()=>{const oe=ue,_e=ce;if(X(!1),!(!oe||!_e))try{const $e=await fetch(`/api/users/${encodeURIComponent(oe.username)}/role`,{method:"POST",headers:{"Content-Type":"application/json"},credentials:"include",body:JSON.stringify({role:_e})}),Xe=await $e.json();if(!$e.ok){F((Xe==null?void 0:Xe.error)||"Failed to change role"),w(!0);return}await ie()}catch($e){console.error($e),F("Failed to change role"),w(!0)}},bt=oe=>{oe&&(je(oe),Le(!0))},vt=async()=>{const oe=Fe;if(Le(!1),je(null),!oe)return;const _e=oe.username,$e=!!oe.mfa_enabled;Re(_e);try{const Xe=await fetch(`/api/users/${encodeURIComponent(_e)}/mfa`,{method:"POST",headers:{"Content-Type":"application/json"},credentials:"include",body:JSON.stringify({enabled:$e,reset_secret:!0})}),We=await Xe.json();if(!Xe.ok){F((We==null?void 0:We.error)||"Failed to reset MFA for this user."),w(!0);return}await ie()}catch(Xe){console.error(Xe),F("Failed to reset MFA for this user."),w(!0)}finally{Re(null)}},Ut=async(oe,_e)=>{if(!oe)return;const $e=!!oe.mfa_enabled,Xe=_e?1:0;o(We=>We.map(Je=>String(Je.username).toLowerCase()===String(oe.username).toLowerCase()?{...Je,mfa_enabled:Xe}:Je)),Re(oe.username);try{const We=await fetch(`/api/users/${encodeURIComponent(oe.username)}/mfa`,{method:"POST",headers:{"Content-Type":"application/json"},credentials:"include",body:JSON.stringify({enabled:_e})}),Je=await We.json();if(!We.ok){o(ft=>ft.map(ht=>String(ht.username).toLowerCase()===String(oe.username).toLowerCase()?{...ht,mfa_enabled:$e?1:0}:ht)),F((Je==null?void 0:Je.error)||"Failed to update MFA settings."),w(!0);return}await ie()}catch(We){console.error(We),o(Je=>Je.map(ft=>String(ft.username).toLowerCase()===String(oe.username).toLowerCase()?{...ft,mfa_enabled:$e?1:0}:ft)),F("Failed to update MFA settings."),w(!0)}finally{Re(null)}},It=async()=>{const oe=y;if(!oe)return;const _e=I||"";if(_e.trim())try{const $e=await oo(_e),Xe=await fetch(`/api/users/${encodeURIComponent(oe.username)}/reset_password`,{method:"POST",headers:{"Content-Type":"application/json"},credentials:"include",body:JSON.stringify({password_sha512:$e})}),We=await Xe.json();if(!Xe.ok){alert((We==null?void 0:We.error)||"Failed to reset password");return}f(!1),C(null),k("")}catch($e){console.error($e),alert("Failed to reset password")}},yt=oe=>{oe&&(C(oe),f(!0),k(""))},pt=()=>{j(!0),R({username:"",display_name:"",password:"",role:"User"})},St=async()=>{const oe=(B.username||"").trim(),_e=(B.display_name||oe).trim(),$e=(B.password||"").trim(),Xe=B.role||"User";if(!(!oe||!$e))try{const We=await oo($e),Je=await fetch("/api/users",{method:"POST",headers:{"Content-Type":"application/json"},credentials:"include",body:JSON.stringify({username:oe,display_name:_e,password_sha512:We,role:Xe})}),ft=await Je.json();if(!Je.ok){alert((ft==null?void 0:ft.error)||"Failed to create user");return}j(!1),await ie()}catch(We){console.error(We),alert("Failed to create user")}};return n?e.jsxs(e.Fragment,{children:[e.jsxs(Qe,{sx:Fl,elevation:2,children:[e.jsxs(m,{sx:{p:2,pb:1,display:"flex",alignItems:"center",justifyContent:"space-between"},children:[e.jsxs(m,{children:[e.jsx($,{variant:"h6",sx:{color:"#58a6ff",mb:0},children:"User Management"}),e.jsx($,{variant:"body2",sx:{color:"#aaa"},children:"Manage authorized users of the Borealis Automation Platform."})]}),e.jsx(Z,{variant:"outlined",size:"small",onClick:pt,sx:{color:"#58a6ff",borderColor:"#58a6ff",textTransform:"none"},children:"Create User"})]}),e.jsxs(Rt,{size:"small",sx:Ll,children:[e.jsx(Bt,{children:e.jsxs(Ue,{children:[e.jsx(Q,{padding:"checkbox"}),V.map(oe=>e.jsx(Q,{sortDirection:["actions"].includes(oe.id)?!1:a===oe.id?u:!1,children:oe.id!=="actions"?e.jsxs(m,{sx:{display:"flex",alignItems:"center",gap:1},children:[e.jsx(Tt,{active:a===oe.id,direction:a===oe.id?u:"asc",onClick:()=>Ce(oe.id),children:oe.label}),e.jsx(nt,{size:"small",onClick:we(oe.id),sx:{color:O[oe.id]?"#58a6ff":"#888"},children:e.jsx(Rn,{fontSize:"inherit"})})]}):null},oe.id))]})}),e.jsxs(Nt,{children:[Ee.map(oe=>e.jsxs(Ue,{hover:!0,children:[e.jsx(Q,{padding:"checkbox"}),e.jsx(Q,{children:oe.display_name||oe.username}),e.jsx(Q,{children:oe.username}),e.jsx(Q,{children:no(oe.last_login)}),e.jsx(Q,{children:oe.role||"User"}),e.jsx(Q,{align:"center",children:e.jsx(At,{size:"small",checked:!!oe.mfa_enabled,disabled:!!(be&&String(be).toLowerCase()===String(oe.username).toLowerCase()),onChange:_e=>{_e.stopPropagation(),Ut(oe,_e.target.checked)},onClick:_e=>_e.stopPropagation(),sx:{color:"#888","&.Mui-checked":{color:"#58a6ff"}},inputProps:{"aria-label":`Toggle MFA for ${oe.username}`}})}),e.jsx(Q,{align:"right",children:e.jsx(nt,{size:"small",onClick:_e=>Ne(_e,oe),sx:{color:"#ccc"},children:e.jsx(on,{fontSize:"inherit"})})})]},oe.username)),Ee.length===0&&e.jsx(Ue,{children:e.jsx(Q,{colSpan:V.length+1,sx:{color:"#888"},children:"No users found."})})]})]}),e.jsx(Ls,{open:!!g,anchorEl:(g==null?void 0:g.anchorEl)||null,onClose:T,anchorOrigin:{vertical:"bottom",horizontal:"left"},PaperProps:{sx:{bgcolor:"#1e1e1e",p:1}},children:g&&e.jsxs(m,{sx:{display:"flex",gap:1,alignItems:"center"},children:[e.jsx(Ie,{autoFocus:!0,size:"small",placeholder:`Filter ${((ct=V.find(oe=>oe.id===g.id))==null?void 0:ct.label)||""}`,value:O[g.id]||"",onChange:G(g.id),onKeyDown:oe=>{oe.key==="Escape"&&T()},sx:Ul}),e.jsx(Z,{variant:"outlined",size:"small",onClick:()=>{M(oe=>({...oe,[g.id]:""})),T()},sx:{textTransform:"none",borderColor:"#555",color:"#bbb"},children:"Clear"})]})}),e.jsxs(Et,{anchorEl:i==null?void 0:i.anchorEl,open:!!i,onClose:Ke,anchorOrigin:{vertical:"bottom",horizontal:"right"},transformOrigin:{vertical:"top",horizontal:"right"},PaperProps:{sx:$l},children:[e.jsx(fe,{disabled:te&&p&&String(te.username).toLowerCase()===String(p.username).toLowerCase(),onClick:()=>{const oe=p;Ke(),at(oe)},children:"Delete User"}),e.jsx(fe,{onClick:()=>{const oe=p;Ke(),yt(oe)},children:"Reset Password"}),e.jsx(fe,{disabled:te&&p&&String(te.username).toLowerCase()===String(p.username).toLowerCase(),onClick:()=>{const oe=p;Ke(),Pe(oe)},children:"Change Role"}),e.jsx(fe,{onClick:()=>{const oe=p;Ke(),bt(oe)},children:"Reset MFA"})]}),e.jsxs(Ze,{open:h,onClose:()=>f(!1),PaperProps:{sx:{bgcolor:"#121212",color:"#fff"}},children:[e.jsx(et,{children:"Reset Password"}),e.jsxs(rt,{children:[e.jsxs($t,{sx:{color:"#ccc"},children:["Enter a new password for ",y==null?void 0:y.username,"."]}),e.jsx(Ie,{autoFocus:!0,margin:"dense",fullWidth:!0,label:"New Password",type:"password",variant:"outlined",value:I,onChange:oe=>k(oe.target.value),sx:{"& .MuiOutlinedInput-root":{backgroundColor:"#2a2a2a",color:"#ccc","& fieldset":{borderColor:"#444"},"&:hover fieldset":{borderColor:"#666"}},label:{color:"#aaa"},mt:1}})]}),e.jsxs(tt,{children:[e.jsx(Z,{onClick:()=>{f(!1),C(null)},sx:{color:"#58a6ff"},children:"Cancel"}),e.jsx(Z,{onClick:It,sx:{color:"#58a6ff"},children:"OK"})]})]}),e.jsxs(Ze,{open:v,onClose:()=>j(!1),PaperProps:{sx:{bgcolor:"#121212",color:"#fff"}},children:[e.jsx(et,{children:"Create User"}),e.jsxs(rt,{children:[e.jsx(Ie,{autoFocus:!0,margin:"dense",fullWidth:!0,label:"Username",variant:"outlined",value:B.username,onChange:oe=>R(_e=>({..._e,username:oe.target.value})),sx:{"& .MuiOutlinedInput-root":{backgroundColor:"#2a2a2a",color:"#ccc","& fieldset":{borderColor:"#444"},"&:hover fieldset":{borderColor:"#666"}},label:{color:"#aaa"},mt:1}}),e.jsx(Ie,{margin:"dense",fullWidth:!0,label:"Display Name (optional)",variant:"outlined",value:B.display_name,onChange:oe=>R(_e=>({..._e,display_name:oe.target.value})),sx:{"& .MuiOutlinedInput-root":{backgroundColor:"#2a2a2a",color:"#ccc","& fieldset":{borderColor:"#444"},"&:hover fieldset":{borderColor:"#666"}},label:{color:"#aaa"},mt:1}}),e.jsx(Ie,{margin:"dense",fullWidth:!0,label:"Password",type:"password",variant:"outlined",value:B.password,onChange:oe=>R(_e=>({..._e,password:oe.target.value})),sx:{"& .MuiOutlinedInput-root":{backgroundColor:"#2a2a2a",color:"#ccc","& fieldset":{borderColor:"#444"},"&:hover fieldset":{borderColor:"#666"}},label:{color:"#aaa"},mt:1}}),e.jsxs(Ht,{fullWidth:!0,sx:{mt:2},children:[e.jsx(Gt,{sx:{color:"#aaa"},children:"Role"}),e.jsxs(wt,{native:!0,value:B.role,onChange:oe=>R(_e=>({..._e,role:oe.target.value})),sx:{backgroundColor:"#2a2a2a",color:"#ccc",borderColor:"#444"},children:[e.jsx("option",{value:"User",children:"User"}),e.jsx("option",{value:"Admin",children:"Admin"})]})]})]}),e.jsxs(tt,{children:[e.jsx(Z,{onClick:()=>j(!1),sx:{color:"#58a6ff"},children:"Cancel"}),e.jsx(Z,{onClick:St,sx:{color:"#58a6ff"},children:"Create"})]})]})]}),e.jsx(Zt,{open:x,message:`Are you sure you want to delete user '${(z==null?void 0:z.username)||""}'?`,onCancel:()=>S(!1),onConfirm:ut}),e.jsx(Zt,{open:U,message:ue?`Change role for '${ue.username}' to ${ce}?`:"",onCancel:()=>X(!1),onConfirm:gt}),e.jsx(Zt,{open:Ae,message:Fe?`Reset MFA enrollment for '${Fe.username}'? This clears their existing authenticator.`:"",onCancel:()=>{Le(!1),je(null)},onConfirm:vt}),e.jsx(Zt,{open:me,message:W,onCancel:()=>w(!1),onConfirm:()=>w(!1)})]}):null}const Vl={m:2,p:0,bgcolor:"#1e1e1e",color:"#f5f7fa",display:"flex",flexDirection:"column",flexGrow:1,minWidth:0,minHeight:320},Hl={mt:2,"& .MuiOutlinedInput-root":{bgcolor:"#181818",color:"#f5f7fa","& fieldset":{borderColor:"#2a2a2a"},"&:hover fieldset":{borderColor:"#58a6ff"},"&.Mui-focused fieldset":{borderColor:"#58a6ff"}},"& .MuiInputLabel-root":{color:"#bbb"},"& .MuiInputLabel-root.Mui-focused":{color:"#7db7ff"}};function Gl({isAdmin:n=!1}){const[t,o]=s.useState(!1),[a,d]=s.useState(!1),[u,r]=s.useState(""),[i,c]=s.useState(""),[p,l]=s.useState(""),[h,f]=s.useState(!1),[y,C]=s.useState({message:"",valid:null,status:"",rateLimit:null,error:""}),I=s.useCallback(async()=>{o(!0),l("");try{const R=await fetch("/api/github/token"),x=await R.json();if(!R.ok)throw new Error((x==null?void 0:x.error)||`HTTP ${R.status}`);const S=typeof(x==null?void 0:x.token)=="string"?x.token:"";r(S),c(S),f(!1),C({message:typeof(x==null?void 0:x.message)=="string"?x.message:"",valid:(x==null?void 0:x.valid)===!0,status:typeof(x==null?void 0:x.status)=="string"?x.status:"",rateLimit:typeof(x==null?void 0:x.rate_limit)=="number"?x.rate_limit:null,error:typeof(x==null?void 0:x.error)=="string"?x.error:""})}catch(R){const x=R&&typeof R.message=="string"?R.message:String(R);l(x),r(""),c(""),C({message:"",valid:null,status:"",rateLimit:null,error:""})}finally{o(!1)}},[]);s.useEffect(()=>{n&&I()},[I,n]);const k=s.useCallback(async()=>{d(!0),l("");try{const R=await fetch("/api/github/token",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({token:i})}),x=await R.json();if(!R.ok)throw new Error((x==null?void 0:x.error)||`HTTP ${R.status}`);const S=typeof(x==null?void 0:x.token)=="string"?x.token:"";r(S),c(S),f(!1),C({message:typeof(x==null?void 0:x.message)=="string"?x.message:"",valid:(x==null?void 0:x.valid)===!0,status:typeof(x==null?void 0:x.status)=="string"?x.status:"",rateLimit:typeof(x==null?void 0:x.rate_limit)=="number"?x.rate_limit:null,error:typeof(x==null?void 0:x.error)=="string"?x.error:""})}catch(R){const x=R&&typeof R.message=="string"?R.message:String(R);l(x)}finally{d(!1)}},[i]),v=s.useMemo(()=>i!==u,[i,u]),j=s.useMemo(()=>{if(v)return{text:"Token has not been saved yet — Save to verify.",color:"#f0c36d"};const R=y.message||"";return R?y.valid?{text:R,color:"#7dffac"}:(y.status||"").toLowerCase()==="missing"?{text:R,color:"#bbb"}:{text:R,color:"#ff8080"}:{text:"",color:"#bbb"}},[v,y]),B=s.useCallback(()=>{f(R=>!R)},[]);return n?e.jsxs(Qe,{sx:Vl,elevation:2,children:[e.jsx(m,{sx:{display:"flex",alignItems:"center",justifyContent:"space-between",p:2,borderBottom:"1px solid #2a2a2a"},children:e.jsxs(m,{children:[e.jsx($,{variant:"h6",sx:{color:"#58a6ff",mb:.3},children:"Github API Token"}),e.jsxs($,{variant:"body2",sx:{color:"#aaa"},children:['Using a Github "Personal Access Token" increases the Github API rate limits from 60/hr to 5,000/hr. This is important for production Borealis usage as it likes to hit its unauthenticated API limits sometimes despite my best efforts.',e.jsx("br",{}),"Navigate to"," ",e.jsx(kr,{href:"https://github.com/settings/tokens",target:"_blank",rel:"noopener noreferrer",sx:{color:"#7db7ff"},children:"https://github.com/settings/tokens"})," ","❯ ",e.jsx("b",{children:"Personal Access Tokens ❯ Tokens (Classic) ❯ Generate New Token ❯ New Personal Access Token (Classic)"})]}),e.jsx("br",{}),e.jsxs($,{variant:"body2",sx:{color:"#ccc"},children:[e.jsx(m,{component:"span",sx:{fontWeight:600},children:"Note:"})," ",e.jsx(m,{component:"code",sx:{bgcolor:"#222",px:.75,py:.25,borderRadius:1,fontSize:"0.85rem"},children:"Borealis Automation Platform"})]}),e.jsxs($,{variant:"body2",sx:{color:"#ccc"},children:[e.jsx(m,{component:"span",sx:{fontWeight:600},children:"Scope:"})," ",e.jsx(m,{component:"code",sx:{bgcolor:"#222",px:.75,py:.25,borderRadius:1,fontSize:"0.85rem"},children:"public_repo"})]}),e.jsxs($,{variant:"body2",sx:{color:"#ccc"},children:[e.jsx(m,{component:"span",sx:{fontWeight:600},children:"Expiration:"})," ",e.jsx(m,{component:"code",sx:{bgcolor:"#222",px:.75,py:.25,borderRadius:1,fontSize:"0.85rem"},children:"No Expiration"})]})]})}),e.jsxs(m,{sx:{px:2,py:2,display:"flex",flexDirection:"column",gap:1.5},children:[e.jsx(Ie,{label:"Personal Access Token",value:i,onChange:R=>c(R.target.value),fullWidth:!0,variant:"outlined",sx:Hl,disabled:a||t,type:h?"text":"password",InputProps:{endAdornment:e.jsxs(Ir,{position:"end",sx:{mr:-1,display:"flex",alignItems:"center",gap:1},children:[e.jsx(Z,{variant:"contained",size:"small",onClick:B,disabled:t||a,startIcon:h?e.jsx(Rr,{}):e.jsx(Nr,{}),sx:{bgcolor:"#3a3a3a",color:"#f5f7fa",minWidth:96,mr:.5,"&:hover":{bgcolor:"#4a4a4a"}},children:h?"Hide":"Reveal"}),e.jsx(Z,{variant:"contained",size:"small",onClick:k,disabled:a||t,startIcon:a?null:e.jsx(ho,{}),sx:{bgcolor:"#58a6ff",color:"#0b0f19",minWidth:88,mr:1,"&:hover":{bgcolor:"#7db7ff"}},children:a?e.jsx(Mt,{size:16,sx:{color:"#0b0f19"}}):"Save"})]})}}),e.jsxs(m,{sx:{display:"flex",alignItems:"center",justifyContent:"space-between",gap:2},children:[e.jsx(Z,{variant:"outlined",size:"small",startIcon:e.jsx(Ss,{}),sx:{borderColor:"#58a6ff",color:"#58a6ff"},onClick:I,disabled:t||a,children:"Refresh"}),(j.text||!v&&y.rateLimit)&&e.jsxs($,{variant:"body2",sx:{display:"inline-flex",alignItems:"center",color:j.color||"#7db7ff",textAlign:"right"},children:[j.text&&`${j.text} `,!v&&y.rateLimit&&`- Hourly Request Rate Limit: ${y.rateLimit.toLocaleString()}`]})]}),t&&e.jsxs(m,{sx:{display:"flex",alignItems:"center",gap:1,color:"#7db7ff",px:2,py:1.5,borderBottom:"1px solid #2a2a2a"},children:[e.jsx(Mt,{size:18,sx:{color:"#58a6ff"}}),e.jsx($,{variant:"body2",children:"Loading token…"})]}),p&&e.jsx(m,{sx:{px:2,py:1.5,color:"#ff8080",borderBottom:"1px solid #2a2a2a"},children:e.jsx($,{variant:"body2",children:p})})]})]}):e.jsxs(Qe,{sx:{m:2,p:3,bgcolor:"#1e1e1e"},children:[e.jsx($,{variant:"h6",sx:{color:"#ff8080"},children:"Access denied"}),e.jsx($,{variant:"body2",sx:{color:"#bbb"},children:"You do not have permission to manage the GitHub API token."})]})}function ql({isAdmin:n=!1}){const[t,o]=s.useState(null),[a,d]=s.useState(null),[u,r]=s.useState(!1);return s.useEffect(()=>{if(!n)return;let i=!0;const c=async()=>{try{const l=await fetch("/api/server/time");if(!l.ok)throw new Error(`HTTP ${l.status}`);const h=await l.json();i&&(o((h==null?void 0:h.display)||(h==null?void 0:h.iso)||null),d(null))}catch(l){i&&d(String(l))}};c();const p=setInterval(c,6e4);return()=>{i=!1,clearInterval(p)}},[n]),n?e.jsxs(Qe,{sx:{m:2,p:0,bgcolor:"#1e1e1e"},elevation:2,children:[e.jsxs(m,{sx:{p:2},children:[e.jsx($,{variant:"h6",sx:{color:"#58a6ff",mb:1},children:"Server Info"}),e.jsx($,{sx:{color:"#aaa",mb:1},children:"Basic server information will appear here for informative and debug purposes."}),e.jsxs(m,{sx:{display:"flex",gap:2,alignItems:"baseline"},children:[e.jsx($,{sx:{color:"#ccc",fontWeight:600,minWidth:120},children:"Server Time"}),e.jsx($,{sx:{color:a?"#ff6b6b":"#ddd",fontFamily:'ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace'},children:a?`Error: ${a}`:t||"Loading..."})]}),e.jsxs(m,{sx:{mt:3},children:[e.jsx($,{variant:"subtitle1",sx:{color:"#58a6ff",mb:1},children:"Project Links"}),e.jsxs(m,{sx:{display:"flex",gap:2,flexWrap:"wrap"},children:[e.jsx(Z,{variant:"outlined",color:"primary",startIcon:e.jsx(po,{}),onClick:()=>window.open("https://github.com/bunny-lab-io/Borealis","_blank"),sx:{borderColor:"#3a3a3a",color:"#7db7ff"},children:"GitHub Project"}),e.jsx(Z,{variant:"outlined",color:"inherit",startIcon:e.jsx(Tr,{}),onClick:()=>r(!0),sx:{borderColor:"#3a3a3a",color:"#ddd"},children:"About Borealis"})]})]})]}),e.jsx(ki,{open:u,onClose:()=>r(!1)})]}):null}const Jl=[{value:1,label:"1 hour"},{value:3,label:"3 hours"},{value:6,label:"6 hours"},{value:12,label:"12 hours"},{value:24,label:"24 hours"}],Yl={active:"success",used:"default",expired:"warning"},Kl=n=>{if(!n)return"—";const t=n.split("-");if(t.length<=1){const o=n.slice(0,4);return`${o}${"•".repeat(Math.max(0,n.length-o.length))}`}return t.map((o,a)=>a===0||a===t.length-1?o:"•".repeat(o.length)).join("-")},vn=n=>{if(!n)return"—";const t=new Date(n);return Number.isNaN(t.getTime())?n:t.toLocaleString()},Sn=n=>{if(!n)return"expired";const t=Number.isFinite(n==null?void 0:n.max_uses)?n.max_uses:1;if((Number.isFinite(n==null?void 0:n.use_count)?n.use_count:0)>=Math.max(1,t||1))return"used";if(!n.expires_at)return"expired";const a=new Date(n.expires_at);return Number.isNaN(a.getTime())?"expired":a.getTime()>Date.now()?"active":"expired"};function Xl(){const[n,t]=s.useState([]),[o,a]=s.useState(!1),[d,u]=s.useState(""),[r,i]=s.useState(null),[c,p]=s.useState("all"),[l,h]=s.useState(6),[f,y]=s.useState(!1),[C,I]=s.useState(2),k=s.useMemo(()=>c==="all"?n:n.filter(S=>Sn(S)===c),[n,c]),v=s.useCallback(async()=>{a(!0),u("");try{const S=c==="all"?"":`?status=${encodeURIComponent(c)}`,z=await fetch(`/api/admin/enrollment-codes${S}`,{credentials:"include"});if(!z.ok){const U=await z.json().catch(()=>({}));throw new Error(U.error||`Request failed (${z.status})`)}const E=await z.json();t(Array.isArray(E.codes)?E.codes:[])}catch(S){u(S.message||"Unable to load enrollment codes")}finally{a(!1)}},[c]);s.useEffect(()=>{v()},[v]);const j=s.useCallback(async()=>{y(!0),u("");try{const S=await fetch("/api/admin/enrollment-codes",{method:"POST",credentials:"include",headers:{"Content-Type":"application/json"},body:JSON.stringify({ttl_hours:l,max_uses:C})});if(!S.ok){const E=await S.json().catch(()=>({}));throw new Error(E.error||`Request failed (${S.status})`)}const z=await S.json();i({type:"success",message:`Installer code ${z.code} created`}),await v()}catch(S){i({type:"error",message:S.message||"Failed to create code"})}finally{y(!1)}},[v,l,C]),B=s.useCallback(async S=>{if(!(!S||!window.confirm("Delete this unused installer code?"))){u("");try{const E=await fetch(`/api/admin/enrollment-codes/${encodeURIComponent(S)}`,{method:"DELETE",credentials:"include"});if(!E.ok){const U=await E.json().catch(()=>({}));throw new Error(U.error||`Request failed (${E.status})`)}i({type:"success",message:"Installer code deleted"}),await v()}catch(E){i({type:"error",message:E.message||"Failed to delete code"})}}},[v]),R=s.useCallback(S=>{var z;if(S)try{if((z=navigator.clipboard)!=null&&z.writeText)navigator.clipboard.writeText(S),i({type:"success",message:"Code copied to clipboard"});else{const E=document.createElement("textarea");E.value=S,E.style.position="fixed",E.style.opacity="0",document.body.appendChild(E),E.select(),document.execCommand("copy"),document.body.removeChild(E),i({type:"success",message:"Code copied to clipboard"})}}catch(E){i({type:"error",message:E.message||"Unable to copy code"})}},[]),x=S=>{const z=Sn(S);return e.jsx(yo,{size:"small",label:z,color:Yl[z]||"default",variant:"outlined"})};return e.jsxs(m,{sx:{p:3,display:"flex",flexDirection:"column",gap:3},children:[e.jsxs(ds,{direction:"row",alignItems:"center",spacing:2,children:[e.jsx(uo,{color:"primary"}),e.jsx($,{variant:"h5",children:"Enrollment Installer Codes"})]}),e.jsxs(Qe,{sx:{p:2,display:"flex",flexDirection:"column",gap:2},children:[e.jsxs(ds,{direction:{xs:"column",sm:"row"},spacing:2,alignItems:{xs:"stretch",sm:"center"},children:[e.jsxs(Ht,{size:"small",sx:{minWidth:160},children:[e.jsx(Gt,{id:"status-filter-label",children:"Filter"}),e.jsxs(wt,{labelId:"status-filter-label",label:"Filter",value:c,onChange:S=>p(S.target.value),children:[e.jsx(fe,{value:"all",children:"All"}),e.jsx(fe,{value:"active",children:"Active"}),e.jsx(fe,{value:"used",children:"Used"}),e.jsx(fe,{value:"expired",children:"Expired"})]})]}),e.jsxs(Ht,{size:"small",sx:{minWidth:180},children:[e.jsx(Gt,{id:"ttl-select-label",children:"Duration"}),e.jsx(wt,{labelId:"ttl-select-label",label:"Duration",value:l,onChange:S=>h(Number(S.target.value)),children:Jl.map(S=>e.jsx(fe,{value:S.value,children:S.label},S.value))})]}),e.jsxs(Ht,{size:"small",sx:{minWidth:160},children:[e.jsx(Gt,{id:"uses-select-label",children:"Allowed Uses"}),e.jsx(wt,{labelId:"uses-select-label",label:"Allowed Uses",value:C,onChange:S=>I(Number(S.target.value)),children:[1,2,3,5].map(S=>e.jsx(fe,{value:S,children:S===1?"Single use":`${S} uses`},S))})]}),e.jsx(Z,{variant:"contained",color:"primary",onClick:j,disabled:f,startIcon:f?e.jsx(Mt,{size:16,color:"inherit"}):null,children:f?"Generating…":"Generate Code"}),e.jsx(Z,{variant:"outlined",startIcon:e.jsx(Ss,{}),onClick:v,disabled:o,children:"Refresh"})]}),r?e.jsx(rn,{severity:r.type,onClose:()=>i(null),variant:"outlined",children:r.message}):null,d?e.jsx(rn,{severity:"error",variant:"outlined",children:d}):null,e.jsx(bo,{component:Qe,variant:"outlined",sx:{maxHeight:420},children:e.jsxs(Rt,{size:"small",stickyHeader:!0,children:[e.jsx(Bt,{children:e.jsxs(Ue,{children:[e.jsx(Q,{children:"Status"}),e.jsx(Q,{children:"Installer Code"}),e.jsx(Q,{children:"Expires At"}),e.jsx(Q,{children:"Created By"}),e.jsx(Q,{children:"Usage"}),e.jsx(Q,{children:"Last Used"}),e.jsx(Q,{children:"Consumed At"}),e.jsx(Q,{children:"Used By GUID"}),e.jsx(Q,{align:"right",children:"Actions"})]})}),e.jsx(Nt,{children:o?e.jsx(Ue,{children:e.jsx(Q,{colSpan:7,align:"center",children:e.jsxs(ds,{direction:"row",spacing:1,alignItems:"center",justifyContent:"center",children:[e.jsx(Mt,{size:20}),e.jsx($,{variant:"body2",children:"Loading installer codes…"})]})})}):k.length===0?e.jsx(Ue,{children:e.jsx(Q,{colSpan:7,align:"center",children:e.jsx($,{variant:"body2",color:"text.secondary",children:"No installer codes match this filter."})})}):k.map(S=>{Sn(S);const z=Math.max(1,Number.isFinite(S==null?void 0:S.max_uses)?S.max_uses:1),E=Math.max(0,Number.isFinite(S==null?void 0:S.use_count)?S.use_count:0),U=E!==0;return e.jsxs(Ue,{hover:!0,children:[e.jsx(Q,{children:x(S)}),e.jsx(Q,{sx:{fontFamily:"monospace"},children:Kl(S.code)}),e.jsx(Q,{children:vn(S.expires_at)}),e.jsx(Q,{children:S.created_by_user_id||"—"}),e.jsx(Q,{sx:{fontFamily:"monospace"},children:`${E} / ${z}`}),e.jsx(Q,{children:vn(S.last_used_at)}),e.jsx(Q,{children:vn(S.used_at)}),e.jsx(Q,{sx:{fontFamily:"monospace"},children:S.used_by_guid||"—"}),e.jsxs(Q,{align:"right",children:[e.jsx(st,{title:"Copy code",children:e.jsx("span",{children:e.jsx(nt,{size:"small",onClick:()=>R(S.code),disabled:!S.code,children:e.jsx(fo,{fontSize:"small"})})})}),e.jsx(st,{title:U?"Only unused codes can be deleted":"Delete code",children:e.jsx("span",{children:e.jsx(nt,{size:"small",onClick:()=>B(S.id),disabled:U,children:e.jsx(mo,{fontSize:"small"})})})})]})]},S.id)})})]})})]})]})}const Ql=es.memo(Xl),Zl=[{value:"all",label:"All"},{value:"pending",label:"Pending"},{value:"approved",label:"Approved"},{value:"completed",label:"Completed"},{value:"denied",label:"Denied"},{value:"expired",label:"Expired"}],ec={pending:"warning",approved:"info",completed:"success",denied:"default",expired:"default"},ro=n=>{if(!n)return"—";const t=new Date(n);return Number.isNaN(t.getTime())?n:t.toLocaleString()},tc=n=>{var o;if(!n)return"—";const t=n.replace(/[^a-f0-9]/gi,"").toLowerCase();return t?((o=t.match(/.{1,4}/g))==null?void 0:o.join(" "))??t:n},Cn=n=>n?n==="completed"?"completed":n.toLowerCase():"pending";function sc(){const[n,t]=s.useState([]),[o,a]=s.useState("all"),[d,u]=s.useState(!1),[r,i]=s.useState(""),[c,p]=s.useState(null),[l,h]=s.useState({}),[f,y]=s.useState(null),[C,I]=s.useState(null),k=s.useCallback(async()=>{u(!0),i("");try{const w=o==="all"?"":`?status=${encodeURIComponent(o)}`,W=await fetch(`/api/admin/device-approvals${w}`,{credentials:"include"});if(!W.ok){const te=await W.json().catch(()=>({}));throw new Error(te.error||`Request failed (${W.status})`)}const F=await W.json();t(Array.isArray(F.approvals)?F.approvals:[])}catch(w){i(w.message||"Unable to load device approvals")}finally{u(!1)}},[o]);s.useEffect(()=>{k()},[k]);const v=s.useMemo(()=>{const w=n.map(te=>({...te,status:Cn(te.status)})).sort((te,ee)=>{const be=new Date(te.created_at||0).getTime(),Re=new Date(ee.created_at||0).getTime();return be-Re});if(o!=="pending")return w;const W=new Set,F=[];for(const te of w){const ee=te.ssl_key_fingerprint_claimed||te.hostname_claimed||te.id;W.has(ee)||(W.add(ee),F.push(te))}return F},[n,o]),j=s.useCallback((w,W)=>{h(F=>({...F,[w]:W}))},[]),B=s.useCallback(async(w,W={})=>{if(w!=null&&w.id){y(w.id),p(null),i("");try{const F=(l[w.id]||"").trim(),te={},ee=W.guid;let be="";typeof ee=="string"?be=ee.trim():ee!=null&&(be=String(ee).trim()),be?te.guid=be:F&&(te.guid=F);const Re=W.conflictResolution||W.resolution;typeof Re=="string"&&Re.trim()&&(te.conflict_resolution=Re.trim().toLowerCase());const Ae=await fetch(`/api/admin/device-approvals/${encodeURIComponent(w.id)}/approve`,{method:"POST",credentials:"include",headers:{"Content-Type":"application/json"},body:JSON.stringify(Object.keys(te).length?te:{})}),Le=await Ae.json().catch(()=>({}));if(!Ae.ok){if(Ae.status===409&&Le.error==="conflict_resolution_required"){const V=w.hostname_conflict,O=w.alternate_hostname||(w.hostname_claimed?`${w.hostname_claimed}-1`:"");V&&I({record:w,conflict:V,alternate:O||""});return}throw new Error(Le.error||`Approval failed (${Ae.status})`)}const Fe=(Le.conflict_resolution||te.conflict_resolution||"").toLowerCase();let je="Enrollment approved";Fe==="overwrite"?je="Enrollment approved; existing device overwritten":Fe==="coexist"?je="Enrollment approved; devices will co-exist":Fe==="auto_merge_fingerprint"&&(je="Enrollment approved; device reconnected with its existing identity"),p({type:"success",message:je}),await k()}catch(F){p({type:"error",message:F.message||"Unable to approve request"})}finally{y(null)}}},[l,k]),R=s.useCallback(w=>{if(!(w!=null&&w.id)||Cn(w.status)!=="pending")return;const F=(l[w.id]||"").trim(),te=w.hostname_conflict;if(!!((te==null?void 0:te.requires_prompt)??w.conflict_requires_prompt)&&!F){const be=w.alternate_hostname||(w.hostname_claimed?`${w.hostname_claimed}-1`:"");I({record:w,conflict:te,alternate:be||""});return}B(w)},[l,B]),x=s.useCallback(()=>{I(null)},[]),S=s.useCallback(()=>{if(!(C!=null&&C.record)){I(null);return}const{record:w,conflict:W}=C;I(null);const F=(W==null?void 0:W.guid)!=null?String(W.guid).trim():"";B(w,{guid:F,conflictResolution:"overwrite"})},[C,B]),z=s.useCallback(()=>{if(!(C!=null&&C.record)){I(null);return}const{record:w}=C;I(null),B(w,{conflictResolution:"coexist"})},[C,B]),E=C==null?void 0:C.record,U=C==null?void 0:C.conflict,X=(E==null?void 0:E.hostname_claimed)||(E==null?void 0:E.hostname)||"",ue=(U==null?void 0:U.site_name)||"",Se=U&&ue?`under site ${ue}`:"under site (not assigned)",ce=(C==null?void 0:C.alternate)||(X?`${X}-1`:"hostname-1"),de=(U==null?void 0:U.guid)||"",me=s.useCallback(async w=>{if(!(!(w!=null&&w.id)||!window.confirm("Deny this enrollment request?"))){y(w.id),p(null),i("");try{const F=await fetch(`/api/admin/device-approvals/${encodeURIComponent(w.id)}/deny`,{method:"POST",credentials:"include"});if(!F.ok){const te=await F.json().catch(()=>({}));throw new Error(te.error||`Deny failed (${F.status})`)}p({type:"success",message:"Enrollment denied"}),await k()}catch(F){p({type:"error",message:F.message||"Unable to deny request"})}finally{y(null)}}},[k]);return e.jsxs(m,{sx:{p:3,display:"flex",flexDirection:"column",gap:3},children:[e.jsxs(ds,{direction:"row",alignItems:"center",spacing:2,children:[e.jsx(Ar,{color:"primary"}),e.jsx($,{variant:"h5",children:"Device Approval Queue"})]}),e.jsxs(Qe,{sx:{p:2,display:"flex",flexDirection:"column",gap:2},children:[e.jsxs(ds,{direction:{xs:"column",sm:"row"},spacing:2,alignItems:{xs:"stretch",sm:"center"},children:[e.jsxs(Ht,{size:"small",sx:{minWidth:200},children:[e.jsx(Gt,{id:"approval-status-filter-label",children:"Status"}),e.jsx(wt,{labelId:"approval-status-filter-label",label:"Status",value:o,onChange:w=>a(w.target.value),children:Zl.map(w=>e.jsx(fe,{value:w.value,children:w.label},w.value))})]}),e.jsx(Z,{variant:"outlined",startIcon:e.jsx(Ss,{}),onClick:k,disabled:d,children:"Refresh"})]}),c?e.jsx(rn,{severity:c.type,variant:"outlined",onClose:()=>p(null),children:c.message}):null,r?e.jsx(rn,{severity:"error",variant:"outlined",children:r}):null,e.jsx(bo,{component:Qe,variant:"outlined",sx:{maxHeight:480},children:e.jsxs(Rt,{size:"small",stickyHeader:!0,children:[e.jsx(Bt,{children:e.jsxs(Ue,{children:[e.jsx(Q,{children:"Status"}),e.jsx(Q,{children:"Hostname"}),e.jsx(Q,{children:"Fingerprint"}),e.jsx(Q,{children:"Enrollment Code"}),e.jsx(Q,{children:"Created"}),e.jsx(Q,{children:"Updated"}),e.jsx(Q,{children:"Approved By"}),e.jsx(Q,{align:"right",children:"Actions"})]})}),e.jsx(Nt,{children:d?e.jsx(Ue,{children:e.jsx(Q,{colSpan:8,align:"center",children:e.jsxs(ds,{direction:"row",spacing:1,alignItems:"center",justifyContent:"center",children:[e.jsx(Mt,{size:20}),e.jsx($,{variant:"body2",children:"Loading approvals…"})]})})}):v.length===0?e.jsx(Ue,{children:e.jsx(Q,{colSpan:8,align:"center",children:e.jsx($,{variant:"body2",color:"text.secondary",children:"No enrollment requests match this filter."})})}):v.map(w=>{const W=Cn(w.status),F=W==="pending",te=l[w.id]||"",ee=w.approved_by_username||w.approved_by_user_id;return e.jsxs(Ue,{hover:!0,children:[e.jsx(Q,{children:e.jsx(yo,{size:"small",label:W,color:ec[W]||"default",variant:"outlined"})}),e.jsx(Q,{children:w.hostname_claimed||"—"}),e.jsx(Q,{sx:{fontFamily:"monospace",whiteSpace:"nowrap"},children:tc(w.ssl_key_fingerprint_claimed)}),e.jsx(Q,{sx:{fontFamily:"monospace"},children:w.enrollment_code_id||"—"}),e.jsx(Q,{children:ro(w.created_at)}),e.jsx(Q,{children:ro(w.updated_at)}),e.jsx(Q,{children:ee||"—"}),e.jsx(Q,{align:"right",children:F?e.jsxs(ds,{direction:{xs:"column",sm:"row"},spacing:1,alignItems:"center",children:[e.jsx(Ie,{size:"small",label:"Optional GUID",placeholder:"Leave empty to auto-generate",value:te,onChange:be=>j(w.id,be.target.value),sx:{minWidth:200}}),e.jsxs(ds,{direction:"row",spacing:1,children:[e.jsx(st,{title:"Approve enrollment",children:e.jsx("span",{children:e.jsx(nt,{color:"success",onClick:()=>R(w),disabled:f===w.id,children:f===w.id?e.jsx(Mt,{color:"success",size:20}):e.jsx(Br,{fontSize:"small"})})})}),e.jsx(st,{title:"Deny enrollment",children:e.jsx("span",{children:e.jsx(nt,{color:"error",onClick:()=>me(w),disabled:f===w.id,children:e.jsx(Or,{fontSize:"small"})})})})]})]}):e.jsx($,{variant:"body2",color:"text.secondary",children:"No actions available"})})]},w.id)})})]})})]}),e.jsxs(Ze,{open:!!C,onClose:x,maxWidth:"sm",fullWidth:!0,children:[e.jsx(et,{children:"Hostname Conflict"}),e.jsx(rt,{dividers:!0,children:e.jsxs(ds,{spacing:2,children:[e.jsx($t,{children:X?`Device ${X} already exists in the database ${Se}.`:`A device with this hostname already exists in the database ${Se}.`}),e.jsx($t,{children:"Do you want this device to overwrite the existing device, or allow both to co-exist?"}),e.jsx($t,{children:`Device will be renamed ${ce} if you choose to allow both to co-exist.`}),de?e.jsxs($,{variant:"body2",color:"text.secondary",children:["Existing device GUID: ",de]}):null]})}),e.jsxs(tt,{children:[e.jsx(Z,{onClick:x,children:"Cancel"}),e.jsx(Z,{onClick:z,color:"info",variant:"outlined",children:"Allow Both"}),e.jsx(Z,{onClick:S,color:"primary",variant:"contained",disabled:!de,children:"Overwrite Existing"})]})]})]})}const nc=es.memo(sc);window.BorealisSocket||(window.BorealisSocket=qr(window.location.origin,{transports:["websocket"]}));window.BorealisUpdateRate||(window.BorealisUpdateRate=200);const oc=Object.assign({"./Nodes/Agent/Node_Agent.jsx":Kr,"./Nodes/Agent/Node_Agent_Role_Macro.jsx":sa,"./Nodes/Agent/Node_Agent_Role_Screenshot.jsx":ra,"./Nodes/Alerting/Node_Alert_Sound.jsx":ca,"./Nodes/Data Analysis & Manipulation/Node_Array_Index_Extractor.jsx":pa,"./Nodes/Data Analysis & Manipulation/Node_JSON_Display.jsx":ma,"./Nodes/Data Analysis & Manipulation/Node_JSON_Value_Extractor.jsx":ba,"./Nodes/Data Analysis & Manipulation/Node_OCR_Text_Extraction.jsx":Sa,"./Nodes/Data Analysis & Manipulation/Node_Regex_Replace.jsx":ka,"./Nodes/Data Analysis & Manipulation/Node_Regex_Search.jsx":Na,"./Nodes/Data Analysis & Manipulation/Node_TextArray_Display.jsx":Ba,"./Nodes/Data Collection/Node_API_Request.jsx":Ea,"./Nodes/Data Collection/Node_Upload_Text.jsx":za,"./Nodes/Flow Control/Node_Edge_Toggle.jsx":$a,"./Nodes/General Purpose/Node_Data.jsx":Va,"./Nodes/General Purpose/Node_Logical_Operators.jsx":qa,"./Nodes/General Purpose/Node_Math_Operation.jsx":Ka,"./Nodes/Image Processing/Node_Adjust_Contrast.jsx":Za,"./Nodes/Image Processing/Node_BW_Threshold.jsx":si,"./Nodes/Image Processing/Node_Convert_to_Grayscale.jsx":ri,"./Nodes/Image Processing/Node_Export_Image.jsx":li,"./Nodes/Image Processing/Node_Image_Viewer.jsx":ui,"./Nodes/Image Processing/Node_Upload_Image.jsx":hi,"./Nodes/Organization/Node_Backdrop_Group_Box.jsx":gi,"./Nodes/Reporting/Node_Export_to_CSV.jsx":ji,"./Nodes/Templates/Node_Template.jsx":Si}),Ao={},zs={};Object.entries(oc).forEach(([n,t])=>{const o=t.default;if(!o)return;const{type:a,component:d}=o;if(!a||!d)return;const r=n.replace("./Nodes/","").split("/")[0];zs[r]||(zs[r]=[]),zs[r].push(o),Ao[a]=d});const ao=Pr({palette:{mode:"dark",background:{default:"#121212",paper:"#1e1e1e"},text:{primary:"#ffffff"}},components:{MuiTooltip:{styleOverrides:{tooltip:{backgroundColor:"#2a2a2a",color:"#ccc",fontSize:"0.75rem",border:"1px solid #444"},arrow:{color:"#2a2a2a"}}}}}),io="borealis_persistent_state";function rc(){var Ot,_t,Yt,ss;const[n,t]=s.useState([{id:"flow_1",tab_name:"Flow 1",nodes:[],edges:[]}]),[o,a]=s.useState("flow_1"),[d,u]=s.useState("devices"),[r,i]=s.useState(null),[c,p]=s.useState(null),[l,h]=s.useState(!1),[f,y]=s.useState(!1),[C,I]=s.useState(null),[k,v]=s.useState(""),[j,B]=s.useState(null),[R,x]=s.useState(null),S=s.useRef(null),[z,E]=s.useState(null),[U,X]=s.useState(null),[ue,Se]=s.useState(null),[ce,de]=s.useState(null),[me,w]=s.useState(0),[W,F]=s.useState(null),[te,ee]=s.useState(!1),be=s.useRef(window.location.pathname+window.location.search),Re=s.useRef(null),[Ae,Le]=s.useState(!1),Fe=[{key:"hostname",label:"Hostname",scope:"device",placeholder:"Search Hostname"},{key:"internal_ip",label:"Internal IP",scope:"device",placeholder:"Search Internal IP"},{key:"external_ip",label:"External IP",scope:"device",placeholder:"Search External IP"},{key:"description",label:"Description",scope:"device",placeholder:"Search Description"},{key:"last_user",label:"Last User",scope:"device",placeholder:"Search Last User"},{key:"serial_number",label:"Serial Number (Soon)",scope:"device",placeholder:"Search Serial Number"},{key:"site_name",label:"Site Name",scope:"site",placeholder:"Search Site Name"},{key:"site_description",label:"Site Description",scope:"site",placeholder:"Search Site Description"}],[je,V]=s.useState("hostname"),[O,M]=s.useState(!1),[g,L]=s.useState(""),[we,T]=s.useState(null),[G,ie]=s.useState({devices:[],sites:[],q:"",field:""}),Ce=s.useRef(null),Ee=s.useRef(null),Ne=s.useCallback((A,q)=>{const le=String(A??""),he=String(q??"").trim();if(!he)return le;try{const _=he.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),K=new RegExp(`(${_})`,"ig");return le.split(K).map((re,ke)=>re.toLowerCase()===he.toLowerCase()?e.jsx("span",{style:{backgroundColor:"#243a52",color:"#a7d0ff",borderRadius:2,padding:"0 1px"},children:re},ke):e.jsx("span",{children:re},ke))}catch{return le}},[]),Ke=s.useCallback((A,q={})=>{var le;switch(A){case"login":return"/login";case"sites":return"/sites";case"devices":return"/devices";case"agent_devices":return"/devices/agent";case"ssh_devices":return"/devices/ssh";case"winrm_devices":return"/devices/winrm";case"device_details":{const he=q.device||r||(q.deviceId?{agent_guid:q.deviceId,hostname:q.deviceName||q.deviceId}:null),_=(he==null?void 0:he.agent_guid)||(he==null?void 0:he.guid)||((le=he==null?void 0:he.summary)==null?void 0:le.agent_guid)||(he==null?void 0:he.hostname)||(he==null?void 0:he.id);return _?`/device/${encodeURIComponent(_)}`:"/devices"}case"jobs":return"/scheduling";case"create_job":return"/scheduling/create_job";case"workflows":return"/workflows";case"workflow-editor":return"/workflows/editor";case"assemblies":return"/assemblies";case"scripts":case"ansible_editor":{const he=A==="ansible_editor"?"ansible":"scripts",_=new URLSearchParams;he==="ansible"&&_.set("mode","ansible");const K=q.assemblyState||W;K!=null&&K.path&&_.set("path",K.path);const pe=_.toString();return pe?`/assemblies/editor?${pe}`:"/assemblies/editor"}case"access_credentials":return"/access_management/credentials";case"access_github_token":return"/access_management/github_token";case"access_users":return"/access_management/users";case"server_info":return"/admin/server_info";case"admin_enrollment_codes":return"/admin/enrollment-codes";case"admin_device_approvals":return"/admin/device-approvals";default:return"/devices"}},[W,r]),at=s.useCallback(A=>{try{const q=new URL(A||"/",window.location.origin);let le=q.pathname||"/";le.length>1&&le.endsWith("/")&&(le=le.slice(0,-1));const he=le.split("/").filter(Boolean),_=q.searchParams;if(le==="/login")return{page:"login",options:{}};if(le==="/"||le==="")return{page:"devices",options:{}};if(le==="/devices")return{page:"devices",options:{}};if(le==="/devices/agent")return{page:"agent_devices",options:{}};if(le==="/devices/ssh")return{page:"ssh_devices",options:{}};if(le==="/devices/winrm")return{page:"winrm_devices",options:{}};if(he[0]==="device"&&he[1]){const K=decodeURIComponent(he[1]);return{page:"device_details",options:{device:{agent_guid:K,hostname:K}}}}if(le==="/sites")return{page:"sites",options:{}};if(le==="/scheduling")return{page:"jobs",options:{}};if(le==="/scheduling/create_job")return{page:"create_job",options:{}};if(le==="/workflows")return{page:"workflows",options:{}};if(le==="/workflows/editor")return{page:"workflow-editor",options:{}};if(le==="/assemblies")return{page:"assemblies",options:{}};if(le==="/assemblies/editor"){const K=_.get("mode"),pe=_.get("path")||"",re=pe?{path:pe,mode:K==="ansible"?"ansible":"scripts",nonce:Date.now()}:null;return{page:K==="ansible"?"ansible_editor":"scripts",options:re?{assemblyState:re}:{}}}return le==="/access_management/users"?{page:"access_users",options:{}}:le==="/access_management/github_token"?{page:"access_github_token",options:{}}:le==="/access_management/credentials"?{page:"access_credentials",options:{}}:le==="/admin/server_info"?{page:"server_info",options:{}}:le==="/admin/enrollment-codes"?{page:"admin_enrollment_codes",options:{}}:le==="/admin/device-approvals"?{page:"admin_device_approvals",options:{}}:{page:"devices",options:{}}}catch{return{page:"devices",options:{}}}},[]),ut=s.useCallback((A,q={})=>{if(u(A),A==="device_details"){if(q.device)i(q.device);else if(q.deviceId){const le=q.deviceId,he=q.deviceName||q.deviceId;i(_=>{const K=(_==null?void 0:_.agent_guid)||(_==null?void 0:_.guid)||(_==null?void 0:_.hostname)||"";return K===le||K===he?_:{agent_guid:le,hostname:he}})}}else q.preserveDevice||i(null);(A==="scripts"||A==="ansible_editor")&&q.assemblyState&&F(q.assemblyState)},[F,u,i]),Pe=s.useCallback((A,q={})=>{const{replace:le=!1,allowUnauthenticated:he=!1,suppressPending:_=!1}=q,K=Ke(A,q);if(!he&&!z&&A!=="login"){!_&&K&&(Re.current=K),ut("login",{});const pe="/login",re=le?"replaceState":"pushState",ke=window.location.pathname+window.location.search;(le||ke!==pe)&&window.history[re]({},"",pe);return}if(A==="login"){ut("login",{});const pe="/login",re=le?"replaceState":"pushState",ke=window.location.pathname+window.location.search;(le||ke!==pe)&&window.history[re]({},"",pe);return}if(Re.current=null,ut(A,q),K){const pe=le?"replaceState":"pushState",re=window.location.pathname+window.location.search;(le||re!==K)&&window.history[pe]({},"",K)}},[Ke,ut,z]),gt=s.useCallback((A,{replace:q=!1,allowUnauthenticated:le=!1}={})=>{const{page:he,options:_}=at(A);Pe(he,{..._||{},replace:q,allowUnauthenticated:le})},[at,Pe]),bt=s.useRef(Pe),vt=s.useRef(gt);s.useEffect(()=>{bt.current=Pe,vt.current=gt},[Pe,gt]);const Ut=es.useMemo(()=>{const A=[];switch(d){case"sites":A.push({label:"Sites",page:"sites"}),A.push({label:"Site List",page:"sites"});break;case"devices":A.push({label:"Inventory",page:"devices"}),A.push({label:"Devices",page:"devices"});break;case"device_details":A.push({label:"Devices",page:"devices"}),A.push({label:"Device List",page:"devices"}),A.push({label:"Device Details"});break;case"jobs":A.push({label:"Automation",page:"jobs"}),A.push({label:"Scheduled Jobs",page:"jobs"});break;case"create_job":A.push({label:"Automation",page:"jobs"}),A.push({label:"Scheduled Jobs",page:"jobs"}),A.push({label:ce?"Edit Job":"Create Job",page:"create_job"});break;case"workflows":A.push({label:"Automation",page:"jobs"}),A.push({label:"Workflows",page:"workflows"});break;case"workflow-editor":A.push({label:"Automation",page:"jobs"}),A.push({label:"Workflows",page:"workflows"}),A.push({label:"Flow Editor"});break;case"scripts":A.push({label:"Automation",page:"jobs"}),A.push({label:"Scripts",page:"scripts"});break;case"ansible_editor":A.push({label:"Automation",page:"jobs"}),A.push({label:"Ansible Playbooks",page:"assemblies"}),A.push({label:"Playbook Editor"});break;case"assemblies":A.push({label:"Automation",page:"jobs"}),A.push({label:"Assemblies",page:"assemblies"});break;case"community":A.push({label:"Automation",page:"jobs"}),A.push({label:"Community Content",page:"community"});break;case"agent_devices":A.push({label:"Inventory",page:"devices"}),A.push({label:"Devices",page:"devices"}),A.push({label:"Agent Devices",page:"agent_devices"});break;case"ssh_devices":A.push({label:"Inventory",page:"devices"}),A.push({label:"Devices",page:"devices"}),A.push({label:"SSH Devices",page:"ssh_devices"});break;case"winrm_devices":A.push({label:"Inventory",page:"devices"}),A.push({label:"Devices",page:"devices"}),A.push({label:"WinRM Devices",page:"winrm_devices"});break;case"access_credentials":A.push({label:"Access Management",page:"access_credentials"}),A.push({label:"Credentials",page:"access_credentials"});break;case"access_github_token":A.push({label:"Access Management",page:"access_credentials"}),A.push({label:"GitHub API Token",page:"access_github_token"});break;case"access_users":A.push({label:"Access Management",page:"access_credentials"}),A.push({label:"Users",page:"access_users"});break;case"server_info":A.push({label:"Admin Settings"}),A.push({label:"Server Info",page:"server_info"});break;case"admin_enrollment_codes":A.push({label:"Admin Settings",page:"server_info"}),A.push({label:"Installer Codes",page:"admin_enrollment_codes"});break;case"admin_device_approvals":A.push({label:"Admin Settings",page:"server_info"}),A.push({label:"Device Approvals",page:"admin_device_approvals"});break;case"filters":A.push({label:"Filters & Groups",page:"filters"}),A.push({label:"Filters",page:"filters"});break;case"groups":A.push({label:"Filters & Groups",page:"filters"}),A.push({label:"Groups",page:"groups"});break;default:d&&A.push({label:String(d)})}return A},[d,r,ce]);s.useEffect(()=>{let A=!1;return(async()=>{const le=localStorage.getItem("borealis_session");if(le)try{const he=JSON.parse(le);Date.now()-he.timestamp<3600*1e3?A||(E(he.username),X(he.role||null),Se(he.display_name||he.username)):localStorage.removeItem("borealis_session")}catch{localStorage.removeItem("borealis_session")}try{const he=await fetch("/api/auth/me",{credentials:"include"});if(he.ok){const _=await he.json();A||(E(_.username),X(_.role||null),Se(_.display_name||_.username)),localStorage.setItem("borealis_session",JSON.stringify({username:_.username,display_name:_.display_name||_.username,role:_.role,timestamp:Date.now()}))}}catch{}A||ee(!0)})(),()=>{A=!0}},[]),s.useEffect(()=>{if(!te)return;const A=bt.current,q=vt.current;if(z){const le=be.current,he=window.location.pathname+window.location.search;q(le&&le!=="/login"?le:he==="/login"||he===""?"/devices":he,{replace:!0,allowUnauthenticated:!0}),be.current=null,Re.current=null}else{const le=be.current,he=window.location.pathname+window.location.search,_=le&&!le.startsWith("/login")?le:he.startsWith("/login")?null:he;_&&(Re.current=_),A("login",{replace:!0,allowUnauthenticated:!0,suppressPending:!0})}},[te,z]),s.useEffect(()=>{if(!te)return;const A=()=>{const q=window.location.pathname+window.location.search;if(!z){q.startsWith("/login")||(Re.current=q),bt.current("login",{replace:!0,allowUnauthenticated:!0,suppressPending:!0});return}vt.current(q,{replace:!0,allowUnauthenticated:!0})};return window.addEventListener("popstate",A),()=>window.removeEventListener("popstate",A)},[te,z]);const It=s.useCallback((A,q)=>{const le=String(q||"").trim();if(le.length<3){ie({devices:[],sites:[],q:le,field:A});return}const he=new URLSearchParams({field:A,q:le,limit:"5"});fetch(`/api/search/suggest?${he.toString()}`).then(_=>_.ok?_.json():{devices:[],sites:[],q:le,field:A}).then(_=>ie(_)).catch(()=>ie({devices:[],sites:[],q:le,field:A}))},[]);s.useEffect(()=>{if(O)return Ee.current&&clearTimeout(Ee.current),Ee.current=setTimeout(()=>{It(je,g)},220),()=>{Ee.current&&clearTimeout(Ee.current)}},[O,je,g,It]);const yt=s.useCallback(async(A,q,le=!0)=>{var _;if((Fe.find(K=>K.key===A)||Fe[0]).scope==="site"){try{localStorage.setItem("site_list_initial_filters",JSON.stringify(A==="site_name"?{name:q}:{description:q}))}catch{}le&&Pe("sites")}else{const pe={hostname:"hostname",description:"description",last_user:"lastUser",internal_ip:"internalIp",external_ip:"externalIp",serial_number:"serialNumber"}[A]||"hostname",re=String(q||"").toLowerCase(),ke=(G.devices||[]).find(N=>String(N.hostname||N.value||"").toLowerCase()===re);if(ke&&(ke.hostname||"").trim()){const N={hostname:ke.hostname.trim()};le?Pe("device_details",{device:N}):i(N)}else if(A==="hostname")try{const N=await fetch(`/api/device/details/${encodeURIComponent(q)}`);if(N.ok){const H=await N.json();if(H&&((_=H.summary)!=null&&_.hostname||Object.keys(H).length>0)){const Y={hostname:q};le?Pe("device_details",{device:Y}):i(Y)}else{try{localStorage.setItem("device_list_initial_filters",JSON.stringify({[pe]:q}))}catch{}le&&Pe("devices")}}else{try{localStorage.setItem("device_list_initial_filters",JSON.stringify({[pe]:q}))}catch{}le&&Pe("devices")}}catch{try{localStorage.setItem("device_list_initial_filters",JSON.stringify({[pe]:q}))}catch{}le&&Pe("devices")}else{try{const N=pe==="serialNumber"?{}:{[pe]:q};localStorage.setItem("device_list_initial_filters",JSON.stringify(N))}catch{}le&&Pe("devices")}}M(!1)},[Fe,Pe,G.devices]),pt=({username:A,role:q})=>{E(A),X(q||null),Se(A),localStorage.setItem("borealis_session",JSON.stringify({username:A,display_name:A,role:q||null,timestamp:Date.now()})),(async()=>{try{const le=await fetch("/api/auth/me",{credentials:"include"});if(le.ok){const he=await le.json();Se(he.display_name||he.username),localStorage.setItem("borealis_session",JSON.stringify({username:he.username,display_name:he.display_name||he.username,role:he.role,timestamp:Date.now()}))}}catch{}})(),Re.current?(gt(Re.current,{replace:!0,allowUnauthenticated:!0}),Re.current=null):Pe("devices",{replace:!0,allowUnauthenticated:!0})};s.useEffect(()=>{const A=localStorage.getItem(io);if(A)try{const q=JSON.parse(A);Array.isArray(q.tabs)&&q.activeTabId&&(t(q.tabs),a(q.activeTabId))}catch(q){console.warn("Failed to parse saved state:",q)}},[]),s.useEffect(()=>{const A=setTimeout(()=>{const q=JSON.stringify({tabs:n,activeTabId:o});localStorage.setItem(io,q)},1e3);return()=>clearTimeout(A)},[n,o]);const St=s.useCallback((A,q)=>{const le=q||o;t(he=>he.map(_=>_.id===le?{..._,nodes:typeof A=="function"?A(_.nodes):A}:_))},[o]),ct=s.useCallback((A,q)=>{const le=q||o;t(he=>he.map(_=>_.id===le?{..._,edges:typeof A=="function"?A(_.edges):A}:_))},[o]),oe=A=>p(A.currentTarget),_e=()=>p(null),$e=async()=>{try{await fetch("/api/auth/logout",{method:"POST",credentials:"include"})}catch{}try{localStorage.removeItem("borealis_session")}catch{}E(null),X(null),Se(null),Pe("login",{replace:!0,allowUnauthenticated:!0,suppressPending:!0})},Xe=(A,q)=>{A.preventDefault(),B({x:A.clientX,y:A.clientY}),x(q)},We=()=>{t(A=>{const q=A.filter(le=>le.id!==R);if(q.length===0){const le={id:"flow_1",tab_name:"Flow 1",nodes:[],edges:[]};return a(le.id),[le]}return o===R&&a(q[0].id),q}),B(null)},Je=()=>{const A=n.find(q=>q.id===R);A&&(I(R),v(A.tab_name),y(!0)),B(null)},ft=()=>{t(A=>A.map(q=>q.id===C?{...q,tab_name:k}:q)),y(!1)},ht=s.useCallback(()=>{const A=n.find(pe=>pe.id===o);if(!A)return;const q={tab_name:A.tab_name,nodes:A.nodes,edges:A.edges},le=`${A.tab_name||"workflow"}.json`,he=new Blob([JSON.stringify(q,null,2)],{type:"application/json"}),_=URL.createObjectURL(he),K=document.createElement("a");K.href=_,K.download=le,K.click(),URL.revokeObjectURL(_)},[n,o]),Jt=s.useCallback(()=>{S.current&&(S.current.value=null,S.current.click())},[]),Ct=s.useCallback(A=>{const q=A.target.files&&A.target.files[0];if(!q)return;const le=new FileReader;le.onload=()=>{try{const he=JSON.parse(le.result),_="flow_"+Date.now();t(K=>[...K,{id:_,tab_name:he.tab_name||he.name||q.name.replace(/\.json$/i,""),nodes:he.nodes||[],edges:he.edges||[]}]),a(_),Pe("workflow-editor")}catch(he){console.error("Failed to import workflow:",he)}},le.readAsText(q),A.target.value=""},[Pe,t]),Wt=s.useCallback(async A=>{const q=n.find(he=>he.id===o);if(!q||!A)return;const le={path:q.folderPath?`${q.folderPath}/${A}`:A,workflow:{tab_name:q.tab_name,nodes:q.nodes,edges:q.edges}};try{const he={island:"workflows",kind:"file",path:le.path,content:le.workflow};await fetch("/api/assembly/create",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(he)}),t(_=>_.map(K=>K.id===o?{...K,tab_name:A}:K))}catch(he){console.error("Failed to save workflow:",he)}},[n,o]),lt=String(U||"").toLowerCase()==="admin";s.useEffect(()=>{!lt&&(d==="server_info"||d==="admin_enrollment_codes"||d==="admin_device_approvals"||d==="access_credentials"||d==="access_github_token"||d==="access_users"||d==="ssh_devices"||d==="winrm_devices"||d==="agent_devices")&&(Le(!0),Pe("devices",{replace:!0,suppressPending:!0}))},[d,lt,Pe]);const Dt=()=>{var A;switch(d){case"sites":return e.jsx(Ji,{onOpenDevicesForSite:q=>{try{localStorage.setItem("device_list_initial_site_filter",String(q||""))}catch{}Pe("devices")}});case"devices":return e.jsx(_o,{onSelectDevice:q=>{Pe("device_details",{device:q})}});case"agent_devices":return e.jsx(tl,{onSelectDevice:q=>{Pe("device_details",{device:q})}});case"ssh_devices":return e.jsx(ko,{});case"winrm_devices":return e.jsx(nl,{});case"device_details":return e.jsx(el,{device:r,onBack:()=>{Pe("devices"),i(null)}});case"jobs":return e.jsx(Sl,{onCreateJob:()=>{de(null),Pe("create_job")},onEditJob:q=>{de(q),Pe("create_job")},refreshToken:me});case"create_job":return e.jsx(Tl,{initialJob:ce,onCancel:()=>{Pe("jobs"),de(null)},onCreated:()=>{Pe("jobs"),de(null),w(Date.now())}});case"workflows":return e.jsx(Xn,{onOpenWorkflow:async(q,le,he)=>{const _="flow_"+Date.now();if(q&&q.rel_path){const K=q.rel_path.split("/").slice(0,-1).join("/");try{const pe=await fetch(`/api/assembly/load?island=workflows&path=${encodeURIComponent(q.rel_path)}`);if(!pe.ok)throw new Error(`HTTP ${pe.status}`);const re=await pe.json();t([{id:_,tab_name:re.tab_name||q.name||q.file_name||"Workflow",nodes:re.nodes||[],edges:re.edges||[],folderPath:K}])}catch(pe){console.error("Failed to load workflow:",pe),t([{id:_,tab_name:(q==null?void 0:q.name)||"Workflow",nodes:[],edges:[],folderPath:K}])}}else t([{id:_,tab_name:he||"Flow",nodes:[],edges:[],folderPath:le||""}]);a(_),Pe("workflow-editor")},onOpenScript:(q,le,he)=>{const _=Date.now();F({path:q||"",mode:le,context:he?{...he,nonce:_}:null,nonce:_}),Pe(le==="ansible"?"ansible_editor":"scripts",{assemblyState:{path:q||"",mode:le,context:he?{...he,nonce:_}:null,nonce:_}})}});case"assemblies":return e.jsx(Xn,{onOpenWorkflow:async(q,le,he)=>{const _="flow_"+Date.now();if(q&&q.rel_path){const K=q.rel_path.split("/").slice(0,-1).join("/");try{const pe=await fetch(`/api/assembly/load?island=workflows&path=${encodeURIComponent(q.rel_path)}`);if(!pe.ok)throw new Error(`HTTP ${pe.status}`);const re=await pe.json();t([{id:_,tab_name:re.tab_name||q.name||q.file_name||"Workflow",nodes:re.nodes||[],edges:re.edges||[],folderPath:K}])}catch(pe){console.error("Failed to load workflow:",pe),t([{id:_,tab_name:(q==null?void 0:q.name)||"Workflow",nodes:[],edges:[],folderPath:K}])}}else t([{id:_,tab_name:he||"Flow",nodes:[],edges:[],folderPath:le||""}]);a(_),Pe("workflow-editor")},onOpenScript:(q,le,he)=>{const _=Date.now();F({path:q||"",mode:le,context:he?{...he,nonce:_}:null,nonce:_}),Pe(le==="ansible"?"ansible_editor":"scripts",{assemblyState:{path:q||"",mode:le,context:he?{...he,nonce:_}:null,nonce:_}})}});case"scripts":return e.jsx(Zn,{mode:"scripts",initialPath:(W==null?void 0:W.mode)==="scripts"&&(W==null?void 0:W.path)||"",initialContext:(W==null?void 0:W.mode)==="scripts"?W==null?void 0:W.context:null,onConsumeInitialData:()=>F(q=>q&&q.mode==="scripts"?null:q),onSaved:()=>Pe("assemblies")});case"ansible_editor":return e.jsx(Zn,{mode:"ansible",initialPath:(W==null?void 0:W.mode)==="ansible"&&(W==null?void 0:W.path)||"",initialContext:(W==null?void 0:W.mode)==="ansible"?W==null?void 0:W.context:null,onConsumeInitialData:()=>F(q=>q&&q.mode==="ansible"?null:q),onSaved:()=>Pe("assemblies")});case"access_credentials":return e.jsx(zl,{isAdmin:lt});case"access_github_token":return e.jsx(Gl,{isAdmin:lt});case"access_users":return e.jsx(Wl,{isAdmin:lt});case"server_info":return e.jsx(ql,{isAdmin:lt});case"admin_enrollment_codes":return e.jsx(Ql,{});case"admin_device_approvals":return e.jsx(nc,{});case"workflow-editor":return e.jsxs(m,{sx:{display:"flex",flexDirection:"column",flexGrow:1,overflow:"hidden"},children:[e.jsxs(m,{sx:{display:"flex",flexGrow:1,overflow:"hidden"},children:[e.jsx(Vi,{categorizedNodes:zs,handleExportFlow:ht,handleImportFlow:Jt,handleSaveFlow:Wt,handleOpenCloseAllDialog:()=>h(!0),fileInputRef:S,onFileInputChange:Ct,currentTabName:(A=n.find(q=>q.id===o))==null?void 0:A.tab_name}),e.jsxs(m,{sx:{display:"flex",flexDirection:"column",flexGrow:1,overflow:"hidden"},children:[e.jsx(Li,{tabs:n,activeTabId:o,onTabChange:a,onAddTab:()=>{},onTabRightClick:Xe}),e.jsx(m,{sx:{flexGrow:1,position:"relative"},children:n.map(q=>e.jsx(m,{sx:{position:"absolute",top:0,bottom:0,left:0,right:0,display:q.id===o?"block":"none"},children:e.jsx(Do,{id:q.id,children:e.jsx(Wi,{flowId:q.id,nodes:q.nodes,edges:q.edges,setNodes:le=>St(le,q.id),setEdges:le=>ct(le,q.id),nodeTypes:Ao,categorizedNodes:zs})})},q.id))})]})]}),e.jsx(Gi,{})]});default:return e.jsx(m,{sx:{p:2},children:e.jsx($,{children:"Select a section from navigation."})})}};return z?e.jsxs($n,{theme:ao,children:[e.jsx(Un,{}),e.jsxs(m,{sx:{width:"100vw",height:"100vh",display:"flex",flexDirection:"column",overflow:"hidden"},children:[e.jsx(Er,{position:"static",sx:{bgcolor:"#16191d"},children:e.jsxs(Mr,{sx:{minHeight:"36px",position:"relative"},children:[e.jsx(m,{component:"img",src:"/Borealis_Logo_Full.png",alt:"Borealis Logo",sx:{height:"52px",marginRight:"8px"}}),e.jsx(m,{sx:{position:"absolute",left:"calc(260px + 550px)",bottom:6,display:"flex",alignItems:"flex-end",pointerEvents:"none"},children:e.jsx(Dr,{separator:e.jsx(zr,{fontSize:"inherit",sx:{color:"#6b6b6b"}}),"aria-label":"breadcrumb",sx:{color:"#9aa0a6",fontSize:"0.825rem","& .MuiBreadcrumbs-separator":{mx:.6},pointerEvents:"auto"},children:Ut.map((A,q)=>A.page?e.jsx(Z,{onClick:()=>Pe(A.page),size:"small",sx:{color:"#7db7ff",textTransform:"none",minWidth:0,p:0,fontSize:"0.825rem"},children:A.label},q):e.jsx($,{component:"span",sx:{color:"#e0e0e0",fontSize:"0.825rem"},children:A.label},q))})}),e.jsx(Fr,{onClickAway:()=>M(!1),children:e.jsxs(m,{sx:{display:"flex",alignItems:"center",gap:.5,ml:2},children:[e.jsx(Z,{variant:"outlined",size:"small",onClick:A=>T(A.currentTarget),endIcon:we?e.jsx(Lr,{}):e.jsx($r,{}),sx:{height:32,color:"#ddd",left:-11,bottom:-6,borderColor:"#3a3f44",textTransform:"none",bgcolor:"#1e2328","&:hover":{borderColor:"#4b5158",bgcolor:"#22272e"},minWidth:160,justifyContent:"space-between"},children:(Fe.find(A=>A.key===je)||{}).label||"Hostname"}),e.jsx(Et,{anchorEl:we,open:!!we,onClose:()=>T(null),PaperProps:{sx:{bgcolor:"#1e1e1e",color:"#fff",minWidth:240}},children:Fe.map(A=>e.jsx(fe,{onClick:()=>{V(A.key),T(null),L(""),ie({devices:[],sites:[],q:"",field:""})},children:A.label},A.key))}),e.jsxs(m,{ref:Ce,sx:{position:"relative",left:-2,bottom:-6,display:"flex",alignItems:"center",border:"1px solid #3a3f44",borderRadius:1,height:32,minWidth:320,bgcolor:"#1e2328"},children:[e.jsx("input",{value:g,onChange:A=>{L(A.target.value),M(!0)},onFocus:()=>M(!0),onKeyDown:A=>{A.key==="Enter"?yt(je,g):A.key==="Escape"&&M(!1)},placeholder:(Fe.find(A=>A.key===je)||{}).placeholder||"Search",style:{outline:"none",border:"none",background:"transparent",color:"#e8eaed",paddingLeft:10,paddingRight:28,width:360,height:"100%"}}),e.jsx(Ur,{sx:{position:"absolute",right:6,color:"#8aa0b4",fontSize:18}}),O&&(((Ot=Fe.find(A=>A.key===je))==null?void 0:Ot.scope)==="device"&&(G.devices||[]).length>0||((_t=Fe.find(A=>A.key===je))==null?void 0:_t.scope)==="site"&&(G.sites||[]).length>0)&&e.jsxs(m,{sx:{position:"absolute",top:"100%",left:0,right:0,bgcolor:"#1e2328",border:"1px solid #3a3f44",borderTop:"none",zIndex:1400,borderRadius:"0 0 6px 6px",maxHeight:320,overflowY:"auto"},children:[(G.devices||[]).length>0&&((Yt=Fe.find(A=>A.key===je))==null?void 0:Yt.scope)==="device"&&e.jsxs(m,{sx:{borderBottom:"1px solid #2b2f34"},children:[e.jsx(m,{sx:{display:"flex",alignItems:"center",px:1.2,py:.8,color:"#9aa0a6",fontSize:12},children:"Devices"}),G.devices&&G.devices.length>0?G.devices.map((A,q)=>{const le=je==="hostname"?Ne(A.hostname||A.value,g):A.hostname||A.value;let he="";je==="internal_ip"?he=A.internal_ip||"":je==="external_ip"?he=A.external_ip||"":je==="description"?he=A.description||"":je==="last_user"&&(he=A.last_user||"");const _=je!=="hostname"&&he?Ne(he,g):A.internal_ip||A.external_ip||A.description||A.last_user||"";return e.jsxs(m,{onClick:()=>{Pe("device_details",{device:{hostname:A.hostname||A.value}}),M(!1)},sx:{px:1.2,py:.6,"&:hover":{bgcolor:"#22272e"},cursor:"pointer"},children:[e.jsx($,{variant:"body2",sx:{color:"#e8eaed"},children:le}),e.jsxs($,{variant:"caption",sx:{color:"#9aa0a6"},children:[A.site_name||"",A.site_name&&(he||A.internal_ip||A.external_ip||A.description||A.last_user)?" • ":"",_]})]},q)}):e.jsx(m,{sx:{px:1.2,py:1,color:"#6b737c",fontSize:12},children:je==="serial_number"?"Serial numbers are not tracked yet.":"No matches"})]}),(G.sites||[]).length>0&&((ss=Fe.find(A=>A.key===je))==null?void 0:ss.scope)==="site"&&e.jsxs(m,{children:[e.jsx(m,{sx:{display:"flex",alignItems:"center",px:1.2,py:.8,color:"#9aa0a6",fontSize:12},children:"Sites"}),G.sites&&G.sites.length>0?G.sites.map((A,q)=>e.jsxs(m,{onClick:()=>yt(je,A.value),sx:{px:1.2,py:.6,"&:hover":{bgcolor:"#22272e"},cursor:"pointer"},children:[e.jsx($,{variant:"body2",sx:{color:"#e8eaed"},children:je==="site_name"?Ne(A.site_name,g):A.site_name}),e.jsx($,{variant:"caption",sx:{color:"#9aa0a6"},children:je==="site_description"?Ne(A.site_description||"",g):A.site_description||""})]},q)):e.jsx(m,{sx:{px:1.2,py:1,color:"#6b737c",fontSize:12},children:"No matches"})]})]})]})]})}),e.jsx(m,{sx:{flexGrow:1}}),e.jsx(Z,{color:"inherit",onClick:oe,endIcon:e.jsx(Wr,{}),sx:{height:"36px"},children:ue||z||"User"}),e.jsx(Et,{anchorEl:c,open:!!c,onClose:_e,children:e.jsxs(fe,{onClick:()=>{_e(),$e()},children:[e.jsx(Vr,{sx:{fontSize:18,color:"#ff6b6b",mr:1}})," Logout"]})})]})}),e.jsxs(m,{sx:{display:"flex",flexGrow:1,overflow:"auto",minHeight:0},children:[e.jsx(Fi,{currentPage:d,onNavigate:Pe,isAdmin:lt}),e.jsx(m,{sx:{flexGrow:1,display:"flex",flexDirection:"column",overflow:"auto",minHeight:0,"& > *":{alignSelf:"stretch",minHeight:"calc(100% - 32px)"}},children:Dt()})]})]}),e.jsx(Ci,{open:l,onClose:()=>h(!1),onConfirm:()=>{}}),e.jsx(Ii,{open:f,value:k,onChange:v,onCancel:()=>y(!1),onSave:ft}),e.jsx(Oi,{anchor:j,onClose:()=>B(null),onRename:Je,onCloseTab:We}),e.jsx(_i,{open:Ae,onClose:()=>Le(!1)})]}):e.jsxs($n,{theme:ao,children:[e.jsx(Un,{}),e.jsx(qi,{onLogin:pt})]})}const ac=Oo.createRoot(document.getElementById("root"));ac.render(e.jsx(es.StrictMode,{children:e.jsx(rc,{})}));
|