a gallery is a carousel
It always rendered as one — data-carousel, a snap track, two arrows, driven by carousel.client.js. The entity was the last thing still calling it something else, and that collided with the site's own Gallery section: two nav rows reading Gallery and Galleries, meaning a list of objects and a list of photograph sets. GalleriesPanel, GalleryPicker and GalleryItems become Carousels*, the endpoint becomes /fofos-admin/carousels, the block kind becomes carousel and subject-gallery becomes subject-carousel. The publish allowlist follows the renamed tables. What did NOT move: GALLERY_CONFIG at /fofos-admin/gallery, subjects.ts's base '/gallery', and home_gallery_media. Those are the Gallery section and the legacy rows, and both are correct. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -19,7 +19,7 @@ import { paintMeasure, paintSelection, type CanvasComponent, type CanvasSection
|
||||
const LABELS: Record<string, string> = {
|
||||
'free-text': 'Text',
|
||||
media: 'Media',
|
||||
gallery: 'Gallery',
|
||||
carousel: 'Carousel',
|
||||
'contact-form': 'Contact form',
|
||||
partners: 'Partners',
|
||||
collections: 'Collections',
|
||||
@@ -28,7 +28,7 @@ const LABELS: Record<string, string> = {
|
||||
'subject-title': 'Name',
|
||||
'subject-description': 'Description',
|
||||
'subject-specs': 'Specs',
|
||||
'subject-gallery': 'Photographs',
|
||||
'subject-carousel': 'Photographs',
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -47,14 +47,14 @@ const PLACES_ONLY: string[] = [
|
||||
'subject-title',
|
||||
'subject-description',
|
||||
'subject-specs',
|
||||
'subject-gallery',
|
||||
'subject-carousel',
|
||||
];
|
||||
import { AddSectionDialog, type SectionLayout } from './AddSectionDialog';
|
||||
import { FreeTextEditor } from './FreeTextEditor';
|
||||
import { SpacingEditor, type Padding } from './SpacingEditor';
|
||||
import { BandSettings } from './BandSettings';
|
||||
import { BlockSettings } from './BlockSettings';
|
||||
import { GalleryItems } from './GalleryItems';
|
||||
import { CarouselItems } from './CarouselItems';
|
||||
import { PartnersEditor } from './PartnersEditor';
|
||||
import { BlockMedia } from './BlockMedia';
|
||||
import { PageStructure } from './PageStructure';
|
||||
@@ -89,7 +89,7 @@ const shapeOf = (block: { content?: { url?: string; ratio?: number } }): string
|
||||
import { useEditorSlot } from '../useEditorSlot';
|
||||
import { AddComponentDialog, type ComponentKind } from './AddComponentDialog';
|
||||
import { MediaPicker } from '../MediaPicker';
|
||||
import { GalleryPicker } from '../GalleryPicker';
|
||||
import { CarouselPicker } from '../CarouselPicker';
|
||||
import { pageFromParam, pageParam, usePages, useSections, type Page } from '../usePages';
|
||||
|
||||
/**
|
||||
@@ -165,14 +165,14 @@ export const PageBuilderPanel = () => {
|
||||
Which gallery a block shows, while it is being chosen.
|
||||
|
||||
The same shape as `picking` and for the same reason: choosing a set is one act with one outcome, so
|
||||
there is nothing to draft and nothing to cancel out of afterwards. `galleryId` rides along so
|
||||
there is nothing to draft and nothing to cancel out of afterwards. `carouselId` rides along so
|
||||
reopening the picker can show where the block already stands.
|
||||
*/
|
||||
const [choosingGallery, setChoosingGallery] = useState<{
|
||||
const [choosingCarousel, setChoosingCarousel] = useState<{
|
||||
id: number | null;
|
||||
sectionId: number;
|
||||
column: number;
|
||||
galleryId: number | null;
|
||||
carouselId: number | null;
|
||||
} | null>(null);
|
||||
|
||||
const [editing, setEditing] = useState<{ id: number | null; sectionId: number; column: number; html: string } | null>(
|
||||
@@ -248,7 +248,7 @@ export const PageBuilderPanel = () => {
|
||||
/*
|
||||
Selecting a block shows its settings. It does not open a picker.
|
||||
|
||||
`editComponent` means "edit what is IN this block", and for media and galleries that is a modal
|
||||
`editComponent` means "edit what is IN this block", and for media and carousels that is a modal
|
||||
over the whole screen. Firing it on mere selection meant clicking a row in the nav threw a dialog
|
||||
at you before you had said you wanted one — those kinds get a button in the settings instead.
|
||||
|
||||
@@ -463,7 +463,7 @@ export const PageBuilderPanel = () => {
|
||||
// Each kind opens its own editor. A kind with no case here cannot be created, which is the point.
|
||||
if (kind === 'free-text') setEditing({ id: null, ...at, html: '' });
|
||||
if (kind === 'media') setPicking({ id: null, ...at });
|
||||
if (kind === 'gallery') setChoosingGallery({ id: null, ...at, galleryId: null });
|
||||
if (kind === 'carousel') setChoosingCarousel({ id: null, ...at, carouselId: null });
|
||||
if (PLACES_ONLY.includes(kind)) void createEmpty(kind, at);
|
||||
};
|
||||
|
||||
@@ -494,23 +494,23 @@ export const PageBuilderPanel = () => {
|
||||
};
|
||||
|
||||
/*
|
||||
A gallery block is a REFERENCE, saved as soon as the set is chosen — see GalleryPicker.
|
||||
A gallery block is a REFERENCE, saved as soon as the set is chosen — see CarouselPicker.
|
||||
|
||||
Identical in shape to saveVideo because it is the same interaction: pick one thing, store one
|
||||
value. The two are left as two functions rather than one generic saver, because what they store
|
||||
happens to be one field each today and a shared helper would be an abstraction over a coincidence.
|
||||
*/
|
||||
const saveGallery = async (galleryId: number) => {
|
||||
if (!page || !choosingGallery) return;
|
||||
const base = `/fofos-admin/pages/${page.id}/sections/${choosingGallery.sectionId}/components`;
|
||||
const target = choosingGallery;
|
||||
setChoosingGallery(null);
|
||||
const saveCarousel = async (carouselId: number) => {
|
||||
if (!page || !choosingCarousel) return;
|
||||
const base = `/fofos-admin/pages/${page.id}/sections/${choosingCarousel.sectionId}/components`;
|
||||
const target = choosingCarousel;
|
||||
setChoosingCarousel(null);
|
||||
setError(null);
|
||||
try {
|
||||
if (target.id === null) {
|
||||
await clientRef.current.post(base, { kind: 'gallery', column: target.column, content: { galleryId } });
|
||||
await clientRef.current.post(base, { kind: 'carousel', column: target.column, content: { carouselId } });
|
||||
} else {
|
||||
await clientRef.current.patch(`${base}/${target.id}`, { content: { galleryId } });
|
||||
await clientRef.current.patch(`${base}/${target.id}`, { content: { carouselId } });
|
||||
}
|
||||
setRendered((n) => n + 1);
|
||||
} catch (failure) {
|
||||
@@ -590,12 +590,12 @@ export const PageBuilderPanel = () => {
|
||||
}
|
||||
|
||||
if (component.kind === 'gallery') {
|
||||
const held = owner.components.find((one) => one.id === component.id)?.content?.galleryId;
|
||||
setChoosingGallery({
|
||||
const held = owner.components.find((one) => one.id === component.id)?.content?.carouselId;
|
||||
setChoosingCarousel({
|
||||
id: component.id,
|
||||
sectionId: owner.id,
|
||||
column: component.column,
|
||||
galleryId: typeof held === 'number' ? held : null,
|
||||
carouselId: typeof held === 'number' ? held : null,
|
||||
});
|
||||
return;
|
||||
}
|
||||
@@ -805,14 +805,14 @@ export const PageBuilderPanel = () => {
|
||||
</Button>
|
||||
|
||||
{/*
|
||||
The gallery's own contents, here rather than a link to the Galleries section.
|
||||
The gallery's own contents, here rather than a link to the Carousels section.
|
||||
|
||||
A gallery block on a page IS a gallery, and being sent elsewhere to reorder it means
|
||||
losing the page you were arranging it for. `onChanged` reloads the frame, because the
|
||||
page draws this set and has just been given a different one.
|
||||
*/}
|
||||
{typeof block.content?.galleryId === 'number' && (
|
||||
<GalleryItems galleryId={block.content.galleryId} onChanged={() => setRendered((n) => n + 1)} />
|
||||
{typeof block.content?.carouselId === 'number' && (
|
||||
<CarouselItems carouselId={block.content.carouselId} onChanged={() => setRendered((n) => n + 1)} />
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
@@ -1050,11 +1050,11 @@ export const PageBuilderPanel = () => {
|
||||
title="Choose a photograph or a video"
|
||||
/>
|
||||
|
||||
<GalleryPicker
|
||||
open={choosingGallery !== null}
|
||||
onClose={() => setChoosingGallery(null)}
|
||||
onPick={(galleryId) => void saveGallery(galleryId)}
|
||||
selected={choosingGallery?.galleryId ?? null}
|
||||
<CarouselPicker
|
||||
open={choosingCarousel !== null}
|
||||
onClose={() => setChoosingCarousel(null)}
|
||||
onPick={(carouselId) => void saveCarousel(carouselId)}
|
||||
selected={choosingCarousel?.carouselId ?? null}
|
||||
/>
|
||||
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user