@hot-updater/console 1.0.0-rc.8 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (342) hide show
  1. package/.output/nitro.json +1 -1
  2. package/.output/public/assets/ConsoleFeatureUnavailable-jB4Loglh.js +1 -0
  3. package/.output/public/assets/EventDetails-B6yUsyNA.js +1 -0
  4. package/.output/public/assets/HashValueDisplay-BFX_kY3-.js +1 -0
  5. package/.output/public/assets/InsightsInfo-BNO0WznZ.js +1 -0
  6. package/.output/public/assets/InsightsPageHeader-B892oVml.js +1 -0
  7. package/.output/public/assets/NotFoundPage-DIqCpWa3.js +1 -0
  8. package/.output/public/assets/alert-dialog-Bbk_4-WJ.js +1 -0
  9. package/.output/public/assets/api-DCM0wr6O.js +1 -0
  10. package/.output/public/assets/api-keys-CIO9L_wu.js +1 -0
  11. package/.output/public/assets/api-keys-DVTL_--f.js +1 -0
  12. package/.output/public/assets/arrow-left-CnMYpqB7.js +1 -0
  13. package/.output/public/assets/arrow-up-right-BtffZA6e.js +1 -0
  14. package/.output/public/assets/chevron-right-BqD5wtFb.js +1 -0
  15. package/.output/public/assets/clipboard-DS9ucUQL.js +1 -0
  16. package/.output/public/assets/console-features-api-BH5m_PtQ.js +1 -0
  17. package/.output/public/assets/dialog-Bqbb7B0N.js +1 -0
  18. package/.output/public/assets/dist-LxKJB-Vu.js +1 -0
  19. package/.output/public/assets/empty-CuT2UhFp.js +1 -0
  20. package/.output/public/assets/field-BBDpjIqu.js +1 -0
  21. package/.output/public/assets/index-6o51GkFe.js +11 -0
  22. package/.output/public/assets/input-group-ja_30qaF.js +1 -0
  23. package/.output/public/assets/insights-CmraDzQh.js +1 -0
  24. package/.output/public/assets/insights-CxZ2GCYV.js +2 -0
  25. package/.output/public/assets/insights-api-BigAU9sZ.js +1 -0
  26. package/.output/public/assets/insights-usage-rpc-DYEhsCKT.js +1 -0
  27. package/.output/public/assets/insights-vNRCrfnS.js +42 -0
  28. package/.output/public/assets/insights_.distribution-ChOerfJt.js +1 -0
  29. package/.output/public/assets/insights_.distribution-D-e4iga8.js +1 -0
  30. package/.output/public/assets/insights_.distribution-DZtkibX1.js +2 -0
  31. package/.output/public/assets/installations-BazSJXE0.js +2 -0
  32. package/.output/public/assets/installations-ClHTqdAO.js +1 -0
  33. package/.output/public/assets/installations-DpKsBuHi.js +1 -0
  34. package/.output/public/assets/key-round-wS_SIZ6b.js +1 -0
  35. package/.output/public/assets/list-CgrYiadM.js +1 -0
  36. package/.output/public/assets/refresh-cw-BYgoNCco.js +1 -0
  37. package/.output/public/assets/remote-config-BWwHOkCK.js +1 -0
  38. package/.output/public/assets/remote-config-Br56BODb.js +6 -0
  39. package/.output/public/assets/remote-config-CXOi0LRu.js +1 -0
  40. package/.output/public/assets/routes-B88Erkpk.js +2 -0
  41. package/.output/public/assets/routes-CfzsAleC.js +1 -0
  42. package/.output/public/assets/search-DaTDPW25.js +1 -0
  43. package/.output/public/assets/select-BZZBXMkr.js +1 -0
  44. package/.output/public/assets/sidebar-DNVyJPfX.js +3 -0
  45. package/.output/public/assets/smartphone-DpTFgtKf.js +1 -0
  46. package/.output/public/assets/styles-DTGEAJFv.css +2 -0
  47. package/.output/public/assets/switch-DZ1TPwx-.js +1 -0
  48. package/.output/public/assets/table-Gm4qRWwE.js +1 -0
  49. package/.output/public/assets/tabs-C7FOEjFC.js +1 -0
  50. package/.output/public/assets/undo-2-CmrHjwFc.js +1 -0
  51. package/.output/public/assets/useCompositeListItem-9E4pj_CH.js +1 -0
  52. package/.output/public/assets/valueToPercent-CH8GCHaL.js +1 -0
  53. package/.output/server/__23tanstack-start-server-fn-resolver-BpRlos5Q.mjs +170 -0
  54. package/.output/server/_libs/@base-ui/react+[...].mjs +4389 -4207
  55. package/.output/server/_libs/@tanstack/react-router+[...].mjs +3802 -4022
  56. package/.output/server/_libs/@tanstack/react-router-ssr-query+[...].mjs +140 -97
  57. package/.output/server/_libs/lucide-react.mjs +221 -9
  58. package/.output/server/_libs/next-themes.mjs +1 -1
  59. package/.output/server/_libs/react-redux+[...].mjs +1 -1
  60. package/.output/server/_libs/recharts+[...].mjs +483 -901
  61. package/.output/server/_libs/sonner.mjs +1 -1
  62. package/.output/server/_libs/tanstack__history.mjs +68 -41
  63. package/.output/server/_libs/tanstack__query-core.mjs +2010 -309
  64. package/.output/server/_libs/tanstack__react-query.mjs +448 -21
  65. package/.output/server/_libs/verkit.mjs +102 -1
  66. package/.output/server/_ssr/BundleIdDisplay-x94o9rlU.mjs +13 -0
  67. package/.output/server/_ssr/ConsoleFeatureUnavailable-ldW8v8-q.mjs +58 -0
  68. package/.output/server/_ssr/EventDetails-Q8kfj9Nr.mjs +344 -0
  69. package/.output/server/_ssr/{HashValueDisplay-C5tS4oGo.mjs → HashValueDisplay-n1GholGS.mjs} +3 -3
  70. package/.output/server/_ssr/InsightsInfo-DuJFatQO.mjs +75 -0
  71. package/.output/server/_ssr/InsightsPageHeader-BSUX3Ye9.mjs +145 -0
  72. package/.output/server/_ssr/NotFoundPage-DZzOOzS3.mjs +37 -0
  73. package/.output/server/_ssr/{dialog-WiIAKl4L.mjs → alert-dialog-C43Doa0I.mjs} +6 -83
  74. package/.output/server/_ssr/{api-keys-aXriWrv7.mjs → api-keys-B4sYm8dM.mjs} +48 -9
  75. package/.output/server/_ssr/api-keys-CEnM9fqG.mjs +5 -0
  76. package/.output/server/_ssr/api-keys-rpc-BIFuUgMt.mjs +52 -0
  77. package/.output/server/_ssr/api-oZjRn9tP.mjs +186 -0
  78. package/.output/server/_ssr/api-rpc-BNiFRRK8.mjs +240 -0
  79. package/.output/server/_ssr/{auth-BF8mbAgF.mjs → auth-UP0wXs4i.mjs} +1 -1
  80. package/.output/server/_ssr/{auth-rpc-B7w3AdRr.mjs → auth-rpc-DnZqYxyq.mjs} +6 -6
  81. package/.output/server/_ssr/auth.server-DFpyxRDd.mjs +5374 -0
  82. package/.output/server/_ssr/bundleActivity-M5gzBFNg.mjs +18 -0
  83. package/.output/server/_ssr/config-WVX4IxSR.mjs +15 -0
  84. package/.output/server/_ssr/config.server-DskXCAyI.mjs +35 -0
  85. package/.output/server/_ssr/console-access-BJfAXknd.mjs +17 -0
  86. package/.output/server/_ssr/console-features-Oz0q20jJ.mjs +61 -0
  87. package/.output/server/_ssr/console-features-api-C9kiKvaV.mjs +43 -0
  88. package/.output/server/_ssr/console-features-rpc-P0GL7Z-R.mjs +19 -0
  89. package/.output/server/_ssr/{createServerFn-B2hcXoPM.mjs → createMiddleware-Cm6Tn0_Y.mjs} +67 -56
  90. package/.output/server/_ssr/{createServerRpc-DB29C_5p.mjs → createServerRpc-RLR4H-Fn.mjs} +2 -2
  91. package/.output/server/_ssr/databaseConfig-C5SkAyUy.mjs +5 -0
  92. package/.output/server/_ssr/{databaseJsonValue-d6I3nAS4.mjs → databaseJsonValue-Csbuzc9Q.mjs} +28 -5
  93. package/.output/server/_ssr/databaseRows-CPphvbag.mjs +73 -0
  94. package/.output/server/_ssr/dialog-BbYDMjdC.mjs +84 -0
  95. package/.output/server/_ssr/{dist-CyzPaI5v.mjs → dist-CbQbBIw-.mjs} +140 -7
  96. package/.output/server/_ssr/{downloadBundle-CI7JUKvC.mjs → downloadBundle-CZysjmNW.mjs} +10 -10
  97. package/.output/server/_ssr/empty-CVLGfxuu.mjs +60 -0
  98. package/.output/server/_ssr/{empty-plugin-adapters-B5QvGpEl.mjs → empty-plugin-adapters-CPtwX8a7.mjs} +1 -1
  99. package/.output/server/_ssr/failureReports-DKDhVsXA.mjs +33 -0
  100. package/.output/server/_ssr/field-asw83X0v.mjs +189 -0
  101. package/.output/server/_ssr/getBundleChildren-Cv9iz1As.mjs +22 -0
  102. package/.output/server/_ssr/{input-group-Coj6SwVP.mjs → input-group-CuYJHosb.mjs} +2 -2
  103. package/.output/server/_ssr/insights-B55FG5fm.mjs +14 -0
  104. package/.output/server/_ssr/insights-CWnHIFUV.mjs +5 -0
  105. package/.output/server/_ssr/insights-CpLpedFZ.mjs +2315 -0
  106. package/.output/server/_ssr/insights-api-sjws23WF.mjs +122 -0
  107. package/.output/server/_ssr/insights-errors-BjnFUyZj.mjs +34 -0
  108. package/.output/server/_ssr/insights-failures-rpc-BvbWvqNf.mjs +36 -0
  109. package/.output/server/_ssr/insights-failures-xaa41Buf.mjs +46 -0
  110. package/.output/server/_ssr/insights-recovery-BWQhiZaF.mjs +28 -0
  111. package/.output/server/_ssr/insights-recovery-rpc-GiYXdkaY.mjs +32 -0
  112. package/.output/server/_ssr/{insights-rpc-l2-oBYth.mjs → insights-rpc-DP_8Rmz4.mjs} +22 -14
  113. package/.output/server/_ssr/insights-usage-BpBM0U0c.mjs +29 -0
  114. package/.output/server/_ssr/insights-usage-rpc-BiolgB8e.mjs +29 -0
  115. package/.output/server/_ssr/insights-usage-rpc-KStL0zOx.mjs +41 -0
  116. package/.output/server/_ssr/insightsUsage-CzhVjsc8.mjs +56 -0
  117. package/.output/server/_ssr/insights_.distribution-CVrnbP3R.mjs +7 -0
  118. package/.output/server/_ssr/insights_.distribution-D2HaNTAA.mjs +16 -0
  119. package/.output/server/_ssr/{insights_.distribution-INw6QxbU.mjs → insights_.distribution-DN9pR422.mjs} +50 -22
  120. package/.output/server/_ssr/installations-BHmbbnH8.mjs +5 -0
  121. package/.output/server/_ssr/{installations-DH-tQuRo.mjs → installations-BSCmFq8Q.mjs} +279 -367
  122. package/.output/server/_ssr/installations-DD1g__Nc.mjs +69 -0
  123. package/.output/server/_ssr/listReleases-BfUBlCHo.mjs +79 -0
  124. package/.output/server/_ssr/plugins-BaD1slHx.mjs +2086 -0
  125. package/.output/server/_ssr/release-adoption-005tQRpo.mjs +55 -0
  126. package/.output/server/_ssr/release-adoption-rpc-BsstqxUp.mjs +41 -0
  127. package/.output/server/_ssr/releaseAdoption-CtOFkwli.mjs +114 -0
  128. package/.output/server/_ssr/releaseManagement-DFMUnDF5.mjs +11 -0
  129. package/.output/server/_ssr/remote-config-C2Ee8lXO.mjs +5 -0
  130. package/.output/server/_ssr/remote-config-Dv1ccMo-.mjs +17 -0
  131. package/.output/server/_ssr/remote-config-of0lGQH8.mjs +2648 -0
  132. package/.output/server/_ssr/remote-config-rpc-BzX31mUS.mjs +115 -0
  133. package/.output/server/_ssr/rolldown-runtime-rSIU-vHC.mjs +13 -0
  134. package/.output/server/_ssr/{router-DfFyAp5p.mjs → router-D8NuoJ_I.mjs} +117 -136
  135. package/.output/server/_ssr/{routes-BtsfVx-p.mjs → routes-DgvnFqDy.mjs} +195 -429
  136. package/.output/server/_ssr/routes-V8sDybGf.mjs +409 -0
  137. package/.output/server/_ssr/runtime.server-De0QVWc9.mjs +104 -0
  138. package/.output/server/_ssr/schema-BiAVyEj2.mjs +361 -0
  139. package/.output/server/_ssr/{select-CyvLaMza.mjs → select-t3iXRwc9.mjs} +3 -3
  140. package/.output/server/_ssr/server-h4VxnExB.mjs +8325 -0
  141. package/.output/server/_ssr/{createSsrRpc-C-dLcQuy.mjs → sidebar-DJcErBMo.mjs} +107 -47
  142. package/.output/server/_ssr/ssr.mjs +1 -1
  143. package/.output/server/_ssr/start-BfFbHKMK.mjs +4 -0
  144. package/.output/server/_ssr/switch-E-btwMGt.mjs +43 -0
  145. package/.output/server/_ssr/{table-CkVhsNpe.mjs → table-37Dd23TN.mjs} +2 -2
  146. package/.output/server/_ssr/tabs-DEFnTm95.mjs +45 -0
  147. package/.output/server/_ssr/updateFailures-H6pnnYK4.mjs +40 -0
  148. package/.output/server/_ssr/{uuidv7-D0QFkPL_.mjs → uuidv7-C88s9jWF.mjs} +2 -2
  149. package/.output/server/_tanstack-start-manifest_v-55AGsehh.mjs +139 -0
  150. package/.output/server/index.mjs +303 -205
  151. package/LICENSE +13 -14
  152. package/README.md +80 -71
  153. package/lib/index.d.mts +23 -11
  154. package/lib/vite-internal.mjs +13 -3
  155. package/lib/vite.d.mts +2 -0
  156. package/package.json +14 -14
  157. package/src/components/AppSidebar.tsx +74 -75
  158. package/src/components/ConsoleAccessPage.tsx +5 -1
  159. package/src/components/ConsoleFeatureUnavailable.tsx +80 -0
  160. package/src/components/NotFoundPage.tsx +7 -7
  161. package/src/components/features/FeatureSlots.tsx +103 -0
  162. package/src/components/features/api-keys/apiKeysFeatureUi.tsx +15 -0
  163. package/src/components/features/bundles/BundleMetadata.tsx +8 -5
  164. package/src/components/features/bundles/RolloutCohortsDialog.tsx +1 -1
  165. package/src/components/features/channels/ChannelManagementDialog.tsx +8 -6
  166. package/src/components/features/insights/AppUsage.tsx +41 -14
  167. package/src/components/features/insights/BuiltinBundle.tsx +36 -0
  168. package/src/components/features/insights/ComparedBundlesChart.tsx +310 -0
  169. package/src/components/features/insights/EstimatedCount.tsx +18 -0
  170. package/src/components/features/insights/EventDetails.tsx +390 -26
  171. package/src/components/features/insights/EventHistoryCard.tsx +111 -25
  172. package/src/components/features/insights/EventHistoryList.tsx +1 -1
  173. package/src/components/features/insights/FailureReports.tsx +407 -0
  174. package/src/components/features/insights/InsightsControls.tsx +240 -142
  175. package/src/components/features/insights/InsightsErrorAlert.tsx +14 -1
  176. package/src/components/features/insights/InsightsOverview.tsx +601 -403
  177. package/src/components/features/insights/InsightsPageHeader.tsx +19 -14
  178. package/src/components/features/insights/InsightsPeriodSelector.tsx +67 -12
  179. package/src/components/features/insights/InstallationHistoryCard.tsx +65 -10
  180. package/src/components/features/insights/InstallationMatchesCard.tsx +1 -1
  181. package/src/components/features/insights/ReleaseActivity.tsx +308 -0
  182. package/src/components/features/insights/ReportingDevicesSummary.tsx +13 -13
  183. package/src/components/features/insights/RollbackButton.tsx +118 -0
  184. package/src/components/features/insights/UpdateFailures.tsx +382 -0
  185. package/src/components/features/insights/insightsFeatureUi.tsx +35 -0
  186. package/src/components/features/releases/ReleaseEditorSheet.tsx +27 -13
  187. package/src/components/features/remote-config/ConditionDialog.tsx +592 -0
  188. package/src/components/features/remote-config/ConditionsCard.tsx +247 -0
  189. package/src/components/features/remote-config/ParameterDialog.tsx +426 -0
  190. package/src/components/features/remote-config/ParametersCard.tsx +254 -0
  191. package/src/components/features/remote-config/PreviewCard.tsx +284 -0
  192. package/src/components/features/remote-config/PublishDialog.tsx +325 -0
  193. package/src/components/features/remote-config/RemoteConfigPage.tsx +353 -0
  194. package/src/components/features/remote-config/RuleSummary.tsx +21 -0
  195. package/src/components/features/remote-config/ValueInput.tsx +151 -0
  196. package/src/components/features/remote-config/VersionsCard.tsx +384 -0
  197. package/src/components/features/remote-config/remoteConfigFeatureUi.tsx +15 -0
  198. package/src/components/features/remote-config/useDateTimeText.ts +16 -0
  199. package/src/components/ui/sidebar.tsx +22 -29
  200. package/src/index.ts +26 -19
  201. package/src/lib/api-keys-api.ts +0 -28
  202. package/src/lib/api-keys-rpc.ts +27 -38
  203. package/src/lib/api-rpc.ts +125 -288
  204. package/src/lib/api.ts +15 -134
  205. package/src/lib/bundle-activity.ts +24 -4
  206. package/src/lib/console-access.ts +20 -0
  207. package/src/lib/console-features-api.ts +68 -0
  208. package/src/lib/console-features-rpc.ts +13 -0
  209. package/src/lib/console-features.ts +98 -0
  210. package/src/lib/insights-api.ts +56 -2
  211. package/src/lib/insights-errors.ts +64 -0
  212. package/src/lib/insights-failures-rpc.ts +36 -0
  213. package/src/lib/insights-failures.ts +130 -0
  214. package/src/lib/insights-recovery-rpc.ts +13 -17
  215. package/src/lib/insights-recovery.ts +12 -36
  216. package/src/lib/insights-retention.ts +21 -0
  217. package/src/lib/insights-rpc.ts +30 -12
  218. package/src/lib/insights-search.ts +50 -4
  219. package/src/lib/insights-usage-rpc.ts +15 -9
  220. package/src/lib/insights-usage.ts +41 -3
  221. package/src/lib/insights-view.ts +34 -5
  222. package/src/lib/release-adoption-api.ts +214 -0
  223. package/src/lib/release-adoption-rpc.ts +49 -0
  224. package/src/lib/release-adoption.ts +164 -0
  225. package/src/lib/remote-config-api.ts +119 -0
  226. package/src/lib/remote-config-draft.ts +666 -0
  227. package/src/lib/remote-config-rpc.ts +196 -0
  228. package/src/lib/scroll-restoration.ts +21 -0
  229. package/src/lib/server/auth.server.ts +13 -5
  230. package/src/lib/server/bundleActivity.ts +27 -28
  231. package/src/lib/server/config.server.ts +21 -76
  232. package/src/lib/server/console-feature-apis.ts +70 -0
  233. package/src/lib/server/console-runtime.server.ts +82 -38
  234. package/src/lib/server/downloadBundle.ts +14 -15
  235. package/src/lib/server/failureReports.ts +50 -0
  236. package/src/lib/server/getBundleChildren.ts +31 -122
  237. package/src/lib/server/insightsUsage.ts +52 -113
  238. package/src/lib/server/listReleases.ts +109 -44
  239. package/src/lib/server/releaseAdoption.ts +151 -0
  240. package/src/lib/server/releaseReachability.ts +8 -8
  241. package/src/lib/server/remoteConfig.ts +75 -0
  242. package/src/lib/server/runtime.server.ts +120 -31
  243. package/src/lib/server/updateFailures.ts +66 -0
  244. package/src/lib/use-dialog-target.ts +27 -0
  245. package/src/routeTree.gen.ts +44 -44
  246. package/src/router.tsx +3 -2
  247. package/src/routes/-installations-search.ts +32 -8
  248. package/src/routes/-releases-search.ts +76 -29
  249. package/src/routes/__root.tsx +7 -1
  250. package/src/routes/api/bundles/$bundleId/download.ts +2 -5
  251. package/src/routes/api-keys.tsx +5 -2
  252. package/src/routes/index.tsx +210 -152
  253. package/src/routes/insights.tsx +91 -23
  254. package/src/routes/insights_.distribution.tsx +50 -9
  255. package/src/routes/installations.tsx +97 -40
  256. package/src/routes/remote-config.tsx +42 -0
  257. package/src/styles.css +9 -0
  258. package/src/vite-internal.ts +15 -3
  259. package/src/vite.ts +2 -0
  260. package/.output/public/assets/HashValueDisplay-BpTc3Oyg.js +0 -1
  261. package/.output/public/assets/InsightsPageHeader-DC2eEst8.js +0 -1
  262. package/.output/public/assets/api-CdUyUqzR.js +0 -42
  263. package/.output/public/assets/api-keys-64PM9PwW.js +0 -1
  264. package/.output/public/assets/api-keys-api-BeaJnvY5.js +0 -1
  265. package/.output/public/assets/arrow-left-04Rh8Zgp.js +0 -1
  266. package/.output/public/assets/card-CYHs5FZv.js +0 -1
  267. package/.output/public/assets/chart-no-axes-combined-DwyMsVFW.js +0 -1
  268. package/.output/public/assets/createServerFn-DU71xucx.js +0 -3
  269. package/.output/public/assets/dialog-IVMkBRCq.js +0 -1
  270. package/.output/public/assets/dist-BR4GzeEu.js +0 -1
  271. package/.output/public/assets/field-B3CYDpjg.js +0 -1
  272. package/.output/public/assets/index-C39o7rJH.js +0 -10
  273. package/.output/public/assets/info-C3y9HNoU.js +0 -1
  274. package/.output/public/assets/input-group-nLZylhWF.js +0 -1
  275. package/.output/public/assets/insights-Bm9v8uO3.js +0 -2
  276. package/.output/public/assets/insights-DS3iO7Up.js +0 -1
  277. package/.output/public/assets/insights-search-Byj3g3Mp.js +0 -1
  278. package/.output/public/assets/insights-usage-rpc-BaGR3lgq.js +0 -1
  279. package/.output/public/assets/insights_.distribution-B1i6cjlQ.js +0 -1
  280. package/.output/public/assets/insights_.distribution-C1Wf27eB.js +0 -2
  281. package/.output/public/assets/installations-CkFW4fV9.js +0 -2
  282. package/.output/public/assets/installations-DxTaIcHD.js +0 -1
  283. package/.output/public/assets/lazyRouteComponent-BapzjYnb.js +0 -1
  284. package/.output/public/assets/list-Dqt53fWZ.js +0 -1
  285. package/.output/public/assets/loader-circle-CUKfUqow.js +0 -1
  286. package/.output/public/assets/preload-helper-ClBMtM1g.js +0 -1
  287. package/.output/public/assets/refresh-cw-CNE_2PnD.js +0 -1
  288. package/.output/public/assets/routes-Cgtvspjg.js +0 -2
  289. package/.output/public/assets/routes-O2r2UUN8.js +0 -1
  290. package/.output/public/assets/shield-check-BFcJ46kz.js +0 -1
  291. package/.output/public/assets/signing-BgspC-xP.js +0 -1
  292. package/.output/public/assets/styles-DnrWuBwd.css +0 -2
  293. package/.output/public/assets/table-BuWQgxJJ.js +0 -1
  294. package/.output/public/assets/useMutation-CSV9NCUl.js +0 -1
  295. package/.output/public/assets/useOpenInteractionType-D5kduCTD.js +0 -1
  296. package/.output/public/assets/valueToPercent-BAtcbSLk.js +0 -1
  297. package/.output/server/__23tanstack-start-server-fn-resolver-CmYkol9D.mjs +0 -150
  298. package/.output/server/_ssr/InsightsPageHeader-Dma3dVj1.mjs +0 -64
  299. package/.output/server/_ssr/api-C3bGmgY0.mjs +0 -332
  300. package/.output/server/_ssr/api-keys-api-BRF6rbRC.mjs +0 -60
  301. package/.output/server/_ssr/api-keys-rpc-BMa1ZM6N.mjs +0 -136
  302. package/.output/server/_ssr/api-rpc-BYQ2e0z6.mjs +0 -1399
  303. package/.output/server/_ssr/auth.server-CmicHh0J.mjs +0 -47
  304. package/.output/server/_ssr/bundle-signing-rpc-DbQ4pFAX.mjs +0 -16
  305. package/.output/server/_ssr/bundle-signing.server-Uqt1OF49.mjs +0 -12
  306. package/.output/server/_ssr/bundleActivity-pBrPSG01.mjs +0 -28
  307. package/.output/server/_ssr/card-B7KSO_25.mjs +0 -108
  308. package/.output/server/_ssr/config-Dv8qLDZ0.mjs +0 -13
  309. package/.output/server/_ssr/config.server-C-d1QaBU.mjs +0 -368
  310. package/.output/server/_ssr/databaseRows-5bCRTxm-.mjs +0 -126
  311. package/.output/server/_ssr/deleteBundle-8X-jq7Z7.mjs +0 -66
  312. package/.output/server/_ssr/field-BDwuU8RE.mjs +0 -74
  313. package/.output/server/_ssr/getBundleChildren-DoL8l_AS.mjs +0 -50
  314. package/.output/server/_ssr/insights-BDJjaDLp.mjs +0 -938
  315. package/.output/server/_ssr/insights-D0FWpfOS.mjs +0 -10
  316. package/.output/server/_ssr/insights-recovery-Cv6RSyeR.mjs +0 -21
  317. package/.output/server/_ssr/insights-recovery-rpc-BE9YsK_T.mjs +0 -37
  318. package/.output/server/_ssr/insights-search-1czJMZgk.mjs +0 -21
  319. package/.output/server/_ssr/insights-usage-rpc-BE_aCnea.mjs +0 -184
  320. package/.output/server/_ssr/insights-usage-rpc-CtAolz-t.mjs +0 -24
  321. package/.output/server/_ssr/insightsContract-B09K_Px1.mjs +0 -303
  322. package/.output/server/_ssr/insightsHistory-Ci4rYAgl.mjs +0 -41
  323. package/.output/server/_ssr/insightsRecovery-CaghWL2t.mjs +0 -113
  324. package/.output/server/_ssr/insightsUsage-DNIj6jxF.mjs +0 -71
  325. package/.output/server/_ssr/insights_.distribution-Cp0kf1vW.mjs +0 -10
  326. package/.output/server/_ssr/installations-Bhyiwx8G.mjs +0 -29
  327. package/.output/server/_ssr/routes-xBkI2Fmt.mjs +0 -37
  328. package/.output/server/_ssr/runtime.server-CsiKFp_Z.mjs +0 -436
  329. package/.output/server/_ssr/server-BdkuOWe8.mjs +0 -7468
  330. package/.output/server/_ssr/signing-CQ70saFm.mjs +0 -133
  331. package/.output/server/_ssr/start-DpViQGnt.mjs +0 -4
  332. package/.output/server/_tanstack-start-manifest_v-CrBsoKQQ.mjs +0 -125
  333. package/src/components/features/bundles/BundleActivityChart.tsx +0 -97
  334. package/src/components/features/bundles/BundleInsightsSummary.tsx +0 -126
  335. package/src/components/features/signing/BundleSigningPage.tsx +0 -139
  336. package/src/lib/bundle-signing-api.ts +0 -14
  337. package/src/lib/bundle-signing-rpc.ts +0 -16
  338. package/src/lib/server/bundle-signing.server.ts +0 -23
  339. package/src/lib/server/deleteBundle.ts +0 -145
  340. package/src/lib/server/insightsHistory.ts +0 -52
  341. package/src/lib/server/insightsRecovery.ts +0 -187
  342. package/src/routes/signing.tsx +0 -37
@@ -1,938 +0,0 @@
1
- import { i as __toESM } from "../_runtime.mjs";
2
- import { C as ScrollAreaRoot, S as ScrollAreaViewport, _ as ComboboxInput$1, b as ScrollAreaThumb, c as ComboboxItemIndicator, d as ComboboxItem$1, f as ComboboxPopup, g as ComboboxClear$1, h as ComboboxList$1, ht as require_react, l as ComboboxRoot, m as ComboboxPortal, mt as require_jsx_runtime, p as ComboboxPositioner, u as ComboboxEmpty$1, v as ComboboxTrigger$1, x as ScrollAreaScrollbar, y as ScrollAreaCorner } from "../_libs/@base-ui/react+[...].mjs";
3
- import { F as Check, L as ArrowUpRight, M as ChevronRight, P as ChevronDown, R as ArrowRight, n as TriangleAlert, t as X, u as RotateCw, x as List } from "../_libs/lucide-react.mjs";
4
- import { C as cn, S as buttonVariants, _ as Skeleton, r as Separator$1, t as Button$1 } from "./createSsrRpc-C-dLcQuy.mjs";
5
- import { m as Link } from "../_libs/@tanstack/react-router+[...].mjs";
6
- import { n as useQuery } from "../_libs/tanstack__react-query.mjs";
7
- import { a as Badge, d as CardTitle, i as AlertTitle, l as CardFooter, o as Card, r as AlertDescription, s as CardContent, t as Alert, u as CardHeader } from "./card-B7KSO_25.mjs";
8
- import { a as FieldLabel, i as FieldGroup, t as Field } from "./field-BDwuU8RE.mjs";
9
- import { a as TableHeader, i as TableHead, n as TableBody, o as TableRow, r as TableCell, t as Table } from "./table-CkVhsNpe.mjs";
10
- import { t as Route } from "./insights-D0FWpfOS.mjs";
11
- import { i as XAxis, n as LineChart, o as Line, r as YAxis, s as CartesianGrid } from "../_libs/recharts+[...].mjs";
12
- import { a as ChartTooltipContent, d as useChannelsQuery, i as ChartTooltip, s as getRecoveryReportRpc, t as ChartContainer } from "./api-C3bGmgY0.mjs";
13
- import { a as SelectItem, i as SelectGroup, n as Select$1, o as SelectTrigger, r as SelectContent, s as SelectValue, t as PlatformIcon } from "./select-CyvLaMza.mjs";
14
- import { i as InputGroupInput, n as InputGroupAddon, r as InputGroupButton, t as InputGroup } from "./input-group-Coj6SwVP.mjs";
15
- import { a as InsightsInfo, c as Tabs$1, d as TabsTrigger, f as getAppUsageReportRpc, i as EmptyTitle, l as TabsContent, n as EmptyDescription, o as InsightsPeriodSelector, p as usageMetrics, r as EmptyHeader, s as Progress$1, t as Empty, u as TabsList } from "./insights-usage-rpc-BE_aCnea.mjs";
16
- import { n as InsightsPageHeader, t as InsightsErrorAlert } from "./InsightsPageHeader-Dma3dVj1.mjs";
17
- //#region node_modules/.nitro/vite/services/ssr/assets/insights-BDJjaDLp.js
18
- var import_react = /* @__PURE__ */ __toESM(require_react());
19
- var import_jsx_runtime = require_jsx_runtime();
20
- function ScrollArea$1({ className, children, ...props }) {
21
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(ScrollAreaRoot, {
22
- "data-slot": "scroll-area",
23
- className: cn("relative", className),
24
- ...props,
25
- children: [
26
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ScrollAreaViewport, {
27
- "data-slot": "scroll-area-viewport",
28
- className: "size-full rounded-[inherit] transition-[color,box-shadow] outline-none focus-visible:ring-[3px] focus-visible:ring-ring/50 focus-visible:outline-1",
29
- children
30
- }),
31
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ScrollBar, {}),
32
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ScrollAreaCorner, {})
33
- ]
34
- });
35
- }
36
- function ScrollBar({ className, orientation = "vertical", ...props }) {
37
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ScrollAreaScrollbar, {
38
- "data-slot": "scroll-area-scrollbar",
39
- "data-orientation": orientation,
40
- orientation,
41
- className: cn("flex touch-none p-px transition-colors select-none data-horizontal:h-2.5 data-horizontal:flex-col data-horizontal:border-t data-horizontal:border-t-transparent data-vertical:h-full data-vertical:w-2.5 data-vertical:border-l data-vertical:border-l-transparent", className),
42
- ...props,
43
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ScrollAreaThumb, {
44
- "data-slot": "scroll-area-thumb",
45
- className: "relative flex-1 rounded-full bg-border"
46
- })
47
- });
48
- }
49
- function ReportingDevicesSummary({ window, count, isPending, partial }) {
50
- const metric = usageMetrics[window];
51
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
52
- "aria-label": `${metric.label} over ${metric.period}`,
53
- role: "region",
54
- className: "flex items-center gap-3",
55
- children: [isPending ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Skeleton, {
56
- "aria-label": "Loading active users",
57
- className: "h-9 w-12"
58
- }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", {
59
- className: "text-4xl font-semibold tracking-tight tabular-nums",
60
- children: count === void 0 ? "—" : `${partial ? "≥" : ""}${count.toLocaleString()}`
61
- }), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
62
- className: "flex items-center gap-1 text-sm text-muted-foreground",
63
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: metric.label }), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(InsightsInfo, {
64
- label: `How ${metric.label} is counted`,
65
- children: [
66
- "Unique app installations that reported activity in the last",
67
- " ",
68
- metric.period,
69
- ", including no-change reports. Filtered by platform, channel, and app version. The chart counts unique reporting installations per ",
70
- metric.interval,
71
- ".",
72
- partial ? " Only part of the history is available; the total is a lower bound." : ""
73
- ]
74
- })]
75
- })]
76
- });
77
- }
78
- var dates$1 = new Intl.DateTimeFormat("en", {
79
- month: "short",
80
- day: "numeric",
81
- timeZone: "UTC"
82
- });
83
- var times$1 = new Intl.DateTimeFormat("en", {
84
- month: "short",
85
- day: "numeric",
86
- hour: "numeric",
87
- timeZone: "UTC"
88
- });
89
- function AppUsage({ query, search, window, onWindowChange }) {
90
- const report = query.error ? void 0 : query.data;
91
- const formatTime = (ms) => (window === "30d" ? dates$1 : times$1).format(ms);
92
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
93
- className: "grid min-w-0 gap-6 xl:grid-cols-[minmax(0,2fr)_minmax(16rem,1fr)]",
94
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Card, {
95
- "aria-label": "App usage",
96
- role: "region",
97
- className: "min-w-0 shadow-sm",
98
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(CardHeader, {
99
- className: "flex-row flex-wrap items-center justify-between gap-4",
100
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(CardTitle, { children: "App usage" }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(InsightsPeriodSelector, {
101
- window,
102
- onWindowChange
103
- })]
104
- }), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(CardContent, {
105
- className: "flex flex-col gap-4",
106
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(ReportingDevicesSummary, {
107
- window,
108
- count: report?.activeInstallations,
109
- isPending: query.isPending,
110
- partial: report?.truncated ?? false
111
- }), query.isPending ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Skeleton, {
112
- "aria-label": "Loading app usage",
113
- className: "h-48"
114
- }) : query.error ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
115
- className: "flex flex-col items-start gap-4",
116
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(InsightsErrorAlert, {
117
- error: query.error,
118
- fallbackTitle: "App usage unavailable"
119
- }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Button$1, {
120
- variant: "outline",
121
- onClick: () => void query.refetch(),
122
- children: "Retry app usage"
123
- })]
124
- }) : report?.activeInstallations === 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Empty, {
125
- className: "h-48",
126
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(EmptyHeader, { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(EmptyTitle, { children: "No activity reported" }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(EmptyDescription, { children: "Try another period, platform, channel, or app version." })] })
127
- }) : report ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", {
128
- className: "mb-2 text-right text-xs text-muted-foreground",
129
- children: "Reporting installations · UTC"
130
- }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ChartContainer, {
131
- "aria-label": "Active users per interval",
132
- className: "h-48 w-full aspect-auto",
133
- config: { installations: {
134
- label: "Active users",
135
- color: "var(--chart-2)"
136
- } },
137
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(LineChart, {
138
- accessibilityLayer: true,
139
- data: report.points,
140
- margin: {
141
- right: 8,
142
- top: 8
143
- },
144
- children: [
145
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CartesianGrid, { vertical: false }),
146
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(XAxis, {
147
- dataKey: "startMs",
148
- tick: { fill: "var(--muted-foreground)" },
149
- tickFormatter: formatTime,
150
- axisLine: false,
151
- tickLine: false,
152
- minTickGap: 45
153
- }),
154
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(YAxis, {
155
- tick: { fill: "var(--muted-foreground)" },
156
- allowDecimals: false,
157
- axisLine: false,
158
- tickLine: false,
159
- width: "auto"
160
- }),
161
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ChartTooltip, { content: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ChartTooltipContent, { labelFormatter: (_, payload) => `${times$1.format(payload[0]?.payload.startMs)} · UTC` }) }),
162
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Line, {
163
- dataKey: "installations",
164
- type: "linear",
165
- stroke: "var(--color-installations)",
166
- strokeWidth: 2,
167
- dot: { r: 2 },
168
- activeDot: { r: 4 },
169
- isAnimationActive: false
170
- })
171
- ]
172
- })
173
- })] }), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("details", {
174
- className: "text-xs text-muted-foreground",
175
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("summary", {
176
- className: "cursor-pointer py-2",
177
- children: "View usage data"
178
- }), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Table, {
179
- "aria-label": "App usage by interval",
180
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(TableHeader, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(TableRow, { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(TableHead, { children: "Interval · UTC" }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TableHead, {
181
- className: "text-right",
182
- children: "Active users"
183
- })] }) }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TableBody, { children: report.points.map((point) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(TableRow, { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(TableCell, { children: times$1.format(point.startMs) }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TableCell, {
184
- className: "text-right tabular-nums",
185
- children: point.installations?.toLocaleString() ?? "Unknown"
186
- })] }, point.startMs)) })]
187
- })]
188
- })] }) : null]
189
- })]
190
- }), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Card, {
191
- "aria-label": "Usage distribution",
192
- role: "region",
193
- className: "flex min-w-0 flex-col shadow-sm",
194
- children: [
195
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(CardHeader, {
196
- className: "flex-row items-center justify-between gap-3",
197
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(CardTitle, {
198
- className: "flex min-h-9 items-center",
199
- children: "Distribution"
200
- }), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(InsightsInfo, {
201
- label: "How distribution is counted",
202
- children: ["Each reporting installation is counted once, using the app version and platform of its latest matching report in the selected period.", report?.truncated ? " Shares reflect only the available history." : ""]
203
- })]
204
- }),
205
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CardContent, {
206
- className: "flex-1",
207
- children: query.isPending ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Skeleton, {
208
- "aria-label": "Loading distribution",
209
- className: "h-48"
210
- }) : query.error ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(InsightsErrorAlert, {
211
- error: query.error,
212
- fallbackTitle: "Distribution unavailable"
213
- }) : !report?.activeInstallations ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Empty, {
214
- className: "h-40",
215
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(EmptyHeader, { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(EmptyTitle, { children: "No reporting installations" }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(EmptyDescription, { children: "Try a different filter or period." })] })
216
- }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
217
- className: "flex flex-col gap-6",
218
- children: ["versions", "platforms"].map((dimension) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("section", {
219
- "aria-label": dimension === "versions" ? "App version distribution" : "Platform distribution",
220
- className: "flex flex-col gap-4",
221
- children: [
222
- dimension === "platforms" ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Separator$1, {}) : null,
223
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("h3", {
224
- className: "flex items-center gap-2 text-sm font-medium text-muted-foreground",
225
- children: [dimension === "versions" ? "App versions" : "Platforms", dimension === "versions" ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Badge, {
226
- variant: "secondary",
227
- children: report.versions.length
228
- }) : null]
229
- }),
230
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ScrollArea$1, {
231
- className: "min-w-0 [&_[data-slot=scroll-area-viewport]]:max-h-40",
232
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("dl", {
233
- className: "flex flex-col gap-4 pr-4",
234
- children: report[dimension].map((row) => {
235
- const name = dimension === "platforms" ? row.name === "ios" ? "iOS" : "Android" : row.name;
236
- const share = row.installations / report.activeInstallations * 100;
237
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
238
- className: "group relative flex min-h-11 flex-col gap-2 rounded-sm focus-within:ring-2 focus-within:ring-ring sm:min-h-0",
239
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
240
- className: "flex min-w-0 items-baseline justify-between gap-3",
241
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("dt", {
242
- className: "flex min-w-0 items-center gap-2 text-sm",
243
- title: name,
244
- children: [dimension === "platforms" && (row.name === "ios" || row.name === "android") ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(PlatformIcon, {
245
- platform: row.name,
246
- className: "size-4 shrink-0"
247
- }) : null, dimension === "versions" ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Link, {
248
- to: "/insights/distribution",
249
- search: {
250
- ...search,
251
- version: row.name
252
- },
253
- "aria-label": `View bundles for app version ${row.name}`,
254
- className: "flex min-w-0 items-center gap-1 after:absolute after:inset-0 group-hover:underline",
255
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
256
- className: "truncate",
257
- children: name
258
- }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ChevronRight, {
259
- "aria-hidden": "true",
260
- className: "size-3 shrink-0 text-muted-foreground"
261
- })]
262
- }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
263
- className: "truncate",
264
- children: name
265
- })]
266
- }), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("dd", {
267
- className: "flex shrink-0 gap-3 text-sm tabular-nums",
268
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: row.installations.toLocaleString() }), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", {
269
- className: "min-w-10 text-right text-muted-foreground",
270
- children: [share.toFixed(1), "%"]
271
- })]
272
- })]
273
- }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Progress$1, {
274
- "aria-label": `${name} share`,
275
- "aria-valuetext": `${row.installations} installations, ${share.toFixed(1)}%`,
276
- value: share
277
- })]
278
- }, row.name);
279
- })
280
- })
281
- })
282
- ]
283
- }, dimension))
284
- })
285
- }),
286
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CardFooter, {
287
- className: "border-t pt-4",
288
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Link, {
289
- to: "/insights/distribution",
290
- search,
291
- className: buttonVariants({
292
- variant: "outline",
293
- className: "h-11 w-full sm:h-9"
294
- }),
295
- children: ["View distribution", /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ArrowRight, {
296
- "aria-hidden": "true",
297
- "data-icon": "inline-end"
298
- })]
299
- })
300
- })
301
- ]
302
- })]
303
- });
304
- }
305
- var Combobox$1 = ComboboxRoot;
306
- function ComboboxTrigger({ className, children, ...props }) {
307
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(ComboboxTrigger$1, {
308
- "data-slot": "combobox-trigger",
309
- className: cn("[&_svg:not([class*='size-'])]:size-3.5", className),
310
- ...props,
311
- children: [children, /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ChevronDown, { className: "text-muted-foreground size-3.5 pointer-events-none" })]
312
- });
313
- }
314
- function ComboboxClear({ className, ...props }) {
315
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ComboboxClear$1, {
316
- "aria-label": "Clear selection",
317
- "data-slot": "combobox-clear",
318
- render: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(InputGroupButton, {
319
- variant: "ghost",
320
- size: "icon-xs"
321
- }),
322
- className: cn(className),
323
- ...props,
324
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(X, { className: "pointer-events-none" })
325
- });
326
- }
327
- function ComboboxInput({ className, children, disabled = false, showTrigger = true, showClear = false, ...props }) {
328
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(InputGroup, {
329
- className: cn("w-auto", className),
330
- children: [
331
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ComboboxInput$1, {
332
- render: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(InputGroupInput, { disabled }),
333
- ...props
334
- }),
335
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(InputGroupAddon, {
336
- align: "inline-end",
337
- children: [showTrigger && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ComboboxTrigger, { render: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(InputGroupButton, {
338
- size: "icon-xs",
339
- variant: "ghost",
340
- "data-slot": "input-group-button",
341
- className: "group-has-data-[slot=combobox-clear]/input-group:hidden data-pressed:bg-transparent",
342
- disabled
343
- }) }), showClear && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ComboboxClear, { disabled })]
344
- }),
345
- children
346
- ]
347
- });
348
- }
349
- function ComboboxContent({ className, side = "bottom", sideOffset = 6, align = "start", alignOffset = 0, anchor, ...props }) {
350
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ComboboxPortal, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ComboboxPositioner, {
351
- side,
352
- sideOffset,
353
- align,
354
- alignOffset,
355
- anchor,
356
- className: "isolate z-50",
357
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ComboboxPopup, {
358
- "data-slot": "combobox-content",
359
- "data-chips": !!anchor,
360
- className: cn("bg-popover text-popover-foreground data-open:animate-in data-closed:animate-out data-closed:fade-out-0 data-open:fade-in-0 data-closed:zoom-out-95 data-open:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 ring-foreground/10 *:data-[slot=input-group]:bg-input/20 dark:bg-popover max-h-72 min-w-32 overflow-hidden rounded-lg shadow-md ring-1 duration-100 *:data-[slot=input-group]:m-1 *:data-[slot=input-group]:mb-0 *:data-[slot=input-group]:h-7 *:data-[slot=input-group]:border-none *:data-[slot=input-group]:shadow-none dark group/combobox-content relative max-h-(--available-height) w-(--anchor-width) max-w-(--available-width) min-w-[calc(var(--anchor-width)+--spacing(7))] origin-(--transform-origin) data-[chips=true]:min-w-(--anchor-width)", className),
361
- ...props
362
- })
363
- }) });
364
- }
365
- function ComboboxList({ className, ...props }) {
366
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ComboboxList$1, {
367
- "data-slot": "combobox-list",
368
- className: cn("no-scrollbar max-h-[min(calc(--spacing(72)---spacing(9)),calc(var(--available-height)---spacing(9)))] scroll-py-1 overflow-y-auto p-1 data-empty:p-0 overflow-y-auto overscroll-contain", className),
369
- ...props
370
- });
371
- }
372
- function ComboboxItem({ className, children, ...props }) {
373
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(ComboboxItem$1, {
374
- "data-slot": "combobox-item",
375
- className: cn("data-highlighted:bg-accent data-highlighted:text-accent-foreground not-data-[variant=destructive]:data-highlighted:**:text-accent-foreground min-h-7 gap-2 rounded-md px-2 py-1 text-xs/relaxed [&_svg:not([class*='size-'])]:size-3.5 relative flex w-full cursor-default items-center outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0", className),
376
- ...props,
377
- children: [children, /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ComboboxItemIndicator, {
378
- render: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "pointer-events-none absolute right-2 flex items-center justify-center" }),
379
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Check, { className: "pointer-events-none" })
380
- })]
381
- });
382
- }
383
- function ComboboxEmpty({ className, ...props }) {
384
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ComboboxEmpty$1, {
385
- "data-slot": "combobox-empty",
386
- className: cn("text-muted-foreground hidden w-full justify-center py-2 text-center text-xs/relaxed group-data-empty/combobox-content:flex", className),
387
- ...props
388
- });
389
- }
390
- function InsightsControls({ onScopeChange, scope, appVersions }) {
391
- const [platform, setPlatform] = (0, import_react.useState)(scope.platform);
392
- const [channel, setChannel] = (0, import_react.useState)(scope.channel);
393
- const [appVersion, setAppVersion] = (0, import_react.useState)(scope.appVersion ?? "");
394
- const versions = [...new Set([...appVersions, ...appVersion ? [appVersion] : []])];
395
- const channelsQuery = useChannelsQuery();
396
- const channels = channelsQuery.data?.map((item) => item.name) ?? [];
397
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("form", {
398
- "aria-label": "Insights controls",
399
- onSubmit: (event) => {
400
- event.preventDefault();
401
- onScopeChange({
402
- platform,
403
- channel,
404
- ...appVersion ? { appVersion } : {}
405
- });
406
- },
407
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(FieldGroup, {
408
- className: "grid grid-cols-2 items-end gap-4 lg:grid-cols-[9rem_minmax(0,1fr)_minmax(0,1fr)_auto]",
409
- children: [
410
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Field, { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(FieldLabel, {
411
- htmlFor: "insights-platform",
412
- children: "Platform"
413
- }), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Select$1, {
414
- items: {
415
- all: "All platforms",
416
- ios: "iOS",
417
- android: "Android"
418
- },
419
- value: platform,
420
- onValueChange: (value) => {
421
- if (value === "all" || value === "ios" || value === "android") setPlatform(value);
422
- },
423
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(SelectTrigger, {
424
- id: "insights-platform",
425
- className: "min-h-11 w-full sm:min-h-9",
426
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(SelectValue, { children: [platform !== "all" ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(PlatformIcon, {
427
- platform,
428
- className: "size-3.5"
429
- }) : null, platform === "all" ? "All platforms" : platform === "ios" ? "iOS" : "Android"] })
430
- }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SelectContent, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(SelectGroup, { children: [
431
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SelectItem, {
432
- value: "all",
433
- children: "All platforms"
434
- }),
435
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(SelectItem, {
436
- value: "ios",
437
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(PlatformIcon, {
438
- platform: "ios",
439
- className: "size-3.5"
440
- }), "iOS"]
441
- }),
442
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(SelectItem, {
443
- value: "android",
444
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(PlatformIcon, {
445
- platform: "android",
446
- className: "size-3.5"
447
- }), "Android"]
448
- })
449
- ] }) })]
450
- })] }),
451
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Field, {
452
- className: "min-w-0",
453
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(FieldLabel, {
454
- htmlFor: "insights-channel",
455
- children: "Channel"
456
- }), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Combobox$1, {
457
- items: channels,
458
- value: channel,
459
- onValueChange: (value) => {
460
- if (value !== null) setChannel(value);
461
- },
462
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(ComboboxInput, {
463
- className: "h-11 w-full sm:h-9 [&_input]:h-full",
464
- id: "insights-channel",
465
- placeholder: "Search channels",
466
- maxLength: 1024
467
- }), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(ComboboxContent, { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(ComboboxEmpty, { children: channelsQuery.isPending ? "Loading channels…" : channelsQuery.isError ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
468
- className: "flex flex-col items-center gap-2 p-2",
469
- children: ["Couldn't load channels.", /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Button$1, {
470
- onClick: () => void channelsQuery.refetch(),
471
- size: "sm",
472
- variant: "outline",
473
- children: "Retry channels"
474
- })]
475
- }) : "No channels found." }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ComboboxList, { children: (item) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ComboboxItem, {
476
- className: "min-h-11 pr-8 sm:min-h-8",
477
- value: item,
478
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
479
- className: "truncate",
480
- children: item
481
- })
482
- }, item) })] })]
483
- })]
484
- }),
485
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Field, {
486
- className: "min-w-0",
487
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(FieldLabel, {
488
- htmlFor: "insights-app-version",
489
- children: "App version"
490
- }), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Select$1, {
491
- items: Object.fromEntries([["all", "All versions"], ...versions.map((version) => [`version:${version}`, version])]),
492
- value: appVersion ? `version:${appVersion}` : "all",
493
- onValueChange: (value) => {
494
- if (value !== null) setAppVersion(value === "all" ? "" : value.slice(8));
495
- },
496
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(SelectTrigger, {
497
- id: "insights-app-version",
498
- className: "min-h-11 w-full sm:min-h-9",
499
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SelectValue, {})
500
- }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SelectContent, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(SelectGroup, { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(SelectItem, {
501
- value: "all",
502
- children: "All versions"
503
- }), versions.map((version) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SelectItem, {
504
- value: `version:${version}`,
505
- children: version
506
- }, version))] }) })]
507
- })]
508
- }),
509
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Button$1, {
510
- className: "h-11 sm:h-9",
511
- size: "lg",
512
- type: "submit",
513
- variant: "outline",
514
- children: "Apply filters"
515
- })
516
- ]
517
- })
518
- });
519
- }
520
- var dates = new Intl.DateTimeFormat("en", {
521
- month: "short",
522
- day: "numeric",
523
- timeZone: "UTC"
524
- });
525
- var times = new Intl.DateTimeFormat("en", {
526
- month: "short",
527
- day: "numeric",
528
- hour: "numeric",
529
- timeZone: "UTC"
530
- });
531
- var colors = [
532
- "var(--chart-2)",
533
- "var(--foreground)",
534
- "var(--chart-1)",
535
- "var(--muted-foreground)",
536
- "var(--chart-4)"
537
- ];
538
- var dashes = [
539
- void 0,
540
- "6 3",
541
- "2 3"
542
- ];
543
- function ActivityChart({ report }) {
544
- const [metric, setMetric] = (0, import_react.useState)("active");
545
- const [selectedId, setSelectedId] = (0, import_react.useState)(null);
546
- const selected = report.series.find((series) => series.releaseId === selectedId);
547
- const config = Object.fromEntries(report.series.map((series, index) => [`bundle${index}`, {
548
- label: series.releaseId,
549
- color: colors[index % colors.length]
550
- }]));
551
- const data = (report.series[0]?.points ?? []).map((point, pointIndex) => ({
552
- startMs: point.startMs,
553
- ...Object.fromEntries(report.series.map((series, index) => [`bundle${index}`, metric === "active" ? series.points[pointIndex].active : series.points[pointIndex].recoveredInstallations]))
554
- }));
555
- const formatTick = (ms) => (report.intervalMs < 864e5 ? times : dates).format(ms);
556
- const lastSpike = selected ? [...selected.points].reverse().find((point) => point.spike) : void 0;
557
- const total = metric === "active" ? report.series.reduce((sum, series) => sum + series.activeInstallations, 0) : report.series.filter((series) => series.recoveredInstallations > 0).length;
558
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Tabs$1, {
559
- value: metric,
560
- onValueChange: (value) => {
561
- if (value === "active" || value === "rollback") setMetric(value);
562
- },
563
- className: "gap-6",
564
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(TabsList, {
565
- "aria-label": "Activity metric",
566
- variant: "line",
567
- className: "min-h-11 sm:min-h-9",
568
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(TabsTrigger, {
569
- className: "min-w-24 px-4",
570
- value: "active",
571
- children: "Active"
572
- }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TabsTrigger, {
573
- className: "min-w-24 px-4",
574
- value: "rollback",
575
- children: "Rollback"
576
- })]
577
- }), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(TabsContent, {
578
- value: metric,
579
- className: "flex flex-col gap-4",
580
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
581
- className: "flex items-baseline gap-3",
582
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", {
583
- className: "text-4xl font-semibold tracking-tight tabular-nums",
584
- children: total.toLocaleString()
585
- }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", {
586
- className: "text-sm text-muted-foreground",
587
- children: metric === "active" ? "Active installations" : "Bundles with rollbacks"
588
- })]
589
- }), report.series.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
590
- className: "flex h-48 items-center justify-center text-center text-sm text-muted-foreground",
591
- children: "No bundle reports in this period. Try another channel or check again after the app reports activity."
592
- }) : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
593
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("p", {
594
- className: "mb-2 text-right text-xs text-muted-foreground",
595
- children: [
596
- metric === "active" ? "Installations" : "Recovered installations per interval",
597
- " ",
598
- "· UTC"
599
- ]
600
- }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ChartContainer, {
601
- "aria-label": `${metric === "active" ? "Active" : "Rollback"} trend for all reported bundle IDs`,
602
- className: "h-56 w-full aspect-auto sm:h-64",
603
- config,
604
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(LineChart, {
605
- accessibilityLayer: true,
606
- data,
607
- margin: {
608
- left: -12,
609
- right: 12,
610
- top: 8
611
- },
612
- children: [
613
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CartesianGrid, { vertical: false }),
614
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(XAxis, {
615
- tick: { fill: "var(--muted-foreground)" },
616
- axisLine: false,
617
- dataKey: "startMs",
618
- minTickGap: 40,
619
- tickFormatter: formatTick,
620
- tickLine: false
621
- }),
622
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(YAxis, {
623
- tick: { fill: "var(--muted-foreground)" },
624
- allowDecimals: false,
625
- axisLine: false,
626
- tickLine: false,
627
- width: 48
628
- }),
629
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ChartTooltip, { content: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ChartTooltipContent, {
630
- className: "max-h-64 max-w-[calc(100vw-3rem)] overflow-auto",
631
- labelFormatter: (_, payload) => `${times.format(payload[0]?.payload.startMs)} · UTC`
632
- }) }),
633
- report.series.map((series, index) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Line, {
634
- dataKey: `bundle${index}`,
635
- type: "linear",
636
- stroke: `var(--color-bundle${index})`,
637
- strokeWidth: selectedId === series.releaseId ? 3 : 2,
638
- strokeOpacity: !selected || selected === series ? 1 : .4,
639
- strokeDasharray: dashes[Math.floor(index / colors.length) % dashes.length],
640
- dot: { r: 2 },
641
- activeDot: { r: 4 },
642
- isAnimationActive: false
643
- }, series.releaseId))
644
- ]
645
- })
646
- })] }),
647
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ScrollArea$1, {
648
- "aria-label": "Reported bundles",
649
- className: "min-w-0 [&_[data-slot=scroll-area-viewport]]:max-h-48",
650
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
651
- className: cn("grid grid-cols-1 gap-1 pr-3", report.series.length > 1 && "xl:grid-cols-2"),
652
- children: report.series.map((series, index) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("button", {
653
- type: "button",
654
- "aria-label": `Highlight bundle ${series.releaseId}`,
655
- "aria-pressed": selectedId === series.releaseId,
656
- title: series.releaseId,
657
- onClick: () => setSelectedId(selectedId === series.releaseId ? null : series.releaseId),
658
- className: "flex min-w-0 items-center gap-2 rounded-md px-2 py-2 text-left text-xs hover:bg-muted focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring aria-pressed:bg-muted",
659
- children: [
660
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("svg", {
661
- "aria-hidden": "true",
662
- width: "20",
663
- height: "8",
664
- className: "shrink-0",
665
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("line", {
666
- x1: "0",
667
- x2: "20",
668
- y1: "4",
669
- y2: "4",
670
- stroke: colors[index % colors.length],
671
- strokeWidth: "2",
672
- strokeDasharray: dashes[Math.floor(index / colors.length) % dashes.length]
673
- })
674
- }),
675
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
676
- className: "min-w-0 truncate font-mono",
677
- children: series.releaseId
678
- }),
679
- series.points.some((point) => point.spike) ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TriangleAlert, {
680
- "aria-label": "Rollback spike",
681
- className: "size-3 shrink-0"
682
- }) : null,
683
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {
684
- className: "ml-auto tabular-nums",
685
- children: (metric === "active" ? series.activeInstallations : series.recoveredInstallations).toLocaleString()
686
- })
687
- ]
688
- }, series.releaseId))
689
- })
690
- }),
691
- selected ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
692
- className: "flex flex-wrap items-center justify-between gap-3 border-t pt-3",
693
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
694
- className: "min-w-0 flex-1",
695
- children: [
696
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", {
697
- className: "break-all font-mono text-xs",
698
- children: selected.releaseId
699
- }),
700
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("p", {
701
- className: "mt-1 text-xs text-muted-foreground",
702
- children: [
703
- "Active ",
704
- selected.activeInstallations.toLocaleString(),
705
- " · Rollback ",
706
- selected.recoveredInstallations.toLocaleString(),
707
- " ",
708
- "in this period"
709
- ]
710
- }),
711
- metric === "rollback" && lastSpike ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("p", {
712
- className: "mt-2 flex items-center gap-2 text-xs",
713
- children: [
714
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TriangleAlert, {
715
- className: "size-3 shrink-0",
716
- "aria-hidden": "true"
717
- }),
718
- "Rollback spike on ",
719
- dates.format(lastSpike.startMs),
720
- ". Review this bundle’s delivery settings."
721
- ]
722
- }) : null
723
- ]
724
- }), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Link, {
725
- className: buttonVariants({
726
- variant: "outline",
727
- size: "sm"
728
- }),
729
- to: "/",
730
- search: { releaseId: selected.releaseId },
731
- children: ["Review bundle", /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ArrowUpRight, { "aria-hidden": "true" })]
732
- })]
733
- }) : null,
734
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("details", {
735
- className: "text-xs text-muted-foreground",
736
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("summary", {
737
- className: "cursor-pointer",
738
- children: "View chart data"
739
- }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
740
- className: "mt-2 max-h-64 overflow-auto",
741
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("table", {
742
- className: "w-full text-left",
743
- children: [
744
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("caption", {
745
- className: "sr-only",
746
- children: [
747
- metric === "active" ? "Active installations" : "Recovered installations",
748
- " ",
749
- "by bundle ID, UTC"
750
- ]
751
- }),
752
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("thead", { children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("tr", { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("th", {
753
- scope: "col",
754
- className: "pr-4",
755
- children: "Date (UTC)"
756
- }), report.series.map((series) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("th", {
757
- scope: "col",
758
- className: "px-2 font-mono",
759
- children: series.releaseId
760
- }, series.releaseId))] }) }),
761
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("tbody", { children: data.map((point, i) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("tr", { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("th", {
762
- scope: "row",
763
- className: "whitespace-nowrap pr-4 font-normal",
764
- children: times.format(point.startMs)
765
- }), report.series.map((series) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("td", {
766
- className: "px-2 tabular-nums",
767
- children: (metric === "active" ? series.points[i].active : series.points[i].recoveredInstallations) ?? "—"
768
- }, series.releaseId))] }, point.startMs)) })
769
- ]
770
- })
771
- })]
772
- })
773
- ] })]
774
- })]
775
- });
776
- }
777
- function InsightsOverview({ input, onWindowChange, query, onRefresh }) {
778
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Card, {
779
- "aria-label": "Bundle activity",
780
- className: "min-w-0 overflow-hidden shadow-sm",
781
- role: "region",
782
- children: [
783
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(CardHeader, {
784
- className: "flex-row flex-wrap items-center justify-between gap-4 p-6",
785
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(CardTitle, { children: "Bundle activity" }), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
786
- className: "flex w-full items-center justify-between gap-4 sm:w-auto",
787
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(InsightsPeriodSelector, {
788
- window: input.window,
789
- onWindowChange
790
- }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Button$1, {
791
- "aria-label": "Refresh bundle activity",
792
- className: "size-11 sm:size-9",
793
- variant: "ghost",
794
- size: "icon-lg",
795
- disabled: query.isFetching,
796
- onClick: onRefresh,
797
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(RotateCw, { "aria-hidden": "true" })
798
- })]
799
- })]
800
- }),
801
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CardContent, {
802
- className: "px-6 pb-6",
803
- children: query.isPending ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Skeleton, {
804
- "aria-label": "Loading bundle activity",
805
- className: "h-80 w-full"
806
- }) : query.error ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(InsightsErrorAlert, {
807
- error: query.error,
808
- fallbackTitle: "Bundle activity unavailable"
809
- }) : query.data ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ActivityChart, { report: query.data }, JSON.stringify(input)) : null
810
- }),
811
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(CardFooter, {
812
- className: "flex-wrap items-center justify-between gap-4 border-t px-6 py-5",
813
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
814
- className: "flex min-w-0 basis-64 flex-1 flex-col gap-2 text-xs text-muted-foreground",
815
- children: query.data && !query.error ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
816
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { children: "Active follows each installation’s last reported ID in this period. Rollbacks count recovered installations per interval." }),
817
- query.data.unattributedInstallations > 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("p", { children: [
818
- query.data.unattributedInstallations.toLocaleString(),
819
- " ",
820
- "reporting installations have no observed bundle ID and are excluded."
821
- ] }) : null,
822
- query.data.truncated ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("p", { children: [
823
- "Partial history — only reports since",
824
- " ",
825
- times.format(query.data.sinceMs),
826
- " UTC are included. Choose a shorter period to see more complete counts."
827
- ] }) : null
828
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { children: "Browse individual reports in the event log." })
829
- }), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Link, {
830
- className: cn(buttonVariants({
831
- className: "h-11 px-4 sm:h-9",
832
- size: "lg",
833
- variant: "outline"
834
- })),
835
- to: "/installations",
836
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(List, {
837
- "aria-hidden": "true",
838
- "data-icon": "inline-start"
839
- }), "All events"]
840
- })]
841
- })
842
- ]
843
- });
844
- }
845
- function InsightsPage() {
846
- const search = Route.useSearch();
847
- const navigate = Route.useNavigate();
848
- const usageWindow = search.window ?? "24h";
849
- const bundleWindow = search.bundleWindow ?? "24h";
850
- const scope = {
851
- platform: search.platform ?? "all",
852
- channel: search.channel ?? "production",
853
- appVersion: search.appVersion
854
- };
855
- const setUsageWindow = (window) => void navigate({ search: {
856
- ...search,
857
- window
858
- } });
859
- const setBundleWindow = (bundleWindow) => void navigate({ search: {
860
- ...search,
861
- bundleWindow
862
- } });
863
- const setScope = (scope) => void navigate({ search: {
864
- ...search,
865
- ...scope,
866
- appVersion: scope.appVersion
867
- } });
868
- const input = {
869
- ...scope,
870
- window: usageWindow
871
- };
872
- const bundleInput = {
873
- ...scope,
874
- window: bundleWindow
875
- };
876
- const query = useQuery({
877
- queryKey: [
878
- "insights",
879
- "app-usage",
880
- input
881
- ],
882
- queryFn: () => getAppUsageReportRpc({ data: input }),
883
- staleTime: 3e4
884
- });
885
- const bundleQuery = useQuery({
886
- queryKey: [
887
- "insights",
888
- "recovery",
889
- bundleInput
890
- ],
891
- queryFn: () => getRecoveryReportRpc({ data: bundleInput }),
892
- staleTime: 3e4
893
- });
894
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
895
- className: "flex h-svh min-h-0 flex-col",
896
- children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(InsightsPageHeader, {
897
- view: "overview",
898
- overviewSearch: search
899
- }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", {
900
- className: "min-h-0 min-w-0 flex-1 overflow-y-auto bg-muted/5 px-4 py-6 sm:p-8",
901
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", {
902
- className: "mx-auto flex w-full max-w-6xl flex-col gap-6",
903
- children: [
904
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(InsightsControls, {
905
- scope,
906
- appVersions: query.data?.appVersions ?? [],
907
- onScopeChange: setScope
908
- }, JSON.stringify(scope)),
909
- query.data?.truncated && !query.error ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Alert, { children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(AlertTitle, { children: "Partial history" }), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(AlertDescription, { children: [
910
- "Only reports since",
911
- " ",
912
- new Date(query.data.sinceMs).toLocaleString("en", { timeZone: "UTC" }),
913
- " ",
914
- "UTC are available. The active-user count is a lower bound. Choose a shorter period for a more complete view."
915
- ] })] }) : null,
916
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(AppUsage, {
917
- query,
918
- search: {
919
- ...scope,
920
- window: usageWindow,
921
- bundleWindow
922
- },
923
- window: usageWindow,
924
- onWindowChange: setUsageWindow
925
- }),
926
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(InsightsOverview, {
927
- input: bundleInput,
928
- query: bundleQuery,
929
- onWindowChange: setBundleWindow,
930
- onRefresh: () => void bundleQuery.refetch()
931
- })
932
- ]
933
- })
934
- })]
935
- });
936
- }
937
- //#endregion
938
- export { InsightsPage as component };