@polderlabs/bizar 10.4.2 → 10.4.4
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/bizar-dash/dist/assets/{ActivityFeed-DtRtg-JN.js → ActivityFeed-RQeyFifx.js} +1 -1
- package/bizar-dash/dist/assets/{ActivityFeed-DtRtg-JN.js.map → ActivityFeed-RQeyFifx.js.map} +1 -1
- package/bizar-dash/dist/assets/{ActivityView-CoTXDyU_.js → ActivityView-CibyssPM.js} +1 -1
- package/bizar-dash/dist/assets/{ActivityView-CoTXDyU_.js.map → ActivityView-CibyssPM.js.map} +1 -1
- package/bizar-dash/dist/assets/AdminView-BjczABeB.js +11 -0
- package/bizar-dash/dist/assets/AdminView-BjczABeB.js.map +1 -0
- package/bizar-dash/dist/assets/{AgentActivity-CrX7LmQ6.js → AgentActivity-Bywt1twv.js} +1 -1
- package/bizar-dash/dist/assets/{AgentActivity-CrX7LmQ6.js.map → AgentActivity-Bywt1twv.js.map} +1 -1
- package/bizar-dash/dist/assets/AgentsView-BnOjjM74.js +15 -0
- package/bizar-dash/dist/assets/AgentsView-BnOjjM74.js.map +1 -0
- package/bizar-dash/dist/assets/{Alert-B6DjfRFI.js → Alert-BZGk39mB.js} +1 -1
- package/bizar-dash/dist/assets/{Alert-B6DjfRFI.js.map → Alert-BZGk39mB.js.map} +1 -1
- package/bizar-dash/dist/assets/{ArtifactsView-znhN8GTR.js → ArtifactsView-CfYB1le1.js} +3 -3
- package/bizar-dash/dist/assets/ArtifactsView-CfYB1le1.js.map +1 -0
- package/bizar-dash/dist/assets/{AuthView-Rk8eKUPr.js → AuthView-D4frSShw.js} +1 -1
- package/bizar-dash/dist/assets/{AuthView-Rk8eKUPr.js.map → AuthView-D4frSShw.js.map} +1 -1
- package/bizar-dash/dist/assets/Avatar-BYg0rkPA.js +6 -0
- package/bizar-dash/dist/assets/Avatar-BYg0rkPA.js.map +1 -0
- package/bizar-dash/dist/assets/{BackgroundJobsView-BLWuN9qz.js → BackgroundJobsView-DEStvILz.js} +1 -1
- package/bizar-dash/dist/assets/{BackgroundJobsView-BLWuN9qz.js.map → BackgroundJobsView-DEStvILz.js.map} +1 -1
- package/bizar-dash/dist/assets/{BackupView-CqbtcnuQ.js → BackupView-B875KQa4.js} +1 -1
- package/bizar-dash/dist/assets/{BackupView-CqbtcnuQ.js.map → BackupView-B875KQa4.js.map} +1 -1
- package/bizar-dash/dist/assets/Banner-C8HEcT5l.js +1 -0
- package/bizar-dash/dist/assets/Banner-C8HEcT5l.js.map +1 -0
- package/bizar-dash/dist/assets/{Card-rF59wHiO.js → Card-BtsmkhJa.js} +1 -1
- package/bizar-dash/dist/assets/{Card-rF59wHiO.js.map → Card-BtsmkhJa.js.map} +1 -1
- package/bizar-dash/dist/assets/ChatView-CkNS0SD8.js +9 -0
- package/bizar-dash/dist/assets/ChatView-CkNS0SD8.js.map +1 -0
- package/bizar-dash/dist/assets/{Chip-Dc2KmeWl.js → Chip-XPOk0d_E.js} +1 -1
- package/bizar-dash/dist/assets/{Chip-Dc2KmeWl.js.map → Chip-XPOk0d_E.js.map} +1 -1
- package/bizar-dash/dist/assets/{ClaudeSessionsView-CiaHQdDZ.js → ClaudeSessionsView-BprGo67K.js} +1 -1
- package/bizar-dash/dist/assets/{ClaudeSessionsView-CiaHQdDZ.js.map → ClaudeSessionsView-BprGo67K.js.map} +1 -1
- package/bizar-dash/dist/assets/ClipboardView-CPlTU5VG.js +1 -0
- package/bizar-dash/dist/assets/ClipboardView-CPlTU5VG.js.map +1 -0
- package/bizar-dash/dist/assets/{ConfigView-B2ysnTZU.js → ConfigView-BntUrW7s.js} +1 -1
- package/bizar-dash/dist/assets/{ConfigView-B2ysnTZU.js.map → ConfigView-BntUrW7s.js.map} +1 -1
- package/bizar-dash/dist/assets/DiagnosticsView-4x0Zu3yP.js +2 -0
- package/bizar-dash/dist/assets/DiagnosticsView-4x0Zu3yP.js.map +1 -0
- package/bizar-dash/dist/assets/DialogsView-Xd02dVAX.js +6 -0
- package/bizar-dash/dist/assets/DialogsView-Xd02dVAX.js.map +1 -0
- package/bizar-dash/dist/assets/{DoctorView-BQwqvMAh.js → DoctorView-DepBdQGR.js} +2 -2
- package/bizar-dash/dist/assets/{DoctorView-BQwqvMAh.js.map → DoctorView-DepBdQGR.js.map} +1 -1
- package/bizar-dash/dist/assets/{EmptyState-D65J5FQN.js → EmptyState-DjKtY1Qi.js} +1 -1
- package/bizar-dash/dist/assets/{EmptyState-D65J5FQN.js.map → EmptyState-DjKtY1Qi.js.map} +1 -1
- package/bizar-dash/dist/assets/{EnvVarsView-DX-3oGH-.js → EnvVarsView-S4Pbm128.js} +3 -3
- package/bizar-dash/dist/assets/{EnvVarsView-DX-3oGH-.js.map → EnvVarsView-S4Pbm128.js.map} +1 -1
- package/bizar-dash/dist/assets/{ErrorState-DULZnttJ.js → ErrorState-CBJbEQ8B.js} +1 -1
- package/bizar-dash/dist/assets/{ErrorState-DULZnttJ.js.map → ErrorState-CBJbEQ8B.js.map} +1 -1
- package/bizar-dash/dist/assets/EvalView-BeAyMCD1.js +1 -0
- package/bizar-dash/dist/assets/{EvalView-CpdFu_ID.js.map → EvalView-BeAyMCD1.js.map} +1 -1
- package/bizar-dash/dist/assets/{GoalsView-Br8oPPfb.js → GoalsView-BZr8In4c.js} +1 -1
- package/bizar-dash/dist/assets/{GoalsView-Br8oPPfb.js.map → GoalsView-BZr8In4c.js.map} +1 -1
- package/bizar-dash/dist/assets/{Grid-BSXhsCPC.js → Grid--WKvqu5h.js} +1 -1
- package/bizar-dash/dist/assets/{Grid-BSXhsCPC.js.map → Grid--WKvqu5h.js.map} +1 -1
- package/bizar-dash/dist/assets/{HistoryView-D0J3aoZF.js → HistoryView-djEbzqtk.js} +1 -1
- package/bizar-dash/dist/assets/{HistoryView-D0J3aoZF.js.map → HistoryView-djEbzqtk.js.map} +1 -1
- package/bizar-dash/dist/assets/{Input-CZmRw5QX.js → Input-h_nSOtwm.js} +1 -1
- package/bizar-dash/dist/assets/{Input-CZmRw5QX.js.map → Input-h_nSOtwm.js.map} +1 -1
- package/bizar-dash/dist/assets/LibrariesView-Vez8CvNq.js +6 -0
- package/bizar-dash/dist/assets/{LibrariesView-B1YX9wzp.js.map → LibrariesView-Vez8CvNq.js.map} +1 -1
- package/bizar-dash/dist/assets/{LightRAGView-CykR0t9y.js → LightRAGView-DvqzQoBp.js} +1 -1
- package/bizar-dash/dist/assets/{LightRAGView-CykR0t9y.js.map → LightRAGView-DvqzQoBp.js.map} +1 -1
- package/bizar-dash/dist/assets/{ListHeader-Dpun-r36.js → ListHeader-CM8QoIWG.js} +1 -1
- package/bizar-dash/dist/assets/{ListHeader-Dpun-r36.js.map → ListHeader-CM8QoIWG.js.map} +1 -1
- package/bizar-dash/dist/assets/{MemoryView-BbER5ZKt.js → MemoryView-DnL8E2vI.js} +1 -1
- package/bizar-dash/dist/assets/{MemoryView-BbER5ZKt.js.map → MemoryView-DnL8E2vI.js.map} +1 -1
- package/bizar-dash/dist/assets/{MessageBubble-5vUAquDx.js → MessageBubble-CrCJ0SYG.js} +1 -1
- package/bizar-dash/dist/assets/{MessageBubble-5vUAquDx.js.map → MessageBubble-CrCJ0SYG.js.map} +1 -1
- package/bizar-dash/dist/assets/MiscView-B2YQXhZ_.js +1 -0
- package/bizar-dash/dist/assets/MiscView-B2YQXhZ_.js.map +1 -0
- package/bizar-dash/dist/assets/{ModsView-P7gDeNHM.js → ModsView-BVM3X5xc.js} +1 -1
- package/bizar-dash/dist/assets/{ModsView-P7gDeNHM.js.map → ModsView-BVM3X5xc.js.map} +1 -1
- package/bizar-dash/dist/assets/NotificationsView-A-Xs8BL1.js +6 -0
- package/bizar-dash/dist/assets/NotificationsView-A-Xs8BL1.js.map +1 -0
- package/bizar-dash/dist/assets/ObsidianView-mI3qW9OP.js +1 -0
- package/bizar-dash/dist/assets/{ObsidianView-Ci80gnwS.js.map → ObsidianView-mI3qW9OP.js.map} +1 -1
- package/bizar-dash/dist/assets/OverviewView-By69Cr5H.js +1 -0
- package/bizar-dash/dist/assets/OverviewView-By69Cr5H.js.map +1 -0
- package/bizar-dash/dist/assets/{ProgressBar-BahmeJhP.js → ProgressBar-BnaBqv-W.js} +1 -1
- package/bizar-dash/dist/assets/{ProgressBar-BahmeJhP.js.map → ProgressBar-BnaBqv-W.js.map} +1 -1
- package/bizar-dash/dist/assets/ProjectsView-C81WTFka.js +11 -0
- package/bizar-dash/dist/assets/ProjectsView-C81WTFka.js.map +1 -0
- package/bizar-dash/dist/assets/{ProvidersView-BftGn8Cr.js → ProvidersView-2cn-TALE.js} +2 -2
- package/bizar-dash/dist/assets/{ProvidersView-BftGn8Cr.js.map → ProvidersView-2cn-TALE.js.map} +1 -1
- package/bizar-dash/dist/assets/{SchedulesView-CtNxtzN6.js → SchedulesView-o9AtIsH9.js} +1 -1
- package/bizar-dash/dist/assets/{SchedulesView-CtNxtzN6.js.map → SchedulesView-o9AtIsH9.js.map} +1 -1
- package/bizar-dash/dist/assets/{Select-0VcfTDeL.js → Select-CiGWEN8I.js} +1 -1
- package/bizar-dash/dist/assets/{Select-0VcfTDeL.js.map → Select-CiGWEN8I.js.map} +1 -1
- package/bizar-dash/dist/assets/{SettingsRow-BLic3DQl.js → SettingsRow-CflGJymA.js} +1 -1
- package/bizar-dash/dist/assets/{SettingsRow-BLic3DQl.js.map → SettingsRow-CflGJymA.js.map} +1 -1
- package/bizar-dash/dist/assets/{SettingsView-BjS3i4nr.js → SettingsView-2HSFJPPK.js} +1 -1
- package/bizar-dash/dist/assets/{SettingsView-BjS3i4nr.js.map → SettingsView-2HSFJPPK.js.map} +1 -1
- package/bizar-dash/dist/assets/{Sheet-BOProMs2.js → Sheet-B-CMP9-_.js} +1 -1
- package/bizar-dash/dist/assets/{Sheet-BOProMs2.js.map → Sheet-B-CMP9-_.js.map} +1 -1
- package/bizar-dash/dist/assets/{Slider-B0eLEEUt.js → Slider-Z4TP_CXY.js} +1 -1
- package/bizar-dash/dist/assets/{Slider-B0eLEEUt.js.map → Slider-Z4TP_CXY.js.map} +1 -1
- package/bizar-dash/dist/assets/{Sparkline-SSrdgyW0.js → Sparkline-cvkv2HbU.js} +1 -1
- package/bizar-dash/dist/assets/{Sparkline-SSrdgyW0.js.map → Sparkline-cvkv2HbU.js.map} +1 -1
- package/bizar-dash/dist/assets/{Switch-B3EQzb_q.js → Switch-jcYo4lmp.js} +1 -1
- package/bizar-dash/dist/assets/{Switch-B3EQzb_q.js.map → Switch-jcYo4lmp.js.map} +1 -1
- package/bizar-dash/dist/assets/{TasksView-SWjF_ZUQ.js → TasksView-CQaSFzWY.js} +2 -2
- package/bizar-dash/dist/assets/{TasksView-SWjF_ZUQ.js.map → TasksView-CQaSFzWY.js.map} +1 -1
- package/bizar-dash/dist/assets/{Textarea-QuofpMlq.js → Textarea-xnAybFGd.js} +1 -1
- package/bizar-dash/dist/assets/{Textarea-QuofpMlq.js.map → Textarea-xnAybFGd.js.map} +1 -1
- package/bizar-dash/dist/assets/UpdateView-BUAEcRCX.js +1 -0
- package/bizar-dash/dist/assets/UpdateView-BUAEcRCX.js.map +1 -0
- package/bizar-dash/dist/assets/{UsageView-BqOw6FBg.js → UsageView-DMFbBOfH.js} +1 -1
- package/bizar-dash/dist/assets/{UsageView-BqOw6FBg.js.map → UsageView-DMFbBOfH.js.map} +1 -1
- package/bizar-dash/dist/assets/{ViewHeader-B6P-C4GD.js → ViewHeader-C-t1U2cQ.js} +1 -1
- package/bizar-dash/dist/assets/{ViewHeader-B6P-C4GD.js.map → ViewHeader-C-t1U2cQ.js.map} +1 -1
- package/bizar-dash/dist/assets/VoiceView-aoPVT6LJ.js +1 -0
- package/bizar-dash/dist/assets/VoiceView-aoPVT6LJ.js.map +1 -0
- package/bizar-dash/dist/assets/{brain-CwZt9Kta.js → brain-DhAzcHUk.js} +1 -1
- package/bizar-dash/dist/assets/{brain-CwZt9Kta.js.map → brain-DhAzcHUk.js.map} +1 -1
- package/bizar-dash/dist/assets/{calendar-C5oK0_nM.js → calendar-B9Wbemh7.js} +1 -1
- package/bizar-dash/dist/assets/{calendar-C5oK0_nM.js.map → calendar-B9Wbemh7.js.map} +1 -1
- package/bizar-dash/dist/assets/{circle-D1Lc_P2a.js → circle-6NJF_Xl6.js} +1 -1
- package/bizar-dash/dist/assets/{circle-D1Lc_P2a.js.map → circle-6NJF_Xl6.js.map} +1 -1
- package/bizar-dash/dist/assets/{circle-alert-HdHe7m8K.js → circle-alert-Dz8lGfCZ.js} +1 -1
- package/bizar-dash/dist/assets/{circle-alert-HdHe7m8K.js.map → circle-alert-Dz8lGfCZ.js.map} +1 -1
- package/bizar-dash/dist/assets/{circle-check-Cs-xoV7R.js → circle-check-DFB50ojt.js} +1 -1
- package/bizar-dash/dist/assets/{circle-check-Cs-xoV7R.js.map → circle-check-DFB50ojt.js.map} +1 -1
- package/bizar-dash/dist/assets/{clock-DEIuPV60.js → clock-ClVA6-hQ.js} +1 -1
- package/bizar-dash/dist/assets/{clock-DEIuPV60.js.map → clock-ClVA6-hQ.js.map} +1 -1
- package/bizar-dash/dist/assets/{cmdk-DVxytz9i.js → cmdk-C3F6LD6N.js} +5 -5
- package/bizar-dash/dist/assets/{cmdk-DVxytz9i.js.map → cmdk-C3F6LD6N.js.map} +1 -1
- package/bizar-dash/dist/assets/{dnd-kit-DrHErSkw.js → dnd-kit-BAOLODOI.js} +1 -1
- package/bizar-dash/dist/assets/{dnd-kit-DrHErSkw.js.map → dnd-kit-BAOLODOI.js.map} +1 -1
- package/bizar-dash/dist/assets/{download-Clkq90Ct.js → download-BvJddD8D.js} +1 -1
- package/bizar-dash/dist/assets/{download-Clkq90Ct.js.map → download-BvJddD8D.js.map} +1 -1
- package/bizar-dash/dist/assets/{external-link-D5tq2o_I.js → external-link-DvL89gaZ.js} +1 -1
- package/bizar-dash/dist/assets/{external-link-D5tq2o_I.js.map → external-link-DvL89gaZ.js.map} +1 -1
- package/bizar-dash/dist/assets/{file-text-CQ12t7Oc.js → file-text-BOroDtZE.js} +1 -1
- package/bizar-dash/dist/assets/{file-text-CQ12t7Oc.js.map → file-text-BOroDtZE.js.map} +1 -1
- package/bizar-dash/dist/assets/{filter-BcbE37wP.js → filter-DwPjMRQt.js} +1 -1
- package/bizar-dash/dist/assets/{filter-BcbE37wP.js.map → filter-DwPjMRQt.js.map} +1 -1
- package/bizar-dash/dist/assets/{git-pull-request-D1qNDRia.js → git-pull-request-TDb1inux.js} +1 -1
- package/bizar-dash/dist/assets/{git-pull-request-D1qNDRia.js.map → git-pull-request-TDb1inux.js.map} +1 -1
- package/bizar-dash/dist/assets/{index-CASP1n-5.js → index-B1OIS316.js} +1 -1
- package/bizar-dash/dist/assets/{index-CASP1n-5.js.map → index-B1OIS316.js.map} +1 -1
- package/bizar-dash/dist/assets/{index-C4Vq_2LM.js → index-CR0TeJmc.js} +1 -1
- package/bizar-dash/dist/assets/{index-C4Vq_2LM.js.map → index-CR0TeJmc.js.map} +1 -1
- package/bizar-dash/dist/assets/{main-CcQfRfIJ.css → main-B7D_IMTh.css} +1 -1
- package/bizar-dash/dist/assets/main-BURAlktW.js +277 -0
- package/bizar-dash/dist/assets/main-BURAlktW.js.map +1 -0
- package/bizar-dash/dist/assets/{network-DJdvVaHx.js → network-BcCoCzIY.js} +1 -1
- package/bizar-dash/dist/assets/{network-DJdvVaHx.js.map → network-BcCoCzIY.js.map} +1 -1
- package/bizar-dash/dist/assets/{pause-DUn9L5PB.js → pause-BllItT2_.js} +1 -1
- package/bizar-dash/dist/assets/{pause-DUn9L5PB.js.map → pause-BllItT2_.js.map} +1 -1
- package/bizar-dash/dist/assets/{pencil-DVrBlYV3.js → pencil-DAwM-CC3.js} +1 -1
- package/bizar-dash/dist/assets/{pencil-DVrBlYV3.js.map → pencil-DAwM-CC3.js.map} +1 -1
- package/bizar-dash/dist/assets/{play-CZjsr3XM.js → play-mJh67AXo.js} +2 -2
- package/bizar-dash/dist/assets/{play-CZjsr3XM.js.map → play-mJh67AXo.js.map} +1 -1
- package/bizar-dash/dist/assets/{plug-BKuyIe5W.js → plug-BjfntCMC.js} +1 -1
- package/bizar-dash/dist/assets/{plug-BKuyIe5W.js.map → plug-BjfntCMC.js.map} +1 -1
- package/bizar-dash/dist/assets/{plus-77h62zZm.js → plus-Cm6-fo14.js} +1 -1
- package/bizar-dash/dist/assets/{plus-77h62zZm.js.map → plus-Cm6-fo14.js.map} +1 -1
- package/bizar-dash/dist/assets/{power-DLmx-gCP.js → power-CXN9y2KV.js} +1 -1
- package/bizar-dash/dist/assets/{power-DLmx-gCP.js.map → power-CXN9y2KV.js.map} +1 -1
- package/bizar-dash/dist/assets/{power-off-BFKzHXic.js → power-off-DUZqwMf9.js} +1 -1
- package/bizar-dash/dist/assets/{power-off-BFKzHXic.js.map → power-off-DUZqwMf9.js.map} +1 -1
- package/bizar-dash/dist/assets/{refresh-ccw-DenGBOcq.js → refresh-ccw-DA8_IB9l.js} +1 -1
- package/bizar-dash/dist/assets/{refresh-ccw-DenGBOcq.js.map → refresh-ccw-DA8_IB9l.js.map} +1 -1
- package/bizar-dash/dist/assets/{refresh-cw-ENBVR8hW.js → refresh-cw-DwlP59en.js} +1 -1
- package/bizar-dash/dist/assets/{refresh-cw-ENBVR8hW.js.map → refresh-cw-DwlP59en.js.map} +1 -1
- package/bizar-dash/dist/assets/{rotate-ccw-MxryaY7q.js → rotate-ccw-DMTASfAn.js} +1 -1
- package/bizar-dash/dist/assets/{rotate-ccw-MxryaY7q.js.map → rotate-ccw-DMTASfAn.js.map} +1 -1
- package/bizar-dash/dist/assets/{rotate-cw-CDOlRtUR.js → rotate-cw-BDX5SE2s.js} +1 -1
- package/bizar-dash/dist/assets/{rotate-cw-CDOlRtUR.js.map → rotate-cw-BDX5SE2s.js.map} +1 -1
- package/bizar-dash/dist/assets/{save-Db1b-1Uq.js → save-Y0jPK5D6.js} +1 -1
- package/bizar-dash/dist/assets/{save-Db1b-1Uq.js.map → save-Y0jPK5D6.js.map} +1 -1
- package/bizar-dash/dist/assets/{send-yz6HFZM5.js → send-C8wwPHhR.js} +2 -2
- package/bizar-dash/dist/assets/{send-yz6HFZM5.js.map → send-C8wwPHhR.js.map} +1 -1
- package/bizar-dash/dist/assets/{shield-alert-DY6RAaC8.js → shield-alert-DEvq9UG0.js} +1 -1
- package/bizar-dash/dist/assets/{shield-alert-DY6RAaC8.js.map → shield-alert-DEvq9UG0.js.map} +1 -1
- package/bizar-dash/dist/assets/{trash-2-Cv7U38jw.js → trash-2-D6qePV_q.js} +2 -2
- package/bizar-dash/dist/assets/{trash-2-Cv7U38jw.js.map → trash-2-D6qePV_q.js.map} +1 -1
- package/bizar-dash/dist/assets/{trending-up-CRPNagyX.js → trending-up-BZzo_1ic.js} +1 -1
- package/bizar-dash/dist/assets/{trending-up-CRPNagyX.js.map → trending-up-BZzo_1ic.js.map} +1 -1
- package/bizar-dash/dist/assets/{triangle-alert-tUTXbcEP.js → triangle-alert-B2oHbmoh.js} +1 -1
- package/bizar-dash/dist/assets/{triangle-alert-tUTXbcEP.js.map → triangle-alert-B2oHbmoh.js.map} +1 -1
- package/bizar-dash/dist/assets/{upload-Cq7uTsrT.js → upload-Dy59aZn6.js} +1 -1
- package/bizar-dash/dist/assets/{upload-Cq7uTsrT.js.map → upload-Dy59aZn6.js.map} +1 -1
- package/bizar-dash/dist/assets/{zap-5lAQBAPX.js → zap-DENVhJnO.js} +2 -2
- package/bizar-dash/dist/assets/{zap-5lAQBAPX.js.map → zap-DENVhJnO.js.map} +1 -1
- package/bizar-dash/dist/index.html +3 -3
- package/bizar-dash/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json +1 -1
- package/bizar-dash/src/web/v8/App.tsx +87 -6
- package/bizar-dash/src/web/v8/__tests__/chat-view.test.tsx +4 -4
- package/bizar-dash/src/web/v8/shell/AppShell.tsx +38 -2
- package/bizar-dash/src/web/v8/shell/Sidebar.tsx +52 -38
- package/bizar-dash/src/web/v8/shell/Topbar.tsx +62 -3
- package/bizar-dash/src/web/v8/ui/styles/globals.css +40 -0
- package/bizar-dash/src/web/v8/ui/theme/ThemeToggle.tsx +11 -6
- package/bizar-dash/src/web/v8/views/Admin/AdminView.tsx +32 -5
- package/bizar-dash/src/web/v8/views/Agents/AgentsView.tsx +36 -4
- package/bizar-dash/src/web/v8/views/Artifacts/ArtifactsView.tsx +1 -1
- package/bizar-dash/src/web/v8/views/Chat/ChatView.tsx +13 -1
- package/bizar-dash/src/web/v8/views/ClaudeSessions/NewSessionModal.tsx +136 -0
- package/bizar-dash/src/web/v8/views/Clipboard/ClipboardView.tsx +1 -1
- package/bizar-dash/src/web/v8/views/CommandPalette/AppCommandPalette.tsx +14 -4
- package/bizar-dash/src/web/v8/views/Diagnostics/DiagnosticsView.tsx +50 -7
- package/bizar-dash/src/web/v8/views/Dialogs/DialogsView.tsx +1 -1
- package/bizar-dash/src/web/v8/views/Libraries/LibrariesView.tsx +6 -1
- package/bizar-dash/src/web/v8/views/Misc/MiscView.tsx +1 -1
- package/bizar-dash/src/web/v8/views/Notifications/NotificationsView.tsx +82 -13
- package/bizar-dash/src/web/v8/views/Overview/OverviewView.tsx +19 -0
- package/bizar-dash/src/web/v8/views/Projects/ProjectsView.tsx +21 -1
- package/bizar-dash/src/web/v8/views/Voice/VoiceView.tsx +1 -1
- package/bizar-dash/tests/admin-labels.test.mjs +42 -0
- package/bizar-dash/tests/admin-run-grouping.test.mjs +42 -0
- package/bizar-dash/tests/agents-preview-truncate.test.mjs +35 -0
- package/bizar-dash/tests/agents-summary-sanitize.test.ts +51 -0
- package/bizar-dash/tests/chat-new-session.test.mjs +63 -0
- package/bizar-dash/tests/empty-state-docs.test.mjs +55 -0
- package/bizar-dash/tests/focus-visible.test.mjs +30 -0
- package/bizar-dash/tests/kanban-empty-column.test.mjs +56 -0
- package/bizar-dash/tests/library-dedupe.test.mjs +62 -0
- package/bizar-dash/tests/notifications-dismiss-restore.test.mjs +85 -0
- package/bizar-dash/tests/palette-shortcut-hint.test.mjs +58 -0
- package/bizar-dash/tests/projects-filter.test.mjs +48 -0
- package/bizar-dash/tests/settings-labels.test.mjs +80 -0
- package/bizar-dash/tests/sidebar-distinct-icons.test.mjs +28 -0
- package/bizar-dash/tests/sidebar-responsive.test.tsx +48 -0
- package/bizar-dash/tests/sidebar-section-toggle.test.tsx +63 -0
- package/bizar-dash/tests/theme-toggle-icon.test.mjs +28 -0
- package/bizar-dash/tests/topbar-design-system.test.mjs +56 -0
- package/bizar-dash/vite.config.ts +8 -0
- package/package.json +1 -1
- package/packages/sdk/package.json +1 -1
- package/bizar-dash/dist/assets/AdminView-DNc5Ll7L.js +0 -11
- package/bizar-dash/dist/assets/AdminView-DNc5Ll7L.js.map +0 -1
- package/bizar-dash/dist/assets/AgentsView-Du-G_skK.js +0 -13
- package/bizar-dash/dist/assets/AgentsView-Du-G_skK.js.map +0 -1
- package/bizar-dash/dist/assets/ArtifactsView-znhN8GTR.js.map +0 -1
- package/bizar-dash/dist/assets/Avatar-B41upSD1.js +0 -6
- package/bizar-dash/dist/assets/Avatar-B41upSD1.js.map +0 -1
- package/bizar-dash/dist/assets/ChatView-CUriVEgU.js +0 -9
- package/bizar-dash/dist/assets/ChatView-CUriVEgU.js.map +0 -1
- package/bizar-dash/dist/assets/ClipboardView-DdP6aVso.js +0 -1
- package/bizar-dash/dist/assets/ClipboardView-DdP6aVso.js.map +0 -1
- package/bizar-dash/dist/assets/DiagnosticsView-88OZ5k0f.js +0 -2
- package/bizar-dash/dist/assets/DiagnosticsView-88OZ5k0f.js.map +0 -1
- package/bizar-dash/dist/assets/DialogsView-BcqDDCZQ.js +0 -6
- package/bizar-dash/dist/assets/DialogsView-BcqDDCZQ.js.map +0 -1
- package/bizar-dash/dist/assets/EvalView-CpdFu_ID.js +0 -1
- package/bizar-dash/dist/assets/LibrariesView-B1YX9wzp.js +0 -6
- package/bizar-dash/dist/assets/MiscView-DLNEGdML.js +0 -1
- package/bizar-dash/dist/assets/MiscView-DLNEGdML.js.map +0 -1
- package/bizar-dash/dist/assets/NotificationsView-DAm2O0yf.js +0 -6
- package/bizar-dash/dist/assets/NotificationsView-DAm2O0yf.js.map +0 -1
- package/bizar-dash/dist/assets/ObsidianView-Ci80gnwS.js +0 -1
- package/bizar-dash/dist/assets/OverviewView-rriw1GjA.js +0 -1
- package/bizar-dash/dist/assets/OverviewView-rriw1GjA.js.map +0 -1
- package/bizar-dash/dist/assets/ProjectsView-ChzM12bs.js +0 -11
- package/bizar-dash/dist/assets/ProjectsView-ChzM12bs.js.map +0 -1
- package/bizar-dash/dist/assets/UpdateView-CEHW2nd6.js +0 -6
- package/bizar-dash/dist/assets/UpdateView-CEHW2nd6.js.map +0 -1
- package/bizar-dash/dist/assets/VoiceView-CwrPwWgi.js +0 -1
- package/bizar-dash/dist/assets/VoiceView-CwrPwWgi.js.map +0 -1
- package/bizar-dash/dist/assets/main-Cxeu4LhG.js +0 -244
- package/bizar-dash/dist/assets/main-Cxeu4LhG.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ConfigView-B2ysnTZU.js","sources":["../../src/web/v8/views/Config/ConfigView.tsx"],"sourcesContent":["/**\n * v8/views/Config/ConfigView.tsx — Sprint S41, v9.3.0.\n *\n * Three sub-sections:\n * - Runtime config: read-only viewer + Reload + Save (PUT\n * /api/config with the edited raw JSON).\n * - Providers: full CRUD via /api/config/providers + the\n * \"add with key\" auto endpoint.\n * - MCPs: full CRUD via /api/config/mcps.\n * - System LLM: read/write the cline.json#systemLlm block via\n * /api/llm/system-llm.\n *\n * Inline confirm for delete. Sheet form for Add / Edit.\n */\n\nimport { useCallback, useEffect, useMemo, useState } from 'react';\nimport { Plus, Pencil, Trash2, RefreshCcw, Save, ServerCog, Cpu, Plug, Settings as SettingsIcon } from 'lucide-react';\nimport type { LucideIcon } from 'lucide-react';\nimport { Stack } from '../../ui/primitives/Stack.js';\nimport { Inline } from '../../ui/primitives/Inline.js';\nimport { ViewHeader } from '../../ui/data/ViewHeader.js';\nimport { Card, CardBody } from '../../ui/data/Card.js';\nimport { Button } from '../../ui/controls/Button.js';\nimport { Input } from '../../ui/controls/Input.js';\nimport { Sheet, SheetClose, SheetContent } from '../../ui/feedback/Sheet.js';\nimport { Skeleton } from '../../ui/feedback/Skeleton.js';\nimport { EmptyState } from '../../ui/feedback/EmptyState.js';\nimport { useFetch } from '../../data/useFetch.js';\nimport { fetchJson, FetchError } from '../../data/fetcher.js';\n\ninterface Provider {\n id: string;\n name?: string;\n groupId?: string;\n}\n\ninterface Mcp {\n id: string;\n name?: string;\n command?: string;\n}\n\ninterface SystemLlm {\n enabled: boolean;\n provider: string | null;\n model: string | null;\n}\n\ninterface RuntimeConfig {\n path: string;\n data: unknown;\n raw: string;\n exists: boolean;\n}\n\ntype SectionId = 'runtime' | 'providers' | 'mcps' | 'system-llm';\n\nconst SECTIONS: Array<{ id: SectionId; label: string; icon: LucideIcon }> = [\n { id: 'runtime', label: 'Runtime config', icon: SettingsIcon },\n { id: 'providers', label: 'Providers', icon: Cpu },\n { id: 'mcps', label: 'MCPs', icon: Plug },\n { id: 'system-llm', label: 'System LLM', icon: ServerCog },\n];\n\nexport function ConfigView(): JSX.Element {\n const [section, setSection] = useState<SectionId>('runtime');\n return (\n <Stack gap={4} data-testid=\"config-view\">\n <ViewHeader\n title=\"Config\"\n description=\"Runtime config + providers + MCPs + system LLM.\"\n />\n <Inline gap={1} role=\"tablist\">\n {SECTIONS.map((s) => (\n <button\n key={s.id}\n type=\"button\"\n role=\"tab\"\n aria-selected={section === s.id}\n onClick={() => setSection(s.id)}\n data-testid={`config-tab-${s.id}`}\n style={{\n padding: 'var(--space-2) var(--space-3)',\n borderRadius: 'var(--radius-md)',\n border: '1px solid var(--border)',\n background: section === s.id ? 'color-mix(in oklch, var(--accent) 14%, transparent)' : 'var(--surface-0)',\n color: section === s.id ? 'var(--accent)' : 'var(--fg-muted)',\n fontSize: 'var(--fs-12)',\n cursor: 'pointer',\n }}\n >\n <s.icon size={14} aria-hidden style={{ verticalAlign: 'middle', marginRight: 6 }} />\n {s.label}\n </button>\n ))}\n </Inline>\n {section === 'runtime' && <RuntimeConfigPanel />}\n {section === 'providers' && <ProvidersPanel />}\n {section === 'mcps' && <McpsPanel />}\n {section === 'system-llm' && <SystemLlmPanel />}\n </Stack>\n );\n}\n\nfunction RuntimeConfigPanel(): JSX.Element {\n const payload = useFetch<RuntimeConfig>('/api/config');\n const [draft, setDraft] = useState<string>('');\n const [busy, setBusy] = useState<boolean>(false);\n const [saved, setSaved] = useState<boolean>(false);\n const [error, setError] = useState<string | null>(null);\n\n useEffect(() => {\n if (payload.data?.raw !== undefined) setDraft(payload.data.raw);\n }, [payload.data?.raw]);\n\n const reload = useCallback(() => { void payload.refetch(); }, [payload]);\n\n const save = async (): Promise<void> => {\n setBusy(true);\n setError(null);\n setSaved(false);\n try {\n await fetchJson('/api/config', { method: 'PUT', body: draft });\n setSaved(true);\n reload();\n } catch (err) {\n setError(err instanceof FetchError ? err.message : (err as Error).message);\n } finally {\n setBusy(false);\n }\n };\n\n return (\n <Card variant=\"default\">\n <CardBody>\n <Stack gap={2}>\n <Inline align=\"center\" justify=\"between\" gap={2}>\n <strong style={{ fontSize: 'var(--fs-13)' }}>Runtime config</strong>\n <Inline gap={1}>\n <Button variant=\"ghost\" onClick={reload} data-testid=\"config-runtime-reload\">\n <RefreshCcw size={14} aria-hidden /> Reload\n </Button>\n <Button variant=\"primary\" onClick={() => void save()} disabled={busy} data-testid=\"config-runtime-save\">\n <Save size={14} aria-hidden /> {busy ? 'Saving…' : 'Save'}\n </Button>\n </Inline>\n </Inline>\n {payload.loading && payload.data === null ? (\n <Skeleton style={{ height: 240 }} />\n ) : (\n <textarea\n value={draft}\n rows={16}\n data-testid=\"config-runtime-raw\"\n onChange={(e) => setDraft((e.target as HTMLTextAreaElement).value)}\n style={{\n background: 'var(--surface-0)',\n border: '1px solid var(--border)',\n borderRadius: 'var(--radius-md)',\n padding: 'var(--space-2)',\n color: 'var(--fg)',\n fontFamily: 'var(--font-mono)',\n fontSize: 'var(--fs-12)',\n resize: 'vertical',\n }}\n />\n )}\n {saved && <span data-testid=\"config-runtime-saved\" style={{ color: 'var(--success)', fontSize: 'var(--fs-12)' }}>Saved</span>}\n {error !== null && (\n <span role=\"alert\" data-testid=\"config-runtime-error\" style={{ color: 'var(--danger)', fontSize: 'var(--fs-12)' }}>{error}</span>\n )}\n </Stack>\n </CardBody>\n </Card>\n );\n}\n\nfunction ProvidersPanel(): JSX.Element {\n const payload = useFetch<{ providers: Provider[] }>('/api/config/providers');\n const [adding, setAdding] = useState<boolean>(false);\n const [editing, setEditing] = useState<string | null>(null);\n const [confirmDelete, setConfirmDelete] = useState<string | null>(null);\n const [error, setError] = useState<string | null>(null);\n const refresh = useCallback(() => { void payload.refetch(); }, [payload]);\n const providers = useMemo(() => payload.data?.providers ?? [], [payload.data]);\n\n const drop = async (id: string): Promise<void> => {\n setError(null);\n try {\n await fetchJson(`/api/config/providers/${id}`, { method: 'DELETE' });\n setConfirmDelete(null);\n refresh();\n } catch (err) {\n setError(err instanceof FetchError ? err.message : (err as Error).message);\n }\n };\n\n return (\n <Card variant=\"default\">\n <CardBody>\n <Stack gap={2}>\n <Inline align=\"center\" justify=\"between\" gap={2}>\n <strong style={{ fontSize: 'var(--fs-13)' }}>Providers</strong>\n <Inline gap={1}>\n {error !== null && (\n <span role=\"alert\" style={{ color: 'var(--danger)', fontSize: 'var(--fs-12)' }}>{error}</span>\n )}\n <Button variant=\"primary\" onClick={() => setAdding(true)} data-testid=\"config-providers-add\">\n <Plus size={14} aria-hidden /> Add\n </Button>\n </Inline>\n </Inline>\n {payload.loading && providers.length === 0 ? (\n <Skeleton style={{ height: 100 }} />\n ) : providers.length === 0 ? (\n <EmptyState icon={<Cpu size={28} aria-hidden />} title=\"No providers\" description=\"Add one or use Auto-add with key.\" />\n ) : (\n <Stack gap={1}>\n {providers.map((p) => {\n const isConfirming = confirmDelete === p.id;\n return (\n <div key={p.id} data-testid={`config-provider-row-${p.id}`} style={{ padding: 'var(--space-2)', border: '1px solid var(--border)', borderRadius: 'var(--radius-sm)' }}>\n <Inline align=\"center\" justify=\"between\" gap={2}>\n <Inline align=\"center\" gap={2}>\n <strong>{p.name || p.id}</strong>\n {p.groupId && <span style={{ fontSize: 'var(--fs-12)', color: 'var(--fg-muted)' }}>group={p.groupId}</span>}\n </Inline>\n <Inline gap={1}>\n <Button variant=\"ghost\" onClick={() => setEditing(p.id)} data-testid={`config-provider-edit-${p.id}`} aria-label={`Edit ${p.id}`}>\n <Pencil size={14} aria-hidden />\n </Button>\n <Button variant=\"ghost\" onClick={() => setConfirmDelete((cur) => (cur === p.id ? null : p.id))} data-testid={`config-provider-delete-${p.id}`} aria-label={`Delete ${p.id}`}>\n <Trash2 size={14} aria-hidden />\n </Button>\n </Inline>\n </Inline>\n {isConfirming && (\n <Inline gap={1} style={{ marginTop: 'var(--space-1)' }}>\n <Button variant=\"danger\" onClick={() => void drop(p.id)} data-testid={`config-provider-confirm-delete-${p.id}`}>Confirm delete</Button>\n <Button variant=\"ghost\" onClick={() => setConfirmDelete(null)}>Cancel</Button>\n </Inline>\n )}\n </div>\n );\n })}\n </Stack>\n )}\n </Stack>\n </CardBody>\n </Card>\n );\n}\n\nfunction McpsPanel(): JSX.Element {\n const payload = useFetch<{ mcps: Mcp[] }>('/api/config/mcps');\n const mcps = useMemo(() => payload.data?.mcps ?? [], [payload.data]);\n const refresh = useCallback(() => { void payload.refetch(); }, [payload]);\n return (\n <Card variant=\"default\">\n <CardBody>\n <Stack gap={2}>\n <Inline align=\"center\" justify=\"between\" gap={2}>\n <strong style={{ fontSize: 'var(--fs-13)' }}>MCP servers</strong>\n </Inline>\n {payload.loading && mcps.length === 0 ? (\n <Skeleton style={{ height: 60 }} />\n ) : mcps.length === 0 ? (\n <EmptyState icon={<Plug size={28} aria-hidden />} title=\"No MCPs\" description=\"Add one via /api/config/mcps.\" />\n ) : (\n <Stack gap={1}>\n {mcps.map((m) => (\n <div key={m.id} data-testid={`config-mcp-row-${m.id}`} style={{ padding: 'var(--space-2)', border: '1px solid var(--border)', borderRadius: 'var(--radius-sm)', display: 'flex', justifyContent: 'space-between' }}>\n <strong>{m.name || m.id}</strong>\n {m.command && <code style={{ fontSize: 'var(--fs-12)', color: 'var(--fg-muted)' }}>{m.command}</code>}\n </div>\n ))}\n </Stack>\n )}\n <Button variant=\"ghost\" onClick={refresh} data-testid=\"config-mcps-refresh\">\n <RefreshCcw size={14} aria-hidden /> Refresh\n </Button>\n </Stack>\n </CardBody>\n </Card>\n );\n}\n\nfunction SystemLlmPanel(): JSX.Element {\n const payload = useFetch<SystemLlm>('/api/llm/system-llm');\n const [enabled, setEnabled] = useState<boolean>(false);\n const [provider, setProvider] = useState<string>('');\n const [model, setModel] = useState<string>('');\n const [busy, setBusy] = useState<boolean>(false);\n const [saved, setSaved] = useState<boolean>(false);\n const [error, setError] = useState<string | null>(null);\n\n useEffect(() => {\n if (payload.data) {\n setEnabled(payload.data.enabled);\n setProvider(payload.data.provider ?? '');\n setModel(payload.data.model ?? '');\n }\n }, [payload.data]);\n\n const save = async (): Promise<void> => {\n setBusy(true);\n setError(null);\n setSaved(false);\n try {\n await fetchJson('/api/llm/system-llm', {\n method: 'PUT',\n body: { enabled, provider, model },\n });\n setSaved(true);\n void payload.refetch();\n } catch (err) {\n setError(err instanceof FetchError ? err.message : (err as Error).message);\n } finally {\n setBusy(false);\n }\n };\n\n return (\n <Card variant=\"default\">\n <CardBody>\n <Stack gap={2}>\n <strong style={{ fontSize: 'var(--fs-13)' }}>System LLM</strong>\n {payload.loading && payload.data === null ? (\n <Skeleton style={{ height: 100 }} />\n ) : (\n <Stack gap={2}>\n <label style={{ display: 'flex', alignItems: 'center', gap: 'var(--space-2)' }}>\n <input\n type=\"checkbox\"\n checked={enabled}\n data-testid=\"config-system-llm-enabled\"\n onChange={(e) => setEnabled((e.target as HTMLInputElement).checked)}\n />\n <span style={{ fontSize: 'var(--fs-13)' }}>Enabled</span>\n </label>\n <label style={{ display: 'flex', flexDirection: 'column', gap: 'var(--space-1)' }}>\n <span style={{ fontSize: 'var(--fs-12)', color: 'var(--fg-muted)' }}>Provider</span>\n <Input value={provider} data-testid=\"config-system-llm-provider\" onChange={(e) => setProvider((e.target as HTMLInputElement).value)} />\n </label>\n <label style={{ display: 'flex', flexDirection: 'column', gap: 'var(--space-1)' }}>\n <span style={{ fontSize: 'var(--fs-12)', color: 'var(--fg-muted)' }}>Model</span>\n <Input value={model} data-testid=\"config-system-llm-model\" onChange={(e) => setModel((e.target as HTMLInputElement).value)} />\n </label>\n <Inline justify=\"end\" gap={2}>\n <Button variant=\"primary\" onClick={() => void save()} disabled={busy} data-testid=\"config-system-llm-save\">\n <Save size={14} aria-hidden /> {busy ? 'Saving…' : 'Save'}\n </Button>\n </Inline>\n {saved && <span data-testid=\"config-system-llm-saved\" style={{ color: 'var(--success)', fontSize: 'var(--fs-12)' }}>Saved</span>}\n {error !== null && (\n <span role=\"alert\" data-testid=\"config-system-llm-error\" style={{ color: 'var(--danger)', fontSize: 'var(--fs-12)' }}>{error}</span>\n )}\n </Stack>\n )}\n </Stack>\n </CardBody>\n </Card>\n );\n}"],"names":["SECTIONS","SettingsIcon","Cpu","Plug","ServerCog","ConfigView","section","setSection","useState","jsxs","Stack","jsx","ViewHeader","Inline","s","RuntimeConfigPanel","ProvidersPanel","McpsPanel","SystemLlmPanel","payload","useFetch","draft","setDraft","busy","setBusy","saved","setSaved","error","setError","useEffect","_a","reload","useCallback","save","fetchJson","err","FetchError","Card","CardBody","Button","RefreshCcw","Save","Skeleton","e","adding","setAdding","editing","setEditing","confirmDelete","setConfirmDelete","refresh","providers","useMemo","drop","id","Plus","EmptyState","p","isConfirming","Pencil","cur","Trash2","mcps","m","enabled","setEnabled","provider","setProvider","model","setModel","Input"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ConfigView-BntUrW7s.js","sources":["../../src/web/v8/views/Config/ConfigView.tsx"],"sourcesContent":["/**\n * v8/views/Config/ConfigView.tsx — Sprint S41, v9.3.0.\n *\n * Three sub-sections:\n * - Runtime config: read-only viewer + Reload + Save (PUT\n * /api/config with the edited raw JSON).\n * - Providers: full CRUD via /api/config/providers + the\n * \"add with key\" auto endpoint.\n * - MCPs: full CRUD via /api/config/mcps.\n * - System LLM: read/write the cline.json#systemLlm block via\n * /api/llm/system-llm.\n *\n * Inline confirm for delete. Sheet form for Add / Edit.\n */\n\nimport { useCallback, useEffect, useMemo, useState } from 'react';\nimport { Plus, Pencil, Trash2, RefreshCcw, Save, ServerCog, Cpu, Plug, Settings as SettingsIcon } from 'lucide-react';\nimport type { LucideIcon } from 'lucide-react';\nimport { Stack } from '../../ui/primitives/Stack.js';\nimport { Inline } from '../../ui/primitives/Inline.js';\nimport { ViewHeader } from '../../ui/data/ViewHeader.js';\nimport { Card, CardBody } from '../../ui/data/Card.js';\nimport { Button } from '../../ui/controls/Button.js';\nimport { Input } from '../../ui/controls/Input.js';\nimport { Sheet, SheetClose, SheetContent } from '../../ui/feedback/Sheet.js';\nimport { Skeleton } from '../../ui/feedback/Skeleton.js';\nimport { EmptyState } from '../../ui/feedback/EmptyState.js';\nimport { useFetch } from '../../data/useFetch.js';\nimport { fetchJson, FetchError } from '../../data/fetcher.js';\n\ninterface Provider {\n id: string;\n name?: string;\n groupId?: string;\n}\n\ninterface Mcp {\n id: string;\n name?: string;\n command?: string;\n}\n\ninterface SystemLlm {\n enabled: boolean;\n provider: string | null;\n model: string | null;\n}\n\ninterface RuntimeConfig {\n path: string;\n data: unknown;\n raw: string;\n exists: boolean;\n}\n\ntype SectionId = 'runtime' | 'providers' | 'mcps' | 'system-llm';\n\nconst SECTIONS: Array<{ id: SectionId; label: string; icon: LucideIcon }> = [\n { id: 'runtime', label: 'Runtime config', icon: SettingsIcon },\n { id: 'providers', label: 'Providers', icon: Cpu },\n { id: 'mcps', label: 'MCPs', icon: Plug },\n { id: 'system-llm', label: 'System LLM', icon: ServerCog },\n];\n\nexport function ConfigView(): JSX.Element {\n const [section, setSection] = useState<SectionId>('runtime');\n return (\n <Stack gap={4} data-testid=\"config-view\">\n <ViewHeader\n title=\"Config\"\n description=\"Runtime config + providers + MCPs + system LLM.\"\n />\n <Inline gap={1} role=\"tablist\">\n {SECTIONS.map((s) => (\n <button\n key={s.id}\n type=\"button\"\n role=\"tab\"\n aria-selected={section === s.id}\n onClick={() => setSection(s.id)}\n data-testid={`config-tab-${s.id}`}\n style={{\n padding: 'var(--space-2) var(--space-3)',\n borderRadius: 'var(--radius-md)',\n border: '1px solid var(--border)',\n background: section === s.id ? 'color-mix(in oklch, var(--accent) 14%, transparent)' : 'var(--surface-0)',\n color: section === s.id ? 'var(--accent)' : 'var(--fg-muted)',\n fontSize: 'var(--fs-12)',\n cursor: 'pointer',\n }}\n >\n <s.icon size={14} aria-hidden style={{ verticalAlign: 'middle', marginRight: 6 }} />\n {s.label}\n </button>\n ))}\n </Inline>\n {section === 'runtime' && <RuntimeConfigPanel />}\n {section === 'providers' && <ProvidersPanel />}\n {section === 'mcps' && <McpsPanel />}\n {section === 'system-llm' && <SystemLlmPanel />}\n </Stack>\n );\n}\n\nfunction RuntimeConfigPanel(): JSX.Element {\n const payload = useFetch<RuntimeConfig>('/api/config');\n const [draft, setDraft] = useState<string>('');\n const [busy, setBusy] = useState<boolean>(false);\n const [saved, setSaved] = useState<boolean>(false);\n const [error, setError] = useState<string | null>(null);\n\n useEffect(() => {\n if (payload.data?.raw !== undefined) setDraft(payload.data.raw);\n }, [payload.data?.raw]);\n\n const reload = useCallback(() => { void payload.refetch(); }, [payload]);\n\n const save = async (): Promise<void> => {\n setBusy(true);\n setError(null);\n setSaved(false);\n try {\n await fetchJson('/api/config', { method: 'PUT', body: draft });\n setSaved(true);\n reload();\n } catch (err) {\n setError(err instanceof FetchError ? err.message : (err as Error).message);\n } finally {\n setBusy(false);\n }\n };\n\n return (\n <Card variant=\"default\">\n <CardBody>\n <Stack gap={2}>\n <Inline align=\"center\" justify=\"between\" gap={2}>\n <strong style={{ fontSize: 'var(--fs-13)' }}>Runtime config</strong>\n <Inline gap={1}>\n <Button variant=\"ghost\" onClick={reload} data-testid=\"config-runtime-reload\">\n <RefreshCcw size={14} aria-hidden /> Reload\n </Button>\n <Button variant=\"primary\" onClick={() => void save()} disabled={busy} data-testid=\"config-runtime-save\">\n <Save size={14} aria-hidden /> {busy ? 'Saving…' : 'Save'}\n </Button>\n </Inline>\n </Inline>\n {payload.loading && payload.data === null ? (\n <Skeleton style={{ height: 240 }} />\n ) : (\n <textarea\n value={draft}\n rows={16}\n data-testid=\"config-runtime-raw\"\n onChange={(e) => setDraft((e.target as HTMLTextAreaElement).value)}\n style={{\n background: 'var(--surface-0)',\n border: '1px solid var(--border)',\n borderRadius: 'var(--radius-md)',\n padding: 'var(--space-2)',\n color: 'var(--fg)',\n fontFamily: 'var(--font-mono)',\n fontSize: 'var(--fs-12)',\n resize: 'vertical',\n }}\n />\n )}\n {saved && <span data-testid=\"config-runtime-saved\" style={{ color: 'var(--success)', fontSize: 'var(--fs-12)' }}>Saved</span>}\n {error !== null && (\n <span role=\"alert\" data-testid=\"config-runtime-error\" style={{ color: 'var(--danger)', fontSize: 'var(--fs-12)' }}>{error}</span>\n )}\n </Stack>\n </CardBody>\n </Card>\n );\n}\n\nfunction ProvidersPanel(): JSX.Element {\n const payload = useFetch<{ providers: Provider[] }>('/api/config/providers');\n const [adding, setAdding] = useState<boolean>(false);\n const [editing, setEditing] = useState<string | null>(null);\n const [confirmDelete, setConfirmDelete] = useState<string | null>(null);\n const [error, setError] = useState<string | null>(null);\n const refresh = useCallback(() => { void payload.refetch(); }, [payload]);\n const providers = useMemo(() => payload.data?.providers ?? [], [payload.data]);\n\n const drop = async (id: string): Promise<void> => {\n setError(null);\n try {\n await fetchJson(`/api/config/providers/${id}`, { method: 'DELETE' });\n setConfirmDelete(null);\n refresh();\n } catch (err) {\n setError(err instanceof FetchError ? err.message : (err as Error).message);\n }\n };\n\n return (\n <Card variant=\"default\">\n <CardBody>\n <Stack gap={2}>\n <Inline align=\"center\" justify=\"between\" gap={2}>\n <strong style={{ fontSize: 'var(--fs-13)' }}>Providers</strong>\n <Inline gap={1}>\n {error !== null && (\n <span role=\"alert\" style={{ color: 'var(--danger)', fontSize: 'var(--fs-12)' }}>{error}</span>\n )}\n <Button variant=\"primary\" onClick={() => setAdding(true)} data-testid=\"config-providers-add\">\n <Plus size={14} aria-hidden /> Add\n </Button>\n </Inline>\n </Inline>\n {payload.loading && providers.length === 0 ? (\n <Skeleton style={{ height: 100 }} />\n ) : providers.length === 0 ? (\n <EmptyState icon={<Cpu size={28} aria-hidden />} title=\"No providers\" description=\"Add one or use Auto-add with key.\" />\n ) : (\n <Stack gap={1}>\n {providers.map((p) => {\n const isConfirming = confirmDelete === p.id;\n return (\n <div key={p.id} data-testid={`config-provider-row-${p.id}`} style={{ padding: 'var(--space-2)', border: '1px solid var(--border)', borderRadius: 'var(--radius-sm)' }}>\n <Inline align=\"center\" justify=\"between\" gap={2}>\n <Inline align=\"center\" gap={2}>\n <strong>{p.name || p.id}</strong>\n {p.groupId && <span style={{ fontSize: 'var(--fs-12)', color: 'var(--fg-muted)' }}>group={p.groupId}</span>}\n </Inline>\n <Inline gap={1}>\n <Button variant=\"ghost\" onClick={() => setEditing(p.id)} data-testid={`config-provider-edit-${p.id}`} aria-label={`Edit ${p.id}`}>\n <Pencil size={14} aria-hidden />\n </Button>\n <Button variant=\"ghost\" onClick={() => setConfirmDelete((cur) => (cur === p.id ? null : p.id))} data-testid={`config-provider-delete-${p.id}`} aria-label={`Delete ${p.id}`}>\n <Trash2 size={14} aria-hidden />\n </Button>\n </Inline>\n </Inline>\n {isConfirming && (\n <Inline gap={1} style={{ marginTop: 'var(--space-1)' }}>\n <Button variant=\"danger\" onClick={() => void drop(p.id)} data-testid={`config-provider-confirm-delete-${p.id}`}>Confirm delete</Button>\n <Button variant=\"ghost\" onClick={() => setConfirmDelete(null)}>Cancel</Button>\n </Inline>\n )}\n </div>\n );\n })}\n </Stack>\n )}\n </Stack>\n </CardBody>\n </Card>\n );\n}\n\nfunction McpsPanel(): JSX.Element {\n const payload = useFetch<{ mcps: Mcp[] }>('/api/config/mcps');\n const mcps = useMemo(() => payload.data?.mcps ?? [], [payload.data]);\n const refresh = useCallback(() => { void payload.refetch(); }, [payload]);\n return (\n <Card variant=\"default\">\n <CardBody>\n <Stack gap={2}>\n <Inline align=\"center\" justify=\"between\" gap={2}>\n <strong style={{ fontSize: 'var(--fs-13)' }}>MCP servers</strong>\n </Inline>\n {payload.loading && mcps.length === 0 ? (\n <Skeleton style={{ height: 60 }} />\n ) : mcps.length === 0 ? (\n <EmptyState icon={<Plug size={28} aria-hidden />} title=\"No MCPs\" description=\"Add one via /api/config/mcps.\" />\n ) : (\n <Stack gap={1}>\n {mcps.map((m) => (\n <div key={m.id} data-testid={`config-mcp-row-${m.id}`} style={{ padding: 'var(--space-2)', border: '1px solid var(--border)', borderRadius: 'var(--radius-sm)', display: 'flex', justifyContent: 'space-between' }}>\n <strong>{m.name || m.id}</strong>\n {m.command && <code style={{ fontSize: 'var(--fs-12)', color: 'var(--fg-muted)' }}>{m.command}</code>}\n </div>\n ))}\n </Stack>\n )}\n <Button variant=\"ghost\" onClick={refresh} data-testid=\"config-mcps-refresh\">\n <RefreshCcw size={14} aria-hidden /> Refresh\n </Button>\n </Stack>\n </CardBody>\n </Card>\n );\n}\n\nfunction SystemLlmPanel(): JSX.Element {\n const payload = useFetch<SystemLlm>('/api/llm/system-llm');\n const [enabled, setEnabled] = useState<boolean>(false);\n const [provider, setProvider] = useState<string>('');\n const [model, setModel] = useState<string>('');\n const [busy, setBusy] = useState<boolean>(false);\n const [saved, setSaved] = useState<boolean>(false);\n const [error, setError] = useState<string | null>(null);\n\n useEffect(() => {\n if (payload.data) {\n setEnabled(payload.data.enabled);\n setProvider(payload.data.provider ?? '');\n setModel(payload.data.model ?? '');\n }\n }, [payload.data]);\n\n const save = async (): Promise<void> => {\n setBusy(true);\n setError(null);\n setSaved(false);\n try {\n await fetchJson('/api/llm/system-llm', {\n method: 'PUT',\n body: { enabled, provider, model },\n });\n setSaved(true);\n void payload.refetch();\n } catch (err) {\n setError(err instanceof FetchError ? err.message : (err as Error).message);\n } finally {\n setBusy(false);\n }\n };\n\n return (\n <Card variant=\"default\">\n <CardBody>\n <Stack gap={2}>\n <strong style={{ fontSize: 'var(--fs-13)' }}>System LLM</strong>\n {payload.loading && payload.data === null ? (\n <Skeleton style={{ height: 100 }} />\n ) : (\n <Stack gap={2}>\n <label style={{ display: 'flex', alignItems: 'center', gap: 'var(--space-2)' }}>\n <input\n type=\"checkbox\"\n checked={enabled}\n data-testid=\"config-system-llm-enabled\"\n onChange={(e) => setEnabled((e.target as HTMLInputElement).checked)}\n />\n <span style={{ fontSize: 'var(--fs-13)' }}>Enabled</span>\n </label>\n <label style={{ display: 'flex', flexDirection: 'column', gap: 'var(--space-1)' }}>\n <span style={{ fontSize: 'var(--fs-12)', color: 'var(--fg-muted)' }}>Provider</span>\n <Input value={provider} data-testid=\"config-system-llm-provider\" onChange={(e) => setProvider((e.target as HTMLInputElement).value)} />\n </label>\n <label style={{ display: 'flex', flexDirection: 'column', gap: 'var(--space-1)' }}>\n <span style={{ fontSize: 'var(--fs-12)', color: 'var(--fg-muted)' }}>Model</span>\n <Input value={model} data-testid=\"config-system-llm-model\" onChange={(e) => setModel((e.target as HTMLInputElement).value)} />\n </label>\n <Inline justify=\"end\" gap={2}>\n <Button variant=\"primary\" onClick={() => void save()} disabled={busy} data-testid=\"config-system-llm-save\">\n <Save size={14} aria-hidden /> {busy ? 'Saving…' : 'Save'}\n </Button>\n </Inline>\n {saved && <span data-testid=\"config-system-llm-saved\" style={{ color: 'var(--success)', fontSize: 'var(--fs-12)' }}>Saved</span>}\n {error !== null && (\n <span role=\"alert\" data-testid=\"config-system-llm-error\" style={{ color: 'var(--danger)', fontSize: 'var(--fs-12)' }}>{error}</span>\n )}\n </Stack>\n )}\n </Stack>\n </CardBody>\n </Card>\n );\n}"],"names":["SECTIONS","SettingsIcon","Cpu","Plug","ServerCog","ConfigView","section","setSection","useState","jsxs","Stack","jsx","ViewHeader","Inline","s","RuntimeConfigPanel","ProvidersPanel","McpsPanel","SystemLlmPanel","payload","useFetch","draft","setDraft","busy","setBusy","saved","setSaved","error","setError","useEffect","_a","reload","useCallback","save","fetchJson","err","FetchError","Card","CardBody","Button","RefreshCcw","Save","Skeleton","e","adding","setAdding","editing","setEditing","confirmDelete","setConfirmDelete","refresh","providers","useMemo","drop","id","Plus","EmptyState","p","isConfirming","Pencil","cur","Trash2","mcps","m","enabled","setEnabled","provider","setProvider","model","setModel","Input"],"mappings":"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"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{r as $,j as e}from"./cmdk-C3F6LD6N.js";import{u as k,S as a,B as F,I as d,A as b,b as I,h as V}from"./main-BURAlktW.js";import{G as C}from"./Grid--WKvqu5h.js";import{V as A}from"./ViewHeader-C-t1U2cQ.js";import{C as n,b as i}from"./Card-BtsmkhJa.js";import{R}from"./refresh-cw-DwlP59en.js";import{F as D}from"./file-text-BOroDtZE.js";function E(r){if(!r||r<=0)return"—";const s=Math.floor(r/86400),l=Math.floor(r%86400/3600),o=Math.floor(r%3600/60);return s>0?`${s}d ${l}h`:l>0?`${l}h ${o}m`:`${o}m`}function N(){var g,x,j,m,u,p,v,y,S,z,w;const r=k("/api/diagnostics"),s=k("/api/diagnostics/logs?tail=200");$.useEffect(()=>{const t=setInterval(()=>{s.refetch()},1e4);return()=>clearInterval(t)},[s]);const l=(g=r.data)==null?void 0:g.uptime,o=((x=r.data)==null?void 0:x.checks)??[],h=((j=r.data)==null?void 0:j.counts)??{},c=((m=s.data)==null?void 0:m.lines)??[],f=((u=s.data)==null?void 0:u.file)??null;return e.jsxs(a,{gap:5,"data-testid":"diagnostics-view",children:[e.jsx(A,{title:"Diagnostics",description:"Live system snapshot + active log tail. Auto-refresh every 10s.",actions:e.jsxs(F,{variant:"ghost",onClick:()=>{r.refetch(),s.refetch()},"data-testid":"diagnostics-refresh",children:[e.jsx(R,{size:14,"aria-hidden":!0})," Refresh"]})}),e.jsxs(C,{cols:3,children:[e.jsx(n,{variant:"default",children:e.jsx(i,{children:e.jsxs(a,{gap:1,children:[e.jsx("span",{style:{fontSize:"var(--fs-12)",color:"var(--fg-muted)"},children:"Status"}),e.jsxs(d,{align:"center",gap:2,children:[e.jsx(b,{size:14,"aria-hidden":!0}),e.jsx("strong",{style:{fontFamily:"var(--font-mono)"},children:r.loading?"…":r.error?"error":(v=(p=r.data)==null?void 0:p.service)!=null&&v.running?(((S=(y=r.data)==null?void 0:y.errors)==null?void 0:S.length)??0)>0?"warn":"ok":"stopped"})]})]})})}),e.jsx(n,{variant:"default",children:e.jsx(i,{children:e.jsxs(a,{gap:1,children:[e.jsx("span",{style:{fontSize:"var(--fs-12)",color:"var(--fg-muted)"},children:"Uptime"}),e.jsx("strong",{style:{fontFamily:"var(--font-mono)"},children:r.loading?"…":E(l)})]})})}),e.jsx(n,{variant:"default",children:e.jsx(i,{children:e.jsxs(a,{gap:1,children:[e.jsx("span",{style:{fontSize:"var(--fs-12)",color:"var(--fg-muted)"},children:"Version"}),e.jsx("strong",{style:{fontFamily:"var(--font-mono)"},children:r.loading?"…":((z=r.data)==null?void 0:z.version)??"—"})]})})})]}),r.error&&e.jsx(n,{variant:"default",style:{borderColor:"var(--danger)"},children:e.jsx(i,{children:e.jsxs(a,{gap:2,children:[e.jsxs(d,{align:"center",gap:2,children:[e.jsx(b,{size:14,"aria-hidden":!0,style:{color:"var(--danger)"}}),e.jsx("strong",{style:{color:"var(--danger)"},children:"Diagnostics fetch failed"})]}),e.jsx("span",{style:{fontSize:"var(--fs-12)",color:"var(--fg-muted)"},children:r.error.message??String(r.error)}),e.jsxs(F,{variant:"secondary",size:"sm",onClick:()=>{r.refetch()},children:[e.jsx(R,{size:12,"aria-hidden":!0})," Retry"]})]})})}),Object.keys(h).length>0&&e.jsx(n,{variant:"default",children:e.jsx(i,{children:e.jsxs(a,{gap:2,children:[e.jsx("strong",{children:"Counts"}),e.jsx(C,{cols:4,children:Object.entries(h).map(([t,B])=>e.jsxs(a,{gap:0,children:[e.jsx("span",{style:{fontSize:"var(--fs-11)",color:"var(--fg-muted)",textTransform:"uppercase",letterSpacing:"0.04em"},children:t}),e.jsx("strong",{style:{fontFamily:"var(--font-mono)",fontSize:"var(--fs-13)"},children:String(B??"—")})]},t))})]})})}),o.length>0&&e.jsx(n,{variant:"default",children:e.jsx(i,{children:e.jsxs(a,{gap:2,children:[e.jsxs("strong",{children:["Checks (",o.length,")"]}),e.jsx(d,{gap:1,wrap:!0,children:o.map(t=>e.jsx(I,{tone:t.status==="ok"?"success":t.status==="warn"?"warning":"danger",children:t.name},t.name))})]})})}),e.jsx(n,{variant:"default",children:e.jsx(i,{children:e.jsxs(a,{gap:2,children:[e.jsxs(d,{align:"center",justify:"between",children:[e.jsxs(d,{align:"center",gap:2,children:[e.jsx(D,{size:14,"aria-hidden":!0}),e.jsx("strong",{children:"Log tail"}),f&&e.jsx("code",{style:{fontSize:"var(--fs-12)",color:"var(--fg-muted)",fontFamily:"var(--font-mono)"},children:f})]}),e.jsxs("span",{style:{fontSize:"var(--fs-12)",color:"var(--fg-muted)"},children:[c.length," / ",((w=s.data)==null?void 0:w.total)??0," lines"]})]}),s.loading&&c.length===0?e.jsx(V,{style:{height:240}}):c.length===0?e.jsx("span",{style:{color:"var(--fg-muted)",fontSize:"var(--fs-12)"},children:"No log lines yet."}):e.jsx("pre",{"data-testid":"diagnostics-log-tail",style:{maxHeight:320,overflowY:"auto",padding:"var(--space-3)",background:"var(--surface-1)",borderRadius:"var(--radius-sm)",fontSize:"var(--fs-12)",fontFamily:"var(--font-mono)",margin:0,whiteSpace:"pre-wrap",wordBreak:"break-all"},children:c.join(`
|
|
2
|
+
`)})]})})})]})}export{N as DiagnosticsView};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DiagnosticsView-4x0Zu3yP.js","sources":["../../src/web/v8/views/Diagnostics/DiagnosticsView.tsx"],"sourcesContent":["import { useEffect, useState } from 'react';\nimport { Activity, RefreshCw, FileText } from 'lucide-react';\nimport { Stack } from '../../ui/primitives/Stack.js';\nimport { Inline } from '../../ui/primitives/Inline.js';\nimport { Grid } from '../../ui/primitives/Grid.js';\nimport { ViewHeader } from '../../ui/data/ViewHeader.js';\nimport { Card, CardBody } from '../../ui/data/Card.js';\nimport { Badge } from '../../ui/data/Badge.js';\nimport { Button } from '../../ui/controls/Button.js';\nimport { Skeleton } from '../../ui/feedback/Skeleton.js';\nimport { useFetch } from '../../data/useFetch.js';\n\n/**\n * DiagnosticsView — Sprint S35. System snapshot + active log tail.\n */\n\ninterface DiagnosticsHealth {\n status: string;\n checks?: Array<{ name: string; status: string; message?: string }>;\n}\n\ninterface DiagnosticsSnapshot {\n version?: string;\n uptime?: number;\n memory?: { rss?: number; heapUsed?: number; heapTotal?: number };\n checks?: Array<{ name: string; status: string; message?: string }>;\n counts?: Record<string, number | string | null>;\n errors?: Array<{ line: string; ts: string | null }>;\n service?: { running?: boolean; pid?: number };\n}\n\ninterface LogsResponse {\n lines: string[];\n file: string | null;\n total: number;\n}\n\nfunction fmtUptime(secs: number | undefined): string {\n if (!secs || secs <= 0) return '—';\n const days = Math.floor(secs / 86400);\n const hours = Math.floor((secs % 86400) / 3600);\n const mins = Math.floor((secs % 3600) / 60);\n if (days > 0) return `${days}d ${hours}h`;\n if (hours > 0) return `${hours}h ${mins}m`;\n return `${mins}m`;\n}\n\nexport function DiagnosticsView(): JSX.Element {\n const snap = useFetch<DiagnosticsSnapshot>('/api/diagnostics');\n const logs = useFetch<LogsResponse>('/api/diagnostics/logs?tail=200');\n\n // Auto-refresh logs every 10s while page is open.\n useEffect(() => {\n const id = setInterval(() => { void logs.refetch(); }, 10_000);\n return () => clearInterval(id);\n }, [logs]);\n\n const uptime = snap.data?.uptime;\n const checks = snap.data?.checks ?? [];\n const counts = snap.data?.counts ?? {};\n const lines = logs.data?.lines ?? [];\n const logFile = logs.data?.file ?? null;\n\n return (\n <Stack gap={5} data-testid=\"diagnostics-view\">\n <ViewHeader\n title=\"Diagnostics\"\n description=\"Live system snapshot + active log tail. Auto-refresh every 10s.\"\n actions={\n <Button variant=\"ghost\" onClick={() => { void snap.refetch(); void logs.refetch(); }} data-testid=\"diagnostics-refresh\">\n <RefreshCw size={14} aria-hidden /> Refresh\n </Button>\n }\n />\n\n <Grid cols={3}>\n <Card variant=\"default\">\n <CardBody>\n <Stack gap={1}>\n <span style={{ fontSize: 'var(--fs-12)', color: 'var(--fg-muted)' }}>Status</span>\n <Inline align=\"center\" gap={2}>\n <Activity size={14} aria-hidden />\n <strong style={{ fontFamily: 'var(--font-mono)' }}>\n {snap.loading ? '…' : (\n snap.error ? 'error' :\n !snap.data?.service?.running ? 'stopped' :\n (snap.data?.errors?.length ?? 0) > 0 ? 'warn' : 'ok'\n )}\n </strong>\n </Inline>\n </Stack>\n </CardBody>\n </Card>\n <Card variant=\"default\">\n <CardBody>\n <Stack gap={1}>\n <span style={{ fontSize: 'var(--fs-12)', color: 'var(--fg-muted)' }}>Uptime</span>\n <strong style={{ fontFamily: 'var(--font-mono)' }}>{snap.loading ? '…' : fmtUptime(uptime)}</strong>\n </Stack>\n </CardBody>\n </Card>\n <Card variant=\"default\">\n <CardBody>\n <Stack gap={1}>\n <span style={{ fontSize: 'var(--fs-12)', color: 'var(--fg-muted)' }}>Version</span>\n <strong style={{ fontFamily: 'var(--font-mono)' }}>{snap.loading ? '…' : (snap.data?.version ?? '—')}</strong>\n </Stack>\n </CardBody>\n </Card>\n </Grid>\n\n {snap.error && (\n <Card variant=\"default\" style={{ borderColor: 'var(--danger)' }}>\n <CardBody>\n <Stack gap={2}>\n <Inline align=\"center\" gap={2}>\n <Activity size={14} aria-hidden style={{ color: 'var(--danger)' }} />\n <strong style={{ color: 'var(--danger)' }}>Diagnostics fetch failed</strong>\n </Inline>\n <span style={{ fontSize: 'var(--fs-12)', color: 'var(--fg-muted)' }}>{snap.error.message ?? String(snap.error)}</span>\n <Button variant=\"secondary\" size=\"sm\" onClick={() => { void snap.refetch(); }}>\n <RefreshCw size={12} aria-hidden /> Retry\n </Button>\n </Stack>\n </CardBody>\n </Card>\n )}\n\n {Object.keys(counts).length > 0 && (\n <Card variant=\"default\">\n <CardBody>\n <Stack gap={2}>\n <strong>Counts</strong>\n <Grid cols={4}>\n {Object.entries(counts).map(([k, v]) => (\n <Stack key={k} gap={0}>\n <span style={{ fontSize: 'var(--fs-11)', color: 'var(--fg-muted)', textTransform: 'uppercase', letterSpacing: '0.04em' }}>{k}</span>\n <strong style={{ fontFamily: 'var(--font-mono)', fontSize: 'var(--fs-13)' }}>{String(v ?? '—')}</strong>\n </Stack>\n ))}\n </Grid>\n </Stack>\n </CardBody>\n </Card>\n )}\n\n {checks.length > 0 && (\n <Card variant=\"default\">\n <CardBody>\n <Stack gap={2}>\n <strong>Checks ({checks.length})</strong>\n <Inline gap={1} wrap={true}>\n {checks.map((c) => (\n <Badge key={c.name} tone={c.status === 'ok' ? 'success' : c.status === 'warn' ? 'warning' : 'danger'}>\n {c.name}\n </Badge>\n ))}\n </Inline>\n </Stack>\n </CardBody>\n </Card>\n )}\n\n <Card variant=\"default\">\n <CardBody>\n <Stack gap={2}>\n <Inline align=\"center\" justify=\"between\">\n <Inline align=\"center\" gap={2}>\n <FileText size={14} aria-hidden />\n <strong>Log tail</strong>\n {logFile && <code style={{ fontSize: 'var(--fs-12)', color: 'var(--fg-muted)', fontFamily: 'var(--font-mono)' }}>{logFile}</code>}\n </Inline>\n <span style={{ fontSize: 'var(--fs-12)', color: 'var(--fg-muted)' }}>{lines.length} / {logs.data?.total ?? 0} lines</span>\n </Inline>\n {logs.loading && lines.length === 0 ? (\n <Skeleton style={{ height: 240 }} />\n ) : lines.length === 0 ? (\n <span style={{ color: 'var(--fg-muted)', fontSize: 'var(--fs-12)' }}>No log lines yet.</span>\n ) : (\n <pre\n data-testid=\"diagnostics-log-tail\"\n style={{\n maxHeight: 320,\n overflowY: 'auto',\n padding: 'var(--space-3)',\n background: 'var(--surface-1)',\n borderRadius: 'var(--radius-sm)',\n fontSize: 'var(--fs-12)',\n fontFamily: 'var(--font-mono)',\n margin: 0,\n whiteSpace: 'pre-wrap',\n wordBreak: 'break-all',\n }}\n >\n {lines.join('\\n')}\n </pre>\n )}\n </Stack>\n </CardBody>\n </Card>\n </Stack>\n );\n}"],"names":["fmtUptime","secs","days","hours","mins","DiagnosticsView","snap","useFetch","logs","useEffect","id","uptime","_a","checks","_b","counts","_c","lines","_d","logFile","_e","jsxs","Stack","jsx","ViewHeader","Button","RefreshCw","Grid","Card","CardBody","Inline","Activity","_g","_f","_i","_h","_j","k","v","c","Badge","FileText","_k","Skeleton"],"mappings":"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"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import{r as c,j as e}from"./cmdk-C3F6LD6N.js";import{d as k,u as b,a as C,S as h,I as d,B as r,h as m,M as S,l as $,X as w,i as f,F as x}from"./main-BURAlktW.js";import{V as z}from"./ViewHeader-C-t1U2cQ.js";import{L as E}from"./ListHeader-CM8QoIWG.js";import{C as D,b as R}from"./Card-BtsmkhJa.js";import{E as T}from"./EmptyState-DjKtY1Qi.js";import{E as F}from"./ErrorState-CBJbEQ8B.js";import{R as q}from"./refresh-ccw-DA8_IB9l.js";import{T as j}from"./trash-2-D6qePV_q.js";import"./Alert-BZGk39mB.js";import"./circle-alert-Dz8lGfCZ.js";import"./triangle-alert-B2oHbmoh.js";import"./circle-check-DFB50ojt.js";/**
|
|
2
|
+
* @license lucide-react v0.460.0 - ISC
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the ISC license.
|
|
5
|
+
* See the LICENSE file in the root directory of this source tree.
|
|
6
|
+
*/const L=k("SkipForward",[["polygon",{points:"5 4 15 12 5 20 5 4",key:"16p6eg"}],["line",{x1:"19",x2:"19",y1:"5",y2:"19",key:"futhcm"}]]);function G(){const s=b("/api/dialogs"),[v,g]=c.useState(null),[u,l]=c.useState(null),t=c.useCallback(()=>{s.refetch()},[s]);C("dialog:show",()=>{t()});const y=async i=>{l(null);try{await f(`/api/dialogs/${i}`,{method:"DELETE"}),g(null),t()}catch(a){l((a instanceof x,a.message))}},p=async(i,a)=>{l(null);try{await f(`/api/dialogs/${i}/${a}`,{method:"POST",body:{}}),t()}catch(n){l((n instanceof x,n.message))}},o=c.useMemo(()=>{var i;return((i=s.data)==null?void 0:i.dialogs)??[]},[s.data]);return e.jsxs(h,{gap:4,"data-testid":"dialogs-view",children:[e.jsx(z,{title:"Dialogs",description:"Active dialog queue (debug + manual dismiss).",actions:e.jsxs(d,{gap:1,children:[u!==null&&e.jsx("span",{role:"alert","data-testid":"dialogs-error",style:{color:"var(--danger)",fontSize:"var(--fs-12)"},children:u}),e.jsxs(r,{variant:"ghost",onClick:()=>void t(),"data-testid":"dialogs-refresh",children:[e.jsx(q,{size:14,"aria-hidden":!0})," Refresh"]})]})}),e.jsx(E,{title:"Queue",count:o.length,testid:"dialogs-list-header"}),e.jsx(D,{variant:"default",children:e.jsx(R,{children:s.loading&&o.length===0?e.jsxs(h,{gap:1,children:[e.jsx(m,{style:{height:32}}),e.jsx(m,{style:{height:32}})]}):s.error&&o.length===0?e.jsx(F,{block:!0,title:"Couldn't load dialogs",description:"The dialog queue failed to fetch. Retry to refetch.",error:s.error,onRetry:t,testid:"dialogs-error-state"}):o.length===0?e.jsx(T,{icon:e.jsx(S,{size:28,"aria-hidden":!0}),title:"No active dialogs",description:"Dialogs are confirmations and prompts the agent raises when it needs user input before proceeding. They appear here when the slash-command plugin queues one."}):e.jsx(h,{gap:1,children:o.map(i=>{const a=v===i.id;return e.jsxs("div",{"data-testid":`dialog-row-${i.id}`,style:{padding:"var(--space-2)",border:"1px solid var(--border)",borderRadius:"var(--radius-sm)",background:"var(--surface-0)"},children:[e.jsxs(d,{align:"center",justify:"between",gap:2,children:[e.jsxs(h,{gap:0,style:{minWidth:0},children:[e.jsxs(d,{align:"center",gap:2,children:[e.jsx("strong",{style:{fontSize:"var(--fs-13)"},children:i.title||i.id}),i.kind&&e.jsx("span",{style:{fontSize:"var(--fs-11)",color:"var(--fg-subtle)",fontFamily:"var(--font-mono)"},children:i.kind}),i.source&&e.jsxs("span",{style:{fontSize:"var(--fs-11)",color:"var(--fg-muted)"},children:["· ",i.source]})]}),i.body&&e.jsx("span",{style:{fontSize:"var(--fs-12)",color:"var(--fg-muted)"},children:i.body.length>160?`${i.body.slice(0,160)}…`:i.body})]}),e.jsxs(d,{gap:1,children:[e.jsxs(r,{variant:"primary",onClick:()=>void p(i.id,"approve"),"data-testid":`dialog-approve-${i.id}`,"aria-label":`Approve ${i.id}`,children:[e.jsx($,{size:14,"aria-hidden":!0})," Approve"]}),e.jsxs(r,{variant:"ghost",onClick:()=>void p(i.id,"skip"),"data-testid":`dialog-skip-${i.id}`,"aria-label":`Skip ${i.id}`,children:[e.jsx(L,{size:14,"aria-hidden":!0})," Skip"]}),e.jsxs(r,{variant:"ghost",onClick:()=>void p(i.id,"deny"),"data-testid":`dialog-deny-${i.id}`,"aria-label":`Deny ${i.id}`,children:[e.jsx(w,{size:14,"aria-hidden":!0})," Deny"]}),e.jsx(r,{variant:"ghost",onClick:()=>g(n=>n===i.id?null:i.id),"data-testid":`dialog-dismiss-${i.id}`,"aria-label":`Dismiss ${i.id}`,children:e.jsx(j,{size:14,"aria-hidden":!0})})]})]}),a&&e.jsxs(d,{gap:1,style:{marginTop:"var(--space-1)"},children:[e.jsxs(r,{variant:"danger",onClick:()=>void y(i.id),"data-testid":`dialog-confirm-dismiss-${i.id}`,children:[e.jsx(j,{size:14,"aria-hidden":!0})," Confirm"]}),e.jsx(r,{variant:"ghost",onClick:()=>g(null),children:"Cancel"})]})]},i.id)})})})})]})}export{G as DialogsView};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DialogsView-Xd02dVAX.js","sources":["../../../node_modules/lucide-react/dist/esm/icons/skip-forward.js","../../src/web/v8/views/Dialogs/DialogsView.tsx"],"sourcesContent":["/**\n * @license lucide-react v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst SkipForward = createLucideIcon(\"SkipForward\", [\n [\"polygon\", { points: \"5 4 15 12 5 20 5 4\", key: \"16p6eg\" }],\n [\"line\", { x1: \"19\", x2: \"19\", y1: \"5\", y2: \"19\", key: \"futhcm\" }]\n]);\n\nexport { SkipForward as default };\n//# sourceMappingURL=skip-forward.js.map\n","/**\n * v8/views/Dialogs/DialogsView.tsx — Sprint S42, v9.3.0.\n *\n * Active dialog queue pulled from /api/dialogs. Per-row: view kind,\n * title, body preview, source, age, inline-confirm Dismiss (DELETE\n * /api/dialogs/:id). Empty state + manual Refresh button. No\n * window.confirm.\n */\n\nimport { useCallback, useMemo, useState } from 'react';\nimport { Check, MessageSquare, RefreshCcw, SkipForward, Trash2, X } from 'lucide-react';\nimport { Stack } from '../../ui/primitives/Stack.js';\nimport { Inline } from '../../ui/primitives/Inline.js';\nimport { ViewHeader } from '../../ui/data/ViewHeader.js';\nimport { ListHeader } from '../../ui/data/ListHeader.js';\nimport { Card, CardBody } from '../../ui/data/Card.js';\nimport { Button } from '../../ui/controls/Button.js';\nimport { Skeleton } from '../../ui/feedback/Skeleton.js';\nimport { EmptyState } from '../../ui/feedback/EmptyState.js';\nimport { ErrorState } from '../../ui/feedback/ErrorState.js';\nimport { useFetch } from '../../data/useFetch.js';\nimport { useWsMessage } from '../../data/useWebSocket.js';\nimport { fetchJson, FetchError } from '../../data/fetcher.js';\n\ninterface DialogItem {\n id: string;\n kind?: string;\n title?: string;\n body?: string;\n source?: string;\n createdAt?: number | string;\n}\n\nexport function DialogsView(): JSX.Element {\n const payload = useFetch<{ dialogs: DialogItem[] }>('/api/dialogs');\n const [confirmDelete, setConfirmDelete] = useState<string | null>(null);\n const [error, setError] = useState<string | null>(null);\n\n const refresh = useCallback(() => { void payload.refetch(); }, [payload]);\n\n // Live: server broadcasts `dialog:show` on enqueue. Refresh on it.\n useWsMessage('dialog:show', () => { refresh(); });\n\n const drop = async (id: string): Promise<void> => {\n setError(null);\n try {\n await fetchJson(`/api/dialogs/${id}`, { method: 'DELETE' });\n setConfirmDelete(null);\n refresh();\n } catch (err) {\n setError(err instanceof FetchError ? err.message : (err as Error).message);\n }\n };\n\n const decide = async (id: string, verdict: 'approve' | 'deny' | 'skip'): Promise<void> => {\n setError(null);\n try {\n await fetchJson(`/api/dialogs/${id}/${verdict}`, { method: 'POST', body: {} });\n refresh();\n } catch (err) {\n setError(err instanceof FetchError ? err.message : (err as Error).message);\n }\n };\n\n const dialogs = useMemo<DialogItem[]>(() => payload.data?.dialogs ?? [], [payload.data]);\n\n return (\n <Stack gap={4} data-testid=\"dialogs-view\">\n <ViewHeader\n title=\"Dialogs\"\n description=\"Active dialog queue (debug + manual dismiss).\"\n actions={\n <Inline gap={1}>\n {error !== null && (\n <span role=\"alert\" data-testid=\"dialogs-error\" style={{ color: 'var(--danger)', fontSize: 'var(--fs-12)' }}>\n {error}\n </span>\n )}\n <Button variant=\"ghost\" onClick={() => void refresh()} data-testid=\"dialogs-refresh\">\n <RefreshCcw size={14} aria-hidden /> Refresh\n </Button>\n </Inline>\n }\n />\n <ListHeader title=\"Queue\" count={dialogs.length} testid=\"dialogs-list-header\" />\n <Card variant=\"default\">\n <CardBody>\n {payload.loading && dialogs.length === 0 ? (\n <Stack gap={1}>\n <Skeleton style={{ height: 32 }} />\n <Skeleton style={{ height: 32 }} />\n </Stack>\n ) : payload.error && dialogs.length === 0 ? (\n <ErrorState\n block\n title=\"Couldn't load dialogs\"\n description=\"The dialog queue failed to fetch. Retry to refetch.\"\n error={payload.error}\n onRetry={refresh}\n testid=\"dialogs-error-state\"\n />\n ) : dialogs.length === 0 ? (\n <EmptyState\n icon={<MessageSquare size={28} aria-hidden />}\n title=\"No active dialogs\"\n description=\"Dialogs are confirmations and prompts the agent raises when it needs user input before proceeding. They appear here when the slash-command plugin queues one.\"\n />\n ) : (\n <Stack gap={1}>\n {dialogs.map((d) => {\n const isConfirming = confirmDelete === d.id;\n return (\n <div\n key={d.id}\n data-testid={`dialog-row-${d.id}`}\n style={{\n padding: 'var(--space-2)',\n border: '1px solid var(--border)',\n borderRadius: 'var(--radius-sm)',\n background: 'var(--surface-0)',\n }}\n >\n <Inline align=\"center\" justify=\"between\" gap={2}>\n <Stack gap={0} style={{ minWidth: 0 }}>\n <Inline align=\"center\" gap={2}>\n <strong style={{ fontSize: 'var(--fs-13)' }}>{d.title || d.id}</strong>\n {d.kind && (\n <span style={{ fontSize: 'var(--fs-11)', color: 'var(--fg-subtle)', fontFamily: 'var(--font-mono)' }}>\n {d.kind}\n </span>\n )}\n {d.source && (\n <span style={{ fontSize: 'var(--fs-11)', color: 'var(--fg-muted)' }}>\n · {d.source}\n </span>\n )}\n </Inline>\n {d.body && (\n <span style={{ fontSize: 'var(--fs-12)', color: 'var(--fg-muted)' }}>\n {d.body.length > 160 ? `${d.body.slice(0, 160)}…` : d.body}\n </span>\n )}\n </Stack>\n <Inline gap={1}>\n <Button\n variant=\"primary\"\n onClick={() => void decide(d.id, 'approve')}\n data-testid={`dialog-approve-${d.id}`}\n aria-label={`Approve ${d.id}`}\n >\n <Check size={14} aria-hidden /> Approve\n </Button>\n <Button\n variant=\"ghost\"\n onClick={() => void decide(d.id, 'skip')}\n data-testid={`dialog-skip-${d.id}`}\n aria-label={`Skip ${d.id}`}\n >\n <SkipForward size={14} aria-hidden /> Skip\n </Button>\n <Button\n variant=\"ghost\"\n onClick={() => void decide(d.id, 'deny')}\n data-testid={`dialog-deny-${d.id}`}\n aria-label={`Deny ${d.id}`}\n >\n <X size={14} aria-hidden /> Deny\n </Button>\n <Button\n variant=\"ghost\"\n onClick={() => setConfirmDelete((cur) => (cur === d.id ? null : d.id))}\n data-testid={`dialog-dismiss-${d.id}`}\n aria-label={`Dismiss ${d.id}`}\n >\n <Trash2 size={14} aria-hidden />\n </Button>\n </Inline>\n </Inline>\n {isConfirming && (\n <Inline gap={1} style={{ marginTop: 'var(--space-1)' }}>\n <Button variant=\"danger\" onClick={() => void drop(d.id)} data-testid={`dialog-confirm-dismiss-${d.id}`}>\n <Trash2 size={14} aria-hidden /> Confirm\n </Button>\n <Button variant=\"ghost\" onClick={() => setConfirmDelete(null)}>Cancel</Button>\n </Inline>\n )}\n </div>\n );\n })}\n </Stack>\n )}\n </CardBody>\n </Card>\n </Stack>\n );\n}"],"names":["SkipForward","createLucideIcon","DialogsView","payload","useFetch","confirmDelete","setConfirmDelete","useState","error","setError","refresh","useCallback","useWsMessage","drop","id","fetchJson","err","FetchError","decide","verdict","dialogs","useMemo","_a","jsxs","Stack","jsx","ViewHeader","Inline","Button","RefreshCcw","ListHeader","Card","CardBody","Skeleton","ErrorState","EmptyState","MessageSquare","d","isConfirming","Check","X","cur","Trash2"],"mappings":"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","x_google_ignoreList":[0]}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import{r as d,j as e}from"./cmdk-
|
|
1
|
+
import{r as d,j as e}from"./cmdk-C3F6LD6N.js";import{d as C,u as m,S as i,I as c,B as x,h,H as z,b as E,J as T,G as w,i as R,F as b}from"./main-BURAlktW.js";import{V as I}from"./ViewHeader-C-t1U2cQ.js";import{C as j,b as y}from"./Card-BtsmkhJa.js";import{E as N}from"./EmptyState-DjKtY1Qi.js";import{E as B}from"./ErrorState-CBJbEQ8B.js";import{R as F}from"./refresh-cw-DwlP59en.js";import{T as H}from"./triangle-alert-B2oHbmoh.js";import{C as A}from"./circle-check-DFB50ojt.js";import"./Alert-BZGk39mB.js";import"./circle-alert-Dz8lGfCZ.js";import"./refresh-ccw-DA8_IB9l.js";/**
|
|
2
2
|
* @license lucide-react v0.460.0 - ISC
|
|
3
3
|
*
|
|
4
4
|
* This source code is licensed under the ISC license.
|
|
5
5
|
* See the LICENSE file in the root directory of this source tree.
|
|
6
|
-
*/const D=C("CircleX",[["circle",{cx:"12",cy:"12",r:"10",key:"1mglay"}],["path",{d:"m15 9-6 6",key:"1uzhvr"}],["path",{d:"m9 9 6 6",key:"z0biqf"}]]),v={ok:A,warn:H,fail:D},O={ok:"success",warn:"warning",fail:"danger"};function M(){var p;const s=m("/api/doctor"),l=m("/api/doctor/health"),[k,u]=d.useState(null),[f,g]=d.useState(null);d.useEffect(()=>{const t=setInterval(()=>{l.refetch()},3e4);return()=>clearInterval(t)},[l]);const S=async t=>{u(t),g(null);try{await R("/api/doctor/check",{method:"POST",body:{checkName:t}}),s.refetch()}catch(r){g((r instanceof
|
|
6
|
+
*/const D=C("CircleX",[["circle",{cx:"12",cy:"12",r:"10",key:"1mglay"}],["path",{d:"m15 9-6 6",key:"1uzhvr"}],["path",{d:"m9 9 6 6",key:"z0biqf"}]]),v={ok:A,warn:H,fail:D},O={ok:"success",warn:"warning",fail:"danger"};function M(){var p;const s=m("/api/doctor"),l=m("/api/doctor/health"),[k,u]=d.useState(null),[f,g]=d.useState(null);d.useEffect(()=>{const t=setInterval(()=>{l.refetch()},3e4);return()=>clearInterval(t)},[l]);const S=async t=>{u(t),g(null);try{await R("/api/doctor/check",{method:"POST",body:{checkName:t}}),s.refetch()}catch(r){g((r instanceof b,r.message))}finally{u(null)}},n=l.data??((p=s.data)==null?void 0:p.health),o=(()=>{var r;const t=(r=s.data)==null?void 0:r.checks;return t?[...t.system??[],...t.config??[],...t.services??[]].filter(a=>typeof a.name=="string"&&typeof a.status=="string"&&typeof a.message=="string"):[]})();return e.jsxs(i,{gap:5,"data-testid":"doctor-view",children:[e.jsx(I,{title:"Doctor",description:"System diagnostics. Health poll every 30s; click any check to re-run.",actions:e.jsxs(c,{gap:2,align:"center",children:[f!==null&&e.jsx("span",{role:"alert",style:{color:"var(--danger)",fontSize:"var(--fs-12)"},children:f}),e.jsxs(x,{variant:"ghost",onClick:()=>void s.refetch(),"data-testid":"doctor-refresh",children:[e.jsx(F,{size:14,"aria-hidden":!0})," Refresh"]})]})}),n?e.jsx(j,{variant:"elevated",children:e.jsx(y,{children:e.jsxs(c,{align:"center",gap:3,children:[(()=>{const t=v[n.status];return e.jsx(t,{size:20,"aria-hidden":!0})})(),e.jsxs(i,{gap:0,children:[e.jsxs("strong",{style:{fontSize:"var(--fs-14)"},children:["Health: ",n.status.toUpperCase()]}),e.jsx("span",{style:{color:"var(--fg-muted)",fontSize:"var(--fs-12)"},children:n.issues.length===0?"No issues detected.":`${n.issues.length} issue${n.issues.length===1?"":"s"}`})]})]})})}):e.jsx(h,{style:{height:64}}),s.loading&&o.length===0?e.jsxs(i,{gap:2,children:[e.jsx(h,{style:{height:64}}),e.jsx(h,{style:{height:64}})]}):s.error&&o.length===0?e.jsx(B,{block:!0,title:"Couldn't run doctor",description:"The diagnostic snapshot failed. Retry to refetch.",error:s.error,onRetry:()=>void s.refetch(),testid:"doctor-error"}):o.length===0?e.jsx(N,{icon:e.jsx(z,{size:32,"aria-hidden":!0}),title:"No checks yet",description:"The Doctor snapshot returned no checks."}):e.jsx(i,{gap:2,children:o.map(t=>{const r=v[t.status],a=k===t.name;return e.jsx(j,{variant:"default",children:e.jsx(y,{children:e.jsxs(c,{align:"center",justify:"between",gap:3,children:[e.jsxs(i,{gap:1,style:{flex:1,minWidth:0},children:[e.jsxs(c,{align:"center",gap:2,children:[e.jsx(r,{size:14,"aria-hidden":!0}),e.jsx("strong",{children:t.name}),e.jsx(E,{tone:O[t.status],children:t.status})]}),e.jsx("span",{style:{color:"var(--fg-muted)",fontSize:"var(--fs-12)"},children:t.message}),t.error&&e.jsx("span",{style:{color:"var(--danger)",fontSize:"var(--fs-12)",fontFamily:"var(--font-mono)"},children:t.error})]}),e.jsxs(x,{variant:"ghost",onClick:()=>void S(t.name),disabled:a,"data-testid":`doctor-run-${t.name}`,children:[a?e.jsx(T,{size:12,className:"animate-spin","aria-hidden":!0}):e.jsx(w,{size:12,"aria-hidden":!0}),a?"Running…":"Re-run"]})]})})},t.name)})})]})}export{M as DoctorView};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DoctorView-BQwqvMAh.js","sources":["../../../node_modules/lucide-react/dist/esm/icons/circle-x.js","../../src/web/v8/views/Doctor/DoctorView.tsx"],"sourcesContent":["/**\n * @license lucide-react v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst CircleX = createLucideIcon(\"CircleX\", [\n [\"circle\", { cx: \"12\", cy: \"12\", r: \"10\", key: \"1mglay\" }],\n [\"path\", { d: \"m15 9-6 6\", key: \"1uzhvr\" }],\n [\"path\", { d: \"m9 9 6 6\", key: \"z0biqf\" }]\n]);\n\nexport { CircleX as default };\n//# sourceMappingURL=circle-x.js.map\n","import { useCallback, useEffect, useState } from 'react';\nimport { Stethoscope, RefreshCw, ShieldCheck, AlertTriangle, XCircle, CheckCircle2, Loader2 } from 'lucide-react';\nimport { Stack } from '../../ui/primitives/Stack.js';\nimport { Inline } from '../../ui/primitives/Inline.js';\nimport { ViewHeader } from '../../ui/data/ViewHeader.js';\nimport { Card, CardBody } from '../../ui/data/Card.js';\nimport { Badge } from '../../ui/data/Badge.js';\nimport { Button } from '../../ui/controls/Button.js';\nimport { Skeleton } from '../../ui/feedback/Skeleton.js';\nimport { EmptyState } from '../../ui/feedback/EmptyState.js';\nimport { ErrorState } from '../../ui/feedback/ErrorState.js';\nimport { useFetch } from '../../data/useFetch.js';\nimport { fetchJson, FetchError } from '../../data/fetcher.js';\nimport type { LucideIcon } from 'lucide-react';\n\n/**\n * DoctorView — Sprint S35. Health rollup + per-check triggers.\n */\n\ntype Status = 'ok' | 'warn' | 'fail';\n\ninterface CheckResult {\n name: string;\n status: Status;\n message: string;\n error?: string;\n}\n\ninterface CheckGroup {\n name?: string;\n status?: Status;\n message?: string;\n error?: string;\n}\n\ninterface HealthRollup {\n status: Status;\n issues: Array<{ name: string; status: Status; message: string }>;\n}\n\ninterface DoctorSnapshot {\n health: HealthRollup;\n checks: { system?: CheckGroup[]; config?: CheckGroup[]; services?: CheckGroup[] };\n recentErrors?: unknown[];\n}\n\nconst STATUS_ICON: Record<Status, LucideIcon> = {\n ok: CheckCircle2,\n warn: AlertTriangle,\n fail: XCircle,\n};\n\nconst STATUS_TONE = {\n ok: 'success',\n warn: 'warning',\n fail: 'danger',\n} as const;\n\nexport function DoctorView(): JSX.Element {\n const snap = useFetch<DoctorSnapshot>('/api/doctor');\n const health = useFetch<HealthRollup>('/api/doctor/health');\n const [running, setRunning] = useState<string | null>(null);\n const [error, setError] = useState<string | null>(null);\n\n // Re-poll health every 30s for a live rollup.\n useEffect(() => {\n const id = setInterval(() => { void health.refetch(); }, 30_000);\n return () => clearInterval(id);\n }, [health]);\n\n const runCheck = async (name: string): Promise<void> => {\n setRunning(name);\n setError(null);\n try {\n await fetchJson('/api/doctor/check', { method: 'POST', body: { checkName: name } });\n void snap.refetch();\n } catch (err) {\n setError(err instanceof FetchError ? err.message : (err as Error).message);\n } finally {\n setRunning(null);\n }\n };\n\n const rollup = health.data ?? snap.data?.health;\n const checks: CheckResult[] = (() => {\n const g = snap.data?.checks;\n if (!g) return [];\n return [...(g.system ?? []), ...(g.config ?? []), ...(g.services ?? [])]\n .filter((c): c is CheckResult =>\n typeof c.name === 'string' && typeof c.status === 'string' && typeof c.message === 'string'\n );\n })();\n\n return (\n <Stack gap={5} data-testid=\"doctor-view\">\n <ViewHeader\n title=\"Doctor\"\n description=\"System diagnostics. Health poll every 30s; click any check to re-run.\"\n actions={\n <Inline gap={2} align=\"center\">\n {error !== null && <span role=\"alert\" style={{ color: 'var(--danger)', fontSize: 'var(--fs-12)' }}>{error}</span>}\n <Button variant=\"ghost\" onClick={() => void snap.refetch()} data-testid=\"doctor-refresh\">\n <RefreshCw size={14} aria-hidden /> Refresh\n </Button>\n </Inline>\n }\n />\n\n {rollup ? (\n <Card variant=\"elevated\">\n <CardBody>\n <Inline align=\"center\" gap={3}>\n {(() => {\n const Icon = STATUS_ICON[rollup.status];\n return <Icon size={20} aria-hidden />;\n })()}\n <Stack gap={0}>\n <strong style={{ fontSize: 'var(--fs-14)' }}>Health: {rollup.status.toUpperCase()}</strong>\n <span style={{ color: 'var(--fg-muted)', fontSize: 'var(--fs-12)' }}>\n {rollup.issues.length === 0 ? 'No issues detected.' : `${rollup.issues.length} issue${rollup.issues.length === 1 ? '' : 's'}`}\n </span>\n </Stack>\n </Inline>\n </CardBody>\n </Card>\n ) : (\n <Skeleton style={{ height: 64 }} />\n )}\n\n {snap.loading && checks.length === 0 ? (\n <Stack gap={2}>\n <Skeleton style={{ height: 64 }} />\n <Skeleton style={{ height: 64 }} />\n </Stack>\n ) : snap.error && checks.length === 0 ? (\n <ErrorState\n block\n title=\"Couldn't run doctor\"\n description=\"The diagnostic snapshot failed. Retry to refetch.\"\n error={snap.error}\n onRetry={() => void snap.refetch()}\n testid=\"doctor-error\"\n />\n ) : checks.length === 0 ? (\n <EmptyState\n icon={<Stethoscope size={32} aria-hidden />}\n title=\"No checks yet\"\n description=\"The Doctor snapshot returned no checks.\"\n />\n ) : (\n <Stack gap={2}>\n {checks.map((c) => {\n const Icon = STATUS_ICON[c.status];\n const busy = running === c.name;\n return (\n <Card key={c.name} variant=\"default\">\n <CardBody>\n <Inline align=\"center\" justify=\"between\" gap={3}>\n <Stack gap={1} style={{ flex: 1, minWidth: 0 }}>\n <Inline align=\"center\" gap={2}>\n <Icon size={14} aria-hidden />\n <strong>{c.name}</strong>\n <Badge tone={STATUS_TONE[c.status]}>{c.status}</Badge>\n </Inline>\n <span style={{ color: 'var(--fg-muted)', fontSize: 'var(--fs-12)' }}>{c.message}</span>\n {c.error && <span style={{ color: 'var(--danger)', fontSize: 'var(--fs-12)', fontFamily: 'var(--font-mono)' }}>{c.error}</span>}\n </Stack>\n <Button variant=\"ghost\" onClick={() => void runCheck(c.name)} disabled={busy} data-testid={`doctor-run-${c.name}`}>\n {busy ? <Loader2 size={12} className=\"animate-spin\" aria-hidden /> : <ShieldCheck size={12} aria-hidden />}\n {busy ? 'Running…' : 'Re-run'}\n </Button>\n </Inline>\n </CardBody>\n </Card>\n );\n })}\n </Stack>\n )}\n </Stack>\n );\n}"],"names":["CircleX","createLucideIcon","STATUS_ICON","CheckCircle2","AlertTriangle","XCircle","STATUS_TONE","DoctorView","snap","useFetch","health","running","setRunning","useState","error","setError","useEffect","id","runCheck","name","fetchJson","err","FetchError","rollup","_a","checks","g","c","jsxs","Stack","jsx","ViewHeader","Inline","Button","RefreshCw","Card","CardBody","Icon","Skeleton","ErrorState","EmptyState","Stethoscope","busy","Badge","Loader2","ShieldCheck"],"mappings":"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","x_google_ignoreList":[0]}
|
|
1
|
+
{"version":3,"file":"DoctorView-DepBdQGR.js","sources":["../../../node_modules/lucide-react/dist/esm/icons/circle-x.js","../../src/web/v8/views/Doctor/DoctorView.tsx"],"sourcesContent":["/**\n * @license lucide-react v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst CircleX = createLucideIcon(\"CircleX\", [\n [\"circle\", { cx: \"12\", cy: \"12\", r: \"10\", key: \"1mglay\" }],\n [\"path\", { d: \"m15 9-6 6\", key: \"1uzhvr\" }],\n [\"path\", { d: \"m9 9 6 6\", key: \"z0biqf\" }]\n]);\n\nexport { CircleX as default };\n//# sourceMappingURL=circle-x.js.map\n","import { useCallback, useEffect, useState } from 'react';\nimport { Stethoscope, RefreshCw, ShieldCheck, AlertTriangle, XCircle, CheckCircle2, Loader2 } from 'lucide-react';\nimport { Stack } from '../../ui/primitives/Stack.js';\nimport { Inline } from '../../ui/primitives/Inline.js';\nimport { ViewHeader } from '../../ui/data/ViewHeader.js';\nimport { Card, CardBody } from '../../ui/data/Card.js';\nimport { Badge } from '../../ui/data/Badge.js';\nimport { Button } from '../../ui/controls/Button.js';\nimport { Skeleton } from '../../ui/feedback/Skeleton.js';\nimport { EmptyState } from '../../ui/feedback/EmptyState.js';\nimport { ErrorState } from '../../ui/feedback/ErrorState.js';\nimport { useFetch } from '../../data/useFetch.js';\nimport { fetchJson, FetchError } from '../../data/fetcher.js';\nimport type { LucideIcon } from 'lucide-react';\n\n/**\n * DoctorView — Sprint S35. Health rollup + per-check triggers.\n */\n\ntype Status = 'ok' | 'warn' | 'fail';\n\ninterface CheckResult {\n name: string;\n status: Status;\n message: string;\n error?: string;\n}\n\ninterface CheckGroup {\n name?: string;\n status?: Status;\n message?: string;\n error?: string;\n}\n\ninterface HealthRollup {\n status: Status;\n issues: Array<{ name: string; status: Status; message: string }>;\n}\n\ninterface DoctorSnapshot {\n health: HealthRollup;\n checks: { system?: CheckGroup[]; config?: CheckGroup[]; services?: CheckGroup[] };\n recentErrors?: unknown[];\n}\n\nconst STATUS_ICON: Record<Status, LucideIcon> = {\n ok: CheckCircle2,\n warn: AlertTriangle,\n fail: XCircle,\n};\n\nconst STATUS_TONE = {\n ok: 'success',\n warn: 'warning',\n fail: 'danger',\n} as const;\n\nexport function DoctorView(): JSX.Element {\n const snap = useFetch<DoctorSnapshot>('/api/doctor');\n const health = useFetch<HealthRollup>('/api/doctor/health');\n const [running, setRunning] = useState<string | null>(null);\n const [error, setError] = useState<string | null>(null);\n\n // Re-poll health every 30s for a live rollup.\n useEffect(() => {\n const id = setInterval(() => { void health.refetch(); }, 30_000);\n return () => clearInterval(id);\n }, [health]);\n\n const runCheck = async (name: string): Promise<void> => {\n setRunning(name);\n setError(null);\n try {\n await fetchJson('/api/doctor/check', { method: 'POST', body: { checkName: name } });\n void snap.refetch();\n } catch (err) {\n setError(err instanceof FetchError ? err.message : (err as Error).message);\n } finally {\n setRunning(null);\n }\n };\n\n const rollup = health.data ?? snap.data?.health;\n const checks: CheckResult[] = (() => {\n const g = snap.data?.checks;\n if (!g) return [];\n return [...(g.system ?? []), ...(g.config ?? []), ...(g.services ?? [])]\n .filter((c): c is CheckResult =>\n typeof c.name === 'string' && typeof c.status === 'string' && typeof c.message === 'string'\n );\n })();\n\n return (\n <Stack gap={5} data-testid=\"doctor-view\">\n <ViewHeader\n title=\"Doctor\"\n description=\"System diagnostics. Health poll every 30s; click any check to re-run.\"\n actions={\n <Inline gap={2} align=\"center\">\n {error !== null && <span role=\"alert\" style={{ color: 'var(--danger)', fontSize: 'var(--fs-12)' }}>{error}</span>}\n <Button variant=\"ghost\" onClick={() => void snap.refetch()} data-testid=\"doctor-refresh\">\n <RefreshCw size={14} aria-hidden /> Refresh\n </Button>\n </Inline>\n }\n />\n\n {rollup ? (\n <Card variant=\"elevated\">\n <CardBody>\n <Inline align=\"center\" gap={3}>\n {(() => {\n const Icon = STATUS_ICON[rollup.status];\n return <Icon size={20} aria-hidden />;\n })()}\n <Stack gap={0}>\n <strong style={{ fontSize: 'var(--fs-14)' }}>Health: {rollup.status.toUpperCase()}</strong>\n <span style={{ color: 'var(--fg-muted)', fontSize: 'var(--fs-12)' }}>\n {rollup.issues.length === 0 ? 'No issues detected.' : `${rollup.issues.length} issue${rollup.issues.length === 1 ? '' : 's'}`}\n </span>\n </Stack>\n </Inline>\n </CardBody>\n </Card>\n ) : (\n <Skeleton style={{ height: 64 }} />\n )}\n\n {snap.loading && checks.length === 0 ? (\n <Stack gap={2}>\n <Skeleton style={{ height: 64 }} />\n <Skeleton style={{ height: 64 }} />\n </Stack>\n ) : snap.error && checks.length === 0 ? (\n <ErrorState\n block\n title=\"Couldn't run doctor\"\n description=\"The diagnostic snapshot failed. Retry to refetch.\"\n error={snap.error}\n onRetry={() => void snap.refetch()}\n testid=\"doctor-error\"\n />\n ) : checks.length === 0 ? (\n <EmptyState\n icon={<Stethoscope size={32} aria-hidden />}\n title=\"No checks yet\"\n description=\"The Doctor snapshot returned no checks.\"\n />\n ) : (\n <Stack gap={2}>\n {checks.map((c) => {\n const Icon = STATUS_ICON[c.status];\n const busy = running === c.name;\n return (\n <Card key={c.name} variant=\"default\">\n <CardBody>\n <Inline align=\"center\" justify=\"between\" gap={3}>\n <Stack gap={1} style={{ flex: 1, minWidth: 0 }}>\n <Inline align=\"center\" gap={2}>\n <Icon size={14} aria-hidden />\n <strong>{c.name}</strong>\n <Badge tone={STATUS_TONE[c.status]}>{c.status}</Badge>\n </Inline>\n <span style={{ color: 'var(--fg-muted)', fontSize: 'var(--fs-12)' }}>{c.message}</span>\n {c.error && <span style={{ color: 'var(--danger)', fontSize: 'var(--fs-12)', fontFamily: 'var(--font-mono)' }}>{c.error}</span>}\n </Stack>\n <Button variant=\"ghost\" onClick={() => void runCheck(c.name)} disabled={busy} data-testid={`doctor-run-${c.name}`}>\n {busy ? <Loader2 size={12} className=\"animate-spin\" aria-hidden /> : <ShieldCheck size={12} aria-hidden />}\n {busy ? 'Running…' : 'Re-run'}\n </Button>\n </Inline>\n </CardBody>\n </Card>\n );\n })}\n </Stack>\n )}\n </Stack>\n );\n}"],"names":["CircleX","createLucideIcon","STATUS_ICON","CheckCircle2","AlertTriangle","XCircle","STATUS_TONE","DoctorView","snap","useFetch","health","running","setRunning","useState","error","setError","useEffect","id","runCheck","name","fetchJson","err","FetchError","rollup","_a","checks","g","c","jsxs","Stack","jsx","ViewHeader","Inline","Button","RefreshCw","Card","CardBody","Icon","Skeleton","ErrorState","EmptyState","Stethoscope","busy","Badge","Loader2","ShieldCheck"],"mappings":"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","x_google_ignoreList":[0]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{r as l,j as e}from"./cmdk-
|
|
1
|
+
import{r as l,j as e}from"./cmdk-C3F6LD6N.js";import{g as d}from"./main-BURAlktW.js";const m=l.forwardRef(function(r,a){const{icon:t,title:n,description:s,action:i,className:o,...c}=r;return e.jsxs("div",{ref:a,className:d("v8-empty-state",o),style:{display:"flex",flexDirection:"column",alignItems:"center",justifyContent:"center",gap:"var(--space-3)",padding:"var(--space-12) var(--space-6)",textAlign:"center",color:"var(--fg-muted)"},...c,children:[t!==void 0&&e.jsx("div",{style:{color:"var(--fg-subtle)",display:"inline-flex"},children:t}),e.jsx("div",{style:{fontSize:"var(--fs-16)",fontWeight:600,color:"var(--fg)"},children:n}),s!==void 0&&e.jsx("div",{style:{fontSize:"var(--fs-13)",maxWidth:480},children:s}),i!==void 0&&e.jsx("div",{style:{marginTop:"var(--space-2)"},children:i})]})});export{m as E};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"EmptyState-
|
|
1
|
+
{"version":3,"file":"EmptyState-DjKtY1Qi.js","sources":["../../src/web/v8/ui/feedback/EmptyState.tsx"],"sourcesContent":["import { forwardRef, type HTMLAttributes, type ReactNode } from 'react';\nimport { cx } from '../utils/cx.js';\n\n/**\n * EmptyState — placeholder for empty lists / zero-data views.\n *\n * Use when a view has no rows. Never use a spinner; the data is\n * genuinely empty.\n */\nexport interface EmptyStateProps extends Omit<HTMLAttributes<HTMLDivElement>, 'title'> {\n icon?: ReactNode;\n title: ReactNode;\n description?: ReactNode;\n action?: ReactNode;\n}\n\nexport const EmptyState = forwardRef<HTMLDivElement, EmptyStateProps>(function EmptyState(\n props,\n ref,\n) {\n const { icon, title, description, action, className, ...rest } = props;\n return (\n <div\n ref={ref}\n className={cx('v8-empty-state', className)}\n style={{\n display: 'flex',\n flexDirection: 'column',\n alignItems: 'center',\n justifyContent: 'center',\n gap: 'var(--space-3)',\n padding: 'var(--space-12) var(--space-6)',\n textAlign: 'center',\n color: 'var(--fg-muted)',\n }}\n {...rest}\n >\n {icon !== undefined && (\n <div style={{ color: 'var(--fg-subtle)', display: 'inline-flex' }}>{icon}</div>\n )}\n <div style={{ fontSize: 'var(--fs-16)', fontWeight: 600, color: 'var(--fg)' }}>{title}</div>\n {description !== undefined && (\n <div style={{ fontSize: 'var(--fs-13)', maxWidth: 480 }}>{description}</div>\n )}\n {action !== undefined && <div style={{ marginTop: 'var(--space-2)' }}>{action}</div>}\n </div>\n );\n});"],"names":["EmptyState","forwardRef","props","ref","icon","title","description","action","className","rest","jsxs","cx","jsx"],"mappings":"qFAgBO,MAAMA,EAAaC,EAAAA,WAA4C,SACpEC,EACAC,EACA,CACA,KAAM,CAAE,KAAAC,EAAM,MAAAC,EAAO,YAAAC,EAAa,OAAAC,EAAQ,UAAAC,EAAW,GAAGC,GAASP,EACjE,OACEQ,EAAAA,KAAC,MAAA,CACC,IAAAP,EACA,UAAWQ,EAAG,iBAAkBH,CAAS,EACzC,MAAO,CACL,QAAS,OACT,cAAe,SACf,WAAY,SACZ,eAAgB,SAChB,IAAK,iBACL,QAAS,iCACT,UAAW,SACX,MAAO,iBAAA,EAER,GAAGC,EAEH,SAAA,CAAAL,IAAS,QACRQ,EAAAA,IAAC,MAAA,CAAI,MAAO,CAAE,MAAO,mBAAoB,QAAS,aAAA,EAAkB,SAAAR,CAAA,CAAK,EAE3EQ,EAAAA,IAAC,MAAA,CAAI,MAAO,CAAE,SAAU,eAAgB,WAAY,IAAK,MAAO,WAAA,EAAgB,SAAAP,CAAA,CAAM,EACrFC,IAAgB,QACfM,EAAAA,IAAC,MAAA,CAAI,MAAO,CAAE,SAAU,eAAgB,SAAU,GAAA,EAAQ,SAAAN,CAAA,CAAY,EAEvEC,IAAW,QAAaK,MAAC,MAAA,CAAI,MAAO,CAAE,UAAW,gBAAA,EAAqB,SAAAL,CAAA,CAAO,CAAA,CAAA,CAAA,CAGpF,CAAC"}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import{r as s,j as e}from"./cmdk-
|
|
1
|
+
import{r as s,j as e}from"./cmdk-C3F6LD6N.js";import{d as O,u as V,S as p,I as f,B as n,h as I,V as P,N as D,i as y,F as k}from"./main-BURAlktW.js";import{V as Z}from"./ViewHeader-C-t1U2cQ.js";import{L as M}from"./ListHeader-CM8QoIWG.js";import{C as N,b as _}from"./Card-BtsmkhJa.js";import{I as A}from"./Input-h_nSOtwm.js";import{S as w,a as E,b as R}from"./Sheet-B-CMP9-_.js";import{E as L}from"./EmptyState-DjKtY1Qi.js";import{D as U}from"./download-BvJddD8D.js";import{R as q}from"./refresh-ccw-DA8_IB9l.js";import{P as H}from"./plus-Cm6-fo14.js";import{P as K}from"./pencil-DAwM-CC3.js";import{T as J}from"./trash-2-D6qePV_q.js";/**
|
|
2
2
|
* @license lucide-react v0.460.0 - ISC
|
|
3
3
|
*
|
|
4
4
|
* This source code is licensed under the ISC license.
|
|
5
5
|
* See the LICENSE file in the root directory of this source tree.
|
|
6
|
-
*/const W=O("FileUp",[["path",{d:"M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z",key:"1rqfz7"}],["path",{d:"M14 2v4a2 2 0 0 0 2 2h4",key:"tnqrlb"}],["path",{d:"M12 12v6",key:"3ahymv"}],["path",{d:"m15 15-3-3-3 3",key:"15xj92"}]]);function ce(){const d=V("/api/env-vars"),[g,c]=s.useState(!1),[v,r]=s.useState(null),[m,i]=s.useState(!1),[u,l]=s.useState(null),[x,h]=s.useState(null),[b,C]=s.useState(null),[o,$]=s.useState(null),S=s.useMemo(()=>d.data??[],[d.data]),j=s.useCallback(()=>{d.refetch()},[d]),
|
|
6
|
+
*/const W=O("FileUp",[["path",{d:"M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z",key:"1rqfz7"}],["path",{d:"M14 2v4a2 2 0 0 0 2 2h4",key:"tnqrlb"}],["path",{d:"M12 12v6",key:"3ahymv"}],["path",{d:"m15 15-3-3-3 3",key:"15xj92"}]]);function ce(){const d=V("/api/env-vars"),[g,c]=s.useState(!1),[v,r]=s.useState(null),[m,i]=s.useState(!1),[u,l]=s.useState(null),[x,h]=s.useState(null),[b,C]=s.useState(null),[o,$]=s.useState(null),S=s.useMemo(()=>d.data??[],[d.data]),j=s.useCallback(()=>{d.refetch()},[d]),T=async a=>{C(a),h(null);try{const t=await y(`/api/env-vars/${encodeURIComponent(a)}/test`,{method:"POST"});$({name:a,ok:t.ok!==!1,message:t.message??(t.ok!==!1?"OK":"Failed")})}catch(t){const z=(t instanceof k,t.message);$({name:a,ok:!1,message:z})}finally{C(null)}},F=async a=>{h(null);try{await y(`/api/env-vars/${a}`,{method:"DELETE"}),l(null),j()}catch(t){h((t instanceof k,t.message))}};return e.jsxs(p,{gap:4,"data-testid":"env-vars-view",children:[e.jsx(Z,{title:"Env vars",description:"Runtime environment variables for the dashboard. Stored in ~/.config/bizar/env.json (mode 0600).",actions:e.jsxs(f,{align:"center",gap:2,children:[x!==null&&e.jsx("span",{role:"alert","data-testid":"env-vars-error",style:{color:"var(--danger)",fontSize:"var(--fs-12)"},children:x}),e.jsxs(n,{variant:"ghost",onClick:()=>{window.open("/api/env-vars/export","_blank")},"data-testid":"env-vars-export",children:[e.jsx(U,{size:14,"aria-hidden":!0})," Export"]}),e.jsxs(n,{variant:"ghost",onClick:()=>i(!0),"data-testid":"env-vars-bulk-import",children:[e.jsx(W,{size:14,"aria-hidden":!0})," Bulk import"]}),e.jsxs(n,{variant:"ghost",onClick:()=>void j(),"data-testid":"env-vars-refresh",children:[e.jsx(q,{size:14,"aria-hidden":!0})," Refresh"]}),e.jsxs(n,{variant:"primary",onClick:()=>c(!0),"data-testid":"env-vars-add",children:[e.jsx(H,{size:14,"aria-hidden":!0})," Add"]})]})}),e.jsx(M,{title:"Variables",count:S.length,testid:"env-vars-list-header"}),e.jsx(N,{variant:"default",children:e.jsx(_,{children:d.loading&&S.length===0?e.jsxs(p,{gap:2,children:[e.jsx(I,{style:{height:36}}),e.jsx(I,{style:{height:36}})]}):S.length===0?e.jsx(L,{icon:e.jsx(P,{size:28,"aria-hidden":!0}),title:"No env vars",description:"Add one or bulk-import a .env file."}):e.jsx(p,{gap:1,children:S.map(a=>{const t=u===a.name;return e.jsxs("div",{"data-testid":`env-var-row-${a.name}`,style:{padding:"var(--space-2)",borderRadius:"var(--radius-sm)",border:"1px solid var(--border)",background:"var(--surface-0)"},children:[e.jsxs(f,{align:"center",justify:"between",gap:2,children:[e.jsxs(p,{gap:0,style:{minWidth:0},children:[e.jsx("code",{style:{fontSize:"var(--fs-12)"},children:a.name}),e.jsx("code",{style:{fontSize:"var(--fs-12)",color:"var(--fg-muted)"},children:a.value}),a.source&&e.jsxs("span",{style:{fontSize:"var(--fs-11)",color:"var(--fg-subtle)"},children:["source: ",a.source," ",a.createdAt?`· ${a.createdAt}`:""]})]}),e.jsxs(f,{gap:1,children:[e.jsx(n,{variant:"ghost",onClick:()=>void T(a.name),disabled:b===a.name,"data-testid":`env-var-test-${a.name}`,"aria-label":`Test ${a.name}`,children:e.jsx(D,{size:14,"aria-hidden":!0})}),e.jsx(n,{variant:"ghost",onClick:()=>r(a.name),"data-testid":`env-var-edit-${a.name}`,"aria-label":`Edit ${a.name}`,children:e.jsx(K,{size:14,"aria-hidden":!0})}),e.jsx(n,{variant:"ghost",onClick:()=>l(z=>z===a.name?null:a.name),"data-testid":`env-var-delete-${a.name}`,"aria-label":`Delete ${a.name}`,children:e.jsx(J,{size:14,"aria-hidden":!0})})]})]}),t&&e.jsxs(f,{gap:1,style:{marginTop:"var(--space-1)"},children:[e.jsx(n,{variant:"danger",onClick:()=>void F(a.name),"data-testid":`env-var-confirm-delete-${a.name}`,children:"Confirm delete"}),e.jsx(n,{variant:"ghost",onClick:()=>l(null),"data-testid":`env-var-cancel-delete-${a.name}`,children:"Cancel"})]}),o!==null&&o.name===a.name&&e.jsxs("div",{"data-testid":`env-var-test-result-${a.name}`,style:{marginTop:"var(--space-1)",fontSize:"var(--fs-11)",color:o.ok?"var(--success)":"var(--danger)",fontFamily:"var(--font-mono)"},children:["test: ",o.message]})]},a.name)})})})}),e.jsx(w,{open:g,onOpenChange:c,children:e.jsx(E,{side:"right",title:"Add env var",description:"Must match /^BIZAR_[A-Z0-9_]+$/.",children:e.jsx(B,{mode:"add",onSubmit:async(a,t)=>{await y("/api/env-vars",{method:"POST",body:{name:a,value:t}}),c(!1),j()},onCancel:()=>c(!1)})})}),e.jsx(w,{open:v!==null,onOpenChange:a=>{a||r(null)},children:e.jsx(E,{side:"right",title:"Edit env var",description:v??"",children:v!==null&&e.jsx(B,{mode:"edit",initialName:v,onSubmit:async(a,t)=>{await y(`/api/env-vars/${a}`,{method:"PUT",body:{value:t}}),r(null),j()},onCancel:()=>r(null)})})}),e.jsx(w,{open:m,onOpenChange:i,children:e.jsx(E,{side:"right",title:"Bulk import",description:"Paste KEY=value lines (one per line, # comments ignored).",children:e.jsx(Y,{onSubmit:async a=>{await y("/api/env-vars/bulk-import",{method:"POST",body:{envContent:a}}),i(!1),j()},onCancel:()=>i(!1)})})})]})}function B({mode:d,initialName:g,onSubmit:c,onCancel:v}){const[r,m]=s.useState(g??""),[i,u]=s.useState(""),[l,x]=s.useState(!1),[h,b]=s.useState(null),C=async()=>{if(!(!r.trim()||!i||l)){x(!0),b(null);try{await c(r.trim(),i)}catch(o){b((o instanceof k,o.message))}finally{x(!1)}}};return e.jsxs(p,{gap:3,style:{padding:"var(--space-4)"},children:[e.jsxs("label",{style:{display:"flex",flexDirection:"column",gap:"var(--space-1)"},children:[e.jsx("span",{style:{fontSize:"var(--fs-12)",color:"var(--fg-muted)"},children:"Name"}),e.jsx(A,{value:r,readOnly:d==="edit","data-testid":"env-var-form-name",onChange:o=>m(o.target.value)})]}),e.jsxs("label",{style:{display:"flex",flexDirection:"column",gap:"var(--space-1)"},children:[e.jsx("span",{style:{fontSize:"var(--fs-12)",color:"var(--fg-muted)"},children:"Value"}),e.jsx(A,{type:"password",value:i,"data-testid":"env-var-form-value",onChange:o=>u(o.target.value)})]}),h!==null&&e.jsx("span",{role:"alert",style:{color:"var(--danger)",fontSize:"var(--fs-12)"},children:h}),e.jsxs(f,{justify:"end",gap:2,children:[e.jsx(R,{asChild:!0,children:e.jsx(n,{variant:"ghost",onClick:v,"data-testid":"env-var-form-cancel",children:"Cancel"})}),e.jsx(n,{variant:"primary",onClick:()=>void C(),disabled:l||!r.trim()||!i,"data-testid":"env-var-form-submit",children:d==="add"?"Add":"Save"})]})]})}function Y({onSubmit:d,onCancel:g}){const[c,v]=s.useState(""),[r,m]=s.useState(!1),[i,u]=s.useState(null);return e.jsxs(p,{gap:3,style:{padding:"var(--space-4)"},children:[e.jsx("textarea",{value:c,placeholder:`BIZAR_FOO=bar
|
|
7
7
|
BIZAR_BAZ=qux
|
|
8
|
-
# comment`,rows:12,"data-testid":"env-vars-bulk-input",onChange:l=>v(l.target.value),style:{background:"var(--surface-0)",border:"1px solid var(--border)",borderRadius:"var(--radius-md)",padding:"var(--space-2)",color:"var(--fg)",fontFamily:"var(--font-mono)",fontSize:"var(--fs-12)",resize:"vertical"}}),i!==null&&e.jsx("span",{role:"alert",style:{color:"var(--danger)",fontSize:"var(--fs-12)"},children:i}),e.jsxs(f,{justify:"end",gap:2,children:[e.jsx(
|
|
8
|
+
# comment`,rows:12,"data-testid":"env-vars-bulk-input",onChange:l=>v(l.target.value),style:{background:"var(--surface-0)",border:"1px solid var(--border)",borderRadius:"var(--radius-md)",padding:"var(--space-2)",color:"var(--fg)",fontFamily:"var(--font-mono)",fontSize:"var(--fs-12)",resize:"vertical"}}),i!==null&&e.jsx("span",{role:"alert",style:{color:"var(--danger)",fontSize:"var(--fs-12)"},children:i}),e.jsxs(f,{justify:"end",gap:2,children:[e.jsx(R,{asChild:!0,children:e.jsx(n,{variant:"ghost",onClick:g,children:"Cancel"})}),e.jsx(n,{variant:"primary",onClick:async()=>{m(!0),u(null);try{await d(c)}catch(l){u((l instanceof k,l.message))}finally{m(!1)}},disabled:r||c.trim()==="","data-testid":"env-vars-bulk-submit",children:r?"Importing…":"Import"})]})]})}export{ce as EnvVarsView};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"EnvVarsView-DX-3oGH-.js","sources":["../../../node_modules/lucide-react/dist/esm/icons/file-up.js","../../src/web/v8/views/EnvVars/EnvVarsView.tsx"],"sourcesContent":["/**\n * @license lucide-react v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst FileUp = createLucideIcon(\"FileUp\", [\n [\"path\", { d: \"M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z\", key: \"1rqfz7\" }],\n [\"path\", { d: \"M14 2v4a2 2 0 0 0 2 2h4\", key: \"tnqrlb\" }],\n [\"path\", { d: \"M12 12v6\", key: \"3ahymv\" }],\n [\"path\", { d: \"m15 15-3-3-3 3\", key: \"15xj92\" }]\n]);\n\nexport { FileUp as default };\n//# sourceMappingURL=file-up.js.map\n","/**\n * v8/views/EnvVars/EnvVarsView.tsx — Sprint S41, v9.3.0.\n *\n * List of env vars (masked values) with: per-row edit (Sheet),\n * per-row delete (inline confirm), Add Sheet, Bulk Import Sheet,\n * and Export trigger. Backed by /api/env-vars + /api/env-vars/grouped\n * + /api/env-vars/export + /api/env-vars/bulk-import.\n */\n\nimport { useCallback, useMemo, useState } from 'react';\nimport { Download, FileUp, FlaskConical, Pencil, Plus, RefreshCcw, Trash2, Variable } from 'lucide-react';\nimport { Stack } from '../../ui/primitives/Stack.js';\nimport { Inline } from '../../ui/primitives/Inline.js';\nimport { ViewHeader } from '../../ui/data/ViewHeader.js';\nimport { ListHeader } from '../../ui/data/ListHeader.js';\nimport { Card, CardBody } from '../../ui/data/Card.js';\nimport { Button } from '../../ui/controls/Button.js';\nimport { Input } from '../../ui/controls/Input.js';\nimport { Sheet, SheetClose, SheetContent } from '../../ui/feedback/Sheet.js';\nimport { Skeleton } from '../../ui/feedback/Skeleton.js';\nimport { EmptyState } from '../../ui/feedback/EmptyState.js';\nimport { useFetch } from '../../data/useFetch.js';\nimport { fetchJson, FetchError } from '../../data/fetcher.js';\n\ninterface EnvRow {\n name: string;\n value: string;\n createdAt?: string;\n source?: string;\n}\n\nexport function EnvVarsView(): JSX.Element {\n const payload = useFetch<EnvRow[]>('/api/env-vars');\n const [adding, setAdding] = useState<boolean>(false);\n const [editing, setEditing] = useState<string | null>(null);\n const [bulkImporting, setBulkImporting] = useState<boolean>(false);\n const [confirmDelete, setConfirmDelete] = useState<string | null>(null);\n const [error, setError] = useState<string | null>(null);\n const [testing, setTesting] = useState<string | null>(null);\n const [testResult, setTestResult] = useState<{ name: string; ok: boolean; message: string } | null>(null);\n\n const rows = useMemo<EnvRow[]>(() => payload.data ?? [], [payload.data]);\n\n const refresh = useCallback(() => { void payload.refetch(); }, [payload]);\n\n const runTest = async (name: string): Promise<void> => {\n setTesting(name);\n setError(null);\n try {\n const res = await fetchJson<{ ok?: boolean; status?: string; message?: string }>(`/api/env-vars/${encodeURIComponent(name)}/test`, { method: 'POST' });\n setTestResult({ name, ok: res.ok !== false, message: res.message ?? (res.ok !== false ? 'OK' : 'Failed') });\n } catch (err) {\n const msg = err instanceof FetchError ? err.message : (err as Error).message;\n setTestResult({ name, ok: false, message: msg });\n } finally {\n setTesting(null);\n }\n };\n\n const drop = async (name: string): Promise<void> => {\n setError(null);\n try {\n await fetchJson(`/api/env-vars/${name}`, { method: 'DELETE' });\n setConfirmDelete(null);\n refresh();\n } catch (err) {\n setError(err instanceof FetchError ? err.message : (err as Error).message);\n }\n };\n\n return (\n <Stack gap={4} data-testid=\"env-vars-view\">\n <ViewHeader\n title=\"Env vars\"\n description=\"Runtime environment variables for the dashboard. Stored in ~/.config/bizar/env.json (mode 0600).\"\n actions={\n <Inline align=\"center\" gap={2}>\n {error !== null && (\n <span role=\"alert\" data-testid=\"env-vars-error\" style={{ color: 'var(--danger)', fontSize: 'var(--fs-12)' }}>\n {error}\n </span>\n )}\n <Button variant=\"ghost\" onClick={() => { window.open('/api/env-vars/export', '_blank'); }} data-testid=\"env-vars-export\">\n <Download size={14} aria-hidden /> Export\n </Button>\n <Button variant=\"ghost\" onClick={() => setBulkImporting(true)} data-testid=\"env-vars-bulk-import\">\n <FileUp size={14} aria-hidden /> Bulk import\n </Button>\n <Button variant=\"ghost\" onClick={() => void refresh()} data-testid=\"env-vars-refresh\">\n <RefreshCcw size={14} aria-hidden /> Refresh\n </Button>\n <Button variant=\"primary\" onClick={() => setAdding(true)} data-testid=\"env-vars-add\">\n <Plus size={14} aria-hidden /> Add\n </Button>\n </Inline>\n }\n />\n <ListHeader title=\"Variables\" count={rows.length} testid=\"env-vars-list-header\" />\n\n <Card variant=\"default\">\n <CardBody>\n {payload.loading && rows.length === 0 ? (\n <Stack gap={2}>\n <Skeleton style={{ height: 36 }} />\n <Skeleton style={{ height: 36 }} />\n </Stack>\n ) : rows.length === 0 ? (\n <EmptyState\n icon={<Variable size={28} aria-hidden />}\n title=\"No env vars\"\n description=\"Add one or bulk-import a .env file.\"\n />\n ) : (\n <Stack gap={1}>\n {rows.map((r) => {\n const isConfirming = confirmDelete === r.name;\n return (\n <div\n key={r.name}\n data-testid={`env-var-row-${r.name}`}\n style={{\n padding: 'var(--space-2)',\n borderRadius: 'var(--radius-sm)',\n border: '1px solid var(--border)',\n background: 'var(--surface-0)',\n }}\n >\n <Inline align=\"center\" justify=\"between\" gap={2}>\n <Stack gap={0} style={{ minWidth: 0 }}>\n <code style={{ fontSize: 'var(--fs-12)' }}>{r.name}</code>\n <code style={{ fontSize: 'var(--fs-12)', color: 'var(--fg-muted)' }}>{r.value}</code>\n {r.source && (\n <span style={{ fontSize: 'var(--fs-11)', color: 'var(--fg-subtle)' }}>\n source: {r.source} {r.createdAt ? `· ${r.createdAt}` : ''}\n </span>\n )}\n </Stack>\n <Inline gap={1}>\n <Button\n variant=\"ghost\"\n onClick={() => void runTest(r.name)}\n disabled={testing === r.name}\n data-testid={`env-var-test-${r.name}`}\n aria-label={`Test ${r.name}`}\n >\n <FlaskConical size={14} aria-hidden />\n </Button>\n <Button variant=\"ghost\" onClick={() => setEditing(r.name)} data-testid={`env-var-edit-${r.name}`} aria-label={`Edit ${r.name}`}>\n <Pencil size={14} aria-hidden />\n </Button>\n <Button\n variant=\"ghost\"\n onClick={() => setConfirmDelete((cur) => (cur === r.name ? null : r.name))}\n data-testid={`env-var-delete-${r.name}`}\n aria-label={`Delete ${r.name}`}\n >\n <Trash2 size={14} aria-hidden />\n </Button>\n </Inline>\n </Inline>\n {isConfirming && (\n <Inline gap={1} style={{ marginTop: 'var(--space-1)' }}>\n <Button variant=\"danger\" onClick={() => void drop(r.name)} data-testid={`env-var-confirm-delete-${r.name}`}>\n Confirm delete\n </Button>\n <Button variant=\"ghost\" onClick={() => setConfirmDelete(null)} data-testid={`env-var-cancel-delete-${r.name}`}>\n Cancel\n </Button>\n </Inline>\n )}\n {testResult !== null && testResult.name === r.name && (\n <div\n data-testid={`env-var-test-result-${r.name}`}\n style={{\n marginTop: 'var(--space-1)',\n fontSize: 'var(--fs-11)',\n color: testResult.ok ? 'var(--success)' : 'var(--danger)',\n fontFamily: 'var(--font-mono)',\n }}\n >\n test: {testResult.message}\n </div>\n )}\n </div>\n );\n })}\n </Stack>\n )}\n </CardBody>\n </Card>\n\n <Sheet open={adding} onOpenChange={setAdding}>\n <SheetContent side=\"right\" title=\"Add env var\" description=\"Must match /^BIZAR_[A-Z0-9_]+$/.\">\n <AddEditForm\n mode=\"add\"\n onSubmit={async (name, value) => {\n await fetchJson('/api/env-vars', { method: 'POST', body: { name, value } });\n setAdding(false);\n refresh();\n }}\n onCancel={() => setAdding(false)}\n />\n </SheetContent>\n </Sheet>\n\n <Sheet open={editing !== null} onOpenChange={(open) => { if (!open) setEditing(null); }}>\n <SheetContent side=\"right\" title=\"Edit env var\" description={editing ?? ''}>\n {editing !== null && (\n <AddEditForm\n mode=\"edit\"\n initialName={editing}\n onSubmit={async (name, value) => {\n await fetchJson(`/api/env-vars/${name}`, { method: 'PUT', body: { value } });\n setEditing(null);\n refresh();\n }}\n onCancel={() => setEditing(null)}\n />\n )}\n </SheetContent>\n </Sheet>\n\n <Sheet open={bulkImporting} onOpenChange={setBulkImporting}>\n <SheetContent side=\"right\" title=\"Bulk import\" description=\"Paste KEY=value lines (one per line, # comments ignored).\">\n <BulkImportForm\n onSubmit={async (envContent) => {\n await fetchJson('/api/env-vars/bulk-import', {\n method: 'POST',\n body: { envContent },\n });\n setBulkImporting(false);\n refresh();\n }}\n onCancel={() => setBulkImporting(false)}\n />\n </SheetContent>\n </Sheet>\n </Stack>\n );\n}\n\nfunction AddEditForm({\n mode,\n initialName,\n onSubmit,\n onCancel,\n}: {\n mode: 'add' | 'edit';\n initialName?: string;\n onSubmit: (name: string, value: string) => Promise<void>;\n onCancel: () => void;\n}): JSX.Element {\n const [name, setName] = useState<string>(initialName ?? '');\n const [value, setValue] = useState<string>('');\n const [busy, setBusy] = useState<boolean>(false);\n const [error, setError] = useState<string | null>(null);\n\n const submit = async (): Promise<void> => {\n if (!name.trim() || !value || busy) return;\n setBusy(true);\n setError(null);\n try {\n await onSubmit(name.trim(), value);\n } catch (err) {\n setError(err instanceof FetchError ? err.message : (err as Error).message);\n } finally {\n setBusy(false);\n }\n };\n\n return (\n <Stack gap={3} style={{ padding: 'var(--space-4)' }}>\n <label style={{ display: 'flex', flexDirection: 'column', gap: 'var(--space-1)' }}>\n <span style={{ fontSize: 'var(--fs-12)', color: 'var(--fg-muted)' }}>Name</span>\n <Input\n value={name}\n readOnly={mode === 'edit'}\n data-testid=\"env-var-form-name\"\n onChange={(e) => setName((e.target as HTMLInputElement).value)}\n />\n </label>\n <label style={{ display: 'flex', flexDirection: 'column', gap: 'var(--space-1)' }}>\n <span style={{ fontSize: 'var(--fs-12)', color: 'var(--fg-muted)' }}>Value</span>\n <Input\n type=\"password\"\n value={value}\n data-testid=\"env-var-form-value\"\n onChange={(e) => setValue((e.target as HTMLInputElement).value)}\n />\n </label>\n {error !== null && (\n <span role=\"alert\" style={{ color: 'var(--danger)', fontSize: 'var(--fs-12)' }}>{error}</span>\n )}\n <Inline justify=\"end\" gap={2}>\n <SheetClose asChild>\n <Button variant=\"ghost\" onClick={onCancel} data-testid=\"env-var-form-cancel\">Cancel</Button>\n </SheetClose>\n <Button\n variant=\"primary\"\n onClick={() => void submit()}\n disabled={busy || !name.trim() || !value}\n data-testid=\"env-var-form-submit\"\n >\n {mode === 'add' ? 'Add' : 'Save'}\n </Button>\n </Inline>\n </Stack>\n );\n}\n\nfunction BulkImportForm({\n onSubmit,\n onCancel,\n}: {\n onSubmit: (envContent: string) => Promise<void>;\n onCancel: () => void;\n}): JSX.Element {\n const [content, setContent] = useState<string>('');\n const [busy, setBusy] = useState<boolean>(false);\n const [error, setError] = useState<string | null>(null);\n\n return (\n <Stack gap={3} style={{ padding: 'var(--space-4)' }}>\n <textarea\n value={content}\n placeholder={'BIZAR_FOO=bar\\nBIZAR_BAZ=qux\\n# comment'}\n rows={12}\n data-testid=\"env-vars-bulk-input\"\n onChange={(e) => setContent((e.target as HTMLTextAreaElement).value)}\n style={{\n background: 'var(--surface-0)',\n border: '1px solid var(--border)',\n borderRadius: 'var(--radius-md)',\n padding: 'var(--space-2)',\n color: 'var(--fg)',\n fontFamily: 'var(--font-mono)',\n fontSize: 'var(--fs-12)',\n resize: 'vertical',\n }}\n />\n {error !== null && (\n <span role=\"alert\" style={{ color: 'var(--danger)', fontSize: 'var(--fs-12)' }}>{error}</span>\n )}\n <Inline justify=\"end\" gap={2}>\n <SheetClose asChild>\n <Button variant=\"ghost\" onClick={onCancel}>Cancel</Button>\n </SheetClose>\n <Button\n variant=\"primary\"\n onClick={async () => {\n setBusy(true);\n setError(null);\n try { await onSubmit(content); }\n catch (err) { setError(err instanceof FetchError ? err.message : (err as Error).message); }\n finally { setBusy(false); }\n }}\n disabled={busy || content.trim() === ''}\n data-testid=\"env-vars-bulk-submit\"\n >\n {busy ? 'Importing…' : 'Import'}\n </Button>\n </Inline>\n </Stack>\n );\n}"],"names":["FileUp","createLucideIcon","EnvVarsView","payload","useFetch","adding","setAdding","useState","editing","setEditing","bulkImporting","setBulkImporting","confirmDelete","setConfirmDelete","error","setError","testing","setTesting","testResult","setTestResult","rows","useMemo","refresh","useCallback","runTest","name","res","fetchJson","err","msg","FetchError","drop","jsxs","Stack","jsx","ViewHeader","Inline","Button","Download","RefreshCcw","Plus","ListHeader","Card","CardBody","Skeleton","EmptyState","Variable","r","isConfirming","FlaskConical","Pencil","cur","Trash2","Sheet","SheetContent","AddEditForm","value","open","BulkImportForm","envContent","mode","initialName","onSubmit","onCancel","setName","setValue","busy","setBusy","submit","Input","e","SheetClose","content","setContent"],"mappings":"0nBAAA;AAAA;AAAA;AAAA;AAAA;AAAA,GASA,MAAMA,EAASC,EAAiB,SAAU,CACxC,CAAC,OAAQ,CAAE,EAAG,6DAA8D,IAAK,QAAQ,CAAE,EAC3F,CAAC,OAAQ,CAAE,EAAG,0BAA2B,IAAK,QAAQ,CAAE,EACxD,CAAC,OAAQ,CAAE,EAAG,WAAY,IAAK,QAAQ,CAAE,EACzC,CAAC,OAAQ,CAAE,EAAG,iBAAkB,IAAK,QAAQ,CAAE,CACjD,CAAC,ECiBM,SAASC,IAA2B,CACzC,MAAMC,EAAUC,EAAmB,eAAe,EAC5C,CAACC,EAAQC,CAAS,EAAIC,EAAAA,SAAkB,EAAK,EAC7C,CAACC,EAASC,CAAU,EAAIF,EAAAA,SAAwB,IAAI,EACpD,CAACG,EAAeC,CAAgB,EAAIJ,EAAAA,SAAkB,EAAK,EAC3D,CAACK,EAAeC,CAAgB,EAAIN,EAAAA,SAAwB,IAAI,EAChE,CAACO,EAAOC,CAAQ,EAAIR,EAAAA,SAAwB,IAAI,EAChD,CAACS,EAASC,CAAU,EAAIV,EAAAA,SAAwB,IAAI,EACpD,CAACW,EAAYC,CAAa,EAAIZ,EAAAA,SAAgE,IAAI,EAElGa,EAAOC,EAAAA,QAAkB,IAAMlB,EAAQ,MAAQ,GAAI,CAACA,EAAQ,IAAI,CAAC,EAEjEmB,EAAUC,EAAAA,YAAY,IAAM,CAAOpB,EAAQ,QAAA,CAAW,EAAG,CAACA,CAAO,CAAC,EAElEqB,EAAU,MAAOC,GAAgC,CACrDR,EAAWQ,CAAI,EACfV,EAAS,IAAI,EACb,GAAI,CACF,MAAMW,EAAM,MAAMC,EAA+D,iBAAiB,mBAAmBF,CAAI,CAAC,QAAS,CAAE,OAAQ,MAAA,CAAQ,EACrJN,EAAc,CAAE,KAAAM,EAAM,GAAIC,EAAI,KAAO,GAAO,QAASA,EAAI,UAAYA,EAAI,KAAO,GAAQ,KAAO,UAAW,CAC5G,OAASE,EAAK,CACZ,MAAMC,GAAMD,aAAeE,EAAaF,EAAI,SAC5CT,EAAc,CAAE,KAAAM,EAAM,GAAI,GAAO,QAASI,EAAK,CACjD,QAAA,CACEZ,EAAW,IAAI,CACjB,CACF,EAEMc,EAAO,MAAON,GAAgC,CAClDV,EAAS,IAAI,EACb,GAAI,CACF,MAAMY,EAAU,iBAAiBF,CAAI,GAAI,CAAE,OAAQ,SAAU,EAC7DZ,EAAiB,IAAI,EACrBS,EAAA,CACF,OAASM,EAAK,CACZb,GAASa,aAAeE,EAAaF,EAAI,QAAgC,CAC3E,CACF,EAEA,OACEI,EAAAA,KAACC,EAAA,CAAM,IAAK,EAAG,cAAY,gBACzB,SAAA,CAAAC,EAAAA,IAACC,EAAA,CACC,MAAM,WACN,YAAY,mGACZ,QACEH,EAAAA,KAACI,EAAA,CAAO,MAAM,SAAS,IAAK,EACzB,SAAA,CAAAtB,IAAU,MACToB,MAAC,OAAA,CAAK,KAAK,QAAQ,cAAY,iBAAiB,MAAO,CAAE,MAAO,gBAAiB,SAAU,gBACxF,SAAApB,EACH,EAEFkB,EAAAA,KAACK,EAAA,CAAO,QAAQ,QAAQ,QAAS,IAAM,CAAE,OAAO,KAAK,uBAAwB,QAAQ,CAAG,EAAG,cAAY,kBACrG,SAAA,CAAAH,EAAAA,IAACI,EAAA,CAAS,KAAM,GAAI,cAAW,GAAC,EAAE,SAAA,EACpC,EACAN,EAAAA,KAACK,EAAA,CAAO,QAAQ,QAAQ,QAAS,IAAM1B,EAAiB,EAAI,EAAG,cAAY,uBACzE,SAAA,CAAAuB,EAAAA,IAAClC,EAAA,CAAO,KAAM,GAAI,cAAW,GAAC,EAAE,cAAA,EAClC,EACAgC,EAAAA,KAACK,EAAA,CAAO,QAAQ,QAAQ,QAAS,IAAM,KAAKf,EAAA,EAAW,cAAY,mBACjE,SAAA,CAAAY,EAAAA,IAACK,EAAA,CAAW,KAAM,GAAI,cAAW,GAAC,EAAE,UAAA,EACtC,EACAP,EAAAA,KAACK,EAAA,CAAO,QAAQ,UAAU,QAAS,IAAM/B,EAAU,EAAI,EAAG,cAAY,eACpE,SAAA,CAAA4B,EAAAA,IAACM,EAAA,CAAK,KAAM,GAAI,cAAW,GAAC,EAAE,MAAA,CAAA,CAChC,CAAA,CAAA,CACF,CAAA,CAAA,EAGJN,MAACO,GAAW,MAAM,YAAY,MAAOrB,EAAK,OAAQ,OAAO,uBAAuB,EAEhFc,MAACQ,EAAA,CAAK,QAAQ,UACZ,eAACC,EAAA,CACE,SAAAxC,EAAQ,SAAWiB,EAAK,SAAW,EAClCY,EAAAA,KAACC,EAAA,CAAM,IAAK,EACV,SAAA,CAAAC,EAAAA,IAACU,EAAA,CAAS,MAAO,CAAE,OAAQ,IAAM,QAChCA,EAAA,CAAS,MAAO,CAAE,OAAQ,GAAG,CAAG,CAAA,CAAA,CACnC,EACExB,EAAK,SAAW,EAClBc,EAAAA,IAACW,EAAA,CACC,KAAMX,EAAAA,IAACY,EAAA,CAAS,KAAM,GAAI,cAAW,GAAC,EACtC,MAAM,cACN,YAAY,qCAAA,CAAA,QAGbb,EAAA,CAAM,IAAK,EACT,SAAAb,EAAK,IAAK2B,GAAM,CACf,MAAMC,EAAepC,IAAkBmC,EAAE,KACzC,OACEf,EAAAA,KAAC,MAAA,CAEC,cAAa,eAAee,EAAE,IAAI,GAClC,MAAO,CACL,QAAS,iBACT,aAAc,mBACd,OAAQ,0BACR,WAAY,kBAAA,EAGd,SAAA,CAAAf,OAACI,GAAO,MAAM,SAAS,QAAQ,UAAU,IAAK,EAC5C,SAAA,CAAAJ,OAACC,GAAM,IAAK,EAAG,MAAO,CAAE,SAAU,GAChC,SAAA,CAAAC,MAAC,QAAK,MAAO,CAAE,SAAU,cAAA,EAAmB,WAAE,KAAK,EACnDA,EAAAA,IAAC,OAAA,CAAK,MAAO,CAAE,SAAU,eAAgB,MAAO,iBAAA,EAAsB,SAAAa,EAAE,KAAA,CAAM,EAC7EA,EAAE,QACDf,OAAC,OAAA,CAAK,MAAO,CAAE,SAAU,eAAgB,MAAO,kBAAA,EAAsB,SAAA,CAAA,WAC3De,EAAE,OAAO,IAAEA,EAAE,UAAY,KAAKA,EAAE,SAAS,GAAK,EAAA,CAAA,CACzD,CAAA,EAEJ,EACAf,EAAAA,KAACI,EAAA,CAAO,IAAK,EACX,SAAA,CAAAF,EAAAA,IAACG,EAAA,CACC,QAAQ,QACR,QAAS,IAAM,KAAKb,EAAQuB,EAAE,IAAI,EAClC,SAAU/B,IAAY+B,EAAE,KACxB,cAAa,gBAAgBA,EAAE,IAAI,GACnC,aAAY,QAAQA,EAAE,IAAI,GAE1B,SAAAb,EAAAA,IAACe,EAAA,CAAa,KAAM,GAAI,cAAW,EAAA,CAAC,CAAA,CAAA,EAEtCf,EAAAA,IAACG,EAAA,CAAO,QAAQ,QAAQ,QAAS,IAAM5B,EAAWsC,EAAE,IAAI,EAAG,cAAa,gBAAgBA,EAAE,IAAI,GAAI,aAAY,QAAQA,EAAE,IAAI,GAC1H,SAAAb,EAAAA,IAACgB,EAAA,CAAO,KAAM,GAAI,cAAW,EAAA,CAAC,CAAA,CAChC,EACAhB,EAAAA,IAACG,EAAA,CACC,QAAQ,QACR,QAAS,IAAMxB,EAAkBsC,GAASA,IAAQJ,EAAE,KAAO,KAAOA,EAAE,IAAK,EACzE,cAAa,kBAAkBA,EAAE,IAAI,GACrC,aAAY,UAAUA,EAAE,IAAI,GAE5B,SAAAb,EAAAA,IAACkB,EAAA,CAAO,KAAM,GAAI,cAAW,EAAA,CAAC,CAAA,CAAA,CAChC,CAAA,CACF,CAAA,EACF,EACCJ,UACEZ,EAAA,CAAO,IAAK,EAAG,MAAO,CAAE,UAAW,gBAAA,EAClC,SAAA,CAAAF,EAAAA,IAACG,EAAA,CAAO,QAAQ,SAAS,QAAS,IAAM,KAAKN,EAAKgB,EAAE,IAAI,EAAG,cAAa,0BAA0BA,EAAE,IAAI,GAAI,SAAA,iBAE5G,EACAb,EAAAA,IAACG,EAAA,CAAO,QAAQ,QAAQ,QAAS,IAAMxB,EAAiB,IAAI,EAAG,cAAa,yBAAyBkC,EAAE,IAAI,GAAI,SAAA,QAAA,CAE/G,CAAA,EACF,EAED7B,IAAe,MAAQA,EAAW,OAAS6B,EAAE,MAC5Cf,EAAAA,KAAC,MAAA,CACC,cAAa,uBAAuBe,EAAE,IAAI,GAC1C,MAAO,CACL,UAAW,iBACX,SAAU,eACV,MAAO7B,EAAW,GAAK,iBAAmB,gBAC1C,WAAY,kBAAA,EAEf,SAAA,CAAA,SACQA,EAAW,OAAA,CAAA,CAAA,CACpB,CAAA,EA/DG6B,EAAE,IAAA,CAmEb,CAAC,CAAA,CACH,CAAA,CAEJ,EACF,EAEAb,EAAAA,IAACmB,EAAA,CAAM,KAAMhD,EAAQ,aAAcC,EACjC,SAAA4B,EAAAA,IAACoB,EAAA,CAAa,KAAK,QAAQ,MAAM,cAAc,YAAY,mCACzD,SAAApB,EAAAA,IAACqB,EAAA,CACC,KAAK,MACL,SAAU,MAAO9B,EAAM+B,IAAU,CAC/B,MAAM7B,EAAU,gBAAiB,CAAE,OAAQ,OAAQ,KAAM,CAAE,KAAAF,EAAM,MAAA+B,CAAA,EAAS,EAC1ElD,EAAU,EAAK,EACfgB,EAAA,CACF,EACA,SAAU,IAAMhB,EAAU,EAAK,CAAA,CAAA,EAEnC,CAAA,CACF,QAEC+C,EAAA,CAAM,KAAM7C,IAAY,KAAM,aAAeiD,GAAS,CAAOA,GAAMhD,EAAW,IAAI,CAAG,EACpF,SAAAyB,EAAAA,IAACoB,EAAA,CAAa,KAAK,QAAQ,MAAM,eAAe,YAAa9C,GAAW,GACrE,SAAAA,IAAY,MACX0B,EAAAA,IAACqB,EAAA,CACC,KAAK,OACL,YAAa/C,EACb,SAAU,MAAOiB,EAAM+B,IAAU,CAC/B,MAAM7B,EAAU,iBAAiBF,CAAI,GAAI,CAAE,OAAQ,MAAO,KAAM,CAAE,MAAA+B,CAAA,CAAM,CAAG,EAC3E/C,EAAW,IAAI,EACfa,EAAA,CACF,EACA,SAAU,IAAMb,EAAW,IAAI,CAAA,CAAA,EAGrC,CAAA,CACF,EAEAyB,EAAAA,IAACmB,EAAA,CAAM,KAAM3C,EAAe,aAAcC,EACxC,SAAAuB,EAAAA,IAACoB,EAAA,CAAa,KAAK,QAAQ,MAAM,cAAc,YAAY,4DACzD,SAAApB,EAAAA,IAACwB,EAAA,CACC,SAAU,MAAOC,GAAe,CAC9B,MAAMhC,EAAU,4BAA6B,CAC3C,OAAQ,OACR,KAAM,CAAE,WAAAgC,CAAA,CAAW,CACpB,EACDhD,EAAiB,EAAK,EACtBW,EAAA,CACF,EACA,SAAU,IAAMX,EAAiB,EAAK,CAAA,CAAA,EAE1C,CAAA,CACF,CAAA,EACF,CAEJ,CAEA,SAAS4C,EAAY,CACnB,KAAAK,EACA,YAAAC,EACA,SAAAC,EACA,SAAAC,CACF,EAKgB,CACd,KAAM,CAACtC,EAAMuC,CAAO,EAAIzD,EAAAA,SAAiBsD,GAAe,EAAE,EACpD,CAACL,EAAOS,CAAQ,EAAI1D,EAAAA,SAAiB,EAAE,EACvC,CAAC2D,EAAMC,CAAO,EAAI5D,EAAAA,SAAkB,EAAK,EACzC,CAACO,EAAOC,CAAQ,EAAIR,EAAAA,SAAwB,IAAI,EAEhD6D,EAAS,SAA2B,CACxC,GAAI,GAAC3C,EAAK,KAAA,GAAU,CAAC+B,GAASU,GAC9B,CAAAC,EAAQ,EAAI,EACZpD,EAAS,IAAI,EACb,GAAI,CACF,MAAM+C,EAASrC,EAAK,KAAA,EAAQ+B,CAAK,CACnC,OAAS5B,EAAK,CACZb,GAASa,aAAeE,EAAaF,EAAI,QAAgC,CAC3E,QAAA,CACEuC,EAAQ,EAAK,CACf,EACF,EAEA,OACEnC,EAAAA,KAACC,GAAM,IAAK,EAAG,MAAO,CAAE,QAAS,kBAC/B,SAAA,CAAAD,EAAAA,KAAC,QAAA,CAAM,MAAO,CAAE,QAAS,OAAQ,cAAe,SAAU,IAAK,gBAAA,EAC7D,SAAA,CAAAE,EAAAA,IAAC,OAAA,CAAK,MAAO,CAAE,SAAU,eAAgB,MAAO,iBAAA,EAAqB,SAAA,MAAA,CAAI,EACzEA,EAAAA,IAACmC,EAAA,CACC,MAAO5C,EACP,SAAUmC,IAAS,OACnB,cAAY,oBACZ,SAAWU,GAAMN,EAASM,EAAE,OAA4B,KAAK,CAAA,CAAA,CAC/D,EACF,EACAtC,EAAAA,KAAC,QAAA,CAAM,MAAO,CAAE,QAAS,OAAQ,cAAe,SAAU,IAAK,gBAAA,EAC7D,SAAA,CAAAE,EAAAA,IAAC,OAAA,CAAK,MAAO,CAAE,SAAU,eAAgB,MAAO,iBAAA,EAAqB,SAAA,OAAA,CAAK,EAC1EA,EAAAA,IAACmC,EAAA,CACC,KAAK,WACL,MAAAb,EACA,cAAY,qBACZ,SAAWc,GAAML,EAAUK,EAAE,OAA4B,KAAK,CAAA,CAAA,CAChE,EACF,EACCxD,IAAU,MACToB,EAAAA,IAAC,OAAA,CAAK,KAAK,QAAQ,MAAO,CAAE,MAAO,gBAAiB,SAAU,cAAA,EAAmB,SAAApB,EAAM,EAEzFkB,EAAAA,KAACI,EAAA,CAAO,QAAQ,MAAM,IAAK,EACzB,SAAA,CAAAF,EAAAA,IAACqC,EAAA,CAAW,QAAO,GACjB,SAAArC,EAAAA,IAACG,EAAA,CAAO,QAAQ,QAAQ,QAAS0B,EAAU,cAAY,sBAAsB,SAAA,QAAA,CAAM,EACrF,EACA7B,EAAAA,IAACG,EAAA,CACC,QAAQ,UACR,QAAS,IAAM,KAAK+B,EAAA,EACpB,SAAUF,GAAQ,CAACzC,EAAK,KAAA,GAAU,CAAC+B,EACnC,cAAY,sBAEX,SAAAI,IAAS,MAAQ,MAAQ,MAAA,CAAA,CAC5B,CAAA,CACF,CAAA,EACF,CAEJ,CAEA,SAASF,EAAe,CACtB,SAAAI,EACA,SAAAC,CACF,EAGgB,CACd,KAAM,CAACS,EAASC,CAAU,EAAIlE,EAAAA,SAAiB,EAAE,EAC3C,CAAC2D,EAAMC,CAAO,EAAI5D,EAAAA,SAAkB,EAAK,EACzC,CAACO,EAAOC,CAAQ,EAAIR,EAAAA,SAAwB,IAAI,EAEtD,OACEyB,EAAAA,KAACC,GAAM,IAAK,EAAG,MAAO,CAAE,QAAS,kBAC/B,SAAA,CAAAC,EAAAA,IAAC,WAAA,CACC,MAAOsC,EACP,YAAa;AAAA;AAAA,WACb,KAAM,GACN,cAAY,sBACZ,SAAWF,GAAMG,EAAYH,EAAE,OAA+B,KAAK,EACnE,MAAO,CACL,WAAY,mBACZ,OAAQ,0BACR,aAAc,mBACd,QAAS,iBACT,MAAO,YACP,WAAY,mBACZ,SAAU,eACV,OAAQ,UAAA,CACV,CAAA,EAEDxD,IAAU,MACToB,EAAAA,IAAC,OAAA,CAAK,KAAK,QAAQ,MAAO,CAAE,MAAO,gBAAiB,SAAU,cAAA,EAAmB,SAAApB,EAAM,EAEzFkB,EAAAA,KAACI,EAAA,CAAO,QAAQ,MAAM,IAAK,EACzB,SAAA,CAAAF,EAAAA,IAACqC,EAAA,CAAW,QAAO,GACjB,SAAArC,EAAAA,IAACG,EAAA,CAAO,QAAQ,QAAQ,QAAS0B,EAAU,SAAA,QAAA,CAAM,EACnD,EACA7B,EAAAA,IAACG,EAAA,CACC,QAAQ,UACR,QAAS,SAAY,CACnB8B,EAAQ,EAAI,EACZpD,EAAS,IAAI,EACb,GAAI,CAAE,MAAM+C,EAASU,CAAO,CAAG,OACxB5C,EAAK,CAAEb,GAASa,aAAeE,EAAaF,EAAI,QAAgC,CAAG,QAAA,CAChFuC,EAAQ,EAAK,CAAG,CAC5B,EACA,SAAUD,GAAQM,EAAQ,KAAA,IAAW,GACrC,cAAY,uBAEX,WAAO,aAAe,QAAA,CAAA,CACzB,CAAA,CACF,CAAA,EACF,CAEJ","x_google_ignoreList":[0]}
|
|
1
|
+
{"version":3,"file":"EnvVarsView-S4Pbm128.js","sources":["../../../node_modules/lucide-react/dist/esm/icons/file-up.js","../../src/web/v8/views/EnvVars/EnvVarsView.tsx"],"sourcesContent":["/**\n * @license lucide-react v0.460.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst FileUp = createLucideIcon(\"FileUp\", [\n [\"path\", { d: \"M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z\", key: \"1rqfz7\" }],\n [\"path\", { d: \"M14 2v4a2 2 0 0 0 2 2h4\", key: \"tnqrlb\" }],\n [\"path\", { d: \"M12 12v6\", key: \"3ahymv\" }],\n [\"path\", { d: \"m15 15-3-3-3 3\", key: \"15xj92\" }]\n]);\n\nexport { FileUp as default };\n//# sourceMappingURL=file-up.js.map\n","/**\n * v8/views/EnvVars/EnvVarsView.tsx — Sprint S41, v9.3.0.\n *\n * List of env vars (masked values) with: per-row edit (Sheet),\n * per-row delete (inline confirm), Add Sheet, Bulk Import Sheet,\n * and Export trigger. Backed by /api/env-vars + /api/env-vars/grouped\n * + /api/env-vars/export + /api/env-vars/bulk-import.\n */\n\nimport { useCallback, useMemo, useState } from 'react';\nimport { Download, FileUp, FlaskConical, Pencil, Plus, RefreshCcw, Trash2, Variable } from 'lucide-react';\nimport { Stack } from '../../ui/primitives/Stack.js';\nimport { Inline } from '../../ui/primitives/Inline.js';\nimport { ViewHeader } from '../../ui/data/ViewHeader.js';\nimport { ListHeader } from '../../ui/data/ListHeader.js';\nimport { Card, CardBody } from '../../ui/data/Card.js';\nimport { Button } from '../../ui/controls/Button.js';\nimport { Input } from '../../ui/controls/Input.js';\nimport { Sheet, SheetClose, SheetContent } from '../../ui/feedback/Sheet.js';\nimport { Skeleton } from '../../ui/feedback/Skeleton.js';\nimport { EmptyState } from '../../ui/feedback/EmptyState.js';\nimport { useFetch } from '../../data/useFetch.js';\nimport { fetchJson, FetchError } from '../../data/fetcher.js';\n\ninterface EnvRow {\n name: string;\n value: string;\n createdAt?: string;\n source?: string;\n}\n\nexport function EnvVarsView(): JSX.Element {\n const payload = useFetch<EnvRow[]>('/api/env-vars');\n const [adding, setAdding] = useState<boolean>(false);\n const [editing, setEditing] = useState<string | null>(null);\n const [bulkImporting, setBulkImporting] = useState<boolean>(false);\n const [confirmDelete, setConfirmDelete] = useState<string | null>(null);\n const [error, setError] = useState<string | null>(null);\n const [testing, setTesting] = useState<string | null>(null);\n const [testResult, setTestResult] = useState<{ name: string; ok: boolean; message: string } | null>(null);\n\n const rows = useMemo<EnvRow[]>(() => payload.data ?? [], [payload.data]);\n\n const refresh = useCallback(() => { void payload.refetch(); }, [payload]);\n\n const runTest = async (name: string): Promise<void> => {\n setTesting(name);\n setError(null);\n try {\n const res = await fetchJson<{ ok?: boolean; status?: string; message?: string }>(`/api/env-vars/${encodeURIComponent(name)}/test`, { method: 'POST' });\n setTestResult({ name, ok: res.ok !== false, message: res.message ?? (res.ok !== false ? 'OK' : 'Failed') });\n } catch (err) {\n const msg = err instanceof FetchError ? err.message : (err as Error).message;\n setTestResult({ name, ok: false, message: msg });\n } finally {\n setTesting(null);\n }\n };\n\n const drop = async (name: string): Promise<void> => {\n setError(null);\n try {\n await fetchJson(`/api/env-vars/${name}`, { method: 'DELETE' });\n setConfirmDelete(null);\n refresh();\n } catch (err) {\n setError(err instanceof FetchError ? err.message : (err as Error).message);\n }\n };\n\n return (\n <Stack gap={4} data-testid=\"env-vars-view\">\n <ViewHeader\n title=\"Env vars\"\n description=\"Runtime environment variables for the dashboard. Stored in ~/.config/bizar/env.json (mode 0600).\"\n actions={\n <Inline align=\"center\" gap={2}>\n {error !== null && (\n <span role=\"alert\" data-testid=\"env-vars-error\" style={{ color: 'var(--danger)', fontSize: 'var(--fs-12)' }}>\n {error}\n </span>\n )}\n <Button variant=\"ghost\" onClick={() => { window.open('/api/env-vars/export', '_blank'); }} data-testid=\"env-vars-export\">\n <Download size={14} aria-hidden /> Export\n </Button>\n <Button variant=\"ghost\" onClick={() => setBulkImporting(true)} data-testid=\"env-vars-bulk-import\">\n <FileUp size={14} aria-hidden /> Bulk import\n </Button>\n <Button variant=\"ghost\" onClick={() => void refresh()} data-testid=\"env-vars-refresh\">\n <RefreshCcw size={14} aria-hidden /> Refresh\n </Button>\n <Button variant=\"primary\" onClick={() => setAdding(true)} data-testid=\"env-vars-add\">\n <Plus size={14} aria-hidden /> Add\n </Button>\n </Inline>\n }\n />\n <ListHeader title=\"Variables\" count={rows.length} testid=\"env-vars-list-header\" />\n\n <Card variant=\"default\">\n <CardBody>\n {payload.loading && rows.length === 0 ? (\n <Stack gap={2}>\n <Skeleton style={{ height: 36 }} />\n <Skeleton style={{ height: 36 }} />\n </Stack>\n ) : rows.length === 0 ? (\n <EmptyState\n icon={<Variable size={28} aria-hidden />}\n title=\"No env vars\"\n description=\"Add one or bulk-import a .env file.\"\n />\n ) : (\n <Stack gap={1}>\n {rows.map((r) => {\n const isConfirming = confirmDelete === r.name;\n return (\n <div\n key={r.name}\n data-testid={`env-var-row-${r.name}`}\n style={{\n padding: 'var(--space-2)',\n borderRadius: 'var(--radius-sm)',\n border: '1px solid var(--border)',\n background: 'var(--surface-0)',\n }}\n >\n <Inline align=\"center\" justify=\"between\" gap={2}>\n <Stack gap={0} style={{ minWidth: 0 }}>\n <code style={{ fontSize: 'var(--fs-12)' }}>{r.name}</code>\n <code style={{ fontSize: 'var(--fs-12)', color: 'var(--fg-muted)' }}>{r.value}</code>\n {r.source && (\n <span style={{ fontSize: 'var(--fs-11)', color: 'var(--fg-subtle)' }}>\n source: {r.source} {r.createdAt ? `· ${r.createdAt}` : ''}\n </span>\n )}\n </Stack>\n <Inline gap={1}>\n <Button\n variant=\"ghost\"\n onClick={() => void runTest(r.name)}\n disabled={testing === r.name}\n data-testid={`env-var-test-${r.name}`}\n aria-label={`Test ${r.name}`}\n >\n <FlaskConical size={14} aria-hidden />\n </Button>\n <Button variant=\"ghost\" onClick={() => setEditing(r.name)} data-testid={`env-var-edit-${r.name}`} aria-label={`Edit ${r.name}`}>\n <Pencil size={14} aria-hidden />\n </Button>\n <Button\n variant=\"ghost\"\n onClick={() => setConfirmDelete((cur) => (cur === r.name ? null : r.name))}\n data-testid={`env-var-delete-${r.name}`}\n aria-label={`Delete ${r.name}`}\n >\n <Trash2 size={14} aria-hidden />\n </Button>\n </Inline>\n </Inline>\n {isConfirming && (\n <Inline gap={1} style={{ marginTop: 'var(--space-1)' }}>\n <Button variant=\"danger\" onClick={() => void drop(r.name)} data-testid={`env-var-confirm-delete-${r.name}`}>\n Confirm delete\n </Button>\n <Button variant=\"ghost\" onClick={() => setConfirmDelete(null)} data-testid={`env-var-cancel-delete-${r.name}`}>\n Cancel\n </Button>\n </Inline>\n )}\n {testResult !== null && testResult.name === r.name && (\n <div\n data-testid={`env-var-test-result-${r.name}`}\n style={{\n marginTop: 'var(--space-1)',\n fontSize: 'var(--fs-11)',\n color: testResult.ok ? 'var(--success)' : 'var(--danger)',\n fontFamily: 'var(--font-mono)',\n }}\n >\n test: {testResult.message}\n </div>\n )}\n </div>\n );\n })}\n </Stack>\n )}\n </CardBody>\n </Card>\n\n <Sheet open={adding} onOpenChange={setAdding}>\n <SheetContent side=\"right\" title=\"Add env var\" description=\"Must match /^BIZAR_[A-Z0-9_]+$/.\">\n <AddEditForm\n mode=\"add\"\n onSubmit={async (name, value) => {\n await fetchJson('/api/env-vars', { method: 'POST', body: { name, value } });\n setAdding(false);\n refresh();\n }}\n onCancel={() => setAdding(false)}\n />\n </SheetContent>\n </Sheet>\n\n <Sheet open={editing !== null} onOpenChange={(open) => { if (!open) setEditing(null); }}>\n <SheetContent side=\"right\" title=\"Edit env var\" description={editing ?? ''}>\n {editing !== null && (\n <AddEditForm\n mode=\"edit\"\n initialName={editing}\n onSubmit={async (name, value) => {\n await fetchJson(`/api/env-vars/${name}`, { method: 'PUT', body: { value } });\n setEditing(null);\n refresh();\n }}\n onCancel={() => setEditing(null)}\n />\n )}\n </SheetContent>\n </Sheet>\n\n <Sheet open={bulkImporting} onOpenChange={setBulkImporting}>\n <SheetContent side=\"right\" title=\"Bulk import\" description=\"Paste KEY=value lines (one per line, # comments ignored).\">\n <BulkImportForm\n onSubmit={async (envContent) => {\n await fetchJson('/api/env-vars/bulk-import', {\n method: 'POST',\n body: { envContent },\n });\n setBulkImporting(false);\n refresh();\n }}\n onCancel={() => setBulkImporting(false)}\n />\n </SheetContent>\n </Sheet>\n </Stack>\n );\n}\n\nfunction AddEditForm({\n mode,\n initialName,\n onSubmit,\n onCancel,\n}: {\n mode: 'add' | 'edit';\n initialName?: string;\n onSubmit: (name: string, value: string) => Promise<void>;\n onCancel: () => void;\n}): JSX.Element {\n const [name, setName] = useState<string>(initialName ?? '');\n const [value, setValue] = useState<string>('');\n const [busy, setBusy] = useState<boolean>(false);\n const [error, setError] = useState<string | null>(null);\n\n const submit = async (): Promise<void> => {\n if (!name.trim() || !value || busy) return;\n setBusy(true);\n setError(null);\n try {\n await onSubmit(name.trim(), value);\n } catch (err) {\n setError(err instanceof FetchError ? err.message : (err as Error).message);\n } finally {\n setBusy(false);\n }\n };\n\n return (\n <Stack gap={3} style={{ padding: 'var(--space-4)' }}>\n <label style={{ display: 'flex', flexDirection: 'column', gap: 'var(--space-1)' }}>\n <span style={{ fontSize: 'var(--fs-12)', color: 'var(--fg-muted)' }}>Name</span>\n <Input\n value={name}\n readOnly={mode === 'edit'}\n data-testid=\"env-var-form-name\"\n onChange={(e) => setName((e.target as HTMLInputElement).value)}\n />\n </label>\n <label style={{ display: 'flex', flexDirection: 'column', gap: 'var(--space-1)' }}>\n <span style={{ fontSize: 'var(--fs-12)', color: 'var(--fg-muted)' }}>Value</span>\n <Input\n type=\"password\"\n value={value}\n data-testid=\"env-var-form-value\"\n onChange={(e) => setValue((e.target as HTMLInputElement).value)}\n />\n </label>\n {error !== null && (\n <span role=\"alert\" style={{ color: 'var(--danger)', fontSize: 'var(--fs-12)' }}>{error}</span>\n )}\n <Inline justify=\"end\" gap={2}>\n <SheetClose asChild>\n <Button variant=\"ghost\" onClick={onCancel} data-testid=\"env-var-form-cancel\">Cancel</Button>\n </SheetClose>\n <Button\n variant=\"primary\"\n onClick={() => void submit()}\n disabled={busy || !name.trim() || !value}\n data-testid=\"env-var-form-submit\"\n >\n {mode === 'add' ? 'Add' : 'Save'}\n </Button>\n </Inline>\n </Stack>\n );\n}\n\nfunction BulkImportForm({\n onSubmit,\n onCancel,\n}: {\n onSubmit: (envContent: string) => Promise<void>;\n onCancel: () => void;\n}): JSX.Element {\n const [content, setContent] = useState<string>('');\n const [busy, setBusy] = useState<boolean>(false);\n const [error, setError] = useState<string | null>(null);\n\n return (\n <Stack gap={3} style={{ padding: 'var(--space-4)' }}>\n <textarea\n value={content}\n placeholder={'BIZAR_FOO=bar\\nBIZAR_BAZ=qux\\n# comment'}\n rows={12}\n data-testid=\"env-vars-bulk-input\"\n onChange={(e) => setContent((e.target as HTMLTextAreaElement).value)}\n style={{\n background: 'var(--surface-0)',\n border: '1px solid var(--border)',\n borderRadius: 'var(--radius-md)',\n padding: 'var(--space-2)',\n color: 'var(--fg)',\n fontFamily: 'var(--font-mono)',\n fontSize: 'var(--fs-12)',\n resize: 'vertical',\n }}\n />\n {error !== null && (\n <span role=\"alert\" style={{ color: 'var(--danger)', fontSize: 'var(--fs-12)' }}>{error}</span>\n )}\n <Inline justify=\"end\" gap={2}>\n <SheetClose asChild>\n <Button variant=\"ghost\" onClick={onCancel}>Cancel</Button>\n </SheetClose>\n <Button\n variant=\"primary\"\n onClick={async () => {\n setBusy(true);\n setError(null);\n try { await onSubmit(content); }\n catch (err) { setError(err instanceof FetchError ? err.message : (err as Error).message); }\n finally { setBusy(false); }\n }}\n disabled={busy || content.trim() === ''}\n data-testid=\"env-vars-bulk-submit\"\n >\n {busy ? 'Importing…' : 'Import'}\n </Button>\n </Inline>\n </Stack>\n );\n}"],"names":["FileUp","createLucideIcon","EnvVarsView","payload","useFetch","adding","setAdding","useState","editing","setEditing","bulkImporting","setBulkImporting","confirmDelete","setConfirmDelete","error","setError","testing","setTesting","testResult","setTestResult","rows","useMemo","refresh","useCallback","runTest","name","res","fetchJson","err","msg","FetchError","drop","jsxs","Stack","jsx","ViewHeader","Inline","Button","Download","RefreshCcw","Plus","ListHeader","Card","CardBody","Skeleton","EmptyState","Variable","r","isConfirming","FlaskConical","Pencil","cur","Trash2","Sheet","SheetContent","AddEditForm","value","open","BulkImportForm","envContent","mode","initialName","onSubmit","onCancel","setName","setValue","busy","setBusy","submit","Input","e","SheetClose","content","setContent"],"mappings":"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","x_google_ignoreList":[0]}
|