@xenon-device-management/xenon 2.3.0 → 2.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/package.json +1 -1
- package/lib/public/assets/{AnnotationOverlay-AxcBYoKp.js → AnnotationOverlay-BeypNvFL.js} +1 -1
- package/lib/public/assets/{ApiKeyGate-CIU02EIx.js → ApiKeyGate-CQg51mzi.js} +1 -1
- package/lib/public/assets/{BugReportButton-_akEEjXm.js → BugReportButton-JVduDicX.js} +1 -1
- package/lib/public/assets/{DeviceMosaicView-Bhk1udmn.js → DeviceMosaicView-BnEKlOi9.js} +1 -1
- package/lib/public/assets/{EmptyState-DRKRm19_.js → EmptyState-CVk_39sG.js} +1 -1
- package/lib/public/assets/{FieldGroup-zQQHPh7x.js → FieldGroup-DC4jWFOr.js} +1 -1
- package/lib/public/assets/{FilterMenu-C9_StnDi.js → FilterMenu-Df4ApWT_.js} +1 -1
- package/lib/public/assets/{Menu-0J7io6pF.js → Menu-BZcyp6Df.js} +1 -1
- package/lib/public/assets/{Modal-C677ljNX.js → Modal-D27eM9ja.js} +1 -1
- package/lib/public/assets/{RecordingPage-BDJFck-L.js → RecordingPage-ScK_NxUR.js} +1 -1
- package/lib/public/assets/{RecordingsPage-DQkimbKK.js → RecordingsPage-DO6KsDwr.js} +1 -1
- package/lib/public/assets/{SegmentedControl-DvGMZBIE.js → SegmentedControl-P0_wzUSa.js} +1 -1
- package/lib/public/assets/{SettingCard-ogyouYBq.js → SettingCard-CnbZajUY.js} +1 -1
- package/lib/public/assets/{Table-BLFCOLlO.js → Table-DCLEpILV.js} +1 -1
- package/lib/public/assets/{activity-BU55TGRG.js → activity-c-lgQI29.js} +1 -1
- package/lib/public/assets/{ai-settings-GpDAiHav.js → ai-settings-S4Qb0zMX.js} +1 -1
- package/lib/public/assets/{api-keys-dOzP0k8_.js → api-keys-B8OZRdWq.js} +1 -1
- package/lib/public/assets/{apps-mAwAQmkn.js → apps-BUdm1f-6.js} +1 -1
- package/lib/public/assets/{arrow-left-Dg9mxe9T.js → arrow-left-DuWnjija.js} +1 -1
- package/lib/public/assets/{arrow-right-BVcmUyq3.js → arrow-right-9qDEU3uD.js} +1 -1
- package/lib/public/assets/{arrow-up-right-ByR5pZrH.js → arrow-up-right-b6Of0lQ3.js} +1 -1
- package/lib/public/assets/{auth-shell-Jpgk8CgY.js → auth-shell-DM7UlvlL.js} +2 -2
- package/lib/public/assets/builds-page-AOQqU3g3.js +16 -0
- package/lib/public/assets/{button-D-X4wjO8.js → button-D2poE4AT.js} +1 -1
- package/lib/public/assets/{calendar-ur_p5ETA.js → calendar-BwZZxp7_.js} +1 -1
- package/lib/public/assets/{check-K33iMeyq.js → check-bpRVp-8m.js} +1 -1
- package/lib/public/assets/{chevron-left-DMVWShd-.js → chevron-left-o5fCPIVE.js} +1 -1
- package/lib/public/assets/{chevron-right-DphLJ2_X.js → chevron-right-Bp0cGaHf.js} +1 -1
- package/lib/public/assets/{circle-check-CNFhu8oE.js → circle-check-C7h_YWkh.js} +1 -1
- package/lib/public/assets/{circle-x-BH_cUbqZ.js → circle-x-BevILQ_g.js} +1 -1
- package/lib/public/assets/{clock-CVMVdVvp.js → clock-BEKymxJ4.js} +1 -1
- package/lib/public/assets/{copy-CZ2XHafL.js → copy-R5Kb2Sya.js} +1 -1
- package/lib/public/assets/{device-explorer-B94BhaqF.js → device-explorer-DuD_PXL0.js} +51 -56
- package/lib/public/assets/{download-UUiyw7kO.js → download-CUlaFpHe.js} +1 -1
- package/lib/public/assets/{forgot-password-CrS14F79.js → forgot-password-CHO8yPDz.js} +1 -1
- package/lib/public/assets/{funnel-BMOE5qJY.js → funnel-uB2CBRiY.js} +1 -1
- package/lib/public/assets/{index-hymrhlEZ.css → index-DSFSk-0t.css} +1 -1
- package/lib/public/assets/{index-D0R9Yic3.js → index-KgmoUqNo.js} +1 -1
- package/lib/public/assets/{index-2XPPbPwy.js → index-yibbsLFD.js} +2 -2
- package/lib/public/assets/{input-C-1b8J7i.js → input-BR-cDtqC.js} +1 -1
- package/lib/public/assets/{keycodes-Cly7dQc9.js → keycodes-dLBaFcVi.js} +1 -1
- package/lib/public/assets/{layers-DFZfqGdX.js → layers-BESinxSO.js} +1 -1
- package/lib/public/assets/list-checks-DpKchgZl.js +6 -0
- package/lib/public/assets/{lock-ylHMJpfP.js → lock--sC5e3s6.js} +1 -1
- package/lib/public/assets/{login-DWsWKqDx.js → login-Cc-IivWH.js} +1 -1
- package/lib/public/assets/{maintenance-settings-9B6_MTqW.js → maintenance-settings-CO1mxmXj.js} +1 -1
- package/lib/public/assets/{monitor-CzX0hBH1.js → monitor-Cf5xQDkm.js} +1 -1
- package/lib/public/assets/{mouse-pointer-2-CZHD7N3z.js → mouse-pointer-2-D0FTHFsu.js} +1 -1
- package/lib/public/assets/{network-Bikc4MyT.js → network-BDR_XEsw.js} +1 -1
- package/lib/public/assets/{overview-DzaA0aMe.js → overview-Bgr23HrL.js} +1 -1
- package/lib/public/assets/{page-header-DqGlDufy.js → page-header-mkEQJJPW.js} +1 -1
- package/lib/public/assets/{plus-Ct6aQTGM.js → plus-BGTOA7GD.js} +1 -1
- package/lib/public/assets/{profile-page-CCnUQ1Qk.js → profile-page-hogPzCrJ.js} +1 -1
- package/lib/public/assets/{reset-password-AmkGGXo5.js → reset-password-BobaiMBQ.js} +1 -1
- package/lib/public/assets/{runbook-page-DQQn9VyE.js → runbook-page-qw6u9fmW.js} +1 -1
- package/lib/public/assets/{select-k5ogtEWW.js → select-skq1Kjsx.js} +1 -1
- package/lib/public/assets/{selector-detail-page-BCcwC5ku.js → selector-detail-page-BJl3YxfV.js} +1 -1
- package/lib/public/assets/{selector-health-BVyX6kIh.js → selector-health-CMmIKYip.js} +1 -1
- package/lib/public/assets/{selector-health-page-CElBB6XT.js → selector-health-page-DR8zYoS9.js} +1 -1
- package/lib/public/assets/session-detail-page-Cpbl4HPh.js +3 -0
- package/lib/public/assets/{settings-DKBj9KyN.js → settings-rZ0cTErR.js} +1 -1
- package/lib/public/assets/{tablet-B6HI5OxV.js → tablet-C08V4-n2.js} +1 -1
- package/lib/public/assets/{teams-owoDHbOU.js → teams-9lNK5Hv4.js} +1 -1
- package/lib/public/assets/{trash-2-D61PoUrZ.js → trash-2-Uko_-EoJ.js} +1 -1
- package/lib/public/assets/{upload-1ZYEVvgD.js → upload-CyTBX5YJ.js} +1 -1
- package/lib/public/assets/use-builds-data-TVBd_s-l.js +1 -0
- package/lib/public/assets/{use-password-reset-mode-Dx0ghiiQ.js → use-password-reset-mode-BQkqB45G.js} +1 -1
- package/lib/public/assets/{users-C5CS5Qez.js → users-CQKCMBqe.js} +1 -1
- package/lib/public/assets/{users-PbGMd5sD.js → users-D7RusV-M.js} +1 -1
- package/lib/public/assets/{video-off-_XusI0HK.js → video-off-CWBbZnqz.js} +1 -1
- package/lib/public/assets/{webhook-settings-Bi_HHQlQ.js → webhook-settings-Q3AJC_pt.js} +1 -1
- package/lib/public/assets/{zap-uzHWFAKI.js → zap-CN2fMC_t.js} +1 -1
- package/lib/public/index.html +2 -2
- package/lib/src/app/routers/dashboard.js +42 -2
- package/lib/src/app/routers/nodePhoneControl.js +29 -6
- package/lib/src/app/routers/sessionInsights.js +221 -0
- package/lib/src/services/recording/RecordingOrchestrator.js +39 -5
- package/lib/src/services/recording/busy-precheck.js +5 -2
- package/lib/src/services/recording/nodeRecordingSource.js +156 -0
- package/lib/test/unit/busy-precheck.spec.js +32 -0
- package/lib/test/unit/node-phone-control.spec.js +26 -0
- package/lib/test/unit/node-recording-relay.spec.js +165 -0
- package/lib/test/unit/recording-orchestrator.spec.js +86 -2
- package/lib/test/unit/session-list-insights.spec.js +329 -0
- package/lib/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/lib/public/assets/builds-page-VnRTrcdl.js +0 -6
- package/lib/public/assets/session-detail-page-6bqo_-ND.js +0 -3
- package/lib/public/assets/status-pill-outline-CZNpvqej.js +0 -1
|
@@ -1,3 +0,0 @@
|
|
|
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-2XPPbPwy.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-CZNpvqej.js";import{B as oe,P as j}from"./BugReportButton-_akEEjXm.js";import{A as le}from"./arrow-left-Dg9mxe9T.js";import{C as $}from"./chevron-right-DphLJ2_X.js";import{C as L}from"./copy-CZ2XHafL.js";import{A as ce}from"./arrow-up-right-ByR5pZrH.js";import{V as de}from"./video-off-_XusI0HK.js";import{E as O}from"./EmptyState-DRKRm19_.js";import{T as xe,a as me,b as M,c as S,d as ue,e as R}from"./Table-BLFCOLlO.js";import{M as fe}from"./Modal-C677ljNX.js";import{D as he}from"./download-UUiyw7kO.js";import{N as pe}from"./network-Bikc4MyT.js";import{s as ve}from"./labels-C21SA4JG.js";import"./time-B8FIgwPE.js";import"./index-D0R9Yic3.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
|
-
`)}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
|
-
`)})]})]})]})},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 +0,0 @@
|
|
|
1
|
-
import{r as a,p as _,X as v,j as y}from"./index-2XPPbPwy.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};
|