Add governed GRB refresh workflow
This commit is contained in:
@@ -1,4 +1,7 @@
|
||||
import type {
|
||||
GrbRefreshLayerPlan,
|
||||
GrbRefreshLayerStatus,
|
||||
GrbRefreshPlan,
|
||||
SourceCatalogComparisonStatus,
|
||||
SourceCatalogProbeItem,
|
||||
SourceCatalogProbeReport,
|
||||
@@ -17,6 +20,9 @@ interface SourceFreshnessPanelProps {
|
||||
catalogLoading: boolean
|
||||
catalogError: string | null
|
||||
onProbeCatalogs: (force: boolean) => void
|
||||
grbRefreshPlan: GrbRefreshPlan | null
|
||||
grbRefreshPlanLoading: boolean
|
||||
grbRefreshPlanError: string | null
|
||||
}
|
||||
|
||||
function statusLabel(status: SourceFreshnessStatus): string {
|
||||
@@ -46,6 +52,35 @@ function formatDate(value?: string | null): string {
|
||||
return new Intl.DateTimeFormat('nl-BE', { dateStyle: 'medium' }).format(new Date(value))
|
||||
}
|
||||
|
||||
function formatCount(value?: number | null): string {
|
||||
return value == null ? 'nog niet bekend' : value.toLocaleString('nl-BE')
|
||||
}
|
||||
|
||||
function grbLayerStatusLabel(status: GrbRefreshLayerStatus): string {
|
||||
if (status === 'current') return 'actueel'
|
||||
if (status === 'update_available') return 'update beschikbaar'
|
||||
if (status === 'not_loaded') return 'nog niet ingeladen'
|
||||
if (status === 'remote_unavailable') return 'bron niet bereikbaar'
|
||||
return 'beoordeling nodig'
|
||||
}
|
||||
|
||||
function GrbRefreshLayerRow({ item, remoteEdition }: { item: GrbRefreshLayerPlan; remoteEdition?: string | null }): JSX.Element {
|
||||
return (
|
||||
<div className={`grb-refresh-layer grb-refresh-layer-${item.status}`}>
|
||||
<div>
|
||||
<strong>{item.display_name}</strong>
|
||||
<span>{grbLayerStatusLabel(item.status)}</span>
|
||||
</div>
|
||||
<p>{item.action_message}</p>
|
||||
<div className="source-freshness-meta">
|
||||
<span>Lokaal: {item.local_source_version ?? 'niet aanwezig'}</span>
|
||||
<span>Officieel: {remoteEdition ?? 'onbekend'}</span>
|
||||
<span>{formatCount(item.local_feature_count)} objecten lokaal</span>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
function integrityIssueCount(item: SourceFreshnessItem): number {
|
||||
return Object.values(item.integrity).reduce((total, value) => total + value, 0)
|
||||
}
|
||||
@@ -102,6 +137,9 @@ export function SourceFreshnessPanel({
|
||||
catalogLoading,
|
||||
catalogError,
|
||||
onProbeCatalogs,
|
||||
grbRefreshPlan,
|
||||
grbRefreshPlanLoading,
|
||||
grbRefreshPlanError,
|
||||
}: SourceFreshnessPanelProps): JSX.Element {
|
||||
const attentionItems = report?.items.filter((item) => item.status === 'due' || item.status === 'review_required') ?? []
|
||||
const summary = report?.summary
|
||||
@@ -180,6 +218,27 @@ export function SourceFreshnessPanel({
|
||||
</p>
|
||||
</>
|
||||
) : null}
|
||||
{grbRefreshPlanLoading ? <p className="source-catalog-empty">Veilig vernieuwingsplan wordt opgebouwd...</p> : null}
|
||||
{grbRefreshPlanError ? <p className="inline-error">{grbRefreshPlanError}</p> : null}
|
||||
{grbRefreshPlan ? (
|
||||
<div className="grb-refresh-plan">
|
||||
<div className="grb-refresh-plan-heading">
|
||||
<div>
|
||||
<strong>Veilige GRB-vernieuwing</strong>
|
||||
<span>{grbRefreshPlan.message}</span>
|
||||
</div>
|
||||
<span>{grbRefreshPlan.summary.update_available_count} updates</span>
|
||||
</div>
|
||||
<div className="grb-refresh-layer-list">
|
||||
{grbRefreshPlan.layers.map((item) => (
|
||||
<GrbRefreshLayerRow item={item} remoteEdition={grbRefreshPlan.remote_edition_date} key={item.theme} />
|
||||
))}
|
||||
</div>
|
||||
<p className="source-freshness-limitation">
|
||||
Een serveroperator controleert eerst exacte aantallen en checksums. Bestaande snapshots blijven altijd behouden.
|
||||
</p>
|
||||
</div>
|
||||
) : null}
|
||||
</div>
|
||||
</>
|
||||
) : null}
|
||||
|
||||
Reference in New Issue
Block a user