@hot-updater/console 1.0.0-rc.0 → 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-DspNKfMj.js → dist-C_NydL0e.js} +1 -1
- 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-Bqc72UZG.js +1 -0
- package/.output/public/assets/{routes-DcQnVajO.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-DBP9TQ7K.mjs → __23tanstack-start-server-fn-resolver-B7ioJhtE.mjs} +44 -52
- package/.output/server/_libs/@base-ui/react+[...].mjs +1906 -4040
- 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-BnM_o2nS.mjs → api-keys-CZeTPQys.mjs} +11 -13
- package/.output/server/_ssr/{api-keys-api-CIywsSF5.mjs → api-keys-api-BUPQVSpk.mjs} +2 -2
- package/.output/server/_ssr/{api-keys-rpc-BSp1wkIV.mjs → api-keys-rpc-Cs7tS5_j.mjs} +5 -5
- package/.output/server/_ssr/{api-rpc-cG5wd_tO.mjs → api-rpc-tAupfGQm.mjs} +73 -142
- package/.output/server/_ssr/{auth-rpc-BrJ6obHJ.mjs → auth-rpc-DUaeOWKK.mjs} +4 -4
- package/.output/server/_ssr/{auth.server-DwKoZoQM.mjs → auth.server-DW71WzsD.mjs} +2 -5
- package/.output/server/_ssr/{bundle-signing-rpc-COoQhW8E.mjs → bundle-signing-rpc-BhnBw0-d.mjs} +2 -2
- package/.output/server/_ssr/bundle-signing.server-C4NW5mWx.mjs +12 -0
- package/.output/server/_ssr/{alert-Dim3MGY5.mjs → card-BRiPmi0C.mjs} +61 -39
- package/.output/server/_ssr/{config.server-DEiLhKmy.mjs → config.server-afDuAwaG.mjs} +15 -8
- package/.output/server/_ssr/{createSsrRpc-9P0S0lJ3.mjs → createSsrRpc-DjWNJ0uc.mjs} +6 -6
- package/.output/server/_ssr/databaseJsonValue-d6I3nAS4.mjs +45 -0
- package/.output/server/_ssr/{databaseRows-CwbNwYSl.mjs → databaseRows-5bCRTxm-.mjs} +4 -44
- package/.output/server/_ssr/{deleteBundle-Cu_XOMt0.mjs → deleteBundle-BTGwBgzx.mjs} +2 -2
- package/.output/server/_ssr/{dialog-CQuRMNZ4.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-C-KUBfOi.mjs → router-B9wG_9f8.mjs} +37 -46
- package/.output/server/_ssr/{routes-Z7TwC6nC.mjs → routes-CKrrS2q2.mjs} +3 -3
- package/.output/server/_ssr/{routes-BM4ht9jb.mjs → routes-D7Yh_jfj.mjs} +402 -390
- package/.output/server/_ssr/runtime.server-DacU1TBV.mjs +438 -0
- package/.output/server/_ssr/{server-BjzmvXnO.mjs → server-D_C2rMzf.mjs} +5 -5
- package/.output/server/_ssr/{signing-k8GxyBDF.mjs → signing-Dz1WkZOf.mjs} +16 -85
- package/.output/server/_ssr/ssr.mjs +1 -1
- package/.output/server/_ssr/{field-DRIXKjZG.mjs → table-CnZmon_Z.mjs} +51 -5
- package/.output/server/_ssr/{uuidv7-BbJ-9D_I.mjs → uuidv7-D0QFkPL_.mjs} +3 -3
- package/.output/server/_tanstack-start-manifest_v-2MjTyxil.mjs +97 -0
- package/.output/server/index.mjs +168 -203
- package/lib/index.d.mts +4 -4
- package/lib/vite-internal.mjs +1 -1
- package/lib/vite.d.mts +0 -1
- package/package.json +8 -8
- package/src/components/AppSidebar.tsx +12 -16
- package/src/components/ConsoleAccessPage.tsx +1 -1
- package/src/components/HashValueDisplay.tsx +11 -2
- package/src/components/features/api-keys/ApiKeysPage.tsx +1 -1
- 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 +121 -0
- package/src/components/features/{analytics/AnalyticsErrorAlert.tsx → insights/InsightsErrorAlert.tsx} +6 -6
- package/src/components/features/insights/InsightsOverview.tsx +203 -0
- 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 +250 -0
- package/src/components/features/insights/InstallationMatchesCard.tsx +178 -0
- package/src/components/features/insights/InstallationPageHeader.tsx +90 -0
- package/src/components/features/releases/ReleaseEditorSheet.tsx +24 -24
- package/src/components/features/signing/BundleSigningPage.tsx +18 -126
- 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 -3
- package/src/lib/api-rpc.ts +19 -90
- package/src/lib/api.ts +0 -99
- package/src/lib/insights-api.ts +100 -0
- package/src/lib/insights-rpc.ts +88 -0
- package/src/lib/insights-view.ts +15 -0
- package/src/lib/public-bundle-error.ts +19 -0
- package/src/lib/server/bundle-signing.server.ts +5 -82
- package/src/lib/server/console-runtime.server.ts +0 -9
- package/src/lib/server/releaseReachability.ts +1 -4
- package/src/lib/server/runtime.server.ts +6 -142
- package/src/routeTree.gen.ts +21 -21
- package/src/router.tsx +3 -0
- package/src/routes/-installations-search.ts +25 -12
- package/src/routes/__root.tsx +6 -16
- package/src/routes/api-keys.tsx +1 -1
- package/src/routes/index.tsx +21 -81
- package/src/routes/insights.tsx +84 -0
- package/src/routes/installations.tsx +294 -142
- package/src/styles.css +6 -0
- package/.output/public/assets/AnalyticsCapabilityContext-BCke57-7.js +0 -1
- package/.output/public/assets/BundleActivityChart-CnsBe_1J.js +0 -42
- package/.output/public/assets/BundleIdDisplay-Dky75zLU.js +0 -1
- package/.output/public/assets/alert-C-1KvDW8.js +0 -1
- package/.output/public/assets/analytics-Bqz0c-BT.js +0 -1
- package/.output/public/assets/analytics-api-CJdrTLLO.js +0 -1
- package/.output/public/assets/api-B_Rh-uzC.js +0 -1
- package/.output/public/assets/api-keys-BurCFhzH.js +0 -1
- package/.output/public/assets/api-keys-api-BEDJdQg3.js +0 -1
- package/.output/public/assets/badge-Bf0fZ-Gx.js +0 -1
- package/.output/public/assets/createServerFn-gM2-LFBy.js +0 -3
- package/.output/public/assets/dialog-BS60BRr2.js +0 -1
- package/.output/public/assets/download-O-yNBc9H.js +0 -1
- package/.output/public/assets/field-Buq148-A.js +0 -1
- package/.output/public/assets/index-kFhd2S78.js +0 -10
- package/.output/public/assets/installations-BrQ-od41.js +0 -2
- package/.output/public/assets/installations-CGlZ3ROz.js +0 -1
- package/.output/public/assets/lazyRouteComponent-rPzgA7S-.js +0 -1
- package/.output/public/assets/loader-circle-DCYF-wJl.js +0 -1
- package/.output/public/assets/refresh-cw-n8XYbPPj.js +0 -1
- package/.output/public/assets/routes-CrdokJ80.js +0 -1
- package/.output/public/assets/search-DLhbWw3W.js +0 -1
- package/.output/public/assets/signing-HRexfjsH.js +0 -1
- package/.output/public/assets/styles-eB4EtvFS.css +0 -2
- package/.output/public/assets/table-D8CLieHX.js +0 -1
- package/.output/public/assets/textarea-YJLTVAoq.js +0 -1
- package/.output/public/assets/useMutation-JsGVjQMY.js +0 -1
- package/.output/public/assets/useOpenInteractionType-4cRD5xO0.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/AnalyticsCapabilityContext-ui4DX8GO.mjs +0 -15
- package/.output/server/_ssr/BundleActivityChart-BiB9ZORH.mjs +0 -288
- package/.output/server/_ssr/BundleIdDisplay-Czk6iR6p.mjs +0 -13
- package/.output/server/_ssr/analytics-DtMTn8fn.mjs +0 -858
- package/.output/server/_ssr/analytics-api-Cg1M5v_H.mjs +0 -71
- package/.output/server/_ssr/analytics-input-fRRRn0uA.mjs +0 -96
- package/.output/server/_ssr/analytics-rpc-DY5uXvHT.mjs +0 -155
- package/.output/server/_ssr/api-BTSv1tZb.mjs +0 -282
- package/.output/server/_ssr/badge-DCxbEeof.mjs +0 -26
- package/.output/server/_ssr/bundle-signing.server-D5u8KkMp.mjs +0 -51
- package/.output/server/_ssr/installations-B-azgAvX.mjs +0 -19
- package/.output/server/_ssr/installations-Ctvzp2JH.mjs +0 -535
- package/.output/server/_ssr/runtime.server-awTLiiXW.mjs +0 -527
- package/.output/server/_ssr/table-v1yCvYo7.mjs +0 -53
- package/.output/server/_ssr/textarea-DYHnskhb.mjs +0 -14
- package/.output/server/_tanstack-start-manifest_v-CH4StzJu.mjs +0 -108
- package/src/components/features/analytics/ActivityChart.tsx +0 -150
- package/src/components/features/analytics/AnalyticsCapabilityContext.tsx +0 -24
- package/src/components/features/analytics/AnalyticsControls.tsx +0 -115
- package/src/components/features/analytics/AnalyticsOverview.tsx +0 -208
- package/src/components/features/analytics/BundleDistribution.tsx +0 -133
- package/src/components/features/analytics/BundleSelector.tsx +0 -114
- package/src/components/features/analytics/InstallationHistoryCard.tsx +0 -248
- package/src/components/features/analytics/InstallationMatchesCard.tsx +0 -132
- package/src/components/features/analytics/InstallationPageHeader.tsx +0 -138
- package/src/components/features/analytics/InstallationPagination.tsx +0 -48
- package/src/components/features/analytics/InstallationSearch.tsx +0 -230
- package/src/components/features/analytics/UpdateOutcomes.tsx +0 -147
- package/src/components/features/bundles/BundleActivityChart.tsx +0 -193
- package/src/components/features/bundles/BundleAnalyticsSummary.tsx +0 -123
- package/src/lib/analytics-api.ts +0 -145
- package/src/lib/analytics-error.ts +0 -19
- package/src/lib/analytics-input.ts +0 -187
- package/src/lib/analytics-overview.ts +0 -170
- package/src/lib/analytics-rpc.ts +0 -218
- package/src/lib/server/releaseActivity.ts +0 -27
- package/src/routes/analytics.tsx +0 -139
- /package/.output/public/assets/{preload-helper-TKOBYGYD.js → preload-helper-CQ36nxok.js} +0 -0
|
@@ -0,0 +1,250 @@
|
|
|
1
|
+
import { RefreshCw } from "lucide-react";
|
|
2
|
+
|
|
3
|
+
import { HashValueDisplay } from "@/components/HashValueDisplay";
|
|
4
|
+
import { Button } from "@/components/ui/button";
|
|
5
|
+
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
|
|
6
|
+
import { Separator } from "@/components/ui/separator";
|
|
7
|
+
import { Skeleton } from "@/components/ui/skeleton";
|
|
8
|
+
import {
|
|
9
|
+
Table,
|
|
10
|
+
TableBody,
|
|
11
|
+
TableCell,
|
|
12
|
+
TableHead,
|
|
13
|
+
TableHeader,
|
|
14
|
+
TableRow,
|
|
15
|
+
} from "@/components/ui/table";
|
|
16
|
+
import type {
|
|
17
|
+
InsightsEventRow,
|
|
18
|
+
InsightsInstallationViewRow,
|
|
19
|
+
InsightsViewPage,
|
|
20
|
+
} from "@/lib/insights-view";
|
|
21
|
+
|
|
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";
|
|
31
|
+
|
|
32
|
+
const getUserLabel = (event: {
|
|
33
|
+
readonly username: string | null;
|
|
34
|
+
readonly userId: string | null;
|
|
35
|
+
}) => event.userId ?? event.username ?? "—";
|
|
36
|
+
|
|
37
|
+
const getLastKnownBundleId = (
|
|
38
|
+
event: InsightsEventRow | InsightsInstallationViewRow,
|
|
39
|
+
) =>
|
|
40
|
+
"lastKnownBundleId" in event
|
|
41
|
+
? event.lastKnownBundleId
|
|
42
|
+
: (event.toBundleId ?? event.fromBundleId);
|
|
43
|
+
|
|
44
|
+
export function InstallationHistoryCard({
|
|
45
|
+
error,
|
|
46
|
+
history,
|
|
47
|
+
isLoading,
|
|
48
|
+
onNext,
|
|
49
|
+
onPrevious,
|
|
50
|
+
onRefresh,
|
|
51
|
+
pageNumber,
|
|
52
|
+
selectedEvent,
|
|
53
|
+
selectedInstallId,
|
|
54
|
+
}: {
|
|
55
|
+
readonly error: unknown;
|
|
56
|
+
readonly history: InsightsViewPage<InsightsEventRow> | undefined;
|
|
57
|
+
readonly isLoading: boolean;
|
|
58
|
+
readonly onRefresh?: () => void;
|
|
59
|
+
readonly onNext: () => void;
|
|
60
|
+
readonly onPrevious: () => void;
|
|
61
|
+
readonly pageNumber: number;
|
|
62
|
+
readonly selectedEvent:
|
|
63
|
+
| InsightsEventRow
|
|
64
|
+
| InsightsInstallationViewRow
|
|
65
|
+
| undefined;
|
|
66
|
+
readonly selectedInstallId: string | undefined;
|
|
67
|
+
}) {
|
|
68
|
+
const dateTimeFormat = useInsightsTimeFormat();
|
|
69
|
+
const lastKnownBundleId = selectedEvent
|
|
70
|
+
? getLastKnownBundleId(selectedEvent)
|
|
71
|
+
: undefined;
|
|
72
|
+
|
|
73
|
+
return (
|
|
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">
|
|
77
|
+
<div className="flex min-w-0 flex-col gap-1.5">
|
|
78
|
+
<CardTitle className="text-sm font-medium">
|
|
79
|
+
<h2>
|
|
80
|
+
{selectedInstallId !== undefined
|
|
81
|
+
? "Installation history"
|
|
82
|
+
: "Select an installation"}
|
|
83
|
+
</h2>
|
|
84
|
+
</CardTitle>
|
|
85
|
+
</div>
|
|
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>
|
|
97
|
+
) : null}
|
|
98
|
+
</div>
|
|
99
|
+
</CardHeader>
|
|
100
|
+
<CardContent className="min-h-0 p-0">
|
|
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 ? (
|
|
147
|
+
isLoading ? (
|
|
148
|
+
<div
|
|
149
|
+
className="flex flex-col gap-3 p-6"
|
|
150
|
+
role="status"
|
|
151
|
+
aria-label="Loading installation history"
|
|
152
|
+
>
|
|
153
|
+
<Skeleton className="h-10 w-full" />
|
|
154
|
+
<Skeleton className="h-10 w-full" />
|
|
155
|
+
<Skeleton className="h-10 w-full" />
|
|
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>
|
|
164
|
+
) : history && history.data.length > 0 ? (
|
|
165
|
+
<>
|
|
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>
|
|
180
|
+
</TableRow>
|
|
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}
|
|
218
|
+
label="Installation history"
|
|
219
|
+
nextCursor={history.nextCursor}
|
|
220
|
+
onNext={onNext}
|
|
221
|
+
onPrevious={onPrevious}
|
|
222
|
+
pageLength={history.data.length}
|
|
223
|
+
pageNumber={pageNumber}
|
|
224
|
+
/>
|
|
225
|
+
</>
|
|
226
|
+
) : (
|
|
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
|
+
</>
|
|
245
|
+
)
|
|
246
|
+
) : null}
|
|
247
|
+
</CardContent>
|
|
248
|
+
</Card>
|
|
249
|
+
);
|
|
250
|
+
}
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
import { Check, ChevronDown } from "lucide-react";
|
|
2
|
+
import { useId, useRef, useState } from "react";
|
|
3
|
+
|
|
4
|
+
import { shortenIdentifier } from "@/components/HashValueDisplay";
|
|
5
|
+
import { Button, buttonVariants } from "@/components/ui/button";
|
|
6
|
+
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
|
|
7
|
+
import type {
|
|
8
|
+
InsightsInstallationViewRow,
|
|
9
|
+
InsightsViewPage,
|
|
10
|
+
} from "@/lib/insights-view";
|
|
11
|
+
import { cn } from "@/lib/utils";
|
|
12
|
+
|
|
13
|
+
import { InsightsErrorAlert } from "./InsightsErrorAlert";
|
|
14
|
+
import { InsightsPagination } from "./InsightsPagination";
|
|
15
|
+
|
|
16
|
+
const getLastKnownBundleId = (event: InsightsInstallationViewRow) =>
|
|
17
|
+
event.lastKnownBundleId;
|
|
18
|
+
|
|
19
|
+
const getUserLabel = (event: InsightsInstallationViewRow) =>
|
|
20
|
+
event.userId ?? event.username ?? "—";
|
|
21
|
+
|
|
22
|
+
export function InstallationMatchesCard({
|
|
23
|
+
error,
|
|
24
|
+
onNext,
|
|
25
|
+
onPrevious,
|
|
26
|
+
onSelect,
|
|
27
|
+
pageNumber,
|
|
28
|
+
results,
|
|
29
|
+
selectedInstallId,
|
|
30
|
+
}: {
|
|
31
|
+
readonly error: unknown;
|
|
32
|
+
readonly onNext: () => void;
|
|
33
|
+
readonly onPrevious: () => void;
|
|
34
|
+
readonly onSelect: (installId: string) => void;
|
|
35
|
+
readonly pageNumber: number;
|
|
36
|
+
readonly results: InsightsViewPage<InsightsInstallationViewRow> | undefined;
|
|
37
|
+
readonly selectedInstallId: string | undefined;
|
|
38
|
+
}) {
|
|
39
|
+
const [expanded, setExpanded] = useState(false);
|
|
40
|
+
const contentId = useId();
|
|
41
|
+
const triggerRef = useRef<HTMLButtonElement>(null);
|
|
42
|
+
const canCollapse = !error && results && results.data.length > 0;
|
|
43
|
+
|
|
44
|
+
return (
|
|
45
|
+
<Card className="min-h-0 min-w-0 shadow-sm">
|
|
46
|
+
<CardHeader className="p-4 sm:px-6">
|
|
47
|
+
<div className="flex items-center justify-between gap-3">
|
|
48
|
+
<div className="flex min-w-0 flex-col gap-1.5">
|
|
49
|
+
<CardTitle className="text-sm font-medium">
|
|
50
|
+
<h2>Matching installations</h2>
|
|
51
|
+
</CardTitle>
|
|
52
|
+
</div>
|
|
53
|
+
<div className="flex shrink-0 items-center gap-2">
|
|
54
|
+
{canCollapse ? (
|
|
55
|
+
<Button
|
|
56
|
+
aria-controls={contentId}
|
|
57
|
+
aria-expanded={expanded}
|
|
58
|
+
aria-label={
|
|
59
|
+
expanded
|
|
60
|
+
? "Hide matching installations"
|
|
61
|
+
: "Show matching installations"
|
|
62
|
+
}
|
|
63
|
+
className="size-11 lg:hidden"
|
|
64
|
+
onClick={() => setExpanded(!expanded)}
|
|
65
|
+
ref={triggerRef}
|
|
66
|
+
size="icon-lg"
|
|
67
|
+
variant="ghost"
|
|
68
|
+
>
|
|
69
|
+
<ChevronDown
|
|
70
|
+
aria-hidden="true"
|
|
71
|
+
className={cn(expanded && "rotate-180")}
|
|
72
|
+
/>
|
|
73
|
+
</Button>
|
|
74
|
+
) : null}
|
|
75
|
+
</div>
|
|
76
|
+
</div>
|
|
77
|
+
</CardHeader>
|
|
78
|
+
<CardContent
|
|
79
|
+
className={cn(
|
|
80
|
+
"min-h-0 p-0",
|
|
81
|
+
canCollapse && !expanded && "hidden lg:block",
|
|
82
|
+
)}
|
|
83
|
+
id={contentId}
|
|
84
|
+
>
|
|
85
|
+
{error ? (
|
|
86
|
+
<div className="p-6">
|
|
87
|
+
<InsightsErrorAlert
|
|
88
|
+
error={error instanceof Error ? error : new Error()}
|
|
89
|
+
fallbackTitle="Installation search unavailable"
|
|
90
|
+
/>
|
|
91
|
+
</div>
|
|
92
|
+
) : results && results.data.length > 0 ? (
|
|
93
|
+
<ul aria-label="Matching installations" className="divide-y">
|
|
94
|
+
{results.data.map((event) => {
|
|
95
|
+
const currentBundleId = getLastKnownBundleId(event);
|
|
96
|
+
const isSelected = event.installId === selectedInstallId;
|
|
97
|
+
return (
|
|
98
|
+
<li key={event.installId}>
|
|
99
|
+
<button
|
|
100
|
+
aria-label={`${getUserLabel(event)}, install ID ${event.installId}`}
|
|
101
|
+
aria-pressed={isSelected}
|
|
102
|
+
className="group flex w-full min-w-0 flex-col gap-2 border-l-2 border-transparent px-4 py-4 text-left outline-none transition-colors hover:bg-muted/40 focus-visible:border-ring focus-visible:bg-muted/40 focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-ring/30 aria-pressed:border-primary aria-pressed:bg-muted/60 motion-reduce:transition-none sm:px-6"
|
|
103
|
+
onClick={() => {
|
|
104
|
+
onSelect(event.installId);
|
|
105
|
+
setExpanded(false);
|
|
106
|
+
triggerRef.current?.focus();
|
|
107
|
+
}}
|
|
108
|
+
type="button"
|
|
109
|
+
>
|
|
110
|
+
<span className="flex w-full min-w-0 items-center justify-between gap-3">
|
|
111
|
+
<span className="min-w-0 truncate text-sm font-medium">
|
|
112
|
+
{getUserLabel(event)}
|
|
113
|
+
</span>
|
|
114
|
+
{isSelected ? (
|
|
115
|
+
<span className="flex shrink-0 items-center gap-1 text-xs font-medium text-primary">
|
|
116
|
+
<Check aria-hidden="true" className="size-3.5" />
|
|
117
|
+
<span className="sr-only">Selected</span>
|
|
118
|
+
</span>
|
|
119
|
+
) : null}
|
|
120
|
+
</span>
|
|
121
|
+
<span className="flex flex-wrap items-center gap-2">
|
|
122
|
+
<span
|
|
123
|
+
className="font-mono text-xs"
|
|
124
|
+
title={event.installId}
|
|
125
|
+
>
|
|
126
|
+
{shortenIdentifier(event.installId)}
|
|
127
|
+
</span>
|
|
128
|
+
</span>
|
|
129
|
+
<span className="flex min-w-0 flex-wrap items-center gap-2">
|
|
130
|
+
<span className="text-xs text-muted-foreground">
|
|
131
|
+
Bundle
|
|
132
|
+
</span>
|
|
133
|
+
{currentBundleId ? (
|
|
134
|
+
<span
|
|
135
|
+
className="font-mono text-xs"
|
|
136
|
+
title={currentBundleId}
|
|
137
|
+
>
|
|
138
|
+
{shortenIdentifier(currentBundleId)}
|
|
139
|
+
</span>
|
|
140
|
+
) : (
|
|
141
|
+
<span className="text-sm text-muted-foreground">—</span>
|
|
142
|
+
)}
|
|
143
|
+
</span>
|
|
144
|
+
</button>
|
|
145
|
+
</li>
|
|
146
|
+
);
|
|
147
|
+
})}
|
|
148
|
+
</ul>
|
|
149
|
+
) : (
|
|
150
|
+
<div className="flex flex-wrap items-center justify-between gap-3 p-4 sm:px-6">
|
|
151
|
+
<p className="text-sm text-muted-foreground">No matches</p>
|
|
152
|
+
<a
|
|
153
|
+
className={buttonVariants({
|
|
154
|
+
variant: "outline",
|
|
155
|
+
className: "h-11 px-3 lg:h-8",
|
|
156
|
+
})}
|
|
157
|
+
href="#installation-history-search"
|
|
158
|
+
>
|
|
159
|
+
Edit search
|
|
160
|
+
</a>
|
|
161
|
+
</div>
|
|
162
|
+
)}
|
|
163
|
+
{results &&
|
|
164
|
+
(results.data.length > 0 || pageNumber > 1 || results.nextCursor) ? (
|
|
165
|
+
<InsightsPagination
|
|
166
|
+
hasPrevious={pageNumber > 1}
|
|
167
|
+
label="Installation results"
|
|
168
|
+
nextCursor={results.nextCursor}
|
|
169
|
+
onNext={onNext}
|
|
170
|
+
onPrevious={onPrevious}
|
|
171
|
+
pageLength={results.data.length}
|
|
172
|
+
pageNumber={pageNumber}
|
|
173
|
+
/>
|
|
174
|
+
) : null}
|
|
175
|
+
</CardContent>
|
|
176
|
+
</Card>
|
|
177
|
+
);
|
|
178
|
+
}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { Search, X } from "lucide-react";
|
|
2
|
+
|
|
3
|
+
import { Button } from "@/components/ui/button";
|
|
4
|
+
import { Field, FieldLabel } from "@/components/ui/field";
|
|
5
|
+
import {
|
|
6
|
+
InputGroup,
|
|
7
|
+
InputGroupAddon,
|
|
8
|
+
InputGroupButton,
|
|
9
|
+
InputGroupInput,
|
|
10
|
+
} from "@/components/ui/input-group";
|
|
11
|
+
import { Skeleton } from "@/components/ui/skeleton";
|
|
12
|
+
|
|
13
|
+
export function InstallationSearchPanel({
|
|
14
|
+
draftQuery,
|
|
15
|
+
onDraftQueryChange,
|
|
16
|
+
onSubmit,
|
|
17
|
+
onClear,
|
|
18
|
+
}: {
|
|
19
|
+
readonly draftQuery: string;
|
|
20
|
+
readonly onDraftQueryChange: (value: string) => void;
|
|
21
|
+
readonly onSubmit: () => void;
|
|
22
|
+
readonly onClear: () => void;
|
|
23
|
+
}) {
|
|
24
|
+
return (
|
|
25
|
+
<form
|
|
26
|
+
aria-label="Find installation"
|
|
27
|
+
onSubmit={(event) => {
|
|
28
|
+
event.preventDefault();
|
|
29
|
+
if (draftQuery.trim()) onSubmit();
|
|
30
|
+
}}
|
|
31
|
+
role="search"
|
|
32
|
+
>
|
|
33
|
+
<Field className="gap-2">
|
|
34
|
+
<FieldLabel className="sr-only" htmlFor="installation-history-search">
|
|
35
|
+
User ID or installation ID
|
|
36
|
+
</FieldLabel>
|
|
37
|
+
<div className="flex flex-wrap gap-2">
|
|
38
|
+
<InputGroup className="h-11 w-auto min-w-0 flex-1 basis-44 lg:h-8">
|
|
39
|
+
<InputGroupAddon>
|
|
40
|
+
<Search aria-hidden="true" />
|
|
41
|
+
</InputGroupAddon>
|
|
42
|
+
<InputGroupInput
|
|
43
|
+
autoComplete="off"
|
|
44
|
+
className="h-11 text-base md:text-base lg:h-8 lg:text-xs"
|
|
45
|
+
id="installation-history-search"
|
|
46
|
+
maxLength={1024}
|
|
47
|
+
name="installation"
|
|
48
|
+
onChange={(event) => onDraftQueryChange(event.target.value)}
|
|
49
|
+
placeholder="User ID or installation ID"
|
|
50
|
+
spellCheck={false}
|
|
51
|
+
type="search"
|
|
52
|
+
value={draftQuery}
|
|
53
|
+
/>
|
|
54
|
+
{draftQuery.length > 0 ? (
|
|
55
|
+
<InputGroupAddon align="inline-end">
|
|
56
|
+
<InputGroupButton
|
|
57
|
+
aria-label="Clear installation lookup"
|
|
58
|
+
className="size-11 lg:size-5"
|
|
59
|
+
onClick={onClear}
|
|
60
|
+
size="icon-xs"
|
|
61
|
+
>
|
|
62
|
+
<X aria-hidden="true" />
|
|
63
|
+
</InputGroupButton>
|
|
64
|
+
</InputGroupAddon>
|
|
65
|
+
) : null}
|
|
66
|
+
</InputGroup>
|
|
67
|
+
<Button
|
|
68
|
+
aria-label="Find installation"
|
|
69
|
+
className="h-11 px-3 lg:h-8"
|
|
70
|
+
disabled={draftQuery.trim().length === 0}
|
|
71
|
+
size="lg"
|
|
72
|
+
type="submit"
|
|
73
|
+
variant="outline"
|
|
74
|
+
>
|
|
75
|
+
Find
|
|
76
|
+
</Button>
|
|
77
|
+
</div>
|
|
78
|
+
</Field>
|
|
79
|
+
</form>
|
|
80
|
+
);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export function InstallationResultsSkeleton() {
|
|
84
|
+
return (
|
|
85
|
+
<div className="grid items-stretch gap-6 lg:min-h-96 lg:grid-cols-[minmax(18rem,20rem)_minmax(0,1fr)]">
|
|
86
|
+
<Skeleton className="h-64 w-full lg:h-full" />
|
|
87
|
+
<Skeleton className="h-64 w-full lg:h-full" />
|
|
88
|
+
</div>
|
|
89
|
+
);
|
|
90
|
+
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import {
|
|
2
|
+
getPatchBaseBundleId,
|
|
2
3
|
INVALID_COHORT_ERROR_MESSAGE,
|
|
3
4
|
isValidCohort,
|
|
4
5
|
normalizeCohortValue,
|
|
@@ -14,7 +15,6 @@ import { toast } from "sonner";
|
|
|
14
15
|
import { normalizeRange } from "verkit";
|
|
15
16
|
|
|
16
17
|
import { BundleIdDisplay } from "@/components/BundleIdDisplay";
|
|
17
|
-
import { BundleAnalyticsSummary } from "@/components/features/bundles/BundleAnalyticsSummary";
|
|
18
18
|
import { BundleMetadata } from "@/components/features/bundles/BundleMetadata";
|
|
19
19
|
import { RolloutCohortsDialog } from "@/components/features/bundles/RolloutCohortsDialog";
|
|
20
20
|
import { PlatformIcon } from "@/components/PlatformIcon";
|
|
@@ -215,6 +215,7 @@ export function ReleaseEditorSheet({
|
|
|
215
215
|
const release = releaseQuery.data;
|
|
216
216
|
const bundleQuery = useBundleQuery(release?.bundle_id ?? "");
|
|
217
217
|
const bundle = bundleQuery.data;
|
|
218
|
+
const patchBaseBundleId = bundle ? getPatchBaseBundleId(bundle) : null;
|
|
218
219
|
const diagnostics = useReleaseCatalogDiagnosticsQuery(
|
|
219
220
|
release?.scope_key ?? "",
|
|
220
221
|
);
|
|
@@ -295,6 +296,7 @@ export function ReleaseEditorSheet({
|
|
|
295
296
|
await preflight.mutateAsync(input);
|
|
296
297
|
await update.mutateAsync(input);
|
|
297
298
|
toast.success("Bundle settings saved");
|
|
299
|
+
onOpenChange(false);
|
|
298
300
|
} catch (caught) {
|
|
299
301
|
setError(
|
|
300
302
|
caught instanceof Error
|
|
@@ -357,21 +359,18 @@ export function ReleaseEditorSheet({
|
|
|
357
359
|
</div>
|
|
358
360
|
</div>
|
|
359
361
|
<div className="flex flex-wrap items-start gap-2">
|
|
360
|
-
<span className="font-medium text-muted-foreground">
|
|
361
|
-
Bundle
|
|
362
|
-
</span>
|
|
362
|
+
<span className="font-medium text-muted-foreground">ID</span>
|
|
363
363
|
<span className="min-w-0 basis-full sm:basis-auto">
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
) : (
|
|
364
|
+
<BundleIdDisplay
|
|
365
|
+
bundleId={release.id}
|
|
366
|
+
fullOnMobile
|
|
367
|
+
maxLength={18}
|
|
368
|
+
/>
|
|
369
|
+
{!release.bundle_id ? (
|
|
371
370
|
<span className="text-xs text-foreground">
|
|
372
371
|
Built-in app
|
|
373
372
|
</span>
|
|
374
|
-
)}
|
|
373
|
+
) : null}
|
|
375
374
|
</span>
|
|
376
375
|
</div>
|
|
377
376
|
<div className="flex flex-wrap items-center gap-2">
|
|
@@ -409,10 +408,6 @@ export function ReleaseEditorSheet({
|
|
|
409
408
|
|
|
410
409
|
{release && draft ? (
|
|
411
410
|
<div className="flex flex-col gap-6 px-4 pb-4 sm:px-6 sm:pb-6">
|
|
412
|
-
{release.bundle_id ? (
|
|
413
|
-
<BundleAnalyticsSummary bundleId={release.bundle_id} />
|
|
414
|
-
) : null}
|
|
415
|
-
|
|
416
411
|
<section
|
|
417
412
|
aria-labelledby="delivery-settings-heading"
|
|
418
413
|
className="flex flex-col gap-4"
|
|
@@ -478,7 +473,7 @@ export function ReleaseEditorSheet({
|
|
|
478
473
|
</div>
|
|
479
474
|
<FieldDescription>
|
|
480
475
|
Disabling rolls devices back to the previous enabled
|
|
481
|
-
|
|
476
|
+
bundle on their next check, or to the built-in app when
|
|
482
477
|
none remains.
|
|
483
478
|
</FieldDescription>
|
|
484
479
|
</Field>
|
|
@@ -655,9 +650,9 @@ export function ReleaseEditorSheet({
|
|
|
655
650
|
</summary>
|
|
656
651
|
<dl className="mt-4 grid gap-3 text-muted-foreground sm:grid-cols-2">
|
|
657
652
|
<div className="sm:col-span-2">
|
|
658
|
-
<dt>
|
|
653
|
+
<dt>Artifact ID</dt>
|
|
659
654
|
<dd className="mt-1 break-all font-mono text-foreground">
|
|
660
|
-
{release.
|
|
655
|
+
{release.bundle_id ?? "Built-in app"}
|
|
661
656
|
</dd>
|
|
662
657
|
</div>
|
|
663
658
|
<div>
|
|
@@ -666,6 +661,14 @@ export function ReleaseEditorSheet({
|
|
|
666
661
|
{release.revision}
|
|
667
662
|
</dd>
|
|
668
663
|
</div>
|
|
664
|
+
{patchBaseBundleId ? (
|
|
665
|
+
<div className="sm:col-span-2">
|
|
666
|
+
<dt>Patch base artifact ID</dt>
|
|
667
|
+
<dd className="mt-1 break-all font-mono text-foreground">
|
|
668
|
+
{patchBaseBundleId}
|
|
669
|
+
</dd>
|
|
670
|
+
</div>
|
|
671
|
+
) : null}
|
|
669
672
|
<div>
|
|
670
673
|
<dt>Catalog generation</dt>
|
|
671
674
|
<dd className="mt-1 font-mono text-foreground">
|
|
@@ -730,8 +733,8 @@ export function ReleaseEditorSheet({
|
|
|
730
733
|
Remove this Bundle from {channelName ?? "the channel"}?
|
|
731
734
|
</AlertDialogTitle>
|
|
732
735
|
<AlertDialogDescription>
|
|
733
|
-
The
|
|
734
|
-
channel.
|
|
736
|
+
The uploaded artifact stays available. This only removes the
|
|
737
|
+
Bundle from the channel.
|
|
735
738
|
</AlertDialogDescription>
|
|
736
739
|
</AlertDialogHeader>
|
|
737
740
|
<AlertDialogFooter>
|
|
@@ -850,9 +853,6 @@ export function ReleaseEditorSheet({
|
|
|
850
853
|
isCopyPromotion
|
|
851
854
|
? `Bundle copied to ${normalizedTargetChannel}`
|
|
852
855
|
: `Bundle moved to ${normalizedTargetChannel}`,
|
|
853
|
-
release.bundle_id
|
|
854
|
-
? { description: `bundleId: ${release.bundle_id}` }
|
|
855
|
-
: undefined,
|
|
856
856
|
);
|
|
857
857
|
} catch (caught) {
|
|
858
858
|
toast.error(
|