Skip to content

Commit

Permalink
Improve UX of scheduling update
Browse files Browse the repository at this point in the history
Improve the UX of scheduling the update of an image's data:

- Add hover, active and disable styles to the button
- Add a spinner animation for when the request is in-flight
- Add a warning if the request fails
- Add another string shown when the request was successful

Solves: #69
  • Loading branch information
AlexGustafsson committed Jan 14, 2025
1 parent 8c39822 commit 3b5db0e
Show file tree
Hide file tree
Showing 2 changed files with 69 additions and 31 deletions.
23 changes: 11 additions & 12 deletions web/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -328,19 +328,18 @@ export function usePagination<T extends { pagination: PaginationMetadata }>(
return pages
}

export function useScheduleScan(): (reference: string) => Promise<void> {
return async (reference: string) => {
const query = new URLSearchParams({ reference })
const res = await fetch(
`${import.meta.env.VITE_API_ENDPOINT}/image/scans?${query.toString()}`,
{
method: 'POST',
}
)

if (res.status !== 202) {
throw new Error(`unexpected status - ${res.status}`)
export async function scheduleScan(reference: string): Promise<void> {
const query = new URLSearchParams({ reference })
const res = await fetch(
`${import.meta.env.VITE_API_ENDPOINT}/image/scans?${query.toString()}`,
{
method: 'POST',
signal: AbortSignal.timeout(5000),
}
)

if (res.status !== 202) {
throw new Error(`unexpected status - ${res.status}`)
}
}

Expand Down
77 changes: 58 additions & 19 deletions web/pages/ImagePage.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import type { JSX, ReactNode } from 'react'
import { type JSX, type ReactNode, useCallback, useState } from 'react'
import { Link, NavLink, Navigate, useSearchParams } from 'react-router-dom'

import {
type Graph,
scheduleScan,
useImage,
useImageDescription,
useImageGraph,
useImageReleaseNotes,
useScheduleScan,
useTags,
} from '../api'
import { Badge } from '../components/Badge'
Expand Down Expand Up @@ -132,8 +132,6 @@ export function ImagePage(): JSX.Element {
const releaseNotes = useImageReleaseNotes(reference)
const graph = useImageGraph(reference)

const scheduleScan = useScheduleScan()

if (
tags.status === 'idle' ||
image.status === 'idle' ||
Expand Down Expand Up @@ -359,23 +357,64 @@ export function ImagePage(): JSX.Element {
{graph.value && <GraphCard graph={graph.value} />}

<div className="flex justify-center gap-x-2 items-center">
<p>
Last processed{' '}
<span title={new Date(image.value.lastModified).toLocaleString()}>
{formatRelativeTimeTo(new Date(image.value.lastModified))}
</span>
</p>
<button
type="button"
title="Schedule update"
onClick={() =>
image.value ? scheduleScan(image.value.reference) : undefined
}
>
<FluentArrowSync16Regular />
</button>
<ProcessStatus
reference={image.value.reference}
lastModified={image.value.lastModified}
/>
</div>
</main>
</div>
)
}

type ProcessStatusProps = {
lastModified: string
reference: string
}

function ProcessStatus({
lastModified,
reference,
}: ProcessStatusProps): JSX.Element {
const [status, setStatus] = useState<
'idle' | 'in-flight' | 'successful' | 'failed'
>('idle')

const onSchedule = useCallback(() => {
setStatus('in-flight')
scheduleScan(reference)
.then(() => setStatus('successful'))
.catch(() => setStatus('failed'))
}, [reference])

return (
<>
{status !== 'successful' && (
<p>
Last processed{' '}
<span title={new Date(lastModified).toLocaleString()}>
{formatRelativeTimeTo(new Date(lastModified))}
</span>
</p>
)}
<p>{status === 'successful' && 'Image is scheduled for processing'}</p>
<button
type="button"
title={status === 'idle' ? 'Schedule update' : ''}
onClick={onSchedule}
disabled={status !== 'idle'}
>
{(status === 'idle' || status === 'in-flight') && (
<FluentArrowSync16Regular
className={`ml-1 hover:opacity-90 active:opacity-80 disabled:opacity-70 ${status === 'in-flight' ? 'animate-spin' : ''}`}
/>
)}
{status === 'failed' && (
<InfoTooltip icon={<FluentWarning16Filled />}>
Failed to schedule image. Cupdate is likely busy. Try again later.
</InfoTooltip>
)}
</button>
</>
)
}

0 comments on commit 3b5db0e

Please sign in to comment.