@tinacms/app 0.0.0-e0ddb8c-20241004065742 → 0.0.0-e5c0e91-20250421003142
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 +150 -11
- package/package.json +8 -8
- package/src/App.tsx +24 -24
- package/src/Playground.tsx +55 -55
- 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 +54 -54
- package/src/fields/rich-text/monaco/index.tsx +56 -56
- package/src/fields/rich-text/monaco/use-debounce.ts +8 -8
- package/src/global.css +3 -3
- package/src/index.css +15 -15
- package/src/lib/build-form.ts +24 -24
- package/src/lib/errors.tsx +7 -7
- package/src/lib/expand-query.ts +66 -61
- package/src/lib/graphql-reducer.ts +297 -275
- package/src/lib/types.ts +35 -33
- package/src/lib/util.ts +41 -41
- 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,6 +41,7 @@ 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(),
|
|
@@ -49,14 +50,14 @@ const sysSchema = z.object({
|
|
|
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,77 @@ export const useGraphQLReducer = (
|
|
|
300
303
|
id: null,
|
|
301
304
|
fields: [],
|
|
302
305
|
prefix: '',
|
|
303
|
-
}
|
|
306
|
+
};
|
|
304
307
|
}
|
|
305
308
|
if (isConnectionType(info.returnType)) {
|
|
306
|
-
const name = G.getNamedType(info.returnType).name
|
|
309
|
+
const name = G.getNamedType(info.returnType).name;
|
|
307
310
|
const connectionCollection = tinaSchema
|
|
308
311
|
.getCollections()
|
|
309
312
|
.find((collection) => {
|
|
310
313
|
const collectionName = NAMER.referenceConnectionType(
|
|
311
314
|
collection.namespace
|
|
312
|
-
)
|
|
315
|
+
);
|
|
313
316
|
if (collectionName === name) {
|
|
314
|
-
return true
|
|
317
|
+
return true;
|
|
315
318
|
}
|
|
316
|
-
return false
|
|
317
|
-
})
|
|
319
|
+
return false;
|
|
320
|
+
});
|
|
318
321
|
if (connectionCollection) {
|
|
319
322
|
formListItems.push({
|
|
320
323
|
type: 'list',
|
|
321
324
|
label: connectionCollection.label || connectionCollection.name,
|
|
322
|
-
})
|
|
325
|
+
});
|
|
323
326
|
}
|
|
324
327
|
}
|
|
325
328
|
if (isNodeType(info.returnType)) {
|
|
326
329
|
if (!value) {
|
|
327
|
-
return
|
|
330
|
+
return;
|
|
328
331
|
}
|
|
329
|
-
let resolvedDocument: ResolvedDocument
|
|
332
|
+
let resolvedDocument: ResolvedDocument;
|
|
330
333
|
// This is a reference from another form
|
|
331
334
|
if (typeof value === 'string') {
|
|
332
335
|
const valueFromSetup = getIn(
|
|
333
336
|
expandedData,
|
|
334
337
|
G.responsePathAsArray(info.path).join('.')
|
|
335
|
-
)
|
|
338
|
+
);
|
|
336
339
|
const maybeResolvedDocument = resolvedDocuments.find(
|
|
337
340
|
(doc) => doc._internalSys.path === value
|
|
338
|
-
)
|
|
341
|
+
);
|
|
339
342
|
// If we already have this document, use it.
|
|
340
343
|
if (maybeResolvedDocument) {
|
|
341
|
-
resolvedDocument = maybeResolvedDocument
|
|
344
|
+
resolvedDocument = maybeResolvedDocument;
|
|
342
345
|
} else if (valueFromSetup) {
|
|
343
346
|
// Else, even though in this context the value is a string because it's
|
|
344
347
|
// resolved from a parent form, if the reference hasn't changed
|
|
345
348
|
// from when we ran the setup query, we can avoid a data fetch
|
|
346
349
|
// here and just grab it from the response
|
|
347
350
|
const maybeResolvedDocument =
|
|
348
|
-
documentSchema.parse(valueFromSetup)
|
|
351
|
+
documentSchema.parse(valueFromSetup);
|
|
349
352
|
if (maybeResolvedDocument._internalSys.path === value) {
|
|
350
|
-
resolvedDocument = maybeResolvedDocument
|
|
353
|
+
resolvedDocument = maybeResolvedDocument;
|
|
351
354
|
} else {
|
|
352
|
-
throw new NoFormError(`No form found`, value)
|
|
355
|
+
throw new NoFormError(`No form found`, value);
|
|
353
356
|
}
|
|
354
357
|
} else {
|
|
355
|
-
throw new NoFormError(`No form found`, value)
|
|
358
|
+
throw new NoFormError(`No form found`, value);
|
|
356
359
|
}
|
|
357
360
|
} else {
|
|
358
|
-
resolvedDocument = documentSchema.parse(value)
|
|
361
|
+
resolvedDocument = documentSchema.parse(value);
|
|
359
362
|
}
|
|
360
|
-
const id = resolvedDocument._internalSys.path
|
|
361
|
-
formIds.push(id)
|
|
363
|
+
const id = resolvedDocument._internalSys.path;
|
|
364
|
+
formIds.push(id);
|
|
362
365
|
const existingForm = cms.state.forms.find(
|
|
363
366
|
(f) => f.tinaForm.id === id
|
|
364
|
-
)
|
|
367
|
+
);
|
|
365
368
|
|
|
366
|
-
const pathArray = G.responsePathAsArray(info.path)
|
|
367
|
-
const pathString = pathArray.join('.')
|
|
369
|
+
const pathArray = G.responsePathAsArray(info.path);
|
|
370
|
+
const pathString = pathArray.join('.');
|
|
368
371
|
const ancestors = formListItems.filter((item) => {
|
|
369
372
|
if (item.type === 'document') {
|
|
370
|
-
return pathString.startsWith(item.path)
|
|
373
|
+
return pathString.startsWith(item.path);
|
|
371
374
|
}
|
|
372
|
-
})
|
|
373
|
-
const parent = ancestors[ancestors.length - 1]
|
|
375
|
+
});
|
|
376
|
+
const parent = ancestors[ancestors.length - 1];
|
|
374
377
|
if (parent) {
|
|
375
378
|
if (parent.type === 'document') {
|
|
376
379
|
parent.subItems.push({
|
|
@@ -378,7 +381,7 @@ export const useGraphQLReducer = (
|
|
|
378
381
|
path: pathString,
|
|
379
382
|
formId: id,
|
|
380
383
|
subItems: [],
|
|
381
|
-
})
|
|
384
|
+
});
|
|
382
385
|
}
|
|
383
386
|
} else {
|
|
384
387
|
formListItems.push({
|
|
@@ -386,7 +389,7 @@ export const useGraphQLReducer = (
|
|
|
386
389
|
path: pathString,
|
|
387
390
|
formId: id,
|
|
388
391
|
subItems: [],
|
|
389
|
-
})
|
|
392
|
+
});
|
|
390
393
|
}
|
|
391
394
|
|
|
392
395
|
if (!existingForm) {
|
|
@@ -395,65 +398,65 @@ export const useGraphQLReducer = (
|
|
|
395
398
|
tinaSchema,
|
|
396
399
|
payloadId: payload.id,
|
|
397
400
|
cms,
|
|
398
|
-
})
|
|
401
|
+
});
|
|
399
402
|
form.subscribe(
|
|
400
403
|
() => {
|
|
401
|
-
setOperationIndex((i) => i + 1)
|
|
404
|
+
setOperationIndex((i) => i + 1);
|
|
402
405
|
},
|
|
403
406
|
{ values: true }
|
|
404
|
-
)
|
|
407
|
+
);
|
|
405
408
|
return resolveDocument(
|
|
406
409
|
resolvedDocument,
|
|
407
410
|
template,
|
|
408
411
|
form,
|
|
409
412
|
pathString
|
|
410
|
-
)
|
|
413
|
+
);
|
|
411
414
|
} else {
|
|
412
|
-
existingForm.tinaForm.addQuery(payload.id)
|
|
415
|
+
existingForm.tinaForm.addQuery(payload.id);
|
|
413
416
|
const { template } = getTemplateForDocument(
|
|
414
417
|
resolvedDocument,
|
|
415
418
|
tinaSchema
|
|
416
|
-
)
|
|
417
|
-
existingForm.tinaForm.addQuery(payload.id)
|
|
419
|
+
);
|
|
420
|
+
existingForm.tinaForm.addQuery(payload.id);
|
|
418
421
|
return resolveDocument(
|
|
419
422
|
resolvedDocument,
|
|
420
423
|
template,
|
|
421
424
|
existingForm.tinaForm,
|
|
422
425
|
pathString
|
|
423
|
-
)
|
|
426
|
+
);
|
|
424
427
|
}
|
|
425
428
|
}
|
|
426
|
-
return value
|
|
429
|
+
return value;
|
|
427
430
|
},
|
|
428
|
-
})
|
|
431
|
+
});
|
|
429
432
|
if (result.errors) {
|
|
430
433
|
result.errors.forEach((error) => {
|
|
431
434
|
if (
|
|
432
435
|
error instanceof G.GraphQLError &&
|
|
433
436
|
error.originalError instanceof NoFormError
|
|
434
437
|
) {
|
|
435
|
-
const id = error.originalError.id
|
|
438
|
+
const id = error.originalError.id;
|
|
436
439
|
setDocumentsToResolve((docs) => [
|
|
437
440
|
...docs.filter((doc) => doc !== id),
|
|
438
441
|
id,
|
|
439
|
-
])
|
|
442
|
+
]);
|
|
440
443
|
} else {
|
|
441
|
-
console.log(error)
|
|
444
|
+
console.log(error);
|
|
442
445
|
// throw new Error(
|
|
443
446
|
// `Error processing value change, please contact support`
|
|
444
447
|
// )
|
|
445
448
|
}
|
|
446
|
-
})
|
|
449
|
+
});
|
|
447
450
|
} else {
|
|
448
451
|
if (result.data) {
|
|
449
452
|
setResults((results) => [
|
|
450
453
|
...results.filter((result) => result.id !== payload.id),
|
|
451
454
|
{ id: payload.id, data: result.data },
|
|
452
|
-
])
|
|
455
|
+
]);
|
|
453
456
|
}
|
|
454
457
|
if (activeField) {
|
|
455
|
-
setSearchParams({})
|
|
456
|
-
const [queryId, eventFieldName] = activeField.split('---')
|
|
458
|
+
setSearchParams({});
|
|
459
|
+
const [queryId, eventFieldName] = activeField.split('---');
|
|
457
460
|
if (queryId === payload.id) {
|
|
458
461
|
if (result?.data) {
|
|
459
462
|
cms.dispatch({
|
|
@@ -462,19 +465,19 @@ export const useGraphQLReducer = (
|
|
|
462
465
|
result.data,
|
|
463
466
|
eventFieldName
|
|
464
467
|
),
|
|
465
|
-
})
|
|
468
|
+
});
|
|
466
469
|
}
|
|
467
470
|
cms.dispatch({
|
|
468
471
|
type: 'sidebar:set-display-state',
|
|
469
472
|
value: 'openOrFull',
|
|
470
|
-
})
|
|
473
|
+
});
|
|
471
474
|
}
|
|
472
475
|
}
|
|
473
476
|
iframe.current?.contentWindow?.postMessage({
|
|
474
477
|
type: 'updateData',
|
|
475
478
|
id: payload.id,
|
|
476
479
|
data: result.data,
|
|
477
|
-
})
|
|
480
|
+
});
|
|
478
481
|
}
|
|
479
482
|
cms.dispatch({
|
|
480
483
|
type: 'form-lists:add',
|
|
@@ -484,57 +487,64 @@ export const useGraphQLReducer = (
|
|
|
484
487
|
items: formListItems,
|
|
485
488
|
formIds,
|
|
486
489
|
},
|
|
487
|
-
})
|
|
490
|
+
});
|
|
488
491
|
},
|
|
489
492
|
[
|
|
490
493
|
resolvedDocuments.map((doc) => doc._internalSys.path).join('.'),
|
|
491
494
|
activeField,
|
|
492
495
|
]
|
|
493
|
-
)
|
|
496
|
+
);
|
|
494
497
|
|
|
495
498
|
const handleMessage = React.useCallback(
|
|
496
499
|
(event: MessageEvent<PostMessage>) => {
|
|
500
|
+
if (event.data.type === 'user-select-form') {
|
|
501
|
+
cms.dispatch({
|
|
502
|
+
type: 'forms:set-active-form-id',
|
|
503
|
+
value: event.data.formId,
|
|
504
|
+
});
|
|
505
|
+
}
|
|
506
|
+
|
|
497
507
|
if (event?.data?.type === 'quick-edit') {
|
|
498
508
|
cms.dispatch({
|
|
499
509
|
type: 'set-quick-editing-supported',
|
|
500
510
|
value: event.data.value,
|
|
501
|
-
})
|
|
511
|
+
});
|
|
502
512
|
iframe.current?.contentWindow?.postMessage({
|
|
503
513
|
type: 'quickEditEnabled',
|
|
504
514
|
value: cms.state.sidebarDisplayState === 'open',
|
|
505
|
-
})
|
|
515
|
+
});
|
|
506
516
|
}
|
|
507
517
|
if (event?.data?.type === 'isEditMode') {
|
|
508
518
|
iframe?.current?.contentWindow?.postMessage({
|
|
509
519
|
type: 'tina:editMode',
|
|
510
|
-
})
|
|
520
|
+
});
|
|
511
521
|
}
|
|
512
522
|
if (event.data.type === 'field:selected') {
|
|
513
|
-
const [queryId, eventFieldName] = event.data.fieldName.split('---')
|
|
514
|
-
const result = results.find((res) => res.id === queryId)
|
|
523
|
+
const [queryId, eventFieldName] = event.data.fieldName.split('---');
|
|
524
|
+
const result = results.find((res) => res.id === queryId);
|
|
515
525
|
if (result?.data) {
|
|
516
526
|
cms.dispatch({
|
|
517
527
|
type: 'forms:set-active-field-name',
|
|
518
528
|
value: getFormAndFieldNameFromMetadata(result.data, eventFieldName),
|
|
519
|
-
})
|
|
529
|
+
});
|
|
520
530
|
}
|
|
521
531
|
cms.dispatch({
|
|
522
532
|
type: 'sidebar:set-display-state',
|
|
523
533
|
value: 'openOrFull',
|
|
524
|
-
})
|
|
534
|
+
});
|
|
525
535
|
}
|
|
526
536
|
if (event.data.type === 'close') {
|
|
527
|
-
const payloadSchema = z.object({ id: z.string() })
|
|
528
|
-
const { id } = payloadSchema.parse(event.data)
|
|
537
|
+
const payloadSchema = z.object({ id: z.string() });
|
|
538
|
+
const { id } = payloadSchema.parse(event.data);
|
|
529
539
|
setPayloads((previous) =>
|
|
530
540
|
previous.filter((payload) => payload.id !== id)
|
|
531
|
-
)
|
|
532
|
-
setResults((previous) => previous.filter((result) => result.id !== id))
|
|
541
|
+
);
|
|
542
|
+
setResults((previous) => previous.filter((result) => result.id !== id));
|
|
533
543
|
cms.forms.all().map((form) => {
|
|
534
|
-
form.removeQuery(id)
|
|
535
|
-
})
|
|
536
|
-
cms.removeOrphanedForms()
|
|
537
|
-
cms.dispatch({ type: 'form-lists:remove', value: id })
|
|
544
|
+
form.removeQuery(id);
|
|
545
|
+
});
|
|
546
|
+
cms.removeOrphanedForms();
|
|
547
|
+
cms.dispatch({ type: 'form-lists:remove', value: id });
|
|
538
548
|
}
|
|
539
549
|
if (event.data.type === 'open') {
|
|
540
550
|
const payloadSchema = z.object({
|
|
@@ -542,60 +552,66 @@ export const useGraphQLReducer = (
|
|
|
542
552
|
query: z.string(),
|
|
543
553
|
variables: z.record(z.unknown()),
|
|
544
554
|
data: z.record(z.unknown()),
|
|
545
|
-
})
|
|
546
|
-
const payload = payloadSchema.parse(event.data)
|
|
555
|
+
});
|
|
556
|
+
const payload = payloadSchema.parse(event.data);
|
|
547
557
|
setPayloads((payloads) => [
|
|
548
558
|
...payloads.filter(({ id }) => id !== payload.id),
|
|
549
559
|
payload,
|
|
550
|
-
])
|
|
560
|
+
]);
|
|
561
|
+
}
|
|
562
|
+
if (event.data.type === 'url-changed') {
|
|
563
|
+
cms.dispatch({
|
|
564
|
+
type: 'sidebar:set-loading-state',
|
|
565
|
+
value: true,
|
|
566
|
+
});
|
|
551
567
|
}
|
|
552
568
|
},
|
|
553
569
|
[cms, JSON.stringify(results)]
|
|
554
|
-
)
|
|
570
|
+
);
|
|
555
571
|
|
|
556
572
|
React.useEffect(() => {
|
|
557
573
|
payloads.forEach((payload) => {
|
|
558
574
|
if (payload.expandedData) {
|
|
559
|
-
processPayload(payload)
|
|
575
|
+
processPayload(payload);
|
|
560
576
|
}
|
|
561
|
-
})
|
|
562
|
-
}, [operationIndex])
|
|
577
|
+
});
|
|
578
|
+
}, [operationIndex]);
|
|
563
579
|
|
|
564
580
|
React.useEffect(() => {
|
|
565
581
|
return () => {
|
|
566
|
-
setPayloads([])
|
|
567
|
-
setResults([])
|
|
568
|
-
cms.removeAllForms()
|
|
569
|
-
cms.dispatch({ type: 'form-lists:clear' })
|
|
570
|
-
}
|
|
571
|
-
}, [url])
|
|
582
|
+
setPayloads([]);
|
|
583
|
+
setResults([]);
|
|
584
|
+
cms.removeAllForms();
|
|
585
|
+
cms.dispatch({ type: 'form-lists:clear' });
|
|
586
|
+
};
|
|
587
|
+
}, [url]);
|
|
572
588
|
|
|
573
589
|
React.useEffect(() => {
|
|
574
590
|
iframe.current?.contentWindow?.postMessage({
|
|
575
591
|
type: 'quickEditEnabled',
|
|
576
592
|
value: cms.state.sidebarDisplayState === 'open',
|
|
577
|
-
})
|
|
578
|
-
}, [cms.state.sidebarDisplayState])
|
|
593
|
+
});
|
|
594
|
+
}, [cms.state.sidebarDisplayState]);
|
|
579
595
|
|
|
580
596
|
React.useEffect(() => {
|
|
581
|
-
cms.dispatch({ type: 'set-edit-mode', value: 'visual' })
|
|
597
|
+
cms.dispatch({ type: 'set-edit-mode', value: 'visual' });
|
|
582
598
|
if (iframe) {
|
|
583
|
-
window.addEventListener('message', handleMessage)
|
|
599
|
+
window.addEventListener('message', handleMessage);
|
|
584
600
|
}
|
|
585
601
|
|
|
586
602
|
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)])
|
|
603
|
+
window.removeEventListener('message', handleMessage);
|
|
604
|
+
cms.removeAllForms();
|
|
605
|
+
cms.dispatch({ type: 'set-edit-mode', value: 'basic' });
|
|
606
|
+
};
|
|
607
|
+
}, [iframe.current, JSON.stringify(results)]);
|
|
592
608
|
|
|
593
609
|
React.useEffect(() => {
|
|
594
610
|
if (requestErrors.length) {
|
|
595
|
-
showErrorModal('Unexpected error querying content', requestErrors, cms)
|
|
611
|
+
showErrorModal('Unexpected error querying content', requestErrors, cms);
|
|
596
612
|
}
|
|
597
|
-
}, [requestErrors])
|
|
598
|
-
}
|
|
613
|
+
}, [requestErrors]);
|
|
614
|
+
};
|
|
599
615
|
|
|
600
616
|
const onSubmit = async (
|
|
601
617
|
collection: Collection<true>,
|
|
@@ -603,7 +619,7 @@ const onSubmit = async (
|
|
|
603
619
|
payload: Record<string, unknown>,
|
|
604
620
|
cms: TinaCMS
|
|
605
621
|
) => {
|
|
606
|
-
const tinaSchema = cms.api.tina.schema
|
|
622
|
+
const tinaSchema = cms.api.tina.schema;
|
|
607
623
|
try {
|
|
608
624
|
const mutationString = `#graphql
|
|
609
625
|
mutation UpdateDocument($collection: String!, $relativePath: String!, $params: DocumentUpdateMutation!) {
|
|
@@ -611,7 +627,7 @@ const onSubmit = async (
|
|
|
611
627
|
__typename
|
|
612
628
|
}
|
|
613
629
|
}
|
|
614
|
-
|
|
630
|
+
`;
|
|
615
631
|
|
|
616
632
|
await cms.api.tina.request(mutationString, {
|
|
617
633
|
variables: {
|
|
@@ -619,8 +635,8 @@ const onSubmit = async (
|
|
|
619
635
|
relativePath: relativePath,
|
|
620
636
|
params: tinaSchema.transformPayload(collection.name, payload),
|
|
621
637
|
},
|
|
622
|
-
})
|
|
623
|
-
cms.alerts.success('Document saved!')
|
|
638
|
+
});
|
|
639
|
+
cms.alerts.success('Document saved!');
|
|
624
640
|
} catch (e) {
|
|
625
641
|
cms.alerts.error(() =>
|
|
626
642
|
ErrorDialog({
|
|
@@ -628,12 +644,12 @@ const onSubmit = async (
|
|
|
628
644
|
message: 'Tina caught an error while updating the page',
|
|
629
645
|
error: e,
|
|
630
646
|
})
|
|
631
|
-
)
|
|
632
|
-
console.error(e)
|
|
647
|
+
);
|
|
648
|
+
console.error(e);
|
|
633
649
|
}
|
|
634
|
-
}
|
|
650
|
+
};
|
|
635
651
|
|
|
636
|
-
type Path = (string | number)[]
|
|
652
|
+
type Path = (string | number)[];
|
|
637
653
|
|
|
638
654
|
const resolveDocument = (
|
|
639
655
|
doc: ResolvedDocument,
|
|
@@ -642,20 +658,20 @@ const resolveDocument = (
|
|
|
642
658
|
pathToDocument: string
|
|
643
659
|
): ResolvedDocument => {
|
|
644
660
|
// @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 = []
|
|
661
|
+
const fields = form.fields as TinaField<true>[];
|
|
662
|
+
const id = doc._internalSys.path;
|
|
663
|
+
const path: Path = [];
|
|
648
664
|
const formValues = resolveFormValue({
|
|
649
665
|
fields: fields,
|
|
650
666
|
values: form.values,
|
|
651
667
|
path,
|
|
652
668
|
id,
|
|
653
669
|
pathToDocument,
|
|
654
|
-
})
|
|
655
|
-
const metadataFields: Record<string, string> = {}
|
|
670
|
+
});
|
|
671
|
+
const metadataFields: Record<string, string> = {};
|
|
656
672
|
Object.keys(formValues).forEach((key) => {
|
|
657
|
-
metadataFields[key] = [...path, key].join('.')
|
|
658
|
-
})
|
|
673
|
+
metadataFields[key] = [...path, key].join('.');
|
|
674
|
+
});
|
|
659
675
|
|
|
660
676
|
return {
|
|
661
677
|
...formValues,
|
|
@@ -671,8 +687,8 @@ const resolveDocument = (
|
|
|
671
687
|
_internalSys: doc._internalSys,
|
|
672
688
|
_internalValues: doc._internalValues,
|
|
673
689
|
__typename: NAMER.dataTypeName(template.namespace),
|
|
674
|
-
}
|
|
675
|
-
}
|
|
690
|
+
};
|
|
691
|
+
};
|
|
676
692
|
|
|
677
693
|
const resolveFormValue = <T extends Record<string, unknown>>({
|
|
678
694
|
fields,
|
|
@@ -682,21 +698,21 @@ const resolveFormValue = <T extends Record<string, unknown>>({
|
|
|
682
698
|
pathToDocument,
|
|
683
699
|
}: // tinaSchema,
|
|
684
700
|
{
|
|
685
|
-
fields: TinaField<true>[]
|
|
686
|
-
values: T
|
|
687
|
-
path: Path
|
|
688
|
-
id: string
|
|
689
|
-
pathToDocument: string
|
|
701
|
+
fields: TinaField<true>[];
|
|
702
|
+
values: T;
|
|
703
|
+
path: Path;
|
|
704
|
+
id: string;
|
|
705
|
+
pathToDocument: string;
|
|
690
706
|
// tinaSchema: TinaSchema
|
|
691
707
|
}): T & { __typename?: string } => {
|
|
692
|
-
const accum: Record<string, unknown> = {}
|
|
708
|
+
const accum: Record<string, unknown> = {};
|
|
693
709
|
fields.forEach((field) => {
|
|
694
|
-
const v = values[field.name]
|
|
710
|
+
const v = values[field.name];
|
|
695
711
|
if (typeof v === 'undefined') {
|
|
696
|
-
return
|
|
712
|
+
return;
|
|
697
713
|
}
|
|
698
714
|
if (v === null) {
|
|
699
|
-
return
|
|
715
|
+
return;
|
|
700
716
|
}
|
|
701
717
|
accum[field.name] = resolveFieldValue({
|
|
702
718
|
field,
|
|
@@ -704,10 +720,10 @@ const resolveFormValue = <T extends Record<string, unknown>>({
|
|
|
704
720
|
path,
|
|
705
721
|
id,
|
|
706
722
|
pathToDocument,
|
|
707
|
-
})
|
|
708
|
-
})
|
|
709
|
-
return accum as T & { __typename?: string }
|
|
710
|
-
}
|
|
723
|
+
});
|
|
724
|
+
});
|
|
725
|
+
return accum as T & { __typename?: string };
|
|
726
|
+
};
|
|
711
727
|
const resolveFieldValue = ({
|
|
712
728
|
field,
|
|
713
729
|
value,
|
|
@@ -715,11 +731,11 @@ const resolveFieldValue = ({
|
|
|
715
731
|
id,
|
|
716
732
|
pathToDocument,
|
|
717
733
|
}: {
|
|
718
|
-
field: TinaField<true
|
|
719
|
-
value: unknown
|
|
720
|
-
path: Path
|
|
721
|
-
id: string
|
|
722
|
-
pathToDocument: string
|
|
734
|
+
field: TinaField<true>;
|
|
735
|
+
value: unknown;
|
|
736
|
+
path: Path;
|
|
737
|
+
id: string;
|
|
738
|
+
pathToDocument: string;
|
|
723
739
|
}) => {
|
|
724
740
|
switch (field.type) {
|
|
725
741
|
case 'object': {
|
|
@@ -727,15 +743,17 @@ const resolveFieldValue = ({
|
|
|
727
743
|
if (field.list) {
|
|
728
744
|
if (Array.isArray(value)) {
|
|
729
745
|
return value.map((item, index) => {
|
|
730
|
-
const template = field.templates[item._template]
|
|
746
|
+
const template = field.templates[item._template];
|
|
731
747
|
if (typeof template === 'string') {
|
|
732
|
-
throw new Error('Global templates not supported')
|
|
748
|
+
throw new Error('Global templates not supported');
|
|
733
749
|
}
|
|
734
|
-
const nextPath = [...path, field.name, index]
|
|
735
|
-
const metadataFields: Record<string, string> = {}
|
|
750
|
+
const nextPath = [...path, field.name, index];
|
|
751
|
+
const metadataFields: Record<string, string> = {};
|
|
736
752
|
template.fields.forEach((field) => {
|
|
737
|
-
metadataFields[field.name] = [...nextPath, field.name].join(
|
|
738
|
-
|
|
753
|
+
metadataFields[field.name] = [...nextPath, field.name].join(
|
|
754
|
+
'.'
|
|
755
|
+
);
|
|
756
|
+
});
|
|
739
757
|
return {
|
|
740
758
|
__typename: NAMER.dataTypeName(template.namespace),
|
|
741
759
|
_tina_metadata: {
|
|
@@ -751,29 +769,29 @@ const resolveFieldValue = ({
|
|
|
751
769
|
id,
|
|
752
770
|
pathToDocument,
|
|
753
771
|
}),
|
|
754
|
-
}
|
|
755
|
-
})
|
|
772
|
+
};
|
|
773
|
+
});
|
|
756
774
|
}
|
|
757
775
|
} else {
|
|
758
776
|
// not implemented
|
|
759
777
|
}
|
|
760
778
|
}
|
|
761
779
|
|
|
762
|
-
const templateFields = field.fields
|
|
780
|
+
const templateFields = field.fields;
|
|
763
781
|
if (typeof templateFields === 'string') {
|
|
764
|
-
throw new Error('Global templates not supported')
|
|
782
|
+
throw new Error('Global templates not supported');
|
|
765
783
|
}
|
|
766
784
|
if (!templateFields) {
|
|
767
|
-
throw new Error(`Expected to find sub-fields on field ${field.name}`)
|
|
785
|
+
throw new Error(`Expected to find sub-fields on field ${field.name}`);
|
|
768
786
|
}
|
|
769
787
|
if (field.list) {
|
|
770
788
|
if (Array.isArray(value)) {
|
|
771
789
|
return value.map((item, index) => {
|
|
772
|
-
const nextPath = [...path, field.name, index]
|
|
773
|
-
const metadataFields: Record<string, string> = {}
|
|
790
|
+
const nextPath = [...path, field.name, index];
|
|
791
|
+
const metadataFields: Record<string, string> = {};
|
|
774
792
|
templateFields.forEach((field) => {
|
|
775
|
-
metadataFields[field.name] = [...nextPath, field.name].join('.')
|
|
776
|
-
})
|
|
793
|
+
metadataFields[field.name] = [...nextPath, field.name].join('.');
|
|
794
|
+
});
|
|
777
795
|
return {
|
|
778
796
|
__typename: NAMER.dataTypeName(field.namespace),
|
|
779
797
|
_tina_metadata: {
|
|
@@ -789,15 +807,15 @@ const resolveFieldValue = ({
|
|
|
789
807
|
id,
|
|
790
808
|
pathToDocument,
|
|
791
809
|
}),
|
|
792
|
-
}
|
|
793
|
-
})
|
|
810
|
+
};
|
|
811
|
+
});
|
|
794
812
|
}
|
|
795
813
|
} else {
|
|
796
|
-
const nextPath = [...path, field.name]
|
|
797
|
-
const metadataFields: Record<string, string> = {}
|
|
814
|
+
const nextPath = [...path, field.name];
|
|
815
|
+
const metadataFields: Record<string, string> = {};
|
|
798
816
|
templateFields.forEach((field) => {
|
|
799
|
-
metadataFields[field.name] = [...nextPath, field.name].join('.')
|
|
800
|
-
})
|
|
817
|
+
metadataFields[field.name] = [...nextPath, field.name].join('.');
|
|
818
|
+
});
|
|
801
819
|
return {
|
|
802
820
|
__typename: NAMER.dataTypeName(field.namespace),
|
|
803
821
|
_tina_metadata: {
|
|
@@ -813,18 +831,21 @@ const resolveFieldValue = ({
|
|
|
813
831
|
id,
|
|
814
832
|
pathToDocument,
|
|
815
833
|
}),
|
|
816
|
-
}
|
|
834
|
+
};
|
|
817
835
|
}
|
|
818
836
|
}
|
|
819
837
|
default: {
|
|
820
|
-
return value
|
|
838
|
+
return value;
|
|
821
839
|
}
|
|
822
840
|
}
|
|
823
|
-
}
|
|
841
|
+
};
|
|
824
842
|
|
|
825
843
|
const getDocument = async (id: string, tina: Client) => {
|
|
826
844
|
const response = await tina.request<{
|
|
827
|
-
node: {
|
|
845
|
+
node: {
|
|
846
|
+
_internalSys: SystemInfo;
|
|
847
|
+
_internalValues: Record<string, unknown>;
|
|
848
|
+
};
|
|
828
849
|
}>(
|
|
829
850
|
`query GetNode($id: String!) {
|
|
830
851
|
node(id: $id) {
|
|
@@ -838,6 +859,7 @@ _internalSys: _sys {
|
|
|
838
859
|
extension
|
|
839
860
|
relativePath
|
|
840
861
|
title
|
|
862
|
+
hasReferences
|
|
841
863
|
template
|
|
842
864
|
collection {
|
|
843
865
|
name
|
|
@@ -856,29 +878,29 @@ _internalSys: _sys {
|
|
|
856
878
|
}
|
|
857
879
|
}`,
|
|
858
880
|
{ variables: { id: id } }
|
|
859
|
-
)
|
|
860
|
-
return response.node
|
|
861
|
-
}
|
|
881
|
+
);
|
|
882
|
+
return response.node;
|
|
883
|
+
};
|
|
862
884
|
|
|
863
885
|
const expandPayload = async (
|
|
864
886
|
payload: Payload,
|
|
865
887
|
cms: TinaCMS
|
|
866
888
|
): 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)
|
|
889
|
+
const { query, variables } = payload;
|
|
890
|
+
const documentNode = G.parse(query);
|
|
891
|
+
const expandedDocumentNode = expandQuery({ schema, documentNode });
|
|
892
|
+
const expandedQuery = G.print(expandedDocumentNode);
|
|
871
893
|
const expandedData = await cms.api.tina.request<object>(expandedQuery, {
|
|
872
894
|
variables,
|
|
873
|
-
})
|
|
895
|
+
});
|
|
874
896
|
|
|
875
897
|
const expandedDocumentNodeForResolver = expandQuery({
|
|
876
898
|
schema: schemaForResolver,
|
|
877
899
|
documentNode,
|
|
878
|
-
})
|
|
879
|
-
const expandedQueryForResolver = G.print(expandedDocumentNodeForResolver)
|
|
880
|
-
return { ...payload, expandedQuery, expandedData, expandedQueryForResolver }
|
|
881
|
-
}
|
|
900
|
+
});
|
|
901
|
+
const expandedQueryForResolver = G.print(expandedDocumentNodeForResolver);
|
|
902
|
+
return { ...payload, expandedQuery, expandedData, expandedQueryForResolver };
|
|
903
|
+
};
|
|
882
904
|
|
|
883
905
|
/**
|
|
884
906
|
* When we resolve the graphql data we check for these errors,
|
|
@@ -886,11 +908,11 @@ const expandPayload = async (
|
|
|
886
908
|
* process it once we have that document
|
|
887
909
|
*/
|
|
888
910
|
class NoFormError extends Error {
|
|
889
|
-
id: string
|
|
911
|
+
id: string;
|
|
890
912
|
constructor(msg: string, id: string) {
|
|
891
|
-
super(msg)
|
|
892
|
-
this.id = id
|
|
893
|
-
Object.setPrototypeOf(this, NoFormError.prototype)
|
|
913
|
+
super(msg);
|
|
914
|
+
this.id = id;
|
|
915
|
+
Object.setPrototypeOf(this, NoFormError.prototype);
|
|
894
916
|
}
|
|
895
917
|
}
|
|
896
918
|
|
|
@@ -898,22 +920,22 @@ const getTemplateForDocument = (
|
|
|
898
920
|
resolvedDocument: ResolvedDocument,
|
|
899
921
|
tinaSchema: TinaSchema
|
|
900
922
|
) => {
|
|
901
|
-
const id = resolvedDocument._internalSys.path
|
|
902
|
-
let collection: Collection<true> | undefined
|
|
923
|
+
const id = resolvedDocument._internalSys.path;
|
|
924
|
+
let collection: Collection<true> | undefined;
|
|
903
925
|
try {
|
|
904
|
-
collection = tinaSchema.getCollectionByFullPath(id)
|
|
926
|
+
collection = tinaSchema.getCollectionByFullPath(id);
|
|
905
927
|
} catch (e) {}
|
|
906
928
|
|
|
907
929
|
if (!collection) {
|
|
908
|
-
throw new Error(`Unable to determine collection for path ${id}`)
|
|
930
|
+
throw new Error(`Unable to determine collection for path ${id}`);
|
|
909
931
|
}
|
|
910
932
|
|
|
911
933
|
const template = tinaSchema.getTemplateForData({
|
|
912
934
|
data: resolvedDocument._internalValues,
|
|
913
935
|
collection,
|
|
914
|
-
})
|
|
915
|
-
return { template, collection }
|
|
916
|
-
}
|
|
936
|
+
});
|
|
937
|
+
return { template, collection };
|
|
938
|
+
};
|
|
917
939
|
|
|
918
940
|
const buildForm = ({
|
|
919
941
|
resolvedDocument,
|
|
@@ -921,18 +943,18 @@ const buildForm = ({
|
|
|
921
943
|
payloadId,
|
|
922
944
|
cms,
|
|
923
945
|
}: {
|
|
924
|
-
resolvedDocument: ResolvedDocument
|
|
925
|
-
tinaSchema: TinaSchema
|
|
926
|
-
payloadId: string
|
|
927
|
-
cms: TinaCMS
|
|
946
|
+
resolvedDocument: ResolvedDocument;
|
|
947
|
+
tinaSchema: TinaSchema;
|
|
948
|
+
payloadId: string;
|
|
949
|
+
cms: TinaCMS;
|
|
928
950
|
}) => {
|
|
929
951
|
const { template, collection } = getTemplateForDocument(
|
|
930
952
|
resolvedDocument,
|
|
931
953
|
tinaSchema
|
|
932
|
-
)
|
|
933
|
-
const id = resolvedDocument._internalSys.path
|
|
934
|
-
let form: Form | undefined
|
|
935
|
-
let shouldRegisterForm = true
|
|
954
|
+
);
|
|
955
|
+
const id = resolvedDocument._internalSys.path;
|
|
956
|
+
let form: Form | undefined;
|
|
957
|
+
let shouldRegisterForm = true;
|
|
936
958
|
const formConfig: FormOptions<any> = {
|
|
937
959
|
id,
|
|
938
960
|
initialValues: resolvedDocument._internalValues,
|
|
@@ -945,10 +967,10 @@ const buildForm = ({
|
|
|
945
967
|
cms
|
|
946
968
|
),
|
|
947
969
|
label: collection.label || collection.name,
|
|
948
|
-
}
|
|
970
|
+
};
|
|
949
971
|
if (tinaSchema.config.config?.formifyCallback) {
|
|
950
972
|
const callback = tinaSchema.config.config
|
|
951
|
-
?.formifyCallback as FormifyCallback
|
|
973
|
+
?.formifyCallback as FormifyCallback;
|
|
952
974
|
form =
|
|
953
975
|
callback(
|
|
954
976
|
{
|
|
@@ -958,30 +980,30 @@ const buildForm = ({
|
|
|
958
980
|
formConfig,
|
|
959
981
|
},
|
|
960
982
|
cms
|
|
961
|
-
) || undefined
|
|
983
|
+
) || undefined;
|
|
962
984
|
if (!form) {
|
|
963
985
|
// If the form isn't created from formify, we still
|
|
964
986
|
// need it, just don't show it to the user.
|
|
965
|
-
shouldRegisterForm = false
|
|
966
|
-
form = new Form(formConfig)
|
|
987
|
+
shouldRegisterForm = false;
|
|
988
|
+
form = new Form(formConfig);
|
|
967
989
|
}
|
|
968
990
|
} else {
|
|
969
991
|
if (collection.ui?.global) {
|
|
970
|
-
form = createGlobalForm(formConfig)
|
|
992
|
+
form = createGlobalForm(formConfig);
|
|
971
993
|
} else {
|
|
972
|
-
form = createForm(formConfig)
|
|
994
|
+
form = createForm(formConfig);
|
|
973
995
|
}
|
|
974
996
|
}
|
|
975
997
|
if (form) {
|
|
976
998
|
if (shouldRegisterForm) {
|
|
977
999
|
if (collection.ui?.global) {
|
|
978
|
-
cms.plugins.add(new GlobalFormPlugin(form))
|
|
1000
|
+
cms.plugins.add(new GlobalFormPlugin(form));
|
|
979
1001
|
}
|
|
980
|
-
cms.dispatch({ type: 'forms:add', value: form })
|
|
1002
|
+
cms.dispatch({ type: 'forms:add', value: form });
|
|
981
1003
|
}
|
|
982
1004
|
}
|
|
983
1005
|
if (!form) {
|
|
984
|
-
throw new Error(`No form registered for ${id}.`)
|
|
1006
|
+
throw new Error(`No form registered for ${id}.`);
|
|
985
1007
|
}
|
|
986
|
-
return { template, form }
|
|
987
|
-
}
|
|
1008
|
+
return { template, form };
|
|
1009
|
+
};
|