diff --git a/client/coral-admin/src/containers/UserDetail.js b/client/coral-admin/src/containers/UserDetail.js index 3a458ff83..702ca4d81 100644 --- a/client/coral-admin/src/containers/UserDetail.js +++ b/client/coral-admin/src/containers/UserDetail.js @@ -19,7 +19,7 @@ import update from 'immutability-helper'; import {notify} from 'coral-framework/actions/notification'; const commentConnectionFragment = gql` - fragment CoralAdmin_Moderation_CommentConnection on CommentConnection { + fragment CoralAdmin_UserDetail_CommentConnection on CommentConnection { nodes { ...${getDefinitionName(UserDetailComment.fragments.comment)} } @@ -155,7 +155,7 @@ export const withUserDetailQuery = withQuery(gql` author_id: $author_id, statuses: $statuses }) { - ...CoralAdmin_Moderation_CommentConnection + ...CoralAdmin_UserDetail_CommentConnection } ...${getDefinitionName(UserDetailComment.fragments.root)} ${getSlotFragmentSpreads(slots, 'root')} diff --git a/client/coral-framework/graphql/reduceDocument.js b/client/coral-framework/graphql/reduceDocument.js index 3e0118eba..fb47daaff 100644 --- a/client/coral-framework/graphql/reduceDocument.js +++ b/client/coral-framework/graphql/reduceDocument.js @@ -63,12 +63,32 @@ export function mergeSelectionSets(a, b) { }; } +function getFragment(name, execContext) { + const { + rawFragmentMap, + fragmentMap, + } = execContext; + + if (!(name in fragmentMap)) { + const fragment = rawFragmentMap[name]; + + if (!fragment) { + throw new Error(`fragment ${fragment.name.value} does not exist`); + } + + const typeCondition = fragment.typeCondition.name.value; + const transformed = transformDefinition(fragment, execContext, `type.${typeCondition}`, typeCondition); + fragmentMap[name] = transformed; + } + + return fragmentMap[name]; +} + /** * Return selections with resolved named fragments and directives. */ function getTransformedSelections(definition, path, gqlType, execContext) { const { - fragmentMap, variables, } = execContext; @@ -92,7 +112,7 @@ function getTransformedSelections(definition, path, gqlType, execContext) { return o; } - const fragment = fragmentMap[sel.name.value]; + const fragment = getFragment(sel.name.value, execContext); if (!fragment) { throw new Error(`fragment ${fragment.name.value} does not exist`); @@ -105,20 +125,19 @@ function getTransformedSelections(definition, path, gqlType, execContext) { ...fragment, kind: 'InlineFragment', }; - const transformed = transformDefinition(node, execContext, path, typeCondition); const name = getDefinitionName(node); // Merge existing value. if (name in o) { - o[name] = mergeDefinitions(o[name], transformed); + o[name] = mergeDefinitions(o[name], node); return o; } - o[name] = transformed; + o[name] = node; return o; } - const fragmentSelections = getTransformedSelections(fragment, path, typeCondition, execContext); + const fragmentSelections = fragment.selectionSet.selections; fragmentSelections.forEach((s) => { if (variables && !shouldInclude(s, variables)) { @@ -184,7 +203,8 @@ export default function reduceDocument(document, options = {}) { : `type.${mainDefinition.typeCondition.name.value}`; const execContext = { - fragmentMap: createFragmentMap(fragments), + rawFragmentMap: createFragmentMap(fragments), + fragmentMap: options.fragmentMap || {}, keepFragments: [], variables: options.variables, typeGetter: options.typeGetter || (() => null), diff --git a/client/coral-framework/services/graphql.js b/client/coral-framework/services/graphql.js index 42e9cd8ad..87b8e220a 100644 --- a/client/coral-framework/services/graphql.js +++ b/client/coral-framework/services/graphql.js @@ -9,13 +9,17 @@ import {addTypenameToDocument} from 'apollo-client/queries/queryTransform'; export function createGraphQLService(registry, introspectionData) { const typeGetter = createTypeGetter(introspectionData); + // Use shared fragment map. + // Attention: Fragment names must be unique otherwise weird things will happen. + const fragmentMap = {}; + return { registry, resolveDocument(documentOrCallback, props, context) { let document = typeof documentOrCallback === 'function' ? documentOrCallback(props, context) : documentOrCallback; - document = reduceDocument(registry.resolveFragments(document), {typeGetter}); + document = reduceDocument(registry.resolveFragments(document), {typeGetter, fragmentMap}); // We also add typenames to the document which apollo would usually do, // but we also use the network interface in subscriptions directly