feat(10-03): tabs, toggles, relation fields, form lifecycle and settings pages
- FormTabs groups fields by tab (untabbed fields in the default tab) as a
segmented tablist; a tab holding invalid fields after a 422 shows a
count badge and the form switches to the first invalid field
- switch, checkbox and relation join the renderer registry: toggle cards
(role=switch, 20px checkbox) keep a numeric value numeric; relation
fields are read-only labels from meta.labels, a searchable single
select over fields/{field}/options with emptyOption first, or ordered
removable chips with an appending search (300 ms debounce, 20 per
page, more on scroll or the more action)
- FormView gets the back button, record title and update subtitle, a
sticky footer (Usuń with deleteConfirm then DELETE, Anuluj, Zapisz i
zamknij to the mapped redirectClose, Zapisz), and asks before leaving a
dirty form on any route change plus a beforeunload guard
- Settings: the rail pins Ustawienia to the bottom when /settings is
non-empty; /settings lists pages by category; /settings/:code renders
the settings schema through FormGrid and the registry, PUTs the values
and maps a 422 like the record form
- New backend::lang keys (form.more_options, tab_default, discard,
settings.back); form and settings smoke tests; boardwalk/dist rebuilt
This commit is contained in:
12
admin/tests/fixtures/lang.json
vendored
12
admin/tests/fixtures/lang.json
vendored
@@ -45,6 +45,9 @@
|
||||
"backend::lang.form.deleting": {
|
||||
"other": "Usuwanie…"
|
||||
},
|
||||
"backend::lang.form.discard": {
|
||||
"other": "Porzuć zmiany"
|
||||
},
|
||||
"backend::lang.form.error_fields": {
|
||||
"one": "Popraw :count pole oznaczone poniżej.",
|
||||
"few": "Popraw :count pola oznaczone poniżej.",
|
||||
@@ -63,6 +66,9 @@
|
||||
"backend::lang.form.loading_options": {
|
||||
"other": "Wczytywanie…"
|
||||
},
|
||||
"backend::lang.form.more_options": {
|
||||
"other": "Więcej wyników"
|
||||
},
|
||||
"backend::lang.form.no_options": {
|
||||
"other": "Brak wyników"
|
||||
},
|
||||
@@ -87,6 +93,9 @@
|
||||
"backend::lang.form.select_placeholder": {
|
||||
"other": "Wybierz…"
|
||||
},
|
||||
"backend::lang.form.tab_default": {
|
||||
"other": "Podstawowe"
|
||||
},
|
||||
"backend::lang.form.tab_errors": {
|
||||
"one": ":count błąd",
|
||||
"few": ":count błędy",
|
||||
@@ -309,6 +318,9 @@
|
||||
"backend::lang.relation.unlink": {
|
||||
"other": "Odłącz"
|
||||
},
|
||||
"backend::lang.settings.back": {
|
||||
"other": "Wróć do ustawień"
|
||||
},
|
||||
"backend::lang.settings.empty": {
|
||||
"other": "Brak dostępnych ustawień."
|
||||
},
|
||||
|
||||
104
admin/tests/fixtures/settings.json
vendored
Normal file
104
admin/tests/fixtures/settings.json
vendored
Normal file
@@ -0,0 +1,104 @@
|
||||
{
|
||||
"list": {
|
||||
"data": [
|
||||
{
|
||||
"code": "search",
|
||||
"label": "Search",
|
||||
"description": "Search engine options",
|
||||
"icon": "search",
|
||||
"category": "System",
|
||||
"keywords": [],
|
||||
"model": "Acme\\Demo\\Models\\Settings",
|
||||
"order": 20
|
||||
},
|
||||
{
|
||||
"code": "mail",
|
||||
"label": "Mail",
|
||||
"description": "Outgoing mail",
|
||||
"icon": "icon-cog",
|
||||
"category": "System",
|
||||
"keywords": [],
|
||||
"model": "Acme\\Demo\\Models\\MailSettings",
|
||||
"order": 10
|
||||
},
|
||||
{
|
||||
"code": "branding",
|
||||
"label": "Branding",
|
||||
"description": "Logo and colours",
|
||||
"icon": "palette",
|
||||
"category": "Appearance",
|
||||
"keywords": [],
|
||||
"model": "Acme\\Demo\\Models\\Branding",
|
||||
"order": 5
|
||||
}
|
||||
],
|
||||
"meta": {
|
||||
"locale": "en"
|
||||
}
|
||||
},
|
||||
"schema": {
|
||||
"data": {
|
||||
"name": "Search",
|
||||
"fields": [
|
||||
{
|
||||
"name": "use_engine",
|
||||
"label": "Use the search engine",
|
||||
"type": "switch",
|
||||
"default": 0,
|
||||
"comment": "Queries go to the external engine",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "engine_host",
|
||||
"label": "Engine host",
|
||||
"type": "text",
|
||||
"span": "full"
|
||||
}
|
||||
],
|
||||
"messages": {
|
||||
"create": {
|
||||
"other": "New record"
|
||||
},
|
||||
"update": {
|
||||
"other": "Edit record"
|
||||
},
|
||||
"saved": {
|
||||
"other": "Saved"
|
||||
},
|
||||
"deleteConfirm": {
|
||||
"other": "Delete?"
|
||||
},
|
||||
"deleted": {
|
||||
"other": "Deleted"
|
||||
}
|
||||
},
|
||||
"meta": {
|
||||
"locale": "en"
|
||||
},
|
||||
"redirects": {
|
||||
"create": {
|
||||
"redirect": "",
|
||||
"redirectClose": ""
|
||||
},
|
||||
"update": {
|
||||
"redirect": "",
|
||||
"redirectClose": ""
|
||||
},
|
||||
"default": ""
|
||||
}
|
||||
},
|
||||
"meta": {
|
||||
"locale": "en"
|
||||
}
|
||||
},
|
||||
"values": {
|
||||
"data": {
|
||||
"data": {
|
||||
"use_engine": 0,
|
||||
"engine_host": "search.local"
|
||||
},
|
||||
"exists": true
|
||||
},
|
||||
"meta": {}
|
||||
}
|
||||
}
|
||||
157
admin/tests/fixtures/widgets.form-schema.json
vendored
157
admin/tests/fixtures/widgets.form-schema.json
vendored
@@ -2,8 +2,20 @@
|
||||
"data": {
|
||||
"name": "Widget",
|
||||
"fields": [
|
||||
{ "name": "name", "label": "Name", "type": "text", "span": "left", "required": true },
|
||||
{ "name": "code", "label": "Code", "type": "text", "span": "right", "comment": "Unique widget code" },
|
||||
{
|
||||
"name": "name",
|
||||
"label": "Name",
|
||||
"type": "text",
|
||||
"span": "left",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "code",
|
||||
"label": "Code",
|
||||
"type": "text",
|
||||
"span": "right",
|
||||
"comment": "Unique widget code"
|
||||
},
|
||||
{
|
||||
"name": "size",
|
||||
"label": "Size",
|
||||
@@ -11,28 +23,139 @@
|
||||
"span": "left",
|
||||
"emptyOption": "— none —",
|
||||
"options": [
|
||||
{ "value": "s", "label": "Small" },
|
||||
{ "value": "m", "label": "Medium" },
|
||||
{ "value": "l", "label": "Large" }
|
||||
{
|
||||
"value": "s",
|
||||
"label": "Small"
|
||||
},
|
||||
{
|
||||
"value": "m",
|
||||
"label": "Medium"
|
||||
},
|
||||
{
|
||||
"value": "l",
|
||||
"label": "Large"
|
||||
}
|
||||
]
|
||||
},
|
||||
{ "name": "weight", "label": "Weight", "type": "number", "span": "right" },
|
||||
{ "name": "notes", "label": "Notes", "type": "textarea", "span": "full", "size": "small" },
|
||||
{ "name": "color", "label": "Colour", "type": "colorpicker", "span": "left" }
|
||||
{
|
||||
"name": "weight",
|
||||
"label": "Weight",
|
||||
"type": "number",
|
||||
"span": "right"
|
||||
},
|
||||
{
|
||||
"name": "notes",
|
||||
"label": "Notes",
|
||||
"type": "textarea",
|
||||
"span": "full",
|
||||
"size": "small"
|
||||
},
|
||||
{
|
||||
"name": "color",
|
||||
"label": "Colour",
|
||||
"type": "colorpicker",
|
||||
"span": "left"
|
||||
},
|
||||
{
|
||||
"name": "active",
|
||||
"label": "Active",
|
||||
"type": "switch",
|
||||
"span": "left",
|
||||
"comment": "Shown in the catalogue"
|
||||
},
|
||||
{
|
||||
"name": "featured",
|
||||
"label": "Featured",
|
||||
"type": "checkbox",
|
||||
"span": "right",
|
||||
"comment": "Pinned to the top"
|
||||
},
|
||||
{
|
||||
"name": "maker",
|
||||
"label": "Maker",
|
||||
"type": "relation",
|
||||
"span": "left",
|
||||
"nameFrom": "name",
|
||||
"emptyOption": "— none —"
|
||||
},
|
||||
{
|
||||
"name": "tags",
|
||||
"label": "Tags",
|
||||
"type": "relation",
|
||||
"span": "right",
|
||||
"nameFrom": "name",
|
||||
"multiple": true,
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"name": "owner",
|
||||
"label": "Owner",
|
||||
"type": "relation",
|
||||
"span": "left",
|
||||
"nameFrom": "email",
|
||||
"emptyOption": "Current user",
|
||||
"readOnly": true
|
||||
},
|
||||
{
|
||||
"name": "serial",
|
||||
"label": "Serial",
|
||||
"type": "text",
|
||||
"span": "left",
|
||||
"tab": "Details",
|
||||
"context": "update"
|
||||
},
|
||||
{
|
||||
"name": "batch",
|
||||
"label": "Batch",
|
||||
"type": "text",
|
||||
"span": "right",
|
||||
"tab": "Details",
|
||||
"context": [
|
||||
"create"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "parts",
|
||||
"type": "relation-manager",
|
||||
"relation": "parts",
|
||||
"span": "full",
|
||||
"tab": "Parts",
|
||||
"context": "update"
|
||||
}
|
||||
],
|
||||
"messages": {
|
||||
"create": { "other": "New widget" },
|
||||
"update": { "other": "Editing widget" },
|
||||
"saved": { "other": "Widget „:name” saved" },
|
||||
"deleteConfirm": { "other": "Delete this widget?" },
|
||||
"deleted": { "other": "Widget deleted" }
|
||||
"create": {
|
||||
"other": "New widget"
|
||||
},
|
||||
"update": {
|
||||
"other": "Editing widget"
|
||||
},
|
||||
"saved": {
|
||||
"other": "Widget „:name” saved"
|
||||
},
|
||||
"deleteConfirm": {
|
||||
"other": "Delete this widget?"
|
||||
},
|
||||
"deleted": {
|
||||
"other": "Widget deleted"
|
||||
}
|
||||
},
|
||||
"meta": {
|
||||
"locale": "en"
|
||||
},
|
||||
"meta": { "locale": "en" },
|
||||
"redirects": {
|
||||
"create": { "redirect": "acme/demo/widgets/update/:id", "redirectClose": "acme/demo/widgets" },
|
||||
"update": { "redirect": "acme/demo/widgets", "redirectClose": "acme/demo/widgets" },
|
||||
"create": {
|
||||
"redirect": "acme/demo/widgets/update/:id",
|
||||
"redirectClose": "acme/demo/widgets"
|
||||
},
|
||||
"update": {
|
||||
"redirect": "acme/demo/widgets",
|
||||
"redirectClose": "acme/demo/widgets"
|
||||
},
|
||||
"default": "acme/demo/widgets"
|
||||
}
|
||||
},
|
||||
"meta": { "locale": "en" }
|
||||
"meta": {
|
||||
"locale": "en"
|
||||
}
|
||||
}
|
||||
|
||||
82
admin/tests/fixtures/widgets.options.json
vendored
82
admin/tests/fixtures/widgets.options.json
vendored
@@ -1,9 +1,85 @@
|
||||
{
|
||||
"maker": {
|
||||
"data": [
|
||||
{ "value": "1", "label": "Acme Works" },
|
||||
{ "value": "2", "label": "Bolt & Co" }
|
||||
{
|
||||
"value": "1",
|
||||
"label": "Acme Works"
|
||||
},
|
||||
{
|
||||
"value": "2",
|
||||
"label": "Bolt & Co"
|
||||
}
|
||||
],
|
||||
"meta": { "locale": "en" }
|
||||
"meta": {
|
||||
"locale": "en"
|
||||
}
|
||||
},
|
||||
"makerField": {
|
||||
"data": [
|
||||
{
|
||||
"value": 1,
|
||||
"label": "Acme Works"
|
||||
},
|
||||
{
|
||||
"value": 2,
|
||||
"label": "Bolt & Co"
|
||||
}
|
||||
],
|
||||
"meta": {
|
||||
"page": 1,
|
||||
"per_page": 20,
|
||||
"total": 3,
|
||||
"last_page": 2
|
||||
}
|
||||
},
|
||||
"makerFieldPage2": {
|
||||
"data": [
|
||||
{
|
||||
"value": 7,
|
||||
"label": "Cog Ltd"
|
||||
}
|
||||
],
|
||||
"meta": {
|
||||
"page": 2,
|
||||
"per_page": 20,
|
||||
"total": 3,
|
||||
"last_page": 2
|
||||
}
|
||||
},
|
||||
"makerFieldSearch": {
|
||||
"data": [
|
||||
{
|
||||
"value": 1,
|
||||
"label": "Acme Works"
|
||||
}
|
||||
],
|
||||
"meta": {
|
||||
"page": 1,
|
||||
"per_page": 20,
|
||||
"total": 1,
|
||||
"last_page": 1
|
||||
}
|
||||
},
|
||||
"tagsField": {
|
||||
"data": [
|
||||
{
|
||||
"value": 1,
|
||||
"label": "Small"
|
||||
},
|
||||
{
|
||||
"value": 3,
|
||||
"label": "Round"
|
||||
},
|
||||
{
|
||||
"value": 4,
|
||||
"label": "Large"
|
||||
}
|
||||
],
|
||||
"meta": {
|
||||
"page": 1,
|
||||
"per_page": 20,
|
||||
"total": 3,
|
||||
"last_page": 1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
38
admin/tests/fixtures/widgets.record.json
vendored
38
admin/tests/fixtures/widgets.record.json
vendored
@@ -6,7 +6,41 @@
|
||||
"size": "m",
|
||||
"weight": 12,
|
||||
"notes": "Round",
|
||||
"color": "#0000ff"
|
||||
"color": "#0000ff",
|
||||
"active": true,
|
||||
"featured": false,
|
||||
"maker": 2,
|
||||
"tags": [
|
||||
3,
|
||||
1
|
||||
],
|
||||
"owner": 5,
|
||||
"serial": "SN-1"
|
||||
},
|
||||
"meta": { "labels": {} }
|
||||
"meta": {
|
||||
"labels": {
|
||||
"maker": [
|
||||
{
|
||||
"value": 2,
|
||||
"label": "Bolt & Co"
|
||||
}
|
||||
],
|
||||
"tags": [
|
||||
{
|
||||
"value": 3,
|
||||
"label": "Round"
|
||||
},
|
||||
{
|
||||
"value": 1,
|
||||
"label": "Small"
|
||||
}
|
||||
],
|
||||
"owner": [
|
||||
{
|
||||
"value": 5,
|
||||
"label": "dana@example.test"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user