feat(10-02): backend strings, controller messages and declarative toolbar
- phrasebook ships the backend::lang admin strings (pl, en) with CLDR plural maps, loads them as namespace backend, applies pact.HasLangOverrides trees (lang/<locale>/<namespace>/<group>.yaml) after every namespace, and fails activation when a backend key cannot convert to plural forms - Translator.Forms, Bundle, Resolved and Has serve keys as CLDR form maps - Public GET /lang returns every backend::lang key for the request locale over the fallback locale, Cache-Control no-cache - config_list, config_form and config_relation accept a strict messages block; omitted keys take framework defaults, schemas serve every message as CLDR forms, and activation fails on a missing phrase key - toolbar.buttons is an ordered [create, delete] list; the Winter string form, duplicates, unknown actions and delete without showCheckboxes fail at boot, and create is dropped when the controller has no form - Form schema serves the raw Winter redirects; scaffold emits the list syntax; form and relation schema routes are typed in the admin OpenAPI
This commit is contained in:
164
admin/src/api/schema.d.ts
vendored
164
admin/src/api/schema.d.ts
vendored
@@ -204,6 +204,45 @@ export interface paths {
|
||||
patch?: never;
|
||||
trace?: never;
|
||||
};
|
||||
"/lang": {
|
||||
parameters: {
|
||||
query?: never;
|
||||
header?: never;
|
||||
path?: never;
|
||||
cookie?: never;
|
||||
};
|
||||
/**
|
||||
* Admin UI strings
|
||||
* @description Every backend::lang key as CLDR plural forms for the Accept-Language locale, over the fallback locale's keys. Public: the login screen loads it before signing in. meta.locale is the locale the bundle resolved to.
|
||||
*/
|
||||
get: {
|
||||
parameters: {
|
||||
query?: never;
|
||||
header?: never;
|
||||
path?: never;
|
||||
cookie?: never;
|
||||
};
|
||||
requestBody?: never;
|
||||
responses: {
|
||||
/** @description OK */
|
||||
200: {
|
||||
headers: {
|
||||
[name: string]: unknown;
|
||||
};
|
||||
content: {
|
||||
"application/json": components["schemas"]["cabana.Envelope-cabana_LangBundle"];
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
put?: never;
|
||||
post?: never;
|
||||
delete?: never;
|
||||
options?: never;
|
||||
head?: never;
|
||||
patch?: never;
|
||||
trace?: never;
|
||||
};
|
||||
"/navigation": {
|
||||
parameters: {
|
||||
query?: never;
|
||||
@@ -823,7 +862,7 @@ export interface paths {
|
||||
[name: string]: unknown;
|
||||
};
|
||||
content: {
|
||||
"application/json": components["schemas"]["cabana.SuccessEnvelope"];
|
||||
"application/json": components["schemas"]["cabana.Envelope-cabana_FormView"];
|
||||
};
|
||||
};
|
||||
/** @description Unauthorized */
|
||||
@@ -965,7 +1004,7 @@ export interface paths {
|
||||
[name: string]: unknown;
|
||||
};
|
||||
content: {
|
||||
"application/json": components["schemas"]["cabana.SuccessEnvelope"];
|
||||
"application/json": components["schemas"]["cabana.Envelope-cabana_RelationSchema"];
|
||||
};
|
||||
};
|
||||
/** @description Unauthorized */
|
||||
@@ -1523,10 +1562,22 @@ export interface components {
|
||||
data: components["schemas"]["cabana.AdminProfile"];
|
||||
meta: components["schemas"]["cabana.SuccessMeta"];
|
||||
};
|
||||
"cabana.Envelope-cabana_FormView": {
|
||||
data: components["schemas"]["cabana.FormView"];
|
||||
meta: components["schemas"]["cabana.SuccessMeta"];
|
||||
};
|
||||
"cabana.Envelope-cabana_LangBundle": {
|
||||
data: components["schemas"]["cabana.LangBundle"];
|
||||
meta: components["schemas"]["cabana.SuccessMeta"];
|
||||
};
|
||||
"cabana.Envelope-cabana_ListSchema": {
|
||||
data: components["schemas"]["cabana.ListSchema"];
|
||||
meta: components["schemas"]["cabana.SuccessMeta"];
|
||||
};
|
||||
"cabana.Envelope-cabana_RelationSchema": {
|
||||
data: components["schemas"]["cabana.RelationSchema"];
|
||||
meta: components["schemas"]["cabana.SuccessMeta"];
|
||||
};
|
||||
"cabana.ErrorBody": {
|
||||
code: string;
|
||||
details: {
|
||||
@@ -1537,6 +1588,34 @@ export interface components {
|
||||
"cabana.ErrorEnvelope": {
|
||||
error: components["schemas"]["cabana.ErrorBody"];
|
||||
};
|
||||
"cabana.FormField": {
|
||||
attributes?: {
|
||||
[key: string]: components["schemas"]["cabana.jsonScalar"];
|
||||
};
|
||||
comment?: string;
|
||||
context?: components["schemas"]["cabana.fieldContext"];
|
||||
default?: components["schemas"]["cabana.jsonScalar"];
|
||||
emptyOption?: string;
|
||||
label?: string;
|
||||
multiple?: boolean;
|
||||
name: string;
|
||||
nameFrom?: string;
|
||||
options?: components["schemas"]["cabana.FormOption"][];
|
||||
readOnly?: boolean;
|
||||
relation?: string;
|
||||
required?: boolean;
|
||||
size?: string;
|
||||
span?: string;
|
||||
tab?: string;
|
||||
type: string;
|
||||
};
|
||||
"cabana.FormMessages": {
|
||||
create: components["schemas"]["cabana.MessageForms"];
|
||||
deleteConfirm: components["schemas"]["cabana.MessageForms"];
|
||||
deleted: components["schemas"]["cabana.MessageForms"];
|
||||
saved: components["schemas"]["cabana.MessageForms"];
|
||||
update: components["schemas"]["cabana.MessageForms"];
|
||||
};
|
||||
"cabana.FormMeta": {
|
||||
locale: string;
|
||||
};
|
||||
@@ -1544,6 +1623,31 @@ export interface components {
|
||||
label: string;
|
||||
value: components["schemas"]["cabana.jsonScalar"];
|
||||
};
|
||||
"cabana.FormRedirect": {
|
||||
redirect: string;
|
||||
redirectClose: string;
|
||||
};
|
||||
"cabana.FormRedirects": {
|
||||
create: components["schemas"]["cabana.FormRedirect"];
|
||||
default: string;
|
||||
update: components["schemas"]["cabana.FormRedirect"];
|
||||
};
|
||||
"cabana.FormView": {
|
||||
fields: components["schemas"]["cabana.FormField"][];
|
||||
/** @description Messages is the form's copy resolved in the request locale (D-13). */
|
||||
messages: components["schemas"]["cabana.FormMessages"];
|
||||
meta: components["schemas"]["cabana.FormMeta"];
|
||||
modelClass?: string;
|
||||
name?: string;
|
||||
/**
|
||||
* @description Redirects are the raw Winter config_form.yaml targets; the SPA maps
|
||||
* them onto its routes.
|
||||
*/
|
||||
redirects: components["schemas"]["cabana.FormRedirects"];
|
||||
};
|
||||
"cabana.LangBundle": {
|
||||
[key: string]: components["schemas"]["cabana.MessageForms"];
|
||||
};
|
||||
"cabana.ListColumn": {
|
||||
key: string;
|
||||
label: string;
|
||||
@@ -1575,6 +1679,18 @@ export interface components {
|
||||
trueValue?: components["schemas"]["cabana.jsonScalar"];
|
||||
type: string;
|
||||
};
|
||||
"cabana.ListMessages": {
|
||||
create: components["schemas"]["cabana.MessageForms"];
|
||||
deleteConfirm: components["schemas"]["cabana.MessageForms"];
|
||||
deleteSelected: components["schemas"]["cabana.MessageForms"];
|
||||
deleted: components["schemas"]["cabana.MessageForms"];
|
||||
empty: components["schemas"]["cabana.MessageForms"];
|
||||
emptySearch: components["schemas"]["cabana.MessageForms"];
|
||||
emptySearchHint: components["schemas"]["cabana.MessageForms"];
|
||||
recordCount: components["schemas"]["cabana.MessageForms"];
|
||||
searchPrompt: components["schemas"]["cabana.MessageForms"];
|
||||
selected: components["schemas"]["cabana.MessageForms"];
|
||||
};
|
||||
"cabana.ListMeta": {
|
||||
last_page: number;
|
||||
page: number;
|
||||
@@ -1586,6 +1702,11 @@ export interface components {
|
||||
columns: components["schemas"]["cabana.ListColumn"][];
|
||||
defaultSort?: components["schemas"]["cabana.ListSort"];
|
||||
filters: components["schemas"]["cabana.ListFilter"][];
|
||||
/**
|
||||
* @description Messages is the list's copy (D-13). The cached schema carries each
|
||||
* phrase key as its own form; a response resolves them in its locale.
|
||||
*/
|
||||
messages: components["schemas"]["cabana.ListMessages"];
|
||||
meta?: components["schemas"]["cabana.FormMeta"];
|
||||
modelClass?: string;
|
||||
noRecordsMessage?: string;
|
||||
@@ -1606,6 +1727,9 @@ export interface components {
|
||||
column: string;
|
||||
direction: string;
|
||||
};
|
||||
"cabana.MessageForms": {
|
||||
[key: string]: string;
|
||||
};
|
||||
"cabana.NavigationEntry": {
|
||||
code: string;
|
||||
controller: string;
|
||||
@@ -1623,10 +1747,45 @@ export interface components {
|
||||
[key: string]: components["schemas"]["cabana.RelationOption"][];
|
||||
};
|
||||
};
|
||||
"cabana.RelationColumn": {
|
||||
key: string;
|
||||
label: string;
|
||||
searchable: boolean;
|
||||
sortable: boolean;
|
||||
};
|
||||
"cabana.RelationList": {
|
||||
columns: components["schemas"]["cabana.RelationColumn"][];
|
||||
};
|
||||
"cabana.RelationMessages": {
|
||||
candidateSearch: components["schemas"]["cabana.MessageForms"];
|
||||
empty: components["schemas"]["cabana.MessageForms"];
|
||||
link: components["schemas"]["cabana.MessageForms"];
|
||||
linkHint: components["schemas"]["cabana.MessageForms"];
|
||||
linked: components["schemas"]["cabana.MessageForms"];
|
||||
unlinkConfirm: components["schemas"]["cabana.MessageForms"];
|
||||
unlinkSelected: components["schemas"]["cabana.MessageForms"];
|
||||
unlinked: components["schemas"]["cabana.MessageForms"];
|
||||
};
|
||||
"cabana.RelationOption": {
|
||||
label: string;
|
||||
value: number;
|
||||
};
|
||||
"cabana.RelationPanel": {
|
||||
list: components["schemas"]["cabana.RelationList"];
|
||||
showSearch: boolean;
|
||||
toolbarButtons: string[];
|
||||
};
|
||||
"cabana.RelationSchema": {
|
||||
label: string;
|
||||
manage: components["schemas"]["cabana.RelationPanel"];
|
||||
/**
|
||||
* @description Messages is the relation manager's copy (D-13); the cached schema
|
||||
* carries each phrase key as its own form.
|
||||
*/
|
||||
messages: components["schemas"]["cabana.RelationMessages"];
|
||||
name: string;
|
||||
view: components["schemas"]["cabana.RelationPanel"];
|
||||
};
|
||||
"cabana.RowAction": {
|
||||
label?: string;
|
||||
name: string;
|
||||
@@ -1643,6 +1802,7 @@ export interface components {
|
||||
per_page?: number;
|
||||
total?: number;
|
||||
};
|
||||
"cabana.fieldContext": string | string[];
|
||||
"cabana.jsonScalar": (string | number | boolean) | null;
|
||||
};
|
||||
responses: never;
|
||||
|
||||
Reference in New Issue
Block a user