Skip to content

Commit ac20f53

Browse files
committed
apply values to form
1 parent c29fc68 commit ac20f53

File tree

4 files changed

+609
-43
lines changed

4 files changed

+609
-43
lines changed

src/app/src/components/shared/form/FormSchemaBased.vue

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { computed } from 'vue'
33
import type { FormTree } from '../../../types'
44
import type { PropType } from 'vue'
55
import type { Draft07 } from '@nuxt/content'
6-
import { buildFormTreeFromSchema } from '../../../utils/form'
6+
import { buildFormTreeFromSchema, applyValuesToFormTree } from '../../../utils/form'
77
88
const props = defineProps({
99
collectionName: {
@@ -16,15 +16,26 @@ const props = defineProps({
1616
},
1717
})
1818
19-
console.log('props.schema', props.schema)
19+
const data = defineModel<Record<string, unknown>>({ required: true })
2020
21-
defineModel<Record<string, unknown>>({ required: true })
21+
console.log('data', data.value)
2222
2323
const formTree = computed<FormTree>(() => {
2424
return buildFormTreeFromSchema(props.collectionName, props.schema)
2525
})
2626
27-
console.log('formTree', formTree.value)
27+
const formTreeWithValues = computed({
28+
get: () => {
29+
if (!data.value || !formTree.value) {
30+
return null
31+
}
32+
33+
return applyValuesToFormTree(formTree.value, { [props.collectionName]: data.value })
34+
},
35+
set: (newFormTree) => {
36+
console.log('newFormTree', newFormTree)
37+
},
38+
})
2839
2940
// const jsonString = computed({
3041
// get: () => JSON.stringify(model.value, null, 2),
@@ -43,7 +54,7 @@ console.log('formTree', formTree.value)
4354
<FormPanelSection
4455
v-for="formItem in formTree[collectionName].children"
4556
:key="formItem.id"
46-
v-model="formTree"
57+
v-model="formTreeWithValues"
4758
:form-item="formItem"
4859
/>
4960
</template>

src/app/src/utils/form.ts

Lines changed: 88 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,17 @@
11
import type { Draft07, Draft07DefinitionProperty, Draft07DefinitionPropertyAnyOf, Draft07DefinitionPropertyAllOf, Draft07DefinitionPropertyOneOf } from '@nuxt/content'
22
import type { FormTree, FormItem } from '../types'
33
import { upperFirst } from 'scule'
4+
import { omit } from './object'
45

56
export const buildFormTreeFromSchema = (treeKey: string, schema: Draft07): FormTree => {
67
if (!schema || !schema.definitions || !schema.definitions[treeKey]) {
78
return {}
89
}
910

10-
const buildFormTreeItem = (def: Draft07DefinitionProperty, id: string = `#frontmatter/${treeKey}`): FormItem | null => {
11+
const buildFormTreeItem = (def: Draft07DefinitionProperty, id: string = `#${treeKey}`): FormItem | null => {
1112
const paths = id.split('/')
12-
const itemKey = paths.pop()!
13-
const level = paths.length - 1 // deduce #frontmatter
13+
const itemKey = paths.pop()!.replace('#', '')
14+
const level = paths.length
1415

1516
const editor = def.$content?.editor
1617
if (editor?.hidden) {
@@ -140,3 +141,87 @@ export const buildFormTreeFromSchema = (treeKey: string, schema: Draft07): FormT
140141
[treeKey]: buildFormTreeItem(schema.definitions[treeKey] as Draft07DefinitionProperty) as FormItem,
141142
}
142143
}
144+
145+
// Apply json to form tree values
146+
// Only override properties that are present in the tree
147+
export const applyValuesToFormTree = (tree: FormTree, override: Record<string, unknown>): FormTree => {
148+
console.log('tree', tree)
149+
console.log('override', override)
150+
return Object.keys(tree).reduce((acc, key) => {
151+
// Recursively override if found
152+
if (override[key]) {
153+
if (tree[key].children) {
154+
return {
155+
...acc,
156+
[key]: {
157+
...(omit(tree[key], ['children'])),
158+
children: {
159+
...tree[key].children,
160+
...applyValuesToFormTree(tree[key].children, override[key] as Record<string, unknown>),
161+
},
162+
},
163+
} as FormTree
164+
}
165+
166+
return {
167+
...acc,
168+
[key]: {
169+
...tree[key],
170+
value: override[key],
171+
},
172+
} as FormTree
173+
}
174+
// Else recusively add empty value
175+
else {
176+
if (tree[key].children) {
177+
return {
178+
...acc,
179+
[key]: {
180+
...(omit(tree[key], ['children'])),
181+
children: {
182+
...tree[key].children,
183+
...applyValuesToFormTree(tree[key].children, {}),
184+
},
185+
},
186+
}
187+
}
188+
189+
return {
190+
...acc,
191+
[key]: {
192+
...tree[key],
193+
value: '',
194+
},
195+
196+
}
197+
}
198+
}, {})
199+
}
200+
201+
// Recursively traverse the form tree to find the corresponding id and update the value
202+
export const applyValueById = (form: FormTree, id: string, value: unknown): FormTree => {
203+
return Object.keys(form).reduce((acc, key) => {
204+
if (form[key].id === id) {
205+
return {
206+
...acc,
207+
[key]: {
208+
...form[key],
209+
value,
210+
},
211+
}
212+
}
213+
else if (form[key].children) {
214+
return {
215+
...acc,
216+
[key]: {
217+
...form[key],
218+
children: applyValueById(form[key].children, id, value),
219+
},
220+
}
221+
}
222+
return {
223+
...acc,
224+
[key]: form[key],
225+
}
226+
}, {})
227+
}

src/app/test/mocks/schema.ts

Lines changed: 198 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,198 @@
1+
import type { Draft07 } from '@nuxt/content'
2+
3+
export const postsSchema: Draft07 = {
4+
$ref: '#/definitions/posts',
5+
definitions: {
6+
posts: {
7+
type: 'object',
8+
properties: {
9+
contentId: {
10+
type: 'string',
11+
},
12+
weight: {
13+
type: 'string',
14+
},
15+
stem: {
16+
type: 'string',
17+
},
18+
extension: {
19+
type: 'string',
20+
enum: [
21+
'md',
22+
'yaml',
23+
'json',
24+
'csv',
25+
'xml',
26+
],
27+
},
28+
meta: {
29+
type: 'object',
30+
additionalProperties: {},
31+
},
32+
path: {
33+
type: 'string',
34+
},
35+
title: {
36+
type: 'string',
37+
},
38+
description: {
39+
type: 'string',
40+
},
41+
seo: {
42+
allOf: [
43+
{
44+
type: 'object',
45+
properties: {
46+
title: {
47+
type: 'string',
48+
},
49+
description: {
50+
type: 'string',
51+
},
52+
},
53+
},
54+
{
55+
type: 'object',
56+
additionalProperties: {},
57+
},
58+
],
59+
},
60+
body: {
61+
type: 'object',
62+
properties: {
63+
type: {
64+
type: 'string',
65+
},
66+
children: {},
67+
toc: {},
68+
},
69+
required: [
70+
'type',
71+
],
72+
additionalProperties: false,
73+
},
74+
navigation: {
75+
anyOf: [
76+
{
77+
type: 'boolean',
78+
},
79+
{
80+
type: 'object',
81+
properties: {
82+
title: {
83+
type: 'string',
84+
},
85+
description: {
86+
type: 'string',
87+
},
88+
icon: {
89+
type: 'string',
90+
},
91+
},
92+
required: [
93+
'title',
94+
'description',
95+
'icon',
96+
],
97+
additionalProperties: false,
98+
},
99+
],
100+
default: true,
101+
},
102+
authors: {
103+
type: 'array',
104+
items: {
105+
type: 'object',
106+
properties: {
107+
slug: {
108+
type: 'string',
109+
},
110+
name: {
111+
type: 'string',
112+
},
113+
to: {
114+
type: 'string',
115+
},
116+
avatar: {
117+
type: 'object',
118+
properties: {
119+
src: {
120+
type: 'string',
121+
},
122+
alt: {
123+
type: 'string',
124+
},
125+
},
126+
required: [
127+
'src',
128+
'alt',
129+
],
130+
additionalProperties: false,
131+
},
132+
},
133+
required: [
134+
'slug',
135+
'name',
136+
'to',
137+
'avatar',
138+
],
139+
additionalProperties: false,
140+
},
141+
},
142+
date: {
143+
type: 'string',
144+
format: 'date-time',
145+
},
146+
image: {
147+
type: 'object',
148+
properties: {
149+
src: {
150+
type: 'string',
151+
},
152+
alt: {
153+
type: 'string',
154+
},
155+
},
156+
required: [
157+
'src',
158+
'alt',
159+
],
160+
additionalProperties: false,
161+
},
162+
badge: {
163+
type: 'object',
164+
properties: {
165+
label: {
166+
type: 'string',
167+
},
168+
color: {
169+
type: 'string',
170+
},
171+
},
172+
required: [
173+
'label',
174+
'color',
175+
],
176+
additionalProperties: false,
177+
},
178+
},
179+
required: [
180+
'contentId',
181+
'weight',
182+
'stem',
183+
'extension',
184+
'meta',
185+
'path',
186+
'title',
187+
'description',
188+
'body',
189+
'authors',
190+
'date',
191+
'image',
192+
'badge',
193+
],
194+
additionalProperties: false,
195+
},
196+
},
197+
$schema: 'http://json-schema.org/draft-07/schema#',
198+
}

0 commit comments

Comments
 (0)