feat: entry list at /content/:key
This commit is contained in:
1 parent
b4cbcb0395
commit
91d916fb74
44 files changed
+4984
-32
No files matched your search
@@ -646,6 +646,9 @@ const boardGroupLabels: Record<string, Record<string, string>> = {
|
||||
'Review and delete': '3 Review and delete',
|
||||
'Field types': '4 Field types',
|
||||
},
|
||||
content: {
|
||||
'Content and entry list': '5 Content and entry list',
|
||||
},
|
||||
}
|
||||
|
||||
const referenceGroups: Record<string, string> = {
|
||||
|
||||
@@ -6988,9 +6988,248 @@ const schemaStates: Record<string, VisualState> = {
|
||||
},
|
||||
}
|
||||
|
||||
const contentRows = [
|
||||
[
|
||||
42,
|
||||
'Lime plaster workshop',
|
||||
'2026-11-21',
|
||||
'2026-11-22',
|
||||
false,
|
||||
18,
|
||||
'Workshop',
|
||||
'Two days of hands-on work with lime putty and old stone.',
|
||||
'2026-10-12',
|
||||
'2026-10-15',
|
||||
3,
|
||||
],
|
||||
[
|
||||
41,
|
||||
'Heat pumps: what the numbers say',
|
||||
'2026-11-03',
|
||||
'',
|
||||
true,
|
||||
500,
|
||||
'Talk',
|
||||
'A look at running costs after two winters.',
|
||||
'2026-10-08',
|
||||
'2026-10-14',
|
||||
5,
|
||||
],
|
||||
[
|
||||
40,
|
||||
'Open day at the Rue Verte site',
|
||||
'2026-11-12',
|
||||
'2026-11-12',
|
||||
false,
|
||||
120,
|
||||
'Meetup',
|
||||
'',
|
||||
'2026-10-02',
|
||||
'2026-10-12',
|
||||
4,
|
||||
],
|
||||
[
|
||||
39,
|
||||
'Winter windows clinic',
|
||||
'2026-12-05',
|
||||
'',
|
||||
false,
|
||||
null,
|
||||
'Workshop',
|
||||
'Bring a window, leave with a plan.',
|
||||
'2026-09-30',
|
||||
'2026-10-09',
|
||||
3,
|
||||
],
|
||||
[
|
||||
38,
|
||||
'Timber joinery for beginners',
|
||||
'2027-01-14',
|
||||
'2027-01-15',
|
||||
false,
|
||||
12,
|
||||
'Workshop',
|
||||
'Mortise, tenon and a lot of patience.',
|
||||
'2026-09-28',
|
||||
'2026-10-07',
|
||||
4,
|
||||
],
|
||||
[
|
||||
37,
|
||||
'Q&A with the site managers',
|
||||
'2026-10-28',
|
||||
'',
|
||||
true,
|
||||
null,
|
||||
'Meetup',
|
||||
'',
|
||||
'2026-09-21',
|
||||
'2026-10-02',
|
||||
5,
|
||||
],
|
||||
[
|
||||
36,
|
||||
'Reclaimed floorboards talk',
|
||||
'2026-10-17',
|
||||
'',
|
||||
false,
|
||||
60,
|
||||
'Talk',
|
||||
'Where to find them and how to lay them.',
|
||||
'2026-09-14',
|
||||
'2026-09-29',
|
||||
3,
|
||||
],
|
||||
].map(
|
||||
([
|
||||
id,
|
||||
title,
|
||||
startsOn,
|
||||
endsOn,
|
||||
online,
|
||||
capacity,
|
||||
category,
|
||||
description,
|
||||
created,
|
||||
updated,
|
||||
by,
|
||||
]) => ({
|
||||
id,
|
||||
content_type_id: 1,
|
||||
data: {
|
||||
title,
|
||||
starts_on: startsOn,
|
||||
ends_on: endsOn,
|
||||
online,
|
||||
capacity,
|
||||
category,
|
||||
description,
|
||||
},
|
||||
created_by: by,
|
||||
updated_by: by,
|
||||
created_at: `${created}T09:14:00Z`,
|
||||
updated_at: `${updated}T11:02:00Z`,
|
||||
}),
|
||||
)
|
||||
|
||||
const contentTypeNames = [
|
||||
'Events',
|
||||
'Recipes',
|
||||
'Press mentions',
|
||||
'Frequently asked questions and answers',
|
||||
'Job openings',
|
||||
'Testimonials',
|
||||
'Suppliers',
|
||||
'Certifications',
|
||||
'Case studies',
|
||||
'Glossary terms',
|
||||
'Partners',
|
||||
'Downloads',
|
||||
'Locations',
|
||||
'Awards',
|
||||
]
|
||||
|
||||
const contentManyTypes = contentTypeNames.map((name, index) => ({
|
||||
id: index + 1,
|
||||
key: name === 'Events' ? 'events' : name.toLowerCase().replace(/[^a-z0-9]+/g, '-'),
|
||||
name,
|
||||
icon: 'files',
|
||||
fields: index === 0 ? schemaEventsFields : [],
|
||||
created_at: '2026-09-01T09:30:00Z',
|
||||
updated_at: '2026-10-15T09:30:00Z',
|
||||
}))
|
||||
|
||||
const contentUsers = [
|
||||
{ id: 3, display_name: 'Marta Alves' },
|
||||
{ id: 4, display_name: 'Inès Duarte' },
|
||||
{ id: 5, display_name: 'Jonas Pereira' },
|
||||
]
|
||||
|
||||
const contentEventsType = schemaCustomTypes[0]!
|
||||
|
||||
function contentEntries(url: URL) {
|
||||
const size = Number(url.searchParams.get('size'))
|
||||
if (size === 5) {
|
||||
return {
|
||||
items: contentRows.slice(0, 5),
|
||||
total: 37,
|
||||
page: 1,
|
||||
size: 5,
|
||||
sort: 'updated_at:desc',
|
||||
}
|
||||
}
|
||||
return { items: contentRows, total: 7, page: 1, size: 25, sort: 'updated_at:desc' }
|
||||
}
|
||||
|
||||
function contentApi(overrides: Record<string, ApiMock> = {}): Record<string, ApiMock> {
|
||||
return {
|
||||
'GET /v1/auth/me': schemaSession('owner'),
|
||||
'GET /v1/content-type': { status: 200, body: schemaCustomTypes },
|
||||
'GET /v1/content-type/events': { status: 200, body: contentEventsType },
|
||||
'GET /v1/content-type/events/entry': { status: 200, bodyFor: contentEntries },
|
||||
'GET /v1/user/lookup': { status: 200, body: contentUsers },
|
||||
...overrides,
|
||||
}
|
||||
}
|
||||
|
||||
const contentStates: Record<string, VisualState> = {
|
||||
Populated: { path: '/content/events', api: contentApi() },
|
||||
'Paginated, 5 per page': { path: '/content/events?size=5', api: contentApi() },
|
||||
'Columns menu': {
|
||||
path: '/content/events',
|
||||
api: contentApi(),
|
||||
steps: async (page) => {
|
||||
await page.getByRole('button', { name: 'Columns' }).click()
|
||||
await page.getByText('Created and updated dates always show').waitFor()
|
||||
await schemaSettle(page)
|
||||
},
|
||||
},
|
||||
'Many types in the sidebar': {
|
||||
path: '/content/events',
|
||||
api: contentApi({ 'GET /v1/content-type': { status: 200, body: contentManyTypes } }),
|
||||
steps: async (page) => {
|
||||
if (schemaIsMobile(page)) {
|
||||
await page.locator('[data-slot="toggle"]').first().click()
|
||||
await page.getByRole('button', { name: 'All content types' }).click()
|
||||
await page.getByText('Frequently asked questions and answers').first().waitFor()
|
||||
}
|
||||
await schemaSettle(page)
|
||||
},
|
||||
},
|
||||
Loading: {
|
||||
path: '/content/events',
|
||||
api: contentApi({ 'GET /v1/content-type/events/entry': { status: 200, hang: true } }),
|
||||
},
|
||||
'Empty for this type': {
|
||||
path: '/content/events',
|
||||
api: contentApi({
|
||||
'GET /v1/content-type/events/entry': {
|
||||
status: 200,
|
||||
body: { items: [], total: 0, page: 1, size: 25, sort: 'updated_at:desc' },
|
||||
},
|
||||
}),
|
||||
},
|
||||
Error: {
|
||||
path: '/content/events',
|
||||
api: contentApi({ 'GET /v1/content-type/events/entry': { status: 500 } }),
|
||||
},
|
||||
'Forbidden (403)': {
|
||||
path: '/content/events',
|
||||
api: contentApi({ 'GET /v1/content-type/events/entry': { status: 403 } }),
|
||||
},
|
||||
'Type not found': {
|
||||
path: '/content/unknown',
|
||||
api: contentApi({
|
||||
'GET /v1/content-type/unknown': { status: 404, body: 'content_type_not_found' },
|
||||
'GET /v1/content-type/unknown/entry': { status: 404, body: 'content_type_not_found' },
|
||||
}),
|
||||
},
|
||||
}
|
||||
|
||||
export const visualStates: Record<string, Record<string, VisualState>> = {
|
||||
sites: sitesStates,
|
||||
schema: schemaStates,
|
||||
content: contentStates,
|
||||
authors: authorsStates,
|
||||
activity: activityStates,
|
||||
profile: {
|
||||
|
||||
Reference in new issue
Block a user