Skip to content

Commit 33eeeab

Browse files
committed
dev-demo: add json form plugin on dev-demo
AdminForth/1797/implement-jsonformplugin-using
1 parent 4adbae7 commit 33eeeab

3 files changed

Lines changed: 213 additions & 2 deletions

File tree

dev-demo/Taskfile.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ vars:
3535
- "adminforth-agent"
3636
- "adminforth-dashboard"
3737
- "adminforth-json-editor"
38+
- "adminforth-json-form"
3839

3940
ADAPTERS:
4041
- "adminforth-email-adapter-aws-ses"
Lines changed: 208 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,208 @@
1+
import type { JsonFormSchema } from '../../../plugins/adminforth-json-form/types.js';
2+
3+
/**
4+
* JSON Schema for the `specifications` JSON column of the Car resource,
5+
* rendered by the json-form plugin. Kept in its own file to keep the
6+
* resource config readable.
7+
*/
8+
const carSpecificationsSchema: JsonFormSchema = {
9+
title: 'Car Specifications',
10+
description: 'Detailed technical specification sheet',
11+
type: 'object',
12+
'x-format': 'nav-vertical',
13+
properties: {
14+
general: {
15+
title: 'General',
16+
type: 'object',
17+
'x-format': 'grid',
18+
required: ['trim'],
19+
properties: {
20+
trim: {
21+
title: 'Trim',
22+
type: 'string',
23+
description: 'Trim / edition name',
24+
minLength: 2,
25+
'x-grid': { columns: 6 },
26+
'x-messages': {
27+
required: 'Trim is required.',
28+
minLength: 'Trim must be at least 2 characters long.',
29+
},
30+
default: 'Base',
31+
},
32+
segment: {
33+
title: 'Segment',
34+
type: 'string',
35+
enum: ['a', 'b', 'c', 'd', 'suv', 'sport'],
36+
'x-enumTitles': ['A - City', 'B - Small', 'C - Compact', 'D - Mid', 'SUV', 'Sport'],
37+
'x-grid': { columns: 6 },
38+
default: 'c',
39+
},
40+
doors: {
41+
title: 'Doors',
42+
type: 'integer',
43+
minimum: 2,
44+
maximum: 6,
45+
'x-format': 'range',
46+
'x-grid': { columns: 6 },
47+
default: 4,
48+
},
49+
condition: {
50+
title: 'Condition',
51+
type: 'string',
52+
enum: ['new', 'used', 'damaged'],
53+
'x-enumTitles': ['New', 'Used', 'Damaged'],
54+
'x-format': 'radios',
55+
'x-grid': { columns: 6 },
56+
default: 'used',
57+
},
58+
exteriorColor: {
59+
title: 'Exterior Color',
60+
type: 'string',
61+
'x-format': 'color',
62+
'x-grid': { columns: 6 },
63+
default: '#1f6feb',
64+
},
65+
certified: {
66+
title: 'Certified Pre-Owned',
67+
type: 'boolean',
68+
description: 'Passed the manufacturer certification',
69+
'x-grid': { columns: 6 },
70+
default: false,
71+
},
72+
notes: {
73+
title: 'Notes',
74+
type: 'string',
75+
'x-format': 'textarea',
76+
'x-grid': { columns: 12 },
77+
default: '',
78+
},
79+
},
80+
},
81+
engine: {
82+
title: 'Engine',
83+
type: 'object',
84+
'x-format': 'grid',
85+
properties: {
86+
fuel: {
87+
title: 'Fuel',
88+
type: 'string',
89+
enum: ['petrol', 'diesel', 'hybrid', 'electric'],
90+
'x-enumTitles': ['Petrol', 'Diesel', 'Hybrid', 'Electric'],
91+
'x-format': 'radios-inline',
92+
'x-grid': { columns: 12 },
93+
default: 'petrol',
94+
},
95+
horsepower: {
96+
title: 'Horsepower',
97+
type: 'integer',
98+
minimum: 0,
99+
maximum: 2000,
100+
'x-grid': { columns: 6 },
101+
'x-messages': { maximum: 'Even hypercars stay under 2000 hp.' },
102+
default: 150,
103+
},
104+
torque: {
105+
title: 'Torque (Nm)',
106+
type: 'integer',
107+
minimum: 0,
108+
'x-grid': { columns: 6 },
109+
default: 200,
110+
},
111+
},
112+
},
113+
features: {
114+
title: 'Features',
115+
type: 'object',
116+
properties: {
117+
comfort: {
118+
title: 'Comfort',
119+
type: 'array',
120+
uniqueItems: true,
121+
'x-format': 'checkboxes-inline',
122+
items: { type: 'string', enum: ['ac', 'heated-seats', 'sunroof', 'leather'] },
123+
'x-enumTitles': ['A/C', 'Heated Seats', 'Sunroof', 'Leather'],
124+
default: ['ac'],
125+
},
126+
safety: {
127+
title: 'Safety',
128+
type: 'array',
129+
uniqueItems: true,
130+
items: { type: 'string', enum: ['abs', 'airbags', 'lane-assist', 'blind-spot'] },
131+
'x-enumTitles': ['ABS', 'Airbags', 'Lane Assist', 'Blind Spot'],
132+
'x-messages': { uniqueItems: 'Each safety feature can only be listed once.' },
133+
default: ['abs', 'airbags'],
134+
},
135+
},
136+
},
137+
serviceHistory: {
138+
title: 'Service History',
139+
type: 'array',
140+
'x-format': 'table-object',
141+
'x-sortable': true,
142+
default: [],
143+
items: {
144+
type: 'object',
145+
title: 'Service Entry',
146+
properties: {
147+
date: { title: 'Date', type: 'string', default: '' },
148+
mileage: { title: 'Mileage (km)', type: 'integer', minimum: 0, default: 0 },
149+
service: {
150+
title: 'Service',
151+
type: 'string',
152+
enum: ['oil', 'brakes', 'tires', 'general'],
153+
'x-enumTitles': ['Oil', 'Brakes', 'Tires', 'General'],
154+
default: 'general',
155+
},
156+
done: { title: 'Done', type: 'boolean', 'x-format': 'checkbox', default: false },
157+
},
158+
},
159+
},
160+
owners: {
161+
title: 'Owners',
162+
type: 'array',
163+
'x-format': 'nav-horizontal',
164+
'x-titleTemplate': '{{ i1 }}) {{ value.name }}',
165+
default: [],
166+
items: {
167+
type: 'object',
168+
title: 'Owner',
169+
'x-format': 'grid',
170+
properties: {
171+
name: { title: 'Name', type: 'string', 'x-grid': { columns: 6 }, default: 'New Owner' },
172+
years: { title: 'Years Owned', type: 'integer', minimum: 0, 'x-grid': { columns: 6 }, default: 1 },
173+
seller: {
174+
title: 'Seller Type',
175+
type: 'object',
176+
'x-grid': { columns: 12 },
177+
'x-discriminator': 'kind',
178+
oneOf: [
179+
{
180+
title: 'Dealer',
181+
'x-switcherTitle': 'Dealer',
182+
type: 'object',
183+
required: ['kind'],
184+
properties: {
185+
kind: { type: 'string', const: 'dealer', default: 'dealer', readOnly: true, 'x-enforceConst': true },
186+
dealership: { title: 'Dealership', type: 'string', default: 'AutoHouse' },
187+
},
188+
},
189+
{
190+
title: 'Private',
191+
'x-switcherTitle': 'Private',
192+
type: 'object',
193+
required: ['kind'],
194+
properties: {
195+
kind: { type: 'string', const: 'private', default: 'private', readOnly: true, 'x-enforceConst': true },
196+
city: { title: 'City', type: 'string', default: 'Berlin' },
197+
},
198+
},
199+
],
200+
default: { kind: 'dealer', dealership: 'AutoHouse' },
201+
},
202+
},
203+
},
204+
},
205+
},
206+
};
207+
208+
export default carSpecificationsSchema;

dev-demo/resources/cars_resources/carsResourseTemplate.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,8 @@ import AdminForthImageVisionAdapterOpenAi from '../../../adapters/adminforth-ima
2626
import { logger } from '../../../adminforth/modules/logger.js';
2727
import { afLogger } from '../../../adminforth/modules/logger.js';
2828
import ForeignInlineListPlugin from '../../../plugins/adminforth-foreign-inline-list/index.js';
29-
import JsonEditorPlugin from '../../../plugins/adminforth-json-editor/index.js';
29+
import JsonFormPlugin from '../../../plugins/adminforth-json-form/index.js';
30+
import carSpecificationsSchema from './carSpecificationsSchema.js';
3031

3132
const CAR_RESOURCE_DB_LABELS = {
3233
sqlite: 'SQLite',
@@ -267,8 +268,9 @@ export default function carsResourseTemplate(resourceId: string, dataSource: Car
267268
}
268269
} : {}),
269270
}),
270-
new JsonEditorPlugin({
271+
new JsonFormPlugin({
271272
fieldName: 'specifications',
273+
schema: carSpecificationsSchema,
272274
}),
273275
new importExport({}),
274276
// new InlineCreatePlugin({}),

0 commit comments

Comments
 (0)