feat: entry editor at /content/:key/new and /content/:key/:id

This commit is contained in:
Florian Sylvain committed 2026-10-21 00:12:34 +02:00
1 parent 91d916fb74
commit fba20f83c5
94 files changed
+7116 -423

No files matched your search

+77
View File
@@ -0,0 +1,77 @@
import { t } from '@/i18n'
import type { BuiltinField, ContentEntry } from '@/lib/contentTypes'
import { describeCell, plainCellText } from '@/lib/entryCells'
import { ruleMessage, type EntryRule } from '@/lib/entryMessages'
import { isBlank } from '@/lib/entryValue'
import { fieldTypeSpec } from '@/lib/fieldTypes'
export type EntryValues = Record<string, unknown>
export interface FieldIssue {
rule: EntryRule
message: string
}
export type EntryIssues = Record<string, FieldIssue>
export function initialValues(fields: BuiltinField[], stored: ContentEntry | null): EntryValues {
return Object.fromEntries(
fields.map((field) => [
field.key,
fieldTypeSpec(field.type).editor.initial(
field,
stored?.data[field.key],
stored === null,
),
]),
)
}
export function buildData(fields: BuiltinField[], values: EntryValues) {
return Object.fromEntries(
fields.map((field) => [
field.key,
fieldTypeSpec(field.type).editor.payload(field, values[field.key]),
]),
)
}
export function issueFor(field: BuiltinField, rule: EntryRule): FieldIssue {
return { rule, message: ruleMessage(rule, field) }
}
export function validateEntry(fields: BuiltinField[], values: EntryValues): EntryIssues {
const issues: EntryIssues = {}
for (const field of fields) {
const rule = fieldTypeSpec(field.type).editor.validate(field, values[field.key])
if (rule) {
issues[field.key] = issueFor(field, rule)
}
}
return issues
}
export function firstIssueKey(fields: BuiltinField[], issues: EntryIssues) {
return fields.find((field) => issues[field.key])?.key ?? null
}
export function valuesDiffer(fields: BuiltinField[], current: EntryValues, saved: EntryValues) {
return fields.some((field) => !Object.is(current[field.key], saved[field.key]))
}
export function carriesDefault(field: BuiltinField, value: unknown) {
if (isBlank(field.default)) {
return false
}
const initial = fieldTypeSpec(field.type).editor.initial(field, undefined, true)
return Object.is(initial, value)
}
export function entryTitle(fields: BuiltinField[], entry: ContentEntry | null) {
const first = fields[0]
if (!first || !entry) {
return entry ? t('Entry {0}', [entry.id]) : t('New entry')
}
const cell = describeCell(first, entry.data[first.key])
return cell.kind === 'empty' ? t('Entry {0}', [entry.id]) : plainCellText(cell)
}