Files
summercms/admin/src/app/winterUrl.ts
Jakub Zych a65c670574 feat(12.1-02): read-only preview screen with a status hint and record actions
- 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
2026-10-05 00:10:48 +02:00

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
}