milestone 20: declarative configuration for iac

This commit is contained in:
2026-08-11 23:31:40 +02:00
parent 2f29121e27
commit d76afc147a
74 changed files with 6722 additions and 1949 deletions
+12 -3
View File
@@ -22,6 +22,7 @@ import {
tdClass,
thClass,
} from "@/ui/classes";
import { READ_ONLY_HINT, useReadOnlyConfig } from "@/features/settings/authority";
export default function BlocklistsPage() {
const queryClient = useQueryClient();
@@ -36,6 +37,9 @@ export default function BlocklistsPage() {
const sources = useRefreshStatus();
const namesById = new Map(blocklists.map((b) => [b.id, b.name]));
// The refresh below re-fetches the sources the config already declares, so
// it stays live in file mode; every other control here writes config.
const readOnly = useReadOnlyConfig();
async function submitForm(input: BlocklistInput) {
if (editing === null) {
@@ -122,7 +126,8 @@ export default function BlocklistsPage() {
type="checkbox"
aria-label={`${b.name} enabled`}
checked={b.enabled}
disabled={toggle.isPending}
disabled={toggle.isPending || readOnly}
title={readOnly ? READ_ONLY_HINT : undefined}
onChange={() => toggleEnabled(b)}
className={focusRing}
/>
@@ -138,14 +143,17 @@ export default function BlocklistsPage() {
<button
type="button"
onClick={() => setEditing(b)}
className={linkButtonClass}
disabled={readOnly}
title={readOnly ? READ_ONLY_HINT : undefined}
className={`${linkButtonClass} disabled:opacity-50`}
>
Edit
</button>
<button
type="button"
onClick={() => deleteBlocklist(b)}
disabled={remove.isPending}
disabled={remove.isPending || readOnly}
title={readOnly ? READ_ONLY_HINT : undefined}
className={dangerLinkButtonClass}
>
Delete
@@ -164,6 +172,7 @@ export default function BlocklistsPage() {
key={editing?.id ?? "add"}
initial={editing ?? undefined}
busy={editing === null ? create.isPending : save.isPending}
readOnly={readOnly}
error={formError}
onSubmit={submitForm}
onCancel={editing === null ? undefined : () => setEditing(null)}