diff --git a/src/containers/SubjectPage/components/SubjectTopic.tsx b/src/containers/SubjectPage/components/SubjectTopic.tsx index 423fbfb710..371e00625a 100644 --- a/src/containers/SubjectPage/components/SubjectTopic.tsx +++ b/src/containers/SubjectPage/components/SubjectTopic.tsx @@ -27,6 +27,7 @@ import { GQLTopic_SubjectFragment, GQLTopic_TopicFragment, } from "../../../graphqlTypes"; +import { copyrightInfoFragment } from "../../../queries"; import { toTopic, useUrnIds } from "../../../routeHelpers"; import { getTopicPath } from "../../../util/getTopicPath"; import { htmlTitle } from "../../../util/titleHelper"; @@ -217,6 +218,9 @@ export const topicFragments = { metaImage { url alt + copyright { + ...CopyrightInfo + } } transformedContent(transformArgs: $transformArgs) { visualElementEmbed { @@ -229,6 +233,7 @@ export const topicFragments = { } ${MultidisciplinaryArticleList.fragments.topic} ${Resources.fragments.topic} + ${copyrightInfoFragment} `, resourceType: gql` fragment Topic_ResourceTypeDefinition on ResourceTypeDefinition { diff --git a/src/containers/SubjectPage/components/TopicVisualElementContent.tsx b/src/containers/SubjectPage/components/TopicVisualElementContent.tsx index 1cf3e3767c..29d240379f 100644 --- a/src/containers/SubjectPage/components/TopicVisualElementContent.tsx +++ b/src/containers/SubjectPage/components/TopicVisualElementContent.tsx @@ -7,15 +7,24 @@ */ import { Image } from "@ndla/primitives"; +import { styled } from "@ndla/styled-system/jsx"; import { EmbedMetaData } from "@ndla/types-embed"; -import { ImageEmbed } from "@ndla/ui"; +import { EmbedByline, ImageEmbed } from "@ndla/ui"; import { GQLArticle } from "../../../graphqlTypes"; interface Props { embed: EmbedMetaData; - metaImage: GQLArticle["metaImage"]; + metaImage?: GQLArticle["metaImage"]; } +const StyledFigure = styled("figure", { + base: { + display: "flex", + flexDirection: "column", + alignItems: "center", + }, +}); + const TopicVisualElementContent = ({ embed, metaImage }: Props) => { if (embed.resource === "image") { return ; @@ -23,9 +32,16 @@ const TopicVisualElementContent = ({ embed, metaImage }: Props) => { return null; } else { return ( -
+ {metaImage?.alt -
+ {metaImage.copyright ? ( + + ) : null} + ); } }; diff --git a/src/graphqlTypes.ts b/src/graphqlTypes.ts index 91c1db337a..8b11ce81f5 100644 --- a/src/graphqlTypes.ts +++ b/src/graphqlTypes.ts @@ -225,7 +225,7 @@ export type GQLArticle = { introduction?: Maybe; language: Scalars["String"]["output"]; metaDescription: Scalars["String"]["output"]; - metaImage?: Maybe; + metaImage: GQLMetaImageWithCopyright; oembed?: Maybe; oldNdlaUrl?: Maybe; published: Scalars["String"]["output"]; @@ -907,6 +907,11 @@ export type GQLLearningpathStep = { type: Scalars["String"]["output"]; }; +export type GQLLearningpathStepResourceArgs = { + parentId?: InputMaybe; + rootId?: InputMaybe; +}; + export type GQLLearningpathStepEmbedUrl = { __typename?: "LearningpathStepEmbedUrl"; embedType: Scalars["String"]["output"]; @@ -958,6 +963,14 @@ export type GQLMeta = { export type GQLMetaImage = { __typename?: "MetaImage"; alt: Scalars["String"]["output"]; + copyright?: Maybe; + url: Scalars["String"]["output"]; +}; + +export type GQLMetaImageWithCopyright = { + __typename?: "MetaImageWithCopyright"; + alt: Scalars["String"]["output"]; + copyright: GQLCopyright; url: Scalars["String"]["output"]; }; @@ -969,6 +982,7 @@ export type GQLMovie = { path: Scalars["String"]["output"]; resourceTypes: Array; title: Scalars["String"]["output"]; + url: Scalars["String"]["output"]; }; export type GQLMovieMeta = { @@ -978,12 +992,6 @@ export type GQLMovieMeta = { title: Scalars["String"]["output"]; }; -export type GQLMoviePath = { - __typename?: "MoviePath"; - path?: Maybe; - paths?: Maybe>; -}; - export type GQLMovieResourceTypes = { __typename?: "MovieResourceTypes"; resourceTypes?: Maybe>; @@ -1207,6 +1215,7 @@ export type GQLMutationTransformArticleContentArgs = { absoluteUrl?: InputMaybe; content: Scalars["String"]["input"]; draftConcept?: InputMaybe; + prettyUrl?: InputMaybe; previewH5p?: InputMaybe; subject?: InputMaybe; visualElement?: InputMaybe; @@ -1326,6 +1335,44 @@ export type GQLNewFolderResource = { tags?: Maybe>; }; +export type GQLNode = GQLTaxBase & + GQLTaxonomyEntity & + GQLWithArticle & { + __typename?: "Node"; + alternateNodes?: Maybe>; + article?: Maybe; + availability?: Maybe; + breadcrumbs: Array; + children?: Maybe>; + connectionId?: Maybe; + contentUri?: Maybe; + context?: Maybe; + contextId?: Maybe; + contexts: Array; + grepCodes?: Maybe>; + id: Scalars["String"]["output"]; + language?: Maybe; + learningpath?: Maybe; + meta?: Maybe; + metadata: GQLTaxonomyMetadata; + name: Scalars["String"]["output"]; + nodeType: Scalars["String"]["output"]; + parentId?: Maybe; + path?: Maybe; + paths: Array; + rank?: Maybe; + relevanceId?: Maybe; + resourceTypes?: Maybe>; + subjectpage?: Maybe; + supportedLanguages: Array; + url?: Maybe; + }; + +export type GQLNodeChildrenArgs = { + nodeType?: InputMaybe; + recursive?: InputMaybe; +}; + export type GQLOwner = { __typename?: "Owner"; name: Scalars["String"]["output"]; @@ -1490,6 +1537,9 @@ export type GQLQuery = { learningpath?: Maybe; listArenaUserV2: GQLPaginatedArenaUsers; listingPage?: Maybe; + node?: Maybe; + nodeByArticleId?: Maybe; + nodes?: Maybe>; personalData?: Maybe; podcastSearch?: Maybe; podcastSeries?: Maybe; @@ -1686,6 +1736,27 @@ export type GQLQueryListingPageArgs = { subjects?: InputMaybe; }; +export type GQLQueryNodeArgs = { + contextId?: InputMaybe; + id?: InputMaybe; + parentId?: InputMaybe; + rootId?: InputMaybe; +}; + +export type GQLQueryNodeByArticleIdArgs = { + articleId?: InputMaybe; + nodeId?: InputMaybe; +}; + +export type GQLQueryNodesArgs = { + contentUri?: InputMaybe; + filterVisible?: InputMaybe; + ids?: InputMaybe>; + metadataFilterKey?: InputMaybe; + metadataFilterValue?: InputMaybe; + nodeType?: InputMaybe; +}; + export type GQLQueryPodcastSearchArgs = { fallback?: InputMaybe; page: Scalars["Int"]["input"]; @@ -1805,13 +1876,16 @@ export type GQLRelatedContent = { url: Scalars["String"]["output"]; }; -export type GQLResource = GQLTaxonomyEntity & +export type GQLResource = GQLTaxBase & + GQLTaxonomyEntity & GQLWithArticle & { __typename?: "Resource"; article?: Maybe; availability?: Maybe; breadcrumbs: Array; contentUri?: Maybe; + context?: Maybe; + contextId?: Maybe; contexts: Array; id: Scalars["String"]["output"]; language?: Maybe; @@ -1819,6 +1893,7 @@ export type GQLResource = GQLTaxonomyEntity & meta?: Maybe; metadata: GQLTaxonomyMetadata; name: Scalars["String"]["output"]; + nodeType: Scalars["String"]["output"]; parents?: Maybe>; path?: Maybe; paths: Array; @@ -1856,11 +1931,6 @@ export type GQLResourceType = { __typename?: "ResourceType"; id: Scalars["String"]["output"]; name: Scalars["String"]["output"]; - resources?: Maybe>; -}; - -export type GQLResourceTypeResourcesArgs = { - topicId: Scalars["String"]["input"]; }; export type GQLResourceTypeDefinition = { @@ -1954,26 +2024,30 @@ export type GQLSortResult = { sortedIds: Array; }; -export type GQLSubject = GQLTaxonomyEntity & { - __typename?: "Subject"; - allTopics?: Maybe>; - breadcrumbs: Array; - contentUri?: Maybe; - contexts: Array; - grepCodes?: Maybe>; - id: Scalars["String"]["output"]; - language?: Maybe; - metadata: GQLTaxonomyMetadata; - name: Scalars["String"]["output"]; - path?: Maybe; - paths: Array; - relevanceId?: Maybe; - resourceTypes?: Maybe>; - subjectpage?: Maybe; - supportedLanguages: Array; - topics?: Maybe>; - url?: Maybe; -}; +export type GQLSubject = GQLTaxBase & + GQLTaxonomyEntity & { + __typename?: "Subject"; + allTopics?: Maybe>; + breadcrumbs: Array; + contentUri?: Maybe; + context?: Maybe; + contextId?: Maybe; + contexts: Array; + grepCodes?: Maybe>; + id: Scalars["String"]["output"]; + language?: Maybe; + metadata: GQLTaxonomyMetadata; + name: Scalars["String"]["output"]; + nodeType: Scalars["String"]["output"]; + path?: Maybe; + paths: Array; + relevanceId?: Maybe; + resourceTypes?: Maybe>; + subjectpage?: Maybe; + supportedLanguages: Array; + topics?: Maybe>; + url?: Maybe; + }; export type GQLSubjectTopicsArgs = { all?: InputMaybe; @@ -1983,6 +2057,7 @@ export type GQLSubjectLink = { __typename?: "SubjectLink"; name?: Maybe; path?: Maybe; + url?: Maybe; }; export type GQLSubjectPage = { @@ -2038,10 +2113,31 @@ export type GQLTags = { tags: Array; }; +export type GQLTaxBase = { + id: Scalars["String"]["output"]; + name: Scalars["String"]["output"]; + path?: Maybe; + url?: Maybe; +}; + export type GQLTaxonomyContext = { __typename?: "TaxonomyContext"; breadcrumbs: Array; + contextId: Scalars["String"]["output"]; + name: Scalars["String"]["output"]; parentIds: Array; + parents?: Maybe>; + path: Scalars["String"]["output"]; + relevance: Scalars["String"]["output"]; + rootId: Scalars["String"]["output"]; + url: Scalars["String"]["output"]; +}; + +export type GQLTaxonomyCrumb = GQLTaxBase & { + __typename?: "TaxonomyCrumb"; + contextId: Scalars["String"]["output"]; + id: Scalars["String"]["output"]; + name: Scalars["String"]["output"]; path: Scalars["String"]["output"]; url: Scalars["String"]["output"]; }; @@ -2049,11 +2145,14 @@ export type GQLTaxonomyContext = { export type GQLTaxonomyEntity = { breadcrumbs: Array; contentUri?: Maybe; + context?: Maybe; + contextId?: Maybe; contexts: Array; id: Scalars["String"]["output"]; language?: Maybe; metadata: GQLTaxonomyMetadata; name: Scalars["String"]["output"]; + nodeType: Scalars["String"]["output"]; path?: Maybe; paths: Array; relevanceId?: Maybe; @@ -2081,7 +2180,8 @@ export type GQLTitle = { title: Scalars["String"]["output"]; }; -export type GQLTopic = GQLTaxonomyEntity & +export type GQLTopic = GQLTaxBase & + GQLTaxonomyEntity & GQLWithArticle & { __typename?: "Topic"; alternateTopics?: Maybe>; @@ -2089,6 +2189,8 @@ export type GQLTopic = GQLTaxonomyEntity & availability?: Maybe; breadcrumbs: Array; contentUri?: Maybe; + context?: Maybe; + contextId?: Maybe; contexts: Array; coreResources?: Maybe>; id: Scalars["String"]["output"]; @@ -2097,10 +2199,9 @@ export type GQLTopic = GQLTaxonomyEntity & meta?: Maybe; metadata: GQLTaxonomyMetadata; name: Scalars["String"]["output"]; - parent?: Maybe; + nodeType: Scalars["String"]["output"]; parentId?: Maybe; path?: Maybe; - pathTopics?: Maybe>>; paths: Array; relevanceId?: Maybe; resourceTypes?: Maybe>; @@ -2153,6 +2254,7 @@ export type GQLTransformedArticleContentInput = { draftConcept?: InputMaybe; isOembed?: InputMaybe; path?: InputMaybe; + prettyUrl?: InputMaybe; previewH5p?: InputMaybe; showVisualElement?: InputMaybe; subjectId?: InputMaybe; @@ -2215,7 +2317,9 @@ export type GQLVisualElementOembed = { }; export type GQLWithArticle = { + article?: Maybe; availability?: Maybe; + contentUri?: Maybe; meta?: Maybe; }; @@ -2874,7 +2978,7 @@ export type GQLMovedResourcePage_ResourceFragment = { __typename?: "Article"; id: number; metaDescription: string; - metaImage?: { __typename?: "MetaImage"; url: string; alt: string }; + metaImage: { __typename?: "MetaImageWithCopyright"; url: string; alt: string }; }; learningpath?: { __typename?: "Learningpath"; @@ -2902,7 +3006,7 @@ export type GQLMultidisciplinarySubjectArticlePageQuery = { introduction?: string; metaDescription: string; tags?: Array; - metaImage?: { __typename?: "MetaImage"; url: string }; + metaImage: { __typename?: "MetaImageWithCopyright"; url: string }; }; } & GQLMultidisciplinarySubjectArticle_TopicFragment; resourceTypes?: Array< @@ -3582,13 +3686,12 @@ export type GQLSortFoldersMutation = { }; export type GQLSortSavedSharedFoldersMutationVariables = Exact<{ - parentId?: InputMaybe; sortedIds: Array | Scalars["String"]["input"]; }>; export type GQLSortSavedSharedFoldersMutation = { __typename?: "Mutation"; - sortSavedSharedFolders: { __typename?: "SortResult"; parentId?: string; sortedIds: Array }; + sortSavedSharedFolders: { __typename?: "SortResult"; sortedIds: Array }; }; export type GQLSortResourcesMutationVariables = Exact<{ @@ -4308,7 +4411,7 @@ export type GQLResources_ResourceFragment = { rank?: number; language?: string; relevanceId?: string; - article?: { __typename?: "Article"; metaImage?: { __typename?: "MetaImage"; url: string; alt: string } }; + article?: { __typename?: "Article"; metaImage: { __typename?: "MetaImageWithCopyright"; url: string; alt: string } }; learningpath?: { __typename?: "Learningpath"; coverphoto?: { __typename?: "LearningpathCoverphoto"; url: string } }; resourceTypes?: Array<{ __typename?: "ResourceType"; id: string; name: string }>; }; @@ -4414,7 +4517,12 @@ export type GQLTopic_TopicFragment = { grepCodes?: Array; oembed?: string; revisionDate?: string; - metaImage?: { __typename?: "MetaImage"; url: string; alt: string }; + metaImage: { + __typename?: "MetaImageWithCopyright"; + url: string; + alt: string; + copyright: { __typename?: "Copyright" } & GQLCopyrightInfoFragment; + }; transformedContent: { __typename?: "TransformedArticleContent"; visualElementEmbed?: { __typename?: "ResourceEmbed"; content: string }; @@ -4480,7 +4588,7 @@ export type GQLIframeArticlePage_ArticleFragment = { metaDescription: string; oembed?: string; tags?: Array; - metaImage?: { __typename?: "MetaImage"; url: string }; + metaImage: { __typename?: "MetaImageWithCopyright"; url: string }; } & GQLArticle_ArticleFragment & GQLStructuredArticleDataFragment; @@ -4576,6 +4684,7 @@ export type GQLGroupSearchQuery = { export type GQLCopyrightInfoFragment = { __typename?: "Copyright"; origin?: string; + processed?: boolean; license: { __typename?: "License"; license: string; url?: string; description?: string }; creators: Array<{ __typename?: "Contributor" } & GQLContributorInfoFragment>; processors: Array<{ __typename?: "Contributor" } & GQLContributorInfoFragment>; @@ -4768,7 +4877,7 @@ export type GQLStructuredArticleDataFragment = { supportedLanguages?: Array; availability?: string; copyright: { __typename?: "Copyright" } & GQLStructuredArticleData_CopyrightFragment; - metaImage?: { __typename?: "MetaImage"; url: string; alt: string }; + metaImage: { __typename?: "MetaImageWithCopyright"; url: string; alt: string }; competenceGoals?: Array<{ __typename?: "CompetenceGoal"; id: string; code?: string; title: string; type: string }>; coreElements?: Array<{ __typename?: "CoreElement"; id: string; title: string }>; transformedContent: { diff --git a/src/queries.ts b/src/queries.ts index 907b0764ef..979fca9afe 100644 --- a/src/queries.ts +++ b/src/queries.ts @@ -130,6 +130,7 @@ export const copyrightInfoFragment = gql` ...ContributorInfo } origin + processed } `; diff --git a/src/schema.graphql b/src/schema.graphql index 0ba70d852a..6199ed7e00 100644 --- a/src/schema.graphql +++ b/src/schema.graphql @@ -194,7 +194,7 @@ type Article { introduction: String language: String! metaDescription: String! - metaImage: MetaImage + metaImage: MetaImageWithCopyright! oembed: String oldNdlaUrl: String published: String! @@ -790,7 +790,7 @@ type LearningpathStep { license: License metaUrl: String! oembed: LearningpathStepOembed - resource: Resource + resource(parentId: String, rootId: String): Resource revision: Int! seqNo: Int! showTitle: Boolean! @@ -844,6 +844,13 @@ type Meta { type MetaImage { alt: String! + copyright: Copyright + url: String! +} + +type MetaImageWithCopyright { + alt: String! + copyright: Copyright! url: String! } @@ -854,6 +861,7 @@ type Movie { path: String! resourceTypes: [ResourceType!]! title: String! + url: String! } type MovieMeta { @@ -862,11 +870,6 @@ type MovieMeta { title: String! } -type MoviePath { - path: String - paths: [String!] -} - type MovieResourceTypes { resourceTypes: [ResourceType!] } @@ -927,6 +930,7 @@ type Mutation { absoluteUrl: Boolean content: String! draftConcept: Boolean + prettyUrl: Boolean previewH5p: Boolean subject: String visualElement: String @@ -991,6 +995,36 @@ type NewFolderResource { tags: [String!] } +type Node implements TaxBase & TaxonomyEntity & WithArticle { + alternateNodes: [Node!] + article: Article + availability: String + breadcrumbs: [String!]! + children(nodeType: String, recursive: Boolean): [Node!] + connectionId: String + contentUri: String + context: TaxonomyContext + contextId: String + contexts: [TaxonomyContext!]! + grepCodes: [String!] + id: String! + language: String + learningpath: Learningpath + meta: Meta + metadata: TaxonomyMetadata! + name: String! + nodeType: String! + parentId: String + path: String + paths: [String!]! + rank: Int + relevanceId: String + resourceTypes: [ResourceType!] + subjectpage: SubjectPage + supportedLanguages: [String!]! + url: String +} + type Owner { name: String! } @@ -1166,6 +1200,16 @@ type Query { learningpath(pathId: String!): Learningpath listArenaUserV2(filterTeachers: Boolean, page: Int, pageSize: Int, query: String): PaginatedArenaUsers! listingPage(subjects: String): ListingPage + node(contextId: String, id: String, parentId: String, rootId: String): Node + nodeByArticleId(articleId: String, nodeId: String): Node + nodes( + contentUri: String + filterVisible: Boolean + ids: [String!] + metadataFilterKey: String + metadataFilterValue: String + nodeType: String + ): [Node!] personalData: MyNdlaPersonalData podcastSearch(fallback: Boolean, page: Int!, pageSize: Int!): AudioSearch podcastSeries(id: Int!): PodcastSeriesWithEpisodes @@ -1229,11 +1273,13 @@ type RelatedContent { url: String! } -type Resource implements TaxonomyEntity & WithArticle { +type Resource implements TaxBase & TaxonomyEntity & WithArticle { article: Article availability: String breadcrumbs: [String!]! contentUri: String + context: TaxonomyContext + contextId: String contexts: [TaxonomyContext!]! id: String! language: String @@ -1241,6 +1287,7 @@ type Resource implements TaxonomyEntity & WithArticle { meta: Meta metadata: TaxonomyMetadata! name: String! + nodeType: String! parents: [Topic!] path: String paths: [String!]! @@ -1275,7 +1322,6 @@ type ResourceMetaData { type ResourceType { id: String! name: String! - resources(topicId: String!): [Resource!] } type ResourceTypeDefinition { @@ -1363,16 +1409,19 @@ type SortResult { scalar StringRecord -type Subject implements TaxonomyEntity { +type Subject implements TaxBase & TaxonomyEntity { allTopics: [Topic!] breadcrumbs: [String!]! contentUri: String + context: TaxonomyContext + contextId: String contexts: [TaxonomyContext!]! grepCodes: [String!] id: String! language: String metadata: TaxonomyMetadata! name: String! + nodeType: String! path: String paths: [String!]! relevanceId: String @@ -1386,6 +1435,7 @@ type Subject implements TaxonomyEntity { type SubjectLink { name: String path: String + url: String } type SubjectPage { @@ -1434,9 +1484,29 @@ type Tags { tags: [String!]! } +interface TaxBase { + id: String! + name: String! + path: String + url: String +} + type TaxonomyContext { breadcrumbs: [String!]! + contextId: String! + name: String! parentIds: [String!]! + parents: [TaxonomyCrumb!] + path: String! + relevance: String! + rootId: String! + url: String! +} + +type TaxonomyCrumb implements TaxBase { + contextId: String! + id: String! + name: String! path: String! url: String! } @@ -1444,11 +1514,14 @@ type TaxonomyContext { interface TaxonomyEntity { breadcrumbs: [String!]! contentUri: String + context: TaxonomyContext + contextId: String contexts: [TaxonomyContext!]! id: String! language: String metadata: TaxonomyMetadata! name: String! + nodeType: String! path: String paths: [String!]! relevanceId: String @@ -1473,12 +1546,14 @@ type Title { title: String! } -type Topic implements TaxonomyEntity & WithArticle { +type Topic implements TaxBase & TaxonomyEntity & WithArticle { alternateTopics: [Topic!] article: Article availability: String breadcrumbs: [String!]! contentUri: String + context: TaxonomyContext + contextId: String contexts: [TaxonomyContext!]! coreResources(subjectId: String): [Resource!] id: String! @@ -1487,10 +1562,9 @@ type Topic implements TaxonomyEntity & WithArticle { meta: Meta metadata: TaxonomyMetadata! name: String! - parent: String + nodeType: String! parentId: String path: String - pathTopics: [[Topic!]!] paths: [String!]! relevanceId: String resourceTypes: [ResourceType!] @@ -1532,6 +1606,7 @@ input TransformedArticleContentInput { draftConcept: Boolean isOembed: String path: String + prettyUrl: Boolean previewH5p: Boolean showVisualElement: String subjectId: String @@ -1587,6 +1662,8 @@ type VisualElementOembed { } interface WithArticle { + article: Article availability: String + contentUri: String meta: Meta }