@hot-updater/console 1.0.0-rc.1 → 1.0.0-rc.2
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/HashValueDisplay-CB0Eskit.js +1 -0
- package/.output/public/assets/InsightsPageHeader-Car5LNiZ.js +1 -0
- package/.output/public/assets/api-keys-BzKocqRy.js +1 -0
- package/.output/public/assets/api-keys-api-BHcODB7q.js +1 -0
- package/.output/public/assets/card-Dhr_eFYj.js +1 -0
- package/.output/public/assets/{chart-no-axes-combined-FaYMGmQS.js → chart-no-axes-combined-Dy4WJv2U.js} +1 -1
- package/.output/public/assets/composite-Bp98A0Ld.js +1 -0
- package/.output/public/assets/createServerFn-CA8fs7QD.js +3 -0
- package/.output/public/assets/dialog-CUTrcPlB.js +1 -0
- package/.output/public/assets/dist-C_NydL0e.js +1 -0
- package/.output/public/assets/index-DdAz-CXv.js +10 -0
- package/.output/public/assets/input-group-cSOG4wh_.js +1 -0
- package/.output/public/assets/insights-C0PBSZ-n.js +1 -0
- package/.output/public/assets/installations-CE33wgbY.js +2 -0
- package/.output/public/assets/installations-CStZja8x.js +1 -0
- package/.output/public/assets/lazyRouteComponent-Ccp3bwBY.js +1 -0
- package/.output/public/assets/link-CI8idAUi.js +1 -0
- package/.output/public/assets/loader-circle-BoxLrsOu.js +1 -0
- package/.output/public/assets/{refresh-cw-BkbfZ62O.js → refresh-cw-Bqc72UZG.js} +1 -1
- package/.output/public/assets/{routes-BuoI5-Cr.js → routes-DGVXdzpw.js} +2 -2
- package/.output/public/assets/routes-DTlwOr8I.js +1 -0
- package/.output/public/assets/{shield-check-DE_hVuHu.js → shield-check-uK3MHWJZ.js} +1 -1
- package/.output/public/assets/signing-CMf4aqDO.js +1 -0
- package/.output/public/assets/styles-BCvbtKsm.css +2 -0
- package/.output/public/assets/table-2vcV89QB.js +1 -0
- package/.output/public/assets/useCompositeListItem-CHLITE_4.js +1 -0
- package/.output/public/assets/x-DCd0j8c6.js +1 -0
- package/.output/server/{__23tanstack-start-server-fn-resolver-Dftxlm2E.mjs → __23tanstack-start-server-fn-resolver-B7ioJhtE.mjs} +46 -54
- package/.output/server/_libs/@base-ui/react+[...].mjs +283 -2417
- package/.output/server/_libs/@tanstack/react-router+[...].mjs +52 -4
- package/.output/server/_libs/@tanstack/react-router-ssr-query+[...].mjs +2 -2
- package/.output/server/_libs/lucide-react.mjs +36 -3
- package/.output/server/_libs/next-themes.mjs +2 -2
- package/.output/server/_libs/sonner.mjs +2 -2
- package/.output/server/_libs/tanstack__react-query.mjs +2 -2
- package/.output/server/_libs/verkit.mjs +20 -15
- package/.output/server/_runtime.mjs +1 -10
- package/.output/server/_ssr/HashValueDisplay-DwpGLfrl.mjs +55 -0
- package/.output/server/_ssr/InsightsPageHeader-Df4Brj8u.mjs +484 -0
- package/.output/server/_ssr/{api-keys-CpBqHpuC.mjs → api-keys-CZeTPQys.mjs} +9 -11
- package/.output/server/_ssr/{api-keys-api-Czkp57UV.mjs → api-keys-api-BUPQVSpk.mjs} +2 -2
- package/.output/server/_ssr/{api-keys-rpc-BTtMDSoR.mjs → api-keys-rpc-Cs7tS5_j.mjs} +5 -5
- package/.output/server/_ssr/{api-rpc-BEX8ISai.mjs → api-rpc-tAupfGQm.mjs} +73 -142
- package/.output/server/_ssr/{auth-rpc-BFMEC-TT.mjs → auth-rpc-DUaeOWKK.mjs} +2 -2
- package/.output/server/_ssr/{bundle-signing-rpc-BbCFUQSu.mjs → bundle-signing-rpc-BhnBw0-d.mjs} +2 -2
- package/.output/server/_ssr/{card-Bsc8mRis.mjs → card-BRiPmi0C.mjs} +25 -3
- package/.output/server/_ssr/{config.server-DQYEr_5X.mjs → config.server-afDuAwaG.mjs} +14 -7
- package/.output/server/_ssr/{createSsrRpc-DhfrxEjg.mjs → createSsrRpc-DjWNJ0uc.mjs} +6 -6
- package/.output/server/_ssr/databaseJsonValue-d6I3nAS4.mjs +45 -0
- package/.output/server/_ssr/{databaseRows-QlCYLi0H.mjs → databaseRows-5bCRTxm-.mjs} +4 -44
- package/.output/server/_ssr/{deleteBundle-Cu_XOMt0.mjs → deleteBundle-BTGwBgzx.mjs} +2 -2
- package/.output/server/_ssr/{dialog-C0vKUp8R.mjs → dialog-DS-nw-pA.mjs} +2 -2
- package/.output/server/_ssr/{dist-BVSLTpoP.mjs → dist-CyzPaI5v.mjs} +2 -2
- package/.output/server/_ssr/{getBundleChildren-BcRMFoDF.mjs → getBundleChildren-C0vh4ZvE.mjs} +2 -2
- package/.output/server/_ssr/input-group-BpsnmvZw.mjs +70 -0
- package/.output/server/_ssr/insights-BdS364Xu.mjs +460 -0
- package/.output/server/_ssr/insights-rpc-38DujK0G.mjs +57 -0
- package/.output/server/_ssr/insightsContract-fjJDBeEE.mjs +303 -0
- package/.output/server/_ssr/installations-CtA59MQG.mjs +29 -0
- package/.output/server/_ssr/installations-DiVKEF5T.mjs +627 -0
- package/.output/server/_ssr/{router-BxBEvtF1.mjs → router-B9wG_9f8.mjs} +23 -32
- package/.output/server/_ssr/{routes-BC7rn-tf.mjs → routes-CKrrS2q2.mjs} +3 -3
- package/.output/server/_ssr/{routes-CM5KAwpB.mjs → routes-D7Yh_jfj.mjs} +402 -389
- package/.output/server/_ssr/runtime.server-DacU1TBV.mjs +438 -0
- package/.output/server/_ssr/{server-CpzW--lT.mjs → server-D_C2rMzf.mjs} +5 -5
- package/.output/server/_ssr/{signing-jk4HANnl.mjs → signing-Dz1WkZOf.mjs} +5 -6
- package/.output/server/_ssr/ssr.mjs +1 -1
- package/.output/server/_ssr/{field-DASCh-5d.mjs → table-CnZmon_Z.mjs} +51 -5
- package/.output/server/_ssr/{uuidv7-CaKuKXrV.mjs → uuidv7-D0QFkPL_.mjs} +3 -3
- package/.output/server/_tanstack-start-manifest_v-2MjTyxil.mjs +97 -0
- package/.output/server/index.mjs +164 -178
- package/lib/index.d.mts +4 -3
- package/lib/vite-internal.mjs +1 -1
- package/lib/vite.d.mts +0 -1
- package/package.json +8 -8
- package/src/components/AppSidebar.tsx +10 -14
- package/src/components/ConsoleAccessPage.tsx +1 -1
- package/src/components/HashValueDisplay.tsx +11 -2
- package/src/components/features/bundles/BundleChildrenPanel.tsx +7 -6
- package/src/components/features/bundles/BundleMetadata.tsx +1 -20
- package/src/components/features/channels/ChannelManagementDialog.tsx +1 -1
- package/src/components/features/insights/EventDetails.tsx +151 -0
- package/src/components/features/insights/EventHistoryCard.tsx +245 -0
- package/src/components/features/insights/EventHistoryList.tsx +63 -0
- package/src/components/features/insights/InsightsBundleReports.tsx +51 -0
- package/src/components/features/insights/InsightsControls.tsx +82 -76
- package/src/components/features/insights/InsightsErrorAlert.tsx +5 -5
- package/src/components/features/insights/InsightsOverview.tsx +156 -161
- package/src/components/features/insights/InsightsPageHeader.tsx +48 -0
- package/src/components/features/insights/InsightsPagination.tsx +52 -0
- package/src/components/features/insights/InstallationHistoryCard.tsx +178 -176
- package/src/components/features/insights/InstallationMatchesCard.tsx +111 -65
- package/src/components/features/insights/InstallationPageHeader.tsx +57 -105
- package/src/components/features/releases/ReleaseEditorSheet.tsx +24 -24
- package/src/components/ui/badge.tsx +2 -0
- package/src/components/ui/combobox.tsx +1 -0
- package/src/components/ui/skeleton.tsx +4 -1
- package/src/components/ui/tooltip.tsx +1 -1
- package/src/index.ts +7 -2
- package/src/lib/api-rpc.ts +19 -90
- package/src/lib/api.ts +0 -99
- package/src/lib/insights-api.ts +93 -137
- package/src/lib/insights-rpc.ts +69 -199
- package/src/lib/insights-view.ts +15 -0
- package/src/lib/public-bundle-error.ts +19 -0
- package/src/lib/server/releaseReachability.ts +1 -4
- package/src/lib/server/runtime.server.ts +5 -141
- package/src/router.tsx +3 -0
- package/src/routes/-installations-search.ts +25 -12
- package/src/routes/__root.tsx +6 -16
- package/src/routes/index.tsx +21 -81
- package/src/routes/insights.tsx +50 -105
- package/src/routes/installations.tsx +290 -138
- package/src/styles.css +6 -0
- package/.output/public/assets/BundleIdDisplay-D4ErdU5_.js +0 -1
- package/.output/public/assets/InsightsCapabilityContext-B42VqvP6.js +0 -1
- package/.output/public/assets/api-keys-api-DGVTTvTJ.js +0 -1
- package/.output/public/assets/api-keys-z16OZIP4.js +0 -1
- package/.output/public/assets/badge-Br_KDO0J.js +0 -1
- package/.output/public/assets/card-DzuEXvyJ.js +0 -1
- package/.output/public/assets/createServerFn-gM2-LFBy.js +0 -3
- package/.output/public/assets/dialog-BeAENgez.js +0 -1
- package/.output/public/assets/dist-Bssh_cv0.js +0 -1
- package/.output/public/assets/field-Buq148-A.js +0 -1
- package/.output/public/assets/index-uOpQAIC4.js +0 -10
- package/.output/public/assets/input-group-B3p5UpyW.js +0 -1
- package/.output/public/assets/insights-DJTr7Ozn.js +0 -1
- package/.output/public/assets/insights-api-DVMOoRMS.js +0 -1
- package/.output/public/assets/installations-BY64iIAK.js +0 -2
- package/.output/public/assets/installations-D5v9i3AL.js +0 -1
- package/.output/public/assets/lazyRouteComponent-DKYu5cZJ.js +0 -1
- package/.output/public/assets/routes-C8fvgETO.js +0 -1
- package/.output/public/assets/search-qsIDvS2I.js +0 -1
- package/.output/public/assets/signing-mJD88Y4C.js +0 -1
- package/.output/public/assets/styles-BZIG7t42.css +0 -2
- package/.output/public/assets/table-RamFEclP.js +0 -1
- package/.output/public/assets/useCompositeListItem-ChzDqdpc.js +0 -42
- package/.output/public/assets/useMutation-JsGVjQMY.js +0 -1
- package/.output/public/assets/useOpenInteractionType-Dwfy-SpA.js +0 -1
- package/.output/server/_libs/@reduxjs/toolkit+[...].mjs +0 -1554
- package/.output/server/_libs/d3-array.mjs +0 -231
- package/.output/server/_libs/d3-color.mjs +0 -330
- package/.output/server/_libs/d3-format.mjs +0 -252
- package/.output/server/_libs/d3-interpolate.mjs +0 -207
- package/.output/server/_libs/d3-path.mjs +0 -77
- package/.output/server/_libs/d3-scale+[...].mjs +0 -1907
- package/.output/server/_libs/d3-shape.mjs +0 -818
- package/.output/server/_libs/decimal.js-light.mjs +0 -884
- package/.output/server/_libs/es-toolkit.mjs +0 -1134
- package/.output/server/_libs/eventemitter3.mjs +0 -236
- package/.output/server/_libs/immer.mjs +0 -532
- package/.output/server/_libs/react-redux+[...].mjs +0 -205
- package/.output/server/_libs/recharts+[...].mjs +0 -14117
- package/.output/server/_ssr/BundleActivityChart-CWcdPuUn.mjs +0 -288
- package/.output/server/_ssr/BundleIdDisplay-BEvB3MvA.mjs +0 -13
- package/.output/server/_ssr/InsightsCapabilityContext-Cx8fjm2s.mjs +0 -15
- package/.output/server/_ssr/badge-CpWXQwyF.mjs +0 -26
- package/.output/server/_ssr/input-group-etIsBUqv.mjs +0 -288
- package/.output/server/_ssr/insights-api-C1F7UreR.mjs +0 -71
- package/.output/server/_ssr/insights-input-9fEJF-ZG.mjs +0 -96
- package/.output/server/_ssr/insights-rpc-C-8R6kED.mjs +0 -155
- package/.output/server/_ssr/insights-ygT_aIfo.mjs +0 -858
- package/.output/server/_ssr/installations-DqRT1QTd.mjs +0 -535
- package/.output/server/_ssr/installations-K8TCYTYh.mjs +0 -19
- package/.output/server/_ssr/runtime.server-la7TRAH_.mjs +0 -527
- package/.output/server/_ssr/table-CU58HeI7.mjs +0 -53
- package/.output/server/_tanstack-start-manifest_v-Mz9MmSlD.mjs +0 -103
- package/src/components/features/bundles/BundleActivityChart.tsx +0 -193
- package/src/components/features/bundles/BundleInsightsSummary.tsx +0 -123
- package/src/components/features/insights/ActivityChart.tsx +0 -150
- package/src/components/features/insights/BundleDistribution.tsx +0 -133
- package/src/components/features/insights/BundleSelector.tsx +0 -114
- package/src/components/features/insights/InsightsCapabilityContext.tsx +0 -24
- package/src/components/features/insights/InstallationPagination.tsx +0 -48
- package/src/components/features/insights/InstallationSearch.tsx +0 -230
- package/src/components/features/insights/UpdateOutcomes.tsx +0 -147
- package/src/lib/insights-error.ts +0 -19
- package/src/lib/insights-input.ts +0 -187
- package/src/lib/insights-overview.ts +0 -170
- package/src/lib/server/releaseActivity.ts +0 -27
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { Button } from "@/components/ui/button";
|
|
2
|
+
|
|
3
|
+
export function InsightsPagination({
|
|
4
|
+
hasPrevious,
|
|
5
|
+
label,
|
|
6
|
+
nextCursor,
|
|
7
|
+
onNext,
|
|
8
|
+
onPrevious,
|
|
9
|
+
pageLength,
|
|
10
|
+
pageNumber,
|
|
11
|
+
}: {
|
|
12
|
+
readonly hasPrevious: boolean;
|
|
13
|
+
readonly label: string;
|
|
14
|
+
readonly nextCursor: string | null;
|
|
15
|
+
readonly onNext: () => void;
|
|
16
|
+
readonly onPrevious: () => void;
|
|
17
|
+
readonly pageLength: number;
|
|
18
|
+
readonly pageNumber: number;
|
|
19
|
+
}) {
|
|
20
|
+
return (
|
|
21
|
+
<nav
|
|
22
|
+
aria-label={`${label} pagination`}
|
|
23
|
+
className="flex flex-wrap items-center justify-between gap-3 border-t px-4 py-3 sm:px-6"
|
|
24
|
+
>
|
|
25
|
+
<span className="text-xs text-muted-foreground tabular-nums">
|
|
26
|
+
Page {pageNumber} · {pageLength.toLocaleString()} rows
|
|
27
|
+
</span>
|
|
28
|
+
<div className="flex gap-2">
|
|
29
|
+
<Button
|
|
30
|
+
className="h-11 min-w-11 px-3 lg:h-8 lg:min-w-0 lg:px-2"
|
|
31
|
+
disabled={!hasPrevious}
|
|
32
|
+
onClick={onPrevious}
|
|
33
|
+
size="sm"
|
|
34
|
+
type="button"
|
|
35
|
+
variant="outline"
|
|
36
|
+
>
|
|
37
|
+
Previous
|
|
38
|
+
</Button>
|
|
39
|
+
<Button
|
|
40
|
+
className="h-11 min-w-11 px-3 lg:h-8 lg:min-w-0 lg:px-2"
|
|
41
|
+
disabled={nextCursor === null}
|
|
42
|
+
onClick={onNext}
|
|
43
|
+
size="sm"
|
|
44
|
+
type="button"
|
|
45
|
+
variant="outline"
|
|
46
|
+
>
|
|
47
|
+
Next
|
|
48
|
+
</Button>
|
|
49
|
+
</div>
|
|
50
|
+
</nav>
|
|
51
|
+
);
|
|
52
|
+
}
|
|
@@ -1,15 +1,8 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { RefreshCw } from "lucide-react";
|
|
2
2
|
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
Card,
|
|
8
|
-
CardContent,
|
|
9
|
-
CardDescription,
|
|
10
|
-
CardHeader,
|
|
11
|
-
CardTitle,
|
|
12
|
-
} from "@/components/ui/card";
|
|
3
|
+
import { HashValueDisplay } from "@/components/HashValueDisplay";
|
|
4
|
+
import { Button } from "@/components/ui/button";
|
|
5
|
+
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
|
|
13
6
|
import { Separator } from "@/components/ui/separator";
|
|
14
7
|
import { Skeleton } from "@/components/ui/skeleton";
|
|
15
8
|
import {
|
|
@@ -21,28 +14,20 @@ import {
|
|
|
21
14
|
TableRow,
|
|
22
15
|
} from "@/components/ui/table";
|
|
23
16
|
import type {
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
} from "@/lib/
|
|
28
|
-
|
|
29
|
-
import { InstallationPagination } from "./InstallationPagination";
|
|
17
|
+
InsightsEventRow,
|
|
18
|
+
InsightsInstallationViewRow,
|
|
19
|
+
InsightsViewPage,
|
|
20
|
+
} from "@/lib/insights-view";
|
|
30
21
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
minute: "2-digit",
|
|
41
|
-
second: "2-digit",
|
|
42
|
-
hour12: false,
|
|
43
|
-
timeZone: "UTC",
|
|
44
|
-
}).format(date);
|
|
45
|
-
};
|
|
22
|
+
import {
|
|
23
|
+
EventBundleTransition,
|
|
24
|
+
EventTimestamp,
|
|
25
|
+
EventTypeBadge,
|
|
26
|
+
useInsightsTimeFormat,
|
|
27
|
+
} from "./EventDetails";
|
|
28
|
+
import { EventHistoryList } from "./EventHistoryList";
|
|
29
|
+
import { InsightsErrorAlert } from "./InsightsErrorAlert";
|
|
30
|
+
import { InsightsPagination } from "./InsightsPagination";
|
|
46
31
|
|
|
47
32
|
const getUserLabel = (event: {
|
|
48
33
|
readonly username: string | null;
|
|
@@ -50,7 +35,7 @@ const getUserLabel = (event: {
|
|
|
50
35
|
}) => event.userId ?? event.username ?? "—";
|
|
51
36
|
|
|
52
37
|
const getLastKnownBundleId = (
|
|
53
|
-
event:
|
|
38
|
+
event: InsightsEventRow | InsightsInstallationViewRow,
|
|
54
39
|
) =>
|
|
55
40
|
"lastKnownBundleId" in event
|
|
56
41
|
? event.lastKnownBundleId
|
|
@@ -60,188 +45,205 @@ export function InstallationHistoryCard({
|
|
|
60
45
|
error,
|
|
61
46
|
history,
|
|
62
47
|
isLoading,
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
48
|
+
onNext,
|
|
49
|
+
onPrevious,
|
|
50
|
+
onRefresh,
|
|
51
|
+
pageNumber,
|
|
66
52
|
selectedEvent,
|
|
67
53
|
selectedInstallId,
|
|
68
54
|
}: {
|
|
69
55
|
readonly error: unknown;
|
|
70
|
-
readonly history:
|
|
56
|
+
readonly history: InsightsViewPage<InsightsEventRow> | undefined;
|
|
71
57
|
readonly isLoading: boolean;
|
|
72
|
-
readonly
|
|
73
|
-
readonly
|
|
74
|
-
readonly
|
|
58
|
+
readonly onRefresh?: () => void;
|
|
59
|
+
readonly onNext: () => void;
|
|
60
|
+
readonly onPrevious: () => void;
|
|
61
|
+
readonly pageNumber: number;
|
|
75
62
|
readonly selectedEvent:
|
|
76
|
-
|
|
|
77
|
-
|
|
|
63
|
+
| InsightsEventRow
|
|
64
|
+
| InsightsInstallationViewRow
|
|
78
65
|
| undefined;
|
|
79
|
-
readonly selectedInstallId: string;
|
|
66
|
+
readonly selectedInstallId: string | undefined;
|
|
80
67
|
}) {
|
|
68
|
+
const dateTimeFormat = useInsightsTimeFormat();
|
|
81
69
|
const lastKnownBundleId = selectedEvent
|
|
82
70
|
? getLastKnownBundleId(selectedEvent)
|
|
83
71
|
: undefined;
|
|
84
72
|
|
|
85
73
|
return (
|
|
86
|
-
<Card className="min-h-0 min-w-0">
|
|
87
|
-
<CardHeader className="p-
|
|
88
|
-
<div className="flex items-
|
|
74
|
+
<Card className="@container min-h-0 min-w-0 shadow-sm">
|
|
75
|
+
<CardHeader className="p-4 sm:p-6">
|
|
76
|
+
<div className="flex flex-wrap items-center justify-between gap-3">
|
|
89
77
|
<div className="flex min-w-0 flex-col gap-1.5">
|
|
90
78
|
<CardTitle className="text-sm font-medium">
|
|
91
79
|
<h2>
|
|
92
|
-
{selectedInstallId
|
|
80
|
+
{selectedInstallId !== undefined
|
|
93
81
|
? "Installation history"
|
|
94
82
|
: "Select an installation"}
|
|
95
83
|
</h2>
|
|
96
84
|
</CardTitle>
|
|
97
|
-
<CardDescription>
|
|
98
|
-
{selectedInstallId
|
|
99
|
-
? "Recorded bundle changes for this installation."
|
|
100
|
-
: "Choose a match to view its recorded bundle changes."}
|
|
101
|
-
</CardDescription>
|
|
102
85
|
</div>
|
|
103
|
-
{
|
|
104
|
-
<
|
|
86
|
+
{onRefresh && selectedInstallId !== undefined ? (
|
|
87
|
+
<Button
|
|
88
|
+
className="h-11 lg:h-8"
|
|
89
|
+
size="lg"
|
|
90
|
+
variant="outline"
|
|
91
|
+
onClick={onRefresh}
|
|
92
|
+
disabled={isLoading}
|
|
93
|
+
>
|
|
94
|
+
<RefreshCw aria-hidden="true" data-icon="inline-start" />
|
|
95
|
+
Refresh
|
|
96
|
+
</Button>
|
|
105
97
|
) : null}
|
|
106
98
|
</div>
|
|
107
99
|
</CardHeader>
|
|
108
100
|
<CardContent className="min-h-0 p-0">
|
|
109
|
-
{selectedInstallId ? (
|
|
101
|
+
{selectedInstallId !== undefined && selectedEvent ? (
|
|
102
|
+
<>
|
|
103
|
+
<section
|
|
104
|
+
aria-labelledby="latest-installation-state"
|
|
105
|
+
className="px-4 pb-4 sm:px-6 sm:pb-6"
|
|
106
|
+
>
|
|
107
|
+
<h3 className="sr-only" id="latest-installation-state">
|
|
108
|
+
Latest reported state
|
|
109
|
+
</h3>
|
|
110
|
+
<dl className="grid grid-cols-2 gap-4 @[36rem]:grid-cols-3">
|
|
111
|
+
<div className="col-span-2 min-w-0 @[36rem]:col-span-1">
|
|
112
|
+
<dt className="text-xs text-muted-foreground">User ID</dt>
|
|
113
|
+
<dd className="mt-1 text-sm font-medium wrap-anywhere">
|
|
114
|
+
{getUserLabel(selectedEvent)}
|
|
115
|
+
</dd>
|
|
116
|
+
</div>
|
|
117
|
+
<div className="min-w-0">
|
|
118
|
+
<dt className="text-xs text-muted-foreground">Install ID</dt>
|
|
119
|
+
<dd className="mt-1 font-mono text-xs">
|
|
120
|
+
<HashValueDisplay
|
|
121
|
+
value={selectedInstallId}
|
|
122
|
+
buttonClassName="min-h-11 px-3 lg:min-h-0 lg:px-1.5"
|
|
123
|
+
/>
|
|
124
|
+
</dd>
|
|
125
|
+
</div>
|
|
126
|
+
<div className="min-w-0">
|
|
127
|
+
<dt className="text-xs text-muted-foreground">
|
|
128
|
+
Last known bundle
|
|
129
|
+
</dt>
|
|
130
|
+
<dd className="mt-1 font-mono text-xs">
|
|
131
|
+
{lastKnownBundleId ? (
|
|
132
|
+
<HashValueDisplay
|
|
133
|
+
value={lastKnownBundleId}
|
|
134
|
+
buttonClassName="min-h-11 px-3 lg:min-h-0 lg:px-1.5"
|
|
135
|
+
/>
|
|
136
|
+
) : (
|
|
137
|
+
"—"
|
|
138
|
+
)}
|
|
139
|
+
</dd>
|
|
140
|
+
</div>
|
|
141
|
+
</dl>
|
|
142
|
+
</section>
|
|
143
|
+
<Separator />
|
|
144
|
+
</>
|
|
145
|
+
) : null}
|
|
146
|
+
{selectedInstallId !== undefined ? (
|
|
110
147
|
isLoading ? (
|
|
111
|
-
<div
|
|
148
|
+
<div
|
|
149
|
+
className="flex flex-col gap-3 p-6"
|
|
150
|
+
role="status"
|
|
151
|
+
aria-label="Loading installation history"
|
|
152
|
+
>
|
|
112
153
|
<Skeleton className="h-10 w-full" />
|
|
113
154
|
<Skeleton className="h-10 w-full" />
|
|
114
155
|
<Skeleton className="h-10 w-full" />
|
|
115
156
|
</div>
|
|
157
|
+
) : error ? (
|
|
158
|
+
<div className="p-6">
|
|
159
|
+
<InsightsErrorAlert
|
|
160
|
+
error={error instanceof Error ? error : new Error()}
|
|
161
|
+
fallbackTitle="Installation history unavailable"
|
|
162
|
+
/>
|
|
163
|
+
</div>
|
|
116
164
|
) : history && history.data.length > 0 ? (
|
|
117
165
|
<>
|
|
118
|
-
<
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
>
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
</dt>
|
|
133
|
-
<dd className="mt-1 font-mono text-xs">
|
|
134
|
-
<BundleIdDisplay bundleId={selectedInstallId} />
|
|
135
|
-
</dd>
|
|
136
|
-
</div>
|
|
137
|
-
<div className="min-w-0">
|
|
138
|
-
<dt className="text-xs text-muted-foreground">User ID</dt>
|
|
139
|
-
<dd className="mt-1 truncate text-xs font-medium">
|
|
140
|
-
{selectedEvent ? getUserLabel(selectedEvent) : "—"}
|
|
141
|
-
</dd>
|
|
142
|
-
</div>
|
|
143
|
-
<div className="min-w-0">
|
|
144
|
-
<dt className="text-xs text-muted-foreground">
|
|
145
|
-
Last known bundle
|
|
146
|
-
</dt>
|
|
147
|
-
<dd className="mt-1 font-mono text-xs">
|
|
148
|
-
{lastKnownBundleId ? (
|
|
149
|
-
<BundleIdDisplay bundleId={lastKnownBundleId} />
|
|
150
|
-
) : (
|
|
151
|
-
"—"
|
|
152
|
-
)}
|
|
153
|
-
</dd>
|
|
154
|
-
</div>
|
|
155
|
-
</dl>
|
|
156
|
-
</section>
|
|
157
|
-
<Separator />
|
|
158
|
-
<Table className="min-w-3xl table-fixed">
|
|
159
|
-
<TableHeader>
|
|
160
|
-
<TableRow className="hover:bg-transparent [&>th]:h-12 [&>th]:px-5">
|
|
161
|
-
<TableHead className="w-1/5 whitespace-normal">
|
|
162
|
-
Reported (UTC)
|
|
163
|
-
</TableHead>
|
|
164
|
-
<TableHead className="w-1/6 whitespace-normal">
|
|
165
|
-
App version
|
|
166
|
-
</TableHead>
|
|
167
|
-
<TableHead className="w-1/5 whitespace-normal">
|
|
168
|
-
Change
|
|
169
|
-
</TableHead>
|
|
170
|
-
<TableHead className="whitespace-normal">
|
|
171
|
-
Bundle transition
|
|
172
|
-
</TableHead>
|
|
173
|
-
</TableRow>
|
|
174
|
-
</TableHeader>
|
|
175
|
-
<TableBody>
|
|
176
|
-
{history.data.map((event) => (
|
|
177
|
-
<TableRow
|
|
178
|
-
className="[&>td]:px-5 [&>td]:py-4"
|
|
179
|
-
key={event.id}
|
|
180
|
-
>
|
|
181
|
-
<TableCell className="whitespace-normal align-top text-sm text-muted-foreground">
|
|
182
|
-
{formatDateTime(event.receivedAtMs)}
|
|
183
|
-
</TableCell>
|
|
184
|
-
<TableCell className="whitespace-normal align-top font-mono text-xs">
|
|
185
|
-
{event.appVersion}
|
|
186
|
-
</TableCell>
|
|
187
|
-
<TableCell className="whitespace-normal align-top">
|
|
188
|
-
<Badge variant="secondary">
|
|
189
|
-
{event.type === "UPDATE_APPLIED"
|
|
190
|
-
? "Bundle applied"
|
|
191
|
-
: "Recovered"}
|
|
192
|
-
</Badge>
|
|
193
|
-
</TableCell>
|
|
194
|
-
<TableCell className="whitespace-normal align-top">
|
|
195
|
-
<div className="grid grid-cols-[2rem_minmax(0,1fr)] gap-x-3 gap-y-3">
|
|
196
|
-
<span className="text-muted-foreground">From</span>
|
|
197
|
-
{event.fromBundleId ? (
|
|
198
|
-
<BundleIdDisplay bundleId={event.fromBundleId} />
|
|
199
|
-
) : (
|
|
200
|
-
"—"
|
|
201
|
-
)}
|
|
202
|
-
<span className="text-muted-foreground">To</span>
|
|
203
|
-
{event.toBundleId ? (
|
|
204
|
-
<BundleIdDisplay bundleId={event.toBundleId} />
|
|
205
|
-
) : (
|
|
206
|
-
"—"
|
|
207
|
-
)}
|
|
208
|
-
</div>
|
|
209
|
-
</TableCell>
|
|
166
|
+
<div className="@[48rem]:hidden">
|
|
167
|
+
<EventHistoryList
|
|
168
|
+
events={history.data}
|
|
169
|
+
formatter={dateTimeFormat}
|
|
170
|
+
/>
|
|
171
|
+
</div>
|
|
172
|
+
<div className="hidden @[48rem]:block">
|
|
173
|
+
<Table className="min-w-3xl table-fixed">
|
|
174
|
+
<TableHeader>
|
|
175
|
+
<TableRow className="[&>th]:px-4 sm:[&>th]:px-6">
|
|
176
|
+
<TableHead className="w-64">Time</TableHead>
|
|
177
|
+
<TableHead className="w-48">Event</TableHead>
|
|
178
|
+
<TableHead className="w-32">App</TableHead>
|
|
179
|
+
<TableHead className="w-52">Bundle</TableHead>
|
|
210
180
|
</TableRow>
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
181
|
+
</TableHeader>
|
|
182
|
+
<TableBody>
|
|
183
|
+
{history.data.map((event) => (
|
|
184
|
+
<TableRow
|
|
185
|
+
className="[&>td]:px-4 [&>td]:py-4 [&>td]:align-top sm:[&>td]:px-6"
|
|
186
|
+
key={event.id}
|
|
187
|
+
>
|
|
188
|
+
<TableCell className="whitespace-normal text-xs tabular-nums">
|
|
189
|
+
<EventTimestamp
|
|
190
|
+
value={event.receivedAtMs}
|
|
191
|
+
formatter={dateTimeFormat}
|
|
192
|
+
/>
|
|
193
|
+
</TableCell>
|
|
194
|
+
<TableCell>
|
|
195
|
+
<EventTypeBadge type={event.type} />
|
|
196
|
+
</TableCell>
|
|
197
|
+
<TableCell className="whitespace-normal text-xs">
|
|
198
|
+
<div className="flex flex-col gap-2">
|
|
199
|
+
<span>
|
|
200
|
+
{event.platform === "ios" ? "iOS" : "Android"}{" "}
|
|
201
|
+
{event.appVersion}
|
|
202
|
+
</span>
|
|
203
|
+
<span className="text-muted-foreground">
|
|
204
|
+
{event.channel}
|
|
205
|
+
</span>
|
|
206
|
+
</div>
|
|
207
|
+
</TableCell>
|
|
208
|
+
<TableCell className="whitespace-normal text-xs">
|
|
209
|
+
<EventBundleTransition event={event} />
|
|
210
|
+
</TableCell>
|
|
211
|
+
</TableRow>
|
|
212
|
+
))}
|
|
213
|
+
</TableBody>
|
|
214
|
+
</Table>
|
|
215
|
+
</div>
|
|
216
|
+
<InsightsPagination
|
|
217
|
+
hasPrevious={pageNumber > 1}
|
|
215
218
|
label="Installation history"
|
|
216
|
-
|
|
217
|
-
|
|
219
|
+
nextCursor={history.nextCursor}
|
|
220
|
+
onNext={onNext}
|
|
221
|
+
onPrevious={onPrevious}
|
|
218
222
|
pageLength={history.data.length}
|
|
219
|
-
|
|
220
|
-
onOffsetChange={onOffsetChange}
|
|
223
|
+
pageNumber={pageNumber}
|
|
221
224
|
/>
|
|
222
225
|
</>
|
|
223
|
-
) : error ? (
|
|
224
|
-
<div className="p-5 pt-0">
|
|
225
|
-
<Alert variant="destructive">
|
|
226
|
-
<TriangleAlert aria-hidden="true" />
|
|
227
|
-
<AlertTitle>Installation history unavailable</AlertTitle>
|
|
228
|
-
<AlertDescription>
|
|
229
|
-
{error instanceof Error
|
|
230
|
-
? error.message
|
|
231
|
-
: "Failed to load installation history."}
|
|
232
|
-
</AlertDescription>
|
|
233
|
-
</Alert>
|
|
234
|
-
</div>
|
|
235
226
|
) : (
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
227
|
+
<>
|
|
228
|
+
<div className="p-6 text-sm text-muted-foreground">
|
|
229
|
+
{pageNumber > 1 || history?.nextCursor
|
|
230
|
+
? "No bundle changes on this page."
|
|
231
|
+
: "No bundle changes recorded yet."}
|
|
232
|
+
</div>
|
|
233
|
+
{history && (pageNumber > 1 || history.nextCursor) ? (
|
|
234
|
+
<InsightsPagination
|
|
235
|
+
hasPrevious={pageNumber > 1}
|
|
236
|
+
label="Installation history"
|
|
237
|
+
nextCursor={history.nextCursor}
|
|
238
|
+
onNext={onNext}
|
|
239
|
+
onPrevious={onPrevious}
|
|
240
|
+
pageLength={0}
|
|
241
|
+
pageNumber={pageNumber}
|
|
242
|
+
/>
|
|
243
|
+
) : null}
|
|
244
|
+
</>
|
|
239
245
|
)
|
|
240
|
-
) :
|
|
241
|
-
<div className="p-5 pt-0 text-sm text-muted-foreground">
|
|
242
|
-
Choose an installation to inspect its update history.
|
|
243
|
-
</div>
|
|
244
|
-
)}
|
|
246
|
+
) : null}
|
|
245
247
|
</CardContent>
|
|
246
248
|
</Card>
|
|
247
249
|
);
|