diff --git a/web/NavPanel.tsx b/web/NavPanel.tsx index 2babaa2..528a0c7 100644 --- a/web/NavPanel.tsx +++ b/web/NavPanel.tsx @@ -6,6 +6,7 @@ import { SECTIONS, sectionOpen } from './sections'; import { href, useNav } from './routes'; import { useReady } from './useReady'; import { pageParam, usePages, type Page } from './usePages'; +import { useFofosChanged } from './channel'; /** * The left column: which part of the fofos site the detail panel is showing. @@ -91,11 +92,15 @@ export const NavPanel = () => { The write happens once, at the end: `PUT /pages/order` takes the whole set, because an order is a property of the SET and sending one row's new index leaves the server guessing about everyone else. */ + const [, bump] = useFofosChanged(); const [dragged, setDragged] = useState(null); const orderedRef = useRef(null); const moveOver = (event: React.DragEvent, overId: number) => { if (dragged === null || !pages) return; + // Home is first and stays first — see the note on its missing grip. Refusing the drop here is what + // stops anything being dragged ABOVE it, which no amount of hiding the handle would prevent. + if (pages.find((page) => page.id === overId)?.is_home) return; // Without this the drop is refused and the browser animates the row back to where it started. event.preventDefault(); if (dragged === overId) return; @@ -119,6 +124,8 @@ export const NavPanel = () => { void clientRef.current .put('/fofos-admin/pages/order', { ids: ordered.map((page) => page.id) }) + // The menu is the site's, so every preview on the screen is now showing the old one. + .then(() => bump()) // The list is already showing the new order; a failure has to put the old one back, and the // server is the only thing that knows what that was. .catch(() => void clientRef.current.get<{ data: Page[] }>('/fofos-admin/pages').then((body) => announce(body.data))); @@ -210,6 +217,16 @@ export const NavPanel = () => { current ? 'bg-muted' : 'hover:bg-muted/50' } ${dragged === page.id ? 'opacity-40' : ''}`} > + {/* + Home has no grip. + + It is the site's front door and its address is `/`; a menu that opens somewhere else + is not a menu with a different order, it is a different site. The space is kept so the + titles still line up — an unindented Home would read as a heading rather than a row. + */} + {page.is_home ? ( + + ) : ( { @@ -224,6 +241,7 @@ export const NavPanel = () => { > + )} { setLoaded(0); - }, [reloadToken]); + }, [reloadToken, changed]); useEffect(() => { if (!loaded) return; @@ -334,7 +347,7 @@ export const SitePreview = ({