@xenon-device-management/xenon 2.2.0 → 2.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (105) hide show
  1. package/lib/package.json +1 -1
  2. package/lib/public/assets/{AnnotationOverlay-XpewX5nn.js → AnnotationOverlay-CpoWcXKP.js} +1 -1
  3. package/lib/public/assets/{ApiKeyGate-BQDv3ZCC.js → ApiKeyGate-DAYuoJDl.js} +1 -1
  4. package/lib/public/assets/{BugReportButton-C7OmS61B.js → BugReportButton-DEXyENUv.js} +1 -1
  5. package/lib/public/assets/DeviceMosaicView-C-sJRz63.js +2 -0
  6. package/lib/public/assets/{EmptyState-fPxujqqE.js → EmptyState-B_JRYedM.js} +1 -1
  7. package/lib/public/assets/{FieldGroup-5bCutWrs.js → FieldGroup-CorXlSLU.js} +1 -1
  8. package/lib/public/assets/{FilterMenu-owsBiDT1.js → FilterMenu-BKv95DEc.js} +1 -1
  9. package/lib/public/assets/{Menu-DFhqzPSt.js → Menu-Cpy5yMwg.js} +1 -1
  10. package/lib/public/assets/{Modal-Bw-a-E-e.js → Modal-Djp4NvyZ.js} +1 -1
  11. package/lib/public/assets/{RecordingPage-WtByf5bC.js → RecordingPage-CP57OKw9.js} +1 -1
  12. package/lib/public/assets/{RecordingsPage-FpWWFNgT.js → RecordingsPage-BjrTit38.js} +1 -1
  13. package/lib/public/assets/{SegmentedControl-Jzn9c7o8.js → SegmentedControl-MGTzJhBf.js} +1 -1
  14. package/lib/public/assets/{SettingCard-BR7nOhpT.js → SettingCard-CYBPhKPe.js} +1 -1
  15. package/lib/public/assets/{Table-B_Va3V05.js → Table-CdKQ9hnU.js} +1 -1
  16. package/lib/public/assets/{activity-DxRFWvkN.js → activity-QsRK21QF.js} +1 -1
  17. package/lib/public/assets/{ai-settings-CQf-9_V6.js → ai-settings-Dn6DtRn7.js} +1 -1
  18. package/lib/public/assets/{api-keys-SoE1Kd7N.js → api-keys-DYyf17eU.js} +1 -1
  19. package/lib/public/assets/{apps-CgGXTlgn.js → apps-HKFKTe1J.js} +1 -1
  20. package/lib/public/assets/{arrow-left-uQ6WIwiC.js → arrow-left-BkA7oMRe.js} +1 -1
  21. package/lib/public/assets/{arrow-right-C9RyfzXS.js → arrow-right-BsSr58EU.js} +1 -1
  22. package/lib/public/assets/{arrow-up-right-DFHi_8yG.js → arrow-up-right-B7TEV_Gr.js} +1 -1
  23. package/lib/public/assets/{auth-shell-Bii1t4qc.js → auth-shell-BlmNHGcG.js} +2 -2
  24. package/lib/public/assets/{builds-page-Bnv8Z9hi.js → builds-page-E4WIKtl8.js} +1 -1
  25. package/lib/public/assets/{button-_Y78wXiP.js → button-BIwCF2bR.js} +1 -1
  26. package/lib/public/assets/{calendar-D4MqSOc2.js → calendar-CMLnXC7N.js} +1 -1
  27. package/lib/public/assets/{check-uGHCXe-L.js → check-zugO3p5U.js} +1 -1
  28. package/lib/public/assets/{chevron-left-Dy1OqpzB.js → chevron-left-sCqxpTY6.js} +1 -1
  29. package/lib/public/assets/{chevron-right-BUsldEli.js → chevron-right-Bb59xwZc.js} +1 -1
  30. package/lib/public/assets/{circle-check-D3Qq0tKp.js → circle-check-DsvxbnTg.js} +1 -1
  31. package/lib/public/assets/{circle-x-B4IOD1DE.js → circle-x-w69AbmbW.js} +1 -1
  32. package/lib/public/assets/{clock-BfYfzvSg.js → clock-C6XOs4bc.js} +1 -1
  33. package/lib/public/assets/{copy-DZwYE5Va.js → copy-pHk-SWBM.js} +1 -1
  34. package/lib/public/assets/{device-explorer-CRG4Utt5.js → device-explorer-BDq38IcO.js} +52 -52
  35. package/lib/public/assets/{download-CCDYo_TN.js → download-CAHtPZmY.js} +1 -1
  36. package/lib/public/assets/{forgot-password-DuLCmVFb.js → forgot-password-cmvhGOUu.js} +1 -1
  37. package/lib/public/assets/{funnel-CtKNPqzb.js → funnel-BrDuhOtM.js} +1 -1
  38. package/lib/public/assets/{index-3uxl3o7K.js → index-BQCXPOXt.js} +2 -2
  39. package/lib/public/assets/{index-Zy1Op5C1.js → index-C-Q4QkXb.js} +1 -1
  40. package/lib/public/assets/{input-CzTWvUXZ.js → input-DnUVHYax.js} +1 -1
  41. package/lib/public/assets/{keycodes-CI-nYDFM.js → keycodes-CmOptFVa.js} +4 -4
  42. package/lib/public/assets/{layers-YZZGFyTX.js → layers-DRtz_bzF.js} +1 -1
  43. package/lib/public/assets/{lock-L8tzWgDo.js → lock-DF2VnPFm.js} +1 -1
  44. package/lib/public/assets/{login-DBbX-fu8.js → login-DHYffYa4.js} +1 -1
  45. package/lib/public/assets/{maintenance-settings-AJwkOIsE.js → maintenance-settings-r0uPsJ6n.js} +1 -1
  46. package/lib/public/assets/{monitor-Di_66F2m.js → monitor-7nt9oGNx.js} +1 -1
  47. package/lib/public/assets/{mouse-pointer-2-Cnab2zdg.js → mouse-pointer-2-ys1MKVr2.js} +1 -1
  48. package/lib/public/assets/{network-DiSumY-1.js → network-B8m-F79k.js} +1 -1
  49. package/lib/public/assets/{overview-CwE4gXl5.js → overview-BHEntlXz.js} +1 -1
  50. package/lib/public/assets/{page-header-CfR4Sm9V.js → page-header-CuFXVUop.js} +1 -1
  51. package/lib/public/assets/{plus-DOS8P9CQ.js → plus-DUSlMac2.js} +1 -1
  52. package/lib/public/assets/{profile-page-BYpHwQIH.js → profile-page-CBamPy_h.js} +1 -1
  53. package/lib/public/assets/{reset-password-BRVJU_qV.js → reset-password-DG0vZl-o.js} +1 -1
  54. package/lib/public/assets/{runbook-page-Bi3JvAFZ.js → runbook-page-5S3T-I4g.js} +1 -1
  55. package/lib/public/assets/{select-Cqx7pEou.js → select-f0ci1QC7.js} +1 -1
  56. package/lib/public/assets/{selector-detail-page-C0DsncKj.js → selector-detail-page-BXA9LUf9.js} +1 -1
  57. package/lib/public/assets/{selector-health-CAhpdilF.js → selector-health-TyMPgAWo.js} +1 -1
  58. package/lib/public/assets/{selector-health-page-CrCVeW2m.js → selector-health-page-uBlXy33G.js} +1 -1
  59. package/lib/public/assets/{session-detail-page-F_hwYqEt.js → session-detail-page-DECim5lh.js} +1 -1
  60. package/lib/public/assets/{settings-C-s5pypL.js → settings-IfOFbqtv.js} +1 -1
  61. package/lib/public/assets/{status-pill-outline-DY5uzv6A.js → status-pill-outline-grXLf8I8.js} +1 -1
  62. package/lib/public/assets/{tablet-Dli7gwyg.js → tablet-lmFk4qxW.js} +1 -1
  63. package/lib/public/assets/{teams-ui4IhHNC.js → teams-CwMSjVVW.js} +1 -1
  64. package/lib/public/assets/{trash-2-BV4hSmXJ.js → trash-2-BKsgmBS6.js} +1 -1
  65. package/lib/public/assets/{upload-DkGy_J-L.js → upload-DXH47sQS.js} +1 -1
  66. package/lib/public/assets/{use-password-reset-mode-BFtMqQOh.js → use-password-reset-mode-DU98dxpc.js} +1 -1
  67. package/lib/public/assets/{users-Nb_rzRmF.js → users-V5O64rVx.js} +1 -1
  68. package/lib/public/assets/{users-BU0nXIVe.js → users-eXWwQZjX.js} +1 -1
  69. package/lib/public/assets/{video-off-CUNzD2kH.js → video-off-BuoIHEYy.js} +1 -1
  70. package/lib/public/assets/{webhook-settings-Ca3UFXZe.js → webhook-settings-ClsxsKnC.js} +1 -1
  71. package/lib/public/assets/{zap-B2bH2vKX.js → zap-I10vdQXd.js} +1 -1
  72. package/lib/public/index.html +1 -1
  73. package/lib/src/app/routers/control.js +114 -61
  74. package/lib/src/app/routers/nodePhoneControl.js +288 -46
  75. package/lib/src/data-service/device-store.js +7 -3
  76. package/lib/src/data-service/deviceClaims.js +14 -0
  77. package/lib/src/data-service/deviceFieldOwners.js +3 -1
  78. package/lib/src/data-service/prisma-store.js +3 -3
  79. package/lib/src/device-managers/AndroidDeviceManager.js +11 -1
  80. package/lib/src/gateway/forwardToNode.js +10 -3
  81. package/lib/src/generated/client/edge.js +5 -4
  82. package/lib/src/generated/client/index-browser.js +2 -1
  83. package/lib/src/generated/client/index.d.ts +36 -1
  84. package/lib/src/generated/client/index.js +5 -4
  85. package/lib/src/generated/client/package.json +1 -1
  86. package/lib/src/generated/client/schema.prisma +4 -0
  87. package/lib/src/generated/client/wasm.js +2 -1
  88. package/lib/src/services/recording/RecordingOrchestrator.js +39 -5
  89. package/lib/src/services/recording/busy-precheck.js +5 -2
  90. package/lib/src/services/recording/nodeRecordingSource.js +156 -0
  91. package/lib/test/unit/AndroidDeviceManager.spec.js +12 -0
  92. package/lib/test/unit/busy-precheck.spec.js +32 -0
  93. package/lib/test/unit/hub-node-control-forward.spec.js +66 -10
  94. package/lib/test/unit/hub-node-race.spec.js +29 -3
  95. package/lib/test/unit/mark-node-busy-loki.spec.js +17 -4
  96. package/lib/test/unit/node-phone-control.spec.js +124 -4
  97. package/lib/test/unit/node-recording-relay.spec.js +165 -0
  98. package/lib/test/unit/recording-orchestrator.spec.js +86 -2
  99. package/lib/test/unit/screenshot-route.spec.js +104 -0
  100. package/lib/test/unit/upload-install-route.spec.js +205 -0
  101. package/lib/tsconfig.tsbuildinfo +1 -1
  102. package/package.json +1 -1
  103. package/prisma/migrations/20261001120000_device_node_hold/migration.sql +2 -0
  104. package/prisma/schema.prisma +4 -0
  105. package/lib/public/assets/DeviceMosaicView-wl3l2Zlt.js +0 -2
@@ -1,4 +1,4 @@
1
- import{c as a}from"./index-3uxl3o7K.js";/**
1
+ import{c as a}from"./index-BQCXPOXt.js";/**
2
2
  * @license lucide-react v0.555.0 - ISC
3
3
  *
4
4
  * This source code is licensed under the ISC license.
@@ -8,14 +8,14 @@ import{c as a}from"./index-3uxl3o7K.js";/**
8
8
  *
9
9
  * This source code is licensed under the ISC license.
10
10
  * See the LICENSE file in the root directory of this source tree.
11
- */const e=[["circle",{cx:"12",cy:"12",r:"10",key:"1mglay"}]],n=a("circle",e);/**
11
+ */const o=[["circle",{cx:"12",cy:"12",r:"10",key:"1mglay"}]],i=a("circle",o);/**
12
12
  * @license lucide-react v0.555.0 - ISC
13
13
  *
14
14
  * This source code is licensed under the ISC license.
15
15
  * See the LICENSE file in the root directory of this source tree.
16
- */const o=[["path",{d:"M15 21v-8a1 1 0 0 0-1-1h-4a1 1 0 0 0-1 1v8",key:"5wwlr5"}],["path",{d:"M3 10a2 2 0 0 1 .709-1.528l7-6a2 2 0 0 1 2.582 0l7 6A2 2 0 0 1 21 10v9a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z",key:"r6nss1"}]],_=a("house",o);/**
16
+ */const s=[["path",{d:"M15 21v-8a1 1 0 0 0-1-1h-4a1 1 0 0 0-1 1v8",key:"5wwlr5"}],["path",{d:"M3 10a2 2 0 0 1 .709-1.528l7-6a2 2 0 0 1 2.582 0l7 6A2 2 0 0 1 21 10v9a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z",key:"r6nss1"}]],l=a("house",s);/**
17
17
  * @license lucide-react v0.555.0 - ISC
18
18
  *
19
19
  * This source code is licensed under the ISC license.
20
20
  * See the LICENSE file in the root directory of this source tree.
21
- */const s=[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2",key:"afitv7"}]],i=a("square",s),l={HOME:3,BACK:4,APP_SWITCH:187,VOLUME_UP:24,VOLUME_DOWN:25},O={HOME:"home",VOLUME_UP:"volumeup",VOLUME_DOWN:"volumedown"};export{l as A,n as C,_ as H,O as I,i as S,r as a};
21
+ */const n=[["rect",{width:"18",height:"18",x:"3",y:"3",rx:"2",key:"afitv7"}]],_=a("square",n);function d(e){return e.session_id||e.nodeHold||null}const u={HOME:3,BACK:4,APP_SWITCH:187,VOLUME_UP:24,VOLUME_DOWN:25},O={HOME:"home",VOLUME_UP:"volumeup",VOLUME_DOWN:"volumedown"};export{u as A,i as C,l as H,O as I,_ as S,r as a,d as h};
@@ -1,4 +1,4 @@
1
- import{c as a}from"./index-3uxl3o7K.js";/**
1
+ import{c as a}from"./index-BQCXPOXt.js";/**
2
2
  * @license lucide-react v0.555.0 - ISC
3
3
  *
4
4
  * This source code is licensed under the ISC license.
@@ -1,4 +1,4 @@
1
- import{c}from"./index-3uxl3o7K.js";/**
1
+ import{c}from"./index-BQCXPOXt.js";/**
2
2
  * @license lucide-react v0.555.0 - ISC
3
3
  *
4
4
  * This source code is licensed under the ISC license.
@@ -1,4 +1,4 @@
1
- import{c as g,L as X,u as z,a as H,b as K,r as a,d as O,j as e,N as B,I as W,e as Y,C as _,f as G,l as J}from"./index-3uxl3o7K.js";import{c as Q}from"./utils-CDN07tui.js";import{u as V}from"./use-password-reset-mode-BFtMqQOh.js";import{A as Z}from"./auth-shell-Bii1t4qc.js";import{L as ee}from"./lock-L8tzWgDo.js";import{C as te}from"./clock-BfYfzvSg.js";import{A as se}from"./arrow-right-C9RyfzXS.js";import"./network-DiSumY-1.js";/**
1
+ import{c as g,L as X,u as z,a as H,b as K,r as a,d as O,j as e,N as B,I as W,e as Y,C as _,f as G,l as J}from"./index-BQCXPOXt.js";import{c as Q}from"./utils-CDN07tui.js";import{u as V}from"./use-password-reset-mode-DU98dxpc.js";import{A as Z}from"./auth-shell-BlmNHGcG.js";import{L as ee}from"./lock-DF2VnPFm.js";import{C as te}from"./clock-C6XOs4bc.js";import{A as se}from"./arrow-right-BsSr58EU.js";import"./network-B8m-F79k.js";/**
2
2
  * @license lucide-react v0.555.0 - ISC
3
3
  *
4
4
  * This source code is licensed under the ISC license.
@@ -1,4 +1,4 @@
1
- import{c as N,t as M,r as d,X as C,j as e,A as D,S as y,I as w,Q as A}from"./index-3uxl3o7K.js";/* empty css */import{S as o,A as k}from"./SettingCard-BR7nOhpT.js";import{P as B}from"./page-header-CfR4Sm9V.js";import{T as z}from"./trash-2-BV4hSmXJ.js";import{C as E}from"./check-uGHCXe-L.js";import{C as R}from"./calendar-D4MqSOc2.js";import"./button-_Y78wXiP.js";import"./utils-CDN07tui.js";/**
1
+ import{c as N,t as M,r as d,X as C,j as e,A as D,S as y,I as w,Q as A}from"./index-BQCXPOXt.js";/* empty css */import{S as o,A as k}from"./SettingCard-CYBPhKPe.js";import{P as B}from"./page-header-CuFXVUop.js";import{T as z}from"./trash-2-BKsgmBS6.js";import{C as E}from"./check-zugO3p5U.js";import{C as R}from"./calendar-CMLnXC7N.js";import"./button-BIwCF2bR.js";import"./utils-CDN07tui.js";/**
2
2
  * @license lucide-react v0.555.0 - ISC
3
3
  *
4
4
  * This source code is licensed under the ISC license.
@@ -1,4 +1,4 @@
1
- import{c as e}from"./index-3uxl3o7K.js";/**
1
+ import{c as e}from"./index-BQCXPOXt.js";/**
2
2
  * @license lucide-react v0.555.0 - ISC
3
3
  *
4
4
  * This source code is licensed under the ISC license.
@@ -1,4 +1,4 @@
1
- import{c as e}from"./index-3uxl3o7K.js";/**
1
+ import{c as e}from"./index-BQCXPOXt.js";/**
2
2
  * @license lucide-react v0.555.0 - ISC
3
3
  *
4
4
  * This source code is licensed under the ISC license.
@@ -1,4 +1,4 @@
1
- import{c as e}from"./index-3uxl3o7K.js";/**
1
+ import{c as e}from"./index-BQCXPOXt.js";/**
2
2
  * @license lucide-react v0.555.0 - ISC
3
3
  *
4
4
  * This source code is licensed under the ISC license.
@@ -1 +1 @@
1
- import{r as h,p as y,X as p,j as e,u as E,T as R,q as T,s as H}from"./index-3uxl3o7K.js";import{p as M}from"./labels-C21SA4JG.js";import{F as L}from"./funnel-CtKNPqzb.js";import{A as O}from"./arrow-right-C9RyfzXS.js";import{T as B}from"./tablet-Dli7gwyg.js";import{M as P}from"./monitor-Di_66F2m.js";import{A as U}from"./activity-DxRFWvkN.js";import{P as X}from"./page-header-CfR4Sm9V.js";const k=20;function G(s){return s.deviceName||(s.deviceUdid?s.deviceUdid.slice(0,8):"device")}function C(s){const n=s.commandName||"selector",i=G(s);return s.tier?e.jsxs(e.Fragment,{children:[e.jsx("strong",{children:s.tier})," healed ",e.jsx("strong",{children:n})," on ",e.jsx("strong",{children:i})]}):e.jsxs(e.Fragment,{children:["Healed ",e.jsx("strong",{children:n})," on ",e.jsx("strong",{children:i})]})}function K(){const[s,n]=h.useState([]),[i,x]=h.useState([]),[u,g]=h.useState(0),[a,j]=h.useState([]),{on:m}=y(),F=h.useRef(0);h.useEffect(()=>{let o=!1;const f=()=>{p.getDevices().then(c=>{!o&&Array.isArray(c)&&n(c)}).catch(()=>{})};f();const w=setInterval(f,3e4);return p.getSessions().then(c=>{!o&&Array.isArray(c)&&x(c)}).catch(()=>{}),p.getPendingSessionsCount().then(c=>{if(o)return;const b=typeof c=="number"?c:typeof(c==null?void 0:c.count)=="number"?c.count:0;g(b)}).catch(()=>{}),p.getRecentHealingEvents().then(c=>{if(o||!c)return;const b=Array.isArray(c.events)?c.events:[];b.length!==0&&j(N=>{const S=new Set(N.map(r=>r.id));return[...b.filter(r=>!S.has(r.id)).map(r=>({id:r.id,ts:Date.parse(r.createdAt)||Date.now(),kind:"heal",message:C(r)})),...N].sort((r,l)=>l.ts-r.ts).slice(0,k)})}).catch(()=>{}),()=>{o=!0,clearInterval(w)}},[]),h.useEffect(()=>{const o=[],f=(t,r)=>{F.current+=1;const l={id:`${Date.now()}-${F.current}`,ts:Date.now(),kind:t,message:r};j(d=>[l,...d].slice(0,k))},w=t=>{var d;t&&t.session&&x(v=>v.find($=>$.id===t.session.id)?v:[t.session,...v]);const r=((d=t==null?void 0:t.session)==null?void 0:d.id)||(t==null?void 0:t.sessionId)||"",l=r?r.slice(0,6):"";f("session",e.jsxs(e.Fragment,{children:["Session ",e.jsx("strong",{children:l||"—"})," started"]}))},c=t=>{var v,A;const r=((v=t==null?void 0:t.session)==null?void 0:v.id)||(t==null?void 0:t.sessionId)||"",l=!!((A=t==null?void 0:t.session)!=null&&A.failure_reason||t!=null&&t.failure_reason);r&&x($=>$.map(D=>D.id===r?{...D,status:l?"failed":"finished"}:D));const d=r?r.slice(0,6):"";f(l?"session-failed":"session-end",l?e.jsxs(e.Fragment,{children:["Session ",e.jsx("strong",{children:d||"—"})," failed"]}):e.jsxs(e.Fragment,{children:["Session ",e.jsx("strong",{children:d||"—"})," ended"]}))},b=t=>{const r=(t==null?void 0:t.nodeId)||(t==null?void 0:t.id)||"node";f("node",e.jsxs(e.Fragment,{children:["Node ",e.jsx("strong",{children:String(r)})," connected"]}))},N=t=>{const r=(t==null?void 0:t.nodeId)||(t==null?void 0:t.id)||"node";f("node",e.jsxs(e.Fragment,{children:["Node ",e.jsx("strong",{children:String(r)})," disconnected"]}))},S=t=>{const r=t;if(!r||!r.id)return;const l={id:r.id,ts:Date.parse(r.createdAt)||Date.now(),kind:"heal",message:C(r)};j(d=>d.some(v=>v.id===l.id)?d:[l,...d].slice(0,k))};return o.push(m("session_started",w)),o.push(m("session_stopped",c)),o.push(m("node_connected",b)),o.push(m("node_disconnected",N)),o.push(m("healing_event",S)),()=>{o.forEach(t=>t&&t())}},[m]);const q=i.filter(o=>o.status==="running");return{devices:s,activeSessions:q,queuedSessions:u,activity:a}}const Q={healthy:"bg-[var(--color-success)]",neutral:"bg-[var(--border-strong)]",warn:"bg-[var(--amber)]",critical:"bg-[var(--red)]"},V={healthy:"bg-[var(--color-success)]",neutral:"bg-[var(--text-dim)]",warn:"bg-[var(--amber)]",critical:"bg-[var(--red)]"},Y={healthy:"text-[var(--color-success)]",neutral:"text-[var(--text-muted)]",warn:"text-[var(--amber)]",critical:"text-[var(--red)]"},I=({label:s,value:n,secondaryValue:i,subtitle:x,state:u="neutral"})=>e.jsxs("div",{className:"relative overflow-hidden rounded-lg border border-[var(--border)] bg-[var(--surface)] p-4 hover:border-[var(--border-strong)] transition-colors",children:[e.jsx("span",{className:`absolute left-0 top-0 bottom-0 w-[2px] ${Q[u]}`}),e.jsx("div",{className:"text-[11px] font-semibold text-[var(--text-muted)]",children:s}),e.jsxs("div",{className:"mt-3 flex items-baseline gap-2",children:[e.jsx("span",{className:"text-3xl font-semibold text-[var(--text)] tabular-nums",children:n}),i!=null&&e.jsxs("span",{className:"text-sm font-mono text-[var(--text-dim)]",children:["/ ",i]})]}),e.jsxs("div",{className:`mt-3 flex items-center gap-1.5 text-xs ${Y[u]}`,children:[e.jsx("span",{className:`h-1.5 w-1.5 rounded-full ${V[u]}`}),e.jsx("span",{children:x})]})]});function _(s){return s.offline?"offline":s.reservedBy?"reserved":s.busy?"busy":"ready"}function z(s){const n=(s.platform||"").toLowerCase();return n==="tvos"?R:/pad|tablet/i.test(s.name||"")?B:n==="ios"||n==="android"?T:P}const J={ready:{dot:"bg-[var(--color-success)]",text:"text-[var(--color-success)]",label:"Ready"},busy:{dot:"bg-[var(--amber)]",text:"text-[var(--amber)]",label:"Busy"},reserved:{dot:"bg-[var(--blue)]",text:"text-[var(--blue)]",label:"Reserved"},offline:{dot:"bg-[var(--text-dim)]",text:"text-[var(--text-dim)]",label:"Offline"}};function W(s){return s?s.length<=16?s:`${s.slice(0,8)}…${s.slice(-4)}`:""}const Z=({devices:s,maxRows:n=6})=>{const[i,x]=h.useState("all"),u=E(),g=(i==="all"?s:s.filter(a=>_(a)!=="ready")).slice(0,n);return e.jsxs("section",{className:"rounded-lg border border-[var(--border)] bg-[var(--surface)] flex flex-col",children:[e.jsxs("header",{className:"flex items-center justify-between px-4 py-3 border-b border-[var(--border)]",children:[e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsx("h2",{className:"text-sm font-semibold text-[var(--text)]",children:"Fleet status"}),e.jsxs("span",{className:"text-xs font-mono text-[var(--text-dim)]",children:[s.length," devices"]})]}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsxs("div",{role:"group","aria-label":"Filter devices",className:"flex items-center gap-0.5 bg-[var(--surface-2)] border border-[var(--border)] rounded-md p-0.5",children:[e.jsx("button",{type:"button",onClick:()=>x("all"),"aria-pressed":i==="all",className:`px-2 py-1 text-[11px] rounded transition-colors ${i==="all"?"bg-[var(--border-strong)] text-[var(--text)]":"text-[var(--text-dim)] hover:text-[var(--text)]"}`,children:"All"}),e.jsxs("button",{type:"button",onClick:()=>x("issues"),"aria-pressed":i==="issues",className:`px-2 py-1 text-[11px] rounded transition-colors flex items-center gap-1 ${i==="issues"?"bg-[var(--border-strong)] text-[var(--text)]":"text-[var(--text-dim)] hover:text-[var(--text)]"}`,children:[e.jsx(L,{className:"h-3 w-3"}),"Non-ready"]})]}),e.jsxs("button",{type:"button",onClick:()=>u("/devices"),className:"ml-1 inline-flex items-center gap-1 text-xs text-[var(--text-muted)] hover:text-[var(--text)] transition-colors",children:["View all ",e.jsx(O,{className:"h-3 w-3"})]})]})]}),e.jsx("div",{className:"divide-y divide-[var(--border)]",children:g.length===0?e.jsx("div",{className:"px-4 py-8 text-center text-xs text-[var(--text-dim)]",children:i==="issues"?"All devices are ready.":"No devices registered."}):g.map(a=>{const j=z(a),m=J[_(a)];return e.jsxs("button",{type:"button",onClick:()=>a.udid&&u(`/devices/${a.udid}/control/screen`),className:"w-full flex items-center gap-3 px-4 py-2.5 hover:bg-[var(--surface-2)] transition-colors text-left",children:[e.jsx("span",{className:`h-1.5 w-1.5 rounded-full shrink-0 ${m.dot}`}),e.jsx(j,{className:"h-4 w-4 text-[var(--text-dim)] shrink-0"}),e.jsxs("div",{className:"flex-1 min-w-0 flex items-center gap-3",children:[e.jsx("div",{className:"min-w-0 flex-1",children:e.jsx("div",{className:"text-xs text-[var(--text)] truncate",children:a.name||a.udid})}),e.jsxs("div",{className:"hidden md:block text-[11px] font-mono text-[var(--text-dim)] w-24 text-right",children:[M(a.platform)," ",a.sdk||""]}),e.jsx("div",{className:"hidden lg:block text-[11px] font-mono text-[var(--text-dim)] w-32 text-right",children:W(a.udid)})]}),e.jsx("span",{className:`font-mono text-[10px] font-semibold tracking-wider w-20 text-right ${m.text}`,children:m.label})]},a.udid||a.name)})})]})},ee={session:"bg-[var(--color-accent)]","session-end":"bg-[var(--text-dim)]","session-failed":"bg-[var(--red)]",node:"bg-[var(--blue)]",heal:"bg-[var(--amber)]"};function te(s){const n=new Date(s);return`${String(n.getHours()).padStart(2,"0")}:${String(n.getMinutes()).padStart(2,"0")}`}const se=({events:s,live:n=!0})=>e.jsxs("section",{className:"rounded-lg border border-[var(--border)] bg-[var(--surface)] flex flex-col",children:[e.jsx("header",{className:"flex items-center justify-between px-4 py-3 border-b border-[var(--border)]",children:e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("h2",{className:"text-sm font-semibold text-[var(--text)]",children:"Recent activity"}),e.jsxs("span",{className:"flex items-center gap-1 text-[11px] text-[var(--text-dim)]",children:[e.jsx("span",{className:`h-1.5 w-1.5 rounded-full ${n?"bg-[var(--color-success)] pulse-dot":"bg-[var(--text-dim)]"}`}),n?"Live":"Offline"]})]})}),s.length===0?e.jsxs("div",{className:"flex-1 flex flex-col items-center justify-center px-6 py-10 text-center gap-2",children:[e.jsx("div",{className:"h-10 w-10 rounded-full bg-[var(--surface-2)] border border-[var(--border)] flex items-center justify-center",children:e.jsx(U,{className:"h-5 w-5 text-[var(--text-dim)]"})}),e.jsx("div",{className:"text-sm font-medium text-[var(--text)]",children:"No activity yet"}),e.jsx("div",{className:"text-xs text-[var(--text-dim)] max-w-xs",children:"Session and heal events will appear here as they happen."})]}):e.jsx("div",{className:"flex-1 overflow-y-auto divide-y divide-[var(--border)]",children:s.map(i=>e.jsxs("div",{className:"flex items-center gap-3 px-4 py-2.5",children:[e.jsx("span",{className:"font-mono text-[10px] text-[var(--text-dim)] w-10 shrink-0",children:te(i.ts)}),e.jsx("span",{className:`h-1.5 w-1.5 rounded-full shrink-0 ${ee[i.kind]}`}),e.jsx("span",{className:"text-xs text-[var(--text-muted)] truncate",children:i.message})]},i.id))})]}),re="—",ue=()=>{const s=K(),n=s.devices.length,i=s.devices.filter(g=>!g.offline).length,x=n===0?"neutral":i===n?"healthy":"warn",u=s.activeSessions.length>0?"healthy":s.queuedSessions>0?"warn":"neutral";return e.jsxs("div",{className:"flex-1 min-w-0 overflow-y-auto",children:[e.jsx(X,{icon:H,title:"Overview",subtitle:"Devices, sessions and healing activity across your lab."}),e.jsxs("div",{className:"max-w-7xl mx-auto px-6 py-6",children:[e.jsxs("div",{className:"grid grid-cols-1 sm:grid-cols-2 gap-3 mb-6",children:[e.jsx(I,{label:"Devices online",value:n===0?re:i,secondaryValue:n===0?void 0:n,subtitle:n===0?"No devices registered":`${i} of ${n} online`,state:x}),e.jsx(I,{label:"Active sessions",value:s.activeSessions.length,subtitle:s.queuedSessions>0?`${s.queuedSessions} queued`:"No queue",state:u})]}),e.jsxs("div",{className:"grid grid-cols-1 lg:grid-cols-2 gap-3",children:[e.jsx(Z,{devices:s.devices}),e.jsx(se,{events:s.activity,live:!0})]})]})]})};export{ue as default};
1
+ import{r as h,p as y,X as p,j as e,u as E,T as R,q as T,s as H}from"./index-BQCXPOXt.js";import{p as M}from"./labels-C21SA4JG.js";import{F as L}from"./funnel-BrDuhOtM.js";import{A as O}from"./arrow-right-BsSr58EU.js";import{T as B}from"./tablet-lmFk4qxW.js";import{M as P}from"./monitor-7nt9oGNx.js";import{A as U}from"./activity-QsRK21QF.js";import{P as X}from"./page-header-CuFXVUop.js";const k=20;function G(s){return s.deviceName||(s.deviceUdid?s.deviceUdid.slice(0,8):"device")}function C(s){const n=s.commandName||"selector",i=G(s);return s.tier?e.jsxs(e.Fragment,{children:[e.jsx("strong",{children:s.tier})," healed ",e.jsx("strong",{children:n})," on ",e.jsx("strong",{children:i})]}):e.jsxs(e.Fragment,{children:["Healed ",e.jsx("strong",{children:n})," on ",e.jsx("strong",{children:i})]})}function K(){const[s,n]=h.useState([]),[i,x]=h.useState([]),[u,g]=h.useState(0),[a,j]=h.useState([]),{on:m}=y(),F=h.useRef(0);h.useEffect(()=>{let o=!1;const f=()=>{p.getDevices().then(c=>{!o&&Array.isArray(c)&&n(c)}).catch(()=>{})};f();const w=setInterval(f,3e4);return p.getSessions().then(c=>{!o&&Array.isArray(c)&&x(c)}).catch(()=>{}),p.getPendingSessionsCount().then(c=>{if(o)return;const b=typeof c=="number"?c:typeof(c==null?void 0:c.count)=="number"?c.count:0;g(b)}).catch(()=>{}),p.getRecentHealingEvents().then(c=>{if(o||!c)return;const b=Array.isArray(c.events)?c.events:[];b.length!==0&&j(N=>{const S=new Set(N.map(r=>r.id));return[...b.filter(r=>!S.has(r.id)).map(r=>({id:r.id,ts:Date.parse(r.createdAt)||Date.now(),kind:"heal",message:C(r)})),...N].sort((r,l)=>l.ts-r.ts).slice(0,k)})}).catch(()=>{}),()=>{o=!0,clearInterval(w)}},[]),h.useEffect(()=>{const o=[],f=(t,r)=>{F.current+=1;const l={id:`${Date.now()}-${F.current}`,ts:Date.now(),kind:t,message:r};j(d=>[l,...d].slice(0,k))},w=t=>{var d;t&&t.session&&x(v=>v.find($=>$.id===t.session.id)?v:[t.session,...v]);const r=((d=t==null?void 0:t.session)==null?void 0:d.id)||(t==null?void 0:t.sessionId)||"",l=r?r.slice(0,6):"";f("session",e.jsxs(e.Fragment,{children:["Session ",e.jsx("strong",{children:l||"—"})," started"]}))},c=t=>{var v,A;const r=((v=t==null?void 0:t.session)==null?void 0:v.id)||(t==null?void 0:t.sessionId)||"",l=!!((A=t==null?void 0:t.session)!=null&&A.failure_reason||t!=null&&t.failure_reason);r&&x($=>$.map(D=>D.id===r?{...D,status:l?"failed":"finished"}:D));const d=r?r.slice(0,6):"";f(l?"session-failed":"session-end",l?e.jsxs(e.Fragment,{children:["Session ",e.jsx("strong",{children:d||"—"})," failed"]}):e.jsxs(e.Fragment,{children:["Session ",e.jsx("strong",{children:d||"—"})," ended"]}))},b=t=>{const r=(t==null?void 0:t.nodeId)||(t==null?void 0:t.id)||"node";f("node",e.jsxs(e.Fragment,{children:["Node ",e.jsx("strong",{children:String(r)})," connected"]}))},N=t=>{const r=(t==null?void 0:t.nodeId)||(t==null?void 0:t.id)||"node";f("node",e.jsxs(e.Fragment,{children:["Node ",e.jsx("strong",{children:String(r)})," disconnected"]}))},S=t=>{const r=t;if(!r||!r.id)return;const l={id:r.id,ts:Date.parse(r.createdAt)||Date.now(),kind:"heal",message:C(r)};j(d=>d.some(v=>v.id===l.id)?d:[l,...d].slice(0,k))};return o.push(m("session_started",w)),o.push(m("session_stopped",c)),o.push(m("node_connected",b)),o.push(m("node_disconnected",N)),o.push(m("healing_event",S)),()=>{o.forEach(t=>t&&t())}},[m]);const q=i.filter(o=>o.status==="running");return{devices:s,activeSessions:q,queuedSessions:u,activity:a}}const Q={healthy:"bg-[var(--color-success)]",neutral:"bg-[var(--border-strong)]",warn:"bg-[var(--amber)]",critical:"bg-[var(--red)]"},V={healthy:"bg-[var(--color-success)]",neutral:"bg-[var(--text-dim)]",warn:"bg-[var(--amber)]",critical:"bg-[var(--red)]"},Y={healthy:"text-[var(--color-success)]",neutral:"text-[var(--text-muted)]",warn:"text-[var(--amber)]",critical:"text-[var(--red)]"},I=({label:s,value:n,secondaryValue:i,subtitle:x,state:u="neutral"})=>e.jsxs("div",{className:"relative overflow-hidden rounded-lg border border-[var(--border)] bg-[var(--surface)] p-4 hover:border-[var(--border-strong)] transition-colors",children:[e.jsx("span",{className:`absolute left-0 top-0 bottom-0 w-[2px] ${Q[u]}`}),e.jsx("div",{className:"text-[11px] font-semibold text-[var(--text-muted)]",children:s}),e.jsxs("div",{className:"mt-3 flex items-baseline gap-2",children:[e.jsx("span",{className:"text-3xl font-semibold text-[var(--text)] tabular-nums",children:n}),i!=null&&e.jsxs("span",{className:"text-sm font-mono text-[var(--text-dim)]",children:["/ ",i]})]}),e.jsxs("div",{className:`mt-3 flex items-center gap-1.5 text-xs ${Y[u]}`,children:[e.jsx("span",{className:`h-1.5 w-1.5 rounded-full ${V[u]}`}),e.jsx("span",{children:x})]})]});function _(s){return s.offline?"offline":s.reservedBy?"reserved":s.busy?"busy":"ready"}function z(s){const n=(s.platform||"").toLowerCase();return n==="tvos"?R:/pad|tablet/i.test(s.name||"")?B:n==="ios"||n==="android"?T:P}const J={ready:{dot:"bg-[var(--color-success)]",text:"text-[var(--color-success)]",label:"Ready"},busy:{dot:"bg-[var(--amber)]",text:"text-[var(--amber)]",label:"Busy"},reserved:{dot:"bg-[var(--blue)]",text:"text-[var(--blue)]",label:"Reserved"},offline:{dot:"bg-[var(--text-dim)]",text:"text-[var(--text-dim)]",label:"Offline"}};function W(s){return s?s.length<=16?s:`${s.slice(0,8)}…${s.slice(-4)}`:""}const Z=({devices:s,maxRows:n=6})=>{const[i,x]=h.useState("all"),u=E(),g=(i==="all"?s:s.filter(a=>_(a)!=="ready")).slice(0,n);return e.jsxs("section",{className:"rounded-lg border border-[var(--border)] bg-[var(--surface)] flex flex-col",children:[e.jsxs("header",{className:"flex items-center justify-between px-4 py-3 border-b border-[var(--border)]",children:[e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsx("h2",{className:"text-sm font-semibold text-[var(--text)]",children:"Fleet status"}),e.jsxs("span",{className:"text-xs font-mono text-[var(--text-dim)]",children:[s.length," devices"]})]}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsxs("div",{role:"group","aria-label":"Filter devices",className:"flex items-center gap-0.5 bg-[var(--surface-2)] border border-[var(--border)] rounded-md p-0.5",children:[e.jsx("button",{type:"button",onClick:()=>x("all"),"aria-pressed":i==="all",className:`px-2 py-1 text-[11px] rounded transition-colors ${i==="all"?"bg-[var(--border-strong)] text-[var(--text)]":"text-[var(--text-dim)] hover:text-[var(--text)]"}`,children:"All"}),e.jsxs("button",{type:"button",onClick:()=>x("issues"),"aria-pressed":i==="issues",className:`px-2 py-1 text-[11px] rounded transition-colors flex items-center gap-1 ${i==="issues"?"bg-[var(--border-strong)] text-[var(--text)]":"text-[var(--text-dim)] hover:text-[var(--text)]"}`,children:[e.jsx(L,{className:"h-3 w-3"}),"Non-ready"]})]}),e.jsxs("button",{type:"button",onClick:()=>u("/devices"),className:"ml-1 inline-flex items-center gap-1 text-xs text-[var(--text-muted)] hover:text-[var(--text)] transition-colors",children:["View all ",e.jsx(O,{className:"h-3 w-3"})]})]})]}),e.jsx("div",{className:"divide-y divide-[var(--border)]",children:g.length===0?e.jsx("div",{className:"px-4 py-8 text-center text-xs text-[var(--text-dim)]",children:i==="issues"?"All devices are ready.":"No devices registered."}):g.map(a=>{const j=z(a),m=J[_(a)];return e.jsxs("button",{type:"button",onClick:()=>a.udid&&u(`/devices/${a.udid}/control/screen`),className:"w-full flex items-center gap-3 px-4 py-2.5 hover:bg-[var(--surface-2)] transition-colors text-left",children:[e.jsx("span",{className:`h-1.5 w-1.5 rounded-full shrink-0 ${m.dot}`}),e.jsx(j,{className:"h-4 w-4 text-[var(--text-dim)] shrink-0"}),e.jsxs("div",{className:"flex-1 min-w-0 flex items-center gap-3",children:[e.jsx("div",{className:"min-w-0 flex-1",children:e.jsx("div",{className:"text-xs text-[var(--text)] truncate",children:a.name||a.udid})}),e.jsxs("div",{className:"hidden md:block text-[11px] font-mono text-[var(--text-dim)] w-24 text-right",children:[M(a.platform)," ",a.sdk||""]}),e.jsx("div",{className:"hidden lg:block text-[11px] font-mono text-[var(--text-dim)] w-32 text-right",children:W(a.udid)})]}),e.jsx("span",{className:`font-mono text-[10px] font-semibold tracking-wider w-20 text-right ${m.text}`,children:m.label})]},a.udid||a.name)})})]})},ee={session:"bg-[var(--color-accent)]","session-end":"bg-[var(--text-dim)]","session-failed":"bg-[var(--red)]",node:"bg-[var(--blue)]",heal:"bg-[var(--amber)]"};function te(s){const n=new Date(s);return`${String(n.getHours()).padStart(2,"0")}:${String(n.getMinutes()).padStart(2,"0")}`}const se=({events:s,live:n=!0})=>e.jsxs("section",{className:"rounded-lg border border-[var(--border)] bg-[var(--surface)] flex flex-col",children:[e.jsx("header",{className:"flex items-center justify-between px-4 py-3 border-b border-[var(--border)]",children:e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("h2",{className:"text-sm font-semibold text-[var(--text)]",children:"Recent activity"}),e.jsxs("span",{className:"flex items-center gap-1 text-[11px] text-[var(--text-dim)]",children:[e.jsx("span",{className:`h-1.5 w-1.5 rounded-full ${n?"bg-[var(--color-success)] pulse-dot":"bg-[var(--text-dim)]"}`}),n?"Live":"Offline"]})]})}),s.length===0?e.jsxs("div",{className:"flex-1 flex flex-col items-center justify-center px-6 py-10 text-center gap-2",children:[e.jsx("div",{className:"h-10 w-10 rounded-full bg-[var(--surface-2)] border border-[var(--border)] flex items-center justify-center",children:e.jsx(U,{className:"h-5 w-5 text-[var(--text-dim)]"})}),e.jsx("div",{className:"text-sm font-medium text-[var(--text)]",children:"No activity yet"}),e.jsx("div",{className:"text-xs text-[var(--text-dim)] max-w-xs",children:"Session and heal events will appear here as they happen."})]}):e.jsx("div",{className:"flex-1 overflow-y-auto divide-y divide-[var(--border)]",children:s.map(i=>e.jsxs("div",{className:"flex items-center gap-3 px-4 py-2.5",children:[e.jsx("span",{className:"font-mono text-[10px] text-[var(--text-dim)] w-10 shrink-0",children:te(i.ts)}),e.jsx("span",{className:`h-1.5 w-1.5 rounded-full shrink-0 ${ee[i.kind]}`}),e.jsx("span",{className:"text-xs text-[var(--text-muted)] truncate",children:i.message})]},i.id))})]}),re="—",ue=()=>{const s=K(),n=s.devices.length,i=s.devices.filter(g=>!g.offline).length,x=n===0?"neutral":i===n?"healthy":"warn",u=s.activeSessions.length>0?"healthy":s.queuedSessions>0?"warn":"neutral";return e.jsxs("div",{className:"flex-1 min-w-0 overflow-y-auto",children:[e.jsx(X,{icon:H,title:"Overview",subtitle:"Devices, sessions and healing activity across your lab."}),e.jsxs("div",{className:"max-w-7xl mx-auto px-6 py-6",children:[e.jsxs("div",{className:"grid grid-cols-1 sm:grid-cols-2 gap-3 mb-6",children:[e.jsx(I,{label:"Devices online",value:n===0?re:i,secondaryValue:n===0?void 0:n,subtitle:n===0?"No devices registered":`${i} of ${n} online`,state:x}),e.jsx(I,{label:"Active sessions",value:s.activeSessions.length,subtitle:s.queuedSessions>0?`${s.queuedSessions} queued`:"No queue",state:u})]}),e.jsxs("div",{className:"grid grid-cols-1 lg:grid-cols-2 gap-3",children:[e.jsx(Z,{devices:s.devices}),e.jsx(se,{events:s.activity,live:!0})]})]})]})};export{ue as default};
@@ -1 +1 @@
1
- import{j as e}from"./index-3uxl3o7K.js";const i=({icon:s,children:t})=>e.jsxs("h1",{className:"flex items-center gap-2 text-xl font-semibold tracking-tight text-[var(--text)]",children:[s&&e.jsx(s,{className:"h-5 w-5 text-[var(--color-accent)] shrink-0","aria-hidden":"true"}),e.jsx("span",{className:"truncate",children:t})]}),l=({icon:s,eyebrow:t,title:x,subtitle:a,action:r})=>e.jsx("header",{className:"px-6 pt-6 pb-4 border-b border-[var(--border)]",children:e.jsxs("div",{className:"flex items-start justify-between gap-4",children:[e.jsxs("div",{className:"min-w-0",children:[t&&e.jsx("div",{className:"text-[11px] font-semibold text-[var(--text-dim)] mb-1.5",children:t}),e.jsx(i,{icon:s,children:x}),a&&e.jsx("p",{className:"mt-1.5 text-sm text-[var(--text-muted)] max-w-3xl",children:a})]}),r&&e.jsx("div",{className:"flex items-center gap-2 shrink-0",children:r})]})});export{l as P,i as a};
1
+ import{j as e}from"./index-BQCXPOXt.js";const i=({icon:s,children:t})=>e.jsxs("h1",{className:"flex items-center gap-2 text-xl font-semibold tracking-tight text-[var(--text)]",children:[s&&e.jsx(s,{className:"h-5 w-5 text-[var(--color-accent)] shrink-0","aria-hidden":"true"}),e.jsx("span",{className:"truncate",children:t})]}),l=({icon:s,eyebrow:t,title:x,subtitle:a,action:r})=>e.jsx("header",{className:"px-6 pt-6 pb-4 border-b border-[var(--border)]",children:e.jsxs("div",{className:"flex items-start justify-between gap-4",children:[e.jsxs("div",{className:"min-w-0",children:[t&&e.jsx("div",{className:"text-[11px] font-semibold text-[var(--text-dim)] mb-1.5",children:t}),e.jsx(i,{icon:s,children:x}),a&&e.jsx("p",{className:"mt-1.5 text-sm text-[var(--text-muted)] max-w-3xl",children:a})]}),r&&e.jsx("div",{className:"flex items-center gap-2 shrink-0",children:r})]})});export{l as P,i as a};
@@ -1,4 +1,4 @@
1
- import{c as e}from"./index-3uxl3o7K.js";/**
1
+ import{c as e}from"./index-BQCXPOXt.js";/**
2
2
  * @license lucide-react v0.555.0 - ISC
3
3
  *
4
4
  * This source code is licensed under the ISC license.
@@ -1,4 +1,4 @@
1
- import{c as S,b as N,r as n,j as e,_ as E,A as T}from"./index-3uxl3o7K.js";import{P as A}from"./page-header-CfR4Sm9V.js";import{a as y,f as w}from"./time-B8FIgwPE.js";import{S as C}from"./select-Cqx7pEou.js";import{C as $}from"./copy-DZwYE5Va.js";import{T as D}from"./trash-2-BV4hSmXJ.js";import"./utils-CDN07tui.js";/**
1
+ import{c as S,b as N,r as n,j as e,_ as E,A as T}from"./index-BQCXPOXt.js";import{P as A}from"./page-header-CuFXVUop.js";import{a as y,f as w}from"./time-B8FIgwPE.js";import{S as C}from"./select-f0ci1QC7.js";import{C as $}from"./copy-pHk-SWBM.js";import{T as D}from"./trash-2-BKsgmBS6.js";import"./utils-CDN07tui.js";/**
2
2
  * @license lucide-react v0.555.0 - ISC
3
3
  *
4
4
  * This source code is licensed under the ISC license.
@@ -1 +1 @@
1
- import{i as f,r as s,u as w,k as v,j as e,e as g,m as j}from"./index-3uxl3o7K.js";import{A as d}from"./auth-shell-Bii1t4qc.js";import"./network-DiSumY-1.js";function k(i){return window.location.hash.replace(/^#/,"")||i||void 0}function S(){const i=f(),[r]=s.useState(()=>k(i.token)),u=w(),[a,o]=s.useState("checking"),[n,x]=s.useState(""),[c,h]=s.useState(""),[m,l]=s.useState(null);s.useEffect(()=>{(window.location.hash||i.token)&&window.history.replaceState(null,"","/xenon/reset-password")},[]),s.useEffect(()=>{if(!r){o("invalid");return}v(r).then(t=>o(t?"ready":"invalid"))},[r]);async function p(t){if(t.preventDefault(),l(null),n!==c){l("Passwords do not match.");return}if(n.length<8){l("Password must be at least 8 characters.");return}o("submitting");try{await j(r,n),o("done"),setTimeout(()=>u("/login",{replace:!0}),1500)}catch(b){l(b.message||"Reset failed"),o("ready")}}return a==="checking"?e.jsx(d,{children:e.jsx("div",{className:"text-sm text-[var(--text-muted)] text-center",children:"Checking link…"})}):a==="invalid"?e.jsx(d,{children:e.jsxs("div",{className:"text-center",children:[e.jsx("h1",{className:"text-xl font-semibold mb-3",children:"This link is invalid or expired"}),e.jsx("p",{className:"text-sm text-[var(--text-muted)] mb-6",children:"Reset links are good for 1 hour and single-use. Request a new one."}),e.jsx(g,{to:"/forgot-password",className:"inline-block h-10 px-4 rounded-md bg-[var(--color-accent)] text-[var(--color-on-accent)] text-sm font-medium leading-10",children:"Request a new link"})]})}):a==="done"?e.jsx(d,{children:e.jsxs("div",{className:"text-center",children:[e.jsx("h1",{className:"text-xl font-semibold mb-3",children:"Password updated"}),e.jsx("p",{className:"text-sm text-[var(--text-muted)]",children:"Redirecting to sign in…"})]})}):e.jsx(d,{children:e.jsxs("form",{onSubmit:p,children:[e.jsx("h1",{className:"text-2xl font-semibold mb-1",children:"Reset your password"}),e.jsx("p",{className:"text-sm text-[var(--text-muted)] mb-6",children:"Choose a new password to sign in with."}),e.jsx("label",{htmlFor:"reset-password",className:"block text-sm font-medium text-[var(--text)] mb-1.5",children:"New password"}),e.jsx("input",{id:"reset-password",type:"password",autoComplete:"new-password",value:n,onChange:t=>x(t.target.value),autoFocus:!0,required:!0,className:"w-full mb-3 h-10 px-3 rounded-lg bg-[var(--bg)] border border-[var(--border-strong)] text-sm text-[var(--text)] outline-none focus:border-[var(--color-accent)] focus:shadow-[0_0_0_3px_var(--accent-subtle)]"}),e.jsx("label",{htmlFor:"reset-confirm",className:"block text-sm font-medium text-[var(--text)] mb-1.5",children:"Confirm new password"}),e.jsx("input",{id:"reset-confirm",type:"password",autoComplete:"new-password",value:c,onChange:t=>h(t.target.value),required:!0,className:"w-full mb-3 h-10 px-3 rounded-lg bg-[var(--bg)] border border-[var(--border-strong)] text-sm text-[var(--text)] outline-none focus:border-[var(--color-accent)] focus:shadow-[0_0_0_3px_var(--accent-subtle)]"}),m&&e.jsx("div",{role:"alert",className:"text-sm text-[var(--red)] mb-3",children:m}),e.jsx("button",{type:"submit",disabled:a==="submitting"||n.length<8,className:"mt-5 w-full h-10 rounded-md bg-[var(--color-accent)] text-[var(--color-on-accent)] font-medium text-sm disabled:opacity-50",children:a==="submitting"?"Updating…":"Update password"})]})})}export{S as default};
1
+ import{i as f,r as s,u as w,k as v,j as e,e as g,m as j}from"./index-BQCXPOXt.js";import{A as d}from"./auth-shell-BlmNHGcG.js";import"./network-B8m-F79k.js";function k(i){return window.location.hash.replace(/^#/,"")||i||void 0}function S(){const i=f(),[r]=s.useState(()=>k(i.token)),u=w(),[a,o]=s.useState("checking"),[n,x]=s.useState(""),[c,h]=s.useState(""),[m,l]=s.useState(null);s.useEffect(()=>{(window.location.hash||i.token)&&window.history.replaceState(null,"","/xenon/reset-password")},[]),s.useEffect(()=>{if(!r){o("invalid");return}v(r).then(t=>o(t?"ready":"invalid"))},[r]);async function p(t){if(t.preventDefault(),l(null),n!==c){l("Passwords do not match.");return}if(n.length<8){l("Password must be at least 8 characters.");return}o("submitting");try{await j(r,n),o("done"),setTimeout(()=>u("/login",{replace:!0}),1500)}catch(b){l(b.message||"Reset failed"),o("ready")}}return a==="checking"?e.jsx(d,{children:e.jsx("div",{className:"text-sm text-[var(--text-muted)] text-center",children:"Checking link…"})}):a==="invalid"?e.jsx(d,{children:e.jsxs("div",{className:"text-center",children:[e.jsx("h1",{className:"text-xl font-semibold mb-3",children:"This link is invalid or expired"}),e.jsx("p",{className:"text-sm text-[var(--text-muted)] mb-6",children:"Reset links are good for 1 hour and single-use. Request a new one."}),e.jsx(g,{to:"/forgot-password",className:"inline-block h-10 px-4 rounded-md bg-[var(--color-accent)] text-[var(--color-on-accent)] text-sm font-medium leading-10",children:"Request a new link"})]})}):a==="done"?e.jsx(d,{children:e.jsxs("div",{className:"text-center",children:[e.jsx("h1",{className:"text-xl font-semibold mb-3",children:"Password updated"}),e.jsx("p",{className:"text-sm text-[var(--text-muted)]",children:"Redirecting to sign in…"})]})}):e.jsx(d,{children:e.jsxs("form",{onSubmit:p,children:[e.jsx("h1",{className:"text-2xl font-semibold mb-1",children:"Reset your password"}),e.jsx("p",{className:"text-sm text-[var(--text-muted)] mb-6",children:"Choose a new password to sign in with."}),e.jsx("label",{htmlFor:"reset-password",className:"block text-sm font-medium text-[var(--text)] mb-1.5",children:"New password"}),e.jsx("input",{id:"reset-password",type:"password",autoComplete:"new-password",value:n,onChange:t=>x(t.target.value),autoFocus:!0,required:!0,className:"w-full mb-3 h-10 px-3 rounded-lg bg-[var(--bg)] border border-[var(--border-strong)] text-sm text-[var(--text)] outline-none focus:border-[var(--color-accent)] focus:shadow-[0_0_0_3px_var(--accent-subtle)]"}),e.jsx("label",{htmlFor:"reset-confirm",className:"block text-sm font-medium text-[var(--text)] mb-1.5",children:"Confirm new password"}),e.jsx("input",{id:"reset-confirm",type:"password",autoComplete:"new-password",value:c,onChange:t=>h(t.target.value),required:!0,className:"w-full mb-3 h-10 px-3 rounded-lg bg-[var(--bg)] border border-[var(--border-strong)] text-sm text-[var(--text)] outline-none focus:border-[var(--color-accent)] focus:shadow-[0_0_0_3px_var(--accent-subtle)]"}),m&&e.jsx("div",{role:"alert",className:"text-sm text-[var(--red)] mb-3",children:m}),e.jsx("button",{type:"submit",disabled:a==="submitting"||n.length<8,className:"mt-5 w-full h-10 rounded-md bg-[var(--color-accent)] text-[var(--color-on-accent)] font-medium text-sm disabled:opacity-50",children:a==="submitting"?"Updating…":"Update password"})]})})}export{S as default};
@@ -1,4 +1,4 @@
1
- import{F as Me,R as Ie,i as Ir,u as Tr,j as J,G as Or}from"./index-3uxl3o7K.js";import{A as vr}from"./arrow-left-uQ6WIwiC.js";const qn=["http","https","mailto","tel"];function Lr(e){const n=(e||"").trim(),t=n.charAt(0);if(t==="#"||t==="/")return n;const r=n.indexOf(":");if(r===-1)return n;let i=-1;for(;++i<qn.length;){const l=qn[i];if(r===l.length&&n.slice(0,l.length).toLowerCase()===l)return n}return i=n.indexOf("?"),i!==-1&&r>i||(i=n.indexOf("#"),i!==-1&&r>i)?n:"javascript:void(0)"}/*!
1
+ import{F as Me,R as Ie,i as Ir,u as Tr,j as J,G as Or}from"./index-BQCXPOXt.js";import{A as vr}from"./arrow-left-BkA7oMRe.js";const qn=["http","https","mailto","tel"];function Lr(e){const n=(e||"").trim(),t=n.charAt(0);if(t==="#"||t==="/")return n;const r=n.indexOf(":");if(r===-1)return n;let i=-1;for(;++i<qn.length;){const l=qn[i];if(r===l.length&&n.slice(0,l.length).toLowerCase()===l)return n}return i=n.indexOf("?"),i!==-1&&r>i||(i=n.indexOf("#"),i!==-1&&r>i)?n:"javascript:void(0)"}/*!
2
2
  * Determine if an object is a Buffer
3
3
  *
4
4
  * @author Feross Aboukhadijeh <https://feross.org>
@@ -1 +1 @@
1
- import{r as c,j as m}from"./index-3uxl3o7K.js";import{c as o}from"./utils-CDN07tui.js";const l=c.forwardRef(({className:s,selectSize:e="md",children:t,...a},r)=>m.jsx("select",{ref:r,className:o("select-base",e==="sm"&&"select-sm",s),...a,children:t}));l.displayName="Select";export{l as S};
1
+ import{r as c,j as m}from"./index-BQCXPOXt.js";import{c as o}from"./utils-CDN07tui.js";const l=c.forwardRef(({className:s,selectSize:e="md",children:t,...a},r)=>m.jsx("select",{ref:r,className:o("select-base",e==="sm"&&"select-sm",s),...a,children:t}));l.displayName="Select";export{l as S};
@@ -1 +1 @@
1
- import{u as I,t as A,E as F,r,X as v,j as e,K as f,A as w,C as R,y as D}from"./index-3uxl3o7K.js";import{f as g}from"./time-B8FIgwPE.js";import{P as S}from"./page-header-CfR4Sm9V.js";import{f as P,H as B,V as E,E as H}from"./selector-health-CAhpdilF.js";import{C as M}from"./chevron-left-Dy1OqpzB.js";import{C as L}from"./circle-check-D3Qq0tKp.js";import{Z as U}from"./zap-B2bH2vKX.js";import{L as O}from"./layers-YZZGFyTX.js";import{C as K}from"./check-uGHCXe-L.js";import{C as q}from"./copy-DZwYE5Va.js";function V(d){const h=Date.parse(d);if(!Number.isFinite(h))return"";const x=Math.max(0,Date.now()-h),l=Math.floor(x/1e3);if(l<60)return`${l}s ago`;const i=Math.floor(l/60);if(i<60)return`${i}m ago`;const o=Math.floor(i/60);return o<24?`${o}h ago`:`${Math.floor(o/24)}d ago`}function X(d){return d===0?"$0":d<.01?"<$0.01":`$${d.toFixed(2)}`}const le=()=>{const d=I(),{toast:h}=A(),[x]=F(),l=x.get("value")??"",i=x.get("strategy")??"",o=parseInt(x.get("windowDays")??"30",10)||30,[t,y]=r.useState(null),[a,p]=r.useState(null),[_,C]=r.useState(!1),[$,T]=r.useState(!1),[N,k]=r.useState(null),b=r.useCallback(async()=>{if(l){C(!0);try{const s=await v.getHealingSelectorDetail(l,o);y(s??null)}catch{y(null)}finally{C(!1),T(!0)}}},[l,o]),j=r.useCallback(async()=>{if(!i||!l){p(null);return}try{const s=await v.getSelectorState(i,l);p((s==null?void 0:s.state)??null)}catch{p(null)}},[i,l]);r.useEffect(()=>{b()},[b]),r.useEffect(()=>{j()},[j]);const m=r.useCallback(async s=>{if(!i||!l)return;const n=(()=>{switch(s){case"mark_fixed":return"Mark this selector as fixed? Move to Pending Verification.";case"mute":return"Mute this selector? It will be hidden from Hotspots, the CI gate, and digests.";case"unmute":return"Unmute this selector?";case"cancel_verification":return"Cancel verification? The selector returns to Active and the clean-build counter resets."}})();if(window.confirm(n))try{await v.postSelectorStateAction({original_strategy:i,original_selector:l,action:s}),h("Done.","success"),j()}catch(c){const u=c!=null&&c.currentStatus?` (currently ${c.currentStatus})`:"";h(`${(c==null?void 0:c.message)??"Action failed"}${u}`,"error")}},[i,l,h,j]),z=(s,n)=>{navigator.clipboard.writeText(s).catch(()=>{}),k(n),setTimeout(()=>k(c=>c===n?null:c),1500)};return l?e.jsxs("div",{className:"selector-health-page",children:[e.jsx(S,{icon:f,eyebrow:"Test quality / Selector",title:e.jsx("span",{className:"sh-detail-title",children:e.jsx("code",{title:l,children:l})}),subtitle:`All heals for this selector over the last ${o} days.`,action:e.jsxs(e.Fragment,{children:[e.jsxs("button",{className:"sh-back-btn",onClick:()=>d("/selector-health"),children:[e.jsx(M,{size:12})," Back"]}),e.jsxs("button",{className:"sh-refresh-btn",onClick:b,disabled:_,title:"Refresh",children:[e.jsx(w,{size:12,className:_?"animate-spin":""}),"Refresh"]})]})}),e.jsxs("div",{className:"sh-content",children:[i&&e.jsxs("div",{className:"sh-detail-strategy-line",title:"Tuple identity for this drill-down",children:[e.jsx("span",{className:"sh-strategy-badge",children:P(i)}),e.jsx("code",{children:l})]}),!i&&e.jsxs("div",{className:"sh-detail-banner",children:["Showing every strategy that ever healed this selector value. To scope to a single tuple, append ",e.jsx("code",{children:"?strategy=<name>"})," ","to the URL or open this row from the Active tab on Selector Health."]}),a&&e.jsxs("div",{className:`sh-detail-state sh-detail-state--${a.status}`,children:[e.jsxs("div",{className:"sh-detail-state__head",children:[e.jsxs("span",{className:"sh-detail-state__badge",children:[a.status==="pending"&&e.jsxs(e.Fragment,{children:[e.jsx(B,{size:16,style:{color:"var(--color-highlight)"}}),e.jsx("span",{children:"Pending verification"})]}),a.status==="resolved"&&e.jsxs(e.Fragment,{children:[e.jsx(L,{size:16,style:{color:"var(--color-success)"}}),e.jsx("span",{children:"Resolved"})]}),a.status==="muted"&&e.jsxs(e.Fragment,{children:[e.jsx(E,{size:16,style:{color:"var(--text-muted)"}}),e.jsx("span",{children:"Muted"})]}),a.status==="active"&&(a.regression_count>0?e.jsxs(e.Fragment,{children:[e.jsx(R,{size:16,style:{color:"var(--amber)"}}),e.jsxs("span",{children:["Active — regressed ",a.regression_count,"×"]})]}):e.jsxs(e.Fragment,{children:[e.jsx(U,{size:16}),e.jsx("span",{children:"Active"})]}))]}),e.jsxs("div",{className:"sh-detail-state__actions",children:[a.status==="active"&&e.jsxs(e.Fragment,{children:[e.jsx("button",{type:"button",className:"sh-action-btn sh-action-btn--primary",onClick:()=>m("mark_fixed"),children:"Mark fixed"}),e.jsx("button",{type:"button",className:"sh-action-btn",onClick:()=>m("mute"),children:"Mute"})]}),a.status==="pending"&&e.jsxs(e.Fragment,{children:[e.jsx("button",{type:"button",className:"sh-action-btn",onClick:()=>m("cancel_verification"),children:"Cancel verification"}),e.jsx("button",{type:"button",className:"sh-action-btn",onClick:()=>m("mute"),children:"Mute"})]}),a.status==="resolved"&&e.jsx("button",{type:"button",className:"sh-action-btn",onClick:()=>m("mute"),children:"Mute"}),a.status==="muted"&&e.jsx("button",{type:"button",className:"sh-action-btn",onClick:()=>m("unmute"),children:"Unmute"})]})]}),e.jsxs("div",{className:"sh-detail-state__meta",children:[a.fixed_at&&e.jsxs("span",{children:["Marked fixed: ",g(a.fixed_at)]}),a.resolved_at&&e.jsxs("span",{children:["Resolved: ",g(a.resolved_at)]}),a.muted_at&&e.jsxs("span",{children:["Muted: ",g(a.muted_at)]}),a.status==="pending"&&e.jsxs("span",{children:["Clean builds: ",a.clean_builds_count,"/3"]}),a.regression_count>0&&e.jsxs("span",{children:["Regressions on record: ",a.regression_count]})]})]}),_&&!$?e.jsxs("div",{className:"sh-empty",children:[e.jsx(w,{size:18,className:"animate-spin"}),e.jsx("span",{children:"Loading detail…"})]}):!t||t.healCount===0?e.jsxs("div",{className:"sh-empty sh-empty--clean",children:[e.jsx(f,{size:28}),e.jsxs("div",{children:[e.jsx("div",{className:"sh-empty__title",children:"No heals recorded"}),e.jsxs("div",{className:"sh-empty__subtitle",children:["This selector has no healing events in the last ",o," days."]})]})]}):e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"sh-detail-stats",children:[e.jsxs("div",{className:"sh-detail-stat",children:[e.jsx("span",{className:"sh-detail-stat__label",children:"Heals"}),e.jsx("span",{className:"sh-detail-stat__value",children:t.healCount})]}),e.jsxs("div",{className:"sh-detail-stat",children:[e.jsx("span",{className:"sh-detail-stat__label",children:"Sessions"}),e.jsx("span",{className:"sh-detail-stat__value",children:t.sessionCount})]}),e.jsxs("div",{className:"sh-detail-stat",children:[e.jsx("span",{className:"sh-detail-stat__label",children:"Est. cost"}),e.jsx("span",{className:"sh-detail-stat__value",children:X(t.estCostUsd)})]}),e.jsxs("div",{className:"sh-detail-stat",children:[e.jsx("span",{className:"sh-detail-stat__label",children:"Tiers used"}),e.jsx("span",{className:"sh-detail-stat__value",children:Object.keys(t.byTier).length||"—"})]})]}),e.jsxs("div",{className:"sh-detail-grid",children:[e.jsxs("section",{className:"sh-card",children:[e.jsxs("header",{className:"sh-card__head",children:[e.jsx(O,{size:12}),e.jsx("span",{children:"Suggested rewrites"}),e.jsx("span",{className:"sh-card__hint",children:"every alternate the healer landed on, ranked by frequency"})]}),e.jsxs("ul",{className:"sh-alternates",children:[t.alternates.length===0&&e.jsx("li",{className:"sh-alternates__empty",children:"No healed selectors recorded — only the failure was captured."}),t.alternates.map((s,n)=>{const c=Math.round(s.share*100),u=`alt-${n}`;return e.jsxs("li",{className:"sh-alternate",children:[e.jsxs("div",{className:"sh-alternate__top",children:[e.jsxs("span",{className:"sh-alternate__share",children:[c,"%"]}),e.jsx("code",{className:"sh-alternate__value",title:s.healedSelector,children:s.healedSelector}),e.jsx("button",{type:"button",className:`sh-icon-btn ${N===u?"copied":""}`,onClick:()=>z(s.healedSelector,u),"aria-label":"Copy alternate",title:N===u?"Copied":"Copy",children:N===u?e.jsx(K,{size:11}):e.jsx(q,{size:11})})]}),e.jsxs("div",{className:"sh-alternate__meta",children:[e.jsxs("span",{children:[s.count," heal",s.count===1?"":"s"]}),s.averageConfidence!==null&&e.jsxs("span",{children:["· avg ",Math.round(s.averageConfidence*100),"% confidence"]}),s.tiers.length>0&&e.jsxs("span",{children:["· via ",s.tiers.join(", ")]})]})]},s.healedSelector)})]})]}),e.jsxs("section",{className:"sh-card",children:[e.jsxs("header",{className:"sh-card__head",children:[e.jsx(D,{size:12}),e.jsx("span",{children:"Breakdown"})]}),e.jsxs("div",{className:"sh-breakdown",children:[e.jsxs("div",{className:"sh-breakdown__group",children:[e.jsx("div",{className:"sh-breakdown__label",children:"By tier"}),Object.entries(t.byTier).sort((s,n)=>n[1]-s[1]).map(([s,n])=>e.jsxs("div",{className:"sh-breakdown__row",children:[e.jsx("span",{className:"sh-tier-pill",children:s}),e.jsx("span",{className:"sh-breakdown__count",children:n})]},s)),Object.keys(t.byTier).length===0&&e.jsx("div",{className:"sh-breakdown__empty",children:"none recorded"})]}),e.jsxs("div",{className:"sh-breakdown__group",children:[e.jsx("div",{className:"sh-breakdown__label",children:"By platform"}),Object.entries(t.byPlatform).sort((s,n)=>n[1]-s[1]).map(([s,n])=>e.jsxs("div",{className:"sh-breakdown__row",children:[e.jsx("span",{className:"sh-platform-pill",children:s}),e.jsx("span",{className:"sh-breakdown__count",children:n})]},s))]}),e.jsxs("div",{className:"sh-breakdown__group",children:[e.jsx("div",{className:"sh-breakdown__label",children:"By build"}),t.byBuild.slice(0,8).map(s=>e.jsxs("div",{className:"sh-breakdown__row",children:[e.jsx("span",{className:"sh-build-pill",title:s.buildId,children:s.buildId==="unattached"?"unattached":s.buildId.length>12?s.buildId.slice(0,8)+"…":s.buildId}),e.jsx("span",{className:"sh-breakdown__count",children:s.count})]},s.buildId)),t.byBuild.length===0&&e.jsx("div",{className:"sh-breakdown__empty",children:"none recorded"})]})]})]})]}),e.jsxs("section",{className:"sh-card",children:[e.jsxs("header",{className:"sh-card__head",children:[e.jsx("span",{children:"Timeline"}),e.jsxs("span",{className:"sh-card__hint",children:["most recent ",t.timeline.length," of ",t.healCount," heal",t.healCount===1?"":"s"]})]}),e.jsx("div",{className:"sh-timeline",children:t.timeline.map(s=>e.jsxs("div",{className:"sh-timeline__row",children:[e.jsx("span",{className:"sh-timeline__when",children:V(s.createdAt)}),s.tier&&e.jsx("span",{className:"sh-tier-pill",children:s.tier}),e.jsx("span",{className:"sh-timeline__cmd",children:s.commandName??"—"}),e.jsx("span",{className:"sh-timeline__device",children:s.deviceName??s.deviceUdid??"—"}),e.jsx("code",{className:"sh-timeline__healed",title:s.healedSelector??"",children:s.healedSelector??"—"}),s.confidence!==null&&e.jsxs("span",{className:"sh-timeline__conf",children:[Math.round(s.confidence*100),"%"]}),s.buildId&&s.sessionId&&e.jsx("a",{className:"sh-timeline__link",href:`/xenon/builds/${encodeURIComponent(s.buildId)}/sessions/${encodeURIComponent(s.sessionId)}`,title:"Open session detail",children:e.jsx(H,{size:11})})]},s.id))})]})]})]})]}):e.jsxs("div",{className:"selector-health-page",children:[e.jsx(S,{icon:f,eyebrow:"Test quality",title:"Selector detail",subtitle:"No selector specified."}),e.jsx("div",{className:"sh-content",children:e.jsxs("button",{className:"sh-back-btn",onClick:()=>d("/selector-health"),children:[e.jsx(M,{size:12})," Back to Selector health"]})})]})};export{le as default};
1
+ import{u as I,t as A,E as F,r,X as v,j as e,K as f,A as w,C as R,y as D}from"./index-BQCXPOXt.js";import{f as g}from"./time-B8FIgwPE.js";import{P as S}from"./page-header-CuFXVUop.js";import{f as P,H as B,V as E,E as H}from"./selector-health-TyMPgAWo.js";import{C as M}from"./chevron-left-sCqxpTY6.js";import{C as L}from"./circle-check-DsvxbnTg.js";import{Z as U}from"./zap-I10vdQXd.js";import{L as O}from"./layers-DRtz_bzF.js";import{C as K}from"./check-zugO3p5U.js";import{C as q}from"./copy-pHk-SWBM.js";function V(d){const h=Date.parse(d);if(!Number.isFinite(h))return"";const x=Math.max(0,Date.now()-h),l=Math.floor(x/1e3);if(l<60)return`${l}s ago`;const i=Math.floor(l/60);if(i<60)return`${i}m ago`;const o=Math.floor(i/60);return o<24?`${o}h ago`:`${Math.floor(o/24)}d ago`}function X(d){return d===0?"$0":d<.01?"<$0.01":`$${d.toFixed(2)}`}const le=()=>{const d=I(),{toast:h}=A(),[x]=F(),l=x.get("value")??"",i=x.get("strategy")??"",o=parseInt(x.get("windowDays")??"30",10)||30,[t,y]=r.useState(null),[a,p]=r.useState(null),[_,C]=r.useState(!1),[$,T]=r.useState(!1),[N,k]=r.useState(null),b=r.useCallback(async()=>{if(l){C(!0);try{const s=await v.getHealingSelectorDetail(l,o);y(s??null)}catch{y(null)}finally{C(!1),T(!0)}}},[l,o]),j=r.useCallback(async()=>{if(!i||!l){p(null);return}try{const s=await v.getSelectorState(i,l);p((s==null?void 0:s.state)??null)}catch{p(null)}},[i,l]);r.useEffect(()=>{b()},[b]),r.useEffect(()=>{j()},[j]);const m=r.useCallback(async s=>{if(!i||!l)return;const n=(()=>{switch(s){case"mark_fixed":return"Mark this selector as fixed? Move to Pending Verification.";case"mute":return"Mute this selector? It will be hidden from Hotspots, the CI gate, and digests.";case"unmute":return"Unmute this selector?";case"cancel_verification":return"Cancel verification? The selector returns to Active and the clean-build counter resets."}})();if(window.confirm(n))try{await v.postSelectorStateAction({original_strategy:i,original_selector:l,action:s}),h("Done.","success"),j()}catch(c){const u=c!=null&&c.currentStatus?` (currently ${c.currentStatus})`:"";h(`${(c==null?void 0:c.message)??"Action failed"}${u}`,"error")}},[i,l,h,j]),z=(s,n)=>{navigator.clipboard.writeText(s).catch(()=>{}),k(n),setTimeout(()=>k(c=>c===n?null:c),1500)};return l?e.jsxs("div",{className:"selector-health-page",children:[e.jsx(S,{icon:f,eyebrow:"Test quality / Selector",title:e.jsx("span",{className:"sh-detail-title",children:e.jsx("code",{title:l,children:l})}),subtitle:`All heals for this selector over the last ${o} days.`,action:e.jsxs(e.Fragment,{children:[e.jsxs("button",{className:"sh-back-btn",onClick:()=>d("/selector-health"),children:[e.jsx(M,{size:12})," Back"]}),e.jsxs("button",{className:"sh-refresh-btn",onClick:b,disabled:_,title:"Refresh",children:[e.jsx(w,{size:12,className:_?"animate-spin":""}),"Refresh"]})]})}),e.jsxs("div",{className:"sh-content",children:[i&&e.jsxs("div",{className:"sh-detail-strategy-line",title:"Tuple identity for this drill-down",children:[e.jsx("span",{className:"sh-strategy-badge",children:P(i)}),e.jsx("code",{children:l})]}),!i&&e.jsxs("div",{className:"sh-detail-banner",children:["Showing every strategy that ever healed this selector value. To scope to a single tuple, append ",e.jsx("code",{children:"?strategy=<name>"})," ","to the URL or open this row from the Active tab on Selector Health."]}),a&&e.jsxs("div",{className:`sh-detail-state sh-detail-state--${a.status}`,children:[e.jsxs("div",{className:"sh-detail-state__head",children:[e.jsxs("span",{className:"sh-detail-state__badge",children:[a.status==="pending"&&e.jsxs(e.Fragment,{children:[e.jsx(B,{size:16,style:{color:"var(--color-highlight)"}}),e.jsx("span",{children:"Pending verification"})]}),a.status==="resolved"&&e.jsxs(e.Fragment,{children:[e.jsx(L,{size:16,style:{color:"var(--color-success)"}}),e.jsx("span",{children:"Resolved"})]}),a.status==="muted"&&e.jsxs(e.Fragment,{children:[e.jsx(E,{size:16,style:{color:"var(--text-muted)"}}),e.jsx("span",{children:"Muted"})]}),a.status==="active"&&(a.regression_count>0?e.jsxs(e.Fragment,{children:[e.jsx(R,{size:16,style:{color:"var(--amber)"}}),e.jsxs("span",{children:["Active — regressed ",a.regression_count,"×"]})]}):e.jsxs(e.Fragment,{children:[e.jsx(U,{size:16}),e.jsx("span",{children:"Active"})]}))]}),e.jsxs("div",{className:"sh-detail-state__actions",children:[a.status==="active"&&e.jsxs(e.Fragment,{children:[e.jsx("button",{type:"button",className:"sh-action-btn sh-action-btn--primary",onClick:()=>m("mark_fixed"),children:"Mark fixed"}),e.jsx("button",{type:"button",className:"sh-action-btn",onClick:()=>m("mute"),children:"Mute"})]}),a.status==="pending"&&e.jsxs(e.Fragment,{children:[e.jsx("button",{type:"button",className:"sh-action-btn",onClick:()=>m("cancel_verification"),children:"Cancel verification"}),e.jsx("button",{type:"button",className:"sh-action-btn",onClick:()=>m("mute"),children:"Mute"})]}),a.status==="resolved"&&e.jsx("button",{type:"button",className:"sh-action-btn",onClick:()=>m("mute"),children:"Mute"}),a.status==="muted"&&e.jsx("button",{type:"button",className:"sh-action-btn",onClick:()=>m("unmute"),children:"Unmute"})]})]}),e.jsxs("div",{className:"sh-detail-state__meta",children:[a.fixed_at&&e.jsxs("span",{children:["Marked fixed: ",g(a.fixed_at)]}),a.resolved_at&&e.jsxs("span",{children:["Resolved: ",g(a.resolved_at)]}),a.muted_at&&e.jsxs("span",{children:["Muted: ",g(a.muted_at)]}),a.status==="pending"&&e.jsxs("span",{children:["Clean builds: ",a.clean_builds_count,"/3"]}),a.regression_count>0&&e.jsxs("span",{children:["Regressions on record: ",a.regression_count]})]})]}),_&&!$?e.jsxs("div",{className:"sh-empty",children:[e.jsx(w,{size:18,className:"animate-spin"}),e.jsx("span",{children:"Loading detail…"})]}):!t||t.healCount===0?e.jsxs("div",{className:"sh-empty sh-empty--clean",children:[e.jsx(f,{size:28}),e.jsxs("div",{children:[e.jsx("div",{className:"sh-empty__title",children:"No heals recorded"}),e.jsxs("div",{className:"sh-empty__subtitle",children:["This selector has no healing events in the last ",o," days."]})]})]}):e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"sh-detail-stats",children:[e.jsxs("div",{className:"sh-detail-stat",children:[e.jsx("span",{className:"sh-detail-stat__label",children:"Heals"}),e.jsx("span",{className:"sh-detail-stat__value",children:t.healCount})]}),e.jsxs("div",{className:"sh-detail-stat",children:[e.jsx("span",{className:"sh-detail-stat__label",children:"Sessions"}),e.jsx("span",{className:"sh-detail-stat__value",children:t.sessionCount})]}),e.jsxs("div",{className:"sh-detail-stat",children:[e.jsx("span",{className:"sh-detail-stat__label",children:"Est. cost"}),e.jsx("span",{className:"sh-detail-stat__value",children:X(t.estCostUsd)})]}),e.jsxs("div",{className:"sh-detail-stat",children:[e.jsx("span",{className:"sh-detail-stat__label",children:"Tiers used"}),e.jsx("span",{className:"sh-detail-stat__value",children:Object.keys(t.byTier).length||"—"})]})]}),e.jsxs("div",{className:"sh-detail-grid",children:[e.jsxs("section",{className:"sh-card",children:[e.jsxs("header",{className:"sh-card__head",children:[e.jsx(O,{size:12}),e.jsx("span",{children:"Suggested rewrites"}),e.jsx("span",{className:"sh-card__hint",children:"every alternate the healer landed on, ranked by frequency"})]}),e.jsxs("ul",{className:"sh-alternates",children:[t.alternates.length===0&&e.jsx("li",{className:"sh-alternates__empty",children:"No healed selectors recorded — only the failure was captured."}),t.alternates.map((s,n)=>{const c=Math.round(s.share*100),u=`alt-${n}`;return e.jsxs("li",{className:"sh-alternate",children:[e.jsxs("div",{className:"sh-alternate__top",children:[e.jsxs("span",{className:"sh-alternate__share",children:[c,"%"]}),e.jsx("code",{className:"sh-alternate__value",title:s.healedSelector,children:s.healedSelector}),e.jsx("button",{type:"button",className:`sh-icon-btn ${N===u?"copied":""}`,onClick:()=>z(s.healedSelector,u),"aria-label":"Copy alternate",title:N===u?"Copied":"Copy",children:N===u?e.jsx(K,{size:11}):e.jsx(q,{size:11})})]}),e.jsxs("div",{className:"sh-alternate__meta",children:[e.jsxs("span",{children:[s.count," heal",s.count===1?"":"s"]}),s.averageConfidence!==null&&e.jsxs("span",{children:["· avg ",Math.round(s.averageConfidence*100),"% confidence"]}),s.tiers.length>0&&e.jsxs("span",{children:["· via ",s.tiers.join(", ")]})]})]},s.healedSelector)})]})]}),e.jsxs("section",{className:"sh-card",children:[e.jsxs("header",{className:"sh-card__head",children:[e.jsx(D,{size:12}),e.jsx("span",{children:"Breakdown"})]}),e.jsxs("div",{className:"sh-breakdown",children:[e.jsxs("div",{className:"sh-breakdown__group",children:[e.jsx("div",{className:"sh-breakdown__label",children:"By tier"}),Object.entries(t.byTier).sort((s,n)=>n[1]-s[1]).map(([s,n])=>e.jsxs("div",{className:"sh-breakdown__row",children:[e.jsx("span",{className:"sh-tier-pill",children:s}),e.jsx("span",{className:"sh-breakdown__count",children:n})]},s)),Object.keys(t.byTier).length===0&&e.jsx("div",{className:"sh-breakdown__empty",children:"none recorded"})]}),e.jsxs("div",{className:"sh-breakdown__group",children:[e.jsx("div",{className:"sh-breakdown__label",children:"By platform"}),Object.entries(t.byPlatform).sort((s,n)=>n[1]-s[1]).map(([s,n])=>e.jsxs("div",{className:"sh-breakdown__row",children:[e.jsx("span",{className:"sh-platform-pill",children:s}),e.jsx("span",{className:"sh-breakdown__count",children:n})]},s))]}),e.jsxs("div",{className:"sh-breakdown__group",children:[e.jsx("div",{className:"sh-breakdown__label",children:"By build"}),t.byBuild.slice(0,8).map(s=>e.jsxs("div",{className:"sh-breakdown__row",children:[e.jsx("span",{className:"sh-build-pill",title:s.buildId,children:s.buildId==="unattached"?"unattached":s.buildId.length>12?s.buildId.slice(0,8)+"…":s.buildId}),e.jsx("span",{className:"sh-breakdown__count",children:s.count})]},s.buildId)),t.byBuild.length===0&&e.jsx("div",{className:"sh-breakdown__empty",children:"none recorded"})]})]})]})]}),e.jsxs("section",{className:"sh-card",children:[e.jsxs("header",{className:"sh-card__head",children:[e.jsx("span",{children:"Timeline"}),e.jsxs("span",{className:"sh-card__hint",children:["most recent ",t.timeline.length," of ",t.healCount," heal",t.healCount===1?"":"s"]})]}),e.jsx("div",{className:"sh-timeline",children:t.timeline.map(s=>e.jsxs("div",{className:"sh-timeline__row",children:[e.jsx("span",{className:"sh-timeline__when",children:V(s.createdAt)}),s.tier&&e.jsx("span",{className:"sh-tier-pill",children:s.tier}),e.jsx("span",{className:"sh-timeline__cmd",children:s.commandName??"—"}),e.jsx("span",{className:"sh-timeline__device",children:s.deviceName??s.deviceUdid??"—"}),e.jsx("code",{className:"sh-timeline__healed",title:s.healedSelector??"",children:s.healedSelector??"—"}),s.confidence!==null&&e.jsxs("span",{className:"sh-timeline__conf",children:[Math.round(s.confidence*100),"%"]}),s.buildId&&s.sessionId&&e.jsx("a",{className:"sh-timeline__link",href:`/xenon/builds/${encodeURIComponent(s.buildId)}/sessions/${encodeURIComponent(s.sessionId)}`,title:"Open session detail",children:e.jsx(H,{size:11})})]},s.id))})]})]})]})]}):e.jsxs("div",{className:"selector-health-page",children:[e.jsx(S,{icon:f,eyebrow:"Test quality",title:"Selector detail",subtitle:"No selector specified."}),e.jsx("div",{className:"sh-content",children:e.jsxs("button",{className:"sh-back-btn",onClick:()=>d("/selector-health"),children:[e.jsx(M,{size:12})," Back to Selector health"]})})]})};export{le as default};
@@ -1,4 +1,4 @@
1
- import{c as e}from"./index-3uxl3o7K.js";/**
1
+ import{c as e}from"./index-BQCXPOXt.js";/**
2
2
  * @license lucide-react v0.555.0 - ISC
3
3
  *
4
4
  * This source code is licensed under the ISC license.
@@ -1,4 +1,4 @@
1
- import{c as z,u as H,E as Y,j as e,r as h,w as le,v as P,C as re,X as k,A,p as Z,t as oe,K as W,y as ce,I as de}from"./index-3uxl3o7K.js";import{Z as he}from"./zap-B2bH2vKX.js";import{H as B,V as R,f as w,E as ue}from"./selector-health-CAhpdilF.js";import{C as Q}from"./circle-check-D3Qq0tKp.js";import{M as me}from"./Modal-Bw-a-E-e.js";import{C as pe}from"./check-uGHCXe-L.js";import{C as ge}from"./copy-DZwYE5Va.js";import{b as N}from"./time-B8FIgwPE.js";import{E as ve}from"./EmptyState-fPxujqqE.js";import{P as be}from"./page-header-CfR4Sm9V.js";import{a as xe}from"./SegmentedControl-Jzn9c7o8.js";import{p as fe}from"./labels-C21SA4JG.js";import{F as G}from"./funnel-CtKNPqzb.js";import{C as _e}from"./chevron-right-BUsldEli.js";import{A as J}from"./arrow-up-right-DFHi_8yG.js";import"./index-Zy1Op5C1.js";/**
1
+ import{c as z,u as H,E as Y,j as e,r as h,w as le,v as P,C as re,X as k,A,p as Z,t as oe,K as W,y as ce,I as de}from"./index-BQCXPOXt.js";import{Z as he}from"./zap-I10vdQXd.js";import{H as B,V as R,f as w,E as ue}from"./selector-health-TyMPgAWo.js";import{C as Q}from"./circle-check-DsvxbnTg.js";import{M as me}from"./Modal-Djp4NvyZ.js";import{C as pe}from"./check-zugO3p5U.js";import{C as ge}from"./copy-pHk-SWBM.js";import{b as N}from"./time-B8FIgwPE.js";import{E as ve}from"./EmptyState-B_JRYedM.js";import{P as be}from"./page-header-CuFXVUop.js";import{a as xe}from"./SegmentedControl-MGTzJhBf.js";import{p as fe}from"./labels-C21SA4JG.js";import{F as G}from"./funnel-BrDuhOtM.js";import{C as _e}from"./chevron-right-Bb59xwZc.js";import{A as J}from"./arrow-up-right-B7TEV_Gr.js";import"./index-C-Q4QkXb.js";/**
2
2
  * @license lucide-react v0.555.0 - ISC
3
3
  *
4
4
  * This source code is licensed under the ISC license.
@@ -1,3 +1,3 @@
1
- import{r as d,X as _,t as D,j as e,e as B,y as Y,p as G,i as Q,u as Z}from"./index-3uxl3o7K.js";import{u as q,h as ee,c as te,d as se,p as re,o as ae,f as ne,S as ie}from"./status-pill-outline-DY5uzv6A.js";import{B as oe,P as j}from"./BugReportButton-C7OmS61B.js";import{A as le}from"./arrow-left-uQ6WIwiC.js";import{C as $}from"./chevron-right-BUsldEli.js";import{C as L}from"./copy-DZwYE5Va.js";import{A as ce}from"./arrow-up-right-DFHi_8yG.js";import{V as de}from"./video-off-CUNzD2kH.js";import{E as O}from"./EmptyState-fPxujqqE.js";import{T as xe,a as me,b as M,c as S,d as ue,e as R}from"./Table-B_Va3V05.js";import{M as fe}from"./Modal-Bw-a-E-e.js";import{D as he}from"./download-CCDYo_TN.js";import{N as pe}from"./network-DiSumY-1.js";import{s as ve}from"./labels-C21SA4JG.js";import"./time-B8FIgwPE.js";import"./index-Zy1Op5C1.js";function be(t){const[s,r]=d.useState(null),[i,n]=d.useState([]),[l,c]=d.useState([]),[a,x]=d.useState([]),[u,f]=d.useState([]),[h,v]=d.useState(!0),[y,N]=d.useState(null),[w,g]=d.useState(!1),[C,E]=d.useState(0);return d.useEffect(()=>{if(!t){r(null),n([]),c([]),x([]),f([]),g(!1),v(!1);return}let p=!0;return v(!0),Promise.all([_.getSession(t),_.getSessionLogs(t),_.getDeviceLogs(t),_.getDebugLogs(t),_.getProfilingData(t).catch(()=>[])]).then(([o,b,k,m,T])=>{if(!p)return;const H=o&&typeof o=="object"&&typeof o.id=="string"&&typeof o.status=="string";r(H?o:null),H?(g(!1),N(null)):(g(!!o&&typeof o=="object"&&(o.error===!0||typeof o.message=="string")),N(typeof(o==null?void 0:o.message)=="string"?o.message:"Session not found")),n(Array.isArray(b)?b:[]),c(Array.isArray(k)?k:[]),x(Array.isArray(m)?m:[]),f(Array.isArray(T)?T:[])}).catch(o=>{p&&N(o instanceof Error?o.message:String(o))}).finally(()=>{p&&v(!1)}),()=>{p=!1}},[t,C]),{session:s,sessionLogs:i,deviceLogs:l,debugLogs:a,profiling:u,loading:h,error:y,notFound:w,refresh:()=>E(p=>p+1)}}const J=({buildId:t,buildName:s,sessionId:r})=>{const{toast:i}=D(),n=async()=>{try{await navigator.clipboard.writeText(r),i("Session ID copied","success")}catch{i("Failed to copy (clipboard unavailable)","error")}};return e.jsxs("header",{className:"flex items-center gap-2 px-4 py-3 border-b border-[var(--border)] bg-[var(--surface)]",children:[e.jsxs(B,{to:`/builds/${t}`,className:"inline-flex items-center gap-1.5 text-xs text-[var(--text-muted)] hover:text-[var(--text)] transition-colors",children:[e.jsx(le,{className:"h-3.5 w-3.5"}),"Builds"]}),e.jsx($,{className:"h-3 w-3 text-[var(--text-dim)]"}),e.jsx(B,{to:`/builds/${t}`,className:"text-[11px] text-[var(--color-accent)] hover:underline",children:s}),e.jsx($,{className:"h-3 w-3 text-[var(--text-dim)]"}),e.jsx("span",{className:"text-[11px] text-[var(--text-dim)]",children:"Sessions"}),e.jsx($,{className:"h-3 w-3 text-[var(--text-dim)]"}),e.jsxs("span",{className:"font-mono text-xs text-[var(--text)]",title:r,children:["#",r]}),e.jsx("button",{type:"button",onClick:n,"aria-label":"Copy session ID",className:"p-1 rounded text-[var(--text-dim)] hover:text-[var(--text)] hover:bg-[var(--surface-2)] transition-colors",children:e.jsx(L,{className:"h-3 w-3"})}),e.jsx("div",{className:"ml-auto",children:e.jsx(oe,{sessionId:r,mode:"full",variant:"inline"})})]})},ge={default:"text-[var(--text)]",red:"text-[var(--red)]",green:"text-[var(--color-success)]",amber:"text-[var(--amber)]"},A=({label:t,rows:s})=>e.jsxs("div",{className:"flex-1 min-w-0 p-4",children:[e.jsx("div",{className:"text-[11px] font-semibold text-[var(--text-dim)] mb-3",children:t}),e.jsx("dl",{className:"space-y-2",children:s.map((r,i)=>e.jsxs("div",{className:"flex items-baseline justify-between gap-3",children:[e.jsx("dt",{className:"text-[11px] text-[var(--text-dim)] shrink-0",children:r.label}),e.jsx("dd",{className:`text-xs text-right truncate min-w-0 ${r.mono?"font-mono":""} ${ge[r.tone??"default"]}`,children:r.value})]},`${r.label}-${i}`))})]}),je=({identity:t,run:s,result:r})=>e.jsxs("div",{className:"grid grid-cols-1 md:grid-cols-3 rounded-lg border border-[var(--border)] bg-[var(--surface)] divide-y md:divide-y-0 md:divide-x divide-[var(--border)]",children:[e.jsx(A,{label:"Identity",rows:t}),e.jsx(A,{label:"Run",rows:s}),e.jsx(A,{label:"Result",rows:r})]});function Ne(t){if(!t||t.length===0)return null;const s=t.find(r=>r.is_success===!1);return s||(t[t.length-1]??null)}function ye(t,s=8){if(!t)return[];const r=t.split(/\r?\n/),i=[];for(const n of r){const l=n.trim();if(/^at\s+/.test(l)&&(i.push(l),i.length>=s))break}return i}function F(t){return t?t.split(/[_\s]+/).filter(Boolean).map(s=>s.charAt(0).toUpperCase()+s.slice(1).toLowerCase()).join(" "):""}function U(t){if(!t)return{};try{const s=JSON.parse(t);return s&&typeof s=="object"&&!Array.isArray(s)?s:{}}catch{return{}}}function I(t,s=200){if(t==null)return"";if(typeof t=="string")return t;if(typeof t=="number"||typeof t=="boolean")return String(t);try{const r=JSON.stringify(t);return r.length>s?r.slice(0,s)+"…":r}catch{return String(t)}}function we(t,s,r,i,n){var u;const l=F(t.failure_category),c=((u=t.device_name)==null?void 0:u.trim())||"Unknown Device",a=t.device_version?` ${t.device_version}`:"",x=(n==null?void 0:n.message)||(n?JSON.stringify(n).slice(0,200):"(no logs captured)");return[`**Session:** ${t.id}`,`**Build:** ${s} (#${r})`,`**Device:** ${c} (${t.node_id||"unknown-node"}) · ${t.device_platform||"unknown"}${a}`,`**Duration:** ${i}`,`**Failure category:** ${l||"(uncategorized)"}`,`**Failure reason:** ${t.failure_reason||"(not set)"}`,`**First error:** ${x}`].join(`
1
+ import{r as d,X as _,t as D,j as e,e as B,y as Y,p as G,i as Q,u as Z}from"./index-BQCXPOXt.js";import{u as q,h as ee,c as te,d as se,p as re,o as ae,f as ne,S as ie}from"./status-pill-outline-grXLf8I8.js";import{B as oe,P as j}from"./BugReportButton-DEXyENUv.js";import{A as le}from"./arrow-left-BkA7oMRe.js";import{C as $}from"./chevron-right-Bb59xwZc.js";import{C as L}from"./copy-pHk-SWBM.js";import{A as ce}from"./arrow-up-right-B7TEV_Gr.js";import{V as de}from"./video-off-BuoIHEYy.js";import{E as O}from"./EmptyState-B_JRYedM.js";import{T as xe,a as me,b as M,c as S,d as ue,e as R}from"./Table-CdKQ9hnU.js";import{M as fe}from"./Modal-Djp4NvyZ.js";import{D as he}from"./download-CAHtPZmY.js";import{N as pe}from"./network-B8m-F79k.js";import{s as ve}from"./labels-C21SA4JG.js";import"./time-B8FIgwPE.js";import"./index-C-Q4QkXb.js";function be(t){const[s,r]=d.useState(null),[i,n]=d.useState([]),[l,c]=d.useState([]),[a,x]=d.useState([]),[u,f]=d.useState([]),[h,v]=d.useState(!0),[y,N]=d.useState(null),[w,g]=d.useState(!1),[C,E]=d.useState(0);return d.useEffect(()=>{if(!t){r(null),n([]),c([]),x([]),f([]),g(!1),v(!1);return}let p=!0;return v(!0),Promise.all([_.getSession(t),_.getSessionLogs(t),_.getDeviceLogs(t),_.getDebugLogs(t),_.getProfilingData(t).catch(()=>[])]).then(([o,b,k,m,T])=>{if(!p)return;const H=o&&typeof o=="object"&&typeof o.id=="string"&&typeof o.status=="string";r(H?o:null),H?(g(!1),N(null)):(g(!!o&&typeof o=="object"&&(o.error===!0||typeof o.message=="string")),N(typeof(o==null?void 0:o.message)=="string"?o.message:"Session not found")),n(Array.isArray(b)?b:[]),c(Array.isArray(k)?k:[]),x(Array.isArray(m)?m:[]),f(Array.isArray(T)?T:[])}).catch(o=>{p&&N(o instanceof Error?o.message:String(o))}).finally(()=>{p&&v(!1)}),()=>{p=!1}},[t,C]),{session:s,sessionLogs:i,deviceLogs:l,debugLogs:a,profiling:u,loading:h,error:y,notFound:w,refresh:()=>E(p=>p+1)}}const J=({buildId:t,buildName:s,sessionId:r})=>{const{toast:i}=D(),n=async()=>{try{await navigator.clipboard.writeText(r),i("Session ID copied","success")}catch{i("Failed to copy (clipboard unavailable)","error")}};return e.jsxs("header",{className:"flex items-center gap-2 px-4 py-3 border-b border-[var(--border)] bg-[var(--surface)]",children:[e.jsxs(B,{to:`/builds/${t}`,className:"inline-flex items-center gap-1.5 text-xs text-[var(--text-muted)] hover:text-[var(--text)] transition-colors",children:[e.jsx(le,{className:"h-3.5 w-3.5"}),"Builds"]}),e.jsx($,{className:"h-3 w-3 text-[var(--text-dim)]"}),e.jsx(B,{to:`/builds/${t}`,className:"text-[11px] text-[var(--color-accent)] hover:underline",children:s}),e.jsx($,{className:"h-3 w-3 text-[var(--text-dim)]"}),e.jsx("span",{className:"text-[11px] text-[var(--text-dim)]",children:"Sessions"}),e.jsx($,{className:"h-3 w-3 text-[var(--text-dim)]"}),e.jsxs("span",{className:"font-mono text-xs text-[var(--text)]",title:r,children:["#",r]}),e.jsx("button",{type:"button",onClick:n,"aria-label":"Copy session ID",className:"p-1 rounded text-[var(--text-dim)] hover:text-[var(--text)] hover:bg-[var(--surface-2)] transition-colors",children:e.jsx(L,{className:"h-3 w-3"})}),e.jsx("div",{className:"ml-auto",children:e.jsx(oe,{sessionId:r,mode:"full",variant:"inline"})})]})},ge={default:"text-[var(--text)]",red:"text-[var(--red)]",green:"text-[var(--color-success)]",amber:"text-[var(--amber)]"},A=({label:t,rows:s})=>e.jsxs("div",{className:"flex-1 min-w-0 p-4",children:[e.jsx("div",{className:"text-[11px] font-semibold text-[var(--text-dim)] mb-3",children:t}),e.jsx("dl",{className:"space-y-2",children:s.map((r,i)=>e.jsxs("div",{className:"flex items-baseline justify-between gap-3",children:[e.jsx("dt",{className:"text-[11px] text-[var(--text-dim)] shrink-0",children:r.label}),e.jsx("dd",{className:`text-xs text-right truncate min-w-0 ${r.mono?"font-mono":""} ${ge[r.tone??"default"]}`,children:r.value})]},`${r.label}-${i}`))})]}),je=({identity:t,run:s,result:r})=>e.jsxs("div",{className:"grid grid-cols-1 md:grid-cols-3 rounded-lg border border-[var(--border)] bg-[var(--surface)] divide-y md:divide-y-0 md:divide-x divide-[var(--border)]",children:[e.jsx(A,{label:"Identity",rows:t}),e.jsx(A,{label:"Run",rows:s}),e.jsx(A,{label:"Result",rows:r})]});function Ne(t){if(!t||t.length===0)return null;const s=t.find(r=>r.is_success===!1);return s||(t[t.length-1]??null)}function ye(t,s=8){if(!t)return[];const r=t.split(/\r?\n/),i=[];for(const n of r){const l=n.trim();if(/^at\s+/.test(l)&&(i.push(l),i.length>=s))break}return i}function F(t){return t?t.split(/[_\s]+/).filter(Boolean).map(s=>s.charAt(0).toUpperCase()+s.slice(1).toLowerCase()).join(" "):""}function U(t){if(!t)return{};try{const s=JSON.parse(t);return s&&typeof s=="object"&&!Array.isArray(s)?s:{}}catch{return{}}}function I(t,s=200){if(t==null)return"";if(typeof t=="string")return t;if(typeof t=="number"||typeof t=="boolean")return String(t);try{const r=JSON.stringify(t);return r.length>s?r.slice(0,s)+"…":r}catch{return String(t)}}function we(t,s,r,i,n){var u;const l=F(t.failure_category),c=((u=t.device_name)==null?void 0:u.trim())||"Unknown Device",a=t.device_version?` ${t.device_version}`:"",x=(n==null?void 0:n.message)||(n?JSON.stringify(n).slice(0,200):"(no logs captured)");return[`**Session:** ${t.id}`,`**Build:** ${s} (#${r})`,`**Device:** ${c} (${t.node_id||"unknown-node"}) · ${t.device_platform||"unknown"}${a}`,`**Duration:** ${i}`,`**Failure category:** ${l||"(uncategorized)"}`,`**Failure reason:** ${t.failure_reason||"(not set)"}`,`**First error:** ${x}`].join(`
2
2
  `)}const ke=({session:t,buildName:s,buildId:r,allLogs:i,durationText:n})=>{const{toast:l}=D(),c=F(t.failure_category),a=Ne(i),x=ye(t.failure_reason),u=x.length>0,f=async()=>{const v=we(t,s,r,n,a);try{await navigator.clipboard.writeText(v),l("Failure report copied","success")}catch{l("Clipboard unavailable","error")}},h=t.failure_category?`/xenon/runbooks/${encodeURIComponent(t.failure_category.toLowerCase())}`:void 0;return e.jsxs("section",{className:"rounded-lg border border-[var(--red)]/30 bg-[var(--surface)] overflow-hidden",children:[e.jsxs("header",{className:"flex items-center justify-between gap-4 px-4 py-3 border-b border-[var(--border)] bg-[var(--red)]/5",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx(Y,{className:"h-4 w-4 text-[var(--red)]"}),e.jsx("span",{className:"text-sm font-semibold text-[var(--red)]",children:"Failure summary"}),c&&e.jsx("span",{className:"text-[11px] text-[var(--text-dim)] ml-2",children:c})]}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsxs("button",{type:"button",onClick:f,className:"inline-flex items-center gap-1.5 h-7 px-2.5 rounded-md border border-[var(--border)] text-xs text-[var(--text)] hover:border-[var(--border-strong)] hover:bg-[var(--surface-2)] transition-colors",children:[e.jsx(L,{className:"h-3 w-3"}),"Copy"]}),e.jsxs("a",{...h?{href:h,target:"_blank",rel:"noreferrer"}:{"aria-disabled":!0,onClick:v=>v.preventDefault()},className:`inline-flex items-center gap-1.5 h-7 px-2.5 rounded-md border border-[var(--border)] text-xs text-[var(--text)] hover:border-[var(--border-strong)] hover:bg-[var(--surface-2)] transition-colors ${h?"":"opacity-50 cursor-not-allowed"}`,title:h?"Open runbook in new tab":"No runbook — failure category not set",children:[e.jsx(ce,{className:"h-3 w-3"}),"Open runbook"]})]})]}),e.jsxs("div",{className:"px-4 py-4 space-y-4",children:[e.jsxs("div",{children:[e.jsx("div",{className:"text-[11px] font-semibold text-[var(--text-dim)] mb-1",children:"Reason"}),e.jsx("div",{className:"text-sm text-[var(--text)]",children:t.failure_reason||e.jsx("span",{className:"text-[var(--text-dim)]",children:"(not set)"})})]}),e.jsxs("div",{children:[e.jsx("div",{className:"text-[11px] font-semibold text-[var(--text-dim)] mb-1",children:"First error"}),e.jsx("div",{className:"text-sm text-[var(--text-muted)] min-w-0",children:a!=null&&a.message?e.jsx("span",{className:"break-words",children:a.message}):a?e.jsxs("dl",{className:"space-y-1 text-xs",children:[e.jsxs("div",{className:"flex gap-2 min-w-0",children:[e.jsx("dt",{className:"text-[var(--text-dim)] shrink-0 text-[11px]",children:"Command"}),e.jsx("dd",{className:"font-mono break-all",children:a.command_name||a.title||"—"})]}),a.subtitle&&e.jsxs("div",{className:"flex gap-2 min-w-0",children:[e.jsx("dt",{className:"text-[var(--text-dim)] shrink-0 text-[11px]",children:"Target"}),e.jsx("dd",{className:"font-mono break-all",children:a.subtitle})]}),a.response&&e.jsxs("div",{className:"flex gap-2 min-w-0",children:[e.jsx("dt",{className:"text-[var(--text-dim)] shrink-0 text-[11px]",children:"Response"}),e.jsx("dd",{className:"font-mono break-all",children:String(a.response).slice(0,400)})]})]}):e.jsx("span",{className:"text-[var(--text-dim)]",children:"(no logs captured before failure)"})})]}),u&&e.jsxs("div",{children:[e.jsx("div",{className:"text-[11px] font-semibold text-[var(--text-dim)] mb-1",children:"Stack trace"}),e.jsx("pre",{className:"rounded-md border border-[var(--border)] bg-[var(--bg)] p-3 font-mono text-[11px] leading-relaxed text-[var(--color-accent)] overflow-x-auto",children:x.join(`
3
3
  `)})]})]})]})},Se=({session:t})=>{const s=t.status==="running",r=!!t.video_recording;return e.jsxs("section",{className:"rounded-lg border border-[var(--border)] bg-[var(--surface)] overflow-hidden",children:[e.jsxs("header",{className:"px-3 py-2 border-b border-[var(--border)] flex items-center justify-between",children:[e.jsx("span",{className:"text-[11px] font-semibold text-[var(--text-dim)]",children:"Recording"}),s&&e.jsxs("span",{className:"inline-flex items-center gap-1.5 text-[11px] text-[var(--red)]",children:[e.jsx("span",{className:"h-1.5 w-1.5 rounded-full bg-[var(--red)] pulse-dot"}),"Live"]})]}),e.jsx("div",{className:"aspect-video bg-[var(--bg)] flex items-center justify-center",children:s&&t.has_live_video?e.jsx("img",{src:_.getSessionLiveVideoUrl(t.id),alt:`Live view of session ${t.id}`,className:"w-full h-full object-contain"}):r?e.jsx("video",{controls:!0,src:_.getAssetUrl(t.video_recording),className:"w-full h-full object-contain"}):e.jsxs("div",{className:"flex flex-col items-center text-center px-6 py-8 gap-2",children:[e.jsx("div",{className:"h-10 w-10 rounded-full bg-[var(--surface-2)] border border-[var(--border)] flex items-center justify-center",children:e.jsx(de,{className:"h-5 w-5 text-[var(--text-dim)]"})}),e.jsx("div",{className:"text-sm text-[var(--text)] font-medium",children:"No video available"}),e.jsx("div",{className:"text-xs text-[var(--text-dim)] max-w-xs",children:t.status==="failed"?"Session failed before recording started.":t.video_recording_enabled===!1?"Recording was disabled for this session.":"No recording was captured."})]})})]})},Re=({session:t})=>{const[s,r]=d.useState("desired"),i=U(t.desired_capabilities),n=U(t.session_capabilities),c=Object.entries(s==="desired"?i:n);return e.jsxs("section",{className:"rounded-lg border border-[var(--border)] bg-[var(--surface)] overflow-hidden",children:[e.jsx("header",{className:"flex items-center border-b border-[var(--border)]",children:["desired","session"].map(a=>e.jsx("button",{type:"button",onClick:()=>r(a),"aria-pressed":s===a,className:`flex-1 h-9 text-[11px] font-semibold transition-colors border-b-2 ${s===a?"border-[var(--color-accent)] text-[var(--text)]":"border-transparent text-[var(--text-muted)] hover:text-[var(--text)]"}`,children:a},a))}),c.length===0?e.jsxs("div",{className:"px-3 py-6 text-center text-xs text-[var(--text-dim)]",children:["No ",s," capabilities reported for this session."]}):e.jsx("dl",{className:"divide-y divide-[var(--border)]",children:c.map(([a,x])=>e.jsxs("div",{className:"flex items-baseline justify-between gap-3 px-3 py-2",children:[e.jsx("dt",{className:"text-xs text-[var(--text-muted)] truncate shrink-0 max-w-[45%]",children:a}),e.jsx("dd",{className:"font-mono text-xs text-[var(--text)] truncate text-right min-w-0",title:I(x,500),children:I(x)})]},a))})]})},_e=({tabs:t,active:s,onChange:r,errorsOnly:i,onErrorsOnlyChange:n})=>{const l=t.filter(c=>!(c.hideWhenEmpty&&c.count===0));return e.jsxs("div",{className:"flex items-center justify-between gap-4 px-3 border-b border-[var(--border)] bg-[var(--surface)]",children:[e.jsx("div",{className:"flex items-center gap-1 overflow-x-auto",children:l.map(c=>{const a=c.key===s;return e.jsxs("button",{type:"button",onClick:()=>r(c.key),"aria-pressed":a,className:`relative inline-flex items-center gap-1.5 h-9 px-3 text-xs whitespace-nowrap transition-colors ${a?"text-[var(--text)]":"text-[var(--text-muted)] hover:text-[var(--text)]"}`,children:[e.jsx("span",{children:c.label}),e.jsx("span",{className:`font-mono text-[10px] ${a?"text-[var(--text-muted)]":"text-[var(--text-dim)]"}`,children:c.count}),a&&e.jsx("span",{className:"absolute left-2 right-2 bottom-0 h-[2px] bg-[var(--color-accent)] rounded-t"})]},c.key)})}),e.jsxs("label",{className:"inline-flex items-center gap-2 text-[11px] text-[var(--text-muted)] cursor-pointer select-none whitespace-nowrap",children:[e.jsx("input",{type:"checkbox",checked:i,onChange:c=>n(c.target.checked),"aria-label":"Show only error rows"}),"Errors only"]})]})};function W(t){const s=t.timestamp;if(!s){const c=t.createdAt;return c?W({timestamp:c}):"--:--:--"}const r=typeof s=="number"?new Date(s):new Date(String(s));if(Number.isNaN(r.getTime()))return"--:--:--";const i=String(r.getHours()).padStart(2,"0"),n=String(r.getMinutes()).padStart(2,"0"),l=String(r.getSeconds()).padStart(2,"0");return`${i}:${n}:${l}`}function Ce(t){if(t.healed===!0)return{label:String(t.command_name||"healed"),tone:"amber"};if(t.is_success===!1)return{label:String(t.command_name||t.title||"error"),tone:"red"};if(t.is_success===!0)return{label:String(t.command_name||t.title||"ok"),tone:"green"};const s=t.title||t.event||t.command_name;return typeof s=="string"?/stop|fail|error/i.test(s)?{label:s,tone:"red"}:/start|begin|init/i.test(s)?{label:s,tone:"green"}:{label:s,tone:"blue"}:{label:"log",tone:"neutral"}}function Te(t){if(t==null)return"";if(typeof t=="string")try{return JSON.stringify(JSON.parse(t),null,2)}catch{return t}try{return JSON.stringify(t,null,2)}catch{return String(t)}}function $e(t){if(!t||typeof t!="string")return[{text:String(t??""),kind:"plain"}];const s=[],r=/("(?:\\.|[^"\\])*")(\s*:)|("(?:\\.|[^"\\])*")|(-?\d+(?:\.\d+)?(?:[eE][+-]?\d+)?)|\b(true|false)\b|\b(null)\b|([{}[\],])/g;let i=0,n;for(;(n=r.exec(t))!==null;)n.index>i&&s.push({text:t.slice(i,n.index),kind:"plain"}),n[1]&&n[2]!==void 0?(s.push({text:n[1],kind:"key"}),s.push({text:n[2],kind:"punct"})):n[3]?s.push({text:n[3],kind:"string"}):n[4]?s.push({text:n[4],kind:"number"}):n[5]?s.push({text:n[5],kind:"boolean"}):n[6]?s.push({text:n[6],kind:"null"}):n[7]&&s.push({text:n[7],kind:"punct"}),i=r.lastIndex;return i<t.length&&s.push({text:t.slice(i),kind:"plain"}),s}function De(t){const s=t,r=typeof s.title=="string"&&s.title.trim()?s.title.trim():null,i=typeof s.command_name=="string"&&s.command_name.trim()?s.command_name.trim():null;return r??i??"Command"}function V(t){const s=t.subtitle;return typeof s=="string"&&s.trim()?s.trim():null}function Le(t,s){return s?t.filter(r=>r.is_success===!1):t}const Ee={key:"text-[var(--blue)]",string:"text-[var(--color-accent)]",number:"text-[var(--amber)]",boolean:"text-[var(--amber)]",null:"text-[var(--text-dim)] italic",punct:"text-[var(--text-muted)]",plain:"text-[var(--text)]"},Oe=({value:t,maxHeightPx:s})=>{const r=Te(t);if(!r)return e.jsx("span",{className:"text-[var(--text-dim)] text-xs",children:"(empty)"});let i;try{i=$e(r)}catch{i=[{text:r,kind:"plain"}]}return e.jsx("pre",{className:"font-mono text-[11px] leading-relaxed bg-[var(--bg)] border border-[var(--border)] rounded-md p-3 overflow-x-auto whitespace-pre",style:s?{maxHeight:s,overflowY:"auto"}:void 0,children:i.map((n,l)=>e.jsx("span",{className:Ee[n.kind],children:n.text},l))})},Ae={green:"bg-[var(--color-success)]",red:"bg-[var(--red)]",amber:"bg-[var(--amber)]",blue:"bg-[var(--blue)]",neutral:"bg-[var(--text-dim)]"},Fe={green:"text-[var(--color-success)]",red:"text-[var(--red)]",amber:"text-[var(--amber)]",blue:"text-[var(--blue)]",neutral:"text-[var(--text-muted)]"},Pe=({log:t})=>{const[s,r]=d.useState(!1),{toast:i}=D(),n=W(t),l=Ce(t),c=async a=>{a.stopPropagation();try{const x=t.body??t,u=typeof x=="string"?x:JSON.stringify(x,null,2);await navigator.clipboard.writeText(u),i("Log entry copied","success")}catch{i("Clipboard unavailable","error")}};return e.jsxs("div",{className:"border-b border-[var(--border)] last:border-b-0",children:[e.jsxs("button",{type:"button",onClick:()=>r(a=>!a),"aria-expanded":s,className:"group w-full flex items-center gap-2 px-3 py-2 text-left hover:bg-[var(--surface-2)]/60 transition-colors",children:[e.jsx($,{className:`h-3 w-3 text-[var(--text-dim)] transition-transform shrink-0 ${s?"rotate-90":""}`}),e.jsx("span",{className:"font-mono text-[11px] text-[var(--text-muted)] w-[64px] shrink-0",children:n}),e.jsx("span",{className:`h-1.5 w-1.5 rounded-full shrink-0 ${Ae[l.tone]}`}),e.jsx("span",{className:`font-mono text-[11px] font-medium shrink-0 ${Fe[l.tone]}`,children:l.label}),e.jsxs("span",{className:"min-w-0 flex-1 flex items-baseline gap-2 truncate",children:[e.jsx("span",{className:"text-[12px] text-[var(--text)] shrink-0",children:De(t)}),V(t)&&e.jsx("span",{className:"font-mono text-[11px] text-[var(--text-dim)] truncate min-w-0",children:V(t)})]}),e.jsx("span",{role:"button",tabIndex:0,onClick:c,onKeyDown:a=>{(a.key==="Enter"||a.key===" ")&&c(a)},"aria-label":"Copy log entry",className:"opacity-0 group-hover:opacity-100 p-1 rounded text-[var(--text-dim)] hover:text-[var(--text)] transition-opacity shrink-0",children:e.jsx(L,{className:"h-3 w-3"})})]}),s&&e.jsx("div",{className:"px-3 pb-3 pl-9",children:e.jsx(Oe,{value:t.body??t,maxHeightPx:400})})]})},He=({sessionLogs:t,deviceLogs:s,debugLogs:r,profiling:i})=>{const[n,l]=d.useState("text"),[c,a]=d.useState(!1),x=d.useMemo(()=>[{key:"text",label:"Text logs",count:t.length},{key:"performance",label:"Performance trace",count:0},{key:"evidence",label:"Evidence",count:0},{key:"device",label:"Device logs",count:s.length},{key:"debug",label:"Debug logs",count:r.length},{key:"profiling",label:"System profiling",count:i.length,hideWhenEmpty:!0}],[t.length,s.length,r.length,i.length]),u=d.useMemo(()=>{let f=[];return n==="text"?f=t:n==="device"?f=s:n==="debug"?f=r:n==="profiling"&&(f=i),Le(f,c)},[n,t,s,r,i,c]);return e.jsxs("section",{className:"rounded-lg border border-[var(--border)] bg-[var(--surface)] flex flex-col min-h-[280px]",children:[e.jsx(_e,{tabs:x,active:n,onChange:l,errorsOnly:c,onErrorsOnlyChange:a}),e.jsxs("div",{className:"flex-1 overflow-y-auto",children:[n==="performance"&&e.jsx("div",{className:"px-4 py-10 text-center text-xs text-[var(--text-dim)]",children:"Performance Trace will be wired up once a session emits trace data."}),n==="evidence"&&e.jsx("div",{className:"px-4 py-10 text-center text-xs text-[var(--text-dim)]",children:"Evidence (screenshots) will be wired up alongside the screenshot service."}),(n==="text"||n==="device"||n==="debug"||n==="profiling")&&(u.length===0?e.jsx("div",{className:"px-4 py-10 text-center text-xs text-[var(--text-dim)]",children:c?"No error rows in this tab.":"No log entries in this tab."}):u.map((f,h)=>e.jsx(Pe,{log:f},f.id??h)))]})]})},Be=({header:t,footer:s,action:r,padded:i=!0,className:n,children:l})=>e.jsxs("div",{className:`card${n?" "+n:""}`,children:[(t||r)&&e.jsxs("div",{className:"card-header",children:[e.jsx("div",{className:"card-header-title",children:t}),r&&e.jsx("div",{className:"card-header-action",children:r})]}),e.jsx("div",{className:i?"card-body":"card-body-flush",children:l}),s&&e.jsx("div",{className:"card-footer",children:s})]});function X(t){if(!t)return"failed";switch(t){case"HTTPS_CLIENT_ERROR":case"HTTPS_SERVER_ERROR":case"OPEN_HTTPS_SERVER_ERROR":case"ON_CONNECT_ERROR":return"tls";case"PROXY_TO_SERVER_REQUEST_ERROR":return"net";default:return"failed"}}const P="/xenon/api/interceptor";async function Me(t){const s=await fetch(`${P}/sessions/${encodeURIComponent(t)}/requests`);if(s.status===404){const i=await s.json().catch(()=>({}));return{active:!1,error:i==null?void 0:i.error}}return s.ok?{active:!0,requests:(await s.json()).requests||[]}:{active:!1,error:`request failed (${s.status})`}}async function Je(t,s){const r=await fetch(`${P}/sessions/${encodeURIComponent(t)}/requests/${encodeURIComponent(s)}`);return r.ok?r.json():null}function Ue(t){return`${P}/sessions/${encodeURIComponent(t)}/har`}function Ie(t){return t>=200&&t<300?"ready":t>=300&&t<400?"neutral":t>=400&&t<500?"busy":t>=500?"error":"neutral"}const K=({headers:t})=>{const s=Object.entries(t||{});return s.length===0?e.jsx("div",{className:"text-xs text-[var(--text-dim)]",children:"No headers"}):e.jsx("div",{className:"space-y-0.5 font-mono text-xs",children:s.map(([r,i])=>e.jsxs("div",{className:"flex gap-2",children:[e.jsxs("span",{className:"text-[var(--text-dim)] shrink-0",children:[r,":"]}),e.jsx("span",{className:"break-all",children:i})]},r))})},z=({body:t})=>{if(t==null||t==="")return e.jsx("div",{className:"text-xs text-[var(--text-dim)]",children:"No body"});let s=t;try{s=JSON.stringify(JSON.parse(t),null,2)}catch{}return e.jsx("pre",{className:"font-mono text-xs whitespace-pre-wrap break-all bg-[var(--surface-2,var(--surface))] rounded p-2 max-h-64 overflow-auto",children:s})},Ve=({request:t,onClose:s})=>{if(!t)return null;const r=e.jsxs("div",{className:"flex items-center gap-2 text-sm",children:[e.jsx(j,{tone:"accent",children:t.method}),t.failed?e.jsx(j,{tone:"error",children:X(t.failureKind)}):e.jsx(j,{tone:Ie(t.resStatus),children:t.resStatus||"—"}),e.jsx("span",{className:"font-mono text-xs truncate",title:t.url,children:t.url})]});return e.jsx(fe,{open:!!t,title:r,onClose:s,width:720,children:e.jsxs("div",{className:"space-y-4 text-xs",children:[t.failed&&e.jsxs("div",{className:"border border-[var(--red)] rounded p-2 bg-[rgb(var(--rgb-red-600)/0.08)]",children:[e.jsx("div",{className:"text-[var(--red)] text-[11px] mb-1",children:"Failure"}),e.jsx("div",{className:"text-xs",children:t.failureReason||"Request failed"}),t.failureKind&&e.jsx("div",{className:"font-mono text-[10px] text-[var(--text-dim)] mt-1",children:t.failureKind})]}),!t.failed&&e.jsxs("div",{className:"grid grid-cols-2 gap-3",children:[e.jsxs("div",{children:[e.jsx("div",{className:"text-[var(--text-dim)] text-[11px] mb-1",children:"Duration"}),e.jsxs("div",{className:"font-mono",children:[t.durationMs," ms"]})]}),e.jsxs("div",{children:[e.jsx("div",{className:"text-[var(--text-dim)] text-[11px] mb-1",children:"Flags"}),e.jsxs("div",{className:"flex gap-1",children:[t.mocked&&e.jsx(j,{tone:"accent",children:"mocked"}),t.modified&&e.jsx(j,{tone:"busy",children:"modified"}),!t.mocked&&!t.modified&&e.jsx("span",{className:"text-[var(--text-dim)]",children:"passthrough"})]})]})]}),t.commandHint&&e.jsxs("div",{children:[e.jsx("div",{className:"text-[var(--text-dim)] text-[11px] mb-1",children:"Triggered by"}),e.jsx("div",{className:"font-mono",children:t.commandHint.commandName})]}),!t.failed&&e.jsxs(e.Fragment,{children:[e.jsxs("div",{children:[e.jsx("div",{className:"text-[var(--text-dim)] text-[11px] mb-1",children:"Request Headers"}),e.jsx(K,{headers:t.reqHeaders})]}),e.jsxs("div",{children:[e.jsx("div",{className:"text-[var(--text-dim)] text-[11px] mb-1",children:"Request Body"}),e.jsx(z,{body:t.reqBody})]}),e.jsxs("div",{children:[e.jsx("div",{className:"text-[var(--text-dim)] text-[11px] mb-1",children:"Response Headers"}),e.jsx(K,{headers:t.resHeaders})]}),e.jsxs("div",{children:[e.jsx("div",{className:"text-[var(--text-dim)] text-[11px] mb-1",children:"Response Body"}),e.jsx(z,{body:t.resBody})]})]})]})})};function Ke(t){return t?new Date(t).toLocaleTimeString(void 0,{hour12:!1}):"—"}function ze(t){return t>=200&&t<300?"ready":t>=300&&t<400?"neutral":t>=400&&t<500?"busy":t>=500?"error":"neutral"}const We=({sessionId:t,sessionEnded:s})=>{const[r,i]=d.useState(null),[n,l]=d.useState(null),[c,a]=d.useState([]),[x,u]=d.useState(!0),[f,h]=d.useState(null),v=d.useRef(new Set),{on:y,isConnected:N}=G();d.useEffect(()=>{let o=!0;return u(!0),Me(t).then(b=>{if(!o)return;i(b.active),l(b.error||null);const k=b.requests||[];a(k),v.current=new Set(k.map(m=>m.id))}).finally(()=>{o&&u(!1)}),()=>{o=!1}},[t]),d.useEffect(()=>{if(s)return;const o=y("interceptor_request",m=>{!m||m.sessionId!==t||v.current.has(m.id)||(v.current.add(m.id),a(T=>[m,...T]),i(!0))}),b=y("interceptor_session_started",m=>{(m==null?void 0:m.sessionId)===t&&i(!0)}),k=y("interceptor_session_stopped",m=>{(m==null?void 0:m.sessionId)===t&&i(!1)});return()=>{o(),b(),k()}},[y,t,s,N]);const w=d.useMemo(()=>[...c].sort((o,b)=>b.ts-o.ts),[c]),g=async o=>{if(h(o),r){const b=await Je(t,o.id);b&&h(b)}},C=r&&c.length>0?e.jsxs("a",{href:Ue(t),className:"inline-flex items-center gap-1 text-xs text-[var(--text-dim)] hover:text-[var(--text)]",title:"Download HAR",children:[e.jsx(he,{className:"h-3 w-3"}),"HAR"]}):null,E=e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx(pe,{className:"h-3.5 w-3.5 text-[var(--text-dim)]"}),e.jsx("span",{children:"Network"}),r&&c.length>0&&e.jsxs("span",{className:"text-xs text-[var(--text-dim)]",children:["(",c.length,")"]})]});let p;return x?p=e.jsx("div",{className:"p-4 text-xs text-[var(--text-dim)]",children:"Loading…"}):r===!1&&s?p=e.jsx(O,{title:"No network capture",description:"Network interception was not enabled for this session."}):r===!1?p=e.jsx(O,{title:"Network interception disabled",description:"Enable interceptor.enabled in plugin config to capture requests for Android sessions."}):n?p=e.jsxs("div",{className:"p-4 text-xs text-[var(--red)]",children:["Failed to load requests: ",n]}):w.length===0?p=e.jsx(O,{title:"Waiting for requests",description:s?"No HTTP traffic was captured during this session.":"Captured requests will appear here as the device makes calls."}):p=e.jsx("div",{className:"overflow-auto max-h-96",children:e.jsxs(xe,{children:[e.jsx(me,{children:e.jsxs(M,{children:[e.jsx(S,{style:{width:80},children:"Time"}),e.jsx(S,{style:{width:70},children:"Method"}),e.jsx(S,{style:{width:70},children:"Status"}),e.jsx(S,{children:"Host"}),e.jsx(S,{children:"Path"}),e.jsx(S,{style:{width:80},children:"Duration"}),e.jsx(S,{style:{width:90},children:"Flags"})]})}),e.jsx(ue,{children:w.map(o=>e.jsxs(M,{onClick:()=>g(o),style:{cursor:"pointer"},title:o.failed?o.failureReason:void 0,children:[e.jsx(R,{className:"font-mono text-[11px]",children:Ke(o.ts)}),e.jsx(R,{children:e.jsx(j,{tone:"accent",children:o.method})}),e.jsx(R,{children:o.failed?e.jsx(j,{tone:"error",children:X(o.failureKind)}):e.jsx(j,{tone:ze(o.resStatus),children:o.resStatus||"—"})}),e.jsx(R,{className:"font-mono text-[11px] truncate",title:o.host,children:o.host}),e.jsx(R,{className:"font-mono text-[11px] truncate",title:o.path,children:o.failed?"—":o.path}),e.jsx(R,{className:"font-mono text-[11px]",children:o.failed?"—":`${o.durationMs}ms`}),e.jsx(R,{children:e.jsxs("div",{className:"flex gap-1",children:[o.mocked&&e.jsx(j,{tone:"accent",children:"mock"}),o.modified&&e.jsx(j,{tone:"busy",children:"mod"})]})})]},o.id))})]})}),e.jsxs(e.Fragment,{children:[e.jsx(Be,{header:E,action:C,padded:!1,children:p}),e.jsx(Ve,{request:f,onClose:()=>h(null)})]})};function Xe(t){return t==="running"?{label:"Running",tone:"running"}:t==="failed"?{label:"Failed",tone:"failed"}:t==="ended"||t==="passed"?{label:"Passed",tone:"passed"}:{label:ve((typeof t=="string"?t:"")||"unknown"),tone:"offline"}}const xt=()=>{const{buildId:t="",sessionId:s=""}=Q(),{toast:r}=D(),i=Z(),n=q(),l=be(s||null),c=d.useMemo(()=>{const g=n.builds.find(C=>C.id===t);return(g==null?void 0:g.name)||"Build"},[n.builds,t]);if(d.useEffect(()=>{!l.loading&&l.notFound&&(r("Session not available — it may belong to a team you are not on.","info"),i("/builds",{replace:!0}))},[l.loading,l.notFound,i,r]),l.loading)return e.jsx("div",{className:"p-6 text-xs text-[var(--text-dim)]",children:"Loading session…"});if(l.error||!l.session)return e.jsxs("div",{className:"p-6 space-y-2",children:[e.jsx(J,{buildId:t,buildName:c,sessionId:s}),e.jsx("div",{className:"mt-6 rounded-md border border-[var(--red)]/30 bg-[var(--surface)] p-4 text-xs text-[var(--red)]",children:l.error||"Session not found."})]});const a=l.session,x=Xe(a.status),u=ee(te(a)),f=[...l.sessionLogs,...l.deviceLogs,...l.debugLogs],h=async()=>{try{await navigator.clipboard.writeText(a.id),r("Session ID copied","success")}catch{r("Clipboard unavailable","error")}},v=[{label:"Device",value:se(a)},{label:"Node ID",value:a.node_id||"—",mono:!0},{label:"Platform",value:re(a)},{label:"OS version",value:a.device_version?ae(a):"—",mono:!0}],y=[{label:"Session ID",value:e.jsxs("span",{className:"inline-flex items-center gap-1",children:[e.jsx("span",{className:"truncate",title:a.id,children:a.id}),e.jsx("button",{type:"button",onClick:h,"aria-label":"Copy session ID",className:"p-0.5 rounded text-[var(--text-dim)] hover:text-[var(--text)]",children:e.jsx(L,{className:"h-3 w-3"})})]}),mono:!0},{label:"Start time",value:ne(a.startTime),mono:!0},{label:"Duration",value:u,mono:!0}],N=a.status==="failed",w=[{label:"Status",value:e.jsx(ie,{label:x.label,tone:x.tone})}];if(N&&a.failure_category){const g=F(a.failure_category);w.push({label:"Category",value:e.jsx("a",{href:`/xenon/runbooks/${encodeURIComponent(a.failure_category.toLowerCase())}`,target:"_blank",rel:"noreferrer",className:"text-[var(--red)] hover:underline",children:g})})}return N&&a.failure_reason&&w.push({label:"Failure reason",value:a.failure_reason,tone:"red"}),e.jsxs("div",{className:"flex flex-col h-full min-h-0",children:[e.jsx(J,{buildId:t,buildName:c,sessionId:a.id}),e.jsx("div",{className:"flex-1 overflow-y-auto overflow-x-hidden",children:e.jsxs("div",{className:"px-4 py-4 space-y-4",children:[e.jsx(je,{identity:v,run:y,result:w}),N&&e.jsx(ke,{session:a,buildName:c,buildId:t,allLogs:f,durationText:u}),e.jsxs("div",{className:"grid grid-cols-1 lg:grid-cols-[1fr_340px] gap-4",children:[e.jsx("div",{className:"min-w-0",children:e.jsx(He,{sessionLogs:l.sessionLogs,deviceLogs:l.deviceLogs,debugLogs:l.debugLogs,profiling:l.profiling})}),e.jsxs("div",{className:"flex flex-col gap-4",children:[e.jsx(Se,{session:a}),e.jsx(Re,{session:a})]})]}),e.jsx(We,{sessionId:a.id,sessionEnded:a.status!=="running"})]})})]})};export{xt as SessionDetailPage,xt as default};
@@ -1,4 +1,4 @@
1
- import{c as q,t as B,r,p as P,X as g,j as e,A as V,O as X,C as G,e as O,P as U,Q as K}from"./index-3uxl3o7K.js";/* empty css */import{S as j,A as Q}from"./SettingCard-BR7nOhpT.js";import{M as W}from"./Modal-Bw-a-E-e.js";import{B as A}from"./button-_Y78wXiP.js";import{P as J}from"./page-header-CfR4Sm9V.js";import{C as I}from"./circle-check-D3Qq0tKp.js";import{C as Y}from"./clock-BfYfzvSg.js";import{M as Z}from"./mouse-pointer-2-Cnab2zdg.js";import{C as ee}from"./check-uGHCXe-L.js";import{A as ae}from"./activity-DxRFWvkN.js";import{C as se}from"./calendar-D4MqSOc2.js";import{A as te}from"./arrow-up-right-DFHi_8yG.js";import"./index-Zy1Op5C1.js";import"./utils-CDN07tui.js";/**
1
+ import{c as q,t as B,r,p as P,X as g,j as e,A as V,O as X,C as G,e as O,P as U,Q as K}from"./index-BQCXPOXt.js";/* empty css */import{S as j,A as Q}from"./SettingCard-CYBPhKPe.js";import{M as W}from"./Modal-Djp4NvyZ.js";import{B as A}from"./button-BIwCF2bR.js";import{P as J}from"./page-header-CuFXVUop.js";import{C as I}from"./circle-check-DsvxbnTg.js";import{C as Y}from"./clock-C6XOs4bc.js";import{M as Z}from"./mouse-pointer-2-ys1MKVr2.js";import{C as ee}from"./check-zugO3p5U.js";import{A as ae}from"./activity-QsRK21QF.js";import{C as se}from"./calendar-CMLnXC7N.js";import{A as te}from"./arrow-up-right-B7TEV_Gr.js";import"./index-C-Q4QkXb.js";import"./utils-CDN07tui.js";/**
2
2
  * @license lucide-react v0.555.0 - ISC
3
3
  *
4
4
  * This source code is licensed under the ISC license.
@@ -1 +1 @@
1
- import{r as a,p as _,X as v,j as y}from"./index-3uxl3o7K.js";import{f as E}from"./time-B8FIgwPE.js";const $=3e3;function k(){const[e,t]=a.useState([]),[r,o]=a.useState([]),[s,i]=a.useState(null),[d,p]=a.useState(""),[S,b]=a.useState(!0),[x,m]=a.useState(null),c=a.useRef(!0),{on:l}=_(),u=a.useCallback(async()=>{try{const[n,f]=await Promise.all([v.getBuilds(),s?v.getSessions({buildId:s,query:d}):Promise.resolve([])]);if(!c.current)return;t(Array.isArray(n)?n:[]),o(Array.isArray(f)?f:[]),m(null)}catch(n){if(!c.current)return;m(n instanceof Error?n.message:String(n))}finally{c.current&&b(!1)}},[s,d]);return a.useEffect(()=>{c.current=!0,u();const n=setInterval(u,$);return()=>{c.current=!1,clearInterval(n)}},[u]),a.useEffect(()=>{const n=()=>u(),f=[l("session_started",n),l("session_stopped",n),l("device_added",n),l("device_removed",n)];return()=>{for(const g of f)g()}},[l,u]),{builds:e,selectedBuildId:s,sessions:r,loading:S,error:x,selectBuild:i,searchQuery:d,setSearchQuery:p,refresh:u}}function h(e){switch(e){case"success":case"passed":case"ended":return"passed";case"failed":case"error":case"timeout":return"failed";case"running":return"running";default:return"other"}}function B(e){const t={all:e.length,passed:0,failed:0,running:0};for(const r of e){const o=h(r.status);o!=="other"&&(t[o]+=1)}return t}function w(e,t){return t==="all"?!0:h(e.status)===t}function C(e,t,r){const o=r.trim().toLowerCase();return e.filter(s=>!(!w(s,t)||o&&!(s.id+" "+(s.name??"")+" "+(s.device_name??"")+" "+(s.device_platform??"")+" "+(s.device_version??"")+" "+(s.node_id??"")).toLowerCase().includes(o)))}function I(e){var r;const t=(r=e.device_name)==null?void 0:r.trim();return t&&t.length>0?t:"Unknown Device"}function T(e){const t=e.device_platform??"";if(!t)return"—";const r=t.toLowerCase();return r==="ios"?"iOS":r==="tvos"?"tvOS":r.charAt(0).toUpperCase()+r.slice(1)}function F(e){return e.device_version?`v${e.device_version}`:""}function M(e){return E(e)}function N(e){if(!e.startTime)return null;const t=Date.parse(e.startTime);if(!Number.isFinite(t))return null;const r=e.endTime?Date.parse(e.endTime):Date.now();return Number.isFinite(r)?Math.max(0,r-t):null}function R(e){if(e==null||!Number.isFinite(e)||e<0)return"—";const t=e/1e3,r=Math.floor(t/3600),o=Math.floor(t%3600/60),i=(t-r*3600-o*60).toFixed(1);return r>0?`${r}h ${o}m ${i}s`:o>0?`${o}m ${i}s`:`${i}s`}function j(e,t=10,r=4){return e?e.length<=t+r+1?e:`${e.slice(0,t)}…${e.slice(-r)}`:""}const D={ready:"border-[var(--color-success)]/40 text-[var(--color-success)]",passed:"border-[var(--color-success)]/40 text-[var(--color-success)]",running:"border-[var(--amber)]/40 text-[var(--amber)]",failed:"border-[var(--red)]/40 text-[var(--red)]",offline:"border-[var(--text-dim)]/40 text-[var(--text-dim)]"},O=({label:e,tone:t})=>y.jsx("span",{className:`inline-flex items-center justify-center h-6 px-2.5 rounded border text-[10px] font-mono font-semibold tracking-wider ${D[t]}`,children:e});export{O as S,h as a,B as b,N as c,I as d,C as e,M as f,R as h,F as o,T as p,j as s,k as u};
1
+ import{r as a,p as _,X as v,j as y}from"./index-BQCXPOXt.js";import{f as E}from"./time-B8FIgwPE.js";const $=3e3;function k(){const[e,t]=a.useState([]),[r,o]=a.useState([]),[s,i]=a.useState(null),[d,p]=a.useState(""),[S,b]=a.useState(!0),[x,m]=a.useState(null),c=a.useRef(!0),{on:l}=_(),u=a.useCallback(async()=>{try{const[n,f]=await Promise.all([v.getBuilds(),s?v.getSessions({buildId:s,query:d}):Promise.resolve([])]);if(!c.current)return;t(Array.isArray(n)?n:[]),o(Array.isArray(f)?f:[]),m(null)}catch(n){if(!c.current)return;m(n instanceof Error?n.message:String(n))}finally{c.current&&b(!1)}},[s,d]);return a.useEffect(()=>{c.current=!0,u();const n=setInterval(u,$);return()=>{c.current=!1,clearInterval(n)}},[u]),a.useEffect(()=>{const n=()=>u(),f=[l("session_started",n),l("session_stopped",n),l("device_added",n),l("device_removed",n)];return()=>{for(const g of f)g()}},[l,u]),{builds:e,selectedBuildId:s,sessions:r,loading:S,error:x,selectBuild:i,searchQuery:d,setSearchQuery:p,refresh:u}}function h(e){switch(e){case"success":case"passed":case"ended":return"passed";case"failed":case"error":case"timeout":return"failed";case"running":return"running";default:return"other"}}function B(e){const t={all:e.length,passed:0,failed:0,running:0};for(const r of e){const o=h(r.status);o!=="other"&&(t[o]+=1)}return t}function w(e,t){return t==="all"?!0:h(e.status)===t}function C(e,t,r){const o=r.trim().toLowerCase();return e.filter(s=>!(!w(s,t)||o&&!(s.id+" "+(s.name??"")+" "+(s.device_name??"")+" "+(s.device_platform??"")+" "+(s.device_version??"")+" "+(s.node_id??"")).toLowerCase().includes(o)))}function I(e){var r;const t=(r=e.device_name)==null?void 0:r.trim();return t&&t.length>0?t:"Unknown Device"}function T(e){const t=e.device_platform??"";if(!t)return"—";const r=t.toLowerCase();return r==="ios"?"iOS":r==="tvos"?"tvOS":r.charAt(0).toUpperCase()+r.slice(1)}function F(e){return e.device_version?`v${e.device_version}`:""}function M(e){return E(e)}function N(e){if(!e.startTime)return null;const t=Date.parse(e.startTime);if(!Number.isFinite(t))return null;const r=e.endTime?Date.parse(e.endTime):Date.now();return Number.isFinite(r)?Math.max(0,r-t):null}function R(e){if(e==null||!Number.isFinite(e)||e<0)return"—";const t=e/1e3,r=Math.floor(t/3600),o=Math.floor(t%3600/60),i=(t-r*3600-o*60).toFixed(1);return r>0?`${r}h ${o}m ${i}s`:o>0?`${o}m ${i}s`:`${i}s`}function j(e,t=10,r=4){return e?e.length<=t+r+1?e:`${e.slice(0,t)}…${e.slice(-r)}`:""}const D={ready:"border-[var(--color-success)]/40 text-[var(--color-success)]",passed:"border-[var(--color-success)]/40 text-[var(--color-success)]",running:"border-[var(--amber)]/40 text-[var(--amber)]",failed:"border-[var(--red)]/40 text-[var(--red)]",offline:"border-[var(--text-dim)]/40 text-[var(--text-dim)]"},O=({label:e,tone:t})=>y.jsx("span",{className:`inline-flex items-center justify-center h-6 px-2.5 rounded border text-[10px] font-mono font-semibold tracking-wider ${D[t]}`,children:e});export{O as S,h as a,B as b,N as c,I as d,C as e,M as f,R as h,F as o,T as p,j as s,k as u};
@@ -1,4 +1,4 @@
1
- import{c as e}from"./index-3uxl3o7K.js";/**
1
+ import{c as e}from"./index-BQCXPOXt.js";/**
2
2
  * @license lucide-react v0.555.0 - ISC
3
3
  *
4
4
  * This source code is licensed under the ISC license.
@@ -1 +1 @@
1
- import{t as A,r as n,j as e,A as I,W as f,q as $}from"./index-3uxl3o7K.js";/* empty css */import{a as F}from"./time-B8FIgwPE.js";import{T as E,a as M,b as T,c as u,d as U,e as p}from"./Table-B_Va3V05.js";import{F as Y}from"./FieldGroup-5bCutWrs.js";import{P as R}from"./page-header-CfR4Sm9V.js";import{M as K}from"./Modal-Bw-a-E-e.js";import{B as D}from"./button-_Y78wXiP.js";import{I as Q}from"./input-CzTWvUXZ.js";import{S as P}from"./select-Cqx7pEou.js";import{l as V}from"./users-BU0nXIVe.js";import{P as N}from"./plus-DOS8P9CQ.js";import{A as X}from"./arrow-left-uQ6WIwiC.js";import{T as L}from"./trash-2-BV4hSmXJ.js";import"./index-Zy1Op5C1.js";import"./utils-CDN07tui.js";const B={SUPER_ADMIN:"Super admin",ADMIN:"Admin",MEMBER:"Member"};async function j(i,r){const t=await fetch(i,{credentials:"include",...r});if(!t.ok){const c=await t.json().catch(()=>({}));throw Object.assign(new Error(c.error||`HTTP ${t.status}`),{status:t.status})}return t.json()}const ve=()=>{const{toast:i}=A(),[r,t]=n.useState([]),[c,m]=n.useState(!0),[l,h]=n.useState(!1),[x,d]=n.useState(!1),[_,C]=n.useState(null),v=async()=>{m(!0);try{const a=await j("/xenon/api/teams");t(a),h(!1)}catch(a){a.status===403?h(!0):i(`Failed to load teams: ${a.message}`,"error")}finally{m(!1)}};if(n.useEffect(()=>{v()},[]),c)return e.jsxs("div",{className:"settings-loading",children:[e.jsx(I,{className:"animate-spin",size:32}),e.jsx("span",{children:"Loading teams…"})]});if(l)return e.jsx("div",{className:"settings-container",children:e.jsx(R,{icon:f,title:"Teams",subtitle:e.jsxs(e.Fragment,{children:["Your key lacks the ",e.jsx("code",{children:"admin"})," scope. Ask an administrator to promote your key before you can manage teams."]})})});if(_)return e.jsx(se,{team:_,onBack:()=>{C(null),v()}});const S=r.reduce((a,o)=>a+o.deviceCount,0),y=r.reduce((a,o)=>a+o.memberCount,0);return e.jsxs("div",{className:"settings-container",children:[e.jsx(R,{icon:f,title:"Teams",subtitle:"Group devices and members by team. Devices with no team assignment stay in the shared pool — visible to every authenticated user.",action:r.length>0?e.jsxs("button",{type:"button",className:"page-header-action",onClick:()=>d(!0),children:[e.jsx(N,{size:16}),e.jsx("span",{children:"New team"})]}):void 0}),e.jsxs("div",{className:"settings-content",children:[r.length>0&&e.jsxs("div",{className:"stat-strip",children:[e.jsxs("div",{className:"stat-strip__cell",children:[e.jsx("div",{className:"stat-strip__value stat-strip__value--accent",children:r.length}),e.jsx("div",{className:"stat-strip__label",children:"Teams"})]}),e.jsxs("div",{className:"stat-strip__cell",children:[e.jsx("div",{className:"stat-strip__value",children:y}),e.jsx("div",{className:"stat-strip__label",children:"Members"})]}),e.jsxs("div",{className:"stat-strip__cell",children:[e.jsx("div",{className:"stat-strip__value",children:S}),e.jsx("div",{className:"stat-strip__label",children:"Devices assigned"})]})]}),r.length===0?e.jsxs("div",{className:"empty-state",children:[e.jsx("div",{className:"empty-state__icon",children:e.jsx(f,{size:28})}),e.jsx("h3",{className:"empty-state__title",children:"No teams yet"}),e.jsx("p",{className:"empty-state__copy",children:"Every device is in the shared pool until you create a team and assign it. Teams let you scope an API key to a subset of devices — useful for separating CI runners, staging fleets, or per-team device pools."}),e.jsxs("button",{type:"button",className:"page-header-action empty-state__action",onClick:()=>d(!0),children:[e.jsx(N,{size:16}),e.jsx("span",{children:"Create your first team"})]})]}):e.jsx("div",{className:"team-grid",children:r.map(a=>e.jsxs("button",{type:"button",className:"team-card",onClick:()=>C(a),children:[e.jsxs("div",{className:"team-card__header",children:[e.jsx("div",{className:"team-card__icon",children:e.jsx(f,{size:16})}),e.jsxs("div",{className:"team-card__title",children:[e.jsx("div",{className:"team-card__name",children:a.name}),e.jsx("div",{className:"team-card__id",children:a.id.slice(0,8)})]}),e.jsx("span",{className:"team-card__delete",role:"button",tabIndex:0,onClick:o=>o.stopPropagation(),children:e.jsx(ee,{team:a,onDeleted:v})})]}),e.jsxs("div",{className:"team-card__metrics",children:[e.jsxs("div",{className:"team-card__metric",children:[e.jsx($,{size:13}),e.jsx("span",{className:"team-card__metric-value",children:a.deviceCount}),e.jsx("span",{className:"team-card__metric-label",children:"devices"})]}),e.jsxs("div",{className:"team-card__metric",children:[e.jsx(f,{size:13}),e.jsx("span",{className:"team-card__metric-value",children:a.memberCount}),e.jsx("span",{className:"team-card__metric-label",children:"members"})]})]}),e.jsxs("div",{className:"team-card__footer",children:["Created ",F(a.createdAt)]})]},a.id))})]}),x&&e.jsx(Z,{onClose:()=>d(!1),onCreated:()=>{d(!1),v()}})]})},Z=({onClose:i,onCreated:r})=>{const{toast:t}=A(),[c,m]=n.useState(""),[l,h]=n.useState(!1),x=async()=>{if(!c.trim())return t("Name required","error");h(!0);try{await j("/xenon/api/teams",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({name:c.trim()})}),t("Team created","success"),r()}catch(d){t(d.message,"error")}finally{h(!1)}};return e.jsx(K,{open:!0,onClose:i,title:"New team",footer:e.jsxs(e.Fragment,{children:[e.jsx(D,{variant:"secondary",onClick:i,disabled:l,children:"Cancel"}),e.jsxs(D,{variant:"primary",onClick:x,disabled:l,children:[l?e.jsx(I,{className:"animate-spin",size:18}):e.jsx(N,{size:18}),l?"Creating…":"Create"]})]}),children:e.jsx("div",{style:{display:"flex",flexDirection:"column"},children:e.jsx(Y,{label:"Name",htmlFor:"team-name",children:e.jsx(Q,{id:"team-name",type:"text",value:c,onChange:d=>m(d.target.value),placeholder:"android-team, qa-ios, …",className:"w-full",autoFocus:!0})})})})},ee=({team:i,onDeleted:r})=>{const{toast:t}=A(),[c,m]=n.useState(!1),l=async h=>{if(h.stopPropagation(),!!window.confirm(`Delete team "${i.name}"? It must have no devices, members or apps.`)){m(!0);try{await j(`/xenon/api/teams/${i.id}`,{method:"DELETE"}),t("Team deleted","success"),r()}catch(x){t(x.message,"error")}finally{m(!1)}}};return e.jsxs("button",{className:"reset-btn",disabled:c,onClick:l,style:{color:"var(--status-error-fg)"},children:[e.jsx(L,{size:14}),c?"Deleting…":"Delete"]})},se=({team:i,onBack:r})=>{const{toast:t}=A(),[c,m]=n.useState([]),[l,h]=n.useState([]),[x,d]=n.useState([]),[_,C]=n.useState([]),[v,S]=n.useState(!0),[y,a]=n.useState(""),[o,k]=n.useState(""),b=async()=>{S(!0);try{const[s,g,W]=await Promise.all([j(`/xenon/api/teams/${i.id}/members`),V(),j("/xenon/api/device")]);m(s),h(g);const z=W;d(z.filter(w=>w.teamId===i.id)),C(z.filter(w=>!w.teamId))}catch(s){t(`Failed to load team detail: ${s.message}`,"error")}finally{S(!1)}};n.useEffect(()=>{b()},[i.id]);const O=async()=>{if(y)try{await j(`/xenon/api/teams/${i.id}/members`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({userId:y})}),t("Member added","success"),a(""),b()}catch(s){t(s.message,"error")}},H=async s=>{if(window.confirm("Remove this member from the team?"))try{await j(`/xenon/api/teams/${i.id}/members/${encodeURIComponent(s)}`,{method:"DELETE"}),t("Member removed","success"),b()}catch(g){t(g.message,"error")}},J=async()=>{if(o)try{await j(`/xenon/api/device/${encodeURIComponent(o)}/team`,{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify({teamId:i.id})}),t("Device assigned","success"),k(""),b()}catch(s){t(s.message,"error")}},q=async s=>{if(window.confirm("Return this device to the shared pool?"))try{await j(`/xenon/api/device/${encodeURIComponent(s)}/team`,{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify({teamId:null})}),t("Device unassigned","success"),b()}catch(g){t(g.message,"error")}},G=l.filter(s=>!c.some(g=>g.userId===s.id));return e.jsxs("div",{className:"settings-container mesh-gradient-infra",children:[e.jsxs("div",{className:"settings-header",children:[e.jsxs("div",{style:{display:"flex",alignItems:"center",gap:12},children:[e.jsx("button",{onClick:r,className:"reset-btn",style:{padding:"4px 8px"},"aria-label":"Back",children:e.jsx(X,{size:18})}),e.jsxs("div",{className:"settings-title-group",children:[e.jsx(f,{className:"settings-icon infra-icon",size:28}),e.jsx("h2",{children:i.name})]})]}),e.jsx("p",{className:"settings-subtitle",children:'Manage members and devices assigned to this team. To add a device, go to Devices and use "Assign to team."'})]}),v?e.jsx("div",{className:"settings-loading",children:e.jsx(I,{className:"animate-spin",size:32})}):e.jsxs("div",{className:"settings-content",style:{display:"flex",flexDirection:"column",gap:24},children:[e.jsxs("section",{children:[e.jsxs("h3",{style:{marginBottom:12},children:["Members (",c.length,")"]}),e.jsxs("div",{className:"surface-card",style:{padding:12},children:[e.jsxs("div",{style:{display:"flex",gap:8,marginBottom:12},children:[e.jsxs(P,{value:y,onChange:s=>a(s.target.value),className:"flex-1",children:[e.jsx("option",{value:"",children:"Select a user to add…"}),G.map(s=>e.jsxs("option",{value:s.id,children:[s.name," (",s.email,") — ",B[s.role]]},s.id))]}),e.jsxs(D,{variant:"primary",onClick:O,disabled:!y,children:[e.jsx(N,{size:16})," Add"]})]}),c.length===0?e.jsx("p",{style:{opacity:.6,textAlign:"center",padding:24},children:"No members yet. Add a user above."}):e.jsxs(E,{children:[e.jsx(M,{children:e.jsxs(T,{children:[e.jsx(u,{children:"Name"}),e.jsx(u,{children:"Email"}),e.jsx(u,{children:"Role"}),e.jsx(u,{children:"Added"}),e.jsx(u,{style:{textAlign:"right"},children:"Action"})]})}),e.jsx(U,{children:c.map(s=>e.jsxs(T,{children:[e.jsx(p,{children:s.name}),e.jsx(p,{children:e.jsx("code",{style:{fontSize:"11px",color:"var(--text-muted)"},children:s.email})}),e.jsx(p,{children:B[s.role]}),e.jsx(p,{children:F(s.addedAt)}),e.jsx(p,{style:{textAlign:"right"},children:e.jsx("button",{className:"reset-btn",onClick:()=>H(s.userId),style:{color:"var(--status-error-fg)"},"aria-label":"Remove member",title:"Remove member",children:e.jsx(L,{size:14})})})]},s.userId))})]})]})]}),e.jsxs("section",{children:[e.jsxs("h3",{style:{marginBottom:12},children:["Devices (",x.length,")"]}),e.jsxs("div",{className:"surface-card",style:{padding:12},children:[e.jsxs("div",{style:{display:"flex",gap:8,marginBottom:12},children:[e.jsxs(P,{value:o,onChange:s=>k(s.target.value),className:"flex-1",children:[e.jsx("option",{value:"",children:"Select a shared-pool device to assign…"}),_.map(s=>e.jsxs("option",{value:s.udid,children:[s.name," (",s.platform,") — ",s.udid.slice(0,12),"…"]},s.udid))]}),e.jsxs(D,{variant:"primary",onClick:J,disabled:!o,children:[e.jsx(N,{size:16})," Assign"]})]}),x.length===0?e.jsx("p",{style:{opacity:.6,textAlign:"center",padding:24},children:"No devices assigned. Use the Devices page to move devices into this team."}):e.jsxs(E,{children:[e.jsx(M,{children:e.jsxs(T,{children:[e.jsx(u,{children:"Name"}),e.jsx(u,{children:"Platform"}),e.jsx(u,{children:"UDID"}),e.jsx(u,{style:{textAlign:"right"},children:"Actions"})]})}),e.jsx(U,{children:x.map(s=>e.jsxs(T,{children:[e.jsxs(p,{children:[e.jsx($,{size:14,style:{marginRight:6,verticalAlign:"middle"}}),s.name]}),e.jsx(p,{children:s.platform}),e.jsx(p,{children:e.jsxs("code",{style:{fontSize:"11px"},children:[s.udid.slice(0,14),"…"]})}),e.jsx(p,{style:{textAlign:"right"},children:e.jsx("button",{className:"reset-btn",onClick:()=>q(s.udid),children:"Return to shared pool"})})]},s.udid))})]})]})]})]})]})};export{ve as Teams};
1
+ import{t as A,r as n,j as e,A as I,W as f,q as $}from"./index-BQCXPOXt.js";/* empty css */import{a as F}from"./time-B8FIgwPE.js";import{T as E,a as M,b as T,c as u,d as U,e as p}from"./Table-CdKQ9hnU.js";import{F as Y}from"./FieldGroup-CorXlSLU.js";import{P as R}from"./page-header-CuFXVUop.js";import{M as K}from"./Modal-Djp4NvyZ.js";import{B as D}from"./button-BIwCF2bR.js";import{I as Q}from"./input-DnUVHYax.js";import{S as P}from"./select-f0ci1QC7.js";import{l as V}from"./users-eXWwQZjX.js";import{P as N}from"./plus-DUSlMac2.js";import{A as X}from"./arrow-left-BkA7oMRe.js";import{T as L}from"./trash-2-BKsgmBS6.js";import"./index-C-Q4QkXb.js";import"./utils-CDN07tui.js";const B={SUPER_ADMIN:"Super admin",ADMIN:"Admin",MEMBER:"Member"};async function j(i,r){const t=await fetch(i,{credentials:"include",...r});if(!t.ok){const c=await t.json().catch(()=>({}));throw Object.assign(new Error(c.error||`HTTP ${t.status}`),{status:t.status})}return t.json()}const ve=()=>{const{toast:i}=A(),[r,t]=n.useState([]),[c,m]=n.useState(!0),[l,h]=n.useState(!1),[x,d]=n.useState(!1),[_,C]=n.useState(null),v=async()=>{m(!0);try{const a=await j("/xenon/api/teams");t(a),h(!1)}catch(a){a.status===403?h(!0):i(`Failed to load teams: ${a.message}`,"error")}finally{m(!1)}};if(n.useEffect(()=>{v()},[]),c)return e.jsxs("div",{className:"settings-loading",children:[e.jsx(I,{className:"animate-spin",size:32}),e.jsx("span",{children:"Loading teams…"})]});if(l)return e.jsx("div",{className:"settings-container",children:e.jsx(R,{icon:f,title:"Teams",subtitle:e.jsxs(e.Fragment,{children:["Your key lacks the ",e.jsx("code",{children:"admin"})," scope. Ask an administrator to promote your key before you can manage teams."]})})});if(_)return e.jsx(se,{team:_,onBack:()=>{C(null),v()}});const S=r.reduce((a,o)=>a+o.deviceCount,0),y=r.reduce((a,o)=>a+o.memberCount,0);return e.jsxs("div",{className:"settings-container",children:[e.jsx(R,{icon:f,title:"Teams",subtitle:"Group devices and members by team. Devices with no team assignment stay in the shared pool — visible to every authenticated user.",action:r.length>0?e.jsxs("button",{type:"button",className:"page-header-action",onClick:()=>d(!0),children:[e.jsx(N,{size:16}),e.jsx("span",{children:"New team"})]}):void 0}),e.jsxs("div",{className:"settings-content",children:[r.length>0&&e.jsxs("div",{className:"stat-strip",children:[e.jsxs("div",{className:"stat-strip__cell",children:[e.jsx("div",{className:"stat-strip__value stat-strip__value--accent",children:r.length}),e.jsx("div",{className:"stat-strip__label",children:"Teams"})]}),e.jsxs("div",{className:"stat-strip__cell",children:[e.jsx("div",{className:"stat-strip__value",children:y}),e.jsx("div",{className:"stat-strip__label",children:"Members"})]}),e.jsxs("div",{className:"stat-strip__cell",children:[e.jsx("div",{className:"stat-strip__value",children:S}),e.jsx("div",{className:"stat-strip__label",children:"Devices assigned"})]})]}),r.length===0?e.jsxs("div",{className:"empty-state",children:[e.jsx("div",{className:"empty-state__icon",children:e.jsx(f,{size:28})}),e.jsx("h3",{className:"empty-state__title",children:"No teams yet"}),e.jsx("p",{className:"empty-state__copy",children:"Every device is in the shared pool until you create a team and assign it. Teams let you scope an API key to a subset of devices — useful for separating CI runners, staging fleets, or per-team device pools."}),e.jsxs("button",{type:"button",className:"page-header-action empty-state__action",onClick:()=>d(!0),children:[e.jsx(N,{size:16}),e.jsx("span",{children:"Create your first team"})]})]}):e.jsx("div",{className:"team-grid",children:r.map(a=>e.jsxs("button",{type:"button",className:"team-card",onClick:()=>C(a),children:[e.jsxs("div",{className:"team-card__header",children:[e.jsx("div",{className:"team-card__icon",children:e.jsx(f,{size:16})}),e.jsxs("div",{className:"team-card__title",children:[e.jsx("div",{className:"team-card__name",children:a.name}),e.jsx("div",{className:"team-card__id",children:a.id.slice(0,8)})]}),e.jsx("span",{className:"team-card__delete",role:"button",tabIndex:0,onClick:o=>o.stopPropagation(),children:e.jsx(ee,{team:a,onDeleted:v})})]}),e.jsxs("div",{className:"team-card__metrics",children:[e.jsxs("div",{className:"team-card__metric",children:[e.jsx($,{size:13}),e.jsx("span",{className:"team-card__metric-value",children:a.deviceCount}),e.jsx("span",{className:"team-card__metric-label",children:"devices"})]}),e.jsxs("div",{className:"team-card__metric",children:[e.jsx(f,{size:13}),e.jsx("span",{className:"team-card__metric-value",children:a.memberCount}),e.jsx("span",{className:"team-card__metric-label",children:"members"})]})]}),e.jsxs("div",{className:"team-card__footer",children:["Created ",F(a.createdAt)]})]},a.id))})]}),x&&e.jsx(Z,{onClose:()=>d(!1),onCreated:()=>{d(!1),v()}})]})},Z=({onClose:i,onCreated:r})=>{const{toast:t}=A(),[c,m]=n.useState(""),[l,h]=n.useState(!1),x=async()=>{if(!c.trim())return t("Name required","error");h(!0);try{await j("/xenon/api/teams",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({name:c.trim()})}),t("Team created","success"),r()}catch(d){t(d.message,"error")}finally{h(!1)}};return e.jsx(K,{open:!0,onClose:i,title:"New team",footer:e.jsxs(e.Fragment,{children:[e.jsx(D,{variant:"secondary",onClick:i,disabled:l,children:"Cancel"}),e.jsxs(D,{variant:"primary",onClick:x,disabled:l,children:[l?e.jsx(I,{className:"animate-spin",size:18}):e.jsx(N,{size:18}),l?"Creating…":"Create"]})]}),children:e.jsx("div",{style:{display:"flex",flexDirection:"column"},children:e.jsx(Y,{label:"Name",htmlFor:"team-name",children:e.jsx(Q,{id:"team-name",type:"text",value:c,onChange:d=>m(d.target.value),placeholder:"android-team, qa-ios, …",className:"w-full",autoFocus:!0})})})})},ee=({team:i,onDeleted:r})=>{const{toast:t}=A(),[c,m]=n.useState(!1),l=async h=>{if(h.stopPropagation(),!!window.confirm(`Delete team "${i.name}"? It must have no devices, members or apps.`)){m(!0);try{await j(`/xenon/api/teams/${i.id}`,{method:"DELETE"}),t("Team deleted","success"),r()}catch(x){t(x.message,"error")}finally{m(!1)}}};return e.jsxs("button",{className:"reset-btn",disabled:c,onClick:l,style:{color:"var(--status-error-fg)"},children:[e.jsx(L,{size:14}),c?"Deleting…":"Delete"]})},se=({team:i,onBack:r})=>{const{toast:t}=A(),[c,m]=n.useState([]),[l,h]=n.useState([]),[x,d]=n.useState([]),[_,C]=n.useState([]),[v,S]=n.useState(!0),[y,a]=n.useState(""),[o,k]=n.useState(""),b=async()=>{S(!0);try{const[s,g,W]=await Promise.all([j(`/xenon/api/teams/${i.id}/members`),V(),j("/xenon/api/device")]);m(s),h(g);const z=W;d(z.filter(w=>w.teamId===i.id)),C(z.filter(w=>!w.teamId))}catch(s){t(`Failed to load team detail: ${s.message}`,"error")}finally{S(!1)}};n.useEffect(()=>{b()},[i.id]);const O=async()=>{if(y)try{await j(`/xenon/api/teams/${i.id}/members`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({userId:y})}),t("Member added","success"),a(""),b()}catch(s){t(s.message,"error")}},H=async s=>{if(window.confirm("Remove this member from the team?"))try{await j(`/xenon/api/teams/${i.id}/members/${encodeURIComponent(s)}`,{method:"DELETE"}),t("Member removed","success"),b()}catch(g){t(g.message,"error")}},J=async()=>{if(o)try{await j(`/xenon/api/device/${encodeURIComponent(o)}/team`,{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify({teamId:i.id})}),t("Device assigned","success"),k(""),b()}catch(s){t(s.message,"error")}},q=async s=>{if(window.confirm("Return this device to the shared pool?"))try{await j(`/xenon/api/device/${encodeURIComponent(s)}/team`,{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify({teamId:null})}),t("Device unassigned","success"),b()}catch(g){t(g.message,"error")}},G=l.filter(s=>!c.some(g=>g.userId===s.id));return e.jsxs("div",{className:"settings-container mesh-gradient-infra",children:[e.jsxs("div",{className:"settings-header",children:[e.jsxs("div",{style:{display:"flex",alignItems:"center",gap:12},children:[e.jsx("button",{onClick:r,className:"reset-btn",style:{padding:"4px 8px"},"aria-label":"Back",children:e.jsx(X,{size:18})}),e.jsxs("div",{className:"settings-title-group",children:[e.jsx(f,{className:"settings-icon infra-icon",size:28}),e.jsx("h2",{children:i.name})]})]}),e.jsx("p",{className:"settings-subtitle",children:'Manage members and devices assigned to this team. To add a device, go to Devices and use "Assign to team."'})]}),v?e.jsx("div",{className:"settings-loading",children:e.jsx(I,{className:"animate-spin",size:32})}):e.jsxs("div",{className:"settings-content",style:{display:"flex",flexDirection:"column",gap:24},children:[e.jsxs("section",{children:[e.jsxs("h3",{style:{marginBottom:12},children:["Members (",c.length,")"]}),e.jsxs("div",{className:"surface-card",style:{padding:12},children:[e.jsxs("div",{style:{display:"flex",gap:8,marginBottom:12},children:[e.jsxs(P,{value:y,onChange:s=>a(s.target.value),className:"flex-1",children:[e.jsx("option",{value:"",children:"Select a user to add…"}),G.map(s=>e.jsxs("option",{value:s.id,children:[s.name," (",s.email,") — ",B[s.role]]},s.id))]}),e.jsxs(D,{variant:"primary",onClick:O,disabled:!y,children:[e.jsx(N,{size:16})," Add"]})]}),c.length===0?e.jsx("p",{style:{opacity:.6,textAlign:"center",padding:24},children:"No members yet. Add a user above."}):e.jsxs(E,{children:[e.jsx(M,{children:e.jsxs(T,{children:[e.jsx(u,{children:"Name"}),e.jsx(u,{children:"Email"}),e.jsx(u,{children:"Role"}),e.jsx(u,{children:"Added"}),e.jsx(u,{style:{textAlign:"right"},children:"Action"})]})}),e.jsx(U,{children:c.map(s=>e.jsxs(T,{children:[e.jsx(p,{children:s.name}),e.jsx(p,{children:e.jsx("code",{style:{fontSize:"11px",color:"var(--text-muted)"},children:s.email})}),e.jsx(p,{children:B[s.role]}),e.jsx(p,{children:F(s.addedAt)}),e.jsx(p,{style:{textAlign:"right"},children:e.jsx("button",{className:"reset-btn",onClick:()=>H(s.userId),style:{color:"var(--status-error-fg)"},"aria-label":"Remove member",title:"Remove member",children:e.jsx(L,{size:14})})})]},s.userId))})]})]})]}),e.jsxs("section",{children:[e.jsxs("h3",{style:{marginBottom:12},children:["Devices (",x.length,")"]}),e.jsxs("div",{className:"surface-card",style:{padding:12},children:[e.jsxs("div",{style:{display:"flex",gap:8,marginBottom:12},children:[e.jsxs(P,{value:o,onChange:s=>k(s.target.value),className:"flex-1",children:[e.jsx("option",{value:"",children:"Select a shared-pool device to assign…"}),_.map(s=>e.jsxs("option",{value:s.udid,children:[s.name," (",s.platform,") — ",s.udid.slice(0,12),"…"]},s.udid))]}),e.jsxs(D,{variant:"primary",onClick:J,disabled:!o,children:[e.jsx(N,{size:16})," Assign"]})]}),x.length===0?e.jsx("p",{style:{opacity:.6,textAlign:"center",padding:24},children:"No devices assigned. Use the Devices page to move devices into this team."}):e.jsxs(E,{children:[e.jsx(M,{children:e.jsxs(T,{children:[e.jsx(u,{children:"Name"}),e.jsx(u,{children:"Platform"}),e.jsx(u,{children:"UDID"}),e.jsx(u,{style:{textAlign:"right"},children:"Actions"})]})}),e.jsx(U,{children:x.map(s=>e.jsxs(T,{children:[e.jsxs(p,{children:[e.jsx($,{size:14,style:{marginRight:6,verticalAlign:"middle"}}),s.name]}),e.jsx(p,{children:s.platform}),e.jsx(p,{children:e.jsxs("code",{style:{fontSize:"11px"},children:[s.udid.slice(0,14),"…"]})}),e.jsx(p,{style:{textAlign:"right"},children:e.jsx("button",{className:"reset-btn",onClick:()=>q(s.udid),children:"Return to shared pool"})})]},s.udid))})]})]})]})]})]})};export{ve as Teams};
@@ -1,4 +1,4 @@
1
- import{c as a}from"./index-3uxl3o7K.js";/**
1
+ import{c as a}from"./index-BQCXPOXt.js";/**
2
2
  * @license lucide-react v0.555.0 - ISC
3
3
  *
4
4
  * This source code is licensed under the ISC license.
@@ -1,4 +1,4 @@
1
- import{c as a}from"./index-3uxl3o7K.js";/**
1
+ import{c as a}from"./index-BQCXPOXt.js";/**
2
2
  * @license lucide-react v0.555.0 - ISC
3
3
  *
4
4
  * This source code is licensed under the ISC license.
@@ -1 +1 @@
1
- import{r as t,h as u}from"./index-3uxl3o7K.js";function n(){const[s,r]=t.useState(null);return t.useEffect(()=>{let e=!0;return u().then(o=>e&&r(o.passwordReset)),()=>{e=!1}},[]),s}export{n as u};
1
+ import{r as t,h as u}from"./index-BQCXPOXt.js";function n(){const[s,r]=t.useState(null);return t.useEffect(()=>{let e=!0;return u().then(o=>e&&r(o.passwordReset)),()=>{e=!1}},[]),s}export{n as u};
@@ -1,4 +1,4 @@
1
- import{c as w,b as k,r as a,j as e,$ as C}from"./index-3uxl3o7K.js";import{l as M,d as R,c as I,a as A,u as D}from"./users-BU0nXIVe.js";import{f as U}from"./time-B8FIgwPE.js";import{P}from"./page-header-CfR4Sm9V.js";import{B as y}from"./button-_Y78wXiP.js";import{I as N}from"./input-CzTWvUXZ.js";import{S as g}from"./select-Cqx7pEou.js";import{P as B}from"./plus-DOS8P9CQ.js";import{T as L}from"./trash-2-BV4hSmXJ.js";import"./utils-CDN07tui.js";/**
1
+ import{c as w,b as k,r as a,j as e,$ as C}from"./index-BQCXPOXt.js";import{l as M,d as R,c as I,a as A,u as D}from"./users-eXWwQZjX.js";import{f as U}from"./time-B8FIgwPE.js";import{P}from"./page-header-CuFXVUop.js";import{B as y}from"./button-BIwCF2bR.js";import{I as N}from"./input-DnUVHYax.js";import{S as g}from"./select-f0ci1QC7.js";import{P as B}from"./plus-DUSlMac2.js";import{T as L}from"./trash-2-BKsgmBS6.js";import"./utils-CDN07tui.js";/**
2
2
  * @license lucide-react v0.555.0 - ISC
3
3
  *
4
4
  * This source code is licensed under the ISC license.
@@ -1 +1 @@
1
- import{o as s}from"./index-3uxl3o7K.js";const o="/xenon/api/users";async function c(){const t=await fetch(`${o}/`,{credentials:"include"});if(!t.ok)throw new Error(`listUsers failed (${t.status})`);return t.json()}async function i(t){const e=await fetch(`${o}/`,{method:"POST",credentials:"include",headers:{"Content-Type":"application/json",...s},body:JSON.stringify(t)});if(!e.ok){const n=await e.json().catch(()=>({}));throw new Error(n.error||`createUser failed (${e.status})`)}return e.json()}async function d(t,e){const n=await fetch(`${o}/${encodeURIComponent(t)}`,{method:"PATCH",credentials:"include",headers:{"Content-Type":"application/json"},body:JSON.stringify(e)});if(!n.ok){const r=await n.json().catch(()=>({}));throw new Error(r.error||`updateUser failed (${n.status})`)}return n.json()}async function l(t){const e=await fetch(`${o}/${encodeURIComponent(t)}`,{method:"DELETE",credentials:"include"});if(!e.ok&&e.status!==204){const n=await e.json().catch(()=>({}));throw new Error(n.error||`deleteUser failed (${e.status})`)}}async function u(t){const e=await fetch(`${o}/${encodeURIComponent(t)}/reset-link`,{method:"POST",credentials:"include"}),n=await e.json().catch(()=>({}));if(!e.ok)throw new Error(n.error||`Reset link failed (${e.status})`);return n}export{i as a,u as c,l as d,c as l,d as u};
1
+ import{o as s}from"./index-BQCXPOXt.js";const o="/xenon/api/users";async function c(){const t=await fetch(`${o}/`,{credentials:"include"});if(!t.ok)throw new Error(`listUsers failed (${t.status})`);return t.json()}async function i(t){const e=await fetch(`${o}/`,{method:"POST",credentials:"include",headers:{"Content-Type":"application/json",...s},body:JSON.stringify(t)});if(!e.ok){const n=await e.json().catch(()=>({}));throw new Error(n.error||`createUser failed (${e.status})`)}return e.json()}async function d(t,e){const n=await fetch(`${o}/${encodeURIComponent(t)}`,{method:"PATCH",credentials:"include",headers:{"Content-Type":"application/json"},body:JSON.stringify(e)});if(!n.ok){const r=await n.json().catch(()=>({}));throw new Error(r.error||`updateUser failed (${n.status})`)}return n.json()}async function l(t){const e=await fetch(`${o}/${encodeURIComponent(t)}`,{method:"DELETE",credentials:"include"});if(!e.ok&&e.status!==204){const n=await e.json().catch(()=>({}));throw new Error(n.error||`deleteUser failed (${e.status})`)}}async function u(t){const e=await fetch(`${o}/${encodeURIComponent(t)}/reset-link`,{method:"POST",credentials:"include"}),n=await e.json().catch(()=>({}));if(!e.ok)throw new Error(n.error||`Reset link failed (${e.status})`);return n}export{i as a,u as c,l as d,c as l,d as u};
@@ -1,4 +1,4 @@
1
- import{c as o}from"./index-3uxl3o7K.js";/**
1
+ import{c as o}from"./index-BQCXPOXt.js";/**
2
2
  * @license lucide-react v0.555.0 - ISC
3
3
  *
4
4
  * This source code is licensed under the ISC license.