- config_form.yaml preview block (optional headerPartial), reported in the form schema as preview
- fields with context: preview show only on the preview screen and are never written
- form messages preview and edit; recordActions without a preview block stops boot
- SPA route {id}/preview, PreviewView and PreviewField, record actions in the footer
- mapWinterUrl maps preview/:id; the update form returns to the preview
- summer-callout partial style classes for status hints
- README, docs, OpenAPI document, TS types and the embedded build updated
45 lines
1.9 KiB
TypeScript
45 lines
1.9 KiB
TypeScript
// Winter-shaped URLs (config_list recordUrl, config_form redirects) mapped
|
|
// onto the SPA's D-10 routes. The strings come from plugin YAML, so they are
|
|
// never used verbatim: only the current controller's list, create, record
|
|
// and preview routes can come out (research Gap 8, T-10-20, T-12.1-16).
|
|
//
|
|
// <vendor>/<plugin>/<controller> -> list
|
|
// <vendor>/<plugin>/<controller>/create -> create
|
|
// <vendor>/<plugin>/<controller>/update/:id -> record (:id substituted)
|
|
// <vendor>/<plugin>/<controller>/preview/:id -> preview (:id substituted)
|
|
// anything else, or another controller -> list
|
|
import { controllerPath, parseControllerId } from './controllerRoutes'
|
|
|
|
const DIGITS = /^\d+$/
|
|
|
|
export function mapWinterUrl(url: string | null | undefined, controllerId: string, id?: string | number | null): string {
|
|
const params = parseControllerId(controllerId)
|
|
const base = controllerPath(controllerId)
|
|
if (!params || !base) {
|
|
return '/'
|
|
}
|
|
const raw = (url ?? '').trim().split(/[?#]/, 1)[0] ?? ''
|
|
const segments = raw.split('/').filter((segment) => segment !== '')
|
|
const owner = [params.vendor, params.plugin, params.controller]
|
|
const ownsUrl = owner.every((segment, index) => segments[index]?.toLowerCase() === segment.toLowerCase())
|
|
if (!ownsUrl) {
|
|
return base
|
|
}
|
|
const rest = segments.slice(owner.length)
|
|
if (rest.length === 0) {
|
|
return base
|
|
}
|
|
if (rest.length === 1 && rest[0] === 'create') {
|
|
return `${base}/create`
|
|
}
|
|
if (rest.length === 2 && rest[0] === 'update') {
|
|
const target = rest[1] === ':id' ? String(id ?? '') : (rest[1] ?? '')
|
|
return DIGITS.test(target) ? `${base}/${target}` : base
|
|
}
|
|
if (rest.length === 2 && rest[0] === 'preview') {
|
|
const target = rest[1] === ':id' ? String(id ?? '') : (rest[1] ?? '')
|
|
return DIGITS.test(target) ? `${base}/${target}/preview` : base
|
|
}
|
|
return base
|
|
}
|