mirror of
https://github.com/pyMC-dev/pyMC_Repeater.git
synced 2026-07-07 02:11:29 +02:00
a48b29837a
- Add pre-restart config preflight to RestartModal with pass/warning/fail result panel and "Restart Anyway" confirmation for warnings - Add Site Identification (site_name) config field shown as browser title and login page caption - Add GET /api/validate_config and GET /api/site_info backend endpoints - Sync document.title with site_name via system store watchEffect - Fix authRegression.test.ts TS2367 type narrowing error - add new radio hardware and radio settings tabs
1 line
11 KiB
JavaScript
1 line
11 KiB
JavaScript
import{r as e}from"./chunk-DECur_0Z.js";import{Ct as t,D as n,E as r,St as i,Y as a,f as o,g as s,k as c,l,m as u,o as d,p as f,r as p,s as m,u as h}from"./runtime-core.esm-bundler-C5QBTNWE.js";import{l as ee,t as g}from"./api-3gMnsCKh.js";import{t as te}from"./system-DbBvxitf.js";import{t as _}from"./_plugin-vue_export-helper-B7aGp3iI.js";import{n as ne}from"./index-DTUpsCzx.js";import{t as v}from"./plotly.min-BmxIBpZZ.js";var y=e(v(),1),re={class:`p-6 space-y-6`},b={class:`glass-card rounded-[15px] p-6`},x={class:`flex justify-center`},S={class:`flex gap-4`},ie=[`disabled`],ae=[`disabled`],oe={class:`glass-card rounded-[15px] p-6 space-y-4`},se={class:`text-content-primary dark:text-content-primary`},ce={class:`flex items-center justify-between gap-4 px-4 bg-primary/10 border border-primary/30 rounded-lg h-[52px] overflow-hidden`},le={key:0,class:`text-content-primary dark:text-primary text-sm`},ue={key:1,class:`text-content-muted dark:text-content-muted text-sm italic`},de={key:2,class:`text-content-primary dark:text-content-primary text-sm`},fe={key:3,class:`text-content-secondary dark:text-content-muted text-sm`},pe={class:`space-y-2`},me={class:`w-full bg-white/10 rounded-full h-2`},he={class:`text-content-secondary dark:text-content-muted text-sm`},C={class:`grid grid-cols-2 md:grid-cols-4 gap-4`},w={class:`glass-card rounded-[15px] p-4 text-center`},T={class:`text-2xl font-bold text-primary`},E={class:`glass-card rounded-[15px] p-4 text-center`},D={class:`text-2xl font-bold text-primary`},O={class:`glass-card rounded-[15px] p-4 text-center`},k={class:`text-2xl font-bold text-primary`},A={class:`glass-card rounded-[15px] p-4 text-center`},j={class:`text-2xl font-bold text-primary`},M=_(s({name:`CADCalibrationView`,__name:`CADCalibration`,setup(e){let s=te(),_=d(()=>document.documentElement.classList.contains(`dark`)),v=()=>{let e=_.value;return{title:e?`#F9FAFB`:`#111827`,subtitle:e?`#9CA3AF`:`#6B7280`,axis:e?`#D1D5DB`:`#374151`,tick:e?`#9CA3AF`:`#6B7280`,grid:e?`rgba(148, 163, 184, 0.1)`:`rgba(107, 114, 128, 0.15)`,zeroline:e?`rgba(148, 163, 184, 0.2)`:`rgba(107, 114, 128, 0.25)`,line:e?`rgba(148, 163, 184, 0.3)`:`rgba(107, 114, 128, 0.35)`,colorbarBorder:e?`rgba(255,255,255,0.2)`:`rgba(0,0,0,0.15)`,markerLine:e?`rgba(255,255,255,0.2)`:`rgba(0,0,0,0.15)`}},M=a(!1),N=a(null),P=a(null),F=a({}),I=a(null),L=a([]),R=a({}),z=a(`Ready to start calibration`),B=a(0),V=a(0),H=a(0),U=a(0),W=a(0),G=a(0),K=a(null),q=a(!1),J=a(!1),Y=a(!1),X=a(!1),Z=null,ge={responsive:!0,displayModeBar:!0,modeBarButtonsToRemove:[`pan2d`,`select2d`,`lasso2d`,`autoScale2d`],displaylogo:!1,toImageButtonOptions:{format:`png`,filename:`cad-calibration-heatmap`,height:600,width:800,scale:2}};function _e(){let e=v(),t=[{x:[],y:[],z:[],mode:`markers`,type:`scatter`,marker:{size:12,color:[],colorscale:[[0,`rgba(75, 85, 99, 0.4)`],[.1,`rgba(6, 182, 212, 0.3)`],[.5,`rgba(6, 182, 212, 0.6)`],[1,`rgba(16, 185, 129, 0.9)`]],showscale:!0,colorbar:{title:{text:`Detection Rate (%)`,font:{color:e.axis,size:14}},tickfont:{color:e.tick},bgcolor:`rgba(0,0,0,0)`,bordercolor:e.colorbarBorder,borderwidth:1,thickness:15},line:{color:e.markerLine,width:1}},hovertemplate:`<b>Peak:</b> %{x}<br><b>Min:</b> %{y}<br><b>Detection Rate:</b> %{marker.color:.1f}%<br><extra></extra>`,name:`Test Results`}],n={title:{text:`CAD Detection Rate<br><sub style="color: ${e.subtitle};">Channel Activity Detection Calibration</sub>`,font:{color:e.title,size:18},x:.5},xaxis:{title:{text:`CAD Peak Threshold`,font:{color:e.axis,size:14}},tickfont:{color:e.tick},gridcolor:e.grid,zerolinecolor:e.zeroline,linecolor:e.line},yaxis:{title:{text:`CAD Min Threshold`,font:{color:e.axis,size:14}},tickfont:{color:e.tick},gridcolor:e.grid,zerolinecolor:e.zeroline,linecolor:e.line},plot_bgcolor:`rgba(0, 0, 0, 0)`,paper_bgcolor:`rgba(0, 0, 0, 0)`,font:{color:e.title,family:`Inter, system-ui, sans-serif`},margin:{l:80,r:80,t:100,b:80},showlegend:!1};y.default.newPlot(`plotly-chart`,t,n,ge)}function ve(){if(Object.keys(F.value).length===0)return;let e=Object.values(F.value),t=[],n=[],r=[];for(let i of e)t.push(i.det_peak),n.push(i.det_min),r.push(i.detection_rate);let i={x:[t],y:[n],"marker.color":[r],hovertemplate:`<b>Peak:</b> %{x}<br><b>Min:</b> %{y}<br><b>Detection Rate:</b> %{marker.color:.1f}%<br><b>Status:</b> Tested<br><extra></extra>`};y.default.restyle(`plotly-chart`,i,[0])}async function ye(){try{let e=await g.post(`/cad-calibration-start`,{samples:10,delay_ms:50});if(e.success)M.value=!0,N.value=Date.now(),s.setCadCalibrationRunning(!0),F.value={},L.value=[],R.value={},I.value=null,q.value=!1,J.value=!1,Y.value=!1,X.value=!1,H.value=0,U.value=0,W.value=0,G.value=0,B.value=0,V.value=0,Z=setInterval(()=>{N.value&&(G.value=Math.floor((Date.now()-N.value)/1e3))},1e3),be();else throw Error(e.error||`Failed to start calibration`)}catch(e){z.value=`Error: ${e instanceof Error?e.message:`Unknown error`}`}}async function Q(){try{(await g.post(`/cad-calibration-stop`)).success&&(M.value=!1,s.setCadCalibrationRunning(!1),P.value&&=(P.value.close(),null),Z&&=(clearInterval(Z),null))}catch(e){console.error(`Failed to stop calibration:`,e)}}function be(){P.value&&P.value.close();let e=ee(),t=e?`?token=${encodeURIComponent(e)}`:``;P.value=new EventSource(`/api/cad-calibration-stream${t}`),P.value.onmessage=function(e){try{xe(JSON.parse(e.data))}catch(e){console.error(`Failed to parse SSE data:`,e)}},P.value.onerror=function(e){console.error(`SSE connection error:`,e),M.value||(P.value&&=(P.value.close(),null))}}function xe(e){switch(e.type){case`status`:z.value=e.message||`Status update`,e.test_ranges&&(K.value=e.test_ranges,q.value=!0);break;case`progress`:B.value=e.current||0,V.value=e.total||0,H.value=e.current||0;break;case`result`:if(e.det_peak!==void 0&&e.det_min!==void 0&&e.detection_rate!==void 0&&e.detections!==void 0&&e.samples!==void 0){let t=`${e.det_peak}_${e.det_min}`;F.value[t]={det_peak:e.det_peak,det_min:e.det_min,detection_rate:e.detection_rate,detections:e.detections,samples:e.samples},ve(),Se()}break;case`complete`:case`completed`:M.value=!1,z.value=e.message||`Calibration completed`,s.setCadCalibrationRunning(!1),Ce(),P.value&&=(P.value.close(),null),Z&&=(clearInterval(Z),null);break;case`error`:z.value=`Error: ${e.message}`,s.setCadCalibrationRunning(!1),Q();break}}function Se(){let e=Object.values(F.value).map(e=>e.detection_rate);e.length!==0&&(U.value=Math.max(...e),W.value=e.reduce((e,t)=>e+t,0)/e.length)}function Ce(){J.value=!0;let e=null,t=0;for(let n of Object.values(F.value))n.detection_rate>t&&(t=n.detection_rate,e=n);I.value=e,e&&t>0?(Y.value=!0,X.value=!1):(Y.value=!1,X.value=!0)}let $=a(!1);async function we(){if(!I.value){z.value=`Error: No calibration results to save`;return}try{let e=await g.post(`/save_cad_settings`,{peak:I.value.det_peak,min_val:I.value.det_min,detection_rate:I.value.detection_rate});if(e.success)$.value=!0;else throw Error(e.error||`Failed to save settings`)}catch(e){z.value=`Error: Failed to save settings: ${e instanceof Error?e.message:`Unknown error`}`}}return r(()=>{_e()}),n(()=>{P.value&&P.value.close(),Z&&clearInterval(Z),s.setCadCalibrationRunning(!1),document.getElementById(`plotly-chart`)&&y.default.purge(`plotly-chart`)}),(e,n)=>(c(),h(p,null,[m(`div`,re,[n[13]||=m(`div`,null,[m(`h1`,{class:`text-2xl font-bold text-content-primary dark:text-content-primary`},` CAD Calibration Tool `),m(`p`,{class:`text-content-secondary dark:text-content-muted mt-2`},` Channel Activity Detection calibration `)],-1),m(`div`,b,[m(`div`,x,[m(`div`,S,[m(`button`,{onClick:ye,disabled:M.value,class:`flex items-center gap-3 px-6 py-3 bg-accent-green/10 hover:bg-accent-green/20 disabled:bg-gray-500/10 text-accent-green disabled:text-gray-400 rounded-lg border border-accent-green/30 disabled:border-gray-500/20 transition-colors disabled:cursor-not-allowed`},[...n[1]||=[o(`<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24" data-v-950ea1f9><polygon points="5 3 19 12 5 21 5 3" data-v-950ea1f9></polygon></svg><div class="text-left" data-v-950ea1f9><div class="font-medium" data-v-950ea1f9>Start Calibration</div><div class="text-xs opacity-80" data-v-950ea1f9>Begin testing</div></div>`,2)]],8,ie),m(`button`,{onClick:Q,disabled:!M.value,class:`flex items-center gap-3 px-6 py-3 bg-accent-red/10 hover:bg-accent-red/20 disabled:bg-gray-500/10 text-accent-red disabled:text-gray-400 rounded-lg border border-accent-red/30 disabled:border-gray-500/20 transition-colors disabled:cursor-not-allowed`},[...n[2]||=[o(`<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24" data-v-950ea1f9><rect x="6" y="6" width="12" height="12" data-v-950ea1f9></rect></svg><div class="text-left" data-v-950ea1f9><div class="font-medium" data-v-950ea1f9>Stop</div><div class="text-xs opacity-80" data-v-950ea1f9>Halt calibration</div></div>`,2)]],8,ae)])])]),m(`div`,oe,[m(`div`,se,t(z.value),1),m(`div`,ce,[!J.value&&q.value&&K.value?(c(),h(`div`,le,[n[3]||=m(`strong`,null,`Configuration:`,-1),f(` SF`+t(K.value.spreading_factor)+` | Peak: `+t(K.value.peak_min)+`–`+t(K.value.peak_max)+` | Min: `+t(K.value.min_min)+`–`+t(K.value.min_max)+` | `+t((K.value.peak_max-K.value.peak_min+1)*(K.value.min_max-K.value.min_min+1))+` tests `,1)])):J.value?Y.value&&I.value?(c(),h(`div`,de,[n[4]||=m(`span`,{class:`text-accent-green font-medium`},`Optimal settings found — `,-1),n[5]||=f(` Peak: `,-1),m(`strong`,null,t(I.value.det_peak),1),n[6]||=f(`, Min: `,-1),m(`strong`,null,t(I.value.det_min),1),n[7]||=f(`, Rate: `,-1),m(`strong`,null,t(I.value.detection_rate.toFixed(1))+`%`,1)])):X.value?(c(),h(`div`,fe,` No optimal settings found. Consider running calibration again. `)):l(``,!0):(c(),h(`div`,ue,` Awaiting calibration… `)),Y.value&&I.value?(c(),h(`button`,{key:4,onClick:we,class:`btn-primary flex-shrink-0 flex items-center gap-2`},[...n[8]||=[m(`svg`,{class:`w-4 h-4`,fill:`none`,stroke:`currentColor`,viewBox:`0 0 24 24`},[m(`path`,{d:`M19 21l-7-5-7 5V5a2 2 0 0 1 2-2h10a2 2 0 0 1 2 2z`})],-1),f(` Save Settings `,-1)]])):l(``,!0)]),m(`div`,pe,[m(`div`,me,[m(`div`,{class:`bg-gradient-to-r from-primary to-accent-green h-2 rounded-full transition-all duration-300`,style:i({width:V.value>0?`${B.value/V.value*100}%`:`0%`})},null,4)]),m(`div`,he,t(B.value)+` / `+t(V.value)+` tests completed `,1)])]),m(`div`,C,[m(`div`,w,[m(`div`,T,t(H.value),1),n[9]||=m(`div`,{class:`text-content-secondary dark:text-content-muted text-sm`},`Tests Completed`,-1)]),m(`div`,E,[m(`div`,D,t(U.value.toFixed(1))+`%`,1),n[10]||=m(`div`,{class:`text-content-secondary dark:text-content-muted text-sm`},` Best Detection Rate `,-1)]),m(`div`,O,[m(`div`,k,t(W.value.toFixed(1))+`%`,1),n[11]||=m(`div`,{class:`text-content-secondary dark:text-content-muted text-sm`},`Average Rate`,-1)]),m(`div`,A,[m(`div`,j,t(G.value)+`s`,1),n[12]||=m(`div`,{class:`text-content-secondary dark:text-content-muted text-sm`},`Elapsed Time`,-1)])]),n[14]||=m(`div`,{class:`glass-card rounded-[15px] p-6`},[m(`div`,{id:`plotly-chart`,class:`w-full h-96`})],-1)]),u(ne,{modelValue:$.value,"onUpdate:modelValue":n[0]||=e=>$.value=e,title:`CAD Calibration Saved: Restart Required`,message:`In order for the CAD Calibration settings to take effect and the noise floor to return to normal, the service needs to be restarted.`},null,8,[`modelValue`])],64))}}),[[`__scopeId`,`data-v-950ea1f9`]]);export{M as default}; |