mirror of
https://github.com/coder/coder.git
synced 2025-07-21 01:28:49 +00:00
site: cleanup code in WorkspaceBuildProgress (#4584)
This commit is contained in:
@ -11,23 +11,19 @@ dayjs.extend(duration)
|
||||
|
||||
const estimateFinish = (
|
||||
startedAt: Dayjs,
|
||||
templateAverage?: number,
|
||||
buildEstimate: number,
|
||||
): [number, string] => {
|
||||
if (templateAverage === undefined) {
|
||||
return [0, "Unknown"]
|
||||
}
|
||||
const realPercentage = dayjs().diff(startedAt) / templateAverage
|
||||
const realPercentage = dayjs().diff(startedAt) / buildEstimate
|
||||
|
||||
// Showing a full bar is frustrating.
|
||||
const maxPercentage = 0.99
|
||||
const maxPercentage = 1
|
||||
if (realPercentage > maxPercentage) {
|
||||
return [maxPercentage, "Any moment now..."]
|
||||
return [maxPercentage * 100, "Any moment now..."]
|
||||
}
|
||||
|
||||
return [
|
||||
realPercentage,
|
||||
realPercentage * 100,
|
||||
`~${Math.ceil(
|
||||
dayjs.duration((1 - realPercentage) * templateAverage).asSeconds(),
|
||||
dayjs.duration((1 - realPercentage) * buildEstimate).asSeconds(),
|
||||
)} seconds remaining...`,
|
||||
]
|
||||
}
|
||||
@ -62,49 +58,55 @@ export const WorkspaceBuildProgress: FC<WorkspaceBuildProgressProps> = ({
|
||||
}) => {
|
||||
const styles = useStyles()
|
||||
const job = workspace.latest_build.job
|
||||
const [progressValue, setProgressValue] = useState(0)
|
||||
const [progressValue, setProgressValue] = useState<number | undefined>(0)
|
||||
|
||||
// By default workspace is updated every second, which can cause visual stutter
|
||||
// when the build estimate is a few seconds. The timer ensures no observable
|
||||
// stutter in all cases.
|
||||
useEffect(() => {
|
||||
const updateProgress = () => {
|
||||
if (job.status !== "running") {
|
||||
setProgressValue(0)
|
||||
if (job.status !== "running" || buildEstimate === undefined) {
|
||||
setProgressValue(undefined)
|
||||
return
|
||||
}
|
||||
setProgressValue(
|
||||
estimateFinish(dayjs(job.started_at), buildEstimate)[0] * 100,
|
||||
)
|
||||
const est = estimateFinish(dayjs(job.started_at), buildEstimate)[0]
|
||||
setProgressValue(est)
|
||||
}
|
||||
setTimeout(updateProgress, 100)
|
||||
setTimeout(updateProgress, 5)
|
||||
}, [progressValue, job, buildEstimate])
|
||||
|
||||
// buildEstimate may be undefined if the template is new or coderd hasn't
|
||||
// finished initial metrics collection.
|
||||
if (buildEstimate === undefined) {
|
||||
return (
|
||||
<div className={styles.stack}>
|
||||
<LinearProgress value={0} variant="indeterminate" />
|
||||
<div className={styles.barHelpers}>
|
||||
<div className={styles.label}>{`Build ${job.status}`}</div>
|
||||
<div className={styles.label}>Unknown ETA</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={styles.stack}>
|
||||
<LinearProgress
|
||||
value={(job.status === "running" && progressValue) || 0}
|
||||
variant={job.status === "running" ? "determinate" : "indeterminate"}
|
||||
value={progressValue !== undefined ? progressValue : 0}
|
||||
variant={
|
||||
// There is an initial state where progressValue may be undefined
|
||||
// (e.g. the build isn't yet running). If we flicker from the
|
||||
// indeterminate bar to the determinate bar, the vigilant user
|
||||
// perceives the bar jumping from 100% to 0%.
|
||||
progressValue !== undefined &&
|
||||
progressValue < 100 &&
|
||||
buildEstimate !== undefined
|
||||
? "determinate"
|
||||
: "indeterminate"
|
||||
}
|
||||
// If a transition is set, there is a moment on new load where the
|
||||
// bar accelerates to progressValue and then rapidly decelerates, which
|
||||
// is not indicative of true progress.
|
||||
classes={{ bar: styles.noTransition }}
|
||||
/>
|
||||
<div className={styles.barHelpers}>
|
||||
<div className={styles.label}>{`Build ${job.status}`}</div>
|
||||
<div className={styles.label}>
|
||||
{job.status === "running" &&
|
||||
estimateFinish(dayjs(job.started_at), buildEstimate)[1]}
|
||||
{(() => {
|
||||
if (job.status !== "running") {
|
||||
return ""
|
||||
} else if (buildEstimate !== undefined) {
|
||||
return estimateFinish(dayjs(job.started_at), buildEstimate)[1]
|
||||
} else {
|
||||
return "Unknown ETA"
|
||||
}
|
||||
})()}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -116,6 +118,9 @@ const useStyles = makeStyles((theme) => ({
|
||||
paddingLeft: theme.spacing(0.2),
|
||||
paddingRight: theme.spacing(0.2),
|
||||
},
|
||||
noTransition: {
|
||||
transition: "none",
|
||||
},
|
||||
barHelpers: {
|
||||
display: "flex",
|
||||
justifyContent: "space-between",
|
||||
|
Reference in New Issue
Block a user