the databases say what is in them, and the block folds away when it is done
Two databases with identical structure look identical until you count what is in them — one is the live site and one is a copy. So a row now reads "18 tables · 155 rows" with the time anything was last written, rather than only reporting that a schema exists. Counted with query_to_xml over information_schema, which is exact. reltuples from the planner would be free and is an ESTIMATE: it reads as zero on a table nobody has analysed, which is precisely the freshly restored database this is meant to reassure somebody about. That is not a hypothetical — it is why pg_stat_user_tables reported an empty database earlier today that had 155 rows in it. And the block collapses with a check once everything is in order, on the same terms as Root location: both databases existing with a schema, and backups configured. Not backups having RUN — a site set up an hour ago has taken none, and calling that incomplete is telling somebody to fix what is not broken. Seeded from /summary so the first paint is already right, then kept live by what the block and BackupsRow know. The `null` sentinel in `collapsed` is left alone while unsettled, which is the bug that stopped Root location folding at all. BackupsRow reports its bit from an EFFECT, not during render: calling the parent's setter mid-render is an update to a different component, which React refuses outright. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
+21
-1
@@ -67,7 +67,15 @@ const size = (bytes: number) =>
|
||||
|
||||
const when = (iso: string | null) => (iso ? new Date(iso).toLocaleString(undefined, { dateStyle: 'medium', timeStyle: 'short' }) : null);
|
||||
|
||||
export const BackupsRow = ({ prodName, devName }: { prodName: string; devName: string }) => {
|
||||
export const BackupsRow = ({
|
||||
prodName,
|
||||
devName,
|
||||
onSettled,
|
||||
}: {
|
||||
prodName: string;
|
||||
devName: string;
|
||||
onSettled?: (settled: boolean) => void;
|
||||
}) => {
|
||||
const client = useClient();
|
||||
const clientRef = useRef(client);
|
||||
clientRef.current = client;
|
||||
@@ -110,6 +118,18 @@ export const BackupsRow = ({ prodName, devName }: { prodName: string; devName: s
|
||||
void load();
|
||||
}, [load]);
|
||||
|
||||
/*
|
||||
One bit upward, so the block above can decide whether the whole section is finished.
|
||||
|
||||
In an effect and not during render. Calling the parent's setter while this component renders is an
|
||||
update to a DIFFERENT component mid-render, which React refuses outright — and the version of this
|
||||
that did it would have thrown on the first paint.
|
||||
*/
|
||||
const settledUp = Boolean(settings?.cron && settings?.sshHost && settings?.sshPath);
|
||||
useEffect(() => {
|
||||
onSettled?.(settledUp);
|
||||
}, [settledUp, onSettled]);
|
||||
|
||||
const save = async () => {
|
||||
setBusy('save');
|
||||
setError(null);
|
||||
|
||||
Reference in New Issue
Block a user