@@ -5,44 +5,74 @@ import { Bars } from "../Bars";
55import { useValuePerSecond } from "../useValuePerSecond" ;
66import { bootProgressPhaseAtom } from "../../atoms" ;
77import { useAtomValue } from "jotai" ;
8- import { useEffect , useMemo } from "react" ;
8+ import { memo , useEffect , useMemo } from "react" ;
99import StorageIcon from "@material-design-icons/svg/filled/storage.svg?react" ;
1010import { compactSingleDecimalFormatter } from "../../../../numUtils" ;
11- import type { FormattedBytes } from "../../../../utils" ;
11+ import Progress from "../../../../components/Progress" ;
12+ import { formatByteValue } from "./utils" ;
13+
14+ const gap = "4px" ;
1215
1316interface SnapshotBarsCardProps {
14- headerContent : JSX . Element ;
15- footer ?: JSX . Element ;
16- throughput : number | null | undefined ;
17- containerClassName : string ;
17+ title : string ;
18+ progressPct : number | undefined ;
19+ completed : number | null | undefined ;
20+ total : number | null | undefined ;
21+ barsThroughput : number | null | undefined ;
1822 maxThroughput : number ;
23+ headerRightContent : JSX . Element ;
24+ footerText ?: string | null ;
1925}
2026export function SnapshotBarsCard ( {
21- headerContent,
22- footer,
23- throughput,
24- containerClassName,
27+ title,
28+ progressPct,
29+ completed,
30+ total,
31+ barsThroughput,
2532 maxThroughput,
33+ headerRightContent,
34+ footerText,
2635} : SnapshotBarsCardProps ) {
2736 return (
28- < Card className = { clsx ( styles . card , styles . barsCard , containerClassName ) } >
29- < Flex
30- justify = "between"
31- align = "center"
32- wrap = "wrap"
33- gapX = "4"
34- className = { styles . cardHeader }
35- >
36- { headerContent }
37+ < Card className = { clsx ( styles . card , styles . barsCard ) } >
38+ < Flex direction = "column" gap = "2px" >
39+ < ProgressBar pct = { progressPct } />
40+ < Flex
41+ justify = "between"
42+ wrap = "nowrap"
43+ gap = { gap }
44+ className = { styles . cardHeader }
45+ >
46+ < SnapshotTitle text = { title } />
47+ < Flex gap = { gap } minWidth = "0" className = { styles . headerRightSection } >
48+ < SnapshotTotalComplete completed = { completed } total = { total } />
49+ { headerRightContent }
50+ </ Flex >
51+ </ Flex >
3752 </ Flex >
53+ < Bars value = { barsThroughput ?? 0 } max = { maxThroughput } />
3854
39- < Bars value = { throughput ?? 0 } max = { maxThroughput } />
40-
41- { footer }
55+ < MSnapshotPath path = { footerText } />
4256 </ Card >
4357 ) ;
4458}
4559
60+ interface ProgressBarProps {
61+ pct : number | undefined ;
62+ }
63+ function ProgressBar ( { pct } : ProgressBarProps ) {
64+ const bootPhase = useAtomValue ( bootProgressPhaseAtom ) ;
65+ // jump to inital value on phase change
66+ return (
67+ < Flex key = { bootPhase } gap = "10px" align = "center" >
68+ < Progress className = { styles . progressBar } value = { pct ?? 0 } />
69+ < Text className = { clsx ( styles . secondaryColor , styles . progressPctText ) } >
70+ { pct == null ? "-" : pct . toFixed ( 0 ) } %
71+ </ Text >
72+ </ Flex >
73+ ) ;
74+ }
75+
4676function ValueUnitText ( {
4777 value,
4878 unit,
@@ -53,27 +83,26 @@ function ValueUnitText({
5383 return (
5484 < >
5585 < Text > { value ?? "--" } </ Text >
56- { unit && (
57- < >
58- { " " }
59- < Text className = { styles . secondaryColor } > { unit } </ Text >
60- </ >
61- ) }
86+ { unit && < Text className = { styles . secondaryColor } > { unit } </ Text > }
6287 </ >
6388 ) ;
6489}
6590
6691interface SnapshotTitleProps {
6792 text : string ;
6893}
69- export function SnapshotTitle ( { text } : SnapshotTitleProps ) {
70- return < Text className = { clsx ( styles . title , styles . ellipsis ) } > { text } </ Text > ;
94+ function SnapshotTitle ( { text } : SnapshotTitleProps ) {
95+ return < Text className = { clsx ( styles . leftColumn , styles . title ) } > { text } </ Text > ;
7196}
7297
7398interface AccountsRateProps {
99+ isComplete : boolean ;
74100 cumulativeAccounts ?: number | null ;
75101}
76- export function AccountsRate ( { cumulativeAccounts } : AccountsRateProps ) {
102+ export function AccountsRate ( {
103+ isComplete,
104+ cumulativeAccounts,
105+ } : AccountsRateProps ) {
77106 const phase = useAtomValue ( bootProgressPhaseAtom ) ;
78107
79108 const { valuePerSecond : accountsPerSecond , reset } = useValuePerSecond (
@@ -87,68 +116,75 @@ export function AccountsRate({ cumulativeAccounts }: AccountsRateProps) {
87116 } , [ phase , reset ] ) ;
88117
89118 const value = useMemo ( ( ) => {
119+ if ( isComplete ) return 0 ;
90120 // Possible to have no rate due to only having a single point
91121 if ( cumulativeAccounts != null && accountsPerSecond == null ) return "0" ;
92122 if ( accountsPerSecond == null ) return ;
93123 return compactSingleDecimalFormatter . format ( accountsPerSecond ) ;
94- } , [ accountsPerSecond , cumulativeAccounts ] ) ;
124+ } , [ accountsPerSecond , cumulativeAccounts , isComplete ] ) ;
95125
96126 return (
97- < div className = { styles . accountsRate } >
127+ < div className = { styles . rightColumn } >
98128 < ValueUnitText value = { value } unit = "Accounts / sec" />
99129 </ div >
100130 ) ;
101131}
102132
103133interface SnapshotTotalCompleteProps {
104- completed : FormattedBytes | undefined ;
105- total : FormattedBytes | undefined ;
134+ completed : number | null | undefined ;
135+ total : number | null | undefined ;
106136}
107- export function SnapshotTotalComplete ( {
137+ function SnapshotTotalComplete ( {
108138 completed,
109139 total,
110140} : SnapshotTotalCompleteProps ) {
141+ const completedObj = formatByteValue ( completed ) ;
142+ const totalObj = formatByteValue ( total ) ;
143+
111144 return (
112- < div className = { styles . total } >
113- < ValueUnitText value = { completed ?. value } unit = { completed ?. unit } />
145+ < Flex className = { styles . centerColumn } >
146+ < ValueUnitText value = { completedObj ?. value } unit = { completedObj ?. unit } />
114147
115148 < Text > / </ Text >
116149
117- < ValueUnitText value = { total ?. value } unit = { total ?. unit } />
118- </ div >
150+ < ValueUnitText value = { totalObj ?. value } unit = { totalObj ?. unit } />
151+ </ Flex >
119152 ) ;
120153}
121154
122155interface SnapshotThroughputProps {
123156 prefix ?: string ;
124- throughput : FormattedBytes | undefined ;
157+ throughput : number | null | undefined ;
125158}
126159export function SnapshotThroughput ( {
127160 prefix,
128161 throughput,
129162} : SnapshotThroughputProps ) {
163+ const throughputObj = formatByteValue ( throughput ) ;
164+
130165 return (
131- < div className = { clsx ( styles . throughput , { [ styles . withPrefix ] : ! ! prefix } ) } >
166+ < div className = { styles . rightColumn } >
132167 { prefix && < Text className = { styles . secondaryColor } > { prefix } </ Text > }
133- < ValueUnitText value = { throughput ?. value } unit = { throughput ?. unit } />
168+ < ValueUnitText value = { throughputObj ?. value } unit = { throughputObj ?. unit } />
134169 < Text className = { styles . secondaryColor } > /sec</ Text >
135170 </ div >
136171 ) ;
137172}
138173
139- interface SnapshotReadPathProps {
140- readPath ?: string | null ;
174+ interface SnapshotPathProps {
175+ path ?: string | null ;
141176}
142- export function SnapshotReadPath ( { readPath } : SnapshotReadPathProps ) {
177+ const MSnapshotPath = memo ( function SnapshotPath ( { path } : SnapshotPathProps ) {
178+ if ( ! path ) return ;
143179 return (
144180 < Flex
145181 align = "center"
146182 gap = "10px"
147183 wrap = "nowrap"
148- className = { styles . readPathContainer }
184+ className = { styles . pathContainer }
149185 >
150186 < StorageIcon />
151- < Text className = { clsx ( styles . readPath , styles . ellipsis ) } > { readPath } </ Text >
187+ < Text className = { clsx ( styles . path , styles . ellipsis ) } > { path } </ Text >
152188 </ Flex >
153189 ) ;
154- }
190+ } ) ;
0 commit comments