From c0532b9afb6ffbd1846e91010d47133ea892be76 Mon Sep 17 00:00:00 2001 From: Alexa Grey Date: Fri, 9 Jan 2026 12:04:27 -0800 Subject: [PATCH 1/5] [B] Ensure that ordering identifiers are set for certain templates These values were missing and are preventing sibling navigation --- .../definitions/nglp/journal_issue/1.0.0/layouts/main.xml | 1 + .../definitions/nglp/journal_volume/1.0.0/layouts/main.xml | 1 + 2 files changed, 2 insertions(+) diff --git a/lib/schemas/definitions/nglp/journal_issue/1.0.0/layouts/main.xml b/lib/schemas/definitions/nglp/journal_issue/1.0.0/layouts/main.xml index 96fbbf17..5da50e04 100644 --- a/lib/schemas/definitions/nglp/journal_issue/1.0.0/layouts/main.xml +++ b/lib/schemas/definitions/nglp/journal_issue/1.0.0/layouts/main.xml @@ -33,6 +33,7 @@ light + issues parent self diff --git a/lib/schemas/definitions/nglp/journal_volume/1.0.0/layouts/main.xml b/lib/schemas/definitions/nglp/journal_volume/1.0.0/layouts/main.xml index 3f082008..a207e526 100644 --- a/lib/schemas/definitions/nglp/journal_volume/1.0.0/layouts/main.xml +++ b/lib/schemas/definitions/nglp/journal_volume/1.0.0/layouts/main.xml @@ -23,6 +23,7 @@ light + volumes parent self From b23239a3e53f207f407c684d621c40f13f2523c4 Mon Sep 17 00:00:00 2001 From: Alexa Grey Date: Fri, 9 Jan 2026 12:04:56 -0800 Subject: [PATCH 2/5] [C] Enable fragment cache for future use --- app/graphql/types/abstract_object_type.rb | 2 ++ config/initializers/960_gql.rb | 4 ++++ 2 files changed, 6 insertions(+) diff --git a/app/graphql/types/abstract_object_type.rb b/app/graphql/types/abstract_object_type.rb index 8b0181f9..d003bd0e 100644 --- a/app/graphql/types/abstract_object_type.rb +++ b/app/graphql/types/abstract_object_type.rb @@ -5,6 +5,8 @@ module Types class AbstractObjectType < GraphQL::Schema::Object include Support::GraphQLAPI::Enhancements::AbstractObject + include GraphQL::FragmentCache::Object + def current_user_privileged? context[:current_user].try(:has_global_admin_access?) end diff --git a/config/initializers/960_gql.rb b/config/initializers/960_gql.rb index 2d081ab2..244e7201 100644 --- a/config/initializers/960_gql.rb +++ b/config/initializers/960_gql.rb @@ -1,5 +1,9 @@ # frozen_string_literal: true +GraphQL::FragmentCache.configure do |config| + config.cache_store = Rails.cache +end + ActiveSupport::Notifications.subscribe(/graphql/) do |event| # :nocov: name = event.name From 986c126830262fc35a8aa02e490821efd1b8793e Mon Sep 17 00:00:00 2001 From: Alexa Grey Date: Fri, 9 Jan 2026 12:05:59 -0800 Subject: [PATCH 3/5] [C] Add slow frontend queries for further testing --- .../CommunityUpdateDrawerQuery.graphql | 393 +++++++ .../data/queries/DashboardLayoutQuery.graphql | 139 +++ spec/data/queries/IntrospectionQuery.graphql | 1 + spec/data/queries/ViewCounterQuery.graphql | 16 + .../queries/collectionMetadataQuery.graphql | 34 + .../queries/communityMetadataQuery.graphql | 34 + ...ilsManageSlugCommunitiesPagesQuery.graphql | 391 +++++++ .../getStaticGlobalContextDataQuery.graphql | 27 + .../getStaticGoogleScholarDataQuery.graphql | 131 +++ spec/data/queries/itemMetadataQuery.graphql | 42 + .../itemsSlugCollectionsPagesQuery.graphql | 294 +++++ spec/data/queries/layoutAllPagesQuery.graphql | 94 ++ .../layoutCollectionTemplateQuery.graphql | 757 ++++++++++++ .../layoutCommunityTemplateQuery.graphql | 713 ++++++++++++ .../queries/layoutItemTemplateQuery.graphql | 879 ++++++++++++++ .../pageBrowseCommunityOrderingQuery.graphql | 425 +++++++ .../pageCollectionTemplateQuery.graphql | 1002 ++++++++++++++++ .../pageContributorDetailQuery.graphql | 162 +++ .../pageInstanceContentLayoutQuery.graphql | 81 ++ .../queries/pageItemTemplateQuery.graphql | 991 ++++++++++++++++ spec/data/queries/pageTemplateQuery.graphql | 991 ++++++++++++++++ ...pageTemplatesBrowseCollectionQuery.graphql | 425 +++++++ ...pageTemplatesItemContributorsQuery.graphql | 75 ++ .../pageTemplatesItemFileDetailQuery.graphql | 61 + .../pageTemplatesItemFilesQuery.graphql | 63 + .../pageTemplatesItemMetadataQuery.graphql | 1022 +++++++++++++++++ .../pageTemplatesItemMetricsQuery.graphql | 49 + .../frontend/page_template_query_spec.rb | 48 + spec/support/helpers/graphql_helpers.rb | 9 + 29 files changed, 9349 insertions(+) create mode 100644 spec/data/queries/CommunityUpdateDrawerQuery.graphql create mode 100644 spec/data/queries/DashboardLayoutQuery.graphql create mode 100644 spec/data/queries/IntrospectionQuery.graphql create mode 100644 spec/data/queries/ViewCounterQuery.graphql create mode 100644 spec/data/queries/collectionMetadataQuery.graphql create mode 100644 spec/data/queries/communityMetadataQuery.graphql create mode 100644 spec/data/queries/detailsManageSlugCommunitiesPagesQuery.graphql create mode 100644 spec/data/queries/getStaticGlobalContextDataQuery.graphql create mode 100644 spec/data/queries/getStaticGoogleScholarDataQuery.graphql create mode 100644 spec/data/queries/itemMetadataQuery.graphql create mode 100644 spec/data/queries/itemsSlugCollectionsPagesQuery.graphql create mode 100644 spec/data/queries/layoutAllPagesQuery.graphql create mode 100644 spec/data/queries/layoutCollectionTemplateQuery.graphql create mode 100644 spec/data/queries/layoutCommunityTemplateQuery.graphql create mode 100644 spec/data/queries/layoutItemTemplateQuery.graphql create mode 100644 spec/data/queries/pageBrowseCommunityOrderingQuery.graphql create mode 100644 spec/data/queries/pageCollectionTemplateQuery.graphql create mode 100644 spec/data/queries/pageContributorDetailQuery.graphql create mode 100644 spec/data/queries/pageInstanceContentLayoutQuery.graphql create mode 100644 spec/data/queries/pageItemTemplateQuery.graphql create mode 100644 spec/data/queries/pageTemplateQuery.graphql create mode 100644 spec/data/queries/pageTemplatesBrowseCollectionQuery.graphql create mode 100644 spec/data/queries/pageTemplatesItemContributorsQuery.graphql create mode 100644 spec/data/queries/pageTemplatesItemFileDetailQuery.graphql create mode 100644 spec/data/queries/pageTemplatesItemFilesQuery.graphql create mode 100644 spec/data/queries/pageTemplatesItemMetadataQuery.graphql create mode 100644 spec/data/queries/pageTemplatesItemMetricsQuery.graphql create mode 100644 spec/requests/graphql/frontend/page_template_query_spec.rb diff --git a/spec/data/queries/CommunityUpdateDrawerQuery.graphql b/spec/data/queries/CommunityUpdateDrawerQuery.graphql new file mode 100644 index 00000000..2ed98a79 --- /dev/null +++ b/spec/data/queries/CommunityUpdateDrawerQuery.graphql @@ -0,0 +1,393 @@ +query CommunityUpdateDrawerQuery( + $communitySlug: Slug! +) { + community(slug: $communitySlug) { + id + title + ...CommunityUpdateFormFragment + allowedActions + } +} + +fragment AssetPropertyFragment on AssetProperty { + ...ScalarPropertyFragment +} + +fragment AssetsPropertyFragment on AssetsProperty { + ...ScalarPropertyFragment +} + +fragment BooleanPropertyFragment on BooleanProperty { + ...ScalarPropertyFragment + checked + checkedByDefault +} + +fragment CommunityUpdateFormFieldsFragment on Community { + title + tagline + summary + heroImageLayout + position + heroImage { + ...FileUploadFragment + } + logo { + ...FileUploadFragment + } + heroImageMetadata { + alt + } +} + +fragment CommunityUpdateFormFragment on Community { + communityId: id + ...CommunityUpdateFormFieldsFragment + ...SchemaFormFieldsFragment + ...useSchemaPropertiesFragment + context: schemaInstanceContext { + ...useSchemaContextFragment + } +} + +fragment ContributorPropertyFragment on ContributorProperty { + ...ScalarPropertyFragment +} + +fragment ContributorsPropertyFragment on ContributorsProperty { + ...ScalarPropertyFragment +} + +fragment DatePropertyFragment on DateProperty { + ...ScalarPropertyFragment + date +} + +fragment EmailPropertyFragment on EmailProperty { + ...ScalarPropertyFragment + address + defaultAddress +} + +fragment EntitiesPropertyFragment on EntitiesProperty { + ...ScalarPropertyFragment + availableEntities { + label + value + entity { + __typename + ...getEntityTitleFragment + ... on Node { + __isNode: __typename + id + } + } + } +} + +fragment EntityPropertyFragment on EntityProperty { + ...ScalarPropertyFragment + availableEntities { + label + value + entity { + __typename + ...getEntityTitleFragment + ... on Node { + __isNode: __typename + id + } + } + } +} + +fragment FileUploadFragment on ImageAttachment { + originalFilename + storage + thumb { + png { + alt + url + } + } +} + +fragment FloatPropertyFragment on FloatProperty { + ...ScalarPropertyFragment + floatValue + defaultFloat +} + +fragment FullTextPropertyFragment on FullTextProperty { + ...ScalarPropertyFragment + description + fullText { + content + kind + lang + } +} + +fragment GroupPropertyFragment on GroupProperty { + legend + path + properties { + __typename + ...SchemaPropertyFragment + } +} + +fragment IntegerPropertyFragment on IntegerProperty { + ...ScalarPropertyFragment + integerValue + defaultInteger +} + +fragment MarkdownPropertyFragment on MarkdownProperty { + ...ScalarPropertyFragment + content + default +} + +fragment MultiselectPropertyFragment on MultiselectProperty { + ...ScalarPropertyFragment + options { + label + value + } +} + +fragment ScalarPropertyFragment on ScalarProperty { + __isScalarProperty: __typename + name: fullPath + label + path + required + type + isWide +} + +fragment SchemaFormFieldsContextFragment on SchemaInstance { + __isSchemaInstance: __typename + context: schemaInstanceContext { + ...useSchemaContextFragment + } + ... on Node { + __isNode: __typename + id + } +} + +fragment SchemaFormFieldsFragment on SchemaInstance { + __isSchemaInstance: __typename + properties: schemaProperties { + __typename + ...SchemaInstancePropertyFragment + } + ...SchemaSelectorDataFragment + ...SchemaFormFieldsContextFragment +} + +fragment SchemaInstancePropertyFragment on SchemaProperty { + __isSchemaProperty: __typename + __typename + ... on GroupProperty { + ...GroupPropertyFragment + } + ...SchemaPropertyFragment +} + +fragment SchemaPropertyFragment on ScalarProperty { + __isScalarProperty: __typename + __typename + ... on AssetProperty { + ...AssetPropertyFragment + } + ... on AssetsProperty { + ...AssetsPropertyFragment + } + ... on BooleanProperty { + ...BooleanPropertyFragment + } + ... on ContributorProperty { + ...ContributorPropertyFragment + } + ... on ContributorsProperty { + ...ContributorsPropertyFragment + } + ... on DateProperty { + ...DatePropertyFragment + } + ... on EmailProperty { + ...EmailPropertyFragment + } + ... on FloatProperty { + ...FloatPropertyFragment + } + ... on IntegerProperty { + ...IntegerPropertyFragment + } + ... on MarkdownProperty { + ...MarkdownPropertyFragment + } + ... on MultiselectProperty { + ...MultiselectPropertyFragment + } + ... on SelectProperty { + ...SelectPropertyFragment + } + ... on StringProperty { + ...StringPropertyFragment + } + ... on TagsProperty { + ...TagsPropertyFragment + } + ... on FullTextProperty { + ...FullTextPropertyFragment + } + ... on URLProperty { + ...URLPropertyFragment + } + ... on VariableDateProperty { + ...VariableDatePropertyFragment + } + ... on EntityProperty { + ...EntityPropertyFragment + } + ... on EntitiesProperty { + ...EntitiesPropertyFragment + } +} + +fragment SchemaSelectorDataFragment on Entity { + __isEntity: __typename + ... on Collection { + entityId: id + schemaVersion { + name + number + slug + id + } + } + ... on Item { + entityId: id + schemaVersion { + name + number + slug + id + } + } + ... on Community { + entityId: id + schemaVersion { + name + number + slug + id + } + } +} + +fragment SelectPropertyFragment on SelectProperty { + options { + label + value + } + ...ScalarPropertyFragment +} + +fragment StringPropertyFragment on StringProperty { + ...ScalarPropertyFragment + content + default +} + +fragment TagsPropertyFragment on TagsProperty { + ...ScalarPropertyFragment + tags +} + +fragment URLPropertyFragment on URLProperty { + ...ScalarPropertyFragment + url { + href + label + title + } +} + +fragment VariableDatePropertyFragment on VariableDateProperty { + ...ScalarPropertyFragment + dateWithPrecision { + ...VariablePrecisionDateControlFragment + } +} + +fragment VariablePrecisionDateControlFragment on VariablePrecisionDate { + precision + value +} + +fragment getEntityTitleFragment on Entity { + __isEntity: __typename + __typename + title + schemaVersion { + identifier + id + } + ... on Collection { + namedAncestors { + ancestor { + __typename + __isEntity: __typename + title + ... on Node { + __isNode: __typename + id + } + } + } + } + ... on Item { + namedAncestors { + ancestor { + __typename + __isEntity: __typename + title + ... on Node { + __isNode: __typename + id + } + } + } + } +} + +fragment useSchemaContextFragment on SchemaInstanceContext { + assets { + kind + label + value + } + contributors { + kind + label + value + } + defaultValues + entityId + fieldValues + schemaVersionSlug +} + +fragment useSchemaPropertiesFragment on SchemaInstance { + __isSchemaInstance: __typename + properties: schemaProperties { + __typename + __isSchemaProperty: __typename + fullPath + } +} diff --git a/spec/data/queries/DashboardLayoutQuery.graphql b/spec/data/queries/DashboardLayoutQuery.graphql new file mode 100644 index 00000000..9003211d --- /dev/null +++ b/spec/data/queries/DashboardLayoutQuery.graphql @@ -0,0 +1,139 @@ +query DashboardLayoutQuery( + $page: Int + $order: EntityOrder +) { + ...DashboardInstallationFragment + ...DashboardCollectionsFragment_1KnpCu + ...DashboardItemsFragment_1KnpCu +} + +fragment DashboardCollectionsFragment_1KnpCu on Query { + viewer { + collections(access: UPDATE, page: $page, order: $order, perPage: 10) { + ...DashboardCollectionsListFragment + } + id + } +} + +fragment DashboardCollectionsListFragment on CollectionConnection { + nodes { + id + title + slug + schemaVersion { + name + number + id + } + ...EntityThumbnailColumnFragment + } + ...ModelPageCountActionsFragment + ...ModelPaginationFragment +} + +fragment DashboardInstallationFragment on Query { + communities { + pageInfo { + totalCount + } + } + contributors { + pageInfo { + totalCount + } + } + users { + pageInfo { + totalCount + } + } + viewer { + allCollections: collections(nodeFilter: ROOTS_AND_LEAVES) { + pageInfo { + totalCount + } + } + allItems: items(nodeFilter: ROOTS_AND_LEAVES) { + pageInfo { + totalCount + } + } + id + } +} + +fragment DashboardItemsFragment_1KnpCu on Query { + viewer { + items(access: UPDATE, page: $page, order: $order, perPage: 10) { + ...DashboardItemsListFragment + } + id + } +} + +fragment DashboardItemsListFragment on ItemConnection { + nodes { + id + title + slug + schemaVersion { + name + number + id + } + ...EntityThumbnailColumnFragment + } + ...ModelPageCountActionsFragment + ...ModelPaginationFragment +} + +fragment EntityThumbnailColumnFragment on Entity { + __isEntity: __typename + __typename + title + thumbnail { + storage + thumb: small { + webp { + ...ImageFragment + } + } + } + ... on Node { + __isNode: __typename + id + } + ... on Sluggable { + __isSluggable: __typename + slug + } +} + +fragment ImageFragment on Image { + __isImage: __typename + alt + url + width + height +} + +fragment ModelPageCountActionsFragment on Paginated { + __isPaginated: __typename + pageInfo { + page + pageCount + perPage + hasNextPage + hasPreviousPage + totalCount + } +} + +fragment ModelPaginationFragment on Paginated { + __isPaginated: __typename + pageInfo { + page + pageCount + } +} diff --git a/spec/data/queries/IntrospectionQuery.graphql b/spec/data/queries/IntrospectionQuery.graphql new file mode 100644 index 00000000..6e868185 --- /dev/null +++ b/spec/data/queries/IntrospectionQuery.graphql @@ -0,0 +1 @@ +query IntrospectionQuery{__schema{queryType{name}mutationType{name}subscriptionType{name}types{...FullType}directives{name description locations args{...InputValue}}}}fragment FullType on __Type{kind name description fields(includeDeprecated:true){name description args{...InputValue}type{...TypeRef}isDeprecated deprecationReason}inputFields{...InputValue}interfaces{...TypeRef}enumValues(includeDeprecated:true){name description isDeprecated deprecationReason}possibleTypes{...TypeRef}}fragment InputValue on __InputValue{name description type{...TypeRef}defaultValue}fragment TypeRef on __Type{kind name ofType{kind name ofType{kind name ofType{kind name ofType{kind name ofType{kind name ofType{kind name ofType{kind name}}}}}}}} \ No newline at end of file diff --git a/spec/data/queries/ViewCounterQuery.graphql b/spec/data/queries/ViewCounterQuery.graphql new file mode 100644 index 00000000..a963368f --- /dev/null +++ b/spec/data/queries/ViewCounterQuery.graphql @@ -0,0 +1,16 @@ +query ViewCounterQuery( + $slug: Slug! +) { + item(slug: $slug) { + __typename + id + } + collection(slug: $slug) { + __typename + id + } + community(slug: $slug) { + __typename + id + } +} diff --git a/spec/data/queries/collectionMetadataQuery.graphql b/spec/data/queries/collectionMetadataQuery.graphql new file mode 100644 index 00000000..acf9cc96 --- /dev/null +++ b/spec/data/queries/collectionMetadataQuery.graphql @@ -0,0 +1,34 @@ +query collectionMetadataQuery( + $slug: Slug! +) { + collection(slug: $slug) { + title + heroImage { + image: large { + webp { + url + } + } + } + heroImageMetadata { + alt + } + thumbnail { + image: large { + webp { + url + } + } + } + thumbnailMetadata { + alt + } + about: schemaProperty(fullPath: "about") { + __typename + ... on MarkdownProperty { + content + } + } + id + } +} diff --git a/spec/data/queries/communityMetadataQuery.graphql b/spec/data/queries/communityMetadataQuery.graphql new file mode 100644 index 00000000..07ac6357 --- /dev/null +++ b/spec/data/queries/communityMetadataQuery.graphql @@ -0,0 +1,34 @@ +query communityMetadataQuery( + $slug: Slug! +) { + community(slug: $slug) { + title + heroImage { + image: large { + webp { + url + } + } + } + heroImageMetadata { + alt + } + thumbnail { + image: large { + webp { + url + } + } + } + thumbnailMetadata { + alt + } + about: schemaProperty(fullPath: "about") { + __typename + ... on MarkdownProperty { + content + } + } + id + } +} diff --git a/spec/data/queries/detailsManageSlugCommunitiesPagesQuery.graphql b/spec/data/queries/detailsManageSlugCommunitiesPagesQuery.graphql new file mode 100644 index 00000000..d95c5c3b --- /dev/null +++ b/spec/data/queries/detailsManageSlugCommunitiesPagesQuery.graphql @@ -0,0 +1,391 @@ +query detailsManageSlugCommunitiesPagesQuery( + $slug: Slug! +) { + community(slug: $slug) { + ...CommunityUpdateFormFragment + id + } +} + +fragment AssetPropertyFragment on AssetProperty { + ...ScalarPropertyFragment +} + +fragment AssetsPropertyFragment on AssetsProperty { + ...ScalarPropertyFragment +} + +fragment BooleanPropertyFragment on BooleanProperty { + ...ScalarPropertyFragment + checked + checkedByDefault +} + +fragment CommunityUpdateFormFieldsFragment on Community { + title + tagline + summary + heroImageLayout + position + heroImage { + ...FileUploadFragment + } + logo { + ...FileUploadFragment + } + heroImageMetadata { + alt + } +} + +fragment CommunityUpdateFormFragment on Community { + communityId: id + ...CommunityUpdateFormFieldsFragment + ...SchemaFormFieldsFragment + ...useSchemaPropertiesFragment + context: schemaInstanceContext { + ...useSchemaContextFragment + } +} + +fragment ContributorPropertyFragment on ContributorProperty { + ...ScalarPropertyFragment +} + +fragment ContributorsPropertyFragment on ContributorsProperty { + ...ScalarPropertyFragment +} + +fragment DatePropertyFragment on DateProperty { + ...ScalarPropertyFragment + date +} + +fragment EmailPropertyFragment on EmailProperty { + ...ScalarPropertyFragment + address + defaultAddress +} + +fragment EntitiesPropertyFragment on EntitiesProperty { + ...ScalarPropertyFragment + availableEntities { + label + value + entity { + __typename + ...getEntityTitleFragment + ... on Node { + __isNode: __typename + id + } + } + } +} + +fragment EntityPropertyFragment on EntityProperty { + ...ScalarPropertyFragment + availableEntities { + label + value + entity { + __typename + ...getEntityTitleFragment + ... on Node { + __isNode: __typename + id + } + } + } +} + +fragment FileUploadFragment on ImageAttachment { + originalFilename + storage + thumb { + png { + alt + url + } + } +} + +fragment FloatPropertyFragment on FloatProperty { + ...ScalarPropertyFragment + floatValue + defaultFloat +} + +fragment FullTextPropertyFragment on FullTextProperty { + ...ScalarPropertyFragment + description + fullText { + content + kind + lang + } +} + +fragment GroupPropertyFragment on GroupProperty { + legend + path + properties { + __typename + ...SchemaPropertyFragment + } +} + +fragment IntegerPropertyFragment on IntegerProperty { + ...ScalarPropertyFragment + integerValue + defaultInteger +} + +fragment MarkdownPropertyFragment on MarkdownProperty { + ...ScalarPropertyFragment + content + default +} + +fragment MultiselectPropertyFragment on MultiselectProperty { + ...ScalarPropertyFragment + options { + label + value + } +} + +fragment ScalarPropertyFragment on ScalarProperty { + __isScalarProperty: __typename + name: fullPath + label + path + required + type + isWide +} + +fragment SchemaFormFieldsContextFragment on SchemaInstance { + __isSchemaInstance: __typename + context: schemaInstanceContext { + ...useSchemaContextFragment + } + ... on Node { + __isNode: __typename + id + } +} + +fragment SchemaFormFieldsFragment on SchemaInstance { + __isSchemaInstance: __typename + properties: schemaProperties { + __typename + ...SchemaInstancePropertyFragment + } + ...SchemaSelectorDataFragment + ...SchemaFormFieldsContextFragment +} + +fragment SchemaInstancePropertyFragment on SchemaProperty { + __isSchemaProperty: __typename + __typename + ... on GroupProperty { + ...GroupPropertyFragment + } + ...SchemaPropertyFragment +} + +fragment SchemaPropertyFragment on ScalarProperty { + __isScalarProperty: __typename + __typename + ... on AssetProperty { + ...AssetPropertyFragment + } + ... on AssetsProperty { + ...AssetsPropertyFragment + } + ... on BooleanProperty { + ...BooleanPropertyFragment + } + ... on ContributorProperty { + ...ContributorPropertyFragment + } + ... on ContributorsProperty { + ...ContributorsPropertyFragment + } + ... on DateProperty { + ...DatePropertyFragment + } + ... on EmailProperty { + ...EmailPropertyFragment + } + ... on FloatProperty { + ...FloatPropertyFragment + } + ... on IntegerProperty { + ...IntegerPropertyFragment + } + ... on MarkdownProperty { + ...MarkdownPropertyFragment + } + ... on MultiselectProperty { + ...MultiselectPropertyFragment + } + ... on SelectProperty { + ...SelectPropertyFragment + } + ... on StringProperty { + ...StringPropertyFragment + } + ... on TagsProperty { + ...TagsPropertyFragment + } + ... on FullTextProperty { + ...FullTextPropertyFragment + } + ... on URLProperty { + ...URLPropertyFragment + } + ... on VariableDateProperty { + ...VariableDatePropertyFragment + } + ... on EntityProperty { + ...EntityPropertyFragment + } + ... on EntitiesProperty { + ...EntitiesPropertyFragment + } +} + +fragment SchemaSelectorDataFragment on Entity { + __isEntity: __typename + ... on Collection { + entityId: id + schemaVersion { + name + number + slug + id + } + } + ... on Item { + entityId: id + schemaVersion { + name + number + slug + id + } + } + ... on Community { + entityId: id + schemaVersion { + name + number + slug + id + } + } +} + +fragment SelectPropertyFragment on SelectProperty { + options { + label + value + } + ...ScalarPropertyFragment +} + +fragment StringPropertyFragment on StringProperty { + ...ScalarPropertyFragment + content + default +} + +fragment TagsPropertyFragment on TagsProperty { + ...ScalarPropertyFragment + tags +} + +fragment URLPropertyFragment on URLProperty { + ...ScalarPropertyFragment + url { + href + label + title + } +} + +fragment VariableDatePropertyFragment on VariableDateProperty { + ...ScalarPropertyFragment + dateWithPrecision { + ...VariablePrecisionDateControlFragment + } +} + +fragment VariablePrecisionDateControlFragment on VariablePrecisionDate { + precision + value +} + +fragment getEntityTitleFragment on Entity { + __isEntity: __typename + __typename + title + schemaVersion { + identifier + id + } + ... on Collection { + namedAncestors { + ancestor { + __typename + __isEntity: __typename + title + ... on Node { + __isNode: __typename + id + } + } + } + } + ... on Item { + namedAncestors { + ancestor { + __typename + __isEntity: __typename + title + ... on Node { + __isNode: __typename + id + } + } + } + } +} + +fragment useSchemaContextFragment on SchemaInstanceContext { + assets { + kind + label + value + } + contributors { + kind + label + value + } + defaultValues + entityId + fieldValues + schemaVersionSlug +} + +fragment useSchemaPropertiesFragment on SchemaInstance { + __isSchemaInstance: __typename + properties: schemaProperties { + __typename + __isSchemaProperty: __typename + fullPath + } +} diff --git a/spec/data/queries/getStaticGlobalContextDataQuery.graphql b/spec/data/queries/getStaticGlobalContextDataQuery.graphql new file mode 100644 index 00000000..7d84ce71 --- /dev/null +++ b/spec/data/queries/getStaticGlobalContextDataQuery.graphql @@ -0,0 +1,27 @@ +query getStaticGlobalContextDataQuery { + globalConfiguration { + site { + providerName + installationName + installationHomePageCopy + logoMode + footer { + description + copyrightStatement + } + } + entities { + suppressExternalLinks + } + id + } + allCommunities: communities(order: POSITION_ASCENDING) { + edges { + node { + slug + title + id + } + } + } +} diff --git a/spec/data/queries/getStaticGoogleScholarDataQuery.graphql b/spec/data/queries/getStaticGoogleScholarDataQuery.graphql new file mode 100644 index 00000000..8e303a6c --- /dev/null +++ b/spec/data/queries/getStaticGoogleScholarDataQuery.graphql @@ -0,0 +1,131 @@ +query getStaticGoogleScholarDataQuery( + $slug: Slug! +) { + item(slug: $slug) { + ...getStaticGoogleScholarDataFragment + id + } +} + +fragment getStaticGoogleScholarDataFragment on Entity { + __isEntity: __typename + ... on Item { + title + schemaDefinition { + identifier + id + } + published { + precision + value + } + pdf: schemaProperty(fullPath: "pdf_version") { + __typename + ... on AssetProperty { + asset { + __typename + ... on AssetPDF { + downloadUrl + } + id + } + } + } + community { + title + id + } + contributions { + nodes { + role + contributor { + __typename + ... on PersonContributor { + __typename + familyName + givenName + } + ... on OrganizationContributor { + __typename + legalName + } + ... on Node { + __isNode: __typename + id + } + } + id + } + } + issueNumber: schemaProperty(fullPath: "issue.number") { + __typename + ... on StringProperty { + value: content + } + } + volumeNumber: schemaProperty(fullPath: "volume.id") { + __typename + ... on StringProperty { + value: content + } + } + startPage: schemaProperty(fullPath: "issue.fpage") { + __typename + ... on IntegerProperty { + value: integerValue + } + } + endPage: schemaProperty(fullPath: "issue.lpage") { + __typename + ... on IntegerProperty { + value: integerValue + } + } + institution: schemaProperty(fullPath: "degree.grantor") { + __typename + ... on StringProperty { + value: content + } + } + journal: ancestorOfType(schema: "nglp:journal") { + __typename + ... on Collection { + title + } + ... on Node { + __isNode: __typename + id + } + } + volume: ancestorOfType(schema: "nglp:journal_volume") { + __typename + ... on Collection { + number: schemaProperty(fullPath: "number") { + __typename + ... on StringProperty { + value: content + } + } + } + ... on Node { + __isNode: __typename + id + } + } + issue: ancestorOfType(schema: "nglp:journal_issue") { + __typename + ... on Collection { + number: schemaProperty(fullPath: "number") { + __typename + ... on StringProperty { + value: content + } + } + } + ... on Node { + __isNode: __typename + id + } + } + } +} diff --git a/spec/data/queries/itemMetadataQuery.graphql b/spec/data/queries/itemMetadataQuery.graphql new file mode 100644 index 00000000..7e9e6054 --- /dev/null +++ b/spec/data/queries/itemMetadataQuery.graphql @@ -0,0 +1,42 @@ +query itemMetadataQuery( + $slug: Slug! +) { + item(slug: $slug) { + title + heroImage { + image: large { + webp { + url + } + } + } + heroImageMetadata { + alt + } + thumbnail { + image: large { + webp { + url + } + } + } + thumbnailMetadata { + alt + } + about: schemaProperty(fullPath: "about") { + __typename + ... on MarkdownProperty { + content + } + } + abstract: schemaProperty(fullPath: "abstract") { + __typename + ... on FullTextProperty { + fullText { + content + } + } + } + id + } +} diff --git a/spec/data/queries/itemsSlugCollectionsPagesQuery.graphql b/spec/data/queries/itemsSlugCollectionsPagesQuery.graphql new file mode 100644 index 00000000..8b71f425 --- /dev/null +++ b/spec/data/queries/itemsSlugCollectionsPagesQuery.graphql @@ -0,0 +1,294 @@ +query itemsSlugCollectionsPagesQuery( + $order: EntityOrder + $page: Int! + $predicates: [SearchPredicateInput!] + $query: String + $hasQuery: Boolean! + $slug: Slug! + $schema: [String!] +) { + collection(slug: $slug) { + items(order: $order, page: $page, perPage: 20) { + ...ItemListFragment + } + search(visibility: ALL, maxDepth: 1) { + ...ItemListSearchFragment_1V70IR + } + id + } +} + +fragment ContributorsColumnFragment on Entity { + __isEntity: __typename + ... on Item { + slug + contributions(page: 1, perPage: 1) { + edges { + node { + contributor { + __typename + ... on OrganizationContributor { + slug + legalName + } + ... on PersonContributor { + slug + givenName + familyName + } + ... on Node { + __isNode: __typename + id + } + } + id + } + } + pageInfo { + totalCount + } + } + } +} + +fragment CurrentSearchFiltersFragment on SearchScope { + coreProperties { + ... on SearchableProperty { + __isSearchableProperty: __typename + searchPath + label + } + } + schemas: availableSchemaVersions { + name + schemaDefinition { + slug + id + } + searchableProperties { + __typename + __isSearchableProperty: __typename + searchPath + label + } + id + } +} + +fragment EntityThumbnailColumnFragment on Entity { + __isEntity: __typename + __typename + title + thumbnail { + storage + thumb: small { + webp { + ...ImageFragment + } + } + } + ... on Node { + __isNode: __typename + id + } + ... on Sluggable { + __isSluggable: __typename + slug + } +} + +fragment ImageFragment on Image { + __isImage: __typename + alt + url + width + height +} + +fragment ItemListFragment on ItemConnection { + nodes { + id + slug + title + schemaVersion { + name + number + id + } + items { + pageInfo { + totalCount + } + } + allowedActions + ...ContributorsColumnFragment + ...EntityThumbnailColumnFragment + ...PublishedDateColumnFragment + } + ...ModelListPageFragment +} + +fragment ItemListSearchFragment_1V70IR on SearchScope { + results(access: UPDATE, query: $query, page: $page, perPage: 20, predicates: $predicates, order: $order, scope: ITEM, schema: $schema) @include(if: $hasQuery) { + nodes { + slug + entity { + __typename + ... on Node { + __isNode: __typename + id + } + ... on Sluggable { + __isSluggable: __typename + slug + } + __isEntity: __typename + title + schemaVersion { + name + number + id + } + allowedActions + ...ContributorsColumnFragment + ...EntityThumbnailColumnFragment + ...PublishedDateColumnFragment + ... on Item { + items { + pageInfo { + totalCount + } + } + } + } + id + } + ...ModelListPageFragment + } + ...ModelListPageSearchFragment +} + +fragment ModelListPageFragment on Paginated { + __isPaginated: __typename + ...ModelPageCountActionsFragment + ...ModelPaginationFragment +} + +fragment ModelListPageSearchFragment on SearchScope { + ...CurrentSearchFiltersFragment + ...SearchWithFiltersFragment +} + +fragment ModelPageCountActionsFragment on Paginated { + __isPaginated: __typename + pageInfo { + page + pageCount + perPage + hasNextPage + hasPreviousPage + totalCount + } +} + +fragment ModelPaginationFragment on Paginated { + __isPaginated: __typename + pageInfo { + page + pageCount + } +} + +fragment PrecisionDateFragment on VariablePrecisionDate { + precision + value +} + +fragment PublishedDateColumnFragment on ReferencesGlobalEntityDates { + __isReferencesGlobalEntityDates: __typename + published { + ...PrecisionDateFragment + } +} + +fragment SearchFilterBooleanFragment on SearchableProperty { + __isSearchableProperty: __typename + label + description + searchPath + searchOperators +} + +fragment SearchFilterDrawerFragment on SearchScope { + ...SearchFilterFormFragment +} + +fragment SearchFilterFormFragment on SearchScope { + coreProperties { + ... on SearchableProperty { + __isSearchableProperty: __typename + searchPath + } + ...SearchFilterFragment + } + schemas: availableSchemaVersions { + searchableProperties { + __typename + __isSearchableProperty: __typename + searchPath + label + ...SearchFilterFragment + } + id + } + ...SearchSchemaFilterFragment +} + +fragment SearchFilterFragment on SearchableProperty { + __isSearchableProperty: __typename + ... on ScalarProperty { + __isScalarProperty: __typename + type + } + ...SearchFilterInputFragment + ...SearchFilterSelectFragment + ...SearchFilterBooleanFragment +} + +fragment SearchFilterInputFragment on SearchableProperty { + __isSearchableProperty: __typename + label + description + searchPath + searchOperators +} + +fragment SearchFilterSelectFragment on SearchableProperty { + __isSearchableProperty: __typename + label + description + searchPath + searchOperators + ... on SelectProperty { + options { + label + value + } + } +} + +fragment SearchSchemaFilterFragment on SearchScope { + schemas: availableSchemaVersions { + name + kind + schemaDefinition { + slug + id + } + id + } +} + +fragment SearchWithFiltersFragment on SearchScope { + ...SearchFilterDrawerFragment +} diff --git a/spec/data/queries/layoutAllPagesQuery.graphql b/spec/data/queries/layoutAllPagesQuery.graphql new file mode 100644 index 00000000..c4296aca --- /dev/null +++ b/spec/data/queries/layoutAllPagesQuery.graphql @@ -0,0 +1,94 @@ +query layoutAllPagesQuery { + ...ViewerContextFragment + ...AppBodyFragment +} + +fragment AppBodyFragment on Query { + ...AppHeaderFragment + ...AppFooterFragment +} + +fragment AppFooterFragment on Query { + communities(order: POSITION_ASCENDING) { + pageInfo { + totalCount + } + } + globalConfiguration { + ...InstallationNameFragment + id + } + ...CommunityPickerFragment +} + +fragment AppHeaderFragment on Query { + communities(order: POSITION_ASCENDING) { + pageInfo { + totalCount + } + } + globalConfiguration { + site { + logoMode + } + ...InstallationNameFragment + id + } + ...CommunityPickerFragment +} + +fragment CommunityPickerFragment on Query { + pickerCommunities: communities(order: POSITION_ASCENDING) { + edges { + node { + slug + title + id + } + } + } +} + +fragment InstallationNameFragment on GlobalConfiguration { + site { + installationName + logoMode + } + logo { + storage + original { + originalFilename + alt + url + width + height + } + sansText { + size + webp { + alt + url + width + height + } + } + } +} + +fragment ViewerContextFragment on Query { + viewer { + name + allowedActions + uploadAccess + uploadToken + avatar { + small { + png { + url + alt + } + } + } + id + } +} diff --git a/spec/data/queries/layoutCollectionTemplateQuery.graphql b/spec/data/queries/layoutCollectionTemplateQuery.graphql new file mode 100644 index 00000000..ff01d91b --- /dev/null +++ b/spec/data/queries/layoutCollectionTemplateQuery.graphql @@ -0,0 +1,757 @@ +query layoutCollectionTemplateQuery( + $slug: Slug! +) { + collection(slug: $slug) { + layouts { + hero { + ...HeroTemplateFragment + id + } + ...ProcessingCheckFragment + } + ...SearchButtonFragment + ...EntityNavBarFragment + community { + ...SetCommunityFragment + id + } + id + } +} + +fragment BreadcrumbLinkFragment on EntityBreadcrumb { + label + kind + slug +} + +fragment BreadcrumbsBarFragment on Entity { + __isEntity: __typename + __typename + title + ... on Sluggable { + __isSluggable: __typename + slug + } + ... on Permalinkable { + __isPermalinkable: __typename + permalinks { + canonical + uri + id + } + } + ...BreadcrumbsFragment +} + +fragment BreadcrumbsFragment on Entity { + __isEntity: __typename + __typename + title + breadcrumbs { + depth + ...BreadcrumbLinkFragment + id + } + ... on Sluggable { + __isSluggable: __typename + slug + } +} + +fragment CommunityContextFragment on Community { + ...CommunityNameFragment + ...CommunityNavListFragment + ...CommunityPickerCommunityNameFragment +} + +fragment CommunityHeroHeaderFragment on HeroLayoutInstance { + entity { + __typename + ... on Community { + heroImage { + ...ImageHeroTemplateFragment + hero { + webp { + url + } + } + } + heroImageLayout + } + ... on Node { + __isNode: __typename + id + } + } + template { + definition { + showHeroImage + showBigSearchPrompt + id + } + slots { + bigSearchPrompt { + ...sharedInlineSlotFragment + } + header { + empty + } + headerSummary { + empty + } + } + ...HeaderHeroFragment + id + } +} + +fragment CommunityLogoFragment on ImageAttachment { + storage + original { + url + alt + width + height + } +} + +fragment CommunityNameFragment on Community { + title + slug + logo { + storage + original { + width + height + } + ...CommunityLogoFragment + } +} + +fragment CommunityNavListContentFragment on Community { + slug + orderings(availability: ENABLED) { + nodes { + name + slug + identifier + count + id + } + } + pages { + nodes { + slug + title + id + } + } +} + +fragment CommunityNavListFragment on Community { + ...CommunityNavListContentFragment +} + +fragment CommunityPickerCommunityNameFragment on Community { + title +} + +fragment ContributorNameFragment on AnyContributor { + __isAnyContributor: __typename + ... on PersonContributor { + __typename + familyName + givenName + } + ... on OrganizationContributor { + __typename + legalName + } +} + +fragment ContributorsListFragment on Entity { + __isEntity: __typename + ... on Item { + attributions { + roles { + label + id + } + contributor { + __typename + slug + ...ContributorNameFragment + ... on Node { + __isNode: __typename + id + } + } + id + } + } + ... on Collection { + attributions { + roles { + label + id + } + contributor { + __typename + slug + ...ContributorNameFragment + ... on Node { + __isNode: __typename + id + } + } + id + } + } +} + +fragment CoverCardListFragment on ImageAttachment { + image: medium { + webp { + url + alt + width + height + } + } +} + +fragment CoverImageFragment on ImageAttachment { + image: medium { + webp { + url + alt + width + height + } + } +} + +fragment DOIFragment on HasDOI { + __isHasDOI: __typename + doiData { + doi + url + } +} + +fragment DetailContentFragment on HeroTemplateInstance { + entity { + __typename + ... on Item { + slug + ...ContributorsListFragment + } + ... on Node { + __isNode: __typename + id + } + } + definition { + listContributors + id + } + slots { + subheader { + ...sharedInlineSlotFragment + } + subheaderSubtitle { + ...sharedInlineSlotFragment + } + subheaderAside { + ...sharedInlineSlotFragment + } + subheaderSummary { + ...sharedBlockSlotFragment + } + metadata { + ...sharedInlineSlotFragment + } + callToAction { + ...sharedBlockSlotFragment + } + } +} + +fragment DetailCoverImageFragment on Entity { + __isEntity: __typename + ... on Collection { + id + title + ...getThumbWithFallbackFragment + } + ... on Item { + id + title + ...getThumbWithFallbackFragment + } +} + +fragment DetailHeroFragment on HeroTemplateInstance { + entity { + __typename + ...DetailCoverImageFragment + ... on Node { + __isNode: __typename + id + } + } + definition { + showThumbnailImage + id + } + ...DetailContentFragment + ...DetailSidebarFragment +} + +fragment DetailSidebarFragment on HeroTemplateInstance { + entity { + __typename + ... on Item { + entityViews { + ...ViewCountFragment + } + assetDownloads { + ...DownloadCountFragment + } + } + ... on Collection { + entityViews { + ...ViewCountFragment + } + assetDownloads { + ...DownloadCountFragment + } + } + ... on Node { + __isNode: __typename + id + } + } + definition { + showBasicViewMetrics + id + } + slots { + sidebar { + ...sharedBlockSlotFragment + } + } +} + +fragment DownloadCountFragment on AnalyticsEventCountSummary { + total +} + +fragment EntityHeroHeaderFragment on HeroLayoutInstance { + entity { + __typename + ... on Collection { + __typename + visibility + currentlyHidden + heroImage { + storage + ...ImageHeroTemplateFragment + } + schemaDefinition { + identifier + id + } + } + ... on Item { + __typename + visibility + currentlyHidden + heroImage { + storage + ...ImageHeroTemplateFragment + } + schemaDefinition { + identifier + id + } + } + ...BreadcrumbsBarFragment + ... on Node { + __isNode: __typename + id + } + } + template { + definition { + background + showHeroImage + showBreadcrumbs + showSharingLink + showSplitDisplay + id + } + ...HeaderHeroFragment + ...DetailHeroFragment + id + } +} + +fragment EntityNavBarFragment on Entity { + __isEntity: __typename + ... on Node { + __isNode: __typename + id + } + ... on Sluggable { + __isSluggable: __typename + slug + } + title + ...EntityNavListFragment + layouts { + hero { + template { + definition { + enableDescendantBrowsing + enableDescendantSearch + id + } + slots { + descendantSearchPrompt { + ...sharedInlineSlotFragment + } + } + id + } + id + } + } +} + +fragment EntityNavListFragment on Entity { + __isEntity: __typename + __typename + schemaVersion { + name + identifier + id + } + orderings(availability: ENABLED) { + nodes { + name + slug + identifier + count + id + } + } + pages { + nodes { + title + slug + id + } + } +} + +fragment HeaderHeroFragment on HeroTemplateInstance { + definition { + showSplitDisplay + id + } + ...HeaderSidebarFragment + ...HeaderTitleBlockFragment +} + +fragment HeaderSidebarFragment on HeroTemplateInstance { + entity { + __typename + ... on HasDOI { + __isHasDOI: __typename + doiData { + doi + } + } + ...DOIFragment + ... on Item { + entityViews { + ...ViewCountFragment + } + assetDownloads { + ...DownloadCountFragment + } + } + ... on Collection { + entityViews { + ...ViewCountFragment + } + assetDownloads { + ...DownloadCountFragment + } + } + ... on Node { + __isNode: __typename + id + } + } + definition { + showDOI + showBasicViewMetrics + showSplitDisplay + id + } + slots { + headerSidebar { + ...sharedBlockSlotFragment + } + } +} + +fragment HeaderTitleBlockFragment on HeroTemplateInstance { + entity { + __typename + ... on Community { + ...ContributorsListFragment + } + ... on Item { + ...ContributorsListFragment + } + ... on Collection { + id + slug + title + ...ContributorsListFragment + thumbnail { + storage + medium { + webp { + width + height + } + } + ...CoverImageFragment + } + } + ... on Node { + __isNode: __typename + id + } + } + definition { + listContributors + showThumbnailImage + showSplitDisplay + id + } + slots { + header { + ...sharedInlineSlotFragment + } + headerSubtitle { + ...sharedInlineSlotFragment + } + headerParent { + ...sharedInlineSlotFragment + } + headerAside { + ...sharedInlineSlotFragment + } + headerSummary { + ...sharedBlockSlotFragment + } + callToAction { + ...sharedBlockSlotFragment + } + } +} + +fragment HeroTemplateFragment on HeroLayoutInstance { + entity { + __typename + ... on Community { + __typename + } + ... on Node { + __isNode: __typename + id + } + } + ...CommunityHeroHeaderFragment + ...EntityHeroHeaderFragment +} + +fragment ImageHeroTemplateFragment on ImageAttachment { + hero { + webp { + url + alt + width + height + } + } + large { + webp { + url + width + } + } + medium { + webp { + url + width + } + } +} + +fragment ProcessingCheckFragment on EntityLayouts { + main { + allHidden + templates { + __typename + ... on TemplateInstance { + __isTemplateInstance: __typename + __typename + } + ... on Node { + __isNode: __typename + id + } + } + id + } +} + +fragment SearchButtonFragment on Entity { + __isEntity: __typename + ...SearchModalFragment +} + +fragment SearchModalFragment on Entity { + __isEntity: __typename + __typename + ... on Sluggable { + __isSluggable: __typename + slug + } + title + breadcrumbs { + crumb { + __typename + ... on Sluggable { + __isSluggable: __typename + slug + } + __isEntity: __typename + title + ... on Node { + __isNode: __typename + id + } + } + id + } +} + +fragment SetCommunityFragment on Community { + ...CommunityContextFragment +} + +fragment ViewCountFragment on AnalyticsEventCountSummary { + total +} + +fragment getThumbWithFallbackFragment on Entity { + __isEntity: __typename + ... on Collection { + thumbnail { + image: medium { + webp { + url + } + } + ...CoverImageFragment + ...CoverCardListFragment + } + breadcrumbs { + crumb { + __typename + ... on Collection { + thumbnail { + image: medium { + webp { + url + } + } + ...CoverImageFragment + ...CoverCardListFragment + } + } + ... on Node { + __isNode: __typename + id + } + } + id + } + } + ... on Item { + thumbnail { + image: medium { + webp { + url + } + } + ...CoverImageFragment + ...CoverCardListFragment + } + breadcrumbs { + crumb { + __typename + ... on Collection { + thumbnail { + image: medium { + webp { + url + } + } + ...CoverImageFragment + ...CoverCardListFragment + } + } + ... on Item { + thumbnail { + image: medium { + webp { + url + } + } + ...CoverImageFragment + ...CoverCardListFragment + } + } + ... on Node { + __isNode: __typename + id + } + } + id + } + } +} + +fragment sharedBlockSlotFragment on TemplateSlotBlockInstance { + empty + content + kind + valid +} + +fragment sharedInlineSlotFragment on TemplateSlotInlineInstance { + empty + content + kind + valid + hidesTemplate +} diff --git a/spec/data/queries/layoutCommunityTemplateQuery.graphql b/spec/data/queries/layoutCommunityTemplateQuery.graphql new file mode 100644 index 00000000..09b6ce1a --- /dev/null +++ b/spec/data/queries/layoutCommunityTemplateQuery.graphql @@ -0,0 +1,713 @@ +query layoutCommunityTemplateQuery( + $slug: Slug! +) { + community(slug: $slug) { + layouts { + hero { + template { + definition { + enableDescendantBrowsing + id + } + id + } + ...HeroTemplateFragment + id + } + ...ProcessingCheckFragment + } + ...CommunityNavBarFragment + ...CommunityNavBarEntityFragment + ...SetCommunityFragment + id + } +} + +fragment BreadcrumbLinkFragment on EntityBreadcrumb { + label + kind + slug +} + +fragment BreadcrumbsBarFragment on Entity { + __isEntity: __typename + __typename + title + ... on Sluggable { + __isSluggable: __typename + slug + } + ... on Permalinkable { + __isPermalinkable: __typename + permalinks { + canonical + uri + id + } + } + ...BreadcrumbsFragment +} + +fragment BreadcrumbsFragment on Entity { + __isEntity: __typename + __typename + title + breadcrumbs { + depth + ...BreadcrumbLinkFragment + id + } + ... on Sluggable { + __isSluggable: __typename + slug + } +} + +fragment CommunityContextFragment on Community { + ...CommunityNameFragment + ...CommunityNavListFragment + ...CommunityPickerCommunityNameFragment +} + +fragment CommunityHeroHeaderFragment on HeroLayoutInstance { + entity { + __typename + ... on Community { + heroImage { + ...ImageHeroTemplateFragment + hero { + webp { + url + } + } + } + heroImageLayout + } + ... on Node { + __isNode: __typename + id + } + } + template { + definition { + showHeroImage + showBigSearchPrompt + id + } + slots { + bigSearchPrompt { + ...sharedInlineSlotFragment + } + header { + empty + } + headerSummary { + empty + } + } + ...HeaderHeroFragment + id + } +} + +fragment CommunityLogoFragment on ImageAttachment { + storage + original { + url + alt + width + height + } +} + +fragment CommunityNameFragment on Community { + title + slug + logo { + storage + original { + width + height + } + ...CommunityLogoFragment + } +} + +fragment CommunityNavBarEntityFragment on Entity { + __isEntity: __typename + ...SearchButtonFragment +} + +fragment CommunityNavBarFragment on Community { + ...CommunityNameFragment + ...CommunityNavListFragment +} + +fragment CommunityNavListContentFragment on Community { + slug + orderings(availability: ENABLED) { + nodes { + name + slug + identifier + count + id + } + } + pages { + nodes { + slug + title + id + } + } +} + +fragment CommunityNavListFragment on Community { + ...CommunityNavListContentFragment +} + +fragment CommunityPickerCommunityNameFragment on Community { + title +} + +fragment ContributorNameFragment on AnyContributor { + __isAnyContributor: __typename + ... on PersonContributor { + __typename + familyName + givenName + } + ... on OrganizationContributor { + __typename + legalName + } +} + +fragment ContributorsListFragment on Entity { + __isEntity: __typename + ... on Item { + attributions { + roles { + label + id + } + contributor { + __typename + slug + ...ContributorNameFragment + ... on Node { + __isNode: __typename + id + } + } + id + } + } + ... on Collection { + attributions { + roles { + label + id + } + contributor { + __typename + slug + ...ContributorNameFragment + ... on Node { + __isNode: __typename + id + } + } + id + } + } +} + +fragment CoverCardListFragment on ImageAttachment { + image: medium { + webp { + url + alt + width + height + } + } +} + +fragment CoverImageFragment on ImageAttachment { + image: medium { + webp { + url + alt + width + height + } + } +} + +fragment DOIFragment on HasDOI { + __isHasDOI: __typename + doiData { + doi + url + } +} + +fragment DetailContentFragment on HeroTemplateInstance { + entity { + __typename + ... on Item { + slug + ...ContributorsListFragment + } + ... on Node { + __isNode: __typename + id + } + } + definition { + listContributors + id + } + slots { + subheader { + ...sharedInlineSlotFragment + } + subheaderSubtitle { + ...sharedInlineSlotFragment + } + subheaderAside { + ...sharedInlineSlotFragment + } + subheaderSummary { + ...sharedBlockSlotFragment + } + metadata { + ...sharedInlineSlotFragment + } + callToAction { + ...sharedBlockSlotFragment + } + } +} + +fragment DetailCoverImageFragment on Entity { + __isEntity: __typename + ... on Collection { + id + title + ...getThumbWithFallbackFragment + } + ... on Item { + id + title + ...getThumbWithFallbackFragment + } +} + +fragment DetailHeroFragment on HeroTemplateInstance { + entity { + __typename + ...DetailCoverImageFragment + ... on Node { + __isNode: __typename + id + } + } + definition { + showThumbnailImage + id + } + ...DetailContentFragment + ...DetailSidebarFragment +} + +fragment DetailSidebarFragment on HeroTemplateInstance { + entity { + __typename + ... on Item { + entityViews { + ...ViewCountFragment + } + assetDownloads { + ...DownloadCountFragment + } + } + ... on Collection { + entityViews { + ...ViewCountFragment + } + assetDownloads { + ...DownloadCountFragment + } + } + ... on Node { + __isNode: __typename + id + } + } + definition { + showBasicViewMetrics + id + } + slots { + sidebar { + ...sharedBlockSlotFragment + } + } +} + +fragment DownloadCountFragment on AnalyticsEventCountSummary { + total +} + +fragment EntityHeroHeaderFragment on HeroLayoutInstance { + entity { + __typename + ... on Collection { + __typename + visibility + currentlyHidden + heroImage { + storage + ...ImageHeroTemplateFragment + } + schemaDefinition { + identifier + id + } + } + ... on Item { + __typename + visibility + currentlyHidden + heroImage { + storage + ...ImageHeroTemplateFragment + } + schemaDefinition { + identifier + id + } + } + ...BreadcrumbsBarFragment + ... on Node { + __isNode: __typename + id + } + } + template { + definition { + background + showHeroImage + showBreadcrumbs + showSharingLink + showSplitDisplay + id + } + ...HeaderHeroFragment + ...DetailHeroFragment + id + } +} + +fragment HeaderHeroFragment on HeroTemplateInstance { + definition { + showSplitDisplay + id + } + ...HeaderSidebarFragment + ...HeaderTitleBlockFragment +} + +fragment HeaderSidebarFragment on HeroTemplateInstance { + entity { + __typename + ... on HasDOI { + __isHasDOI: __typename + doiData { + doi + } + } + ...DOIFragment + ... on Item { + entityViews { + ...ViewCountFragment + } + assetDownloads { + ...DownloadCountFragment + } + } + ... on Collection { + entityViews { + ...ViewCountFragment + } + assetDownloads { + ...DownloadCountFragment + } + } + ... on Node { + __isNode: __typename + id + } + } + definition { + showDOI + showBasicViewMetrics + showSplitDisplay + id + } + slots { + headerSidebar { + ...sharedBlockSlotFragment + } + } +} + +fragment HeaderTitleBlockFragment on HeroTemplateInstance { + entity { + __typename + ... on Community { + ...ContributorsListFragment + } + ... on Item { + ...ContributorsListFragment + } + ... on Collection { + id + slug + title + ...ContributorsListFragment + thumbnail { + storage + medium { + webp { + width + height + } + } + ...CoverImageFragment + } + } + ... on Node { + __isNode: __typename + id + } + } + definition { + listContributors + showThumbnailImage + showSplitDisplay + id + } + slots { + header { + ...sharedInlineSlotFragment + } + headerSubtitle { + ...sharedInlineSlotFragment + } + headerParent { + ...sharedInlineSlotFragment + } + headerAside { + ...sharedInlineSlotFragment + } + headerSummary { + ...sharedBlockSlotFragment + } + callToAction { + ...sharedBlockSlotFragment + } + } +} + +fragment HeroTemplateFragment on HeroLayoutInstance { + entity { + __typename + ... on Community { + __typename + } + ... on Node { + __isNode: __typename + id + } + } + ...CommunityHeroHeaderFragment + ...EntityHeroHeaderFragment +} + +fragment ImageHeroTemplateFragment on ImageAttachment { + hero { + webp { + url + alt + width + height + } + } + large { + webp { + url + width + } + } + medium { + webp { + url + width + } + } +} + +fragment ProcessingCheckFragment on EntityLayouts { + main { + allHidden + templates { + __typename + ... on TemplateInstance { + __isTemplateInstance: __typename + __typename + } + ... on Node { + __isNode: __typename + id + } + } + id + } +} + +fragment SearchButtonFragment on Entity { + __isEntity: __typename + ...SearchModalFragment +} + +fragment SearchModalFragment on Entity { + __isEntity: __typename + __typename + ... on Sluggable { + __isSluggable: __typename + slug + } + title + breadcrumbs { + crumb { + __typename + ... on Sluggable { + __isSluggable: __typename + slug + } + __isEntity: __typename + title + ... on Node { + __isNode: __typename + id + } + } + id + } +} + +fragment SetCommunityFragment on Community { + ...CommunityContextFragment +} + +fragment ViewCountFragment on AnalyticsEventCountSummary { + total +} + +fragment getThumbWithFallbackFragment on Entity { + __isEntity: __typename + ... on Collection { + thumbnail { + image: medium { + webp { + url + } + } + ...CoverImageFragment + ...CoverCardListFragment + } + breadcrumbs { + crumb { + __typename + ... on Collection { + thumbnail { + image: medium { + webp { + url + } + } + ...CoverImageFragment + ...CoverCardListFragment + } + } + ... on Node { + __isNode: __typename + id + } + } + id + } + } + ... on Item { + thumbnail { + image: medium { + webp { + url + } + } + ...CoverImageFragment + ...CoverCardListFragment + } + breadcrumbs { + crumb { + __typename + ... on Collection { + thumbnail { + image: medium { + webp { + url + } + } + ...CoverImageFragment + ...CoverCardListFragment + } + } + ... on Item { + thumbnail { + image: medium { + webp { + url + } + } + ...CoverImageFragment + ...CoverCardListFragment + } + } + ... on Node { + __isNode: __typename + id + } + } + id + } + } +} + +fragment sharedBlockSlotFragment on TemplateSlotBlockInstance { + empty + content + kind + valid +} + +fragment sharedInlineSlotFragment on TemplateSlotInlineInstance { + empty + content + kind + valid + hidesTemplate +} diff --git a/spec/data/queries/layoutItemTemplateQuery.graphql b/spec/data/queries/layoutItemTemplateQuery.graphql new file mode 100644 index 00000000..872a86aa --- /dev/null +++ b/spec/data/queries/layoutItemTemplateQuery.graphql @@ -0,0 +1,879 @@ +query layoutItemTemplateQuery( + $slug: Slug! +) { + item(slug: $slug) { + layouts { + hero { + ...HeroTemplateFragment + id + } + navigation { + ...EntityNavigationTemplateFragment + id + } + ...ProcessingCheckFragment + ...FullTextCheckFragment + } + ...SearchButtonFragment + ...EntityNavBarFragment + community { + ...SetCommunityFragment + id + } + id + } +} + +fragment BreadcrumbLinkFragment on EntityBreadcrumb { + label + kind + slug +} + +fragment BreadcrumbsBarFragment on Entity { + __isEntity: __typename + __typename + title + ... on Sluggable { + __isSluggable: __typename + slug + } + ... on Permalinkable { + __isPermalinkable: __typename + permalinks { + canonical + uri + id + } + } + ...BreadcrumbsFragment +} + +fragment BreadcrumbsFragment on Entity { + __isEntity: __typename + __typename + title + breadcrumbs { + depth + ...BreadcrumbLinkFragment + id + } + ... on Sluggable { + __isSluggable: __typename + slug + } +} + +fragment CommunityContextFragment on Community { + ...CommunityNameFragment + ...CommunityNavListFragment + ...CommunityPickerCommunityNameFragment +} + +fragment CommunityHeroHeaderFragment on HeroLayoutInstance { + entity { + __typename + ... on Community { + heroImage { + ...ImageHeroTemplateFragment + hero { + webp { + url + } + } + } + heroImageLayout + } + ... on Node { + __isNode: __typename + id + } + } + template { + definition { + showHeroImage + showBigSearchPrompt + id + } + slots { + bigSearchPrompt { + ...sharedInlineSlotFragment + } + header { + empty + } + headerSummary { + empty + } + } + ...HeaderHeroFragment + id + } +} + +fragment CommunityLogoFragment on ImageAttachment { + storage + original { + url + alt + width + height + } +} + +fragment CommunityNameFragment on Community { + title + slug + logo { + storage + original { + width + height + } + ...CommunityLogoFragment + } +} + +fragment CommunityNavListContentFragment on Community { + slug + orderings(availability: ENABLED) { + nodes { + name + slug + identifier + count + id + } + } + pages { + nodes { + slug + title + id + } + } +} + +fragment CommunityNavListFragment on Community { + ...CommunityNavListContentFragment +} + +fragment CommunityPickerCommunityNameFragment on Community { + title +} + +fragment ContributorNameFragment on AnyContributor { + __isAnyContributor: __typename + ... on PersonContributor { + __typename + familyName + givenName + } + ... on OrganizationContributor { + __typename + legalName + } +} + +fragment ContributorsListFragment on Entity { + __isEntity: __typename + ... on Item { + attributions { + roles { + label + id + } + contributor { + __typename + slug + ...ContributorNameFragment + ... on Node { + __isNode: __typename + id + } + } + id + } + } + ... on Collection { + attributions { + roles { + label + id + } + contributor { + __typename + slug + ...ContributorNameFragment + ... on Node { + __isNode: __typename + id + } + } + id + } + } +} + +fragment CoverCardListFragment on ImageAttachment { + image: medium { + webp { + url + alt + width + height + } + } +} + +fragment CoverImageFragment on ImageAttachment { + image: medium { + webp { + url + alt + width + height + } + } +} + +fragment DOIFragment on HasDOI { + __isHasDOI: __typename + doiData { + doi + url + } +} + +fragment DetailContentFragment on HeroTemplateInstance { + entity { + __typename + ... on Item { + slug + ...ContributorsListFragment + } + ... on Node { + __isNode: __typename + id + } + } + definition { + listContributors + id + } + slots { + subheader { + ...sharedInlineSlotFragment + } + subheaderSubtitle { + ...sharedInlineSlotFragment + } + subheaderAside { + ...sharedInlineSlotFragment + } + subheaderSummary { + ...sharedBlockSlotFragment + } + metadata { + ...sharedInlineSlotFragment + } + callToAction { + ...sharedBlockSlotFragment + } + } +} + +fragment DetailCoverImageFragment on Entity { + __isEntity: __typename + ... on Collection { + id + title + ...getThumbWithFallbackFragment + } + ... on Item { + id + title + ...getThumbWithFallbackFragment + } +} + +fragment DetailHeroFragment on HeroTemplateInstance { + entity { + __typename + ...DetailCoverImageFragment + ... on Node { + __isNode: __typename + id + } + } + definition { + showThumbnailImage + id + } + ...DetailContentFragment + ...DetailSidebarFragment +} + +fragment DetailSidebarFragment on HeroTemplateInstance { + entity { + __typename + ... on Item { + entityViews { + ...ViewCountFragment + } + assetDownloads { + ...DownloadCountFragment + } + } + ... on Collection { + entityViews { + ...ViewCountFragment + } + assetDownloads { + ...DownloadCountFragment + } + } + ... on Node { + __isNode: __typename + id + } + } + definition { + showBasicViewMetrics + id + } + slots { + sidebar { + ...sharedBlockSlotFragment + } + } +} + +fragment DownloadCountFragment on AnalyticsEventCountSummary { + total +} + +fragment EntityHeroHeaderFragment on HeroLayoutInstance { + entity { + __typename + ... on Collection { + __typename + visibility + currentlyHidden + heroImage { + storage + ...ImageHeroTemplateFragment + } + schemaDefinition { + identifier + id + } + } + ... on Item { + __typename + visibility + currentlyHidden + heroImage { + storage + ...ImageHeroTemplateFragment + } + schemaDefinition { + identifier + id + } + } + ...BreadcrumbsBarFragment + ... on Node { + __isNode: __typename + id + } + } + template { + definition { + background + showHeroImage + showBreadcrumbs + showSharingLink + showSplitDisplay + id + } + ...HeaderHeroFragment + ...DetailHeroFragment + id + } +} + +fragment EntityNavBarFragment on Entity { + __isEntity: __typename + ... on Node { + __isNode: __typename + id + } + ... on Sluggable { + __isSluggable: __typename + slug + } + title + ...EntityNavListFragment + layouts { + hero { + template { + definition { + enableDescendantBrowsing + enableDescendantSearch + id + } + slots { + descendantSearchPrompt { + ...sharedInlineSlotFragment + } + } + id + } + id + } + } +} + +fragment EntityNavListFragment on Entity { + __isEntity: __typename + __typename + schemaVersion { + name + identifier + id + } + orderings(availability: ENABLED) { + nodes { + name + slug + identifier + count + id + } + } + pages { + nodes { + title + slug + id + } + } +} + +fragment EntityNavigationTemplateFragment on NavigationLayoutInstance { + template { + definition { + background + id + } + ...NavigationTabsFragment + id + } +} + +fragment FullTextCheckFragment on EntityLayouts { + main { + templates { + __typename + ... on DetailTemplateInstance { + definition { + showBody + variant + id + } + slots { + body { + valid + content + } + } + } + ... on Node { + __isNode: __typename + id + } + } + id + } +} + +fragment HeaderHeroFragment on HeroTemplateInstance { + definition { + showSplitDisplay + id + } + ...HeaderSidebarFragment + ...HeaderTitleBlockFragment +} + +fragment HeaderSidebarFragment on HeroTemplateInstance { + entity { + __typename + ... on HasDOI { + __isHasDOI: __typename + doiData { + doi + } + } + ...DOIFragment + ... on Item { + entityViews { + ...ViewCountFragment + } + assetDownloads { + ...DownloadCountFragment + } + } + ... on Collection { + entityViews { + ...ViewCountFragment + } + assetDownloads { + ...DownloadCountFragment + } + } + ... on Node { + __isNode: __typename + id + } + } + definition { + showDOI + showBasicViewMetrics + showSplitDisplay + id + } + slots { + headerSidebar { + ...sharedBlockSlotFragment + } + } +} + +fragment HeaderTitleBlockFragment on HeroTemplateInstance { + entity { + __typename + ... on Community { + ...ContributorsListFragment + } + ... on Item { + ...ContributorsListFragment + } + ... on Collection { + id + slug + title + ...ContributorsListFragment + thumbnail { + storage + medium { + webp { + width + height + } + } + ...CoverImageFragment + } + } + ... on Node { + __isNode: __typename + id + } + } + definition { + listContributors + showThumbnailImage + showSplitDisplay + id + } + slots { + header { + ...sharedInlineSlotFragment + } + headerSubtitle { + ...sharedInlineSlotFragment + } + headerParent { + ...sharedInlineSlotFragment + } + headerAside { + ...sharedInlineSlotFragment + } + headerSummary { + ...sharedBlockSlotFragment + } + callToAction { + ...sharedBlockSlotFragment + } + } +} + +fragment HeroTemplateFragment on HeroLayoutInstance { + entity { + __typename + ... on Community { + __typename + } + ... on Node { + __isNode: __typename + id + } + } + ...CommunityHeroHeaderFragment + ...EntityHeroHeaderFragment +} + +fragment ImageHeroTemplateFragment on ImageAttachment { + hero { + webp { + url + alt + width + height + } + } + large { + webp { + url + width + } + } + medium { + webp { + url + width + } + } +} + +fragment NavigationTabsFragment on NavigationTemplateInstance { + entity { + __typename + ... on Item { + __typename + pages { + edges { + node { + title + slug + id + } + } + } + contributions { + pageInfo { + totalCount + } + } + assets { + pageInfo { + totalCount + } + } + } + ... on Collection { + __typename + pages { + edges { + node { + title + slug + id + } + } + } + contributions { + pageInfo { + totalCount + } + } + assets { + pageInfo { + totalCount + } + } + } + ... on Community { + __typename + pages { + edges { + node { + title + slug + id + } + } + } + assets { + pageInfo { + totalCount + } + } + } + ... on Node { + __isNode: __typename + id + } + } + definition { + hideMetadata + id + } + slots { + entityLabel { + ...sharedInlineSlotFragment + } + } +} + +fragment ProcessingCheckFragment on EntityLayouts { + main { + allHidden + templates { + __typename + ... on TemplateInstance { + __isTemplateInstance: __typename + __typename + } + ... on Node { + __isNode: __typename + id + } + } + id + } +} + +fragment SearchButtonFragment on Entity { + __isEntity: __typename + ...SearchModalFragment +} + +fragment SearchModalFragment on Entity { + __isEntity: __typename + __typename + ... on Sluggable { + __isSluggable: __typename + slug + } + title + breadcrumbs { + crumb { + __typename + ... on Sluggable { + __isSluggable: __typename + slug + } + __isEntity: __typename + title + ... on Node { + __isNode: __typename + id + } + } + id + } +} + +fragment SetCommunityFragment on Community { + ...CommunityContextFragment +} + +fragment ViewCountFragment on AnalyticsEventCountSummary { + total +} + +fragment getThumbWithFallbackFragment on Entity { + __isEntity: __typename + ... on Collection { + thumbnail { + image: medium { + webp { + url + } + } + ...CoverImageFragment + ...CoverCardListFragment + } + breadcrumbs { + crumb { + __typename + ... on Collection { + thumbnail { + image: medium { + webp { + url + } + } + ...CoverImageFragment + ...CoverCardListFragment + } + } + ... on Node { + __isNode: __typename + id + } + } + id + } + } + ... on Item { + thumbnail { + image: medium { + webp { + url + } + } + ...CoverImageFragment + ...CoverCardListFragment + } + breadcrumbs { + crumb { + __typename + ... on Collection { + thumbnail { + image: medium { + webp { + url + } + } + ...CoverImageFragment + ...CoverCardListFragment + } + } + ... on Item { + thumbnail { + image: medium { + webp { + url + } + } + ...CoverImageFragment + ...CoverCardListFragment + } + } + ... on Node { + __isNode: __typename + id + } + } + id + } + } +} + +fragment sharedBlockSlotFragment on TemplateSlotBlockInstance { + empty + content + kind + valid +} + +fragment sharedInlineSlotFragment on TemplateSlotInlineInstance { + empty + content + kind + valid + hidesTemplate +} diff --git a/spec/data/queries/pageBrowseCommunityOrderingQuery.graphql b/spec/data/queries/pageBrowseCommunityOrderingQuery.graphql new file mode 100644 index 00000000..7b1945ec --- /dev/null +++ b/spec/data/queries/pageBrowseCommunityOrderingQuery.graphql @@ -0,0 +1,425 @@ +query pageBrowseCommunityOrderingQuery( + $slug: Slug! + $identifier: String! + $page: Int +) { + community(slug: $slug) { + ordering(identifier: $identifier) { + disabled + ...EntityOrderingLayoutFragment + id + } + id + } +} + +fragment BackButtonFragment on Entity { + __isEntity: __typename + __typename + slug + schemaVersion { + name + id + } +} + +fragment BrowseListLayoutFragment on PageInfo { + ...PaginationFragment + ...PageCountFragment +} + +fragment BrowseTreeItemFragment on OrderingEntry { + treeDepth + entry { + __typename + ... on Sluggable { + __isSluggable: __typename + slug + } + ... on Entity { + __isEntity: __typename + layouts { + listItem { + template { + ...sharedListItemTemplateFragment + id + } + id + } + } + } + id + } +} + +fragment BrowseTreeLayoutFragment on OrderingEntryConnection { + nodes { + id + treeDepth + ancestors { + id + treeDepth + ...BrowseTreeItemFragment + } + ...BrowseTreeItemFragment + } + pageInfo { + ...PaginationFragment + ...PageCountFragment + } +} + +fragment ContributorNameFragment on AnyContributor { + __isAnyContributor: __typename + ... on PersonContributor { + __typename + familyName + givenName + } + ... on OrganizationContributor { + __typename + legalName + } +} + +fragment ContributorsListFragment on Entity { + __isEntity: __typename + ... on Item { + attributions { + roles { + label + id + } + contributor { + __typename + slug + ...ContributorNameFragment + ... on Node { + __isNode: __typename + id + } + } + id + } + } + ... on Collection { + attributions { + roles { + label + id + } + contributor { + __typename + slug + ...ContributorNameFragment + ... on Node { + __isNode: __typename + id + } + } + id + } + } +} + +fragment CoverCardListFragment on ImageAttachment { + image: medium { + webp { + url + alt + width + height + } + } +} + +fragment CoverImageFragment on ImageAttachment { + image: medium { + webp { + url + alt + width + height + } + } +} + +fragment EntityOrderingLayoutFragment on Ordering { + name + header + render { + mode + } + entity { + __typename + ... on Sluggable { + __isSluggable: __typename + slug + } + ...BackButtonFragment + ... on Node { + __isNode: __typename + id + } + } + children(page: $page) { + edges { + node { + id + entry { + __typename + ... on Sluggable { + __isSluggable: __typename + slug + } + ...EntitySummaryFragment + id + } + } + } + pageInfo { + ...BrowseListLayoutFragment + } + ...BrowseTreeLayoutFragment + } + id +} + +fragment EntitySummaryFragment on Entity { + __isEntity: __typename + __typename + layouts { + listItem { + template { + ...sharedListItemTemplateFragment + id + } + id + } + } +} + +fragment PageCountFragment on PageInfo { + totalCount + page + perPage +} + +fragment PaginationFragment on PageInfo { + page + pageCount +} + +fragment getThumbWithFallbackFragment on Entity { + __isEntity: __typename + ... on Collection { + thumbnail { + image: medium { + webp { + url + } + } + ...CoverImageFragment + ...CoverCardListFragment + } + breadcrumbs { + crumb { + __typename + ... on Collection { + thumbnail { + image: medium { + webp { + url + } + } + ...CoverImageFragment + ...CoverCardListFragment + } + } + ... on Node { + __isNode: __typename + id + } + } + id + } + } + ... on Item { + thumbnail { + image: medium { + webp { + url + } + } + ...CoverImageFragment + ...CoverCardListFragment + } + breadcrumbs { + crumb { + __typename + ... on Collection { + thumbnail { + image: medium { + webp { + url + } + } + ...CoverImageFragment + ...CoverCardListFragment + } + } + ... on Item { + thumbnail { + image: medium { + webp { + url + } + } + ...CoverImageFragment + ...CoverCardListFragment + } + } + ... on Node { + __isNode: __typename + id + } + } + id + } + } +} + +fragment sharedBlockSlotFragment on TemplateSlotBlockInstance { + empty + content + kind + valid +} + +fragment sharedInlineSlotFragment on TemplateSlotInlineInstance { + empty + content + kind + valid + hidesTemplate +} + +fragment sharedListItemTemplateFragment on ListItemTemplateInstance { + definition { + seeAllOrderingIdentifier + id + } + entity { + __typename + ... on Collection { + __typename + id + slug + title + hierarchicalDepth + ...getThumbWithFallbackFragment + attributions { + id + } + ...ContributorsListFragment + heroImage { + large { + webp { + alt + url + width + height + } + } + medium { + webp { + url + width + } + } + thumb { + webp { + url + width + } + } + } + } + ... on Item { + __typename + id + slug + title + hierarchicalDepth + attributions { + id + } + ...getThumbWithFallbackFragment + ...ContributorsListFragment + heroImage { + large { + webp { + alt + url + width + height + } + } + medium { + webp { + url + width + } + } + thumb { + webp { + url + width + } + } + } + } + ... on Node { + __isNode: __typename + id + } + } + slots { + contextFull { + ...sharedInlineSlotFragment + } + contextAbbr { + ...sharedInlineSlotFragment + } + contextC { + ...sharedInlineSlotFragment + } + description { + ...sharedBlockSlotFragment + } + header { + ...sharedInlineSlotFragment + } + metaA { + ...sharedInlineSlotFragment + } + metaB { + ...sharedInlineSlotFragment + } + subheader { + ...sharedInlineSlotFragment + } + nestedHeader { + ...sharedInlineSlotFragment + } + nestedSubheader { + ...sharedInlineSlotFragment + } + nestedContext { + ...sharedInlineSlotFragment + } + nestedMetadata { + ...sharedInlineSlotFragment + } + } +} diff --git a/spec/data/queries/pageCollectionTemplateQuery.graphql b/spec/data/queries/pageCollectionTemplateQuery.graphql new file mode 100644 index 00000000..63622f7b --- /dev/null +++ b/spec/data/queries/pageCollectionTemplateQuery.graphql @@ -0,0 +1,1002 @@ +query pageCollectionTemplateQuery( + $slug: Slug! +) { + collection(slug: $slug) { + layouts { + main { + ...MainLayoutFragment + templates { + __typename + ... on TemplateInstance { + __isTemplateInstance: __typename + templateKind + } + ... on Node { + __isNode: __typename + id + } + } + id + } + } + id + } +} + +fragment AnnouncementsFragment on AnnouncementConnection { + nodes { + teaser + header + slug + id + } +} + +fragment BlurbTemplateFragment on BlurbTemplateInstance { + __typename + hidden + blurbDefinition: definition { + background + width + id + } + slots { + header { + ...sharedInlineSlotFragment + } + subheader { + ...sharedInlineSlotFragment + } + body { + ...sharedBlockSlotFragment + } + } +} + +fragment ColumnsDetailFragment on DetailTemplateInstance { + slots { + header { + ...sharedInlineSlotFragment + } + itemsA { + ...sharedBlockSlotFragment + } + itemsB { + ...sharedBlockSlotFragment + } + itemsC { + ...sharedBlockSlotFragment + } + itemsD { + ...sharedBlockSlotFragment + } + } +} + +fragment ContentImageFragment on ImageAttachment { + large { + webp { + alt + url + width + height + } + } + medium { + webp { + url + width + } + } + small { + webp { + url + width + } + } +} + +fragment ContributorAvatarFragment on ImageAttachment { + small { + webp { + alt + url + } + } +} + +fragment ContributorFragment on Attribution { + __isAttribution: __typename + roles { + identifier + label + id + } + contributor { + __typename + title + affiliation + slug + image { + ...ContributorAvatarFragment + } + ...ContributorNameFragment + ... on Node { + __isNode: __typename + id + } + } +} + +fragment ContributorNameFragment on AnyContributor { + __isAnyContributor: __typename + ... on PersonContributor { + __typename + familyName + givenName + } + ... on OrganizationContributor { + __typename + legalName + } +} + +fragment ContributorsListFragment on Entity { + __isEntity: __typename + ... on Item { + attributions { + roles { + label + id + } + contributor { + __typename + slug + ...ContributorNameFragment + ... on Node { + __isNode: __typename + id + } + } + id + } + } + ... on Collection { + attributions { + roles { + label + id + } + contributor { + __typename + slug + ...ContributorNameFragment + ... on Node { + __isNode: __typename + id + } + } + id + } + } +} + +fragment ContributorsTemplateFragment on ContributorListTemplateInstance { + __typename + entity { + __typename + ... on Item { + __typename + slug + attributions { + ...ContributorFragment + id + } + } + ... on Collection { + __typename + slug + attributions { + ...ContributorFragment + id + } + } + ... on Node { + __isNode: __typename + id + } + } + contributorsDefinition: definition { + background + limit + width + id + } + slots { + header { + ...sharedInlineSlotFragment + } + } +} + +fragment CoverCardListFragment on ImageAttachment { + image: medium { + webp { + url + alt + width + height + } + } +} + +fragment CoverImageFragment on ImageAttachment { + image: medium { + webp { + url + alt + width + height + } + } +} + +fragment DescendantsTemplateFragment on AnyMainTemplateInstance { + __isAnyMainTemplateInstance: __typename + ... on DescendantListTemplateInstance { + entity { + __typename + ... on Sluggable { + __isSluggable: __typename + slug + } + ... on Node { + __isNode: __typename + id + } + } + descendantsDefinition: definition { + variant + id + } + } + ...sharedListTemplateFragment +} + +fragment DetailTemplateFragment on DetailTemplateInstance { + __typename + hidden + detailDefinition: definition { + background + variant + id + } + ...SummaryDetailFragment + ...FullDetailFragment + ...ColumnsDetailFragment +} + +fragment FactoryTemplatesFragment on AnyMainTemplateInstance { + __isAnyMainTemplateInstance: __typename + ... on TemplateInstance { + __isTemplateInstance: __typename + templateKind + } + ... on ContributorListTemplateInstance { + ...ContributorsTemplateFragment + } + ... on DetailTemplateInstance { + ...DetailTemplateFragment + } + ... on OrderingTemplateInstance { + ...OrderingNavigationTemplateFragment + } + ... on PageListTemplateInstance { + ...PagesTemplateFragment + } + ... on DescendantListTemplateInstance { + slots { + blockHeader { + content + } + } + entityList { + empty + } + } + ... on LinkListTemplateInstance { + entityList { + empty + } + } + ... on BlurbTemplateInstance { + ...BlurbTemplateFragment + } + ...DescendantsTemplateFragment + ...LinksTemplateFragment +} + +fragment FullDetailFragment on DetailTemplateInstance { + entity { + __typename + ... on Item { + __typename + heroImage { + storage + ...ContentImageFragment + } + } + ... on Collection { + __typename + heroImage { + storage + ...ContentImageFragment + } + } + ... on Node { + __isNode: __typename + id + } + } + detailDefinition: definition { + showBody + showHeroImage + id + } + slots { + header { + ...sharedInlineSlotFragment + } + subheader { + ...sharedInlineSlotFragment + } + body { + ...sharedBlockSlotFragment + } + } +} + +fragment LinksTemplateFragment on AnyMainTemplateInstance { + __isAnyMainTemplateInstance: __typename + ... on LinkListTemplateInstance { + __typename + linksDefinition: definition { + variant + id + } + } + ...sharedListTemplateFragment +} + +fragment ListPagesTemplateFragment on Entity { + __isEntity: __typename + ... on Item { + pages { + edges { + node { + slug + title + id + } + } + } + } + ... on Collection { + pages { + edges { + node { + slug + title + id + } + } + } + } + ... on Community { + pages { + edges { + node { + slug + title + id + } + } + } + } +} + +fragment MainLayoutFragment on MainLayoutInstance { + allHidden + entity { + __typename + ... on Node { + __isNode: __typename + id + } + } + templates { + __typename + ... on TemplateInstance { + __isTemplateInstance: __typename + hidden + templateKind + prevSiblings { + dark + hidden + position + templateKind + id + } + nextSiblings { + dark + hidden + position + templateKind + id + } + } + ...FactoryTemplatesFragment + ... on Node { + __isNode: __typename + id + } + } +} + +fragment NavButtonsFragment on OrderingTemplateInstance { + orderingPair { + exists + first + last + nextSibling { + ...routesOrderingTemplateFragment + id + } + prevSibling { + ...routesOrderingTemplateFragment + id + } + } + slots { + nextLabel { + ...sharedInlineSlotFragment + } + previousLabel { + ...sharedInlineSlotFragment + } + } +} + +fragment OrderingNavigationTemplateFragment on OrderingTemplateInstance { + hidden + orderingDefinition: definition { + background + width + id + } + orderingPair { + exists + } + ...NavButtonsFragment +} + +fragment PagesTemplateFragment on PageListTemplateInstance { + __typename + hidden + pagesDefinition: definition { + background + width + id + } + entity { + __typename + ...ListPagesTemplateFragment + ... on Node { + __isNode: __typename + id + } + } +} + +fragment SummaryDetailFragment on DetailTemplateInstance { + entity { + __typename + ... on Collection { + __typename + announcements { + ...AnnouncementsFragment + nodes { + slug + id + } + } + } + ... on Community { + __typename + announcements { + ...AnnouncementsFragment + nodes { + slug + id + } + } + } + ... on Item { + __typename + announcements { + ...AnnouncementsFragment + nodes { + slug + id + } + } + } + ... on Node { + __isNode: __typename + id + } + } + detailDefinition: definition { + showAnnouncements + id + } + slots { + header { + ...sharedInlineSlotFragment + } + subheader { + ...sharedInlineSlotFragment + } + summary { + ...sharedBlockSlotFragment + } + } +} + +fragment getThumbWithFallbackFragment on Entity { + __isEntity: __typename + ... on Collection { + thumbnail { + image: medium { + webp { + url + } + } + ...CoverImageFragment + ...CoverCardListFragment + } + breadcrumbs { + crumb { + __typename + ... on Collection { + thumbnail { + image: medium { + webp { + url + } + } + ...CoverImageFragment + ...CoverCardListFragment + } + } + ... on Node { + __isNode: __typename + id + } + } + id + } + } + ... on Item { + thumbnail { + image: medium { + webp { + url + } + } + ...CoverImageFragment + ...CoverCardListFragment + } + breadcrumbs { + crumb { + __typename + ... on Collection { + thumbnail { + image: medium { + webp { + url + } + } + ...CoverImageFragment + ...CoverCardListFragment + } + } + ... on Item { + thumbnail { + image: medium { + webp { + url + } + } + ...CoverImageFragment + ...CoverCardListFragment + } + } + ... on Node { + __isNode: __typename + id + } + } + id + } + } +} + +fragment routesOrderingTemplateFragment on OrderingEntry { + entrySlug + entry { + __typename + ... on Collection { + __typename + } + ... on Item { + __typename + } + ... on Community { + __typename + } + ... on EntityLink { + __typename + target { + __typename + ... on Collection { + __typename + } + ... on Item { + __typename + } + ... on Community { + __typename + } + ... on Node { + __isNode: __typename + id + } + } + } + id + } +} + +fragment sharedBlockSlotFragment on TemplateSlotBlockInstance { + empty + content + kind + valid +} + +fragment sharedInlineSlotFragment on TemplateSlotInlineInstance { + empty + content + kind + valid + hidesTemplate +} + +fragment sharedListItemTemplateFragment on ListItemTemplateInstance { + definition { + seeAllOrderingIdentifier + id + } + entity { + __typename + ... on Collection { + __typename + id + slug + title + hierarchicalDepth + ...getThumbWithFallbackFragment + attributions { + id + } + ...ContributorsListFragment + heroImage { + large { + webp { + alt + url + width + height + } + } + medium { + webp { + url + width + } + } + thumb { + webp { + url + width + } + } + } + } + ... on Item { + __typename + id + slug + title + hierarchicalDepth + attributions { + id + } + ...getThumbWithFallbackFragment + ...ContributorsListFragment + heroImage { + large { + webp { + alt + url + width + height + } + } + medium { + webp { + url + width + } + } + thumb { + webp { + url + width + } + } + } + } + ... on Node { + __isNode: __typename + id + } + } + slots { + contextFull { + ...sharedInlineSlotFragment + } + contextAbbr { + ...sharedInlineSlotFragment + } + contextC { + ...sharedInlineSlotFragment + } + description { + ...sharedBlockSlotFragment + } + header { + ...sharedInlineSlotFragment + } + metaA { + ...sharedInlineSlotFragment + } + metaB { + ...sharedInlineSlotFragment + } + subheader { + ...sharedInlineSlotFragment + } + nestedHeader { + ...sharedInlineSlotFragment + } + nestedSubheader { + ...sharedInlineSlotFragment + } + nestedContext { + ...sharedInlineSlotFragment + } + nestedMetadata { + ...sharedInlineSlotFragment + } + } +} + +fragment sharedListItemsTemplateFragment on TemplateEntityList { + empty + count + depths: listItemLayouts { + template { + entity { + __typename + ... on Collection { + hierarchicalDepth + } + ... on Item { + hierarchicalDepth + } + ... on Node { + __isNode: __typename + id + } + } + id + } + id + } + listItemLayouts { + template { + entity { + __typename + ... on Collection { + hierarchicalDepth + } + ... on Item { + hierarchicalDepth + } + ... on Node { + __isNode: __typename + id + } + } + ...sharedListItemTemplateFragment + entityList { + empty + count + listItemLayouts { + template { + ...sharedListItemTemplateFragment + id + } + id + } + } + id + } + id + } +} + +fragment sharedListTemplateFragment on AnyMainTemplateInstance { + __isAnyMainTemplateInstance: __typename + ... on LinkListTemplateInstance { + entity { + __typename + ... on Community { + __typename + slug + } + ... on Collection { + __typename + slug + ...getThumbWithFallbackFragment + } + ... on Item { + __typename + slug + ...getThumbWithFallbackFragment + } + ... on Node { + __isNode: __typename + id + } + } + linksDefinition: definition { + background + seeAllButtonLabel + showSeeAllButton + selectionMode + selectionLimit + showEntityContext + title + variant + showHeroImage + width + showNestedEntities + seeAllOrderingIdentifier + showContributors + id + } + slots { + blockHeader { + ...sharedInlineSlotFragment + } + header { + ...sharedInlineSlotFragment + } + headerAside { + ...sharedInlineSlotFragment + } + metadata { + ...sharedInlineSlotFragment + } + subtitle { + ...sharedInlineSlotFragment + } + } + entityList { + count + empty + ...sharedListItemsTemplateFragment + } + } + ... on DescendantListTemplateInstance { + seeAllOrdering { + count + name + id + } + entity { + __typename + ... on Community { + __typename + slug + } + ... on Collection { + __typename + id + title + slug + ...getThumbWithFallbackFragment + } + ... on Item { + __typename + id + title + slug + ...getThumbWithFallbackFragment + } + ... on Node { + __isNode: __typename + id + } + } + descendantsDefinition: definition { + background + seeAllButtonLabel + showSeeAllButton + selectionMode + selectionPropertyPath + orderingIdentifier + dynamicOrderingDefinition { + filter { + schemas { + namespace + identifier + } + } + } + selectionLimit + entityContext + title + variant + showHeroImage + width + showNestedEntities + seeAllOrderingIdentifier + showContributors + id + } + slots { + blockHeader { + ...sharedInlineSlotFragment + } + header { + ...sharedInlineSlotFragment + } + headerAside { + ...sharedInlineSlotFragment + } + metadata { + ...sharedInlineSlotFragment + } + subtitle { + ...sharedInlineSlotFragment + } + } + entityList { + ...sharedListItemsTemplateFragment + } + } +} diff --git a/spec/data/queries/pageContributorDetailQuery.graphql b/spec/data/queries/pageContributorDetailQuery.graphql new file mode 100644 index 00000000..1556ba9e --- /dev/null +++ b/spec/data/queries/pageContributorDetailQuery.graphql @@ -0,0 +1,162 @@ +query pageContributorDetailQuery( + $slug: Slug! + $page: Int +) { + contributor(slug: $slug) { + __typename + ...ContributorDetailFragment + ... on Node { + __isNode: __typename + id + } + } +} + +fragment BrowseListLayoutFragment on PageInfo { + ...PaginationFragment + ...PageCountFragment +} + +fragment ContributionSummaryEntityFragment on Entity { + __isEntity: __typename + __typename + title + subtitle + thumbnail { + storage + ...SquareThumbnailFragment + } + ... on ReferencesGlobalEntityDates { + __isReferencesGlobalEntityDates: __typename + published { + value + ...PrecisionDateFragment + } + } + ... on Sluggable { + __isSluggable: __typename + slug + } + ... on Item { + summary + } + ... on Collection { + summary + } +} + +fragment ContributionSummaryFragment on ContributorAttribution { + __isContributorAttribution: __typename + ... on ContributorItemAttribution { + roles { + identifier + label + id + } + entity: item { + ...ContributionSummaryEntityFragment + id + } + } + ... on ContributorCollectionAttribution { + roles { + identifier + label + id + } + entity: collection { + ...ContributionSummaryEntityFragment + id + } + } +} + +fragment ContributorAvatarFragment on ImageAttachment { + small { + webp { + alt + url + } + } +} + +fragment ContributorDetailFragment on Contributor { + __isContributor: __typename + ...ContributorNameFragment + bio + orcid + attributions(page: $page, perPage: 25) { + nodes { + __typename + ... on ContributorItemAttribution { + id + } + ... on ContributorCollectionAttribution { + id + } + ...ContributionSummaryFragment + ... on Node { + __isNode: __typename + id + } + } + pageInfo { + totalCount + ...BrowseListLayoutFragment + } + } + image { + storage + ...ContributorAvatarFragment + } + links { + title + url + } + ... on PersonContributor { + affiliation + title + } + ... on Node { + __isNode: __typename + id + } +} + +fragment ContributorNameFragment on AnyContributor { + __isAnyContributor: __typename + ... on PersonContributor { + __typename + familyName + givenName + } + ... on OrganizationContributor { + __typename + legalName + } +} + +fragment PageCountFragment on PageInfo { + totalCount + page + perPage +} + +fragment PaginationFragment on PageInfo { + page + pageCount +} + +fragment PrecisionDateFragment on VariablePrecisionDate { + precision + value +} + +fragment SquareThumbnailFragment on ImageAttachment { + thumb: medium { + webp { + alt + url + } + } +} diff --git a/spec/data/queries/pageInstanceContentLayoutQuery.graphql b/spec/data/queries/pageInstanceContentLayoutQuery.graphql new file mode 100644 index 00000000..11df2435 --- /dev/null +++ b/spec/data/queries/pageInstanceContentLayoutQuery.graphql @@ -0,0 +1,81 @@ +query pageInstanceContentLayoutQuery { + communities(order: POSITION_ASCENDING) { + edges { + node { + slug + id + } + } + pageInfo { + totalCount + } + ...InstanceCommunitiesFragment + } + ...InstanceHeroFragment +} + +fragment InstanceCommunitiesFragment on CommunityConnection { + edges { + node { + slug + ...InstanceCommunitySummaryFragment + id + } + } +} + +fragment InstanceCommunitySummaryFragment on Community { + slug + title + tagline + summary + orderings { + nodes { + slug + name + count + id + } + } + heroImage { + large { + webp { + alt + url + width + height + } + } + medium { + webp { + url + width + } + } + small { + webp { + url + width + } + } + } + logo { + original { + alt + url + width + height + } + } +} + +fragment InstanceHeroFragment on Query { + globalConfiguration { + site { + providerName + installationName + installationHomePageCopy + } + id + } +} diff --git a/spec/data/queries/pageItemTemplateQuery.graphql b/spec/data/queries/pageItemTemplateQuery.graphql new file mode 100644 index 00000000..f8ea8c8f --- /dev/null +++ b/spec/data/queries/pageItemTemplateQuery.graphql @@ -0,0 +1,991 @@ +query pageItemTemplateQuery( + $slug: Slug! +) { + item(slug: $slug) { + layouts { + main { + ...MainLayoutFragment + id + } + } + id + } +} + +fragment AnnouncementsFragment on AnnouncementConnection { + nodes { + teaser + header + slug + id + } +} + +fragment BlurbTemplateFragment on BlurbTemplateInstance { + __typename + hidden + blurbDefinition: definition { + background + width + id + } + slots { + header { + ...sharedInlineSlotFragment + } + subheader { + ...sharedInlineSlotFragment + } + body { + ...sharedBlockSlotFragment + } + } +} + +fragment ColumnsDetailFragment on DetailTemplateInstance { + slots { + header { + ...sharedInlineSlotFragment + } + itemsA { + ...sharedBlockSlotFragment + } + itemsB { + ...sharedBlockSlotFragment + } + itemsC { + ...sharedBlockSlotFragment + } + itemsD { + ...sharedBlockSlotFragment + } + } +} + +fragment ContentImageFragment on ImageAttachment { + large { + webp { + alt + url + width + height + } + } + medium { + webp { + url + width + } + } + small { + webp { + url + width + } + } +} + +fragment ContributorAvatarFragment on ImageAttachment { + small { + webp { + alt + url + } + } +} + +fragment ContributorFragment on Attribution { + __isAttribution: __typename + roles { + identifier + label + id + } + contributor { + __typename + title + affiliation + slug + image { + ...ContributorAvatarFragment + } + ...ContributorNameFragment + ... on Node { + __isNode: __typename + id + } + } +} + +fragment ContributorNameFragment on AnyContributor { + __isAnyContributor: __typename + ... on PersonContributor { + __typename + familyName + givenName + } + ... on OrganizationContributor { + __typename + legalName + } +} + +fragment ContributorsListFragment on Entity { + __isEntity: __typename + ... on Item { + attributions { + roles { + label + id + } + contributor { + __typename + slug + ...ContributorNameFragment + ... on Node { + __isNode: __typename + id + } + } + id + } + } + ... on Collection { + attributions { + roles { + label + id + } + contributor { + __typename + slug + ...ContributorNameFragment + ... on Node { + __isNode: __typename + id + } + } + id + } + } +} + +fragment ContributorsTemplateFragment on ContributorListTemplateInstance { + __typename + entity { + __typename + ... on Item { + __typename + slug + attributions { + ...ContributorFragment + id + } + } + ... on Collection { + __typename + slug + attributions { + ...ContributorFragment + id + } + } + ... on Node { + __isNode: __typename + id + } + } + contributorsDefinition: definition { + background + limit + width + id + } + slots { + header { + ...sharedInlineSlotFragment + } + } +} + +fragment CoverCardListFragment on ImageAttachment { + image: medium { + webp { + url + alt + width + height + } + } +} + +fragment CoverImageFragment on ImageAttachment { + image: medium { + webp { + url + alt + width + height + } + } +} + +fragment DescendantsTemplateFragment on AnyMainTemplateInstance { + __isAnyMainTemplateInstance: __typename + ... on DescendantListTemplateInstance { + entity { + __typename + ... on Sluggable { + __isSluggable: __typename + slug + } + ... on Node { + __isNode: __typename + id + } + } + descendantsDefinition: definition { + variant + id + } + } + ...sharedListTemplateFragment +} + +fragment DetailTemplateFragment on DetailTemplateInstance { + __typename + hidden + detailDefinition: definition { + background + variant + id + } + ...SummaryDetailFragment + ...FullDetailFragment + ...ColumnsDetailFragment +} + +fragment FactoryTemplatesFragment on AnyMainTemplateInstance { + __isAnyMainTemplateInstance: __typename + ... on TemplateInstance { + __isTemplateInstance: __typename + templateKind + } + ... on ContributorListTemplateInstance { + ...ContributorsTemplateFragment + } + ... on DetailTemplateInstance { + ...DetailTemplateFragment + } + ... on OrderingTemplateInstance { + ...OrderingNavigationTemplateFragment + } + ... on PageListTemplateInstance { + ...PagesTemplateFragment + } + ... on DescendantListTemplateInstance { + slots { + blockHeader { + content + } + } + entityList { + empty + } + } + ... on LinkListTemplateInstance { + entityList { + empty + } + } + ... on BlurbTemplateInstance { + ...BlurbTemplateFragment + } + ...DescendantsTemplateFragment + ...LinksTemplateFragment +} + +fragment FullDetailFragment on DetailTemplateInstance { + entity { + __typename + ... on Item { + __typename + heroImage { + storage + ...ContentImageFragment + } + } + ... on Collection { + __typename + heroImage { + storage + ...ContentImageFragment + } + } + ... on Node { + __isNode: __typename + id + } + } + detailDefinition: definition { + showBody + showHeroImage + id + } + slots { + header { + ...sharedInlineSlotFragment + } + subheader { + ...sharedInlineSlotFragment + } + body { + ...sharedBlockSlotFragment + } + } +} + +fragment LinksTemplateFragment on AnyMainTemplateInstance { + __isAnyMainTemplateInstance: __typename + ... on LinkListTemplateInstance { + __typename + linksDefinition: definition { + variant + id + } + } + ...sharedListTemplateFragment +} + +fragment ListPagesTemplateFragment on Entity { + __isEntity: __typename + ... on Item { + pages { + edges { + node { + slug + title + id + } + } + } + } + ... on Collection { + pages { + edges { + node { + slug + title + id + } + } + } + } + ... on Community { + pages { + edges { + node { + slug + title + id + } + } + } + } +} + +fragment MainLayoutFragment on MainLayoutInstance { + allHidden + entity { + __typename + ... on Node { + __isNode: __typename + id + } + } + templates { + __typename + ... on TemplateInstance { + __isTemplateInstance: __typename + hidden + templateKind + prevSiblings { + dark + hidden + position + templateKind + id + } + nextSiblings { + dark + hidden + position + templateKind + id + } + } + ...FactoryTemplatesFragment + ... on Node { + __isNode: __typename + id + } + } +} + +fragment NavButtonsFragment on OrderingTemplateInstance { + orderingPair { + exists + first + last + nextSibling { + ...routesOrderingTemplateFragment + id + } + prevSibling { + ...routesOrderingTemplateFragment + id + } + } + slots { + nextLabel { + ...sharedInlineSlotFragment + } + previousLabel { + ...sharedInlineSlotFragment + } + } +} + +fragment OrderingNavigationTemplateFragment on OrderingTemplateInstance { + hidden + orderingDefinition: definition { + background + width + id + } + orderingPair { + exists + } + ...NavButtonsFragment +} + +fragment PagesTemplateFragment on PageListTemplateInstance { + __typename + hidden + pagesDefinition: definition { + background + width + id + } + entity { + __typename + ...ListPagesTemplateFragment + ... on Node { + __isNode: __typename + id + } + } +} + +fragment SummaryDetailFragment on DetailTemplateInstance { + entity { + __typename + ... on Collection { + __typename + announcements { + ...AnnouncementsFragment + nodes { + slug + id + } + } + } + ... on Community { + __typename + announcements { + ...AnnouncementsFragment + nodes { + slug + id + } + } + } + ... on Item { + __typename + announcements { + ...AnnouncementsFragment + nodes { + slug + id + } + } + } + ... on Node { + __isNode: __typename + id + } + } + detailDefinition: definition { + showAnnouncements + id + } + slots { + header { + ...sharedInlineSlotFragment + } + subheader { + ...sharedInlineSlotFragment + } + summary { + ...sharedBlockSlotFragment + } + } +} + +fragment getThumbWithFallbackFragment on Entity { + __isEntity: __typename + ... on Collection { + thumbnail { + image: medium { + webp { + url + } + } + ...CoverImageFragment + ...CoverCardListFragment + } + breadcrumbs { + crumb { + __typename + ... on Collection { + thumbnail { + image: medium { + webp { + url + } + } + ...CoverImageFragment + ...CoverCardListFragment + } + } + ... on Node { + __isNode: __typename + id + } + } + id + } + } + ... on Item { + thumbnail { + image: medium { + webp { + url + } + } + ...CoverImageFragment + ...CoverCardListFragment + } + breadcrumbs { + crumb { + __typename + ... on Collection { + thumbnail { + image: medium { + webp { + url + } + } + ...CoverImageFragment + ...CoverCardListFragment + } + } + ... on Item { + thumbnail { + image: medium { + webp { + url + } + } + ...CoverImageFragment + ...CoverCardListFragment + } + } + ... on Node { + __isNode: __typename + id + } + } + id + } + } +} + +fragment routesOrderingTemplateFragment on OrderingEntry { + entrySlug + entry { + __typename + ... on Collection { + __typename + } + ... on Item { + __typename + } + ... on Community { + __typename + } + ... on EntityLink { + __typename + target { + __typename + ... on Collection { + __typename + } + ... on Item { + __typename + } + ... on Community { + __typename + } + ... on Node { + __isNode: __typename + id + } + } + } + id + } +} + +fragment sharedBlockSlotFragment on TemplateSlotBlockInstance { + empty + content + kind + valid +} + +fragment sharedInlineSlotFragment on TemplateSlotInlineInstance { + empty + content + kind + valid + hidesTemplate +} + +fragment sharedListItemTemplateFragment on ListItemTemplateInstance { + definition { + seeAllOrderingIdentifier + id + } + entity { + __typename + ... on Collection { + __typename + id + slug + title + hierarchicalDepth + ...getThumbWithFallbackFragment + attributions { + id + } + ...ContributorsListFragment + heroImage { + large { + webp { + alt + url + width + height + } + } + medium { + webp { + url + width + } + } + thumb { + webp { + url + width + } + } + } + } + ... on Item { + __typename + id + slug + title + hierarchicalDepth + attributions { + id + } + ...getThumbWithFallbackFragment + ...ContributorsListFragment + heroImage { + large { + webp { + alt + url + width + height + } + } + medium { + webp { + url + width + } + } + thumb { + webp { + url + width + } + } + } + } + ... on Node { + __isNode: __typename + id + } + } + slots { + contextFull { + ...sharedInlineSlotFragment + } + contextAbbr { + ...sharedInlineSlotFragment + } + contextC { + ...sharedInlineSlotFragment + } + description { + ...sharedBlockSlotFragment + } + header { + ...sharedInlineSlotFragment + } + metaA { + ...sharedInlineSlotFragment + } + metaB { + ...sharedInlineSlotFragment + } + subheader { + ...sharedInlineSlotFragment + } + nestedHeader { + ...sharedInlineSlotFragment + } + nestedSubheader { + ...sharedInlineSlotFragment + } + nestedContext { + ...sharedInlineSlotFragment + } + nestedMetadata { + ...sharedInlineSlotFragment + } + } +} + +fragment sharedListItemsTemplateFragment on TemplateEntityList { + empty + count + depths: listItemLayouts { + template { + entity { + __typename + ... on Collection { + hierarchicalDepth + } + ... on Item { + hierarchicalDepth + } + ... on Node { + __isNode: __typename + id + } + } + id + } + id + } + listItemLayouts { + template { + entity { + __typename + ... on Collection { + hierarchicalDepth + } + ... on Item { + hierarchicalDepth + } + ... on Node { + __isNode: __typename + id + } + } + ...sharedListItemTemplateFragment + entityList { + empty + count + listItemLayouts { + template { + ...sharedListItemTemplateFragment + id + } + id + } + } + id + } + id + } +} + +fragment sharedListTemplateFragment on AnyMainTemplateInstance { + __isAnyMainTemplateInstance: __typename + ... on LinkListTemplateInstance { + entity { + __typename + ... on Community { + __typename + slug + } + ... on Collection { + __typename + slug + ...getThumbWithFallbackFragment + } + ... on Item { + __typename + slug + ...getThumbWithFallbackFragment + } + ... on Node { + __isNode: __typename + id + } + } + linksDefinition: definition { + background + seeAllButtonLabel + showSeeAllButton + selectionMode + selectionLimit + showEntityContext + title + variant + showHeroImage + width + showNestedEntities + seeAllOrderingIdentifier + showContributors + id + } + slots { + blockHeader { + ...sharedInlineSlotFragment + } + header { + ...sharedInlineSlotFragment + } + headerAside { + ...sharedInlineSlotFragment + } + metadata { + ...sharedInlineSlotFragment + } + subtitle { + ...sharedInlineSlotFragment + } + } + entityList { + count + empty + ...sharedListItemsTemplateFragment + } + } + ... on DescendantListTemplateInstance { + seeAllOrdering { + count + name + id + } + entity { + __typename + ... on Community { + __typename + slug + } + ... on Collection { + __typename + id + title + slug + ...getThumbWithFallbackFragment + } + ... on Item { + __typename + id + title + slug + ...getThumbWithFallbackFragment + } + ... on Node { + __isNode: __typename + id + } + } + descendantsDefinition: definition { + background + seeAllButtonLabel + showSeeAllButton + selectionMode + selectionPropertyPath + orderingIdentifier + dynamicOrderingDefinition { + filter { + schemas { + namespace + identifier + } + } + } + selectionLimit + entityContext + title + variant + showHeroImage + width + showNestedEntities + seeAllOrderingIdentifier + showContributors + id + } + slots { + blockHeader { + ...sharedInlineSlotFragment + } + header { + ...sharedInlineSlotFragment + } + headerAside { + ...sharedInlineSlotFragment + } + metadata { + ...sharedInlineSlotFragment + } + subtitle { + ...sharedInlineSlotFragment + } + } + entityList { + ...sharedListItemsTemplateFragment + } + } +} diff --git a/spec/data/queries/pageTemplateQuery.graphql b/spec/data/queries/pageTemplateQuery.graphql new file mode 100644 index 00000000..6123181e --- /dev/null +++ b/spec/data/queries/pageTemplateQuery.graphql @@ -0,0 +1,991 @@ +query pageTemplateQuery( + $slug: Slug! +) { + community(slug: $slug) { + layouts { + main { + ...MainLayoutFragment + id + } + } + id + } +} + +fragment AnnouncementsFragment on AnnouncementConnection { + nodes { + teaser + header + slug + id + } +} + +fragment BlurbTemplateFragment on BlurbTemplateInstance { + __typename + hidden + blurbDefinition: definition { + background + width + id + } + slots { + header { + ...sharedInlineSlotFragment + } + subheader { + ...sharedInlineSlotFragment + } + body { + ...sharedBlockSlotFragment + } + } +} + +fragment ColumnsDetailFragment on DetailTemplateInstance { + slots { + header { + ...sharedInlineSlotFragment + } + itemsA { + ...sharedBlockSlotFragment + } + itemsB { + ...sharedBlockSlotFragment + } + itemsC { + ...sharedBlockSlotFragment + } + itemsD { + ...sharedBlockSlotFragment + } + } +} + +fragment ContentImageFragment on ImageAttachment { + large { + webp { + alt + url + width + height + } + } + medium { + webp { + url + width + } + } + small { + webp { + url + width + } + } +} + +fragment ContributorAvatarFragment on ImageAttachment { + small { + webp { + alt + url + } + } +} + +fragment ContributorFragment on Attribution { + __isAttribution: __typename + roles { + identifier + label + id + } + contributor { + __typename + title + affiliation + slug + image { + ...ContributorAvatarFragment + } + ...ContributorNameFragment + ... on Node { + __isNode: __typename + id + } + } +} + +fragment ContributorNameFragment on AnyContributor { + __isAnyContributor: __typename + ... on PersonContributor { + __typename + familyName + givenName + } + ... on OrganizationContributor { + __typename + legalName + } +} + +fragment ContributorsListFragment on Entity { + __isEntity: __typename + ... on Item { + attributions { + roles { + label + id + } + contributor { + __typename + slug + ...ContributorNameFragment + ... on Node { + __isNode: __typename + id + } + } + id + } + } + ... on Collection { + attributions { + roles { + label + id + } + contributor { + __typename + slug + ...ContributorNameFragment + ... on Node { + __isNode: __typename + id + } + } + id + } + } +} + +fragment ContributorsTemplateFragment on ContributorListTemplateInstance { + __typename + entity { + __typename + ... on Item { + __typename + slug + attributions { + ...ContributorFragment + id + } + } + ... on Collection { + __typename + slug + attributions { + ...ContributorFragment + id + } + } + ... on Node { + __isNode: __typename + id + } + } + contributorsDefinition: definition { + background + limit + width + id + } + slots { + header { + ...sharedInlineSlotFragment + } + } +} + +fragment CoverCardListFragment on ImageAttachment { + image: medium { + webp { + url + alt + width + height + } + } +} + +fragment CoverImageFragment on ImageAttachment { + image: medium { + webp { + url + alt + width + height + } + } +} + +fragment DescendantsTemplateFragment on AnyMainTemplateInstance { + __isAnyMainTemplateInstance: __typename + ... on DescendantListTemplateInstance { + entity { + __typename + ... on Sluggable { + __isSluggable: __typename + slug + } + ... on Node { + __isNode: __typename + id + } + } + descendantsDefinition: definition { + variant + id + } + } + ...sharedListTemplateFragment +} + +fragment DetailTemplateFragment on DetailTemplateInstance { + __typename + hidden + detailDefinition: definition { + background + variant + id + } + ...SummaryDetailFragment + ...FullDetailFragment + ...ColumnsDetailFragment +} + +fragment FactoryTemplatesFragment on AnyMainTemplateInstance { + __isAnyMainTemplateInstance: __typename + ... on TemplateInstance { + __isTemplateInstance: __typename + templateKind + } + ... on ContributorListTemplateInstance { + ...ContributorsTemplateFragment + } + ... on DetailTemplateInstance { + ...DetailTemplateFragment + } + ... on OrderingTemplateInstance { + ...OrderingNavigationTemplateFragment + } + ... on PageListTemplateInstance { + ...PagesTemplateFragment + } + ... on DescendantListTemplateInstance { + slots { + blockHeader { + content + } + } + entityList { + empty + } + } + ... on LinkListTemplateInstance { + entityList { + empty + } + } + ... on BlurbTemplateInstance { + ...BlurbTemplateFragment + } + ...DescendantsTemplateFragment + ...LinksTemplateFragment +} + +fragment FullDetailFragment on DetailTemplateInstance { + entity { + __typename + ... on Item { + __typename + heroImage { + storage + ...ContentImageFragment + } + } + ... on Collection { + __typename + heroImage { + storage + ...ContentImageFragment + } + } + ... on Node { + __isNode: __typename + id + } + } + detailDefinition: definition { + showBody + showHeroImage + id + } + slots { + header { + ...sharedInlineSlotFragment + } + subheader { + ...sharedInlineSlotFragment + } + body { + ...sharedBlockSlotFragment + } + } +} + +fragment LinksTemplateFragment on AnyMainTemplateInstance { + __isAnyMainTemplateInstance: __typename + ... on LinkListTemplateInstance { + __typename + linksDefinition: definition { + variant + id + } + } + ...sharedListTemplateFragment +} + +fragment ListPagesTemplateFragment on Entity { + __isEntity: __typename + ... on Item { + pages { + edges { + node { + slug + title + id + } + } + } + } + ... on Collection { + pages { + edges { + node { + slug + title + id + } + } + } + } + ... on Community { + pages { + edges { + node { + slug + title + id + } + } + } + } +} + +fragment MainLayoutFragment on MainLayoutInstance { + allHidden + entity { + __typename + ... on Node { + __isNode: __typename + id + } + } + templates { + __typename + ... on TemplateInstance { + __isTemplateInstance: __typename + hidden + templateKind + prevSiblings { + dark + hidden + position + templateKind + id + } + nextSiblings { + dark + hidden + position + templateKind + id + } + } + ...FactoryTemplatesFragment + ... on Node { + __isNode: __typename + id + } + } +} + +fragment NavButtonsFragment on OrderingTemplateInstance { + orderingPair { + exists + first + last + nextSibling { + ...routesOrderingTemplateFragment + id + } + prevSibling { + ...routesOrderingTemplateFragment + id + } + } + slots { + nextLabel { + ...sharedInlineSlotFragment + } + previousLabel { + ...sharedInlineSlotFragment + } + } +} + +fragment OrderingNavigationTemplateFragment on OrderingTemplateInstance { + hidden + orderingDefinition: definition { + background + width + id + } + orderingPair { + exists + } + ...NavButtonsFragment +} + +fragment PagesTemplateFragment on PageListTemplateInstance { + __typename + hidden + pagesDefinition: definition { + background + width + id + } + entity { + __typename + ...ListPagesTemplateFragment + ... on Node { + __isNode: __typename + id + } + } +} + +fragment SummaryDetailFragment on DetailTemplateInstance { + entity { + __typename + ... on Collection { + __typename + announcements { + ...AnnouncementsFragment + nodes { + slug + id + } + } + } + ... on Community { + __typename + announcements { + ...AnnouncementsFragment + nodes { + slug + id + } + } + } + ... on Item { + __typename + announcements { + ...AnnouncementsFragment + nodes { + slug + id + } + } + } + ... on Node { + __isNode: __typename + id + } + } + detailDefinition: definition { + showAnnouncements + id + } + slots { + header { + ...sharedInlineSlotFragment + } + subheader { + ...sharedInlineSlotFragment + } + summary { + ...sharedBlockSlotFragment + } + } +} + +fragment getThumbWithFallbackFragment on Entity { + __isEntity: __typename + ... on Collection { + thumbnail { + image: medium { + webp { + url + } + } + ...CoverImageFragment + ...CoverCardListFragment + } + breadcrumbs { + crumb { + __typename + ... on Collection { + thumbnail { + image: medium { + webp { + url + } + } + ...CoverImageFragment + ...CoverCardListFragment + } + } + ... on Node { + __isNode: __typename + id + } + } + id + } + } + ... on Item { + thumbnail { + image: medium { + webp { + url + } + } + ...CoverImageFragment + ...CoverCardListFragment + } + breadcrumbs { + crumb { + __typename + ... on Collection { + thumbnail { + image: medium { + webp { + url + } + } + ...CoverImageFragment + ...CoverCardListFragment + } + } + ... on Item { + thumbnail { + image: medium { + webp { + url + } + } + ...CoverImageFragment + ...CoverCardListFragment + } + } + ... on Node { + __isNode: __typename + id + } + } + id + } + } +} + +fragment routesOrderingTemplateFragment on OrderingEntry { + entrySlug + entry { + __typename + ... on Collection { + __typename + } + ... on Item { + __typename + } + ... on Community { + __typename + } + ... on EntityLink { + __typename + target { + __typename + ... on Collection { + __typename + } + ... on Item { + __typename + } + ... on Community { + __typename + } + ... on Node { + __isNode: __typename + id + } + } + } + id + } +} + +fragment sharedBlockSlotFragment on TemplateSlotBlockInstance { + empty + content + kind + valid +} + +fragment sharedInlineSlotFragment on TemplateSlotInlineInstance { + empty + content + kind + valid + hidesTemplate +} + +fragment sharedListItemTemplateFragment on ListItemTemplateInstance { + definition { + seeAllOrderingIdentifier + id + } + entity { + __typename + ... on Collection { + __typename + id + slug + title + hierarchicalDepth + ...getThumbWithFallbackFragment + attributions { + id + } + ...ContributorsListFragment + heroImage { + large { + webp { + alt + url + width + height + } + } + medium { + webp { + url + width + } + } + thumb { + webp { + url + width + } + } + } + } + ... on Item { + __typename + id + slug + title + hierarchicalDepth + attributions { + id + } + ...getThumbWithFallbackFragment + ...ContributorsListFragment + heroImage { + large { + webp { + alt + url + width + height + } + } + medium { + webp { + url + width + } + } + thumb { + webp { + url + width + } + } + } + } + ... on Node { + __isNode: __typename + id + } + } + slots { + contextFull { + ...sharedInlineSlotFragment + } + contextAbbr { + ...sharedInlineSlotFragment + } + contextC { + ...sharedInlineSlotFragment + } + description { + ...sharedBlockSlotFragment + } + header { + ...sharedInlineSlotFragment + } + metaA { + ...sharedInlineSlotFragment + } + metaB { + ...sharedInlineSlotFragment + } + subheader { + ...sharedInlineSlotFragment + } + nestedHeader { + ...sharedInlineSlotFragment + } + nestedSubheader { + ...sharedInlineSlotFragment + } + nestedContext { + ...sharedInlineSlotFragment + } + nestedMetadata { + ...sharedInlineSlotFragment + } + } +} + +fragment sharedListItemsTemplateFragment on TemplateEntityList { + empty + count + depths: listItemLayouts { + template { + entity { + __typename + ... on Collection { + hierarchicalDepth + } + ... on Item { + hierarchicalDepth + } + ... on Node { + __isNode: __typename + id + } + } + id + } + id + } + listItemLayouts { + template { + entity { + __typename + ... on Collection { + hierarchicalDepth + } + ... on Item { + hierarchicalDepth + } + ... on Node { + __isNode: __typename + id + } + } + ...sharedListItemTemplateFragment + entityList { + empty + count + listItemLayouts { + template { + ...sharedListItemTemplateFragment + id + } + id + } + } + id + } + id + } +} + +fragment sharedListTemplateFragment on AnyMainTemplateInstance { + __isAnyMainTemplateInstance: __typename + ... on LinkListTemplateInstance { + entity { + __typename + ... on Community { + __typename + slug + } + ... on Collection { + __typename + slug + ...getThumbWithFallbackFragment + } + ... on Item { + __typename + slug + ...getThumbWithFallbackFragment + } + ... on Node { + __isNode: __typename + id + } + } + linksDefinition: definition { + background + seeAllButtonLabel + showSeeAllButton + selectionMode + selectionLimit + showEntityContext + title + variant + showHeroImage + width + showNestedEntities + seeAllOrderingIdentifier + showContributors + id + } + slots { + blockHeader { + ...sharedInlineSlotFragment + } + header { + ...sharedInlineSlotFragment + } + headerAside { + ...sharedInlineSlotFragment + } + metadata { + ...sharedInlineSlotFragment + } + subtitle { + ...sharedInlineSlotFragment + } + } + entityList { + count + empty + ...sharedListItemsTemplateFragment + } + } + ... on DescendantListTemplateInstance { + seeAllOrdering { + count + name + id + } + entity { + __typename + ... on Community { + __typename + slug + } + ... on Collection { + __typename + id + title + slug + ...getThumbWithFallbackFragment + } + ... on Item { + __typename + id + title + slug + ...getThumbWithFallbackFragment + } + ... on Node { + __isNode: __typename + id + } + } + descendantsDefinition: definition { + background + seeAllButtonLabel + showSeeAllButton + selectionMode + selectionPropertyPath + orderingIdentifier + dynamicOrderingDefinition { + filter { + schemas { + namespace + identifier + } + } + } + selectionLimit + entityContext + title + variant + showHeroImage + width + showNestedEntities + seeAllOrderingIdentifier + showContributors + id + } + slots { + blockHeader { + ...sharedInlineSlotFragment + } + header { + ...sharedInlineSlotFragment + } + headerAside { + ...sharedInlineSlotFragment + } + metadata { + ...sharedInlineSlotFragment + } + subtitle { + ...sharedInlineSlotFragment + } + } + entityList { + ...sharedListItemsTemplateFragment + } + } +} diff --git a/spec/data/queries/pageTemplatesBrowseCollectionQuery.graphql b/spec/data/queries/pageTemplatesBrowseCollectionQuery.graphql new file mode 100644 index 00000000..d034646b --- /dev/null +++ b/spec/data/queries/pageTemplatesBrowseCollectionQuery.graphql @@ -0,0 +1,425 @@ +query pageTemplatesBrowseCollectionQuery( + $slug: Slug! + $identifier: String! + $page: Int +) { + collection(slug: $slug) { + ordering(identifier: $identifier) { + disabled + ...EntityOrderingLayoutFragment + id + } + id + } +} + +fragment BackButtonFragment on Entity { + __isEntity: __typename + __typename + slug + schemaVersion { + name + id + } +} + +fragment BrowseListLayoutFragment on PageInfo { + ...PaginationFragment + ...PageCountFragment +} + +fragment BrowseTreeItemFragment on OrderingEntry { + treeDepth + entry { + __typename + ... on Sluggable { + __isSluggable: __typename + slug + } + ... on Entity { + __isEntity: __typename + layouts { + listItem { + template { + ...sharedListItemTemplateFragment + id + } + id + } + } + } + id + } +} + +fragment BrowseTreeLayoutFragment on OrderingEntryConnection { + nodes { + id + treeDepth + ancestors { + id + treeDepth + ...BrowseTreeItemFragment + } + ...BrowseTreeItemFragment + } + pageInfo { + ...PaginationFragment + ...PageCountFragment + } +} + +fragment ContributorNameFragment on AnyContributor { + __isAnyContributor: __typename + ... on PersonContributor { + __typename + familyName + givenName + } + ... on OrganizationContributor { + __typename + legalName + } +} + +fragment ContributorsListFragment on Entity { + __isEntity: __typename + ... on Item { + attributions { + roles { + label + id + } + contributor { + __typename + slug + ...ContributorNameFragment + ... on Node { + __isNode: __typename + id + } + } + id + } + } + ... on Collection { + attributions { + roles { + label + id + } + contributor { + __typename + slug + ...ContributorNameFragment + ... on Node { + __isNode: __typename + id + } + } + id + } + } +} + +fragment CoverCardListFragment on ImageAttachment { + image: medium { + webp { + url + alt + width + height + } + } +} + +fragment CoverImageFragment on ImageAttachment { + image: medium { + webp { + url + alt + width + height + } + } +} + +fragment EntityOrderingLayoutFragment on Ordering { + name + header + render { + mode + } + entity { + __typename + ... on Sluggable { + __isSluggable: __typename + slug + } + ...BackButtonFragment + ... on Node { + __isNode: __typename + id + } + } + children(page: $page) { + edges { + node { + id + entry { + __typename + ... on Sluggable { + __isSluggable: __typename + slug + } + ...EntitySummaryFragment + id + } + } + } + pageInfo { + ...BrowseListLayoutFragment + } + ...BrowseTreeLayoutFragment + } + id +} + +fragment EntitySummaryFragment on Entity { + __isEntity: __typename + __typename + layouts { + listItem { + template { + ...sharedListItemTemplateFragment + id + } + id + } + } +} + +fragment PageCountFragment on PageInfo { + totalCount + page + perPage +} + +fragment PaginationFragment on PageInfo { + page + pageCount +} + +fragment getThumbWithFallbackFragment on Entity { + __isEntity: __typename + ... on Collection { + thumbnail { + image: medium { + webp { + url + } + } + ...CoverImageFragment + ...CoverCardListFragment + } + breadcrumbs { + crumb { + __typename + ... on Collection { + thumbnail { + image: medium { + webp { + url + } + } + ...CoverImageFragment + ...CoverCardListFragment + } + } + ... on Node { + __isNode: __typename + id + } + } + id + } + } + ... on Item { + thumbnail { + image: medium { + webp { + url + } + } + ...CoverImageFragment + ...CoverCardListFragment + } + breadcrumbs { + crumb { + __typename + ... on Collection { + thumbnail { + image: medium { + webp { + url + } + } + ...CoverImageFragment + ...CoverCardListFragment + } + } + ... on Item { + thumbnail { + image: medium { + webp { + url + } + } + ...CoverImageFragment + ...CoverCardListFragment + } + } + ... on Node { + __isNode: __typename + id + } + } + id + } + } +} + +fragment sharedBlockSlotFragment on TemplateSlotBlockInstance { + empty + content + kind + valid +} + +fragment sharedInlineSlotFragment on TemplateSlotInlineInstance { + empty + content + kind + valid + hidesTemplate +} + +fragment sharedListItemTemplateFragment on ListItemTemplateInstance { + definition { + seeAllOrderingIdentifier + id + } + entity { + __typename + ... on Collection { + __typename + id + slug + title + hierarchicalDepth + ...getThumbWithFallbackFragment + attributions { + id + } + ...ContributorsListFragment + heroImage { + large { + webp { + alt + url + width + height + } + } + medium { + webp { + url + width + } + } + thumb { + webp { + url + width + } + } + } + } + ... on Item { + __typename + id + slug + title + hierarchicalDepth + attributions { + id + } + ...getThumbWithFallbackFragment + ...ContributorsListFragment + heroImage { + large { + webp { + alt + url + width + height + } + } + medium { + webp { + url + width + } + } + thumb { + webp { + url + width + } + } + } + } + ... on Node { + __isNode: __typename + id + } + } + slots { + contextFull { + ...sharedInlineSlotFragment + } + contextAbbr { + ...sharedInlineSlotFragment + } + contextC { + ...sharedInlineSlotFragment + } + description { + ...sharedBlockSlotFragment + } + header { + ...sharedInlineSlotFragment + } + metaA { + ...sharedInlineSlotFragment + } + metaB { + ...sharedInlineSlotFragment + } + subheader { + ...sharedInlineSlotFragment + } + nestedHeader { + ...sharedInlineSlotFragment + } + nestedSubheader { + ...sharedInlineSlotFragment + } + nestedContext { + ...sharedInlineSlotFragment + } + nestedMetadata { + ...sharedInlineSlotFragment + } + } +} diff --git a/spec/data/queries/pageTemplatesItemContributorsQuery.graphql b/spec/data/queries/pageTemplatesItemContributorsQuery.graphql new file mode 100644 index 00000000..2eac09b9 --- /dev/null +++ b/spec/data/queries/pageTemplatesItemContributorsQuery.graphql @@ -0,0 +1,75 @@ +query pageTemplatesItemContributorsQuery( + $slug: Slug! +) { + item(slug: $slug) { + ...ContributionsBlockFragment + id + } +} + +fragment ContributionsBlockFragment on Item { + attributions { + slug + roles { + label + id + } + contributor { + __typename + image { + storage + } + ... on Node { + __isNode: __typename + id + } + } + ...ContributorFragment + id + } +} + +fragment ContributorAvatarFragment on ImageAttachment { + small { + webp { + alt + url + } + } +} + +fragment ContributorFragment on Attribution { + __isAttribution: __typename + roles { + identifier + label + id + } + contributor { + __typename + title + affiliation + slug + image { + ...ContributorAvatarFragment + } + ...ContributorNameFragment + ... on Node { + __isNode: __typename + id + } + } +} + +fragment ContributorNameFragment on AnyContributor { + __isAnyContributor: __typename + ... on PersonContributor { + __typename + familyName + givenName + } + ... on OrganizationContributor { + __typename + legalName + } +} diff --git a/spec/data/queries/pageTemplatesItemFileDetailQuery.graphql b/spec/data/queries/pageTemplatesItemFileDetailQuery.graphql new file mode 100644 index 00000000..3462af4c --- /dev/null +++ b/spec/data/queries/pageTemplatesItemFileDetailQuery.graphql @@ -0,0 +1,61 @@ +query pageTemplatesItemFileDetailQuery( + $file: Slug! +) { + asset(slug: $file) { + __typename + ...AssetDetailBlockFragment + id + } +} + +fragment AssetDetailBlockFragment on Node { + __isNode: __typename + ... on Asset { + __isAsset: __typename + slug + caption + kind + downloadUrl + fileSize + name + altText + preview { + storage + ...ContentImageFragment + } + ...AssetPDFPreviewFragment + } + ... on AssetImage { + updatedAt + } +} + +fragment AssetPDFPreviewFragment on Asset { + __isAsset: __typename + ... on AssetPDF { + downloadUrl + } +} + +fragment ContentImageFragment on ImageAttachment { + large { + webp { + alt + url + width + height + } + } + medium { + webp { + url + width + } + } + small { + webp { + url + width + } + } +} diff --git a/spec/data/queries/pageTemplatesItemFilesQuery.graphql b/spec/data/queries/pageTemplatesItemFilesQuery.graphql new file mode 100644 index 00000000..3da95a6b --- /dev/null +++ b/spec/data/queries/pageTemplatesItemFilesQuery.graphql @@ -0,0 +1,63 @@ +query pageTemplatesItemFilesQuery( + $slug: Slug! +) { + item(slug: $slug) { + assets { + ...AssetsBlockFragment + } + id + } +} + +fragment AssetBlockItemFragment on Asset { + __isAsset: __typename + caption + contentType + downloadUrl + fileSize + kind + name + slug + ...AssetThumbnailFragment + ... on AssetDocument { + updatedAt + } + ... on AssetImage { + updatedAt + } + ... on AssetPDF { + updatedAt + } + ... on AssetAudio { + updatedAt + } + ... on AssetVideo { + updatedAt + } +} + +fragment AssetThumbnailFragment on Asset { + __isAsset: __typename + kind + slug + altText + preview { + storage + image: small { + webp { + alt + url + } + } + } +} + +fragment AssetsBlockFragment on AssetConnection { + edges { + node { + __typename + ...AssetBlockItemFragment + id + } + } +} diff --git a/spec/data/queries/pageTemplatesItemMetadataQuery.graphql b/spec/data/queries/pageTemplatesItemMetadataQuery.graphql new file mode 100644 index 00000000..92897a3e --- /dev/null +++ b/spec/data/queries/pageTemplatesItemMetadataQuery.graphql @@ -0,0 +1,1022 @@ +query pageTemplatesItemMetadataQuery( + $slug: Slug! +) { + item(slug: $slug) { + layouts { + metadata { + template { + ...MetadataTemplateFragment + id + } + id + } + main { + ...MainLayoutFragment + id + } + } + id + } +} + +fragment AnnouncementsFragment on AnnouncementConnection { + nodes { + teaser + header + slug + id + } +} + +fragment BlurbTemplateFragment on BlurbTemplateInstance { + __typename + hidden + blurbDefinition: definition { + background + width + id + } + slots { + header { + ...sharedInlineSlotFragment + } + subheader { + ...sharedInlineSlotFragment + } + body { + ...sharedBlockSlotFragment + } + } +} + +fragment ColumnsDetailFragment on DetailTemplateInstance { + slots { + header { + ...sharedInlineSlotFragment + } + itemsA { + ...sharedBlockSlotFragment + } + itemsB { + ...sharedBlockSlotFragment + } + itemsC { + ...sharedBlockSlotFragment + } + itemsD { + ...sharedBlockSlotFragment + } + } +} + +fragment ContentImageFragment on ImageAttachment { + large { + webp { + alt + url + width + height + } + } + medium { + webp { + url + width + } + } + small { + webp { + url + width + } + } +} + +fragment ContributorAvatarFragment on ImageAttachment { + small { + webp { + alt + url + } + } +} + +fragment ContributorFragment on Attribution { + __isAttribution: __typename + roles { + identifier + label + id + } + contributor { + __typename + title + affiliation + slug + image { + ...ContributorAvatarFragment + } + ...ContributorNameFragment + ... on Node { + __isNode: __typename + id + } + } +} + +fragment ContributorNameFragment on AnyContributor { + __isAnyContributor: __typename + ... on PersonContributor { + __typename + familyName + givenName + } + ... on OrganizationContributor { + __typename + legalName + } +} + +fragment ContributorsListFragment on Entity { + __isEntity: __typename + ... on Item { + attributions { + roles { + label + id + } + contributor { + __typename + slug + ...ContributorNameFragment + ... on Node { + __isNode: __typename + id + } + } + id + } + } + ... on Collection { + attributions { + roles { + label + id + } + contributor { + __typename + slug + ...ContributorNameFragment + ... on Node { + __isNode: __typename + id + } + } + id + } + } +} + +fragment ContributorsTemplateFragment on ContributorListTemplateInstance { + __typename + entity { + __typename + ... on Item { + __typename + slug + attributions { + ...ContributorFragment + id + } + } + ... on Collection { + __typename + slug + attributions { + ...ContributorFragment + id + } + } + ... on Node { + __isNode: __typename + id + } + } + contributorsDefinition: definition { + background + limit + width + id + } + slots { + header { + ...sharedInlineSlotFragment + } + } +} + +fragment CoverCardListFragment on ImageAttachment { + image: medium { + webp { + url + alt + width + height + } + } +} + +fragment CoverImageFragment on ImageAttachment { + image: medium { + webp { + url + alt + width + height + } + } +} + +fragment DescendantsTemplateFragment on AnyMainTemplateInstance { + __isAnyMainTemplateInstance: __typename + ... on DescendantListTemplateInstance { + entity { + __typename + ... on Sluggable { + __isSluggable: __typename + slug + } + ... on Node { + __isNode: __typename + id + } + } + descendantsDefinition: definition { + variant + id + } + } + ...sharedListTemplateFragment +} + +fragment DetailTemplateFragment on DetailTemplateInstance { + __typename + hidden + detailDefinition: definition { + background + variant + id + } + ...SummaryDetailFragment + ...FullDetailFragment + ...ColumnsDetailFragment +} + +fragment FactoryTemplatesFragment on AnyMainTemplateInstance { + __isAnyMainTemplateInstance: __typename + ... on TemplateInstance { + __isTemplateInstance: __typename + templateKind + } + ... on ContributorListTemplateInstance { + ...ContributorsTemplateFragment + } + ... on DetailTemplateInstance { + ...DetailTemplateFragment + } + ... on OrderingTemplateInstance { + ...OrderingNavigationTemplateFragment + } + ... on PageListTemplateInstance { + ...PagesTemplateFragment + } + ... on DescendantListTemplateInstance { + slots { + blockHeader { + content + } + } + entityList { + empty + } + } + ... on LinkListTemplateInstance { + entityList { + empty + } + } + ... on BlurbTemplateInstance { + ...BlurbTemplateFragment + } + ...DescendantsTemplateFragment + ...LinksTemplateFragment +} + +fragment FullDetailFragment on DetailTemplateInstance { + entity { + __typename + ... on Item { + __typename + heroImage { + storage + ...ContentImageFragment + } + } + ... on Collection { + __typename + heroImage { + storage + ...ContentImageFragment + } + } + ... on Node { + __isNode: __typename + id + } + } + detailDefinition: definition { + showBody + showHeroImage + id + } + slots { + header { + ...sharedInlineSlotFragment + } + subheader { + ...sharedInlineSlotFragment + } + body { + ...sharedBlockSlotFragment + } + } +} + +fragment LinksTemplateFragment on AnyMainTemplateInstance { + __isAnyMainTemplateInstance: __typename + ... on LinkListTemplateInstance { + __typename + linksDefinition: definition { + variant + id + } + } + ...sharedListTemplateFragment +} + +fragment ListPagesTemplateFragment on Entity { + __isEntity: __typename + ... on Item { + pages { + edges { + node { + slug + title + id + } + } + } + } + ... on Collection { + pages { + edges { + node { + slug + title + id + } + } + } + } + ... on Community { + pages { + edges { + node { + slug + title + id + } + } + } + } +} + +fragment MainLayoutFragment on MainLayoutInstance { + allHidden + entity { + __typename + ... on Node { + __isNode: __typename + id + } + } + templates { + __typename + ... on TemplateInstance { + __isTemplateInstance: __typename + hidden + templateKind + prevSiblings { + dark + hidden + position + templateKind + id + } + nextSiblings { + dark + hidden + position + templateKind + id + } + } + ...FactoryTemplatesFragment + ... on Node { + __isNode: __typename + id + } + } +} + +fragment MetadataTemplateFragment on MetadataTemplateInstance { + definition { + background + id + } + slots { + header { + ...sharedInlineSlotFragment + } + itemsA { + ...sharedBlockSlotFragment + } + itemsB { + ...sharedBlockSlotFragment + } + itemsC { + ...sharedBlockSlotFragment + } + itemsD { + ...sharedBlockSlotFragment + } + } +} + +fragment NavButtonsFragment on OrderingTemplateInstance { + orderingPair { + exists + first + last + nextSibling { + ...routesOrderingTemplateFragment + id + } + prevSibling { + ...routesOrderingTemplateFragment + id + } + } + slots { + nextLabel { + ...sharedInlineSlotFragment + } + previousLabel { + ...sharedInlineSlotFragment + } + } +} + +fragment OrderingNavigationTemplateFragment on OrderingTemplateInstance { + hidden + orderingDefinition: definition { + background + width + id + } + orderingPair { + exists + } + ...NavButtonsFragment +} + +fragment PagesTemplateFragment on PageListTemplateInstance { + __typename + hidden + pagesDefinition: definition { + background + width + id + } + entity { + __typename + ...ListPagesTemplateFragment + ... on Node { + __isNode: __typename + id + } + } +} + +fragment SummaryDetailFragment on DetailTemplateInstance { + entity { + __typename + ... on Collection { + __typename + announcements { + ...AnnouncementsFragment + nodes { + slug + id + } + } + } + ... on Community { + __typename + announcements { + ...AnnouncementsFragment + nodes { + slug + id + } + } + } + ... on Item { + __typename + announcements { + ...AnnouncementsFragment + nodes { + slug + id + } + } + } + ... on Node { + __isNode: __typename + id + } + } + detailDefinition: definition { + showAnnouncements + id + } + slots { + header { + ...sharedInlineSlotFragment + } + subheader { + ...sharedInlineSlotFragment + } + summary { + ...sharedBlockSlotFragment + } + } +} + +fragment getThumbWithFallbackFragment on Entity { + __isEntity: __typename + ... on Collection { + thumbnail { + image: medium { + webp { + url + } + } + ...CoverImageFragment + ...CoverCardListFragment + } + breadcrumbs { + crumb { + __typename + ... on Collection { + thumbnail { + image: medium { + webp { + url + } + } + ...CoverImageFragment + ...CoverCardListFragment + } + } + ... on Node { + __isNode: __typename + id + } + } + id + } + } + ... on Item { + thumbnail { + image: medium { + webp { + url + } + } + ...CoverImageFragment + ...CoverCardListFragment + } + breadcrumbs { + crumb { + __typename + ... on Collection { + thumbnail { + image: medium { + webp { + url + } + } + ...CoverImageFragment + ...CoverCardListFragment + } + } + ... on Item { + thumbnail { + image: medium { + webp { + url + } + } + ...CoverImageFragment + ...CoverCardListFragment + } + } + ... on Node { + __isNode: __typename + id + } + } + id + } + } +} + +fragment routesOrderingTemplateFragment on OrderingEntry { + entrySlug + entry { + __typename + ... on Collection { + __typename + } + ... on Item { + __typename + } + ... on Community { + __typename + } + ... on EntityLink { + __typename + target { + __typename + ... on Collection { + __typename + } + ... on Item { + __typename + } + ... on Community { + __typename + } + ... on Node { + __isNode: __typename + id + } + } + } + id + } +} + +fragment sharedBlockSlotFragment on TemplateSlotBlockInstance { + empty + content + kind + valid +} + +fragment sharedInlineSlotFragment on TemplateSlotInlineInstance { + empty + content + kind + valid + hidesTemplate +} + +fragment sharedListItemTemplateFragment on ListItemTemplateInstance { + definition { + seeAllOrderingIdentifier + id + } + entity { + __typename + ... on Collection { + __typename + id + slug + title + hierarchicalDepth + ...getThumbWithFallbackFragment + attributions { + id + } + ...ContributorsListFragment + heroImage { + large { + webp { + alt + url + width + height + } + } + medium { + webp { + url + width + } + } + thumb { + webp { + url + width + } + } + } + } + ... on Item { + __typename + id + slug + title + hierarchicalDepth + attributions { + id + } + ...getThumbWithFallbackFragment + ...ContributorsListFragment + heroImage { + large { + webp { + alt + url + width + height + } + } + medium { + webp { + url + width + } + } + thumb { + webp { + url + width + } + } + } + } + ... on Node { + __isNode: __typename + id + } + } + slots { + contextFull { + ...sharedInlineSlotFragment + } + contextAbbr { + ...sharedInlineSlotFragment + } + contextC { + ...sharedInlineSlotFragment + } + description { + ...sharedBlockSlotFragment + } + header { + ...sharedInlineSlotFragment + } + metaA { + ...sharedInlineSlotFragment + } + metaB { + ...sharedInlineSlotFragment + } + subheader { + ...sharedInlineSlotFragment + } + nestedHeader { + ...sharedInlineSlotFragment + } + nestedSubheader { + ...sharedInlineSlotFragment + } + nestedContext { + ...sharedInlineSlotFragment + } + nestedMetadata { + ...sharedInlineSlotFragment + } + } +} + +fragment sharedListItemsTemplateFragment on TemplateEntityList { + empty + count + depths: listItemLayouts { + template { + entity { + __typename + ... on Collection { + hierarchicalDepth + } + ... on Item { + hierarchicalDepth + } + ... on Node { + __isNode: __typename + id + } + } + id + } + id + } + listItemLayouts { + template { + entity { + __typename + ... on Collection { + hierarchicalDepth + } + ... on Item { + hierarchicalDepth + } + ... on Node { + __isNode: __typename + id + } + } + ...sharedListItemTemplateFragment + entityList { + empty + count + listItemLayouts { + template { + ...sharedListItemTemplateFragment + id + } + id + } + } + id + } + id + } +} + +fragment sharedListTemplateFragment on AnyMainTemplateInstance { + __isAnyMainTemplateInstance: __typename + ... on LinkListTemplateInstance { + entity { + __typename + ... on Community { + __typename + slug + } + ... on Collection { + __typename + slug + ...getThumbWithFallbackFragment + } + ... on Item { + __typename + slug + ...getThumbWithFallbackFragment + } + ... on Node { + __isNode: __typename + id + } + } + linksDefinition: definition { + background + seeAllButtonLabel + showSeeAllButton + selectionMode + selectionLimit + showEntityContext + title + variant + showHeroImage + width + showNestedEntities + seeAllOrderingIdentifier + showContributors + id + } + slots { + blockHeader { + ...sharedInlineSlotFragment + } + header { + ...sharedInlineSlotFragment + } + headerAside { + ...sharedInlineSlotFragment + } + metadata { + ...sharedInlineSlotFragment + } + subtitle { + ...sharedInlineSlotFragment + } + } + entityList { + count + empty + ...sharedListItemsTemplateFragment + } + } + ... on DescendantListTemplateInstance { + seeAllOrdering { + count + name + id + } + entity { + __typename + ... on Community { + __typename + slug + } + ... on Collection { + __typename + id + title + slug + ...getThumbWithFallbackFragment + } + ... on Item { + __typename + id + title + slug + ...getThumbWithFallbackFragment + } + ... on Node { + __isNode: __typename + id + } + } + descendantsDefinition: definition { + background + seeAllButtonLabel + showSeeAllButton + selectionMode + selectionPropertyPath + orderingIdentifier + dynamicOrderingDefinition { + filter { + schemas { + namespace + identifier + } + } + } + selectionLimit + entityContext + title + variant + showHeroImage + width + showNestedEntities + seeAllOrderingIdentifier + showContributors + id + } + slots { + blockHeader { + ...sharedInlineSlotFragment + } + header { + ...sharedInlineSlotFragment + } + headerAside { + ...sharedInlineSlotFragment + } + metadata { + ...sharedInlineSlotFragment + } + subtitle { + ...sharedInlineSlotFragment + } + } + entityList { + ...sharedListItemsTemplateFragment + } + } +} diff --git a/spec/data/queries/pageTemplatesItemMetricsQuery.graphql b/spec/data/queries/pageTemplatesItemMetricsQuery.graphql new file mode 100644 index 00000000..c5ef8454 --- /dev/null +++ b/spec/data/queries/pageTemplatesItemMetricsQuery.graphql @@ -0,0 +1,49 @@ +query pageTemplatesItemMetricsQuery( + $slug: Slug! + $dateRange: DateFilterInput! + $precision: AnalyticsPrecision! + $usOnly: Boolean! +) { + item(slug: $slug) { + ...ArticleAnalyticsBlockFragment_3yzii9 + id + } +} + +fragment ArticleAnalyticsBlockFragment_3yzii9 on Item { + downloadsByDate: assetDownloads(dateFilter: $dateRange, precision: $precision) { + total + unfilteredTotal + minDate + results { + count + date + } + } + assetDownloadsByRegion(dateFilter: $dateRange, usOnly: $usOnly) { + total + results { + countryCode + regionCode + count + } + } + viewsByDate: entityViews(dateFilter: $dateRange, precision: $precision) { + total + unfilteredTotal + minDate + results { + count + date + } + } + entityViewsByRegion(dateFilter: $dateRange, usOnly: $usOnly) { + total + results { + countryCode + regionCode + count + } + } + id +} diff --git a/spec/requests/graphql/frontend/page_template_query_spec.rb b/spec/requests/graphql/frontend/page_template_query_spec.rb new file mode 100644 index 00000000..564e6ed9 --- /dev/null +++ b/spec/requests/graphql/frontend/page_template_query_spec.rb @@ -0,0 +1,48 @@ +# frozen_string_literal: true + +RSpec.describe "pageTemplateQuery", type: :request do + let_it_be(:community, refind: true) { FactoryBot.create :community } + let_it_be(:journal, refind: true) { FactoryBot.create(:collection, community:, schema: "nglp:journal") } + let_it_be(:journal_volume, refind: true) { FactoryBot.create(:collection, community:, parent: journal, schema: "nglp:journal_volume") } + let_it_be(:journal_issue, refind: true) { FactoryBot.create(:collection, community:, parent: journal_volume, schema: "nglp:journal_issue") } + let_it_be(:article_1, refind: true) { FactoryBot.create(:item, collection: journal_issue, schema: "nglp:journal_article", published: VariablePrecisionDate.parse(Date.current - 3)) } + let_it_be(:article_2, refind: true) { FactoryBot.create(:item, collection: journal_issue, schema: "nglp:journal_article", published: VariablePrecisionDate.parse(Date.current - 1)) } + + let_it_be(:rendered) do + [article_1, article_2, journal_issue, journal_volume, journal, community].each do |entity| + entity.render_layouts! + end + end + + let(:query) do + named_query("pageTemplateQuery") + end + + let(:slug) { community.system_slug } + + let(:graphql_variables) do + { + slug:, + } + end + + let(:expected_shape) do + gql.query do |q| + q.prop :community do |comm| + comm[:id] = community.to_encoded_id + + comm.prop :layouts do |layouts| + layouts.prop :main do |main| + main[:id] = be_present + end + end + end + end + end + + it "renders details for the community's main layout" do + expect_request! do |req| + req.data! expected_shape + end + end +end diff --git a/spec/support/helpers/graphql_helpers.rb b/spec/support/helpers/graphql_helpers.rb index 24fa324f..0785d0f8 100644 --- a/spec/support/helpers/graphql_helpers.rb +++ b/spec/support/helpers/graphql_helpers.rb @@ -7,6 +7,8 @@ module TestHelpers module GraphQLRequest module ExampleHelpers + QUERIES_ROOT = Rails.root.join("spec", "data", "queries") + def expect_request!(**options, &) tester = TestingAPI::TestContainer["requests.build"].(&) @@ -65,6 +67,13 @@ def make_graphql_request!(query, token: nil, variables: {}, camelize_variables: expect(Array(graphql_response(:errors))).to eq([]) if no_top_level_errors end + # @param [String] name + def named_query(name) + basename = "#{name}.graphql" + + QUERIES_ROOT.join(basename).read + end + def expect_graphql_data(shape) expect(graphql_response(decamelize: true)).to include_json data: shape end From 28c95795a851bac67bd3c361d3651f2e44988044 Mon Sep 17 00:00:00 2001 From: Alexa Grey Date: Fri, 9 Jan 2026 12:06:42 -0800 Subject: [PATCH 4/5] [B] Ensure that templates get processed during rendering This resolves the issue of entity list caches not getting rebuilt as expected and adds test coverage to make sure it works --- .rubocop.yml | 1 + .../types/template_entity_list_type.rb | 8 +- app/models/concerns/template_instance.rb | 2 + app/models/templates/cached_entity_list.rb | 17 +++- .../templates/entity_lists/refresh_cached.rb | 10 +++ app/services/layouts/renderer.rb | 1 + .../entity_lists/cached_refresher.rb | 33 ++++++++ .../templates/instances/entity_list_cacher.rb | 19 ++--- app/services/templates/renderer.rb | 9 ++ app/services/templates/types.rb | 2 + ...add_refreshed_at_to_cached_entity_lists.rb | 11 +++ db/structure.sql | 11 ++- lib/frozen_record/static_cached_columns.yml | 13 +++ spec/factories/items.rb | 18 ++++ .../integrations/rendering/processing_spec.rb | 82 +++++++++++++++++++ 15 files changed, 221 insertions(+), 16 deletions(-) create mode 100644 app/operations/templates/entity_lists/refresh_cached.rb create mode 100644 app/services/templates/entity_lists/cached_refresher.rb create mode 100644 db/migrate/20260109184446_add_refreshed_at_to_cached_entity_lists.rb create mode 100644 spec/integrations/rendering/processing_spec.rb diff --git a/.rubocop.yml b/.rubocop.yml index f008986c..bd18797e 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -618,6 +618,7 @@ RSpec/ContextWording: RSpec/DescribeClass: Exclude: + - spec/integrations/**/*.rb - spec/requests/**/*.rb RSpec/DuplicatedMetadata: diff --git a/app/graphql/types/template_entity_list_type.rb b/app/graphql/types/template_entity_list_type.rb index 1d296ff9..630f4fac 100644 --- a/app/graphql/types/template_entity_list_type.rb +++ b/app/graphql/types/template_entity_list_type.rb @@ -31,7 +31,7 @@ class TemplateEntityListType < Types::BaseObject TEXT end - field :entities, ["::Types::EntityType", { null: false }], null: false, method: :valid_entities do + field :entities, ["::Types::EntityType", { null: false }], null: false do description <<~TEXT The actual entity records within this list. @@ -75,8 +75,12 @@ class TemplateEntityListType < Types::BaseObject TEXT end - load_association! :entities + load_association! :cached_entity_list_items load_association! :list_item_layout_instances, as: :list_item_layouts + + def entities + cached_entity_list_items.then { _1.map(&:entity) } + end end end diff --git a/app/models/concerns/template_instance.rb b/app/models/concerns/template_instance.rb index 1265a740..9b22a4a9 100644 --- a/app/models/concerns/template_instance.rb +++ b/app/models/concerns/template_instance.rb @@ -9,6 +9,8 @@ module TemplateInstance include Renderable included do + self.filter_attributes = [:config, :slots] + attribute :config, Templates::Instances::Config.to_type belongs_to :entity, polymorphic: true diff --git a/app/models/templates/cached_entity_list.rb b/app/models/templates/cached_entity_list.rb index 028b02e5..b0dbd47c 100644 --- a/app/models/templates/cached_entity_list.rb +++ b/app/models/templates/cached_entity_list.rb @@ -11,14 +11,27 @@ class CachedEntityList < ApplicationRecord belongs_to :template_instance, polymorphic: true belongs_to :entity, polymorphic: true - has_many :cached_entity_list_items, -> { in_default_order }, class_name: "Templates::CachedEntityListItem", inverse_of: :cached_entity_list, dependent: :delete_all + has_many :cached_entity_list_items, -> { in_default_order.includes(:entity) }, class_name: "Templates::CachedEntityListItem", + inverse_of: :cached_entity_list, dependent: :delete_all - has_many :entities, through: :cached_entity_list_items, source: :entity has_many :list_item_layout_instances, through: :cached_entity_list_items, source: :list_item_layout_instance + # @note Cannot eager-load because of polymorphic associations. + def entities + # :nocov: + cached_entity_list_items.map(&:entity) + # :nocov: + end + # @return [Integer] def prune_items! cached_entity_list_items.beyond(count).delete_all end + + # @see Templates::EntityLists::RefreshCached + # @see Templates::EntityLists::CachedRefresher + monadic_operation! def refresh + call_operation("templates.entity_lists.refresh_cached", self) + end end end diff --git a/app/operations/templates/entity_lists/refresh_cached.rb b/app/operations/templates/entity_lists/refresh_cached.rb new file mode 100644 index 00000000..a956fd58 --- /dev/null +++ b/app/operations/templates/entity_lists/refresh_cached.rb @@ -0,0 +1,10 @@ +# frozen_string_literal: true + +module Templates + module EntityLists + # @see Templates::EntityLists::CachedRefresher + class RefreshCached < Support::SimpleServiceOperation + service_klass Templates::EntityLists::CachedRefresher + end + end +end diff --git a/app/services/layouts/renderer.rb b/app/services/layouts/renderer.rb index b8864bd2..0e601398 100644 --- a/app/services/layouts/renderer.rb +++ b/app/services/layouts/renderer.rb @@ -74,6 +74,7 @@ def call super end + # @see Layouts::Instances::Processor wrapped_hook! def process yield layout_instance.process diff --git a/app/services/templates/entity_lists/cached_refresher.rb b/app/services/templates/entity_lists/cached_refresher.rb new file mode 100644 index 00000000..3e727d09 --- /dev/null +++ b/app/services/templates/entity_lists/cached_refresher.rb @@ -0,0 +1,33 @@ +# frozen_string_literal: true + +module Templates + module EntityLists + # @see Templates::EntityLists::RefreshCached + class CachedRefresher < Support::HookBased::Actor + include Dry::Initializer[undefined: false].define -> do + param :cached_entity_list, Templates::Types::CachedEntityList + end + + delegate :template_instance, to: :cached_entity_list + + standard_execution! + + # @return [Dry::Monads::Result] + def call + run_callbacks :execute do + yield regenerate! + end + + Success() + end + + wrapped_hook! def regenerate + yield template_instance.cache_entity_list + + cached_entity_list.reload + + super + end + end + end +end diff --git a/app/services/templates/instances/entity_list_cacher.rb b/app/services/templates/instances/entity_list_cacher.rb index 4924ae95..5b51073a 100644 --- a/app/services/templates/instances/entity_list_cacher.rb +++ b/app/services/templates/instances/entity_list_cacher.rb @@ -17,9 +17,6 @@ class EntityListCacher < Support::HookBased::Actor delegate :entity_id, :entity_type, :list_item_template?, to: :template_instance - # @return [String] - attr_reader :advisory_lock_key - # @return [Templates::CachedEntityList] attr_reader :cached_entity_list @@ -46,8 +43,6 @@ def call end wrapped_hook! def prepare - @advisory_lock_key = "templates/instances/entity_list_caching/#{template_instance.id}" - @entity_list = template_instance.entity_list @hidden_by_entity_list = !list_item_template? && entity_list.empty? @@ -67,12 +62,6 @@ def call super end - wrapped_hook! def update_template - template_instance.update_columns(hidden_by_entity_list:) - - super - end - wrapped_hook! def build_list tuple = { template_instance_type:, @@ -120,6 +109,14 @@ def call wrapped_hook! def prune_items cached_entity_list.prune_items! + cached_entity_list.touch(:refreshed_at, :updated_at) + + super + end + + wrapped_hook! def update_template + template_instance.update_columns(hidden_by_entity_list:) + super end end diff --git a/app/services/templates/renderer.rb b/app/services/templates/renderer.rb index 3e55edf4..97acff15 100644 --- a/app/services/templates/renderer.rb +++ b/app/services/templates/renderer.rb @@ -28,6 +28,8 @@ def call yield persist_instance! yield render! + + yield process! end Success template_instance @@ -61,6 +63,13 @@ def call around_render :track_render! + # @see Templates::Instances::Processor + wrapped_hook! def process + yield template_instance.process + + super + end + private # @return [void] diff --git a/app/services/templates/types.rb b/app/services/templates/types.rb index 0acdd7c4..c9f0f640 100644 --- a/app/services/templates/types.rb +++ b/app/services/templates/types.rb @@ -10,6 +10,8 @@ module Types Assigns = Hash.map(Coercible::String, Any) + CachedEntityList = ModelInstance("Templates::CachedEntityList") + Contribution = Instance(::Contribution) Contributions = Coercible::Array.of(Contribution) diff --git a/db/migrate/20260109184446_add_refreshed_at_to_cached_entity_lists.rb b/db/migrate/20260109184446_add_refreshed_at_to_cached_entity_lists.rb new file mode 100644 index 00000000..0b05edbe --- /dev/null +++ b/db/migrate/20260109184446_add_refreshed_at_to_cached_entity_lists.rb @@ -0,0 +1,11 @@ +# frozen_string_literal: true + +class AddRefreshedAtToCachedEntityLists < ActiveRecord::Migration[7.2] + def change + change_table :templates_cached_entity_lists do |t| + t.timestamp :refreshed_at, null: true + + t.index :refreshed_at + end + end +end diff --git a/db/structure.sql b/db/structure.sql index ba0de7b6..ec3bd2e2 100644 --- a/db/structure.sql +++ b/db/structure.sql @@ -7030,7 +7030,8 @@ CREATE TABLE public.templates_cached_entity_lists ( maximum_depth integer, minimum_depth integer, created_at timestamp(6) without time zone DEFAULT CURRENT_TIMESTAMP NOT NULL, - updated_at timestamp(6) without time zone DEFAULT CURRENT_TIMESTAMP NOT NULL + updated_at timestamp(6) without time zone DEFAULT CURRENT_TIMESTAMP NOT NULL, + refreshed_at timestamp without time zone ); @@ -12888,6 +12889,13 @@ CREATE INDEX index_templates_cached_entity_list_items_on_schema_version_id ON pu CREATE INDEX index_templates_cached_entity_lists_on_entity ON public.templates_cached_entity_lists USING btree (entity_type, entity_id); +-- +-- Name: index_templates_cached_entity_lists_on_refreshed_at; Type: INDEX; Schema: public; Owner: - +-- + +CREATE INDEX index_templates_cached_entity_lists_on_refreshed_at ON public.templates_cached_entity_lists USING btree (refreshed_at); + + -- -- Name: index_templates_contributor_list_definitions_on_position; Type: INDEX; Schema: public; Owner: - -- @@ -15262,6 +15270,7 @@ ALTER TABLE ONLY public.templates_ordering_instances SET search_path TO "$user", public; INSERT INTO "schema_migrations" (version) VALUES +('20260109184446'), ('20251119062322'), ('20251119042325'), ('20251119040707'), diff --git a/lib/frozen_record/static_cached_columns.yml b/lib/frozen_record/static_cached_columns.yml index 4b78361c..2ba3d99f 100644 --- a/lib/frozen_record/static_cached_columns.yml +++ b/lib/frozen_record/static_cached_columns.yml @@ -19655,6 +19655,19 @@ default_function: CURRENT_TIMESTAMP has_default: true virtual: false +- id: Templates::CachedEntityList#refreshed_at + model_name: Templates::CachedEntityList + table_name: templates_cached_entity_lists + name: refreshed_at + type: datetime + 'null': true + sql_type_metadata: + sql_type: timestamp without time zone + type: datetime + default: + default_function: + has_default: false + virtual: false - id: Templates::CachedEntityListItem#id model_name: Templates::CachedEntityListItem table_name: templates_cached_entity_list_items diff --git a/spec/factories/items.rb b/spec/factories/items.rb index d6001f89..b93a72fc 100644 --- a/spec/factories/items.rb +++ b/spec/factories/items.rb @@ -42,5 +42,23 @@ Rails.root.join("spec", "data", "lorempixel.jpg").open end end + + trait :journal_article do + transient do + issue_position { nil } + + schema_properties do + { + issue_position:, + } + end + end + + schema { "nglp:journal_article" } + + after(:create) do |item, evaluator| + item.patch_properties!(evaluator.schema_properties) + end + end end end diff --git a/spec/integrations/rendering/processing_spec.rb b/spec/integrations/rendering/processing_spec.rb new file mode 100644 index 00000000..439ae28f --- /dev/null +++ b/spec/integrations/rendering/processing_spec.rb @@ -0,0 +1,82 @@ +# frozen_string_literal: true + +RSpec.describe "Rendering Processing Integration" do + let_it_be(:community, refind: true) { FactoryBot.create :community } + let_it_be(:journal, refind: true) { FactoryBot.create(:collection, community:, schema: "nglp:journal") } + let_it_be(:journal_volume, refind: true) { FactoryBot.create(:collection, community:, parent: journal, schema: "nglp:journal_volume") } + let_it_be(:journal_issue, refind: true) { FactoryBot.create(:collection, community:, parent: journal_volume, schema: "nglp:journal_issue") } + + let_it_be(:article_1, refind: true) do + FactoryBot.create(:item, :journal_article, collection: journal_issue, issue_position: 1, published: VariablePrecisionDate.parse(Date.current - 3)) + end + + let_it_be(:article_2, refind: true) do + FactoryBot.create(:item, :journal_article, collection: journal_issue, issue_position: 2, published: VariablePrecisionDate.parse(Date.current - 1)) + end + + def check_article!(article) + expect do + article.render_layouts! + end.to execute_safely + .and change(Templates::CachedEntityList.where(template_instance_type: "Templates::LinkListInstance"), :count).by(1) + .and change(Templates::CachedEntityList.where(template_instance_type: "Templates::ListItemInstance"), :count).by(1) + .and keep_the_same(Templates::CachedEntityListItem, :count) + end + + def ordering_instance_for(record) + record.main_layout_instance.ordering_template_instances.first! + end + + def ordering_pair_for(ordering_template) + ordering_template.ordering_pair + end + + def prev_entity_for(ordering_template) + ordering_pair_for(ordering_template).prev_sibling.try(:entity) + end + + def next_entity_for(ordering_template) + ordering_pair_for(ordering_template).next_sibling.try(:entity) + end + + it "can navigate between articles" do + check_article!(article_1) + check_article!(article_2) + + ordering_1 = ordering_instance_for(article_1) + ordering_2 = ordering_instance_for(article_2) + + expect(prev_entity_for(ordering_1)).to be_nil + expect(next_entity_for(ordering_1)).to eq article_2 + + expect(prev_entity_for(ordering_2)).to eq article_1 + expect(next_entity_for(ordering_2)).to be_nil + end + + it "processes each template correctly" do + check_article!(article_1) + check_article!(article_2) + + expect do + journal_issue.render_layouts! + end.to execute_safely + .and change(Templates::CachedEntityList, :count).by(3) + .and change(Templates::CachedEntityListItem.where(entity: article_2), :count).by(2) + .and change(Templates::CachedEntityListItem.where(entity: article_1), :count).by(2) + + expect do + journal_volume.render_layouts! + end.to execute_safely + .and change(Templates::CachedEntityList, :count).by(3) + + expect do + journal.render_layouts! + end.to execute_safely + .and change(Templates::CachedEntityList, :count).by(6) + + expect do + community.render_layouts! + end.to execute_safely + .and change(Templates::CachedEntityList, :count).by(7) + end +end From 03765cbaa84bf20b19acea1774294c9f2cb13639 Mon Sep 17 00:00:00 2001 From: Alexa Grey Date: Fri, 9 Jan 2026 12:55:26 -0800 Subject: [PATCH 5/5] [B] Handle harvesting coercion error during data extraction This error ocurred with malformed data (specifically an empty string where an integer was expected). We can just return nil in this case, since Liquid & the extraction templates will handle that correctly. --- .../metadata/drops/data_extractor.rb | 4 +- .../metadata/jats/issue_drop_spec.rb | 45 +++++++++++++++++++ 2 files changed, 48 insertions(+), 1 deletion(-) create mode 100644 spec/services/harvesting/metadata/jats/issue_drop_spec.rb diff --git a/app/services/harvesting/metadata/drops/data_extractor.rb b/app/services/harvesting/metadata/drops/data_extractor.rb index 40ec5f2e..6aa9edc2 100644 --- a/app/services/harvesting/metadata/drops/data_extractor.rb +++ b/app/services/harvesting/metadata/drops/data_extractor.rb @@ -32,7 +32,9 @@ def ivar def extract(data) value = data.public_send(attr) - cast = cast_type[value] + result = cast_type.try(value).to_monad + + cast = result.value_or(default) cast.nil? ? default : cast end diff --git a/spec/services/harvesting/metadata/jats/issue_drop_spec.rb b/spec/services/harvesting/metadata/jats/issue_drop_spec.rb new file mode 100644 index 00000000..6d10ed9f --- /dev/null +++ b/spec/services/harvesting/metadata/jats/issue_drop_spec.rb @@ -0,0 +1,45 @@ +# frozen_string_literal: true + +# This test specifically addresses coercion issues with {Harvesting::Metadata::Drops::DataExtractor} +# and {Harvesting::Metadata::Drops::MapsDataAttrs} when handling values that cannot be coerced properly. +RSpec.describe Harvesting::Metadata::JATS::IssueDrop do + let(:id) { "issue-123" } + let(:seq) { "42" } + let(:content) { "Issue content" } + + let(:data) do + instance_double(Niso::Jats::Issue, id:, content:, seq:) + end + + let(:article) { instance_double(Niso::Jats::Article) } + + let(:metadata_context) do + instance_double(Harvesting::Metadata::JATS::Context, article:) + end + + let(:drop) do + described_class.new(data, metadata_context:) + end + + context "with a valid seq" do + it "coerces the seq" do + expect(drop.seq).to eq 42 + end + end + + context "when the seq value is an empty string" do + let(:seq) { "" } + + it "returns nil for seq" do + expect(drop.seq).to be_nil + end + end + + context "when the seq value is invalid" do + let(:seq) { "not a number" } + + it "returns nil for seq" do + expect(drop.seq).to be_nil + end + end +end