@tinacms/app 0.0.0-c1132cd-20241024060747 → 0.0.0-c19d29e-20251224001156
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 +327 -11
- package/index.html +1 -1
- package/package.json +17 -9
- package/src/App.tsx +24 -24
- package/src/Playground.tsx +56 -58
- package/src/dummy-client.ts +1 -1
- package/src/fields/rich-text/index.tsx +2 -2
- package/src/fields/rich-text/monaco/error-message.tsx +59 -59
- package/src/fields/rich-text/monaco/index.tsx +68 -74
- package/src/fields/rich-text/monaco/use-debounce.ts +8 -8
- package/src/global.css +3 -3
- package/src/index.css +24 -15
- package/src/lib/build-form.ts +24 -24
- package/src/lib/errors.tsx +7 -7
- package/src/lib/expand-query.ts +74 -69
- package/src/lib/graphql-reducer.ts +363 -277
- package/src/lib/types.ts +36 -33
- package/src/lib/util.ts +48 -53
- package/src/main.tsx +7 -7
- package/src/preflight.css +10 -10
- package/src/preview.tsx +12 -12
- package/src/vite-env.d.ts +3 -3
|
@@ -1,36 +1,36 @@
|
|
|
1
|
-
import React from 'react'
|
|
2
|
-
import * as G from 'graphql'
|
|
3
|
-
import { getIn } from 'final-form'
|
|
4
|
-
import { z } from 'zod'
|
|
5
1
|
// @ts-expect-error
|
|
6
|
-
import schemaJson from 'SCHEMA_IMPORT'
|
|
7
|
-
import {
|
|
2
|
+
import schemaJson from 'SCHEMA_IMPORT';
|
|
3
|
+
import { getIn } from 'final-form';
|
|
4
|
+
import * as G from 'graphql';
|
|
5
|
+
import React from 'react';
|
|
6
|
+
import { useSearchParams } from 'react-router-dom';
|
|
8
7
|
import {
|
|
8
|
+
Client,
|
|
9
|
+
Collection,
|
|
10
|
+
ErrorDialog,
|
|
9
11
|
Form,
|
|
10
|
-
|
|
12
|
+
FormOptions,
|
|
13
|
+
GlobalFormPlugin,
|
|
11
14
|
NAMER,
|
|
12
|
-
TinaSchema,
|
|
13
|
-
useCMS,
|
|
14
|
-
resolveField,
|
|
15
|
-
Collection,
|
|
16
15
|
Template,
|
|
16
|
+
TinaCMS,
|
|
17
17
|
TinaField,
|
|
18
|
-
|
|
19
|
-
FormOptions,
|
|
20
|
-
GlobalFormPlugin,
|
|
18
|
+
TinaSchema,
|
|
21
19
|
TinaState,
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
20
|
+
resolveField,
|
|
21
|
+
useCMS,
|
|
22
|
+
} from 'tinacms';
|
|
23
|
+
import { z } from 'zod';
|
|
24
|
+
import { FormifyCallback, createForm, createGlobalForm } from './build-form';
|
|
25
|
+
import { showErrorModal } from './errors';
|
|
26
|
+
import { expandQuery, isConnectionType, isNodeType } from './expand-query';
|
|
25
27
|
import type {
|
|
26
|
-
PostMessage,
|
|
27
28
|
Payload,
|
|
28
|
-
|
|
29
|
+
PostMessage,
|
|
29
30
|
ResolvedDocument,
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
import {
|
|
33
|
-
import { showErrorModal } from './errors'
|
|
31
|
+
SystemInfo,
|
|
32
|
+
} from './types';
|
|
33
|
+
import { getFormAndFieldNameFromMetadata } from './util';
|
|
34
34
|
|
|
35
35
|
const sysSchema = z.object({
|
|
36
36
|
breadcrumbs: z.array(z.string()),
|
|
@@ -41,22 +41,23 @@ const sysSchema = z.object({
|
|
|
41
41
|
relativePath: z.string(),
|
|
42
42
|
title: z.string().optional().nullable(),
|
|
43
43
|
template: z.string(),
|
|
44
|
+
hasReferences: z.boolean().optional().nullable(),
|
|
44
45
|
collection: z.object({
|
|
45
46
|
name: z.string(),
|
|
46
47
|
slug: z.string(),
|
|
47
|
-
label: z.string(),
|
|
48
|
+
label: z.string().optional().nullable(),
|
|
48
49
|
path: z.string(),
|
|
49
50
|
format: z.string().optional().nullable(),
|
|
50
51
|
matches: z.string().optional().nullable(),
|
|
51
52
|
}),
|
|
52
|
-
})
|
|
53
|
+
});
|
|
53
54
|
|
|
54
55
|
const documentSchema: z.ZodType<ResolvedDocument> = z.object({
|
|
55
56
|
_internalValues: z.record(z.unknown()),
|
|
56
57
|
_internalSys: sysSchema,
|
|
57
|
-
})
|
|
58
|
+
});
|
|
58
59
|
|
|
59
|
-
const astNode = schemaJson as G.DocumentNode
|
|
60
|
+
const astNode = schemaJson as G.DocumentNode;
|
|
60
61
|
const astNodeWithMeta: G.DocumentNode = {
|
|
61
62
|
...astNode,
|
|
62
63
|
definitions: astNode.definitions.map((def) => {
|
|
@@ -102,7 +103,7 @@ const astNodeWithMeta: G.DocumentNode = {
|
|
|
102
103
|
},
|
|
103
104
|
},
|
|
104
105
|
],
|
|
105
|
-
}
|
|
106
|
+
};
|
|
106
107
|
}
|
|
107
108
|
if (def.kind === 'ObjectTypeDefinition') {
|
|
108
109
|
return {
|
|
@@ -146,68 +147,68 @@ const astNodeWithMeta: G.DocumentNode = {
|
|
|
146
147
|
},
|
|
147
148
|
},
|
|
148
149
|
],
|
|
149
|
-
}
|
|
150
|
+
};
|
|
150
151
|
}
|
|
151
|
-
return def
|
|
152
|
+
return def;
|
|
152
153
|
}),
|
|
153
|
-
}
|
|
154
|
-
const schema = G.buildASTSchema(astNode)
|
|
155
|
-
const schemaForResolver = G.buildASTSchema(astNodeWithMeta)
|
|
154
|
+
};
|
|
155
|
+
const schema = G.buildASTSchema(astNode);
|
|
156
|
+
const schemaForResolver = G.buildASTSchema(astNodeWithMeta);
|
|
156
157
|
|
|
157
158
|
const isRejected = (
|
|
158
159
|
input: PromiseSettledResult<unknown>
|
|
159
|
-
): input is PromiseRejectedResult => input.status === 'rejected'
|
|
160
|
+
): input is PromiseRejectedResult => input.status === 'rejected';
|
|
160
161
|
|
|
161
162
|
const isFulfilled = <T>(
|
|
162
163
|
input: PromiseSettledResult<T>
|
|
163
|
-
): input is PromiseFulfilledResult<T> => input.status === 'fulfilled'
|
|
164
|
+
): input is PromiseFulfilledResult<T> => input.status === 'fulfilled';
|
|
164
165
|
|
|
165
166
|
export const useGraphQLReducer = (
|
|
166
167
|
iframe: React.MutableRefObject<HTMLIFrameElement>,
|
|
167
168
|
url: string
|
|
168
169
|
) => {
|
|
169
|
-
const cms = useCMS()
|
|
170
|
-
const tinaSchema = cms.api.tina.schema as TinaSchema
|
|
171
|
-
const [payloads, setPayloads] = React.useState<Payload[]>([])
|
|
172
|
-
const [requestErrors, setRequestErrors] = React.useState<string[]>([])
|
|
173
|
-
const [searchParams, setSearchParams] = useSearchParams()
|
|
170
|
+
const cms = useCMS();
|
|
171
|
+
const tinaSchema = cms.api.tina.schema as TinaSchema;
|
|
172
|
+
const [payloads, setPayloads] = React.useState<Payload[]>([]);
|
|
173
|
+
const [requestErrors, setRequestErrors] = React.useState<string[]>([]);
|
|
174
|
+
const [searchParams, setSearchParams] = useSearchParams();
|
|
174
175
|
const [results, setResults] = React.useState<
|
|
175
176
|
{
|
|
176
|
-
id: string
|
|
177
|
+
id: string;
|
|
177
178
|
data:
|
|
178
179
|
| {
|
|
179
|
-
[key: string]: any
|
|
180
|
+
[key: string]: any;
|
|
180
181
|
}
|
|
181
182
|
| null
|
|
182
|
-
| undefined
|
|
183
|
+
| undefined;
|
|
183
184
|
}[]
|
|
184
|
-
>([])
|
|
185
|
+
>([]);
|
|
185
186
|
const [documentsToResolve, setDocumentsToResolve] = React.useState<string[]>(
|
|
186
187
|
[]
|
|
187
|
-
)
|
|
188
|
+
);
|
|
188
189
|
const [resolvedDocuments, setResolvedDocuments] = React.useState<
|
|
189
190
|
ResolvedDocument[]
|
|
190
|
-
>([])
|
|
191
|
-
const [operationIndex, setOperationIndex] = React.useState(0)
|
|
191
|
+
>([]);
|
|
192
|
+
const [operationIndex, setOperationIndex] = React.useState(0);
|
|
192
193
|
|
|
193
|
-
const activeField = searchParams.get('active-field')
|
|
194
|
+
const activeField = searchParams.get('active-field');
|
|
194
195
|
|
|
195
196
|
React.useEffect(() => {
|
|
196
197
|
const run = async () => {
|
|
197
198
|
return Promise.all(
|
|
198
199
|
documentsToResolve.map(async (documentId) => {
|
|
199
|
-
return await getDocument(documentId, cms.api.tina)
|
|
200
|
+
return await getDocument(documentId, cms.api.tina);
|
|
200
201
|
})
|
|
201
|
-
)
|
|
202
|
-
}
|
|
202
|
+
);
|
|
203
|
+
};
|
|
203
204
|
if (documentsToResolve.length) {
|
|
204
205
|
run().then((docs) => {
|
|
205
|
-
setResolvedDocuments((resolvedDocs) => [...resolvedDocs, ...docs])
|
|
206
|
-
setDocumentsToResolve([])
|
|
207
|
-
setOperationIndex((i) => i + 1)
|
|
208
|
-
})
|
|
206
|
+
setResolvedDocuments((resolvedDocs) => [...resolvedDocs, ...docs]);
|
|
207
|
+
setDocumentsToResolve([]);
|
|
208
|
+
setOperationIndex((i) => i + 1);
|
|
209
|
+
});
|
|
209
210
|
}
|
|
210
|
-
}, [documentsToResolve.join('.')])
|
|
211
|
+
}, [documentsToResolve.join('.')]);
|
|
211
212
|
|
|
212
213
|
/**
|
|
213
214
|
* Note: since React runs effects twice in development this will run twice for a given query
|
|
@@ -215,39 +216,41 @@ export const useGraphQLReducer = (
|
|
|
215
216
|
*/
|
|
216
217
|
React.useEffect(() => {
|
|
217
218
|
const run = async () => {
|
|
218
|
-
setRequestErrors([])
|
|
219
|
+
setRequestErrors([]);
|
|
219
220
|
// gather the errors and display an error message containing each error unique message
|
|
220
221
|
return Promise.allSettled(
|
|
221
222
|
payloads.map(async (payload) => {
|
|
222
223
|
// This payload has already been expanded, skip it.
|
|
223
224
|
if (payload.expandedQuery) {
|
|
224
|
-
return payload
|
|
225
|
+
return payload;
|
|
225
226
|
} else {
|
|
226
|
-
const expandedPayload = await expandPayload(payload, cms)
|
|
227
|
-
processPayload(expandedPayload)
|
|
228
|
-
return expandedPayload
|
|
227
|
+
const expandedPayload = await expandPayload(payload, cms);
|
|
228
|
+
processPayload(expandedPayload);
|
|
229
|
+
return expandedPayload;
|
|
229
230
|
}
|
|
230
231
|
})
|
|
231
|
-
)
|
|
232
|
-
}
|
|
232
|
+
);
|
|
233
|
+
};
|
|
233
234
|
if (payloads.length) {
|
|
234
235
|
run().then((updatedPayloads) => {
|
|
235
|
-
setPayloads(updatedPayloads.filter(isFulfilled).map((p) => p.value))
|
|
236
|
+
setPayloads(updatedPayloads.filter(isFulfilled).map((p) => p.value));
|
|
236
237
|
setRequestErrors(
|
|
237
238
|
updatedPayloads.filter(isRejected).map((p) => String(p.reason))
|
|
238
|
-
)
|
|
239
|
-
})
|
|
239
|
+
);
|
|
240
|
+
});
|
|
240
241
|
}
|
|
241
|
-
}, [JSON.stringify(payloads), cms])
|
|
242
|
+
}, [JSON.stringify(payloads), cms]);
|
|
242
243
|
|
|
243
244
|
const processPayload = React.useCallback(
|
|
244
245
|
(payload: Payload) => {
|
|
245
|
-
const { expandedQueryForResolver, variables, expandedData } = payload
|
|
246
|
+
const { expandedQueryForResolver, variables, expandedData } = payload;
|
|
246
247
|
if (!expandedQueryForResolver || !expandedData) {
|
|
247
|
-
throw new Error(
|
|
248
|
+
throw new Error(
|
|
249
|
+
`Unable to process payload which has not been expanded`
|
|
250
|
+
);
|
|
248
251
|
}
|
|
249
|
-
const formListItems: TinaState['formLists'][number]['items'] = []
|
|
250
|
-
const formIds: string[] = []
|
|
252
|
+
const formListItems: TinaState['formLists'][number]['items'] = [];
|
|
253
|
+
const formIds: string[] = [];
|
|
251
254
|
|
|
252
255
|
const result = G.graphqlSync({
|
|
253
256
|
schema: schemaForResolver,
|
|
@@ -255,7 +258,7 @@ export const useGraphQLReducer = (
|
|
|
255
258
|
variableValues: variables,
|
|
256
259
|
rootValue: expandedData,
|
|
257
260
|
fieldResolver: (source, args, context, info) => {
|
|
258
|
-
const fieldName = info.fieldName
|
|
261
|
+
const fieldName = info.fieldName;
|
|
259
262
|
/**
|
|
260
263
|
* Since the `source` for this resolver is the query that
|
|
261
264
|
* ran before passing it into `useTina`, we need to take aliases
|
|
@@ -264,35 +267,35 @@ export const useGraphQLReducer = (
|
|
|
264
267
|
* solution as the `value` gets overwritten depending on the alias
|
|
265
268
|
* query.
|
|
266
269
|
*/
|
|
267
|
-
const aliases: string[] = []
|
|
270
|
+
const aliases: string[] = [];
|
|
268
271
|
info.fieldNodes.forEach((fieldNode) => {
|
|
269
272
|
if (fieldNode.alias) {
|
|
270
|
-
aliases.push(fieldNode.alias.value)
|
|
273
|
+
aliases.push(fieldNode.alias.value);
|
|
271
274
|
}
|
|
272
|
-
})
|
|
273
|
-
let value = source[fieldName] as unknown
|
|
275
|
+
});
|
|
276
|
+
let value = source[fieldName] as unknown;
|
|
274
277
|
aliases.forEach((alias) => {
|
|
275
|
-
const aliasValue = source[alias]
|
|
278
|
+
const aliasValue = source[alias];
|
|
276
279
|
if (aliasValue) {
|
|
277
|
-
value = aliasValue
|
|
280
|
+
value = aliasValue;
|
|
278
281
|
}
|
|
279
|
-
})
|
|
282
|
+
});
|
|
280
283
|
if (fieldName === '_sys') {
|
|
281
|
-
return source._internalSys
|
|
284
|
+
return source._internalSys;
|
|
282
285
|
}
|
|
283
286
|
if (fieldName === '_values') {
|
|
284
|
-
return source._internalValues
|
|
287
|
+
return source._internalValues;
|
|
285
288
|
}
|
|
286
289
|
if (info.fieldName === '_content_source') {
|
|
287
|
-
const pathArray = G.responsePathAsArray(info.path)
|
|
290
|
+
const pathArray = G.responsePathAsArray(info.path);
|
|
288
291
|
return {
|
|
289
292
|
queryId: payload.id,
|
|
290
293
|
path: pathArray.slice(0, pathArray.length - 1),
|
|
291
|
-
}
|
|
294
|
+
};
|
|
292
295
|
}
|
|
293
296
|
if (info.fieldName === '_tina_metadata') {
|
|
294
297
|
if (value) {
|
|
295
|
-
return value
|
|
298
|
+
return value;
|
|
296
299
|
}
|
|
297
300
|
// TODO: ensure all fields that have _tina_metadata
|
|
298
301
|
// actually need it
|
|
@@ -300,77 +303,80 @@ export const useGraphQLReducer = (
|
|
|
300
303
|
id: null,
|
|
301
304
|
fields: [],
|
|
302
305
|
prefix: '',
|
|
303
|
-
}
|
|
306
|
+
};
|
|
304
307
|
}
|
|
308
|
+
|
|
305
309
|
if (isConnectionType(info.returnType)) {
|
|
306
|
-
const name = G.getNamedType(info.returnType).name
|
|
310
|
+
const name = G.getNamedType(info.returnType).name;
|
|
307
311
|
const connectionCollection = tinaSchema
|
|
308
312
|
.getCollections()
|
|
309
313
|
.find((collection) => {
|
|
310
314
|
const collectionName = NAMER.referenceConnectionType(
|
|
311
315
|
collection.namespace
|
|
312
|
-
)
|
|
316
|
+
);
|
|
313
317
|
if (collectionName === name) {
|
|
314
|
-
return true
|
|
318
|
+
return true;
|
|
315
319
|
}
|
|
316
|
-
return false
|
|
317
|
-
})
|
|
320
|
+
return false;
|
|
321
|
+
});
|
|
318
322
|
if (connectionCollection) {
|
|
319
323
|
formListItems.push({
|
|
320
324
|
type: 'list',
|
|
321
325
|
label: connectionCollection.label || connectionCollection.name,
|
|
322
|
-
})
|
|
326
|
+
});
|
|
323
327
|
}
|
|
324
328
|
}
|
|
325
329
|
if (isNodeType(info.returnType)) {
|
|
326
330
|
if (!value) {
|
|
327
|
-
return
|
|
331
|
+
return;
|
|
328
332
|
}
|
|
329
|
-
let resolvedDocument: ResolvedDocument
|
|
333
|
+
let resolvedDocument: ResolvedDocument;
|
|
330
334
|
// This is a reference from another form
|
|
331
335
|
if (typeof value === 'string') {
|
|
332
336
|
const valueFromSetup = getIn(
|
|
333
337
|
expandedData,
|
|
334
338
|
G.responsePathAsArray(info.path).join('.')
|
|
335
|
-
)
|
|
339
|
+
);
|
|
336
340
|
const maybeResolvedDocument = resolvedDocuments.find(
|
|
337
341
|
(doc) => doc._internalSys.path === value
|
|
338
|
-
)
|
|
342
|
+
);
|
|
343
|
+
|
|
339
344
|
// If we already have this document, use it.
|
|
340
345
|
if (maybeResolvedDocument) {
|
|
341
|
-
resolvedDocument = maybeResolvedDocument
|
|
346
|
+
resolvedDocument = maybeResolvedDocument;
|
|
342
347
|
} else if (valueFromSetup) {
|
|
343
348
|
// Else, even though in this context the value is a string because it's
|
|
344
349
|
// resolved from a parent form, if the reference hasn't changed
|
|
345
350
|
// from when we ran the setup query, we can avoid a data fetch
|
|
346
351
|
// here and just grab it from the response
|
|
347
352
|
const maybeResolvedDocument =
|
|
348
|
-
documentSchema.parse(valueFromSetup)
|
|
353
|
+
documentSchema.parse(valueFromSetup);
|
|
354
|
+
|
|
349
355
|
if (maybeResolvedDocument._internalSys.path === value) {
|
|
350
|
-
resolvedDocument = maybeResolvedDocument
|
|
356
|
+
resolvedDocument = maybeResolvedDocument;
|
|
351
357
|
} else {
|
|
352
|
-
throw new NoFormError(`No form found`, value)
|
|
358
|
+
throw new NoFormError(`No form found`, value);
|
|
353
359
|
}
|
|
354
360
|
} else {
|
|
355
|
-
throw new NoFormError(`No form found`, value)
|
|
361
|
+
throw new NoFormError(`No form found`, value);
|
|
356
362
|
}
|
|
357
363
|
} else {
|
|
358
|
-
resolvedDocument = documentSchema.parse(value)
|
|
364
|
+
resolvedDocument = documentSchema.parse(value);
|
|
359
365
|
}
|
|
360
|
-
const id = resolvedDocument._internalSys.path
|
|
361
|
-
formIds.push(id)
|
|
366
|
+
const id = resolvedDocument._internalSys.path;
|
|
367
|
+
formIds.push(id);
|
|
362
368
|
const existingForm = cms.state.forms.find(
|
|
363
369
|
(f) => f.tinaForm.id === id
|
|
364
|
-
)
|
|
370
|
+
);
|
|
365
371
|
|
|
366
|
-
const pathArray = G.responsePathAsArray(info.path)
|
|
367
|
-
const pathString = pathArray.join('.')
|
|
372
|
+
const pathArray = G.responsePathAsArray(info.path);
|
|
373
|
+
const pathString = pathArray.join('.');
|
|
368
374
|
const ancestors = formListItems.filter((item) => {
|
|
369
375
|
if (item.type === 'document') {
|
|
370
|
-
return pathString.startsWith(item.path)
|
|
376
|
+
return pathString.startsWith(item.path);
|
|
371
377
|
}
|
|
372
|
-
})
|
|
373
|
-
const parent = ancestors[ancestors.length - 1]
|
|
378
|
+
});
|
|
379
|
+
const parent = ancestors[ancestors.length - 1];
|
|
374
380
|
if (parent) {
|
|
375
381
|
if (parent.type === 'document') {
|
|
376
382
|
parent.subItems.push({
|
|
@@ -378,7 +384,7 @@ export const useGraphQLReducer = (
|
|
|
378
384
|
path: pathString,
|
|
379
385
|
formId: id,
|
|
380
386
|
subItems: [],
|
|
381
|
-
})
|
|
387
|
+
});
|
|
382
388
|
}
|
|
383
389
|
} else {
|
|
384
390
|
formListItems.push({
|
|
@@ -386,7 +392,7 @@ export const useGraphQLReducer = (
|
|
|
386
392
|
path: pathString,
|
|
387
393
|
formId: id,
|
|
388
394
|
subItems: [],
|
|
389
|
-
})
|
|
395
|
+
});
|
|
390
396
|
}
|
|
391
397
|
|
|
392
398
|
if (!existingForm) {
|
|
@@ -395,65 +401,65 @@ export const useGraphQLReducer = (
|
|
|
395
401
|
tinaSchema,
|
|
396
402
|
payloadId: payload.id,
|
|
397
403
|
cms,
|
|
398
|
-
})
|
|
404
|
+
});
|
|
399
405
|
form.subscribe(
|
|
400
406
|
() => {
|
|
401
|
-
setOperationIndex((i) => i + 1)
|
|
407
|
+
setOperationIndex((i) => i + 1);
|
|
402
408
|
},
|
|
403
409
|
{ values: true }
|
|
404
|
-
)
|
|
410
|
+
);
|
|
405
411
|
return resolveDocument(
|
|
406
412
|
resolvedDocument,
|
|
407
413
|
template,
|
|
408
414
|
form,
|
|
409
415
|
pathString
|
|
410
|
-
)
|
|
416
|
+
);
|
|
411
417
|
} else {
|
|
412
|
-
existingForm.tinaForm.addQuery(payload.id)
|
|
418
|
+
existingForm.tinaForm.addQuery(payload.id);
|
|
413
419
|
const { template } = getTemplateForDocument(
|
|
414
420
|
resolvedDocument,
|
|
415
421
|
tinaSchema
|
|
416
|
-
)
|
|
417
|
-
existingForm.tinaForm.addQuery(payload.id)
|
|
422
|
+
);
|
|
423
|
+
existingForm.tinaForm.addQuery(payload.id);
|
|
418
424
|
return resolveDocument(
|
|
419
425
|
resolvedDocument,
|
|
420
426
|
template,
|
|
421
427
|
existingForm.tinaForm,
|
|
422
428
|
pathString
|
|
423
|
-
)
|
|
429
|
+
);
|
|
424
430
|
}
|
|
425
431
|
}
|
|
426
|
-
return value
|
|
432
|
+
return value;
|
|
427
433
|
},
|
|
428
|
-
})
|
|
434
|
+
});
|
|
429
435
|
if (result.errors) {
|
|
430
436
|
result.errors.forEach((error) => {
|
|
431
437
|
if (
|
|
432
438
|
error instanceof G.GraphQLError &&
|
|
433
439
|
error.originalError instanceof NoFormError
|
|
434
440
|
) {
|
|
435
|
-
const id = error.originalError.id
|
|
441
|
+
const id = error.originalError.id;
|
|
436
442
|
setDocumentsToResolve((docs) => [
|
|
437
443
|
...docs.filter((doc) => doc !== id),
|
|
438
444
|
id,
|
|
439
|
-
])
|
|
445
|
+
]);
|
|
440
446
|
} else {
|
|
441
|
-
console.log(error)
|
|
447
|
+
console.log(error);
|
|
442
448
|
// throw new Error(
|
|
443
449
|
// `Error processing value change, please contact support`
|
|
444
450
|
// )
|
|
445
451
|
}
|
|
446
|
-
})
|
|
452
|
+
});
|
|
447
453
|
} else {
|
|
448
454
|
if (result.data) {
|
|
449
455
|
setResults((results) => [
|
|
450
456
|
...results.filter((result) => result.id !== payload.id),
|
|
451
457
|
{ id: payload.id, data: result.data },
|
|
452
|
-
])
|
|
458
|
+
]);
|
|
453
459
|
}
|
|
454
460
|
if (activeField) {
|
|
455
|
-
setSearchParams({})
|
|
456
|
-
const [queryId, eventFieldName] = activeField.split('---')
|
|
461
|
+
setSearchParams({});
|
|
462
|
+
const [queryId, eventFieldName] = activeField.split('---');
|
|
457
463
|
if (queryId === payload.id) {
|
|
458
464
|
if (result?.data) {
|
|
459
465
|
cms.dispatch({
|
|
@@ -462,19 +468,19 @@ export const useGraphQLReducer = (
|
|
|
462
468
|
result.data,
|
|
463
469
|
eventFieldName
|
|
464
470
|
),
|
|
465
|
-
})
|
|
471
|
+
});
|
|
466
472
|
}
|
|
467
473
|
cms.dispatch({
|
|
468
474
|
type: 'sidebar:set-display-state',
|
|
469
475
|
value: 'openOrFull',
|
|
470
|
-
})
|
|
476
|
+
});
|
|
471
477
|
}
|
|
472
478
|
}
|
|
473
479
|
iframe.current?.contentWindow?.postMessage({
|
|
474
480
|
type: 'updateData',
|
|
475
481
|
id: payload.id,
|
|
476
482
|
data: result.data,
|
|
477
|
-
})
|
|
483
|
+
});
|
|
478
484
|
}
|
|
479
485
|
cms.dispatch({
|
|
480
486
|
type: 'form-lists:add',
|
|
@@ -484,57 +490,96 @@ export const useGraphQLReducer = (
|
|
|
484
490
|
items: formListItems,
|
|
485
491
|
formIds,
|
|
486
492
|
},
|
|
487
|
-
})
|
|
493
|
+
});
|
|
488
494
|
},
|
|
489
495
|
[
|
|
490
496
|
resolvedDocuments.map((doc) => doc._internalSys.path).join('.'),
|
|
491
497
|
activeField,
|
|
492
498
|
]
|
|
493
|
-
)
|
|
499
|
+
);
|
|
494
500
|
|
|
495
501
|
const handleMessage = React.useCallback(
|
|
496
502
|
(event: MessageEvent<PostMessage>) => {
|
|
503
|
+
if (event.data.type === 'user-select-form') {
|
|
504
|
+
cms.dispatch({
|
|
505
|
+
type: 'forms:set-active-form-id',
|
|
506
|
+
value: event.data.formId,
|
|
507
|
+
});
|
|
508
|
+
}
|
|
509
|
+
|
|
497
510
|
if (event?.data?.type === 'quick-edit') {
|
|
498
511
|
cms.dispatch({
|
|
499
512
|
type: 'set-quick-editing-supported',
|
|
500
513
|
value: event.data.value,
|
|
501
|
-
})
|
|
514
|
+
});
|
|
502
515
|
iframe.current?.contentWindow?.postMessage({
|
|
503
516
|
type: 'quickEditEnabled',
|
|
504
517
|
value: cms.state.sidebarDisplayState === 'open',
|
|
505
|
-
})
|
|
518
|
+
});
|
|
506
519
|
}
|
|
507
520
|
if (event?.data?.type === 'isEditMode') {
|
|
508
521
|
iframe?.current?.contentWindow?.postMessage({
|
|
509
522
|
type: 'tina:editMode',
|
|
510
|
-
})
|
|
523
|
+
});
|
|
511
524
|
}
|
|
512
525
|
if (event.data.type === 'field:selected') {
|
|
513
|
-
const [queryId, eventFieldName] = event.data.fieldName.split('---')
|
|
514
|
-
const result = results.find((res) => res.id === queryId)
|
|
526
|
+
const [queryId, eventFieldName] = event.data.fieldName.split('---');
|
|
527
|
+
const result = results.find((res) => res.id === queryId);
|
|
515
528
|
if (result?.data) {
|
|
529
|
+
const { formId, fieldName } = getFormAndFieldNameFromMetadata(
|
|
530
|
+
result.data,
|
|
531
|
+
eventFieldName
|
|
532
|
+
);
|
|
516
533
|
cms.dispatch({
|
|
517
534
|
type: 'forms:set-active-field-name',
|
|
518
|
-
value:
|
|
519
|
-
})
|
|
535
|
+
value: { formId: formId, fieldName: fieldName },
|
|
536
|
+
});
|
|
537
|
+
cms.events.dispatch({
|
|
538
|
+
...event.data,
|
|
539
|
+
type: 'field:focus',
|
|
540
|
+
});
|
|
520
541
|
}
|
|
521
542
|
cms.dispatch({
|
|
522
543
|
type: 'sidebar:set-display-state',
|
|
523
544
|
value: 'openOrFull',
|
|
524
|
-
})
|
|
545
|
+
});
|
|
546
|
+
}
|
|
547
|
+
if (event.data.type === 'field:hovered') {
|
|
548
|
+
if (event.data.fieldName) {
|
|
549
|
+
const [queryId, eventFieldName] = event.data.fieldName.split('---');
|
|
550
|
+
const result = results.find((res) => res.id === queryId);
|
|
551
|
+
if (result?.data) {
|
|
552
|
+
const fieldData = getFormAndFieldNameFromMetadata(
|
|
553
|
+
result.data,
|
|
554
|
+
eventFieldName
|
|
555
|
+
);
|
|
556
|
+
cms.dispatch({
|
|
557
|
+
type: 'forms:set-hovered-field-name',
|
|
558
|
+
value: fieldData,
|
|
559
|
+
});
|
|
560
|
+
}
|
|
561
|
+
} else {
|
|
562
|
+
// Clear hover state when fieldName is null
|
|
563
|
+
cms.forms.all().forEach((form) => {
|
|
564
|
+
cms.dispatch({
|
|
565
|
+
type: 'forms:set-hovered-field-name',
|
|
566
|
+
value: { formId: form.id, fieldName: null },
|
|
567
|
+
});
|
|
568
|
+
});
|
|
569
|
+
}
|
|
525
570
|
}
|
|
526
571
|
if (event.data.type === 'close') {
|
|
527
|
-
const payloadSchema = z.object({ id: z.string() })
|
|
528
|
-
const { id } = payloadSchema.parse(event.data)
|
|
572
|
+
const payloadSchema = z.object({ id: z.string() });
|
|
573
|
+
const { id } = payloadSchema.parse(event.data);
|
|
529
574
|
setPayloads((previous) =>
|
|
530
575
|
previous.filter((payload) => payload.id !== id)
|
|
531
|
-
)
|
|
532
|
-
setResults((previous) => previous.filter((result) => result.id !== id))
|
|
576
|
+
);
|
|
577
|
+
setResults((previous) => previous.filter((result) => result.id !== id));
|
|
533
578
|
cms.forms.all().map((form) => {
|
|
534
|
-
form.removeQuery(id)
|
|
535
|
-
})
|
|
536
|
-
cms.removeOrphanedForms()
|
|
537
|
-
cms.dispatch({ type: 'form-lists:remove', value: id })
|
|
579
|
+
form.removeQuery(id);
|
|
580
|
+
});
|
|
581
|
+
cms.removeOrphanedForms();
|
|
582
|
+
cms.dispatch({ type: 'form-lists:remove', value: id });
|
|
538
583
|
}
|
|
539
584
|
if (event.data.type === 'open') {
|
|
540
585
|
const payloadSchema = z.object({
|
|
@@ -542,60 +587,95 @@ export const useGraphQLReducer = (
|
|
|
542
587
|
query: z.string(),
|
|
543
588
|
variables: z.record(z.unknown()),
|
|
544
589
|
data: z.record(z.unknown()),
|
|
545
|
-
})
|
|
546
|
-
const payload = payloadSchema.parse(event.data)
|
|
590
|
+
});
|
|
591
|
+
const payload = payloadSchema.parse(event.data);
|
|
547
592
|
setPayloads((payloads) => [
|
|
548
593
|
...payloads.filter(({ id }) => id !== payload.id),
|
|
549
594
|
payload,
|
|
550
|
-
])
|
|
595
|
+
]);
|
|
551
596
|
}
|
|
597
|
+
// TODO: This is causing a webpack HMR issue - look into refactoring this logic
|
|
598
|
+
// if (event.data.type === 'url-changed') {
|
|
599
|
+
// console.log('[EVENT_TRIGGERED] url-changed: ', event);
|
|
600
|
+
// cms.dispatch({
|
|
601
|
+
// type: 'sidebar:set-loading-state',
|
|
602
|
+
// value: true,
|
|
603
|
+
// });
|
|
604
|
+
// }
|
|
552
605
|
},
|
|
553
606
|
[cms, JSON.stringify(results)]
|
|
554
|
-
)
|
|
607
|
+
);
|
|
555
608
|
|
|
556
609
|
React.useEffect(() => {
|
|
557
610
|
payloads.forEach((payload) => {
|
|
558
611
|
if (payload.expandedData) {
|
|
559
|
-
processPayload(payload)
|
|
612
|
+
processPayload(payload);
|
|
560
613
|
}
|
|
561
|
-
})
|
|
562
|
-
}, [operationIndex])
|
|
614
|
+
});
|
|
615
|
+
}, [operationIndex]);
|
|
563
616
|
|
|
564
617
|
React.useEffect(() => {
|
|
565
618
|
return () => {
|
|
566
|
-
setPayloads([])
|
|
567
|
-
setResults([])
|
|
568
|
-
cms.removeAllForms()
|
|
569
|
-
cms.dispatch({ type: 'form-lists:clear' })
|
|
570
|
-
}
|
|
571
|
-
}, [url])
|
|
619
|
+
setPayloads([]);
|
|
620
|
+
setResults([]);
|
|
621
|
+
cms.removeAllForms();
|
|
622
|
+
cms.dispatch({ type: 'form-lists:clear' });
|
|
623
|
+
};
|
|
624
|
+
}, [url]);
|
|
572
625
|
|
|
573
626
|
React.useEffect(() => {
|
|
574
627
|
iframe.current?.contentWindow?.postMessage({
|
|
575
628
|
type: 'quickEditEnabled',
|
|
576
629
|
value: cms.state.sidebarDisplayState === 'open',
|
|
577
|
-
})
|
|
578
|
-
}, [cms.state.sidebarDisplayState])
|
|
630
|
+
});
|
|
631
|
+
}, [cms.state.sidebarDisplayState]);
|
|
632
|
+
|
|
633
|
+
// Compute the active field name to send to iframe
|
|
634
|
+
const activeFieldName = React.useMemo(() => {
|
|
635
|
+
const activeForm = cms.state.forms.find(
|
|
636
|
+
(form: any) => form.tinaForm.id === cms.state.activeFormId
|
|
637
|
+
);
|
|
638
|
+
if (!activeForm) {
|
|
639
|
+
return null;
|
|
640
|
+
}
|
|
641
|
+
const fieldName = activeForm.activeFieldName;
|
|
642
|
+
if (fieldName === null) {
|
|
643
|
+
return null;
|
|
644
|
+
}
|
|
645
|
+
const queries = activeForm.tinaForm.queries;
|
|
646
|
+
if (queries && queries.length > 0) {
|
|
647
|
+
const queryId = queries[queries.length - 1];
|
|
648
|
+
return `${queryId}---${fieldName}`;
|
|
649
|
+
}
|
|
650
|
+
return null;
|
|
651
|
+
}, [cms.state.forms, cms.state.activeFormId]);
|
|
652
|
+
|
|
653
|
+
React.useEffect(() => {
|
|
654
|
+
iframe.current?.contentWindow?.postMessage({
|
|
655
|
+
type: 'field:set-focused',
|
|
656
|
+
fieldName: activeFieldName,
|
|
657
|
+
});
|
|
658
|
+
}, [activeFieldName, iframe]);
|
|
579
659
|
|
|
580
660
|
React.useEffect(() => {
|
|
581
|
-
cms.dispatch({ type: 'set-edit-mode', value: 'visual' })
|
|
661
|
+
cms.dispatch({ type: 'set-edit-mode', value: 'visual' });
|
|
582
662
|
if (iframe) {
|
|
583
|
-
window.addEventListener('message', handleMessage)
|
|
663
|
+
window.addEventListener('message', handleMessage);
|
|
584
664
|
}
|
|
585
665
|
|
|
586
666
|
return () => {
|
|
587
|
-
window.removeEventListener('message', handleMessage)
|
|
588
|
-
cms.removeAllForms()
|
|
589
|
-
cms.dispatch({ type: 'set-edit-mode', value: 'basic' })
|
|
590
|
-
}
|
|
591
|
-
}, [iframe.current, JSON.stringify(results)])
|
|
667
|
+
window.removeEventListener('message', handleMessage);
|
|
668
|
+
cms.removeAllForms();
|
|
669
|
+
cms.dispatch({ type: 'set-edit-mode', value: 'basic' });
|
|
670
|
+
};
|
|
671
|
+
}, [iframe.current, JSON.stringify(results)]);
|
|
592
672
|
|
|
593
673
|
React.useEffect(() => {
|
|
594
674
|
if (requestErrors.length) {
|
|
595
|
-
showErrorModal('Unexpected error querying content', requestErrors, cms)
|
|
675
|
+
showErrorModal('Unexpected error querying content', requestErrors, cms);
|
|
596
676
|
}
|
|
597
|
-
}, [requestErrors])
|
|
598
|
-
}
|
|
677
|
+
}, [requestErrors]);
|
|
678
|
+
};
|
|
599
679
|
|
|
600
680
|
const onSubmit = async (
|
|
601
681
|
collection: Collection<true>,
|
|
@@ -603,7 +683,7 @@ const onSubmit = async (
|
|
|
603
683
|
payload: Record<string, unknown>,
|
|
604
684
|
cms: TinaCMS
|
|
605
685
|
) => {
|
|
606
|
-
const tinaSchema = cms.api.tina.schema
|
|
686
|
+
const tinaSchema = cms.api.tina.schema;
|
|
607
687
|
try {
|
|
608
688
|
const mutationString = `#graphql
|
|
609
689
|
mutation UpdateDocument($collection: String!, $relativePath: String!, $params: DocumentUpdateMutation!) {
|
|
@@ -611,7 +691,7 @@ const onSubmit = async (
|
|
|
611
691
|
__typename
|
|
612
692
|
}
|
|
613
693
|
}
|
|
614
|
-
|
|
694
|
+
`;
|
|
615
695
|
|
|
616
696
|
await cms.api.tina.request(mutationString, {
|
|
617
697
|
variables: {
|
|
@@ -619,8 +699,8 @@ const onSubmit = async (
|
|
|
619
699
|
relativePath: relativePath,
|
|
620
700
|
params: tinaSchema.transformPayload(collection.name, payload),
|
|
621
701
|
},
|
|
622
|
-
})
|
|
623
|
-
cms.alerts.success('Document saved!')
|
|
702
|
+
});
|
|
703
|
+
cms.alerts.success('Document saved!');
|
|
624
704
|
} catch (e) {
|
|
625
705
|
cms.alerts.error(() =>
|
|
626
706
|
ErrorDialog({
|
|
@@ -628,12 +708,12 @@ const onSubmit = async (
|
|
|
628
708
|
message: 'Tina caught an error while updating the page',
|
|
629
709
|
error: e,
|
|
630
710
|
})
|
|
631
|
-
)
|
|
632
|
-
console.error(e)
|
|
711
|
+
);
|
|
712
|
+
console.error(e);
|
|
633
713
|
}
|
|
634
|
-
}
|
|
714
|
+
};
|
|
635
715
|
|
|
636
|
-
type Path = (string | number)[]
|
|
716
|
+
type Path = (string | number)[];
|
|
637
717
|
|
|
638
718
|
const resolveDocument = (
|
|
639
719
|
doc: ResolvedDocument,
|
|
@@ -642,20 +722,20 @@ const resolveDocument = (
|
|
|
642
722
|
pathToDocument: string
|
|
643
723
|
): ResolvedDocument => {
|
|
644
724
|
// @ts-ignore AnyField and TinaField don't mix
|
|
645
|
-
const fields = form.fields as TinaField<true>[]
|
|
646
|
-
const id = doc._internalSys.path
|
|
647
|
-
const path: Path = []
|
|
725
|
+
const fields = form.fields as TinaField<true>[];
|
|
726
|
+
const id = doc._internalSys.path;
|
|
727
|
+
const path: Path = [];
|
|
648
728
|
const formValues = resolveFormValue({
|
|
649
729
|
fields: fields,
|
|
650
730
|
values: form.values,
|
|
651
731
|
path,
|
|
652
732
|
id,
|
|
653
733
|
pathToDocument,
|
|
654
|
-
})
|
|
655
|
-
const metadataFields: Record<string, string> = {}
|
|
734
|
+
});
|
|
735
|
+
const metadataFields: Record<string, string> = {};
|
|
656
736
|
Object.keys(formValues).forEach((key) => {
|
|
657
|
-
metadataFields[key] = [...path, key].join('.')
|
|
658
|
-
})
|
|
737
|
+
metadataFields[key] = [...path, key].join('.');
|
|
738
|
+
});
|
|
659
739
|
|
|
660
740
|
return {
|
|
661
741
|
...formValues,
|
|
@@ -671,8 +751,8 @@ const resolveDocument = (
|
|
|
671
751
|
_internalSys: doc._internalSys,
|
|
672
752
|
_internalValues: doc._internalValues,
|
|
673
753
|
__typename: NAMER.dataTypeName(template.namespace),
|
|
674
|
-
}
|
|
675
|
-
}
|
|
754
|
+
};
|
|
755
|
+
};
|
|
676
756
|
|
|
677
757
|
const resolveFormValue = <T extends Record<string, unknown>>({
|
|
678
758
|
fields,
|
|
@@ -682,21 +762,21 @@ const resolveFormValue = <T extends Record<string, unknown>>({
|
|
|
682
762
|
pathToDocument,
|
|
683
763
|
}: // tinaSchema,
|
|
684
764
|
{
|
|
685
|
-
fields: TinaField<true>[]
|
|
686
|
-
values: T
|
|
687
|
-
path: Path
|
|
688
|
-
id: string
|
|
689
|
-
pathToDocument: string
|
|
765
|
+
fields: TinaField<true>[];
|
|
766
|
+
values: T;
|
|
767
|
+
path: Path;
|
|
768
|
+
id: string;
|
|
769
|
+
pathToDocument: string;
|
|
690
770
|
// tinaSchema: TinaSchema
|
|
691
771
|
}): T & { __typename?: string } => {
|
|
692
|
-
const accum: Record<string, unknown> = {}
|
|
772
|
+
const accum: Record<string, unknown> = {};
|
|
693
773
|
fields.forEach((field) => {
|
|
694
|
-
const v = values[field.name]
|
|
774
|
+
const v = values[field.name];
|
|
695
775
|
if (typeof v === 'undefined') {
|
|
696
|
-
return
|
|
776
|
+
return;
|
|
697
777
|
}
|
|
698
778
|
if (v === null) {
|
|
699
|
-
return
|
|
779
|
+
return;
|
|
700
780
|
}
|
|
701
781
|
accum[field.name] = resolveFieldValue({
|
|
702
782
|
field,
|
|
@@ -704,10 +784,10 @@ const resolveFormValue = <T extends Record<string, unknown>>({
|
|
|
704
784
|
path,
|
|
705
785
|
id,
|
|
706
786
|
pathToDocument,
|
|
707
|
-
})
|
|
708
|
-
})
|
|
709
|
-
return accum as T & { __typename?: string }
|
|
710
|
-
}
|
|
787
|
+
});
|
|
788
|
+
});
|
|
789
|
+
return accum as T & { __typename?: string };
|
|
790
|
+
};
|
|
711
791
|
const resolveFieldValue = ({
|
|
712
792
|
field,
|
|
713
793
|
value,
|
|
@@ -715,11 +795,11 @@ const resolveFieldValue = ({
|
|
|
715
795
|
id,
|
|
716
796
|
pathToDocument,
|
|
717
797
|
}: {
|
|
718
|
-
field: TinaField<true
|
|
719
|
-
value: unknown
|
|
720
|
-
path: Path
|
|
721
|
-
id: string
|
|
722
|
-
pathToDocument: string
|
|
798
|
+
field: TinaField<true>;
|
|
799
|
+
value: unknown;
|
|
800
|
+
path: Path;
|
|
801
|
+
id: string;
|
|
802
|
+
pathToDocument: string;
|
|
723
803
|
}) => {
|
|
724
804
|
switch (field.type) {
|
|
725
805
|
case 'object': {
|
|
@@ -727,15 +807,17 @@ const resolveFieldValue = ({
|
|
|
727
807
|
if (field.list) {
|
|
728
808
|
if (Array.isArray(value)) {
|
|
729
809
|
return value.map((item, index) => {
|
|
730
|
-
const template = field.templates[item._template]
|
|
810
|
+
const template = field.templates[item._template];
|
|
731
811
|
if (typeof template === 'string') {
|
|
732
|
-
throw new Error('Global templates not supported')
|
|
812
|
+
throw new Error('Global templates not supported');
|
|
733
813
|
}
|
|
734
|
-
const nextPath = [...path, field.name, index]
|
|
735
|
-
const metadataFields: Record<string, string> = {}
|
|
814
|
+
const nextPath = [...path, field.name, index];
|
|
815
|
+
const metadataFields: Record<string, string> = {};
|
|
736
816
|
template.fields.forEach((field) => {
|
|
737
|
-
metadataFields[field.name] = [...nextPath, field.name].join(
|
|
738
|
-
|
|
817
|
+
metadataFields[field.name] = [...nextPath, field.name].join(
|
|
818
|
+
'.'
|
|
819
|
+
);
|
|
820
|
+
});
|
|
739
821
|
return {
|
|
740
822
|
__typename: NAMER.dataTypeName(template.namespace),
|
|
741
823
|
_tina_metadata: {
|
|
@@ -751,29 +833,29 @@ const resolveFieldValue = ({
|
|
|
751
833
|
id,
|
|
752
834
|
pathToDocument,
|
|
753
835
|
}),
|
|
754
|
-
}
|
|
755
|
-
})
|
|
836
|
+
};
|
|
837
|
+
});
|
|
756
838
|
}
|
|
757
839
|
} else {
|
|
758
840
|
// not implemented
|
|
759
841
|
}
|
|
760
842
|
}
|
|
761
843
|
|
|
762
|
-
const templateFields = field.fields
|
|
844
|
+
const templateFields = field.fields;
|
|
763
845
|
if (typeof templateFields === 'string') {
|
|
764
|
-
throw new Error('Global templates not supported')
|
|
846
|
+
throw new Error('Global templates not supported');
|
|
765
847
|
}
|
|
766
848
|
if (!templateFields) {
|
|
767
|
-
throw new Error(`Expected to find sub-fields on field ${field.name}`)
|
|
849
|
+
throw new Error(`Expected to find sub-fields on field ${field.name}`);
|
|
768
850
|
}
|
|
769
851
|
if (field.list) {
|
|
770
852
|
if (Array.isArray(value)) {
|
|
771
853
|
return value.map((item, index) => {
|
|
772
|
-
const nextPath = [...path, field.name, index]
|
|
773
|
-
const metadataFields: Record<string, string> = {}
|
|
854
|
+
const nextPath = [...path, field.name, index];
|
|
855
|
+
const metadataFields: Record<string, string> = {};
|
|
774
856
|
templateFields.forEach((field) => {
|
|
775
|
-
metadataFields[field.name] = [...nextPath, field.name].join('.')
|
|
776
|
-
})
|
|
857
|
+
metadataFields[field.name] = [...nextPath, field.name].join('.');
|
|
858
|
+
});
|
|
777
859
|
return {
|
|
778
860
|
__typename: NAMER.dataTypeName(field.namespace),
|
|
779
861
|
_tina_metadata: {
|
|
@@ -789,15 +871,15 @@ const resolveFieldValue = ({
|
|
|
789
871
|
id,
|
|
790
872
|
pathToDocument,
|
|
791
873
|
}),
|
|
792
|
-
}
|
|
793
|
-
})
|
|
874
|
+
};
|
|
875
|
+
});
|
|
794
876
|
}
|
|
795
877
|
} else {
|
|
796
|
-
const nextPath = [...path, field.name]
|
|
797
|
-
const metadataFields: Record<string, string> = {}
|
|
878
|
+
const nextPath = [...path, field.name];
|
|
879
|
+
const metadataFields: Record<string, string> = {};
|
|
798
880
|
templateFields.forEach((field) => {
|
|
799
|
-
metadataFields[field.name] = [...nextPath, field.name].join('.')
|
|
800
|
-
})
|
|
881
|
+
metadataFields[field.name] = [...nextPath, field.name].join('.');
|
|
882
|
+
});
|
|
801
883
|
return {
|
|
802
884
|
__typename: NAMER.dataTypeName(field.namespace),
|
|
803
885
|
_tina_metadata: {
|
|
@@ -813,18 +895,21 @@ const resolveFieldValue = ({
|
|
|
813
895
|
id,
|
|
814
896
|
pathToDocument,
|
|
815
897
|
}),
|
|
816
|
-
}
|
|
898
|
+
};
|
|
817
899
|
}
|
|
818
900
|
}
|
|
819
901
|
default: {
|
|
820
|
-
return value
|
|
902
|
+
return value;
|
|
821
903
|
}
|
|
822
904
|
}
|
|
823
|
-
}
|
|
905
|
+
};
|
|
824
906
|
|
|
825
907
|
const getDocument = async (id: string, tina: Client) => {
|
|
826
908
|
const response = await tina.request<{
|
|
827
|
-
node: {
|
|
909
|
+
node: {
|
|
910
|
+
_internalSys: SystemInfo;
|
|
911
|
+
_internalValues: Record<string, unknown>;
|
|
912
|
+
};
|
|
828
913
|
}>(
|
|
829
914
|
`query GetNode($id: String!) {
|
|
830
915
|
node(id: $id) {
|
|
@@ -838,6 +923,7 @@ _internalSys: _sys {
|
|
|
838
923
|
extension
|
|
839
924
|
relativePath
|
|
840
925
|
title
|
|
926
|
+
hasReferences
|
|
841
927
|
template
|
|
842
928
|
collection {
|
|
843
929
|
name
|
|
@@ -856,29 +942,29 @@ _internalSys: _sys {
|
|
|
856
942
|
}
|
|
857
943
|
}`,
|
|
858
944
|
{ variables: { id: id } }
|
|
859
|
-
)
|
|
860
|
-
return response.node
|
|
861
|
-
}
|
|
945
|
+
);
|
|
946
|
+
return response.node;
|
|
947
|
+
};
|
|
862
948
|
|
|
863
949
|
const expandPayload = async (
|
|
864
950
|
payload: Payload,
|
|
865
951
|
cms: TinaCMS
|
|
866
952
|
): Promise<Payload> => {
|
|
867
|
-
const { query, variables } = payload
|
|
868
|
-
const documentNode = G.parse(query)
|
|
869
|
-
const expandedDocumentNode = expandQuery({ schema, documentNode })
|
|
870
|
-
const expandedQuery = G.print(expandedDocumentNode)
|
|
953
|
+
const { query, variables } = payload;
|
|
954
|
+
const documentNode = G.parse(query);
|
|
955
|
+
const expandedDocumentNode = expandQuery({ schema, documentNode });
|
|
956
|
+
const expandedQuery = G.print(expandedDocumentNode);
|
|
871
957
|
const expandedData = await cms.api.tina.request<object>(expandedQuery, {
|
|
872
958
|
variables,
|
|
873
|
-
})
|
|
959
|
+
});
|
|
874
960
|
|
|
875
961
|
const expandedDocumentNodeForResolver = expandQuery({
|
|
876
962
|
schema: schemaForResolver,
|
|
877
963
|
documentNode,
|
|
878
|
-
})
|
|
879
|
-
const expandedQueryForResolver = G.print(expandedDocumentNodeForResolver)
|
|
880
|
-
return { ...payload, expandedQuery, expandedData, expandedQueryForResolver }
|
|
881
|
-
}
|
|
964
|
+
});
|
|
965
|
+
const expandedQueryForResolver = G.print(expandedDocumentNodeForResolver);
|
|
966
|
+
return { ...payload, expandedQuery, expandedData, expandedQueryForResolver };
|
|
967
|
+
};
|
|
882
968
|
|
|
883
969
|
/**
|
|
884
970
|
* When we resolve the graphql data we check for these errors,
|
|
@@ -886,11 +972,11 @@ const expandPayload = async (
|
|
|
886
972
|
* process it once we have that document
|
|
887
973
|
*/
|
|
888
974
|
class NoFormError extends Error {
|
|
889
|
-
id: string
|
|
975
|
+
id: string;
|
|
890
976
|
constructor(msg: string, id: string) {
|
|
891
|
-
super(msg)
|
|
892
|
-
this.id = id
|
|
893
|
-
Object.setPrototypeOf(this, NoFormError.prototype)
|
|
977
|
+
super(msg);
|
|
978
|
+
this.id = id;
|
|
979
|
+
Object.setPrototypeOf(this, NoFormError.prototype);
|
|
894
980
|
}
|
|
895
981
|
}
|
|
896
982
|
|
|
@@ -898,22 +984,22 @@ const getTemplateForDocument = (
|
|
|
898
984
|
resolvedDocument: ResolvedDocument,
|
|
899
985
|
tinaSchema: TinaSchema
|
|
900
986
|
) => {
|
|
901
|
-
const id = resolvedDocument._internalSys.path
|
|
902
|
-
let collection: Collection<true> | undefined
|
|
987
|
+
const id = resolvedDocument._internalSys.path;
|
|
988
|
+
let collection: Collection<true> | undefined;
|
|
903
989
|
try {
|
|
904
|
-
collection = tinaSchema.getCollectionByFullPath(id)
|
|
990
|
+
collection = tinaSchema.getCollectionByFullPath(id);
|
|
905
991
|
} catch (e) {}
|
|
906
992
|
|
|
907
993
|
if (!collection) {
|
|
908
|
-
throw new Error(`Unable to determine collection for path ${id}`)
|
|
994
|
+
throw new Error(`Unable to determine collection for path ${id}`);
|
|
909
995
|
}
|
|
910
996
|
|
|
911
997
|
const template = tinaSchema.getTemplateForData({
|
|
912
998
|
data: resolvedDocument._internalValues,
|
|
913
999
|
collection,
|
|
914
|
-
})
|
|
915
|
-
return { template, collection }
|
|
916
|
-
}
|
|
1000
|
+
});
|
|
1001
|
+
return { template, collection };
|
|
1002
|
+
};
|
|
917
1003
|
|
|
918
1004
|
const buildForm = ({
|
|
919
1005
|
resolvedDocument,
|
|
@@ -921,18 +1007,18 @@ const buildForm = ({
|
|
|
921
1007
|
payloadId,
|
|
922
1008
|
cms,
|
|
923
1009
|
}: {
|
|
924
|
-
resolvedDocument: ResolvedDocument
|
|
925
|
-
tinaSchema: TinaSchema
|
|
926
|
-
payloadId: string
|
|
927
|
-
cms: TinaCMS
|
|
1010
|
+
resolvedDocument: ResolvedDocument;
|
|
1011
|
+
tinaSchema: TinaSchema;
|
|
1012
|
+
payloadId: string;
|
|
1013
|
+
cms: TinaCMS;
|
|
928
1014
|
}) => {
|
|
929
1015
|
const { template, collection } = getTemplateForDocument(
|
|
930
1016
|
resolvedDocument,
|
|
931
1017
|
tinaSchema
|
|
932
|
-
)
|
|
933
|
-
const id = resolvedDocument._internalSys.path
|
|
934
|
-
let form: Form | undefined
|
|
935
|
-
let shouldRegisterForm = true
|
|
1018
|
+
);
|
|
1019
|
+
const id = resolvedDocument._internalSys.path;
|
|
1020
|
+
let form: Form | undefined;
|
|
1021
|
+
let shouldRegisterForm = true;
|
|
936
1022
|
const formConfig: FormOptions<any> = {
|
|
937
1023
|
id,
|
|
938
1024
|
initialValues: resolvedDocument._internalValues,
|
|
@@ -945,10 +1031,10 @@ const buildForm = ({
|
|
|
945
1031
|
cms
|
|
946
1032
|
),
|
|
947
1033
|
label: collection.label || collection.name,
|
|
948
|
-
}
|
|
1034
|
+
};
|
|
949
1035
|
if (tinaSchema.config.config?.formifyCallback) {
|
|
950
1036
|
const callback = tinaSchema.config.config
|
|
951
|
-
?.formifyCallback as FormifyCallback
|
|
1037
|
+
?.formifyCallback as FormifyCallback;
|
|
952
1038
|
form =
|
|
953
1039
|
callback(
|
|
954
1040
|
{
|
|
@@ -958,30 +1044,30 @@ const buildForm = ({
|
|
|
958
1044
|
formConfig,
|
|
959
1045
|
},
|
|
960
1046
|
cms
|
|
961
|
-
) || undefined
|
|
1047
|
+
) || undefined;
|
|
962
1048
|
if (!form) {
|
|
963
1049
|
// If the form isn't created from formify, we still
|
|
964
1050
|
// need it, just don't show it to the user.
|
|
965
|
-
shouldRegisterForm = false
|
|
966
|
-
form = new Form(formConfig)
|
|
1051
|
+
shouldRegisterForm = false;
|
|
1052
|
+
form = new Form(formConfig);
|
|
967
1053
|
}
|
|
968
1054
|
} else {
|
|
969
1055
|
if (collection.ui?.global) {
|
|
970
|
-
form = createGlobalForm(formConfig)
|
|
1056
|
+
form = createGlobalForm(formConfig);
|
|
971
1057
|
} else {
|
|
972
|
-
form = createForm(formConfig)
|
|
1058
|
+
form = createForm(formConfig);
|
|
973
1059
|
}
|
|
974
1060
|
}
|
|
975
1061
|
if (form) {
|
|
976
1062
|
if (shouldRegisterForm) {
|
|
977
1063
|
if (collection.ui?.global) {
|
|
978
|
-
cms.plugins.add(new GlobalFormPlugin(form))
|
|
1064
|
+
cms.plugins.add(new GlobalFormPlugin(form));
|
|
979
1065
|
}
|
|
980
|
-
cms.dispatch({ type: 'forms:add', value: form })
|
|
1066
|
+
cms.dispatch({ type: 'forms:add', value: form });
|
|
981
1067
|
}
|
|
982
1068
|
}
|
|
983
1069
|
if (!form) {
|
|
984
|
-
throw new Error(`No form registered for ${id}.`)
|
|
1070
|
+
throw new Error(`No form registered for ${id}.`);
|
|
985
1071
|
}
|
|
986
|
-
return { template, form }
|
|
987
|
-
}
|
|
1072
|
+
return { template, form };
|
|
1073
|
+
};
|