milestone 18: collapse duplicated infrastructure into shared listener core, crud list helper, resource shells, transport race, name and line helpers, ui modules
This commit is contained in:
@@ -4,6 +4,7 @@ import { groupSourcesPutMutation, groupSourcesQuery } from "@/lib/queries";
|
||||
import type { Blocklist } from "@/lib/types";
|
||||
import { sameSet, toggleSource } from "./sourceSet";
|
||||
import InlineError from "@/lib/InlineError";
|
||||
import { buttonClass, focusRing, primaryButtonClass } from "@/ui/classes";
|
||||
|
||||
interface Props {
|
||||
groupId: number;
|
||||
@@ -46,6 +47,7 @@ export default function GroupSourcesEditor({ groupId, blocklists }: Props) {
|
||||
type="checkbox"
|
||||
checked={current.includes(blocklist.id)}
|
||||
onChange={() => setSelected(toggleSource(current, blocklist.id))}
|
||||
className={focusRing}
|
||||
/>
|
||||
{blocklist.name}
|
||||
</label>
|
||||
@@ -60,16 +62,12 @@ export default function GroupSourcesEditor({ groupId, blocklists }: Props) {
|
||||
onClick={() =>
|
||||
mutation.mutate({ id: groupId, sourceIds: current }, { onSuccess: () => setSelected(null) })
|
||||
}
|
||||
className="rounded bg-blue-600 px-3 py-1.5 text-sm font-medium text-white disabled:opacity-50 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-blue-600"
|
||||
className={primaryButtonClass}
|
||||
>
|
||||
Save sources
|
||||
</button>
|
||||
{dirty && (
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setSelected(null)}
|
||||
className="rounded border border-zinc-300 px-3 py-1.5 text-sm focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-blue-600 dark:border-zinc-700"
|
||||
>
|
||||
<button type="button" onClick={() => setSelected(null)} className={buttonClass}>
|
||||
Discard
|
||||
</button>
|
||||
)}
|
||||
|
||||
@@ -10,15 +10,12 @@ import {
|
||||
import type { Blocklist, Group } from "@/lib/types";
|
||||
import GroupSourcesEditor from "./GroupSourcesEditor";
|
||||
import InlineError from "@/lib/InlineError";
|
||||
import { focusRing, primaryButtonClass, smallButtonClass, smallInputClass } from "@/ui/classes";
|
||||
|
||||
const DEFAULT_GROUP_ID = 1;
|
||||
const DEFAULT_GROUP_NOTE = "The default group cannot be renamed or deleted.";
|
||||
|
||||
const inputClass = "rounded border border-zinc-300 bg-white px-2 py-1.5 text-sm dark:border-zinc-700 dark:bg-zinc-900";
|
||||
const buttonClass =
|
||||
"rounded border border-zinc-300 px-2 py-1 text-sm focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-blue-600 disabled:opacity-50 dark:border-zinc-700";
|
||||
const primaryButtonClass =
|
||||
"rounded bg-blue-600 px-3 py-1.5 text-sm font-medium text-white disabled:opacity-50 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-blue-600";
|
||||
const groupButtonClass = `${smallButtonClass} disabled:opacity-50`;
|
||||
|
||||
export default function GroupsPage() {
|
||||
const { data: groups } = useSuspenseQuery(groupsQuery());
|
||||
@@ -47,7 +44,7 @@ export default function GroupsPage() {
|
||||
type="text"
|
||||
value={newName}
|
||||
onChange={(event) => setNewName(event.target.value)}
|
||||
className={inputClass}
|
||||
className={smallInputClass}
|
||||
/>
|
||||
<button type="submit" disabled={createMutation.isPending} className={primaryButtonClass}>
|
||||
Create
|
||||
@@ -94,10 +91,10 @@ function GroupRow({ group, blocklists }: { group: Group; blocklists: Blocklist[]
|
||||
aria-label={`New name for ${group.name}`}
|
||||
value={name}
|
||||
onChange={(event) => setName(event.target.value)}
|
||||
className={inputClass}
|
||||
className={smallInputClass}
|
||||
autoFocus
|
||||
/>
|
||||
<button type="submit" disabled={updateMutation.isPending} className={buttonClass}>
|
||||
<button type="submit" disabled={updateMutation.isPending} className={groupButtonClass}>
|
||||
Save
|
||||
</button>
|
||||
<button
|
||||
@@ -106,7 +103,7 @@ function GroupRow({ group, blocklists }: { group: Group; blocklists: Blocklist[]
|
||||
setName(group.name);
|
||||
setRenaming(false);
|
||||
}}
|
||||
className={buttonClass}
|
||||
className={groupButtonClass}
|
||||
>
|
||||
Cancel
|
||||
</button>
|
||||
@@ -119,6 +116,7 @@ function GroupRow({ group, blocklists }: { group: Group; blocklists: Blocklist[]
|
||||
type="checkbox"
|
||||
checked={group.safe_search}
|
||||
disabled={updateMutation.isPending}
|
||||
className={focusRing}
|
||||
onChange={(event) =>
|
||||
updateMutation.mutate({
|
||||
id: group.id,
|
||||
@@ -133,7 +131,7 @@ function GroupRow({ group, blocklists }: { group: Group; blocklists: Blocklist[]
|
||||
type="button"
|
||||
aria-expanded={expanded}
|
||||
onClick={() => setExpanded((open) => !open)}
|
||||
className={buttonClass}
|
||||
className={groupButtonClass}
|
||||
>
|
||||
Sources
|
||||
</button>
|
||||
@@ -146,7 +144,7 @@ function GroupRow({ group, blocklists }: { group: Group; blocklists: Blocklist[]
|
||||
setName(group.name);
|
||||
setRenaming(true);
|
||||
}}
|
||||
className={buttonClass}
|
||||
className={groupButtonClass}
|
||||
>
|
||||
Rename
|
||||
</button>
|
||||
@@ -159,11 +157,11 @@ function GroupRow({ group, blocklists }: { group: Group; blocklists: Blocklist[]
|
||||
setConfirming(false);
|
||||
deleteMutation.mutate(group.id);
|
||||
}}
|
||||
className={`${buttonClass} text-red-700 dark:text-red-400`}
|
||||
className={`${groupButtonClass} text-red-700 dark:text-red-400`}
|
||||
>
|
||||
Confirm delete
|
||||
</button>
|
||||
<button type="button" onClick={() => setConfirming(false)} className={buttonClass}>
|
||||
<button type="button" onClick={() => setConfirming(false)} className={groupButtonClass}>
|
||||
Cancel
|
||||
</button>
|
||||
</>
|
||||
@@ -173,7 +171,7 @@ function GroupRow({ group, blocklists }: { group: Group; blocklists: Blocklist[]
|
||||
disabled={isDefault}
|
||||
title={isDefault ? DEFAULT_GROUP_NOTE : undefined}
|
||||
onClick={() => setConfirming(true)}
|
||||
className={`${buttonClass} text-red-700 dark:text-red-400`}
|
||||
className={`${groupButtonClass} text-red-700 dark:text-red-400`}
|
||||
>
|
||||
Delete
|
||||
</button>
|
||||
|
||||
Reference in New Issue
Block a user