@hot-updater/console 1.0.0-rc.2 → 1.0.0-rc.20
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-B9VYGA3N.js +1 -0
- package/.output/public/assets/HashValueDisplay-D880zntR.js +1 -0
- package/.output/public/assets/InsightsInfo-By_sPjTE.js +1 -0
- package/.output/public/assets/InsightsPageHeader-9_kx_LL7.js +1 -0
- package/.output/public/assets/NotFoundPage-Dys8C0cW.js +1 -0
- package/.output/public/assets/api-CtarlV0l.js +1 -0
- package/.output/public/assets/api-keys-DFF_QqtN.js +1 -0
- package/.output/public/assets/api-keys-evfsQ4sN.js +1 -0
- package/.output/public/assets/arrow-left-BP9D-ta_.js +1 -0
- package/.output/public/assets/arrow-up-right-CDP9Tevw.js +1 -0
- package/.output/public/assets/card-DzCPSRsh.js +1 -0
- package/.output/public/assets/console-features-api-yv7rm3DX.js +1 -0
- package/.output/public/assets/dialog-BDvCy_QO.js +1 -0
- package/.output/public/assets/dist-Clb6cQ9l.js +1 -0
- package/.output/public/assets/empty-C5x9mn_s.js +1 -0
- package/.output/public/assets/field-Bou7shoO.js +1 -0
- package/.output/public/assets/index-0eg3l8aC.js +10 -0
- package/.output/public/assets/input-group-DVtWFUUF.js +1 -0
- package/.output/public/assets/insights-2MbdiSNv.js +1 -0
- package/.output/public/assets/insights-C6tmCZHk.js +2 -0
- package/.output/public/assets/insights-CadS_aIA.js +42 -0
- package/.output/public/assets/insights-recovery-rpc-wvdyM4LD.js +1 -0
- package/.output/public/assets/insights-search-KIF7mRtB.js +1 -0
- package/.output/public/assets/insights-usage-rpc-qUkNtrWr.js +1 -0
- package/.output/public/assets/insights_.distribution-BhBs6PNA.js +1 -0
- package/.output/public/assets/insights_.distribution-CItZw3-8.js +1 -0
- package/.output/public/assets/insights_.distribution-CJUH_wAS.js +2 -0
- package/.output/public/assets/installations-CH2H7JQt.js +2 -0
- package/.output/public/assets/installations-DMeMuwsW.js +1 -0
- package/.output/public/assets/installations-DnvxI9Dt.js +1 -0
- package/.output/public/assets/loader-circle-Ca7C9YY1.js +1 -0
- package/.output/public/assets/mutation-x9L28_CD.js +1 -0
- package/.output/public/assets/preload-helper-BN-UkjOE.js +1 -0
- package/.output/public/assets/refresh-cw-CVGqvy8Z.js +1 -0
- package/.output/public/assets/routes-BhK8DuZA.js +1 -0
- package/.output/public/assets/routes-veKtDW39.js +2 -0
- package/.output/public/assets/sidebar-B45aMqRm.js +3 -0
- package/.output/public/assets/styles-Dn0pK1EX.css +2 -0
- package/.output/public/assets/table-CwLnN6KX.js +1 -0
- package/.output/public/assets/useCompositeListItem-CF7vsfcA.js +1 -0
- package/.output/public/assets/useMutation-CN1ygYEr.js +1 -0
- package/.output/public/assets/useOpenInteractionType-AnAMWYIY.js +1 -0
- package/.output/public/assets/valueToPercent-C-t8FT0y.js +1 -0
- package/.output/server/{__23tanstack-start-server-fn-resolver-B7ioJhtE.mjs → __23tanstack-start-server-fn-resolver-CUQLz7hs.mjs} +52 -40
- 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 +49 -3
- package/.output/server/_libs/@tanstack/react-router-ssr-query+[...].mjs +4 -4
- 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__react-query.mjs +8 -3
- package/.output/server/_libs/verkit.mjs +99 -1
- package/.output/server/_runtime.mjs +10 -1
- package/.output/server/_ssr/ConsoleFeatureUnavailable-DoxET2AT.mjs +58 -0
- package/.output/server/_ssr/{HashValueDisplay-DwpGLfrl.mjs → HashValueDisplay-BplboHEb.mjs} +3 -3
- package/.output/server/_ssr/InsightsInfo-o2YPd5Qc.mjs +37 -0
- package/.output/server/_ssr/InsightsPageHeader-NExCJL1I.mjs +154 -0
- package/.output/server/_ssr/NotFoundPage-Cd-A8ock.mjs +37 -0
- package/.output/server/_ssr/api-B1Ro0uys.mjs +202 -0
- package/.output/server/_ssr/api-C0G9MTMI.mjs +4205 -0
- package/.output/server/_ssr/{api-keys-CZeTPQys.mjs → api-keys-CT3HG7KT.mjs} +49 -9
- package/.output/server/_ssr/api-keys-Dvvy1sem.mjs +5 -0
- package/.output/server/_ssr/api-keys-rpc-b1qTTFfG.mjs +52 -0
- package/.output/server/_ssr/api-rpc-Cbns2MGx.mjs +338 -0
- package/.output/server/_ssr/{auth-rpc-DUaeOWKK.mjs → auth-rpc-DChS7m9y.mjs} +6 -6
- package/.output/server/_ssr/auth.server-Ccqz2iVv.mjs +37 -0
- package/.output/server/_ssr/bundleActivity-D17Pb_h5.mjs +19 -0
- package/.output/server/_ssr/card-DMbcvlPz.mjs +49 -0
- package/.output/server/_ssr/config-DMEJdhoW.mjs +13 -0
- package/.output/server/_ssr/config.server-DyypN6cQ.mjs +60 -0
- package/.output/server/_ssr/console-access-KpPv5lin.mjs +17 -0
- package/.output/server/_ssr/console-features-CsbyHYfK.mjs +55 -0
- package/.output/server/_ssr/console-features-api-B-KVuo4p.mjs +43 -0
- package/.output/server/_ssr/console-features-rpc-Djyo5740.mjs +19 -0
- package/.output/server/_ssr/{createServerFn-B2hcXoPM.mjs → createMiddleware-B_I3Ll4M.mjs} +28 -2
- package/.output/server/_ssr/{createServerRpc-DB29C_5p.mjs → createServerRpc-DuNm5mmo.mjs} +2 -2
- package/.output/server/_ssr/databaseRows-CXxf_VIB.mjs +132 -0
- package/.output/server/_ssr/{deleteBundle-BTGwBgzx.mjs → deleteBundle-Dcc21Lbd.mjs} +9 -19
- package/.output/server/_ssr/{dialog-DS-nw-pA.mjs → dialog-cOmLTUV2.mjs} +2 -2
- package/.output/server/_ssr/{dist-CyzPaI5v.mjs → dist-B-r4u3Lg.mjs} +28 -5
- package/.output/server/_ssr/{downloadBundle-CNnYxYO2.mjs → downloadBundle-CexOFoZ4.mjs} +6 -7
- package/.output/server/_ssr/empty-BHoY_5jt.mjs +49 -0
- package/.output/server/_ssr/{table-CnZmon_Z.mjs → field-mjhcNEXD.mjs} +63 -51
- package/.output/server/_ssr/getBundleChildren-DbDXe9wB.mjs +22 -0
- package/.output/server/_ssr/{input-group-BpsnmvZw.mjs → input-group-96H30HWC.mjs} +2 -2
- package/.output/server/_ssr/insights-D25VDVaz.mjs +5 -0
- package/.output/server/_ssr/insights-D359GJFL.mjs +14 -0
- package/.output/server/_ssr/insights-DgFv1NsO.mjs +1238 -0
- package/.output/server/_ssr/insights-api-ChAKrbhG.mjs +105 -0
- package/.output/server/_ssr/insights-failures-WQ-ttjOx.mjs +44 -0
- package/.output/server/_ssr/insights-failures-rpc-BFsqlltN.mjs +21 -0
- package/.output/server/_ssr/insights-recovery-DkL6bxMW.mjs +28 -0
- package/.output/server/_ssr/insights-recovery-rpc-2P5m8F62.mjs +46 -0
- package/.output/server/_ssr/insights-recovery-rpc-Tj8vNC19.mjs +20 -0
- package/.output/server/_ssr/{insights-rpc-38DujK0G.mjs → insights-rpc-DrkVmV9o.mjs} +22 -14
- package/.output/server/_ssr/insights-search-BsalnNw-.mjs +25 -0
- package/.output/server/_ssr/insights-usage-1nVTQrLy.mjs +29 -0
- package/.output/server/_ssr/insights-usage-rpc-Ct_4xHhZ.mjs +29 -0
- package/.output/server/_ssr/insights-usage-rpc-DaYIRtFK.mjs +41 -0
- package/.output/server/_ssr/insightsRecovery-CpGucWN1.mjs +45 -0
- package/.output/server/_ssr/insightsUsage-JYpKZAF7.mjs +56 -0
- package/.output/server/_ssr/insights_.distribution-Bcu6uYs_.mjs +5 -0
- package/.output/server/_ssr/insights_.distribution-D3Csuyjw.mjs +14 -0
- package/.output/server/_ssr/insights_.distribution-jQZEF07J.mjs +335 -0
- package/.output/server/_ssr/installations-B8Vh54lH.mjs +69 -0
- package/.output/server/_ssr/installations-BI5kelHv.mjs +5 -0
- package/.output/server/_ssr/{installations-DiVKEF5T.mjs → installations-Cxikllmx.mjs} +517 -54
- package/.output/server/_ssr/listReleases-DqU9t1l3.mjs +79 -0
- package/.output/server/_ssr/releaseManagement-B3e7I8J9.mjs +11 -0
- package/.output/server/_ssr/{router-B9wG_9f8.mjs → router-CRkm-wHD.mjs} +117 -124
- package/.output/server/_ssr/routes-B3IJo_jL.mjs +292 -0
- package/.output/server/_ssr/{routes-D7Yh_jfj.mjs → routes-CNAi0Mmv.mjs} +176 -455
- package/.output/server/_ssr/runtime.server-NucbYjc7.mjs +1372 -0
- package/.output/server/_ssr/select-BkPAJFL7.mjs +107 -0
- package/.output/server/_ssr/{server-D_C2rMzf.mjs → server-DKJYsaCP.mjs} +6 -32
- package/.output/server/_ssr/{createSsrRpc-DjWNJ0uc.mjs → sidebar-Cw1VuC7d.mjs} +117 -63
- package/.output/server/_ssr/ssr.mjs +1 -1
- package/.output/server/_ssr/table-q0P9wz7x.mjs +53 -0
- package/.output/server/_ssr/updateFailures-DMU9f0pK.mjs +24 -0
- package/.output/server/_ssr/{uuidv7-D0QFkPL_.mjs → uuidv7-BzSO-fr-.mjs} +2 -2
- package/.output/server/_tanstack-start-manifest_v-Bb0gKDbb.mjs +124 -0
- package/.output/server/index.mjs +273 -168
- package/README.md +71 -65
- package/lib/index.d.mts +13 -11
- package/lib/vite-internal.mjs +6 -3
- package/package.json +8 -8
- package/src/components/AppSidebar.tsx +91 -71
- package/src/components/ConsoleAccessPage.tsx +5 -1
- package/src/components/ConsoleFeatureUnavailable.tsx +82 -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 +7 -4
- 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 +24 -1
- 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 +12 -17
- package/src/lib/api-keys-api.ts +0 -28
- package/src/lib/api-keys-rpc.ts +27 -38
- package/src/lib/api-rpc.ts +197 -221
- package/src/lib/api.ts +11 -13
- 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 +16 -32
- package/src/lib/server/console-feature-apis.ts +59 -0
- package/src/lib/server/console-runtime.server.ts +6 -40
- package/src/lib/server/deleteBundle.ts +16 -25
- package/src/lib/server/downloadBundle.ts +7 -10
- 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 +4 -3
- package/src/lib/server/runtime.server.ts +132 -31
- package/src/lib/server/updateFailures.ts +31 -0
- package/src/routeTree.gen.ts +21 -21
- 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 +6 -3
- 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/databaseJsonValue-d6I3nAS4.mjs +0 -45
- package/.output/server/_ssr/databaseRows-5bCRTxm-.mjs +0 -126
- 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/signing-Dz1WkZOf.mjs +0 -133
- 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/routes/signing.tsx +0 -37
package/src/routes/index.tsx
CHANGED
|
@@ -20,6 +20,7 @@ import { ChannelBadge } from "@/components/ChannelBadge";
|
|
|
20
20
|
import { EnabledStatusIcon } from "@/components/EnabledStatusIcon";
|
|
21
21
|
import { BundleChildrenPanel } from "@/components/features/bundles/BundleChildrenPanel";
|
|
22
22
|
import { ChannelManagementDialog } from "@/components/features/channels/ChannelManagementDialog";
|
|
23
|
+
import { useReleaseColumns } from "@/components/features/FeatureSlots";
|
|
23
24
|
import { ReleaseEditorSheet } from "@/components/features/releases/ReleaseEditorSheet";
|
|
24
25
|
import { ReleaseStateBadge } from "@/components/features/releases/ReleaseStateBadge";
|
|
25
26
|
import { HashValueDisplay } from "@/components/HashValueDisplay";
|
|
@@ -28,7 +29,6 @@ import { RolloutPercentageBadge } from "@/components/RolloutPercentageBadge";
|
|
|
28
29
|
import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert";
|
|
29
30
|
import { Badge } from "@/components/ui/badge";
|
|
30
31
|
import { Button, buttonVariants } from "@/components/ui/button";
|
|
31
|
-
import { Input } from "@/components/ui/input";
|
|
32
32
|
import {
|
|
33
33
|
Select,
|
|
34
34
|
SelectContent,
|
|
@@ -59,6 +59,8 @@ import type { ReleaseListRow } from "@/lib/server/releaseReachability";
|
|
|
59
59
|
import { cn } from "@/lib/utils";
|
|
60
60
|
|
|
61
61
|
import {
|
|
62
|
+
hasReleaseFilters,
|
|
63
|
+
releaseFilterOf,
|
|
62
64
|
type ReleaseSearch,
|
|
63
65
|
updateReleaseFilters,
|
|
64
66
|
validateReleaseSearch,
|
|
@@ -66,10 +68,14 @@ import {
|
|
|
66
68
|
|
|
67
69
|
const PAGE_SIZE = 20;
|
|
68
70
|
const platformFilterItems = [
|
|
69
|
-
{ label: "All Platforms", value: "all" },
|
|
70
71
|
{ label: "iOS", value: "ios" },
|
|
71
72
|
{ label: "Android", value: "android" },
|
|
72
73
|
];
|
|
74
|
+
const statusFilterItems = [
|
|
75
|
+
{ label: "Any Status", value: "all" },
|
|
76
|
+
{ label: "Enabled", value: "enabled" },
|
|
77
|
+
{ label: "Disabled", value: "disabled" },
|
|
78
|
+
];
|
|
73
79
|
const dateFormatter = new Intl.DateTimeFormat(undefined, {
|
|
74
80
|
dateStyle: "medium",
|
|
75
81
|
timeStyle: "short",
|
|
@@ -96,16 +102,9 @@ function BundleFilterToolbar({
|
|
|
96
102
|
onManageChannels: () => void;
|
|
97
103
|
search: ReleaseSearch;
|
|
98
104
|
}) {
|
|
99
|
-
const
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
const hasFilters = Boolean(
|
|
103
|
-
search.bundleId ||
|
|
104
|
-
search.channelId ||
|
|
105
|
-
search.enabled !== undefined ||
|
|
106
|
-
search.platform ||
|
|
107
|
-
search.targetAppVersion,
|
|
108
|
-
);
|
|
105
|
+
const hasFilters = hasReleaseFilters(search);
|
|
106
|
+
// Releases list by channel and platform together: the index serves that pair.
|
|
107
|
+
const channelSelected = search.channelId !== undefined;
|
|
109
108
|
const channelFilterItems = [
|
|
110
109
|
{ label: "All Channels", value: "all" },
|
|
111
110
|
...channels.map((channel) => ({
|
|
@@ -113,14 +112,6 @@ function BundleFilterToolbar({
|
|
|
113
112
|
value: channel.id,
|
|
114
113
|
})),
|
|
115
114
|
];
|
|
116
|
-
const applyTargetAppVersion = () => {
|
|
117
|
-
const value = targetAppVersion.trim();
|
|
118
|
-
onChange({ targetAppVersion: value || undefined });
|
|
119
|
-
};
|
|
120
|
-
|
|
121
|
-
useEffect(() => {
|
|
122
|
-
setTargetAppVersion(search.targetAppVersion ?? "");
|
|
123
|
-
}, [search.targetAppVersion]);
|
|
124
115
|
|
|
125
116
|
return (
|
|
126
117
|
<header className="sticky top-0 z-10 flex shrink-0 flex-wrap items-center gap-2 border-b bg-background px-3 py-3 sm:h-12 sm:flex-nowrap sm:bg-card/70 sm:px-4 sm:py-0 sm:backdrop-blur-sm">
|
|
@@ -131,65 +122,85 @@ function BundleFilterToolbar({
|
|
|
131
122
|
<span className="text-xs font-medium">Filters</span>
|
|
132
123
|
</div>
|
|
133
124
|
<Select
|
|
134
|
-
items={
|
|
125
|
+
items={channelFilterItems}
|
|
135
126
|
onValueChange={(value) =>
|
|
136
127
|
onChange({
|
|
137
|
-
|
|
138
|
-
value === "all" ? undefined : (value as "ios" | "android"),
|
|
128
|
+
channelId: value === null || value === "all" ? undefined : value,
|
|
139
129
|
})
|
|
140
130
|
}
|
|
141
|
-
value={search.
|
|
131
|
+
value={search.channelId ?? "all"}
|
|
132
|
+
>
|
|
133
|
+
<SelectTrigger
|
|
134
|
+
aria-label="Channel"
|
|
135
|
+
className="h-8 w-[calc(50%-0.25rem)] min-w-[132px] text-xs sm:w-[140px]"
|
|
136
|
+
>
|
|
137
|
+
<SelectValue />
|
|
138
|
+
</SelectTrigger>
|
|
139
|
+
<SelectContent>
|
|
140
|
+
<SelectGroup>
|
|
141
|
+
<SelectItem value="all">All Channels</SelectItem>
|
|
142
|
+
{channels.map((channel) => (
|
|
143
|
+
<SelectItem key={channel.id} value={channel.id}>
|
|
144
|
+
{channel.name}
|
|
145
|
+
</SelectItem>
|
|
146
|
+
))}
|
|
147
|
+
</SelectGroup>
|
|
148
|
+
</SelectContent>
|
|
149
|
+
</Select>
|
|
150
|
+
<Select
|
|
151
|
+
disabled={!channelSelected}
|
|
152
|
+
items={platformFilterItems}
|
|
153
|
+
onValueChange={(value) =>
|
|
154
|
+
onChange({ platform: value === "android" ? "android" : "ios" })
|
|
155
|
+
}
|
|
156
|
+
value={search.platform ?? "ios"}
|
|
142
157
|
>
|
|
143
158
|
<SelectTrigger
|
|
144
159
|
aria-label="Platform"
|
|
145
160
|
className="h-8 w-[calc(50%-0.25rem)] min-w-[132px] text-xs sm:w-[140px]"
|
|
161
|
+
title={channelSelected ? undefined : "Choose a channel first"}
|
|
146
162
|
>
|
|
147
163
|
<SelectValue />
|
|
148
164
|
</SelectTrigger>
|
|
149
165
|
<SelectContent>
|
|
150
166
|
<SelectGroup>
|
|
151
|
-
<SelectItem value="all">All Platforms</SelectItem>
|
|
152
167
|
<SelectItem value="ios">iOS</SelectItem>
|
|
153
168
|
<SelectItem value="android">Android</SelectItem>
|
|
154
169
|
</SelectGroup>
|
|
155
170
|
</SelectContent>
|
|
156
171
|
</Select>
|
|
157
|
-
<Input
|
|
158
|
-
aria-label="Target app version"
|
|
159
|
-
className="h-8 w-full min-w-[132px] text-xs sm:w-[160px]"
|
|
160
|
-
onBlur={applyTargetAppVersion}
|
|
161
|
-
onChange={(event) => setTargetAppVersion(event.target.value)}
|
|
162
|
-
onKeyDown={(event) => {
|
|
163
|
-
if (event.key === "Enter") {
|
|
164
|
-
applyTargetAppVersion();
|
|
165
|
-
}
|
|
166
|
-
}}
|
|
167
|
-
placeholder="Target version"
|
|
168
|
-
value={targetAppVersion}
|
|
169
|
-
/>
|
|
170
172
|
<Select
|
|
171
|
-
|
|
173
|
+
disabled={!channelSelected && search.scopeKey === undefined}
|
|
174
|
+
items={statusFilterItems}
|
|
172
175
|
onValueChange={(value) =>
|
|
173
176
|
onChange({
|
|
174
|
-
|
|
177
|
+
enabled:
|
|
178
|
+
value === "enabled"
|
|
179
|
+
? true
|
|
180
|
+
: value === "disabled"
|
|
181
|
+
? false
|
|
182
|
+
: undefined,
|
|
175
183
|
})
|
|
176
184
|
}
|
|
177
|
-
value={
|
|
185
|
+
value={
|
|
186
|
+
search.enabled === undefined
|
|
187
|
+
? "all"
|
|
188
|
+
: search.enabled
|
|
189
|
+
? "enabled"
|
|
190
|
+
: "disabled"
|
|
191
|
+
}
|
|
178
192
|
>
|
|
179
193
|
<SelectTrigger
|
|
180
|
-
aria-label="
|
|
194
|
+
aria-label="Status"
|
|
181
195
|
className="h-8 w-[calc(50%-0.25rem)] min-w-[132px] text-xs sm:w-[140px]"
|
|
182
196
|
>
|
|
183
197
|
<SelectValue />
|
|
184
198
|
</SelectTrigger>
|
|
185
199
|
<SelectContent>
|
|
186
200
|
<SelectGroup>
|
|
187
|
-
<SelectItem value="all">
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
{channel.name}
|
|
191
|
-
</SelectItem>
|
|
192
|
-
))}
|
|
201
|
+
<SelectItem value="all">Any Status</SelectItem>
|
|
202
|
+
<SelectItem value="enabled">Enabled</SelectItem>
|
|
203
|
+
<SelectItem value="disabled">Disabled</SelectItem>
|
|
193
204
|
</SelectGroup>
|
|
194
205
|
</SelectContent>
|
|
195
206
|
</Select>
|
|
@@ -215,6 +226,19 @@ function BundleFilterToolbar({
|
|
|
215
226
|
</button>
|
|
216
227
|
</Badge>
|
|
217
228
|
) : null}
|
|
229
|
+
{search.scopeKey ? (
|
|
230
|
+
<Badge className="max-w-48 gap-1" variant="secondary">
|
|
231
|
+
Target filter
|
|
232
|
+
<button
|
|
233
|
+
aria-label="Clear target filter"
|
|
234
|
+
className="rounded-sm focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring"
|
|
235
|
+
onClick={() => onChange({ scopeKey: undefined })}
|
|
236
|
+
type="button"
|
|
237
|
+
>
|
|
238
|
+
<X className="size-3" />
|
|
239
|
+
</button>
|
|
240
|
+
</Badge>
|
|
241
|
+
) : null}
|
|
218
242
|
{hasFilters ? (
|
|
219
243
|
<Button
|
|
220
244
|
className="h-8 px-2 text-xs text-muted-foreground hover:text-foreground sm:ml-auto"
|
|
@@ -374,13 +398,8 @@ function BundlesPage() {
|
|
|
374
398
|
const releasesQuery = useReleasesQuery({
|
|
375
399
|
afterReleaseId: search.afterReleaseId,
|
|
376
400
|
beforeReleaseId: search.beforeReleaseId,
|
|
377
|
-
|
|
378
|
-
channelId: search.channelId,
|
|
379
|
-
enabled: search.enabled,
|
|
401
|
+
filter: releaseFilterOf(search),
|
|
380
402
|
limit: PAGE_SIZE,
|
|
381
|
-
page: search.page,
|
|
382
|
-
platform: search.platform,
|
|
383
|
-
targetAppVersion: search.targetAppVersion,
|
|
384
403
|
});
|
|
385
404
|
const channelsQuery = useChannelsQuery();
|
|
386
405
|
const channels = channelsQuery.data ?? [];
|
|
@@ -394,7 +413,19 @@ function BundlesPage() {
|
|
|
394
413
|
);
|
|
395
414
|
const patchCountsQuery = useBundleChildCountsQuery(bundleIds);
|
|
396
415
|
const patchCountsByBundleId = patchCountsQuery.data ?? {};
|
|
397
|
-
const
|
|
416
|
+
const nextCursor = releasesQuery.data?.next;
|
|
417
|
+
const previousCursor = releasesQuery.data?.previous;
|
|
418
|
+
const slotReleases = releases.flatMap((release) => {
|
|
419
|
+
const channel = channels.find(
|
|
420
|
+
(item) => item.id === release.channel_id,
|
|
421
|
+
)?.name;
|
|
422
|
+
return channel
|
|
423
|
+
? [{ releaseId: release.id, platform: release.platform, channel }]
|
|
424
|
+
: [];
|
|
425
|
+
});
|
|
426
|
+
// Features add columns, such as release activity where the console reads it.
|
|
427
|
+
const featureColumns = useReleaseColumns();
|
|
428
|
+
const columnCount = 10 + featureColumns.length;
|
|
398
429
|
const channelNames = new Map(
|
|
399
430
|
channels.map((channel) => [channel.id, channel.name]),
|
|
400
431
|
);
|
|
@@ -423,33 +454,31 @@ function BundlesPage() {
|
|
|
423
454
|
}
|
|
424
455
|
changeFilters({ bundleId: bundle.id });
|
|
425
456
|
};
|
|
426
|
-
|
|
427
|
-
const
|
|
428
|
-
|
|
429
|
-
const
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
}
|
|
452
|
-
: null;
|
|
457
|
+
// Pages go by key: newer or older than an edge release, never by number.
|
|
458
|
+
const onLaterPage =
|
|
459
|
+
search.afterReleaseId !== undefined || search.beforeReleaseId !== undefined;
|
|
460
|
+
const previousSearch: ReleaseSearch | null = previousCursor
|
|
461
|
+
? {
|
|
462
|
+
...search,
|
|
463
|
+
afterReleaseId: previousCursor,
|
|
464
|
+
beforeReleaseId: undefined,
|
|
465
|
+
releaseId: undefined,
|
|
466
|
+
}
|
|
467
|
+
: null;
|
|
468
|
+
const nextSearch: ReleaseSearch | null = nextCursor
|
|
469
|
+
? {
|
|
470
|
+
...search,
|
|
471
|
+
afterReleaseId: undefined,
|
|
472
|
+
beforeReleaseId: nextCursor,
|
|
473
|
+
releaseId: undefined,
|
|
474
|
+
}
|
|
475
|
+
: null;
|
|
476
|
+
const newestSearch: ReleaseSearch = {
|
|
477
|
+
...search,
|
|
478
|
+
afterReleaseId: undefined,
|
|
479
|
+
beforeReleaseId: undefined,
|
|
480
|
+
releaseId: undefined,
|
|
481
|
+
};
|
|
453
482
|
|
|
454
483
|
return (
|
|
455
484
|
<div className="flex h-svh min-h-0 min-w-0 flex-col">
|
|
@@ -556,6 +585,22 @@ function BundlesPage() {
|
|
|
556
585
|
: "—"}
|
|
557
586
|
</dd>
|
|
558
587
|
</div>
|
|
588
|
+
{featureColumns.map(({ Cell, feature, label }) => (
|
|
589
|
+
<div
|
|
590
|
+
className="col-span-2 rounded-md bg-muted/40 p-3"
|
|
591
|
+
key={feature}
|
|
592
|
+
>
|
|
593
|
+
<dt className="mb-2 text-muted-foreground">
|
|
594
|
+
{label}
|
|
595
|
+
</dt>
|
|
596
|
+
<dd>
|
|
597
|
+
<Cell
|
|
598
|
+
releaseId={release.id}
|
|
599
|
+
releases={slotReleases}
|
|
600
|
+
/>
|
|
601
|
+
</dd>
|
|
602
|
+
</div>
|
|
603
|
+
))}
|
|
559
604
|
<div className="col-span-2 flex flex-wrap items-center gap-2 rounded-md bg-muted/40 p-3">
|
|
560
605
|
<ReleaseStateBadge release={release} />
|
|
561
606
|
{release.should_force_update ? (
|
|
@@ -596,13 +641,11 @@ function BundlesPage() {
|
|
|
596
641
|
})
|
|
597
642
|
) : (
|
|
598
643
|
<p className="p-8 text-center text-sm text-muted-foreground">
|
|
599
|
-
{
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
? "No bundles match these filters."
|
|
605
|
-
: "No bundles yet. Deploy an update to see it here."}
|
|
644
|
+
{onLaterPage
|
|
645
|
+
? "No more bundles on this side."
|
|
646
|
+
: hasReleaseFilters(search)
|
|
647
|
+
? "No bundles match these filters."
|
|
648
|
+
: "No bundles yet. Deploy an update to see it here."}
|
|
606
649
|
</p>
|
|
607
650
|
)}
|
|
608
651
|
</div>
|
|
@@ -618,6 +661,9 @@ function BundlesPage() {
|
|
|
618
661
|
<TableHead>Enabled</TableHead>
|
|
619
662
|
<TableHead>Force update</TableHead>
|
|
620
663
|
<TableHead>Rollout</TableHead>
|
|
664
|
+
{featureColumns.map(({ feature, label }) => (
|
|
665
|
+
<TableHead key={feature}>{label}</TableHead>
|
|
666
|
+
))}
|
|
621
667
|
<TableHead>Message</TableHead>
|
|
622
668
|
<TableHead>Created</TableHead>
|
|
623
669
|
</TableRow>
|
|
@@ -626,7 +672,7 @@ function BundlesPage() {
|
|
|
626
672
|
{releasesQuery.isPending
|
|
627
673
|
? Array.from({ length: 7 }, (_, index) => (
|
|
628
674
|
<TableRow key={index}>
|
|
629
|
-
<TableCell colSpan={
|
|
675
|
+
<TableCell colSpan={columnCount}>
|
|
630
676
|
<Skeleton className="h-8 w-full" />
|
|
631
677
|
</TableCell>
|
|
632
678
|
</TableRow>
|
|
@@ -783,6 +829,14 @@ function BundlesPage() {
|
|
|
783
829
|
percentage={release.rollout_cohort_count / 10}
|
|
784
830
|
/>
|
|
785
831
|
</TableCell>
|
|
832
|
+
{featureColumns.map(({ Cell, feature }) => (
|
|
833
|
+
<TableCell key={feature}>
|
|
834
|
+
<Cell
|
|
835
|
+
releaseId={release.id}
|
|
836
|
+
releases={slotReleases}
|
|
837
|
+
/>
|
|
838
|
+
</TableCell>
|
|
839
|
+
))}
|
|
786
840
|
<TableCell
|
|
787
841
|
className="text-sm text-muted-foreground"
|
|
788
842
|
title={release.message ?? undefined}
|
|
@@ -804,7 +858,7 @@ function BundlesPage() {
|
|
|
804
858
|
<TableRow className="hover:bg-transparent">
|
|
805
859
|
<TableCell
|
|
806
860
|
className="border-t-0 p-0"
|
|
807
|
-
colSpan={
|
|
861
|
+
colSpan={columnCount}
|
|
808
862
|
>
|
|
809
863
|
<ReleaseBundleChildrenPanel
|
|
810
864
|
onDetailClick={openChildBundle}
|
|
@@ -821,15 +875,13 @@ function BundlesPage() {
|
|
|
821
875
|
<TableRow>
|
|
822
876
|
<TableCell
|
|
823
877
|
className="h-40 text-center text-muted-foreground"
|
|
824
|
-
colSpan={
|
|
878
|
+
colSpan={columnCount}
|
|
825
879
|
>
|
|
826
|
-
{
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
? "No bundles match these filters."
|
|
832
|
-
: "No bundles yet. Deploy an update to see it here."}
|
|
880
|
+
{onLaterPage
|
|
881
|
+
? "No more bundles on this side."
|
|
882
|
+
: hasReleaseFilters(search)
|
|
883
|
+
? "No bundles match these filters."
|
|
884
|
+
: "No bundles yet. Deploy an update to see it here."}
|
|
833
885
|
</TableCell>
|
|
834
886
|
</TableRow>
|
|
835
887
|
) : null}
|
|
@@ -845,13 +897,23 @@ function BundlesPage() {
|
|
|
845
897
|
className="flex flex-col gap-3 px-2 sm:flex-row sm:items-center sm:justify-between"
|
|
846
898
|
>
|
|
847
899
|
<p className="text-xs font-medium text-muted-foreground">
|
|
848
|
-
|
|
849
|
-
|
|
900
|
+
<span className="text-foreground">{releases.length}</span>{" "}
|
|
901
|
+
{releases.length === 1 ? "entry" : "entries"}, newest first
|
|
850
902
|
</p>
|
|
851
903
|
<div className="flex flex-wrap items-center gap-3 sm:justify-end">
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
904
|
+
{onLaterPage ? (
|
|
905
|
+
<Link
|
|
906
|
+
className={buttonVariants({
|
|
907
|
+
className: "h-8 flex-1 px-3 text-xs sm:flex-none",
|
|
908
|
+
size: "sm",
|
|
909
|
+
variant: "ghost",
|
|
910
|
+
})}
|
|
911
|
+
search={newestSearch}
|
|
912
|
+
to="/"
|
|
913
|
+
>
|
|
914
|
+
Newest
|
|
915
|
+
</Link>
|
|
916
|
+
) : null}
|
|
855
917
|
{previousSearch ? (
|
|
856
918
|
<Link
|
|
857
919
|
className={buttonVariants({
|
|
@@ -910,6 +972,7 @@ function BundlesPage() {
|
|
|
910
972
|
onOpenChange={(open) =>
|
|
911
973
|
!open && go({ ...search, releaseId: undefined }, false)
|
|
912
974
|
}
|
|
975
|
+
onShowScope={(scopeKey) => changeFilters({ scopeKey })}
|
|
913
976
|
open={Boolean(search.releaseId)}
|
|
914
977
|
releaseId={search.releaseId ?? ""}
|
|
915
978
|
/>
|
package/src/routes/insights.tsx
CHANGED
|
@@ -1,82 +1,123 @@
|
|
|
1
|
+
import { useQuery } from "@tanstack/react-query";
|
|
1
2
|
import { createFileRoute } from "@tanstack/react-router";
|
|
2
|
-
import { useState } from "react";
|
|
3
3
|
|
|
4
|
-
import {
|
|
5
|
-
|
|
6
|
-
type InsightsReportSelection,
|
|
7
|
-
} from "@/components/features/insights/InsightsBundleReports";
|
|
4
|
+
import { ConsoleFeatureUnavailable } from "@/components/ConsoleFeatureUnavailable";
|
|
5
|
+
import { AppUsage } from "@/components/features/insights/AppUsage";
|
|
8
6
|
import { InsightsControls } from "@/components/features/insights/InsightsControls";
|
|
9
7
|
import { InsightsOverview } from "@/components/features/insights/InsightsOverview";
|
|
10
8
|
import { InsightsPageHeader } from "@/components/features/insights/InsightsPageHeader";
|
|
11
|
-
import {
|
|
9
|
+
import { UpdateFailures } from "@/components/features/insights/UpdateFailures";
|
|
10
|
+
import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert";
|
|
11
|
+
import { requireConsoleFeature } from "@/lib/console-features-api";
|
|
12
12
|
import {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
useReportingInstallationsQuery,
|
|
13
|
+
useInsightsRetention,
|
|
14
|
+
useUpdateFailuresQuery,
|
|
16
15
|
} from "@/lib/insights-api";
|
|
16
|
+
import { getRecoveryReportRpc } from "@/lib/insights-recovery-rpc";
|
|
17
|
+
import { validateInsightsSearch } from "@/lib/insights-search";
|
|
18
|
+
import type { AppUsageScope, UsageWindow } from "@/lib/insights-usage";
|
|
19
|
+
import { getAppUsageReportRpc } from "@/lib/insights-usage-rpc";
|
|
17
20
|
|
|
18
21
|
export const Route = createFileRoute("/insights")({
|
|
22
|
+
beforeLoad: ({ context }) =>
|
|
23
|
+
requireConsoleFeature(context.queryClient, "insightsAnalytics"),
|
|
24
|
+
notFoundComponent: ConsoleFeatureUnavailable,
|
|
19
25
|
component: InsightsPage,
|
|
26
|
+
validateSearch: validateInsightsSearch,
|
|
20
27
|
});
|
|
21
28
|
|
|
22
29
|
function InsightsPage() {
|
|
23
|
-
const
|
|
24
|
-
const
|
|
25
|
-
|
|
26
|
-
|
|
30
|
+
const search = Route.useSearch();
|
|
31
|
+
const navigate = Route.useNavigate();
|
|
32
|
+
const retention = useInsightsRetention();
|
|
33
|
+
const usageWindow = search.window ?? "24h";
|
|
34
|
+
const bundleWindow = search.bundleWindow ?? "7d";
|
|
35
|
+
const channel = search.channel ?? search.healthChannel ?? "production";
|
|
36
|
+
const scope: AppUsageScope = {
|
|
37
|
+
platform: search.platform ?? "all",
|
|
38
|
+
channel,
|
|
39
|
+
appVersion: search.appVersion,
|
|
40
|
+
};
|
|
41
|
+
const setUsageWindow = (window: UsageWindow) =>
|
|
42
|
+
void navigate({ search: { ...search, window } });
|
|
43
|
+
const input = { ...scope, window: usageWindow };
|
|
44
|
+
const bundleInput = {
|
|
45
|
+
platform: search.healthPlatform ?? "ios",
|
|
46
|
+
channel,
|
|
47
|
+
window: bundleWindow,
|
|
48
|
+
...(search.releaseId === undefined ? {} : { releaseId: search.releaseId }),
|
|
49
|
+
} as const;
|
|
50
|
+
const query = useQuery({
|
|
51
|
+
queryKey: ["insights", "app-usage", input],
|
|
52
|
+
queryFn: () => getAppUsageReportRpc({ data: input }),
|
|
53
|
+
staleTime: 30_000,
|
|
27
54
|
});
|
|
28
|
-
const
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
55
|
+
const bundleQuery = useQuery({
|
|
56
|
+
queryKey: ["insights", "recovery", bundleInput],
|
|
57
|
+
queryFn: () => getRecoveryReportRpc({ data: bundleInput }),
|
|
58
|
+
staleTime: 30_000,
|
|
59
|
+
});
|
|
60
|
+
const failuresQuery = useUpdateFailuresQuery(bundleInput);
|
|
33
61
|
return (
|
|
34
62
|
<div className="flex h-svh min-h-0 flex-col">
|
|
35
|
-
<InsightsPageHeader view="overview" />
|
|
36
|
-
<div className="min-h-0 min-w-0 flex-1 overflow-y-auto bg-muted/5
|
|
37
|
-
<div className="mx-auto flex w-full max-w-
|
|
63
|
+
<InsightsPageHeader view="overview" overviewSearch={search} />
|
|
64
|
+
<div className="min-h-0 min-w-0 flex-1 overflow-y-auto bg-muted/5 px-4 py-6 sm:p-8">
|
|
65
|
+
<div className="mx-auto flex w-full max-w-6xl flex-col gap-6">
|
|
38
66
|
<InsightsControls
|
|
67
|
+
key={JSON.stringify({ scope, bundleInput })}
|
|
39
68
|
scope={scope}
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
69
|
+
releaseScope={bundleInput}
|
|
70
|
+
appVersions={query.data?.appVersions ?? []}
|
|
71
|
+
onFiltersChange={({ scope, releaseScope }) =>
|
|
72
|
+
void navigate({
|
|
73
|
+
search: {
|
|
74
|
+
...search,
|
|
75
|
+
...scope,
|
|
76
|
+
appVersion: scope.appVersion,
|
|
77
|
+
healthPlatform: releaseScope.platform,
|
|
78
|
+
healthChannel: undefined,
|
|
79
|
+
releaseId: releaseScope.releaseId,
|
|
80
|
+
},
|
|
81
|
+
})
|
|
82
|
+
}
|
|
49
83
|
/>
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
<InsightsOverview status="loading" />
|
|
63
|
-
) : active.error ? (
|
|
64
|
-
<InsightsOverview status="error" error={active.error} />
|
|
65
|
-
) : active.data ? (
|
|
66
|
-
<InsightsOverview
|
|
67
|
-
status="success"
|
|
68
|
-
active={active.data}
|
|
69
|
-
onOutcomeSelect={setSelection}
|
|
70
|
-
/>
|
|
71
|
-
) : (
|
|
72
|
-
<InsightsOverview status="loading" />
|
|
73
|
-
)}
|
|
74
|
-
{selection ? (
|
|
75
|
-
<InsightsBundleReports
|
|
76
|
-
key={JSON.stringify(selection)}
|
|
77
|
-
selection={selection}
|
|
78
|
-
/>
|
|
84
|
+
{query.data?.truncated && !query.error ? (
|
|
85
|
+
<Alert>
|
|
86
|
+
<AlertTitle>Partial history</AlertTitle>
|
|
87
|
+
<AlertDescription>
|
|
88
|
+
Only reports since{" "}
|
|
89
|
+
{new Date(query.data.sinceMs).toLocaleString("en", {
|
|
90
|
+
timeZone: "UTC",
|
|
91
|
+
})}{" "}
|
|
92
|
+
UTC are available. The active-user count is a lower bound.
|
|
93
|
+
Choose a shorter period for a more complete view.
|
|
94
|
+
</AlertDescription>
|
|
95
|
+
</Alert>
|
|
79
96
|
) : null}
|
|
97
|
+
<AppUsage
|
|
98
|
+
query={query}
|
|
99
|
+
search={{ ...scope, window: usageWindow, bundleWindow }}
|
|
100
|
+
window={usageWindow}
|
|
101
|
+
onWindowChange={setUsageWindow}
|
|
102
|
+
retention={retention}
|
|
103
|
+
/>
|
|
104
|
+
<InsightsOverview
|
|
105
|
+
input={bundleInput}
|
|
106
|
+
query={bundleQuery}
|
|
107
|
+
onWindowChange={(window) =>
|
|
108
|
+
void navigate({
|
|
109
|
+
search: {
|
|
110
|
+
...search,
|
|
111
|
+
bundleWindow: window,
|
|
112
|
+
},
|
|
113
|
+
})
|
|
114
|
+
}
|
|
115
|
+
onRefresh={() => void bundleQuery.refetch()}
|
|
116
|
+
/>
|
|
117
|
+
<UpdateFailures
|
|
118
|
+
query={failuresQuery}
|
|
119
|
+
onRefresh={() => void failuresQuery.refetch()}
|
|
120
|
+
/>
|
|
80
121
|
</div>
|
|
81
122
|
</div>
|
|
82
123
|
</div>
|