@hot-updater/console 1.0.0-rc.2 → 1.0.0-rc.21
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/.output/nitro.json +1 -1
- package/.output/public/assets/ConsoleFeatureUnavailable-D0LPL1Gy.js +1 -0
- package/.output/public/assets/HashValueDisplay-BmuB4FW-.js +1 -0
- package/.output/public/assets/InsightsInfo--v4SC07c.js +1 -0
- package/.output/public/assets/InsightsPageHeader-dU83CAQY.js +1 -0
- package/.output/public/assets/NotFoundPage-B5mhGG2a.js +1 -0
- package/.output/public/assets/api-D-vOVlQ4.js +1 -0
- package/.output/public/assets/api-keys-Csh8ARKU.js +1 -0
- package/.output/public/assets/api-keys-OMPUoA_A.js +1 -0
- package/.output/public/assets/arrow-left-Bwq9X1eS.js +1 -0
- package/.output/public/assets/arrow-up-right-BkOVn4if.js +1 -0
- package/.output/public/assets/card-C_7d6O9a.js +1 -0
- package/.output/public/assets/console-features-api-C1jRZTGw.js +1 -0
- package/.output/public/assets/dialog-DE8wFN_P.js +1 -0
- package/.output/public/assets/dist-C7ENGzpS.js +1 -0
- package/.output/public/assets/empty-CVd5NlQD.js +1 -0
- package/.output/public/assets/field-C06q1iC9.js +1 -0
- package/.output/public/assets/index-BeWlQtO6.js +11 -0
- package/.output/public/assets/input-group-Bi61biIA.js +1 -0
- package/.output/public/assets/insights-BjnAtC0f.js +2 -0
- package/.output/public/assets/insights-D86m11yH.js +42 -0
- package/.output/public/assets/insights-DpYstMoY.js +1 -0
- package/.output/public/assets/insights-recovery-rpc-BIm5_ALc.js +1 -0
- package/.output/public/assets/insights-search-KIF7mRtB.js +1 -0
- package/.output/public/assets/insights-usage-rpc-VHj8vyBt.js +1 -0
- package/.output/public/assets/insights_.distribution-ADcrX48c.js +2 -0
- package/.output/public/assets/insights_.distribution-CuuJUN6Y.js +1 -0
- package/.output/public/assets/insights_.distribution-DJRjuXsO.js +1 -0
- package/.output/public/assets/installations-BSBBzqWs.js +2 -0
- package/.output/public/assets/installations-DqIE6WcO.js +1 -0
- package/.output/public/assets/installations-UsELbDvw.js +1 -0
- package/.output/public/assets/loader-circle-CnCBxzHp.js +1 -0
- package/.output/public/assets/mutation-Csp7xUNh.js +1 -0
- package/.output/public/assets/preload-helper-B-cOmpLH.js +1 -0
- package/.output/public/assets/refresh-cw-FF1NtzlQ.js +1 -0
- package/.output/public/assets/routes-CoN9XHP_.js +2 -0
- package/.output/public/assets/routes-DT1jB0Zi.js +1 -0
- package/.output/public/assets/sidebar-D8mJRF15.js +3 -0
- package/.output/public/assets/styles-Bwt7v6U5.css +2 -0
- package/.output/public/assets/table-WBgfvgXg.js +1 -0
- package/.output/public/assets/useCompositeListItem-CloBmDwn.js +1 -0
- package/.output/public/assets/useMutation-DO8cvsTx.js +1 -0
- package/.output/public/assets/useOpenInteractionType-ReGr9GzJ.js +1 -0
- package/.output/public/assets/valueToPercent-BvPAi4bP.js +1 -0
- package/.output/server/{__23tanstack-start-server-fn-resolver-B7ioJhtE.mjs → __23tanstack-start-server-fn-resolver-DMRD4e4f.mjs} +51 -47
- package/.output/server/_libs/@base-ui/react+[...].mjs +7044 -3622
- package/.output/server/_libs/@reduxjs/toolkit+[...].mjs +1554 -0
- package/.output/server/_libs/@tanstack/react-router+[...].mjs +3803 -4023
- package/.output/server/_libs/@tanstack/react-router-ssr-query+[...].mjs +141 -98
- package/.output/server/_libs/d3-array.mjs +231 -0
- package/.output/server/_libs/d3-color.mjs +330 -0
- package/.output/server/_libs/d3-format.mjs +252 -0
- package/.output/server/_libs/d3-interpolate.mjs +207 -0
- package/.output/server/_libs/d3-path.mjs +77 -0
- package/.output/server/_libs/d3-scale+[...].mjs +1907 -0
- package/.output/server/_libs/d3-shape.mjs +818 -0
- package/.output/server/_libs/decimal.js-light.mjs +884 -0
- package/.output/server/_libs/es-toolkit.mjs +1159 -0
- package/.output/server/_libs/eventemitter3.mjs +236 -0
- package/.output/server/_libs/immer.mjs +532 -0
- package/.output/server/_libs/lucide-react.mjs +46 -32
- package/.output/server/_libs/next-themes.mjs +2 -2
- package/.output/server/_libs/react-redux+[...].mjs +205 -0
- package/.output/server/_libs/recharts+[...].mjs +14350 -0
- package/.output/server/_libs/sonner.mjs +2 -2
- package/.output/server/_libs/tanstack__history.mjs +68 -41
- package/.output/server/_libs/tanstack__query-core.mjs +1618 -309
- package/.output/server/_libs/tanstack__react-query.mjs +262 -22
- package/.output/server/_libs/verkit.mjs +99 -1
- package/.output/server/_runtime.mjs +10 -1
- package/.output/server/_ssr/ConsoleFeatureUnavailable-Du7jNPNS.mjs +58 -0
- package/.output/server/_ssr/{HashValueDisplay-DwpGLfrl.mjs → HashValueDisplay-GQvFkXoi.mjs} +3 -3
- package/.output/server/_ssr/InsightsInfo-Do7QSaFR.mjs +37 -0
- package/.output/server/_ssr/InsightsPageHeader-DSUWUWRc.mjs +154 -0
- package/.output/server/_ssr/NotFoundPage-DsF4Vrhg.mjs +37 -0
- package/.output/server/_ssr/api-BEiVs0H7.mjs +203 -0
- package/.output/server/_ssr/api-keys-BrvBWGRf.mjs +5 -0
- package/.output/server/_ssr/{api-keys-CZeTPQys.mjs → api-keys-K5v32nf7.mjs} +49 -9
- package/.output/server/_ssr/api-keys-rpc-B96bBllm.mjs +52 -0
- package/.output/server/_ssr/api-rpc-DcUe280B.mjs +296 -0
- package/.output/server/_ssr/{auth-rpc-DUaeOWKK.mjs → auth-rpc-C68W56DP.mjs} +6 -6
- package/.output/server/_ssr/auth.server-DM1J6NwR.mjs +5712 -0
- package/.output/server/_ssr/bundleActivity-CpuY9CTP.mjs +19 -0
- package/.output/server/_ssr/card-CPAEKx0w.mjs +49 -0
- package/.output/server/_ssr/config-nsIcsHh8.mjs +15 -0
- package/.output/server/_ssr/config.server-DDCZk3Sq.mjs +36 -0
- package/.output/server/_ssr/console-access-Da-2Qd7q.mjs +17 -0
- package/.output/server/_ssr/console-features-Dzu2iUGD.mjs +55 -0
- package/.output/server/_ssr/console-features-api-xAsSgFa_.mjs +43 -0
- package/.output/server/_ssr/console-features-rpc-qARGpB24.mjs +19 -0
- package/.output/server/_ssr/{createServerFn-B2hcXoPM.mjs → createMiddleware-BdBf_ezN.mjs} +67 -56
- package/.output/server/_ssr/{createServerRpc-DB29C_5p.mjs → createServerRpc-B_y2lrwA.mjs} +2 -2
- package/.output/server/_ssr/{databaseJsonValue-d6I3nAS4.mjs → databaseJsonValue-Bhxciy7Z.mjs} +28 -5
- package/.output/server/_ssr/databaseRows-DwMAjaF8.mjs +74 -0
- package/.output/server/_ssr/{dialog-DS-nw-pA.mjs → dialog-q__BJ7mQ.mjs} +2 -2
- package/.output/server/_ssr/{dist-CyzPaI5v.mjs → dist-Cxo9ghYv.mjs} +140 -6
- package/.output/server/_ssr/{downloadBundle-CNnYxYO2.mjs → downloadBundle-BW9I-pMQ.mjs} +10 -10
- package/.output/server/_ssr/empty-DcBTAooP.mjs +49 -0
- package/.output/server/_ssr/{empty-plugin-adapters-B5QvGpEl.mjs → empty-plugin-adapters-CYdinE-i.mjs} +1 -1
- package/.output/server/_ssr/{table-CnZmon_Z.mjs → field-QCDBVpXA.mjs} +63 -51
- package/.output/server/_ssr/getBundleChildren-DIAGCF4a.mjs +22 -0
- package/.output/server/_ssr/{input-group-BpsnmvZw.mjs → input-group-hCk2nUoU.mjs} +2 -2
- package/.output/server/_ssr/insights-BfBO0RFr.mjs +1238 -0
- package/.output/server/_ssr/insights-DsAU3-TB.mjs +14 -0
- package/.output/server/_ssr/insights-RIfg447W.mjs +5 -0
- package/.output/server/_ssr/insights-api-CDn-QQHU.mjs +105 -0
- package/.output/server/_ssr/insights-failures-BBGMhuUr.mjs +44 -0
- package/.output/server/_ssr/insights-failures-rpc-rA2dctK2.mjs +21 -0
- package/.output/server/_ssr/insights-recovery-Dpk6Mfb9.mjs +28 -0
- package/.output/server/_ssr/insights-recovery-rpc-BCaF-xSd.mjs +46 -0
- package/.output/server/_ssr/insights-recovery-rpc-CcgYyUHk.mjs +20 -0
- package/.output/server/_ssr/{insights-rpc-38DujK0G.mjs → insights-rpc-keycmwzw.mjs} +22 -14
- package/.output/server/_ssr/insights-search-BRg5VsNe.mjs +25 -0
- package/.output/server/_ssr/insights-usage-cbw9n2Fq.mjs +29 -0
- package/.output/server/_ssr/insights-usage-rpc-BKgV1QDf.mjs +29 -0
- package/.output/server/_ssr/insights-usage-rpc-D-JYachy.mjs +41 -0
- package/.output/server/_ssr/insightsRecovery-B7oMc8d8.mjs +45 -0
- package/.output/server/_ssr/insightsUsage-Oa7kk5ek.mjs +56 -0
- package/.output/server/_ssr/insights_.distribution-BIqOqRW0.mjs +335 -0
- package/.output/server/_ssr/insights_.distribution-CuUrDa7P.mjs +5 -0
- package/.output/server/_ssr/insights_.distribution-RT_6x_ud.mjs +14 -0
- package/.output/server/_ssr/{installations-DiVKEF5T.mjs → installations-BO5CjX2z.mjs} +517 -54
- package/.output/server/_ssr/installations-BjaHiIfh.mjs +5 -0
- package/.output/server/_ssr/installations-Dt5luA-N.mjs +69 -0
- package/.output/server/_ssr/listReleases-BitHzOYB.mjs +79 -0
- package/.output/server/_ssr/releaseManagement-B3e7I8J9.mjs +11 -0
- package/.output/server/_ssr/{router-B9wG_9f8.mjs → router-DfVAixxe.mjs} +135 -139
- package/.output/server/_ssr/{routes-D7Yh_jfj.mjs → routes-C6LstNp8.mjs} +176 -455
- package/.output/server/_ssr/routes-Q3Uhmwwz.mjs +292 -0
- package/.output/server/_ssr/runtime.server-fL0o6I2b.mjs +1459 -0
- package/.output/server/_ssr/schema-BKY9SqaY.mjs +25 -0
- package/.output/server/_ssr/select-CUlInmjk.mjs +107 -0
- package/.output/server/_ssr/server-C43wq9ft.mjs +8330 -0
- package/.output/server/_ssr/{createSsrRpc-DjWNJ0uc.mjs → sidebar-DKbx2ach.mjs} +117 -63
- package/.output/server/_ssr/ssr.mjs +1 -1
- package/.output/server/_ssr/start-BXUOv_n8.mjs +4 -0
- package/.output/server/_ssr/table-NGWV8B-S.mjs +53 -0
- package/.output/server/_ssr/updateFailures-Jwe2Baab.mjs +24 -0
- package/.output/server/_ssr/{uuidv7-D0QFkPL_.mjs → uuidv7-C8bwiZr8.mjs} +2 -2
- package/.output/server/_tanstack-start-manifest_v-WQ5qGn8n.mjs +124 -0
- package/.output/server/index.mjs +267 -162
- package/LICENSE +13 -14
- package/README.md +82 -72
- package/lib/index.d.mts +23 -11
- package/lib/vite-internal.mjs +13 -3
- package/lib/vite.d.mts +2 -0
- package/package.json +14 -14
- package/src/components/AppSidebar.tsx +100 -71
- package/src/components/ConsoleAccessPage.tsx +5 -1
- package/src/components/ConsoleFeatureUnavailable.tsx +80 -0
- package/src/components/NotFoundPage.tsx +7 -7
- package/src/components/features/FeatureSlots.tsx +99 -0
- package/src/components/features/api-keys/apiKeysFeatureUi.tsx +15 -0
- package/src/components/features/bundles/BundleMetadata.tsx +8 -5
- package/src/components/features/bundles/RolloutCohortsDialog.tsx +1 -1
- package/src/components/features/channels/ChannelManagementDialog.tsx +2 -5
- package/src/components/features/insights/AppUsage.tsx +370 -0
- package/src/components/features/insights/EstimatedCount.tsx +18 -0
- package/src/components/features/insights/EventDetails.tsx +117 -37
- package/src/components/features/insights/EventHistoryCard.tsx +112 -26
- package/src/components/features/insights/EventHistoryList.tsx +2 -2
- package/src/components/features/insights/InsightsControls.tsx +265 -102
- package/src/components/features/insights/InsightsErrorAlert.tsx +14 -1
- package/src/components/features/insights/InsightsInfo.tsx +48 -0
- package/src/components/features/insights/InsightsOverview.tsx +176 -173
- package/src/components/features/insights/InsightsPageHeader.tsx +35 -20
- package/src/components/features/insights/InsightsPeriodSelector.tsx +89 -0
- package/src/components/features/insights/InstallationHistoryCard.tsx +52 -10
- package/src/components/features/insights/InstallationMatchesCard.tsx +1 -1
- package/src/components/features/insights/ReleaseActivity.tsx +188 -0
- package/src/components/features/insights/ReportingDevicesSummary.tsx +65 -0
- package/src/components/features/insights/UpdateFailures.tsx +319 -0
- package/src/components/features/insights/insightsFeatureUi.tsx +35 -0
- package/src/components/features/releases/ReleaseEditorSheet.tsx +30 -7
- package/src/components/ui/card.tsx +1 -1
- package/src/components/ui/empty.tsx +101 -0
- package/src/components/ui/scroll-area.tsx +52 -0
- package/src/components/ui/sidebar.tsx +22 -29
- package/src/components/ui/tabs.tsx +81 -0
- package/src/index.ts +26 -19
- package/src/lib/api-keys-api.ts +0 -28
- package/src/lib/api-keys-rpc.ts +27 -38
- package/src/lib/api-rpc.ts +189 -266
- package/src/lib/api.ts +19 -102
- package/src/lib/bundle-activity.ts +31 -0
- package/src/lib/console-access.ts +20 -0
- package/src/lib/console-features-api.ts +68 -0
- package/src/lib/console-features-rpc.ts +13 -0
- package/src/lib/console-features.ts +91 -0
- package/src/lib/insights-api.ts +37 -1
- package/src/lib/insights-failures-rpc.ts +21 -0
- package/src/lib/insights-failures.ts +129 -0
- package/src/lib/insights-recovery-rpc.ts +51 -0
- package/src/lib/insights-recovery.ts +68 -0
- package/src/lib/insights-retention.ts +21 -0
- package/src/lib/insights-rpc.ts +30 -12
- package/src/lib/insights-search.ts +58 -0
- package/src/lib/insights-usage-rpc.ts +29 -0
- package/src/lib/insights-usage.ts +74 -0
- package/src/lib/insights-view.ts +38 -2
- package/src/lib/scroll-restoration.ts +21 -0
- package/src/lib/server/adminInsights.ts +124 -0
- package/src/lib/server/auth.server.ts +13 -5
- package/src/lib/server/bundleActivity.ts +37 -0
- package/src/lib/server/config.server.ts +21 -74
- package/src/lib/server/console-feature-apis.ts +59 -0
- package/src/lib/server/console-runtime.server.ts +82 -38
- package/src/lib/server/downloadBundle.ts +16 -15
- package/src/lib/server/getBundleChildren.ts +31 -122
- package/src/lib/server/insightsRecovery.ts +55 -0
- package/src/lib/server/insightsUsage.ts +63 -0
- package/src/lib/server/listReleases.ts +109 -44
- package/src/lib/server/releaseReachability.ts +8 -7
- package/src/lib/server/runtime.server.ts +120 -31
- package/src/lib/server/updateFailures.ts +31 -0
- package/src/routeTree.gen.ts +44 -44
- package/src/router.tsx +3 -2
- package/src/routes/-installations-search.ts +32 -8
- package/src/routes/-releases-search.ts +76 -29
- package/src/routes/__root.tsx +10 -4
- package/src/routes/api/bundles/$bundleId/download.ts +2 -5
- package/src/routes/api-keys.tsx +5 -2
- package/src/routes/index.tsx +167 -104
- package/src/routes/insights.tsx +100 -59
- package/src/routes/insights_.distribution.tsx +398 -0
- package/src/routes/installations.tsx +98 -41
- package/src/vite-internal.ts +15 -3
- package/src/vite.ts +2 -0
- package/.output/public/assets/HashValueDisplay-CB0Eskit.js +0 -1
- package/.output/public/assets/InsightsPageHeader-Car5LNiZ.js +0 -1
- package/.output/public/assets/api-keys-BzKocqRy.js +0 -1
- package/.output/public/assets/api-keys-api-BHcODB7q.js +0 -1
- package/.output/public/assets/card-Dhr_eFYj.js +0 -1
- package/.output/public/assets/chart-no-axes-combined-Dy4WJv2U.js +0 -1
- package/.output/public/assets/composite-Bp98A0Ld.js +0 -1
- package/.output/public/assets/createServerFn-CA8fs7QD.js +0 -3
- package/.output/public/assets/dialog-CUTrcPlB.js +0 -1
- package/.output/public/assets/dist-C_NydL0e.js +0 -1
- package/.output/public/assets/index-DdAz-CXv.js +0 -10
- package/.output/public/assets/input-group-cSOG4wh_.js +0 -1
- package/.output/public/assets/insights-C0PBSZ-n.js +0 -1
- package/.output/public/assets/installations-CE33wgbY.js +0 -2
- package/.output/public/assets/installations-CStZja8x.js +0 -1
- package/.output/public/assets/lazyRouteComponent-Ccp3bwBY.js +0 -1
- package/.output/public/assets/link-CI8idAUi.js +0 -1
- package/.output/public/assets/loader-circle-BoxLrsOu.js +0 -1
- package/.output/public/assets/preload-helper-CQ36nxok.js +0 -1
- package/.output/public/assets/refresh-cw-Bqc72UZG.js +0 -1
- package/.output/public/assets/routes-DGVXdzpw.js +0 -2
- package/.output/public/assets/routes-DTlwOr8I.js +0 -1
- package/.output/public/assets/shield-check-uK3MHWJZ.js +0 -1
- package/.output/public/assets/signing-CMf4aqDO.js +0 -1
- package/.output/public/assets/styles-BCvbtKsm.css +0 -2
- package/.output/public/assets/table-2vcV89QB.js +0 -1
- package/.output/public/assets/useCompositeListItem-CHLITE_4.js +0 -1
- package/.output/public/assets/x-DCd0j8c6.js +0 -1
- package/.output/server/_ssr/InsightsPageHeader-Df4Brj8u.mjs +0 -484
- package/.output/server/_ssr/api-keys-api-BUPQVSpk.mjs +0 -60
- package/.output/server/_ssr/api-keys-rpc-Cs7tS5_j.mjs +0 -136
- package/.output/server/_ssr/api-rpc-tAupfGQm.mjs +0 -1399
- package/.output/server/_ssr/auth.server-DW71WzsD.mjs +0 -47
- package/.output/server/_ssr/bundle-signing-rpc-BhnBw0-d.mjs +0 -16
- package/.output/server/_ssr/bundle-signing.server-C4NW5mWx.mjs +0 -12
- package/.output/server/_ssr/card-BRiPmi0C.mjs +0 -108
- package/.output/server/_ssr/config-Dv8qLDZ0.mjs +0 -13
- package/.output/server/_ssr/config.server-afDuAwaG.mjs +0 -368
- package/.output/server/_ssr/databaseRows-5bCRTxm-.mjs +0 -126
- package/.output/server/_ssr/deleteBundle-BTGwBgzx.mjs +0 -66
- package/.output/server/_ssr/getBundleChildren-C0vh4ZvE.mjs +0 -50
- package/.output/server/_ssr/insights-BdS364Xu.mjs +0 -460
- package/.output/server/_ssr/insightsContract-fjJDBeEE.mjs +0 -303
- package/.output/server/_ssr/installations-CtA59MQG.mjs +0 -29
- package/.output/server/_ssr/routes-CKrrS2q2.mjs +0 -37
- package/.output/server/_ssr/runtime.server-DacU1TBV.mjs +0 -438
- package/.output/server/_ssr/server-D_C2rMzf.mjs +0 -7468
- package/.output/server/_ssr/signing-Dz1WkZOf.mjs +0 -133
- package/.output/server/_ssr/start-DpViQGnt.mjs +0 -4
- package/.output/server/_tanstack-start-manifest_v-2MjTyxil.mjs +0 -97
- package/src/components/features/insights/InsightsBundleReports.tsx +0 -51
- package/src/components/features/signing/BundleSigningPage.tsx +0 -139
- package/src/lib/bundle-signing-api.ts +0 -14
- package/src/lib/bundle-signing-rpc.ts +0 -16
- package/src/lib/server/bundle-signing.server.ts +0 -23
- package/src/lib/server/deleteBundle.ts +0 -145
- package/src/routes/signing.tsx +0 -37
|
@@ -2,7 +2,13 @@ import { RefreshCw } from "lucide-react";
|
|
|
2
2
|
|
|
3
3
|
import { HashValueDisplay } from "@/components/HashValueDisplay";
|
|
4
4
|
import { Button } from "@/components/ui/button";
|
|
5
|
-
import {
|
|
5
|
+
import {
|
|
6
|
+
Card,
|
|
7
|
+
CardContent,
|
|
8
|
+
CardDescription,
|
|
9
|
+
CardHeader,
|
|
10
|
+
CardTitle,
|
|
11
|
+
} from "@/components/ui/card";
|
|
6
12
|
import { Separator } from "@/components/ui/separator";
|
|
7
13
|
import { Skeleton } from "@/components/ui/skeleton";
|
|
8
14
|
import {
|
|
@@ -13,6 +19,11 @@ import {
|
|
|
13
19
|
TableHeader,
|
|
14
20
|
TableRow,
|
|
15
21
|
} from "@/components/ui/table";
|
|
22
|
+
import {
|
|
23
|
+
DEFAULT_INSIGHTS_RETENTION,
|
|
24
|
+
formatDays,
|
|
25
|
+
type InsightsRetentionDays,
|
|
26
|
+
} from "@/lib/insights-retention";
|
|
16
27
|
import type {
|
|
17
28
|
InsightsEventRow,
|
|
18
29
|
InsightsInstallationViewRow,
|
|
@@ -22,24 +33,25 @@ import type {
|
|
|
22
33
|
import {
|
|
23
34
|
EventBundleTransition,
|
|
24
35
|
EventTimestamp,
|
|
25
|
-
|
|
36
|
+
EventTypeDetails,
|
|
26
37
|
useInsightsTimeFormat,
|
|
27
38
|
} from "./EventDetails";
|
|
28
39
|
import { EventHistoryList } from "./EventHistoryList";
|
|
29
40
|
import { InsightsErrorAlert } from "./InsightsErrorAlert";
|
|
30
41
|
import { InsightsPagination } from "./InsightsPagination";
|
|
31
42
|
|
|
32
|
-
const getUserLabel = (event: {
|
|
33
|
-
|
|
34
|
-
readonly userId: string | null;
|
|
35
|
-
}) => event.userId ?? event.username ?? "—";
|
|
43
|
+
const getUserLabel = (event: { readonly userId: string | null }) =>
|
|
44
|
+
event.userId ?? "—";
|
|
36
45
|
|
|
46
|
+
/** A download or a failed update leaves the installation on the bundle it ran. */
|
|
37
47
|
const getLastKnownBundleId = (
|
|
38
48
|
event: InsightsEventRow | InsightsInstallationViewRow,
|
|
39
49
|
) =>
|
|
40
50
|
"lastKnownBundleId" in event
|
|
41
51
|
? event.lastKnownBundleId
|
|
42
|
-
:
|
|
52
|
+
: event.type === "UPDATE_DOWNLOADED" || event.type === "UPDATE_FAILED"
|
|
53
|
+
? event.fromBundleId
|
|
54
|
+
: event.toBundleId;
|
|
43
55
|
|
|
44
56
|
export function InstallationHistoryCard({
|
|
45
57
|
error,
|
|
@@ -49,6 +61,7 @@ export function InstallationHistoryCard({
|
|
|
49
61
|
onPrevious,
|
|
50
62
|
onRefresh,
|
|
51
63
|
pageNumber,
|
|
64
|
+
retention = DEFAULT_INSIGHTS_RETENTION,
|
|
52
65
|
selectedEvent,
|
|
53
66
|
selectedInstallId,
|
|
54
67
|
}: {
|
|
@@ -59,6 +72,8 @@ export function InstallationHistoryCard({
|
|
|
59
72
|
readonly onNext: () => void;
|
|
60
73
|
readonly onPrevious: () => void;
|
|
61
74
|
readonly pageNumber: number;
|
|
75
|
+
/** How long the server keeps Insights rows. */
|
|
76
|
+
readonly retention?: InsightsRetentionDays;
|
|
62
77
|
readonly selectedEvent:
|
|
63
78
|
| InsightsEventRow
|
|
64
79
|
| InsightsInstallationViewRow
|
|
@@ -70,6 +85,15 @@ export function InstallationHistoryCard({
|
|
|
70
85
|
? getLastKnownBundleId(selectedEvent)
|
|
71
86
|
: undefined;
|
|
72
87
|
|
|
88
|
+
const pendingBundleId =
|
|
89
|
+
selectedEvent && "pendingBundleId" in selectedEvent
|
|
90
|
+
? selectedEvent.pendingBundleId
|
|
91
|
+
: selectedEvent &&
|
|
92
|
+
"type" in selectedEvent &&
|
|
93
|
+
selectedEvent.type === "UPDATE_DOWNLOADED"
|
|
94
|
+
? selectedEvent.toBundleId
|
|
95
|
+
: null;
|
|
96
|
+
|
|
73
97
|
return (
|
|
74
98
|
<Card className="@container min-h-0 min-w-0 shadow-sm">
|
|
75
99
|
<CardHeader className="p-4 sm:p-6">
|
|
@@ -82,6 +106,14 @@ export function InstallationHistoryCard({
|
|
|
82
106
|
: "Select an installation"}
|
|
83
107
|
</h2>
|
|
84
108
|
</CardTitle>
|
|
109
|
+
{selectedInstallId !== undefined ? (
|
|
110
|
+
<CardDescription>
|
|
111
|
+
Bundle changes and update failures are kept for{" "}
|
|
112
|
+
{formatDays(retention.rawDays)}; the latest report, for{" "}
|
|
113
|
+
{formatDays(retention.dailyDays)} after the installation last
|
|
114
|
+
reports.
|
|
115
|
+
</CardDescription>
|
|
116
|
+
) : null}
|
|
85
117
|
</div>
|
|
86
118
|
{onRefresh && selectedInstallId !== undefined ? (
|
|
87
119
|
<Button
|
|
@@ -138,6 +170,16 @@ export function InstallationHistoryCard({
|
|
|
138
170
|
)}
|
|
139
171
|
</dd>
|
|
140
172
|
</div>
|
|
173
|
+
{pendingBundleId ? (
|
|
174
|
+
<div className="col-span-2 min-w-0">
|
|
175
|
+
<dt className="text-xs text-muted-foreground">
|
|
176
|
+
Downloaded · Pending apply
|
|
177
|
+
</dt>
|
|
178
|
+
<dd className="mt-1 text-xs">
|
|
179
|
+
<HashValueDisplay value={pendingBundleId} />
|
|
180
|
+
</dd>
|
|
181
|
+
</div>
|
|
182
|
+
) : null}
|
|
141
183
|
</dl>
|
|
142
184
|
</section>
|
|
143
185
|
<Separator />
|
|
@@ -192,7 +234,7 @@ export function InstallationHistoryCard({
|
|
|
192
234
|
/>
|
|
193
235
|
</TableCell>
|
|
194
236
|
<TableCell>
|
|
195
|
-
<
|
|
237
|
+
<EventTypeDetails event={event} />
|
|
196
238
|
</TableCell>
|
|
197
239
|
<TableCell className="whitespace-normal text-xs">
|
|
198
240
|
<div className="flex flex-col gap-2">
|
|
@@ -226,8 +268,8 @@ export function InstallationHistoryCard({
|
|
|
226
268
|
) : (
|
|
227
269
|
<>
|
|
228
270
|
<div className="p-6 text-sm text-muted-foreground">
|
|
229
|
-
{pageNumber > 1
|
|
230
|
-
? "No bundle changes
|
|
271
|
+
{pageNumber > 1
|
|
272
|
+
? "No older bundle changes."
|
|
231
273
|
: "No bundle changes recorded yet."}
|
|
232
274
|
</div>
|
|
233
275
|
{history && (pageNumber > 1 || history.nextCursor) ? (
|
|
@@ -17,7 +17,7 @@ const getLastKnownBundleId = (event: InsightsInstallationViewRow) =>
|
|
|
17
17
|
event.lastKnownBundleId;
|
|
18
18
|
|
|
19
19
|
const getUserLabel = (event: InsightsInstallationViewRow) =>
|
|
20
|
-
event.userId ??
|
|
20
|
+
event.userId ?? "—";
|
|
21
21
|
|
|
22
22
|
export function InstallationMatchesCard({
|
|
23
23
|
error,
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
import { Link } from "@tanstack/react-router";
|
|
2
|
+
|
|
3
|
+
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
|
|
4
|
+
import { Skeleton } from "@/components/ui/skeleton";
|
|
5
|
+
import type {
|
|
6
|
+
BundleActivityInput,
|
|
7
|
+
BundleActivityReport,
|
|
8
|
+
} from "@/lib/bundle-activity";
|
|
9
|
+
import { useBundleActivityQuery } from "@/lib/bundle-activity";
|
|
10
|
+
import { useConsoleFeature } from "@/lib/console-features-api";
|
|
11
|
+
import { useUpdateFailuresQuery } from "@/lib/insights-api";
|
|
12
|
+
import { failureRate, formatRate } from "@/lib/insights-failures";
|
|
13
|
+
|
|
14
|
+
import type { ReleaseColumn } from "../FeatureSlots";
|
|
15
|
+
import { InsightsInfo } from "./InsightsInfo";
|
|
16
|
+
|
|
17
|
+
const crashRate = (report: BundleActivityReport): string => {
|
|
18
|
+
const attempts = report.activeDays + report.failedLaunches;
|
|
19
|
+
return attempts === 0
|
|
20
|
+
? "—"
|
|
21
|
+
: `${((report.failedLaunches / attempts) * 100).toFixed(2)}%`;
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
export function BundleMovementSummary({
|
|
25
|
+
report,
|
|
26
|
+
loading = false,
|
|
27
|
+
input,
|
|
28
|
+
}: {
|
|
29
|
+
readonly report?: BundleActivityReport;
|
|
30
|
+
readonly loading?: boolean;
|
|
31
|
+
readonly input?: BundleActivityInput;
|
|
32
|
+
}) {
|
|
33
|
+
if (!report) {
|
|
34
|
+
return loading ? (
|
|
35
|
+
<Skeleton aria-label="Loading release insights" className="h-4 w-40" />
|
|
36
|
+
) : (
|
|
37
|
+
<span aria-label="Release insights unavailable">—</span>
|
|
38
|
+
);
|
|
39
|
+
}
|
|
40
|
+
const metrics = (
|
|
41
|
+
<span className="flex min-w-[220px] flex-wrap items-baseline gap-x-3 gap-y-1 text-sm">
|
|
42
|
+
<span>Downloads {report.downloads.toLocaleString()}</span>
|
|
43
|
+
<span>Active days {report.activeDays.toLocaleString()}</span>
|
|
44
|
+
<span>
|
|
45
|
+
Known crashes {report.failedLaunches.toLocaleString()} (
|
|
46
|
+
{crashRate(report)})
|
|
47
|
+
</span>
|
|
48
|
+
{report.coverage.kind === "partial" ? (
|
|
49
|
+
<span className="text-xs text-muted-foreground">Partial</span>
|
|
50
|
+
) : null}
|
|
51
|
+
</span>
|
|
52
|
+
);
|
|
53
|
+
return (
|
|
54
|
+
<span className="flex items-center gap-1">
|
|
55
|
+
{input ? (
|
|
56
|
+
<Link
|
|
57
|
+
className="rounded-sm hover:underline focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring"
|
|
58
|
+
to="/insights"
|
|
59
|
+
search={{
|
|
60
|
+
healthPlatform: input.platform,
|
|
61
|
+
healthChannel: input.channel,
|
|
62
|
+
releaseId: input.releaseId,
|
|
63
|
+
bundleWindow: "7d",
|
|
64
|
+
}}
|
|
65
|
+
>
|
|
66
|
+
{metrics}
|
|
67
|
+
</Link>
|
|
68
|
+
) : (
|
|
69
|
+
metrics
|
|
70
|
+
)}
|
|
71
|
+
<InsightsInfo label="About release insight metrics">
|
|
72
|
+
Active days count each installation once for each UTC day it launched
|
|
73
|
+
this release. Known crashes are reported OTA launch failures that
|
|
74
|
+
triggered recovery. The rate is known crashes divided by active days
|
|
75
|
+
plus known crashes.
|
|
76
|
+
</InsightsInfo>
|
|
77
|
+
</span>
|
|
78
|
+
);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/** The release's failed downloads and installs since its first report, and their rate. */
|
|
82
|
+
export function BundleDownloadFailures({
|
|
83
|
+
input,
|
|
84
|
+
}: {
|
|
85
|
+
readonly input: BundleActivityInput;
|
|
86
|
+
}) {
|
|
87
|
+
const query = useUpdateFailuresQuery({
|
|
88
|
+
platform: input.platform,
|
|
89
|
+
channel: input.channel,
|
|
90
|
+
releaseId: input.releaseId,
|
|
91
|
+
});
|
|
92
|
+
const report = query.data;
|
|
93
|
+
return (
|
|
94
|
+
<span className="flex items-center gap-1 text-sm">
|
|
95
|
+
{report ? (
|
|
96
|
+
<span>
|
|
97
|
+
Download failures {report.failedUpdates.toLocaleString()} (
|
|
98
|
+
{formatRate(failureRate(report))})
|
|
99
|
+
</span>
|
|
100
|
+
) : query.isPending ? (
|
|
101
|
+
<Skeleton aria-label="Loading download failures" className="h-4 w-40" />
|
|
102
|
+
) : (
|
|
103
|
+
<span aria-label="Download failures unavailable">—</span>
|
|
104
|
+
)}
|
|
105
|
+
<InsightsInfo label="About download failures">
|
|
106
|
+
Reported failures to download or install this release, since its first
|
|
107
|
+
report; each client reports one at most once a UTC day. The rate is the
|
|
108
|
+
failure rate of update attempts: failures divided by failures plus
|
|
109
|
+
download reports.
|
|
110
|
+
</InsightsInfo>
|
|
111
|
+
</span>
|
|
112
|
+
);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/** The bundle detail's Insights card, a section of the release editor: activity and download failures. */
|
|
116
|
+
export function BundleInsightsSummary({
|
|
117
|
+
input,
|
|
118
|
+
}: {
|
|
119
|
+
readonly input: BundleActivityInput;
|
|
120
|
+
}) {
|
|
121
|
+
const query = useBundleActivityQuery([input]);
|
|
122
|
+
return (
|
|
123
|
+
<Card>
|
|
124
|
+
<CardHeader className="px-4 pt-4 pb-3">
|
|
125
|
+
<CardTitle className="text-sm font-medium">Insights</CardTitle>
|
|
126
|
+
</CardHeader>
|
|
127
|
+
<CardContent className="flex flex-col gap-2 px-4 pb-4">
|
|
128
|
+
<BundleMovementSummary
|
|
129
|
+
input={input}
|
|
130
|
+
loading={query.isFetching}
|
|
131
|
+
report={query.data?.[input.releaseId]}
|
|
132
|
+
/>
|
|
133
|
+
<BundleDownloadFailures input={input} />
|
|
134
|
+
</CardContent>
|
|
135
|
+
</Card>
|
|
136
|
+
);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* The release editor's Insights card where the console reads no release
|
|
141
|
+
* activity, as through a self-hosted server's admin API: download failures
|
|
142
|
+
* alone. With release activity, its card shows them.
|
|
143
|
+
*/
|
|
144
|
+
export function ReleaseFailuresSection({
|
|
145
|
+
input,
|
|
146
|
+
}: {
|
|
147
|
+
readonly input: BundleActivityInput;
|
|
148
|
+
}) {
|
|
149
|
+
const activity = useConsoleFeature("insightsAnalytics");
|
|
150
|
+
if (activity) return null;
|
|
151
|
+
return (
|
|
152
|
+
<Card>
|
|
153
|
+
<CardHeader className="px-4 pt-4 pb-3">
|
|
154
|
+
<CardTitle className="text-sm font-medium">Insights</CardTitle>
|
|
155
|
+
</CardHeader>
|
|
156
|
+
<CardContent className="px-4 pb-4">
|
|
157
|
+
<BundleDownloadFailures input={input} />
|
|
158
|
+
</CardContent>
|
|
159
|
+
</Card>
|
|
160
|
+
);
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* One release's activity in the Bundles page's Insights column. Every cell
|
|
165
|
+
* asks for the page's releases under one query key, so the page makes one
|
|
166
|
+
* request.
|
|
167
|
+
*/
|
|
168
|
+
function ReleaseActivityCell({
|
|
169
|
+
releaseId,
|
|
170
|
+
releases,
|
|
171
|
+
}: {
|
|
172
|
+
readonly releaseId: string;
|
|
173
|
+
readonly releases: readonly BundleActivityInput[];
|
|
174
|
+
}) {
|
|
175
|
+
const query = useBundleActivityQuery(releases);
|
|
176
|
+
return (
|
|
177
|
+
<BundleMovementSummary
|
|
178
|
+
input={releases.find((release) => release.releaseId === releaseId)}
|
|
179
|
+
loading={query.isFetching}
|
|
180
|
+
report={query.data?.[releaseId]}
|
|
181
|
+
/>
|
|
182
|
+
);
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
/** The Bundles page's Insights column: each release's downloads, active days, and crashes. */
|
|
186
|
+
export const releaseActivityColumn: ReleaseColumn = {
|
|
187
|
+
Cell: ReleaseActivityCell,
|
|
188
|
+
};
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { Skeleton } from "@/components/ui/skeleton";
|
|
2
|
+
import {
|
|
3
|
+
DEFAULT_INSIGHTS_RETENTION,
|
|
4
|
+
formatDays,
|
|
5
|
+
type InsightsRetentionDays,
|
|
6
|
+
} from "@/lib/insights-retention";
|
|
7
|
+
import { usageMetrics, type UsageWindow } from "@/lib/insights-usage";
|
|
8
|
+
|
|
9
|
+
import { EstimatedCount } from "./EstimatedCount";
|
|
10
|
+
import { InsightsInfo } from "./InsightsInfo";
|
|
11
|
+
|
|
12
|
+
export function ReportingDevicesSummary({
|
|
13
|
+
window,
|
|
14
|
+
count,
|
|
15
|
+
isPending,
|
|
16
|
+
partial,
|
|
17
|
+
retention = DEFAULT_INSIGHTS_RETENTION,
|
|
18
|
+
}: {
|
|
19
|
+
readonly window: UsageWindow;
|
|
20
|
+
readonly count: number | undefined;
|
|
21
|
+
readonly isPending: boolean;
|
|
22
|
+
readonly partial: boolean;
|
|
23
|
+
readonly retention?: InsightsRetentionDays;
|
|
24
|
+
}) {
|
|
25
|
+
const metric = usageMetrics[window];
|
|
26
|
+
return (
|
|
27
|
+
<div
|
|
28
|
+
aria-label={`${metric.label} over ${metric.period}`}
|
|
29
|
+
role="region"
|
|
30
|
+
className="flex items-center gap-3"
|
|
31
|
+
>
|
|
32
|
+
{isPending ? (
|
|
33
|
+
<Skeleton aria-label="Loading active users" className="h-9 w-12" />
|
|
34
|
+
) : (
|
|
35
|
+
<p className="text-4xl font-semibold tracking-tight tabular-nums">
|
|
36
|
+
{count === undefined ? (
|
|
37
|
+
"—"
|
|
38
|
+
) : partial ? (
|
|
39
|
+
`≥${count.toLocaleString()}`
|
|
40
|
+
) : (
|
|
41
|
+
<EstimatedCount value={count} />
|
|
42
|
+
)}
|
|
43
|
+
</p>
|
|
44
|
+
)}
|
|
45
|
+
<div className="flex items-center gap-1 text-sm text-muted-foreground">
|
|
46
|
+
<span>{metric.label}</span>
|
|
47
|
+
<InsightsInfo label={`How ${metric.label} is counted`}>
|
|
48
|
+
Unique app installations that reported activity in the last{" "}
|
|
49
|
+
{metric.period}, including no-change reports. Filtered by platform,
|
|
50
|
+
channel, and app version. The chart counts unique reporting
|
|
51
|
+
installations per {metric.interval}. Unique counts are estimates,
|
|
52
|
+
typically within about 3%. On DynamoDB and Firestore the server
|
|
53
|
+
updates totals in batches: when the Console cannot write to the
|
|
54
|
+
database, totals can leave out up to a minute of the latest reports.
|
|
55
|
+
Hourly counts are kept for {formatDays(retention.rawDays)} and daily
|
|
56
|
+
counts for {formatDays(retention.dailyDays)}, so 12 months counts
|
|
57
|
+
whole UTC days.
|
|
58
|
+
{partial
|
|
59
|
+
? " Only part of the history is available; the total is a lower bound."
|
|
60
|
+
: ""}
|
|
61
|
+
</InsightsInfo>
|
|
62
|
+
</div>
|
|
63
|
+
</div>
|
|
64
|
+
);
|
|
65
|
+
}
|