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
This commit is contained in:
Jakub Zych
2026-10-05 00:10:48 +02:00
parent 1c99de5013
commit a65c670574
50 changed files with 1441 additions and 66 deletions

View File

@@ -1,11 +1,12 @@
// 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 and record
// routes can come out (research Gap 8, T-10-20).
// 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'
@@ -35,5 +36,9 @@ export function mapWinterUrl(url: string | null | undefined, controllerId: strin
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
}