Add Docker and GitHub release update tracker widgets
ci/woodpecker/push/woodpecker Pipeline was successful

This commit is contained in:
2026-05-16 17:00:07 +02:00
parent c1e75f2b19
commit 627b238dcc
7 changed files with 364 additions and 1 deletions
@@ -0,0 +1,74 @@
import { useEffect, useState } from 'react'
interface ContainerInfo {
name: string
image: string
tag: string
upToDate: boolean | null
registry: string
}
export function DockerUpdatesWidget() {
const [containers, setContainers] = useState<ContainerInfo[]>([])
const [error, setError] = useState<string | null>(null)
const [loading, setLoading] = useState(true)
useEffect(() => {
fetch('/api/updates/docker')
.then(r => r.json())
.then(d => {
if (d.error) setError(d.error)
else setContainers(d.containers)
})
.catch(() => setError('Failed to connect'))
.finally(() => setLoading(false))
}, [])
const outdated = containers.filter(c => c.upToDate === false).length
const unknown = containers.filter(c => c.upToDate === null).length
return (
<div className="card">
<div className="widget-header">
<div className="widget-title"><span className="dot" />Docker</div>
{!loading && !error && (
<span className="widget-badge" style={outdated > 0 ? { background: 'rgba(248,113,113,0.15)', color: 'var(--red)' } : {}}>
{outdated > 0 ? `${outdated} outdated` : 'all current'}
</span>
)}
</div>
{loading && <div className="widget-loading">Checking images</div>}
{error && <div className="widget-error"> {error}</div>}
{!loading && !error && (
<div className="progress-group">
{containers.map(c => (
<div key={c.name} className="list-item">
<div className="list-item-left">
<span>{c.name}</span>
<span style={{ fontFamily: 'JetBrains Mono, monospace', fontSize: 10, color: 'var(--muted)' }}>
{c.image}:{c.tag}
</span>
</div>
{c.registry !== 'docker.io' ? (
<span className="pill pill-blue">ext</span>
) : c.upToDate === true ? (
<span className="pill pill-green"></span>
) : c.upToDate === false ? (
<span className="pill pill-red"> update</span>
) : (
<span className="pill" style={{ background: 'var(--surface2)', color: 'var(--muted)' }}>?</span>
)}
</div>
))}
{unknown > 0 && (
<div style={{ fontFamily: 'JetBrains Mono, monospace', fontSize: 10, color: 'var(--muted)', marginTop: 6 }}>
{unknown} non-Docker Hub image{unknown > 1 ? 's' : ''} not checked
</div>
)}
</div>
)}
</div>
)
}