@tinacms/app 0.0.0-bbf2f81-20241024004604 → 0.0.0-bc35474-20251110001045
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 +231 -10
- package/index.html +1 -1
- package/package.json +12 -8
- 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 +303 -276
- package/src/lib/types.ts +35 -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,64 @@ 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) {
|
|
516
529
|
cms.dispatch({
|
|
517
530
|
type: 'forms:set-active-field-name',
|
|
518
531
|
value: getFormAndFieldNameFromMetadata(result.data, eventFieldName),
|
|
519
|
-
})
|
|
532
|
+
});
|
|
520
533
|
}
|
|
521
534
|
cms.dispatch({
|
|
522
535
|
type: 'sidebar:set-display-state',
|
|
523
536
|
value: 'openOrFull',
|
|
524
|
-
})
|
|
537
|
+
});
|
|
525
538
|
}
|
|
526
539
|
if (event.data.type === 'close') {
|
|
527
|
-
const payloadSchema = z.object({ id: z.string() })
|
|
528
|
-
const { id } = payloadSchema.parse(event.data)
|
|
540
|
+
const payloadSchema = z.object({ id: z.string() });
|
|
541
|
+
const { id } = payloadSchema.parse(event.data);
|
|
529
542
|
setPayloads((previous) =>
|
|
530
543
|
previous.filter((payload) => payload.id !== id)
|
|
531
|
-
)
|
|
532
|
-
setResults((previous) => previous.filter((result) => result.id !== id))
|
|
544
|
+
);
|
|
545
|
+
setResults((previous) => previous.filter((result) => result.id !== id));
|
|
533
546
|
cms.forms.all().map((form) => {
|
|
534
|
-
form.removeQuery(id)
|
|
535
|
-
})
|
|
536
|
-
cms.removeOrphanedForms()
|
|
537
|
-
cms.dispatch({ type: 'form-lists:remove', value: id })
|
|
547
|
+
form.removeQuery(id);
|
|
548
|
+
});
|
|
549
|
+
cms.removeOrphanedForms();
|
|
550
|
+
cms.dispatch({ type: 'form-lists:remove', value: id });
|
|
538
551
|
}
|
|
539
552
|
if (event.data.type === 'open') {
|
|
540
553
|
const payloadSchema = z.object({
|
|
@@ -542,60 +555,68 @@ export const useGraphQLReducer = (
|
|
|
542
555
|
query: z.string(),
|
|
543
556
|
variables: z.record(z.unknown()),
|
|
544
557
|
data: z.record(z.unknown()),
|
|
545
|
-
})
|
|
546
|
-
const payload = payloadSchema.parse(event.data)
|
|
558
|
+
});
|
|
559
|
+
const payload = payloadSchema.parse(event.data);
|
|
547
560
|
setPayloads((payloads) => [
|
|
548
561
|
...payloads.filter(({ id }) => id !== payload.id),
|
|
549
562
|
payload,
|
|
550
|
-
])
|
|
563
|
+
]);
|
|
551
564
|
}
|
|
565
|
+
// TODO: This is causing a webpack HMR issue - look into refactoring this logic
|
|
566
|
+
// if (event.data.type === 'url-changed') {
|
|
567
|
+
// console.log('[EVENT_TRIGGERED] url-changed: ', event);
|
|
568
|
+
// cms.dispatch({
|
|
569
|
+
// type: 'sidebar:set-loading-state',
|
|
570
|
+
// value: true,
|
|
571
|
+
// });
|
|
572
|
+
// }
|
|
552
573
|
},
|
|
553
574
|
[cms, JSON.stringify(results)]
|
|
554
|
-
)
|
|
575
|
+
);
|
|
555
576
|
|
|
556
577
|
React.useEffect(() => {
|
|
557
578
|
payloads.forEach((payload) => {
|
|
558
579
|
if (payload.expandedData) {
|
|
559
|
-
processPayload(payload)
|
|
580
|
+
processPayload(payload);
|
|
560
581
|
}
|
|
561
|
-
})
|
|
562
|
-
}, [operationIndex])
|
|
582
|
+
});
|
|
583
|
+
}, [operationIndex]);
|
|
563
584
|
|
|
564
585
|
React.useEffect(() => {
|
|
565
586
|
return () => {
|
|
566
|
-
setPayloads([])
|
|
567
|
-
setResults([])
|
|
568
|
-
cms.removeAllForms()
|
|
569
|
-
cms.dispatch({ type: 'form-lists:clear' })
|
|
570
|
-
}
|
|
571
|
-
}, [url])
|
|
587
|
+
setPayloads([]);
|
|
588
|
+
setResults([]);
|
|
589
|
+
cms.removeAllForms();
|
|
590
|
+
cms.dispatch({ type: 'form-lists:clear' });
|
|
591
|
+
};
|
|
592
|
+
}, [url]);
|
|
572
593
|
|
|
573
594
|
React.useEffect(() => {
|
|
574
595
|
iframe.current?.contentWindow?.postMessage({
|
|
575
596
|
type: 'quickEditEnabled',
|
|
576
597
|
value: cms.state.sidebarDisplayState === 'open',
|
|
577
|
-
})
|
|
578
|
-
}, [cms.state.sidebarDisplayState])
|
|
598
|
+
});
|
|
599
|
+
}, [cms.state.sidebarDisplayState]);
|
|
579
600
|
|
|
580
601
|
React.useEffect(() => {
|
|
581
|
-
cms.dispatch({ type: 'set-edit-mode', value: 'visual' })
|
|
602
|
+
cms.dispatch({ type: 'set-edit-mode', value: 'visual' });
|
|
582
603
|
if (iframe) {
|
|
583
|
-
window.addEventListener('message', handleMessage)
|
|
604
|
+
window.addEventListener('message', handleMessage);
|
|
584
605
|
}
|
|
585
606
|
|
|
586
607
|
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)])
|
|
608
|
+
window.removeEventListener('message', handleMessage);
|
|
609
|
+
cms.removeAllForms();
|
|
610
|
+
cms.dispatch({ type: 'set-edit-mode', value: 'basic' });
|
|
611
|
+
};
|
|
612
|
+
}, [iframe.current, JSON.stringify(results)]);
|
|
592
613
|
|
|
593
614
|
React.useEffect(() => {
|
|
594
615
|
if (requestErrors.length) {
|
|
595
|
-
showErrorModal('Unexpected error querying content', requestErrors, cms)
|
|
616
|
+
showErrorModal('Unexpected error querying content', requestErrors, cms);
|
|
596
617
|
}
|
|
597
|
-
}, [requestErrors])
|
|
598
|
-
}
|
|
618
|
+
}, [requestErrors]);
|
|
619
|
+
};
|
|
599
620
|
|
|
600
621
|
const onSubmit = async (
|
|
601
622
|
collection: Collection<true>,
|
|
@@ -603,7 +624,7 @@ const onSubmit = async (
|
|
|
603
624
|
payload: Record<string, unknown>,
|
|
604
625
|
cms: TinaCMS
|
|
605
626
|
) => {
|
|
606
|
-
const tinaSchema = cms.api.tina.schema
|
|
627
|
+
const tinaSchema = cms.api.tina.schema;
|
|
607
628
|
try {
|
|
608
629
|
const mutationString = `#graphql
|
|
609
630
|
mutation UpdateDocument($collection: String!, $relativePath: String!, $params: DocumentUpdateMutation!) {
|
|
@@ -611,7 +632,7 @@ const onSubmit = async (
|
|
|
611
632
|
__typename
|
|
612
633
|
}
|
|
613
634
|
}
|
|
614
|
-
|
|
635
|
+
`;
|
|
615
636
|
|
|
616
637
|
await cms.api.tina.request(mutationString, {
|
|
617
638
|
variables: {
|
|
@@ -619,8 +640,8 @@ const onSubmit = async (
|
|
|
619
640
|
relativePath: relativePath,
|
|
620
641
|
params: tinaSchema.transformPayload(collection.name, payload),
|
|
621
642
|
},
|
|
622
|
-
})
|
|
623
|
-
cms.alerts.success('Document saved!')
|
|
643
|
+
});
|
|
644
|
+
cms.alerts.success('Document saved!');
|
|
624
645
|
} catch (e) {
|
|
625
646
|
cms.alerts.error(() =>
|
|
626
647
|
ErrorDialog({
|
|
@@ -628,12 +649,12 @@ const onSubmit = async (
|
|
|
628
649
|
message: 'Tina caught an error while updating the page',
|
|
629
650
|
error: e,
|
|
630
651
|
})
|
|
631
|
-
)
|
|
632
|
-
console.error(e)
|
|
652
|
+
);
|
|
653
|
+
console.error(e);
|
|
633
654
|
}
|
|
634
|
-
}
|
|
655
|
+
};
|
|
635
656
|
|
|
636
|
-
type Path = (string | number)[]
|
|
657
|
+
type Path = (string | number)[];
|
|
637
658
|
|
|
638
659
|
const resolveDocument = (
|
|
639
660
|
doc: ResolvedDocument,
|
|
@@ -642,20 +663,20 @@ const resolveDocument = (
|
|
|
642
663
|
pathToDocument: string
|
|
643
664
|
): ResolvedDocument => {
|
|
644
665
|
// @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 = []
|
|
666
|
+
const fields = form.fields as TinaField<true>[];
|
|
667
|
+
const id = doc._internalSys.path;
|
|
668
|
+
const path: Path = [];
|
|
648
669
|
const formValues = resolveFormValue({
|
|
649
670
|
fields: fields,
|
|
650
671
|
values: form.values,
|
|
651
672
|
path,
|
|
652
673
|
id,
|
|
653
674
|
pathToDocument,
|
|
654
|
-
})
|
|
655
|
-
const metadataFields: Record<string, string> = {}
|
|
675
|
+
});
|
|
676
|
+
const metadataFields: Record<string, string> = {};
|
|
656
677
|
Object.keys(formValues).forEach((key) => {
|
|
657
|
-
metadataFields[key] = [...path, key].join('.')
|
|
658
|
-
})
|
|
678
|
+
metadataFields[key] = [...path, key].join('.');
|
|
679
|
+
});
|
|
659
680
|
|
|
660
681
|
return {
|
|
661
682
|
...formValues,
|
|
@@ -671,8 +692,8 @@ const resolveDocument = (
|
|
|
671
692
|
_internalSys: doc._internalSys,
|
|
672
693
|
_internalValues: doc._internalValues,
|
|
673
694
|
__typename: NAMER.dataTypeName(template.namespace),
|
|
674
|
-
}
|
|
675
|
-
}
|
|
695
|
+
};
|
|
696
|
+
};
|
|
676
697
|
|
|
677
698
|
const resolveFormValue = <T extends Record<string, unknown>>({
|
|
678
699
|
fields,
|
|
@@ -682,21 +703,21 @@ const resolveFormValue = <T extends Record<string, unknown>>({
|
|
|
682
703
|
pathToDocument,
|
|
683
704
|
}: // tinaSchema,
|
|
684
705
|
{
|
|
685
|
-
fields: TinaField<true>[]
|
|
686
|
-
values: T
|
|
687
|
-
path: Path
|
|
688
|
-
id: string
|
|
689
|
-
pathToDocument: string
|
|
706
|
+
fields: TinaField<true>[];
|
|
707
|
+
values: T;
|
|
708
|
+
path: Path;
|
|
709
|
+
id: string;
|
|
710
|
+
pathToDocument: string;
|
|
690
711
|
// tinaSchema: TinaSchema
|
|
691
712
|
}): T & { __typename?: string } => {
|
|
692
|
-
const accum: Record<string, unknown> = {}
|
|
713
|
+
const accum: Record<string, unknown> = {};
|
|
693
714
|
fields.forEach((field) => {
|
|
694
|
-
const v = values[field.name]
|
|
715
|
+
const v = values[field.name];
|
|
695
716
|
if (typeof v === 'undefined') {
|
|
696
|
-
return
|
|
717
|
+
return;
|
|
697
718
|
}
|
|
698
719
|
if (v === null) {
|
|
699
|
-
return
|
|
720
|
+
return;
|
|
700
721
|
}
|
|
701
722
|
accum[field.name] = resolveFieldValue({
|
|
702
723
|
field,
|
|
@@ -704,10 +725,10 @@ const resolveFormValue = <T extends Record<string, unknown>>({
|
|
|
704
725
|
path,
|
|
705
726
|
id,
|
|
706
727
|
pathToDocument,
|
|
707
|
-
})
|
|
708
|
-
})
|
|
709
|
-
return accum as T & { __typename?: string }
|
|
710
|
-
}
|
|
728
|
+
});
|
|
729
|
+
});
|
|
730
|
+
return accum as T & { __typename?: string };
|
|
731
|
+
};
|
|
711
732
|
const resolveFieldValue = ({
|
|
712
733
|
field,
|
|
713
734
|
value,
|
|
@@ -715,11 +736,11 @@ const resolveFieldValue = ({
|
|
|
715
736
|
id,
|
|
716
737
|
pathToDocument,
|
|
717
738
|
}: {
|
|
718
|
-
field: TinaField<true
|
|
719
|
-
value: unknown
|
|
720
|
-
path: Path
|
|
721
|
-
id: string
|
|
722
|
-
pathToDocument: string
|
|
739
|
+
field: TinaField<true>;
|
|
740
|
+
value: unknown;
|
|
741
|
+
path: Path;
|
|
742
|
+
id: string;
|
|
743
|
+
pathToDocument: string;
|
|
723
744
|
}) => {
|
|
724
745
|
switch (field.type) {
|
|
725
746
|
case 'object': {
|
|
@@ -727,15 +748,17 @@ const resolveFieldValue = ({
|
|
|
727
748
|
if (field.list) {
|
|
728
749
|
if (Array.isArray(value)) {
|
|
729
750
|
return value.map((item, index) => {
|
|
730
|
-
const template = field.templates[item._template]
|
|
751
|
+
const template = field.templates[item._template];
|
|
731
752
|
if (typeof template === 'string') {
|
|
732
|
-
throw new Error('Global templates not supported')
|
|
753
|
+
throw new Error('Global templates not supported');
|
|
733
754
|
}
|
|
734
|
-
const nextPath = [...path, field.name, index]
|
|
735
|
-
const metadataFields: Record<string, string> = {}
|
|
755
|
+
const nextPath = [...path, field.name, index];
|
|
756
|
+
const metadataFields: Record<string, string> = {};
|
|
736
757
|
template.fields.forEach((field) => {
|
|
737
|
-
metadataFields[field.name] = [...nextPath, field.name].join(
|
|
738
|
-
|
|
758
|
+
metadataFields[field.name] = [...nextPath, field.name].join(
|
|
759
|
+
'.'
|
|
760
|
+
);
|
|
761
|
+
});
|
|
739
762
|
return {
|
|
740
763
|
__typename: NAMER.dataTypeName(template.namespace),
|
|
741
764
|
_tina_metadata: {
|
|
@@ -751,29 +774,29 @@ const resolveFieldValue = ({
|
|
|
751
774
|
id,
|
|
752
775
|
pathToDocument,
|
|
753
776
|
}),
|
|
754
|
-
}
|
|
755
|
-
})
|
|
777
|
+
};
|
|
778
|
+
});
|
|
756
779
|
}
|
|
757
780
|
} else {
|
|
758
781
|
// not implemented
|
|
759
782
|
}
|
|
760
783
|
}
|
|
761
784
|
|
|
762
|
-
const templateFields = field.fields
|
|
785
|
+
const templateFields = field.fields;
|
|
763
786
|
if (typeof templateFields === 'string') {
|
|
764
|
-
throw new Error('Global templates not supported')
|
|
787
|
+
throw new Error('Global templates not supported');
|
|
765
788
|
}
|
|
766
789
|
if (!templateFields) {
|
|
767
|
-
throw new Error(`Expected to find sub-fields on field ${field.name}`)
|
|
790
|
+
throw new Error(`Expected to find sub-fields on field ${field.name}`);
|
|
768
791
|
}
|
|
769
792
|
if (field.list) {
|
|
770
793
|
if (Array.isArray(value)) {
|
|
771
794
|
return value.map((item, index) => {
|
|
772
|
-
const nextPath = [...path, field.name, index]
|
|
773
|
-
const metadataFields: Record<string, string> = {}
|
|
795
|
+
const nextPath = [...path, field.name, index];
|
|
796
|
+
const metadataFields: Record<string, string> = {};
|
|
774
797
|
templateFields.forEach((field) => {
|
|
775
|
-
metadataFields[field.name] = [...nextPath, field.name].join('.')
|
|
776
|
-
})
|
|
798
|
+
metadataFields[field.name] = [...nextPath, field.name].join('.');
|
|
799
|
+
});
|
|
777
800
|
return {
|
|
778
801
|
__typename: NAMER.dataTypeName(field.namespace),
|
|
779
802
|
_tina_metadata: {
|
|
@@ -789,15 +812,15 @@ const resolveFieldValue = ({
|
|
|
789
812
|
id,
|
|
790
813
|
pathToDocument,
|
|
791
814
|
}),
|
|
792
|
-
}
|
|
793
|
-
})
|
|
815
|
+
};
|
|
816
|
+
});
|
|
794
817
|
}
|
|
795
818
|
} else {
|
|
796
|
-
const nextPath = [...path, field.name]
|
|
797
|
-
const metadataFields: Record<string, string> = {}
|
|
819
|
+
const nextPath = [...path, field.name];
|
|
820
|
+
const metadataFields: Record<string, string> = {};
|
|
798
821
|
templateFields.forEach((field) => {
|
|
799
|
-
metadataFields[field.name] = [...nextPath, field.name].join('.')
|
|
800
|
-
})
|
|
822
|
+
metadataFields[field.name] = [...nextPath, field.name].join('.');
|
|
823
|
+
});
|
|
801
824
|
return {
|
|
802
825
|
__typename: NAMER.dataTypeName(field.namespace),
|
|
803
826
|
_tina_metadata: {
|
|
@@ -813,18 +836,21 @@ const resolveFieldValue = ({
|
|
|
813
836
|
id,
|
|
814
837
|
pathToDocument,
|
|
815
838
|
}),
|
|
816
|
-
}
|
|
839
|
+
};
|
|
817
840
|
}
|
|
818
841
|
}
|
|
819
842
|
default: {
|
|
820
|
-
return value
|
|
843
|
+
return value;
|
|
821
844
|
}
|
|
822
845
|
}
|
|
823
|
-
}
|
|
846
|
+
};
|
|
824
847
|
|
|
825
848
|
const getDocument = async (id: string, tina: Client) => {
|
|
826
849
|
const response = await tina.request<{
|
|
827
|
-
node: {
|
|
850
|
+
node: {
|
|
851
|
+
_internalSys: SystemInfo;
|
|
852
|
+
_internalValues: Record<string, unknown>;
|
|
853
|
+
};
|
|
828
854
|
}>(
|
|
829
855
|
`query GetNode($id: String!) {
|
|
830
856
|
node(id: $id) {
|
|
@@ -838,6 +864,7 @@ _internalSys: _sys {
|
|
|
838
864
|
extension
|
|
839
865
|
relativePath
|
|
840
866
|
title
|
|
867
|
+
hasReferences
|
|
841
868
|
template
|
|
842
869
|
collection {
|
|
843
870
|
name
|
|
@@ -856,29 +883,29 @@ _internalSys: _sys {
|
|
|
856
883
|
}
|
|
857
884
|
}`,
|
|
858
885
|
{ variables: { id: id } }
|
|
859
|
-
)
|
|
860
|
-
return response.node
|
|
861
|
-
}
|
|
886
|
+
);
|
|
887
|
+
return response.node;
|
|
888
|
+
};
|
|
862
889
|
|
|
863
890
|
const expandPayload = async (
|
|
864
891
|
payload: Payload,
|
|
865
892
|
cms: TinaCMS
|
|
866
893
|
): 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)
|
|
894
|
+
const { query, variables } = payload;
|
|
895
|
+
const documentNode = G.parse(query);
|
|
896
|
+
const expandedDocumentNode = expandQuery({ schema, documentNode });
|
|
897
|
+
const expandedQuery = G.print(expandedDocumentNode);
|
|
871
898
|
const expandedData = await cms.api.tina.request<object>(expandedQuery, {
|
|
872
899
|
variables,
|
|
873
|
-
})
|
|
900
|
+
});
|
|
874
901
|
|
|
875
902
|
const expandedDocumentNodeForResolver = expandQuery({
|
|
876
903
|
schema: schemaForResolver,
|
|
877
904
|
documentNode,
|
|
878
|
-
})
|
|
879
|
-
const expandedQueryForResolver = G.print(expandedDocumentNodeForResolver)
|
|
880
|
-
return { ...payload, expandedQuery, expandedData, expandedQueryForResolver }
|
|
881
|
-
}
|
|
905
|
+
});
|
|
906
|
+
const expandedQueryForResolver = G.print(expandedDocumentNodeForResolver);
|
|
907
|
+
return { ...payload, expandedQuery, expandedData, expandedQueryForResolver };
|
|
908
|
+
};
|
|
882
909
|
|
|
883
910
|
/**
|
|
884
911
|
* When we resolve the graphql data we check for these errors,
|
|
@@ -886,11 +913,11 @@ const expandPayload = async (
|
|
|
886
913
|
* process it once we have that document
|
|
887
914
|
*/
|
|
888
915
|
class NoFormError extends Error {
|
|
889
|
-
id: string
|
|
916
|
+
id: string;
|
|
890
917
|
constructor(msg: string, id: string) {
|
|
891
|
-
super(msg)
|
|
892
|
-
this.id = id
|
|
893
|
-
Object.setPrototypeOf(this, NoFormError.prototype)
|
|
918
|
+
super(msg);
|
|
919
|
+
this.id = id;
|
|
920
|
+
Object.setPrototypeOf(this, NoFormError.prototype);
|
|
894
921
|
}
|
|
895
922
|
}
|
|
896
923
|
|
|
@@ -898,22 +925,22 @@ const getTemplateForDocument = (
|
|
|
898
925
|
resolvedDocument: ResolvedDocument,
|
|
899
926
|
tinaSchema: TinaSchema
|
|
900
927
|
) => {
|
|
901
|
-
const id = resolvedDocument._internalSys.path
|
|
902
|
-
let collection: Collection<true> | undefined
|
|
928
|
+
const id = resolvedDocument._internalSys.path;
|
|
929
|
+
let collection: Collection<true> | undefined;
|
|
903
930
|
try {
|
|
904
|
-
collection = tinaSchema.getCollectionByFullPath(id)
|
|
931
|
+
collection = tinaSchema.getCollectionByFullPath(id);
|
|
905
932
|
} catch (e) {}
|
|
906
933
|
|
|
907
934
|
if (!collection) {
|
|
908
|
-
throw new Error(`Unable to determine collection for path ${id}`)
|
|
935
|
+
throw new Error(`Unable to determine collection for path ${id}`);
|
|
909
936
|
}
|
|
910
937
|
|
|
911
938
|
const template = tinaSchema.getTemplateForData({
|
|
912
939
|
data: resolvedDocument._internalValues,
|
|
913
940
|
collection,
|
|
914
|
-
})
|
|
915
|
-
return { template, collection }
|
|
916
|
-
}
|
|
941
|
+
});
|
|
942
|
+
return { template, collection };
|
|
943
|
+
};
|
|
917
944
|
|
|
918
945
|
const buildForm = ({
|
|
919
946
|
resolvedDocument,
|
|
@@ -921,18 +948,18 @@ const buildForm = ({
|
|
|
921
948
|
payloadId,
|
|
922
949
|
cms,
|
|
923
950
|
}: {
|
|
924
|
-
resolvedDocument: ResolvedDocument
|
|
925
|
-
tinaSchema: TinaSchema
|
|
926
|
-
payloadId: string
|
|
927
|
-
cms: TinaCMS
|
|
951
|
+
resolvedDocument: ResolvedDocument;
|
|
952
|
+
tinaSchema: TinaSchema;
|
|
953
|
+
payloadId: string;
|
|
954
|
+
cms: TinaCMS;
|
|
928
955
|
}) => {
|
|
929
956
|
const { template, collection } = getTemplateForDocument(
|
|
930
957
|
resolvedDocument,
|
|
931
958
|
tinaSchema
|
|
932
|
-
)
|
|
933
|
-
const id = resolvedDocument._internalSys.path
|
|
934
|
-
let form: Form | undefined
|
|
935
|
-
let shouldRegisterForm = true
|
|
959
|
+
);
|
|
960
|
+
const id = resolvedDocument._internalSys.path;
|
|
961
|
+
let form: Form | undefined;
|
|
962
|
+
let shouldRegisterForm = true;
|
|
936
963
|
const formConfig: FormOptions<any> = {
|
|
937
964
|
id,
|
|
938
965
|
initialValues: resolvedDocument._internalValues,
|
|
@@ -945,10 +972,10 @@ const buildForm = ({
|
|
|
945
972
|
cms
|
|
946
973
|
),
|
|
947
974
|
label: collection.label || collection.name,
|
|
948
|
-
}
|
|
975
|
+
};
|
|
949
976
|
if (tinaSchema.config.config?.formifyCallback) {
|
|
950
977
|
const callback = tinaSchema.config.config
|
|
951
|
-
?.formifyCallback as FormifyCallback
|
|
978
|
+
?.formifyCallback as FormifyCallback;
|
|
952
979
|
form =
|
|
953
980
|
callback(
|
|
954
981
|
{
|
|
@@ -958,30 +985,30 @@ const buildForm = ({
|
|
|
958
985
|
formConfig,
|
|
959
986
|
},
|
|
960
987
|
cms
|
|
961
|
-
) || undefined
|
|
988
|
+
) || undefined;
|
|
962
989
|
if (!form) {
|
|
963
990
|
// If the form isn't created from formify, we still
|
|
964
991
|
// need it, just don't show it to the user.
|
|
965
|
-
shouldRegisterForm = false
|
|
966
|
-
form = new Form(formConfig)
|
|
992
|
+
shouldRegisterForm = false;
|
|
993
|
+
form = new Form(formConfig);
|
|
967
994
|
}
|
|
968
995
|
} else {
|
|
969
996
|
if (collection.ui?.global) {
|
|
970
|
-
form = createGlobalForm(formConfig)
|
|
997
|
+
form = createGlobalForm(formConfig);
|
|
971
998
|
} else {
|
|
972
|
-
form = createForm(formConfig)
|
|
999
|
+
form = createForm(formConfig);
|
|
973
1000
|
}
|
|
974
1001
|
}
|
|
975
1002
|
if (form) {
|
|
976
1003
|
if (shouldRegisterForm) {
|
|
977
1004
|
if (collection.ui?.global) {
|
|
978
|
-
cms.plugins.add(new GlobalFormPlugin(form))
|
|
1005
|
+
cms.plugins.add(new GlobalFormPlugin(form));
|
|
979
1006
|
}
|
|
980
|
-
cms.dispatch({ type: 'forms:add', value: form })
|
|
1007
|
+
cms.dispatch({ type: 'forms:add', value: form });
|
|
981
1008
|
}
|
|
982
1009
|
}
|
|
983
1010
|
if (!form) {
|
|
984
|
-
throw new Error(`No form registered for ${id}.`)
|
|
1011
|
+
throw new Error(`No form registered for ${id}.`);
|
|
985
1012
|
}
|
|
986
|
-
return { template, form }
|
|
987
|
-
}
|
|
1013
|
+
return { template, form };
|
|
1014
|
+
};
|