Move the console onto ReUI PRO

Install ReUI (MCP, skill, @reui registry, Tailwind v4, shadcn base-nova) and move
the shared UI onto it: Button, Tag, Check, Input/Textarea, Segmented, Alert, Panel,
Dialog, Tooltip, Menu and Select (Popover), Toast (sonner), the Table frame
(DataGrid), the Dashboard KPI strip, the shnt Ops palette, Geist and the type scale.

Design only: behaviour, texts and roles are unchanged. Tests that asserted the old
DOM were updated; the tests now format numbers in English wherever they run.
docs/reui-migration-plan.md records the plan and its decisions.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
DenozordecandClaude Sonnet 5.5 committed 2026-10-27 00:06:06 +07:00
commit f3531c64f9
680 files changed
+139836

No files matched your search

+80
View File
@@ -0,0 +1,80 @@
import { useEffect, useRef, useState } from 'react'
import { updateApp } from '../../api/apps'
import { Button } from '../../ui/Button'
import { Dialog } from '../../ui/Dialog'
import { LabeledInput } from '../../ui/Field'
import { error, type AlertState } from './Apps'
import { Notifier } from '../../ui/Notifier'
/*
A replica of `showUpdateAppModal` / `updateApp` (apps.js:211-218 and 381-423).
The name comes filled in and DISABLED (index.html:6232): updating is replacing
the zip of an app that already exists, not renaming it. Only the file is
validated here, just as in upstream.
*/
export function UpdateApp({
open,
onOpenChange,
token,
name,
onUpdated,
}: {
open: boolean
onOpenChange: (o: boolean) => void
token: string | null
name: string
onUpdated: (name: string) => void
}) {
const [alert, setAlert] = useState<AlertState | null>(null)
const [busy, setBusy] = useState(false)
const fileRef = useRef<HTMLInputElement>(null)
useEffect(() => {
if (open) {
setAlert(null)
setBusy(false)
}
}, [open])
async function update() {
const file = fileRef.current?.files?.[0]
if (!file) {
setAlert({
type: 'warning',
title: 'Missing!',
text: 'Please select an application zip file to update.',
})
return
}
setBusy(true)
const outcome = await updateApp(token, name, file)
setBusy(false)
if (outcome.kind !== 'ok') {
setAlert(error(outcome))
return
}
onUpdated(name)
}
return (
<Dialog
open={open}
onOpenChange={onOpenChange}
title="Update App"
actions={
<>
<Button variant="primary" disabled={busy} onClick={() => void update()}>
Update
</Button>
</>
}
>
<Notifier notice={alert} onClose={() => setAlert(null)} />
<LabeledInput label="App Name" value={name} disabled readOnly />
<LabeledInput label="App Zip File" type="file" ref={fileRef} />
</Dialog>
)
}