Collabs, as a third configuration of one panel
The same object as a collection and a gallery piece, so it is a config in subjects.ts and a one-line panel — no new screen. Two differences, both deliberate. It has no SPECS: a collab is a project rather than an object, so there is no measurement or raw material and the form is a name, an address and a description. And its title column is `project_name`, which is the client's word and stays — the site's API publishes both that and `title` so this panel reads one field like every other section, and the translation lives in one router rather than as a branch in every screen. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -6,6 +6,7 @@ import { sectionFor, sectionOpen, type SectionKey } from './sections';
|
|||||||
import { AdministrationPanel } from './AdministrationPanel';
|
import { AdministrationPanel } from './AdministrationPanel';
|
||||||
import { MediaPanel } from './MediaPanel';
|
import { MediaPanel } from './MediaPanel';
|
||||||
import { CollectionsPanel } from './sections/CollectionsPanel';
|
import { CollectionsPanel } from './sections/CollectionsPanel';
|
||||||
|
import { CollabsPanel } from './sections/CollabsPanel';
|
||||||
import { PiecesPanel } from './sections/PiecesPanel';
|
import { PiecesPanel } from './sections/PiecesPanel';
|
||||||
import { CarouselsPanel } from './sections/CarouselsPanel';
|
import { CarouselsPanel } from './sections/CarouselsPanel';
|
||||||
import { LayoutPanel } from './sections/LayoutPanel';
|
import { LayoutPanel } from './sections/LayoutPanel';
|
||||||
@@ -50,6 +51,7 @@ const PANELS: Partial<Record<SectionKey, () => React.JSX.Element>> = {
|
|||||||
layout: LayoutPanel,
|
layout: LayoutPanel,
|
||||||
collections: CollectionsPanel,
|
collections: CollectionsPanel,
|
||||||
pieces: PiecesPanel,
|
pieces: PiecesPanel,
|
||||||
|
collabs: CollabsPanel,
|
||||||
carousels: CarouselsPanel,
|
carousels: CarouselsPanel,
|
||||||
messages: MessagesPanel,
|
messages: MessagesPanel,
|
||||||
administration: AdministrationPanel,
|
administration: AdministrationPanel,
|
||||||
|
|||||||
+19
-1
@@ -1,5 +1,5 @@
|
|||||||
import type { LucideIcon } from 'lucide-react';
|
import type { LucideIcon } from 'lucide-react';
|
||||||
import { Boxes, Cog, Files, FolderOpen, GalleryHorizontal, Images, Mail, PanelsTopLeft, Shapes } from 'lucide-react';
|
import { Boxes, Cog, Files, FolderOpen, GalleryHorizontal, Handshake, Images, Mail, PanelsTopLeft, Shapes } from 'lucide-react';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The sections of the fofos admin, in nav order.
|
* The sections of the fofos admin, in nav order.
|
||||||
@@ -38,6 +38,7 @@ import { Boxes, Cog, Files, FolderOpen, GalleryHorizontal, Images, Mail, PanelsT
|
|||||||
|
|
||||||
export type SectionKey =
|
export type SectionKey =
|
||||||
| 'administration'
|
| 'administration'
|
||||||
|
| 'collabs'
|
||||||
| 'collections'
|
| 'collections'
|
||||||
| 'pieces'
|
| 'pieces'
|
||||||
| 'carousels'
|
| 'carousels'
|
||||||
@@ -171,6 +172,23 @@ export const SECTIONS: Section[] = [
|
|||||||
requires: 'connection',
|
requires: 'connection',
|
||||||
pinned: true,
|
pinned: true,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
Collaborations — the third section drawn through a template, and the flattest of the three.
|
||||||
|
|
||||||
|
Below Pieces because that is the order the sitemap puts them in, and it shares their panel: a
|
||||||
|
collab is the same object with the client's own word for its title and no specs.
|
||||||
|
*/
|
||||||
|
key: 'collabs',
|
||||||
|
label: 'Collabs',
|
||||||
|
icon: Handshake,
|
||||||
|
hint: 'Projects made with somebody else',
|
||||||
|
path: '/fofos-admin/collabs',
|
||||||
|
built: true,
|
||||||
|
// A collab is a ROW read through the site's admin API, like Collections and Pieces above it.
|
||||||
|
requires: 'connection',
|
||||||
|
pinned: true,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
key: 'carousels',
|
key: 'carousels',
|
||||||
label: 'Carousels',
|
label: 'Carousels',
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ export type ComponentKind =
|
|||||||
| 'partners'
|
| 'partners'
|
||||||
| 'collections'
|
| 'collections'
|
||||||
| 'pieces'
|
| 'pieces'
|
||||||
|
| 'collabs'
|
||||||
| 'subject-cover'
|
| 'subject-cover'
|
||||||
| 'subject-title'
|
| 'subject-title'
|
||||||
| 'subject-description'
|
| 'subject-description'
|
||||||
@@ -93,6 +94,7 @@ export const CHOICES: Choice[] = [
|
|||||||
{ kind: 'partners', label: 'Partners', hint: 'The partner logos, from Site', Icon: Handshake },
|
{ kind: 'partners', label: 'Partners', hint: 'The partner logos, from Site', Icon: Handshake },
|
||||||
{ kind: 'collections', label: 'Collections', hint: 'Every collection, as a grid', Icon: LayoutGrid },
|
{ kind: 'collections', label: 'Collections', hint: 'Every collection, as a grid', Icon: LayoutGrid },
|
||||||
{ kind: 'pieces', label: 'Pieces', hint: 'Every gallery piece, as a grid', Icon: LayoutGrid },
|
{ kind: 'pieces', label: 'Pieces', hint: 'Every gallery piece, as a grid', Icon: LayoutGrid },
|
||||||
|
{ kind: 'collabs', label: 'Collabs', hint: 'Every collaboration, as a grid', Icon: LayoutGrid },
|
||||||
|
|
||||||
/*
|
/*
|
||||||
The five that draw whatever the page is ABOUT, on a template.
|
The five that draw whatever the page is ABOUT, on a template.
|
||||||
|
|||||||
@@ -0,0 +1,5 @@
|
|||||||
|
import { SubjectPanel } from './SubjectPanel';
|
||||||
|
import { COLLABS } from './subjects';
|
||||||
|
|
||||||
|
/** Collaborations. The panel is shared with Collections and Pieces — see subjects.ts. */
|
||||||
|
export const CollabsPanel = () => <SubjectPanel section={COLLABS} />;
|
||||||
@@ -24,6 +24,7 @@ const LABELS: Record<string, string> = {
|
|||||||
partners: 'Partners',
|
partners: 'Partners',
|
||||||
collections: 'Collections',
|
collections: 'Collections',
|
||||||
pieces: 'Pieces',
|
pieces: 'Pieces',
|
||||||
|
collabs: 'Collabs',
|
||||||
'subject-cover': 'Lead photograph',
|
'subject-cover': 'Lead photograph',
|
||||||
'subject-title': 'Name',
|
'subject-title': 'Name',
|
||||||
'subject-description': 'Description',
|
'subject-description': 'Description',
|
||||||
@@ -42,6 +43,7 @@ const PLACES_ONLY: string[] = [
|
|||||||
'partners',
|
'partners',
|
||||||
'collections',
|
'collections',
|
||||||
'pieces',
|
'pieces',
|
||||||
|
'collabs',
|
||||||
// The subject blocks hold nothing either: what they draw is the row the URL names.
|
// The subject blocks hold nothing either: what they draw is the row the URL names.
|
||||||
'subject-cover',
|
'subject-cover',
|
||||||
'subject-title',
|
'subject-title',
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import type { LucideIcon } from 'lucide-react';
|
import type { LucideIcon } from 'lucide-react';
|
||||||
import { Boxes, Shapes } from 'lucide-react';
|
import { Boxes, Handshake, Shapes } from 'lucide-react';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The two sections whose rows are drawn through a template — collections, and gallery pieces.
|
* The two sections whose rows are drawn through a template — collections, and gallery pieces.
|
||||||
@@ -42,6 +42,16 @@ export type Collection = SubjectRecord & {
|
|||||||
delivery_time: string | null;
|
delivery_time: string | null;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type Collab = SubjectRecord & {
|
||||||
|
/**
|
||||||
|
* The client's word for the title, carried alongside `title`.
|
||||||
|
*
|
||||||
|
* The column really is `project_name` — see the site's collabs schema — and the wire publishes both
|
||||||
|
* so this panel can go on reading `title` like every other section. Writes accept either.
|
||||||
|
*/
|
||||||
|
project_name: string;
|
||||||
|
};
|
||||||
|
|
||||||
export type Piece = SubjectRecord & {
|
export type Piece = SubjectRecord & {
|
||||||
descriptive_text: string | null;
|
descriptive_text: string | null;
|
||||||
measurement: string | null;
|
measurement: string | null;
|
||||||
@@ -85,6 +95,22 @@ export const COLLECTIONS: SubjectSection<Collection> = {
|
|||||||
long: ['descriptive_text'],
|
long: ['descriptive_text'],
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const COLLABS: SubjectSection<Collab> = {
|
||||||
|
param: 'collab',
|
||||||
|
endpoint: '/fofos-admin/collabs',
|
||||||
|
base: '/collabs',
|
||||||
|
icon: Handshake,
|
||||||
|
noun: 'collab',
|
||||||
|
/*
|
||||||
|
No specs, and that is the difference.
|
||||||
|
|
||||||
|
A collab is a PROJECT rather than an object — there is no measurement, no raw material, no
|
||||||
|
colours to list. The form is a name, an address and a description, which is all the sitemap gives
|
||||||
|
it, and the template carries no specs block to draw.
|
||||||
|
*/
|
||||||
|
specs: [],
|
||||||
|
};
|
||||||
|
|
||||||
export const PIECES: SubjectSection<Piece> = {
|
export const PIECES: SubjectSection<Piece> = {
|
||||||
param: 'piece',
|
param: 'piece',
|
||||||
endpoint: '/fofos-admin/pieces',
|
endpoint: '/fofos-admin/pieces',
|
||||||
|
|||||||
Reference in New Issue
Block a user