feat: Sites feature backend
This commit is contained in:
1 parent
45fcbd890d
commit
a11338094e
98 files changed
+5365
-214
No files matched your search
@@ -126,6 +126,12 @@ const ARTICLE_LIST_QUERY: ApiField[] = [
|
||||
required: false,
|
||||
rule: 'field:direction, with field title, status, created_at or updated_at and direction asc or desc. Default updated_at:desc.',
|
||||
},
|
||||
{
|
||||
name: 'site',
|
||||
type: 'string',
|
||||
required: false,
|
||||
rule: 'The key of a site. Only its articles are listed. An unknown key answers an empty page.',
|
||||
},
|
||||
]
|
||||
|
||||
const MEDIA_QUERY: ApiField[] = [
|
||||
@@ -168,6 +174,7 @@ const article = (overrides: Record<string, unknown> = {}) => ({
|
||||
body: 'A bathroom renovation is priced by room size, plumbing changes and finish level.',
|
||||
body_format: 'markdown',
|
||||
is_online: true,
|
||||
site_id: 1,
|
||||
created_at: '2026-03-12T09:14:00Z',
|
||||
updated_at: '2026-09-10T07:00:00Z',
|
||||
...overrides,
|
||||
@@ -189,6 +196,19 @@ const mediaItem = (overrides: Record<string, unknown> = {}) => ({
|
||||
...overrides,
|
||||
})
|
||||
|
||||
const site = (overrides: Record<string, unknown> = {}) => ({
|
||||
id: 1,
|
||||
name: 'Renew blog',
|
||||
key: 'renew-blog',
|
||||
base_url: 'https://blog.renew.example',
|
||||
default_social_image_id: 4,
|
||||
default_robots: 'index',
|
||||
locale: 'en',
|
||||
is_default: true,
|
||||
article_count: 30,
|
||||
...overrides,
|
||||
})
|
||||
|
||||
const me = {
|
||||
id: 1,
|
||||
username: 'marta',
|
||||
@@ -374,9 +394,15 @@ export const API_GROUPS: ApiGroup[] = [
|
||||
'art-update',
|
||||
'PATCH',
|
||||
'/v1/article/{id}',
|
||||
'Update the body of an article.',
|
||||
'Update the body of an article, or move it to another site. Send body, site_id or both.',
|
||||
'Verified user',
|
||||
verified(articleErrors(e(400, BODY_MISMATCH), ...articleIdErrors)),
|
||||
verified(
|
||||
articleErrors(
|
||||
e(400, BODY_MISMATCH),
|
||||
...articleIdErrors,
|
||||
e(404, 'site_not_found'),
|
||||
),
|
||||
),
|
||||
json(article({ body: 'Updated text.', is_online: false })),
|
||||
{
|
||||
query: [FORMAT_QUERY],
|
||||
@@ -385,11 +411,17 @@ export const API_GROUPS: ApiGroup[] = [
|
||||
{
|
||||
name: 'body',
|
||||
type: 'string',
|
||||
required: true,
|
||||
rule: 'Up to 10 000 characters.',
|
||||
required: false,
|
||||
rule: 'Up to 10 000 characters. An empty string empties the body; null is refused.',
|
||||
},
|
||||
{
|
||||
name: 'site_id',
|
||||
type: 'number',
|
||||
required: false,
|
||||
rule: 'The id of an existing site, 1 or more. null is refused. At least one of body and site_id is required.',
|
||||
},
|
||||
],
|
||||
bodySample: { body: 'Updated text.' },
|
||||
bodySample: { body: 'Updated text.', site_id: 2 },
|
||||
},
|
||||
),
|
||||
endpoint(
|
||||
@@ -523,7 +555,7 @@ export const API_GROUPS: ApiGroup[] = [
|
||||
e(401, UNAUTHORIZED),
|
||||
e(409, 'Some of the images to merge changed. Refresh and try again.'),
|
||||
]),
|
||||
json({ articles_updated: 5, merged: 2 }),
|
||||
json({ articles_updated: 5, sites_updated: 1, merged: 2 }),
|
||||
{
|
||||
bodyKind: 'json',
|
||||
body: [
|
||||
@@ -629,6 +661,7 @@ export const API_GROUPS: ApiGroup[] = [
|
||||
groups_purged: 1,
|
||||
merged: 2,
|
||||
articles_updated: 5,
|
||||
sites_updated: 1,
|
||||
failed_groups: 0,
|
||||
}),
|
||||
{
|
||||
@@ -784,6 +817,36 @@ export const API_GROUPS: ApiGroup[] = [
|
||||
),
|
||||
],
|
||||
},
|
||||
{
|
||||
key: 'sites',
|
||||
title: 'Sites',
|
||||
description:
|
||||
'The sites an article can belong to. Any verified user can read them; changes are made in the browser by the owner.',
|
||||
endpoints: [
|
||||
endpoint(
|
||||
'site-list',
|
||||
'GET',
|
||||
'/v1/site/',
|
||||
'List the sites, the default first and then by name, each with its article count.',
|
||||
'Verified user',
|
||||
verified([e(401, UNAUTHORIZED)]),
|
||||
json([
|
||||
site(),
|
||||
site({
|
||||
id: 2,
|
||||
name: 'Renew shop',
|
||||
key: 'renew-shop',
|
||||
base_url: 'https://shop.renew.example',
|
||||
default_social_image_id: null,
|
||||
default_robots: 'noindex',
|
||||
locale: null,
|
||||
is_default: false,
|
||||
article_count: 4,
|
||||
}),
|
||||
]),
|
||||
),
|
||||
],
|
||||
},
|
||||
]
|
||||
|
||||
const row = (
|
||||
@@ -819,6 +882,15 @@ export const SESSION_GROUPS: SessionGroup[] = [
|
||||
row('POST', '/v1/auth/password-reset', 'Reset password', false),
|
||||
],
|
||||
},
|
||||
{
|
||||
title: 'Sites · owner only',
|
||||
rows: [
|
||||
row('POST', '/v1/site/', 'Create a site'),
|
||||
row('PATCH', '/v1/site/{id}', 'Edit a site'),
|
||||
row('PATCH', '/v1/site/{id}/default', 'Make a site the default'),
|
||||
row('DELETE', '/v1/site/{id}', 'Delete a site, moving its articles with reassign_to'),
|
||||
],
|
||||
},
|
||||
{
|
||||
title: 'Settings · owner only',
|
||||
rows: [row('PATCH', '/v1/settings', 'Change the activity log retention')],
|
||||
|
||||
Reference in new issue
Block a user