@tinacms/app 0.0.0-20230516164752 → 0.0.0-20230516170903
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +3 -3
- package/package.json +5 -5
- package/src/lib/expand-query.ts +12 -1
- package/src/lib/graphql-reducer.ts +192 -26
- package/src/lib/types.ts +8 -5
- package/src/lib/util.ts +124 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
# @tinacms/app
|
|
2
2
|
|
|
3
|
-
## 0.0.0-
|
|
3
|
+
## 0.0.0-20230516170903
|
|
4
4
|
|
|
5
5
|
### Patch Changes
|
|
6
6
|
|
|
7
7
|
- 7f95c1ce5: Reorganize the way fields are presented on the form to allow for deep-linking
|
|
8
8
|
- Updated dependencies [b3d98d159]
|
|
9
9
|
- Updated dependencies [7f95c1ce5]
|
|
10
|
-
- @tinacms/toolkit@0.0.0-
|
|
11
|
-
- tinacms@0.0.0-
|
|
10
|
+
- @tinacms/toolkit@0.0.0-20230516170903
|
|
11
|
+
- tinacms@0.0.0-20230516170903
|
|
12
12
|
|
|
13
13
|
## 1.2.12
|
|
14
14
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tinacms/app",
|
|
3
|
-
"version": "0.0.0-
|
|
3
|
+
"version": "0.0.0-20230516170903",
|
|
4
4
|
"main": "src/main.tsx",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"devDependencies": {
|
|
@@ -13,8 +13,6 @@
|
|
|
13
13
|
"@headlessui/react": "1.6.6",
|
|
14
14
|
"@heroicons/react": "1.0.6",
|
|
15
15
|
"@monaco-editor/react": "4.4.5",
|
|
16
|
-
"@tinacms/mdx": "1.3.10",
|
|
17
|
-
"@tinacms/toolkit": "0.0.0-20230516164752",
|
|
18
16
|
"@xstate/react": "3.0.0",
|
|
19
17
|
"final-form": "4.20.7",
|
|
20
18
|
"graphiql": "^2.4.0",
|
|
@@ -27,8 +25,10 @@
|
|
|
27
25
|
"react-is": "17.0.2",
|
|
28
26
|
"react-router-dom": "6.3.0",
|
|
29
27
|
"tailwindcss": "^3.2.7",
|
|
30
|
-
"tinacms": "0.0.0-20230516164752",
|
|
31
28
|
"typescript": "^4.6.4",
|
|
32
|
-
"zod": "^3.14.3"
|
|
29
|
+
"zod": "^3.14.3",
|
|
30
|
+
"@tinacms/mdx": "1.3.10",
|
|
31
|
+
"@tinacms/toolkit": "0.0.0-20230516170903",
|
|
32
|
+
"tinacms": "0.0.0-20230516170903"
|
|
33
33
|
}
|
|
34
34
|
}
|
package/src/lib/expand-query.ts
CHANGED
|
@@ -67,6 +67,13 @@ const addTypenameToDocument = (doc: G.DocumentNode) => {
|
|
|
67
67
|
})
|
|
68
68
|
}
|
|
69
69
|
|
|
70
|
+
const CONTENT_SOURCE_FIELD: G.FieldNode = {
|
|
71
|
+
kind: G.Kind.FIELD,
|
|
72
|
+
name: {
|
|
73
|
+
kind: G.Kind.NAME,
|
|
74
|
+
value: '_content_source',
|
|
75
|
+
},
|
|
76
|
+
}
|
|
70
77
|
const METADATA_FIELD: G.FieldNode = {
|
|
71
78
|
kind: G.Kind.FIELD,
|
|
72
79
|
name: {
|
|
@@ -94,7 +101,11 @@ const addMetadataField = (
|
|
|
94
101
|
selections: [],
|
|
95
102
|
}),
|
|
96
103
|
selections:
|
|
97
|
-
[
|
|
104
|
+
[
|
|
105
|
+
...(node.selectionSet?.selections || []),
|
|
106
|
+
METADATA_FIELD,
|
|
107
|
+
CONTENT_SOURCE_FIELD,
|
|
108
|
+
] || [],
|
|
98
109
|
},
|
|
99
110
|
}
|
|
100
111
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import React from 'react'
|
|
2
2
|
import * as G from 'graphql'
|
|
3
3
|
import { getIn } from 'final-form'
|
|
4
|
-
import { z
|
|
4
|
+
import { z } from 'zod'
|
|
5
5
|
// @ts-expect-error
|
|
6
6
|
import schemaJson from 'SCHEMA_IMPORT'
|
|
7
7
|
import { expandQuery, isConnectionType, isNodeType } from './expand-query'
|
|
@@ -25,9 +25,10 @@ import type {
|
|
|
25
25
|
PostMessage,
|
|
26
26
|
Payload,
|
|
27
27
|
SystemInfo,
|
|
28
|
-
Document,
|
|
29
28
|
ResolvedDocument,
|
|
30
29
|
} from './types'
|
|
30
|
+
import { getFormAndFieldNameFromMetadata } from './util'
|
|
31
|
+
import { useSearchParams } from 'react-router-dom'
|
|
31
32
|
|
|
32
33
|
const sysSchema = z.object({
|
|
33
34
|
breadcrumbs: z.array(z.string()),
|
|
@@ -57,6 +58,50 @@ const astNode = schemaJson as G.DocumentNode
|
|
|
57
58
|
const astNodeWithMeta: G.DocumentNode = {
|
|
58
59
|
...astNode,
|
|
59
60
|
definitions: astNode.definitions.map((def) => {
|
|
61
|
+
if (def.kind === 'InterfaceTypeDefinition') {
|
|
62
|
+
return {
|
|
63
|
+
...def,
|
|
64
|
+
fields: [
|
|
65
|
+
...(def.fields || []),
|
|
66
|
+
{
|
|
67
|
+
kind: 'FieldDefinition',
|
|
68
|
+
name: {
|
|
69
|
+
kind: 'Name',
|
|
70
|
+
value: '_tina_metadata',
|
|
71
|
+
},
|
|
72
|
+
arguments: [],
|
|
73
|
+
type: {
|
|
74
|
+
kind: 'NonNullType',
|
|
75
|
+
type: {
|
|
76
|
+
kind: 'NamedType',
|
|
77
|
+
name: {
|
|
78
|
+
kind: 'Name',
|
|
79
|
+
value: 'JSON',
|
|
80
|
+
},
|
|
81
|
+
},
|
|
82
|
+
},
|
|
83
|
+
},
|
|
84
|
+
{
|
|
85
|
+
kind: 'FieldDefinition',
|
|
86
|
+
name: {
|
|
87
|
+
kind: 'Name',
|
|
88
|
+
value: '_content_source',
|
|
89
|
+
},
|
|
90
|
+
arguments: [],
|
|
91
|
+
type: {
|
|
92
|
+
kind: 'NonNullType',
|
|
93
|
+
type: {
|
|
94
|
+
kind: 'NamedType',
|
|
95
|
+
name: {
|
|
96
|
+
kind: 'Name',
|
|
97
|
+
value: 'JSON',
|
|
98
|
+
},
|
|
99
|
+
},
|
|
100
|
+
},
|
|
101
|
+
},
|
|
102
|
+
],
|
|
103
|
+
}
|
|
104
|
+
}
|
|
60
105
|
if (def.kind === 'ObjectTypeDefinition') {
|
|
61
106
|
return {
|
|
62
107
|
...def,
|
|
@@ -80,6 +125,24 @@ const astNodeWithMeta: G.DocumentNode = {
|
|
|
80
125
|
},
|
|
81
126
|
},
|
|
82
127
|
},
|
|
128
|
+
{
|
|
129
|
+
kind: 'FieldDefinition',
|
|
130
|
+
name: {
|
|
131
|
+
kind: 'Name',
|
|
132
|
+
value: '_content_source',
|
|
133
|
+
},
|
|
134
|
+
arguments: [],
|
|
135
|
+
type: {
|
|
136
|
+
kind: 'NonNullType',
|
|
137
|
+
type: {
|
|
138
|
+
kind: 'NamedType',
|
|
139
|
+
name: {
|
|
140
|
+
kind: 'Name',
|
|
141
|
+
value: 'JSON',
|
|
142
|
+
},
|
|
143
|
+
},
|
|
144
|
+
},
|
|
145
|
+
},
|
|
83
146
|
],
|
|
84
147
|
}
|
|
85
148
|
}
|
|
@@ -96,6 +159,18 @@ export const useGraphQLReducer = (
|
|
|
96
159
|
const cms = useCMS()
|
|
97
160
|
const tinaSchema = cms.api.tina.schema as TinaSchema
|
|
98
161
|
const [payloads, setPayloads] = React.useState<Payload[]>([])
|
|
162
|
+
const [searchParams, setSearchParams] = useSearchParams()
|
|
163
|
+
const [results, setResults] = React.useState<
|
|
164
|
+
{
|
|
165
|
+
id: string
|
|
166
|
+
data:
|
|
167
|
+
| {
|
|
168
|
+
[key: string]: any
|
|
169
|
+
}
|
|
170
|
+
| null
|
|
171
|
+
| undefined
|
|
172
|
+
}[]
|
|
173
|
+
>([])
|
|
99
174
|
const [documentsToResolve, setDocumentsToResolve] = React.useState<string[]>(
|
|
100
175
|
[]
|
|
101
176
|
)
|
|
@@ -104,6 +179,11 @@ export const useGraphQLReducer = (
|
|
|
104
179
|
>([])
|
|
105
180
|
const [operationIndex, setOperationIndex] = React.useState(0)
|
|
106
181
|
|
|
182
|
+
const helper = React.useMemo(() => {
|
|
183
|
+
const previewPlugins = cms.plugins.getType('preview-helper')
|
|
184
|
+
return previewPlugins.find('preview-helper')
|
|
185
|
+
}, [cms])
|
|
186
|
+
|
|
107
187
|
React.useEffect(() => {
|
|
108
188
|
const run = async () => {
|
|
109
189
|
return Promise.all(
|
|
@@ -145,7 +225,7 @@ export const useGraphQLReducer = (
|
|
|
145
225
|
setPayloads(updatedPayloads)
|
|
146
226
|
})
|
|
147
227
|
}
|
|
148
|
-
}, [
|
|
228
|
+
}, [JSON.stringify(payloads), cms])
|
|
149
229
|
|
|
150
230
|
const processPayload = React.useCallback(
|
|
151
231
|
(payload: Payload) => {
|
|
@@ -192,6 +272,13 @@ export const useGraphQLReducer = (
|
|
|
192
272
|
if (fieldName === '_values') {
|
|
193
273
|
return source._internalValues
|
|
194
274
|
}
|
|
275
|
+
if (info.fieldName === '_content_source') {
|
|
276
|
+
const pathArray = G.responsePathAsArray(info.path)
|
|
277
|
+
return {
|
|
278
|
+
queryId: payload.id,
|
|
279
|
+
path: pathArray.slice(0, pathArray.length - 1),
|
|
280
|
+
}
|
|
281
|
+
}
|
|
195
282
|
if (info.fieldName === '_tina_metadata') {
|
|
196
283
|
if (value) {
|
|
197
284
|
return value
|
|
@@ -201,6 +288,7 @@ export const useGraphQLReducer = (
|
|
|
201
288
|
return {
|
|
202
289
|
id: null,
|
|
203
290
|
fields: [],
|
|
291
|
+
prefix: '',
|
|
204
292
|
}
|
|
205
293
|
}
|
|
206
294
|
if (isConnectionType(info.returnType)) {
|
|
@@ -271,13 +359,9 @@ export const useGraphQLReducer = (
|
|
|
271
359
|
return pathString.startsWith(item.path)
|
|
272
360
|
}
|
|
273
361
|
})
|
|
274
|
-
|
|
362
|
+
const parent = ancestors[ancestors.length - 1]
|
|
275
363
|
if (parent) {
|
|
276
364
|
if (parent.type === 'document') {
|
|
277
|
-
// console.log(
|
|
278
|
-
// 'its a parent',
|
|
279
|
-
// JSON.stringify({ id, value, pathString, parent }, null, 2)
|
|
280
|
-
// )
|
|
281
365
|
parent.subItems.push({
|
|
282
366
|
type: 'document',
|
|
283
367
|
path: pathString,
|
|
@@ -307,7 +391,12 @@ export const useGraphQLReducer = (
|
|
|
307
391
|
},
|
|
308
392
|
{ values: true }
|
|
309
393
|
)
|
|
310
|
-
return resolveDocument(
|
|
394
|
+
return resolveDocument(
|
|
395
|
+
resolvedDocument,
|
|
396
|
+
template,
|
|
397
|
+
form,
|
|
398
|
+
pathString
|
|
399
|
+
)
|
|
311
400
|
} else {
|
|
312
401
|
existingForm.tinaForm.addQuery(payload.id)
|
|
313
402
|
const { template } = getTemplateForDocument(
|
|
@@ -318,10 +407,19 @@ export const useGraphQLReducer = (
|
|
|
318
407
|
return resolveDocument(
|
|
319
408
|
resolvedDocument,
|
|
320
409
|
template,
|
|
321
|
-
existingForm.tinaForm
|
|
410
|
+
existingForm.tinaForm,
|
|
411
|
+
pathString
|
|
322
412
|
)
|
|
323
413
|
}
|
|
324
414
|
}
|
|
415
|
+
if (typeof value === 'string' && source?._tina_metadata) {
|
|
416
|
+
// FIXME: hack to prevent breaking images
|
|
417
|
+
if (helper) {
|
|
418
|
+
const pathArray = G.responsePathAsArray(info.path)
|
|
419
|
+
|
|
420
|
+
return helper.encode(pathArray.join('.'), value, payload.id)
|
|
421
|
+
}
|
|
422
|
+
}
|
|
325
423
|
return value
|
|
326
424
|
},
|
|
327
425
|
})
|
|
@@ -344,6 +442,32 @@ export const useGraphQLReducer = (
|
|
|
344
442
|
}
|
|
345
443
|
})
|
|
346
444
|
} else {
|
|
445
|
+
if (result.data) {
|
|
446
|
+
setResults((results) => [
|
|
447
|
+
...results,
|
|
448
|
+
{ id: payload.id, data: result.data },
|
|
449
|
+
])
|
|
450
|
+
}
|
|
451
|
+
const activeField = searchParams.get('active-field')
|
|
452
|
+
if (activeField) {
|
|
453
|
+
setSearchParams({})
|
|
454
|
+
const [queryId, eventFieldName] = activeField.split('---')
|
|
455
|
+
if (queryId === payload.id) {
|
|
456
|
+
if (result?.data) {
|
|
457
|
+
cms.dispatch({
|
|
458
|
+
type: 'forms:set-active-field-name',
|
|
459
|
+
value: getFormAndFieldNameFromMetadata(
|
|
460
|
+
result.data,
|
|
461
|
+
eventFieldName
|
|
462
|
+
),
|
|
463
|
+
})
|
|
464
|
+
}
|
|
465
|
+
cms.dispatch({
|
|
466
|
+
type: 'sidebar:set-display-state',
|
|
467
|
+
value: 'openOrFull',
|
|
468
|
+
})
|
|
469
|
+
}
|
|
470
|
+
}
|
|
347
471
|
iframe.current?.contentWindow?.postMessage({
|
|
348
472
|
type: 'updateData',
|
|
349
473
|
id: payload.id,
|
|
@@ -363,24 +487,40 @@ export const useGraphQLReducer = (
|
|
|
363
487
|
[resolvedDocuments.map((doc) => doc._internalSys.path).join('.')]
|
|
364
488
|
)
|
|
365
489
|
|
|
366
|
-
const
|
|
490
|
+
const handleMessage = React.useCallback(
|
|
367
491
|
(event: MessageEvent<PostMessage>) => {
|
|
492
|
+
if (event?.data?.type === 'quick-edit') {
|
|
493
|
+
cms.dispatch({
|
|
494
|
+
type: 'set-quick-editing-supported',
|
|
495
|
+
value: event.data.value,
|
|
496
|
+
})
|
|
497
|
+
}
|
|
368
498
|
if (event?.data?.type === 'isEditMode') {
|
|
369
499
|
iframe?.current?.contentWindow?.postMessage({
|
|
370
500
|
type: 'tina:editMode',
|
|
371
501
|
})
|
|
372
502
|
}
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
503
|
+
if (event.data.type === 'field:selected') {
|
|
504
|
+
const [queryId, eventFieldName] = event.data.fieldName.split('---')
|
|
505
|
+
const result = results.find((res) => res.id === queryId)
|
|
506
|
+
if (result?.data) {
|
|
507
|
+
cms.dispatch({
|
|
508
|
+
type: 'forms:set-active-field-name',
|
|
509
|
+
value: getFormAndFieldNameFromMetadata(result.data, eventFieldName),
|
|
510
|
+
})
|
|
511
|
+
}
|
|
512
|
+
cms.dispatch({
|
|
513
|
+
type: 'sidebar:set-display-state',
|
|
514
|
+
value: 'openOrFull',
|
|
515
|
+
})
|
|
516
|
+
}
|
|
378
517
|
if (event.data.type === 'close') {
|
|
379
518
|
const payloadSchema = z.object({ id: z.string() })
|
|
380
519
|
const { id } = payloadSchema.parse(event.data)
|
|
381
520
|
setPayloads((previous) =>
|
|
382
521
|
previous.filter((payload) => payload.id !== id)
|
|
383
522
|
)
|
|
523
|
+
setResults((previous) => previous.filter((result) => result.id !== id))
|
|
384
524
|
cms.forms.all().map((form) => {
|
|
385
525
|
form.removeQuery(id)
|
|
386
526
|
})
|
|
@@ -401,7 +541,7 @@ export const useGraphQLReducer = (
|
|
|
401
541
|
])
|
|
402
542
|
}
|
|
403
543
|
},
|
|
404
|
-
[cms]
|
|
544
|
+
[cms, JSON.stringify(results)]
|
|
405
545
|
)
|
|
406
546
|
|
|
407
547
|
React.useEffect(() => {
|
|
@@ -415,23 +555,31 @@ export const useGraphQLReducer = (
|
|
|
415
555
|
React.useEffect(() => {
|
|
416
556
|
return () => {
|
|
417
557
|
setPayloads([])
|
|
558
|
+
setResults([])
|
|
418
559
|
cms.removeAllForms()
|
|
419
560
|
cms.dispatch({ type: 'form-lists:clear' })
|
|
420
561
|
}
|
|
421
562
|
}, [url])
|
|
422
563
|
|
|
423
564
|
React.useEffect(() => {
|
|
565
|
+
iframe.current?.contentWindow?.postMessage({
|
|
566
|
+
type: 'quickEditEnabled',
|
|
567
|
+
value: cms.state.quickEditEnabled,
|
|
568
|
+
})
|
|
569
|
+
}, [cms.state.quickEditEnabled])
|
|
570
|
+
|
|
571
|
+
React.useEffect(() => {
|
|
572
|
+
cms.dispatch({ type: 'set-edit-mode', value: 'visual' })
|
|
424
573
|
if (iframe) {
|
|
425
|
-
window.addEventListener('message',
|
|
426
|
-
window.addEventListener('message', notifyEditMode)
|
|
574
|
+
window.addEventListener('message', handleMessage)
|
|
427
575
|
}
|
|
428
576
|
|
|
429
577
|
return () => {
|
|
430
|
-
window.removeEventListener('message',
|
|
431
|
-
window.removeEventListener('message', notifyEditMode)
|
|
578
|
+
window.removeEventListener('message', handleMessage)
|
|
432
579
|
cms.removeAllForms()
|
|
580
|
+
cms.dispatch({ type: 'set-edit-mode', value: 'basic' })
|
|
433
581
|
}
|
|
434
|
-
}, [iframe.current])
|
|
582
|
+
}, [iframe.current, JSON.stringify(results)])
|
|
435
583
|
}
|
|
436
584
|
|
|
437
585
|
const onSubmit = async (
|
|
@@ -469,7 +617,8 @@ type Path = (string | number)[]
|
|
|
469
617
|
const resolveDocument = (
|
|
470
618
|
doc: ResolvedDocument,
|
|
471
619
|
template: Template<true>,
|
|
472
|
-
form: Form
|
|
620
|
+
form: Form,
|
|
621
|
+
pathToDocument: string
|
|
473
622
|
): ResolvedDocument => {
|
|
474
623
|
// @ts-ignore AnyField and TinaField don't mix
|
|
475
624
|
const fields = form.fields as TinaField<true>[]
|
|
@@ -480,6 +629,7 @@ const resolveDocument = (
|
|
|
480
629
|
values: form.values,
|
|
481
630
|
path,
|
|
482
631
|
id,
|
|
632
|
+
pathToDocument,
|
|
483
633
|
})
|
|
484
634
|
const metadataFields: Record<string, string> = {}
|
|
485
635
|
Object.keys(formValues).forEach((key) => {
|
|
@@ -492,7 +642,9 @@ const resolveDocument = (
|
|
|
492
642
|
sys: doc._internalSys,
|
|
493
643
|
values: form.values,
|
|
494
644
|
_tina_metadata: {
|
|
645
|
+
prefix: pathToDocument,
|
|
495
646
|
id: doc._internalSys.path,
|
|
647
|
+
name: '',
|
|
496
648
|
fields: metadataFields,
|
|
497
649
|
},
|
|
498
650
|
_internalSys: doc._internalSys,
|
|
@@ -506,12 +658,14 @@ const resolveFormValue = <T extends Record<string, unknown>>({
|
|
|
506
658
|
values,
|
|
507
659
|
path,
|
|
508
660
|
id,
|
|
661
|
+
pathToDocument,
|
|
509
662
|
}: // tinaSchema,
|
|
510
663
|
{
|
|
511
664
|
fields: TinaField<true>[]
|
|
512
665
|
values: T
|
|
513
666
|
path: Path
|
|
514
667
|
id: string
|
|
668
|
+
pathToDocument: string
|
|
515
669
|
// tinaSchema: TinaSchema
|
|
516
670
|
}): T & { __typename?: string } => {
|
|
517
671
|
const accum: Record<string, unknown> = {}
|
|
@@ -528,6 +682,7 @@ const resolveFormValue = <T extends Record<string, unknown>>({
|
|
|
528
682
|
value: v,
|
|
529
683
|
path,
|
|
530
684
|
id,
|
|
685
|
+
pathToDocument,
|
|
531
686
|
})
|
|
532
687
|
})
|
|
533
688
|
return accum as T & { __typename?: string }
|
|
@@ -537,11 +692,13 @@ const resolveFieldValue = ({
|
|
|
537
692
|
value,
|
|
538
693
|
path,
|
|
539
694
|
id,
|
|
695
|
+
pathToDocument,
|
|
540
696
|
}: {
|
|
541
697
|
field: TinaField<true>
|
|
542
698
|
value: unknown
|
|
543
699
|
path: Path
|
|
544
700
|
id: string
|
|
701
|
+
pathToDocument: string
|
|
545
702
|
}) => {
|
|
546
703
|
switch (field.type) {
|
|
547
704
|
case 'object': {
|
|
@@ -562,13 +719,16 @@ const resolveFieldValue = ({
|
|
|
562
719
|
__typename: NAMER.dataTypeName(template.namespace),
|
|
563
720
|
_tina_metadata: {
|
|
564
721
|
id,
|
|
722
|
+
name: nextPath.join('.'),
|
|
565
723
|
fields: metadataFields,
|
|
724
|
+
prefix: pathToDocument,
|
|
566
725
|
},
|
|
567
726
|
...resolveFormValue({
|
|
568
727
|
fields: template.fields,
|
|
569
728
|
values: item,
|
|
570
729
|
path: nextPath,
|
|
571
730
|
id,
|
|
731
|
+
pathToDocument,
|
|
572
732
|
}),
|
|
573
733
|
}
|
|
574
734
|
})
|
|
@@ -597,13 +757,16 @@ const resolveFieldValue = ({
|
|
|
597
757
|
__typename: NAMER.dataTypeName(field.namespace),
|
|
598
758
|
_tina_metadata: {
|
|
599
759
|
id,
|
|
760
|
+
name: nextPath.join('.'),
|
|
600
761
|
fields: metadataFields,
|
|
762
|
+
prefix: pathToDocument,
|
|
601
763
|
},
|
|
602
764
|
...resolveFormValue({
|
|
603
765
|
fields: templateFields,
|
|
604
766
|
values: item,
|
|
605
|
-
path,
|
|
767
|
+
path: nextPath,
|
|
606
768
|
id,
|
|
769
|
+
pathToDocument,
|
|
607
770
|
}),
|
|
608
771
|
}
|
|
609
772
|
})
|
|
@@ -618,13 +781,16 @@ const resolveFieldValue = ({
|
|
|
618
781
|
__typename: NAMER.dataTypeName(field.namespace),
|
|
619
782
|
_tina_metadata: {
|
|
620
783
|
id,
|
|
784
|
+
name: nextPath.join('.'),
|
|
621
785
|
fields: metadataFields,
|
|
786
|
+
prefix: pathToDocument,
|
|
622
787
|
},
|
|
623
788
|
...resolveFormValue({
|
|
624
789
|
fields: templateFields,
|
|
625
790
|
values: value as any,
|
|
626
|
-
path,
|
|
791
|
+
path: nextPath,
|
|
627
792
|
id,
|
|
793
|
+
pathToDocument,
|
|
628
794
|
}),
|
|
629
795
|
}
|
|
630
796
|
}
|
|
@@ -687,7 +853,7 @@ const expandPayload = async (payload: Payload, cms: TinaCMS) => {
|
|
|
687
853
|
documentNode,
|
|
688
854
|
})
|
|
689
855
|
const expandedQueryForResolver = G.print(expandedDocumentNodeForResolver)
|
|
690
|
-
return { ...payload,
|
|
856
|
+
return { ...payload, expandedQuery, expandedData, expandedQueryForResolver }
|
|
691
857
|
}
|
|
692
858
|
|
|
693
859
|
/**
|
package/src/lib/types.ts
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
|
-
export type PostMessage =
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
1
|
+
export type PostMessage =
|
|
2
|
+
| {
|
|
3
|
+
type: 'open' | 'close' | 'isEditMode'
|
|
4
|
+
id: string
|
|
5
|
+
data: object
|
|
6
|
+
}
|
|
7
|
+
| { type: 'field:selected'; fieldName: string }
|
|
8
|
+
| { type: 'quick-edit'; value: boolean }
|
|
6
9
|
|
|
7
10
|
export type Payload = {
|
|
8
11
|
id: string
|
package/src/lib/util.ts
ADDED
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
const charCodeOfDot = '.'.charCodeAt(0)
|
|
2
|
+
const reEscapeChar = /\\(\\)?/g
|
|
3
|
+
const rePropName = RegExp(
|
|
4
|
+
// Match anything that isn't a dot or bracket.
|
|
5
|
+
'[^.[\\]]+' +
|
|
6
|
+
'|' +
|
|
7
|
+
// Or match property names within brackets.
|
|
8
|
+
'\\[(?:' +
|
|
9
|
+
// Match a non-string expression.
|
|
10
|
+
'([^"\'][^[]*)' +
|
|
11
|
+
'|' +
|
|
12
|
+
// Or match strings (supports escaping characters).
|
|
13
|
+
'(["\'])((?:(?!\\2)[^\\\\]|\\\\.)*?)\\2' +
|
|
14
|
+
')\\]' +
|
|
15
|
+
'|' +
|
|
16
|
+
// Or match "" as the space between consecutive dots or empty brackets.
|
|
17
|
+
'(?=(?:\\.|\\[\\])(?:\\.|\\[\\]|$))',
|
|
18
|
+
'g'
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Converts `string` to a property path array.
|
|
23
|
+
*
|
|
24
|
+
* @private
|
|
25
|
+
* @param {string} string The string to convert.
|
|
26
|
+
* @returns {Array} Returns the property path array.
|
|
27
|
+
*/
|
|
28
|
+
const stringToPath = (string: string) => {
|
|
29
|
+
const result = []
|
|
30
|
+
if (string.charCodeAt(0) === charCodeOfDot) {
|
|
31
|
+
result.push('')
|
|
32
|
+
}
|
|
33
|
+
string.replace(rePropName, (match, expression, quote, subString) => {
|
|
34
|
+
let key = match
|
|
35
|
+
if (quote) {
|
|
36
|
+
key = subString.replace(reEscapeChar, '$1')
|
|
37
|
+
} else if (expression) {
|
|
38
|
+
key = expression.trim()
|
|
39
|
+
}
|
|
40
|
+
result.push(key)
|
|
41
|
+
})
|
|
42
|
+
return result
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const keysCache: { [key: string]: string[] } = {}
|
|
46
|
+
const keysRegex = /[.[\]]+/
|
|
47
|
+
|
|
48
|
+
const toPath = (key: string): string[] => {
|
|
49
|
+
if (key === null || key === undefined || !key.length) {
|
|
50
|
+
return []
|
|
51
|
+
}
|
|
52
|
+
if (typeof key !== 'string') {
|
|
53
|
+
throw new Error('toPath() expects a string')
|
|
54
|
+
}
|
|
55
|
+
if (keysCache[key] == null) {
|
|
56
|
+
/**
|
|
57
|
+
* The following patch fixes issue 456, introduced since v4.20.3:
|
|
58
|
+
*
|
|
59
|
+
* Before v4.20.3, i.e. in v4.20.2, a `key` like 'choices[]' would map to ['choices']
|
|
60
|
+
* (e.g. an array of choices used where 'choices[]' is name attribute of an input of type checkbox).
|
|
61
|
+
*
|
|
62
|
+
* Since v4.20.3, a `key` like 'choices[]' would map to ['choices', ''] which is wrong and breaks
|
|
63
|
+
* this kind of inputs e.g. in React.
|
|
64
|
+
*
|
|
65
|
+
* v4.20.3 introduced an unwanted breaking change, this patch fixes it, see the issue at the link below.
|
|
66
|
+
*
|
|
67
|
+
* @see https://github.com/final-form/final-form/issues/456
|
|
68
|
+
*/
|
|
69
|
+
if (key.endsWith('[]')) {
|
|
70
|
+
// v4.20.2 (a `key` like 'choices[]' should map to ['choices'], which is fine).
|
|
71
|
+
keysCache[key] = key.split(keysRegex).filter(Boolean)
|
|
72
|
+
} else {
|
|
73
|
+
// v4.20.3 (a `key` like 'choices[]' maps to ['choices', ''], which breaks applications relying on inputs like `<input type="checkbox" name="choices[]" />`).
|
|
74
|
+
keysCache[key] = stringToPath(key)
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
return keysCache[key]
|
|
78
|
+
}
|
|
79
|
+
export const getDeepestMetadata = (state: Object, complexKey: string): any => {
|
|
80
|
+
// Intentionally using iteration rather than recursion
|
|
81
|
+
const path = toPath(complexKey)
|
|
82
|
+
let current: any = state
|
|
83
|
+
let metadata: any
|
|
84
|
+
for (let i = 0; i < path.length; i++) {
|
|
85
|
+
const key = path[i]
|
|
86
|
+
if (
|
|
87
|
+
current === undefined ||
|
|
88
|
+
current === null ||
|
|
89
|
+
typeof current !== 'object' ||
|
|
90
|
+
(Array.isArray(current) && isNaN(Number(key)))
|
|
91
|
+
) {
|
|
92
|
+
return undefined
|
|
93
|
+
}
|
|
94
|
+
const value = current[key]
|
|
95
|
+
if (value?._tina_metadata) {
|
|
96
|
+
metadata = value._tina_metadata
|
|
97
|
+
}
|
|
98
|
+
current = value
|
|
99
|
+
}
|
|
100
|
+
return metadata
|
|
101
|
+
}
|
|
102
|
+
export const getFormAndFieldNameFromMetadata = (
|
|
103
|
+
object: object,
|
|
104
|
+
eventFieldName: string
|
|
105
|
+
) => {
|
|
106
|
+
let formId
|
|
107
|
+
let n
|
|
108
|
+
const value = getDeepestMetadata(object, eventFieldName)
|
|
109
|
+
if (value) {
|
|
110
|
+
if (value.prefix) {
|
|
111
|
+
const fieldName = eventFieldName.slice(value?.prefix?.length + 1)
|
|
112
|
+
const localFieldName = value.name
|
|
113
|
+
? fieldName.slice(value?.name?.length + 1)
|
|
114
|
+
: fieldName
|
|
115
|
+
if (localFieldName) {
|
|
116
|
+
n = value.fields[localFieldName]
|
|
117
|
+
} else {
|
|
118
|
+
n = value.name
|
|
119
|
+
}
|
|
120
|
+
formId = value.id
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
return { formId, fieldName: n }
|
|
124
|
+
}
|