From 151ae0b126bc65082eec2568a12059f0a5cddf9a Mon Sep 17 00:00:00 2001 From: DrMint Date: Thu, 17 Mar 2022 17:05:34 +0100 Subject: [PATCH] Display the news articles --- src/components/Markdown/Markdawn.tsx | 2 +- src/components/News/PostsPreview.tsx | 64 +++++++++++ src/graphql/operation.graphql | 83 +++++++++++++- src/graphql/operations-types.ts | 106 ++++++++++++++++- src/graphql/operations.ts | 18 +++ src/graphql/schema.graphql | 21 ++-- src/pages/contents/[slug]/index.tsx | 23 +++- src/pages/contents/[slug]/read.tsx | 30 ++++- src/pages/news/[slug].tsx | 165 +++++++++++++++++++++++++++ src/pages/news/index.tsx | 32 +++++- 10 files changed, 517 insertions(+), 27 deletions(-) create mode 100644 src/components/News/PostsPreview.tsx create mode 100644 src/pages/news/[slug].tsx diff --git a/src/components/Markdown/Markdawn.tsx b/src/components/Markdown/Markdawn.tsx index f6fcb7c..cd0dc14 100644 --- a/src/components/Markdown/Markdawn.tsx +++ b/src/components/Markdown/Markdawn.tsx @@ -167,7 +167,7 @@ export default function Markdawn(props: ScenBreakProps): JSX.Element { }, InsetBox: { component: (props) => { - return {props.children}; + return {props.children}; }, }, li: { diff --git a/src/components/News/PostsPreview.tsx b/src/components/News/PostsPreview.tsx new file mode 100644 index 0000000..ee0fdc9 --- /dev/null +++ b/src/components/News/PostsPreview.tsx @@ -0,0 +1,64 @@ +import Link from "next/link"; +import { prettyDate, prettySlug } from "queries/helpers"; +import Chip from "components/Chip"; +import Img, { ImageQuality } from "components/Img"; +import { GetPostsPreviewQuery } from "graphql/operations-types"; + +export type PostPreviewProps = { + post: { + slug: GetPostsPreviewQuery["posts"]["data"][number]["attributes"]["slug"]; + thumbnail: GetPostsPreviewQuery["posts"]["data"][number]["attributes"]["thumbnail"]; + translations: GetPostsPreviewQuery["posts"]["data"][number]["attributes"]["translations"]; + categories: GetPostsPreviewQuery["posts"]["data"][number]["attributes"]["categories"]; + date: GetPostsPreviewQuery["posts"]["data"][number]["attributes"]["date"]; + }; +}; + +export default function PostPreview(props: PostPreviewProps): JSX.Element { + const post = props.post; + + return ( + +
+ {post.thumbnail.data ? ( + + ) : ( +
+ )} +
+
+ {post.date && ( +

+ + event + + {prettyDate(post.date)} +

+ )} +
+
+ {post.translations.length > 0 ? ( + <> +

{post.translations[0].title}

+

{post.translations[0].excerpt}

+ + ) : ( +

{prettySlug(post.slug)}

+ )} +
+
+ {post.categories.data.map((category) => ( + + {category.attributes.short} + + ))} +
+
+
+ + ); +} diff --git a/src/graphql/operation.graphql b/src/graphql/operation.graphql index cefdb37..b6d3730 100644 --- a/src/graphql/operation.graphql +++ b/src/graphql/operation.graphql @@ -1155,8 +1155,12 @@ query getPost($slug: String, $language_code: String) { id attributes { slug - publishedAt updatedAt + date { + year + month + day + } authors { data { id @@ -1200,8 +1204,20 @@ query getPost($slug: String, $language_code: String) { } } hidden + thumbnail { + data { + attributes { + name + alternativeText + caption + width + height + url + } + } + } translations(filters: { language: { code: { eq: $language_code } } }) { - Status + status title excerpt thumbnail { @@ -1222,3 +1238,66 @@ query getPost($slug: String, $language_code: String) { } } } + +query getPostsSlugs { + posts(filters: { hidden: { eq: false } }) { + data { + id + attributes { + slug + } + } + } +} + +query getPostsPreview($language_code: String) { + posts(filters: { hidden: { eq: false } }) { + data { + id + attributes { + slug + date { + year + month + day + } + categories { + data { + id + attributes { + short + } + } + } + thumbnail { + data { + attributes { + name + alternativeText + caption + width + height + url + } + } + } + translations(filters: { language: { code: { eq: $language_code } } }) { + title + excerpt + thumbnail { + data { + attributes { + name + alternativeText + caption + width + height + url + } + } + } + } + } + } + } +} diff --git a/src/graphql/operations-types.ts b/src/graphql/operations-types.ts index 972010f..245677f 100644 --- a/src/graphql/operations-types.ts +++ b/src/graphql/operations-types.ts @@ -1554,8 +1554,13 @@ export type GetPostQuery = { attributes: { __typename: "Post"; slug: string; - publishedAt: any; updatedAt: any; + date: { + __typename: "ComponentBasicsDatepicker"; + year: number; + month: number; + day: number; + }; hidden: boolean; authors: { __typename: "RecorderRelationResponseCollection"; @@ -1609,9 +1614,24 @@ export type GetPostQuery = { }; }>; }; + thumbnail: { + __typename: "UploadFileEntityResponse"; + data: { + __typename: "UploadFileEntity"; + attributes: { + __typename: "UploadFile"; + name: string; + alternativeText: string; + caption: string; + width: number; + height: number; + url: string; + }; + }; + }; translations: Array<{ __typename: "ComponentTranslationsPosts"; - Status: Enum_Componenttranslationsposts_Status; + status: Enum_Componenttranslationsposts_Status; title: string; excerpt: string; body: string; @@ -1635,3 +1655,85 @@ export type GetPostQuery = { }>; }; }; + +export type GetPostsSlugsQueryVariables = Exact<{ [key: string]: never }>; + +export type GetPostsSlugsQuery = { + __typename: "Query"; + posts: { + __typename: "PostEntityResponseCollection"; + data: Array<{ + __typename: "PostEntity"; + id: string; + attributes: { __typename: "Post"; slug: string }; + }>; + }; +}; + +export type GetPostsPreviewQueryVariables = Exact<{ + language_code: InputMaybe; +}>; + +export type GetPostsPreviewQuery = { + __typename: "Query"; + posts: { + __typename: "PostEntityResponseCollection"; + data: Array<{ + __typename: "PostEntity"; + id: string; + attributes: { + __typename: "Post"; + slug: string; + date: { + __typename: "ComponentBasicsDatepicker"; + year: number; + month: number; + day: number; + }; + categories: { + __typename: "CategoryRelationResponseCollection"; + data: Array<{ + __typename: "CategoryEntity"; + id: string; + attributes: { __typename: "Category"; short: string }; + }>; + }; + thumbnail: { + __typename: "UploadFileEntityResponse"; + data: { + __typename: "UploadFileEntity"; + attributes: { + __typename: "UploadFile"; + name: string; + alternativeText: string; + caption: string; + width: number; + height: number; + url: string; + }; + }; + }; + translations: Array<{ + __typename: "ComponentTranslationsPosts"; + title: string; + excerpt: string; + thumbnail: { + __typename: "UploadFileEntityResponse"; + data: { + __typename: "UploadFileEntity"; + attributes: { + __typename: "UploadFile"; + name: string; + alternativeText: string; + caption: string; + width: number; + height: number; + url: string; + }; + }; + }; + }>; + }; + }>; + }; +}; diff --git a/src/graphql/operations.ts b/src/graphql/operations.ts index e309b2f..74a55f2 100644 --- a/src/graphql/operations.ts +++ b/src/graphql/operations.ts @@ -25,6 +25,10 @@ import { GetLibraryItemsSlugsQueryVariables, GetPostQuery, GetPostQueryVariables, + GetPostsPreviewQuery, + GetPostsPreviewQueryVariables, + GetPostsSlugsQuery, + GetPostsSlugsQueryVariables, GetWebsiteInterfaceQuery, GetWebsiteInterfaceQueryVariables, } from "graphql/operations-types"; @@ -150,3 +154,17 @@ export async function getPost( const query = getQueryFromOperations("getPost"); return await graphQL(query, JSON.stringify(variables)); } + +export async function getPostsSlugs( + variables: GetPostsSlugsQueryVariables +): Promise { + const query = getQueryFromOperations("getPostsSlugs"); + return await graphQL(query, JSON.stringify(variables)); +} + +export async function getPostsPreview( + variables: GetPostsPreviewQueryVariables +): Promise { + const query = getQueryFromOperations("getPostsPreview"); + return await graphQL(query, JSON.stringify(variables)); +} diff --git a/src/graphql/schema.graphql b/src/graphql/schema.graphql index cf8f6ed..1514e6c 100644 --- a/src/graphql/schema.graphql +++ b/src/graphql/schema.graphql @@ -26,11 +26,6 @@ type ResponseCollectionMeta { pagination: Pagination! } -enum PublicationState { - LIVE - PREVIEW -} - input IDFilterInput { and: [ID] or: [ID] @@ -387,6 +382,8 @@ input ComponentCollectionsComponentLibraryObiBeltInput { back: ID full: ID inside_full: ID + flap_front: ID + flap_back: ID } type ComponentCollectionsComponentLibraryObiBelt { @@ -396,6 +393,8 @@ type ComponentCollectionsComponentLibraryObiBelt { back: UploadFileEntityResponse full: UploadFileEntityResponse inside_full: UploadFileEntityResponse + flap_front: UploadFileEntityResponse + flap_back: UploadFileEntityResponse } input ComponentCollectionsComponentTitlesFiltersInput { @@ -1057,11 +1056,11 @@ enum ENUM_COMPONENTTRANSLATIONSPOSTS_STATUS { } input ComponentTranslationsPostsFiltersInput { - Status: StringFilterInput title: StringFilterInput excerpt: StringFilterInput body: StringFilterInput language: LanguageFiltersInput + status: StringFilterInput and: [ComponentTranslationsPostsFiltersInput] or: [ComponentTranslationsPostsFiltersInput] not: ComponentTranslationsPostsFiltersInput @@ -1069,22 +1068,22 @@ input ComponentTranslationsPostsFiltersInput { input ComponentTranslationsPostsInput { id: ID - Status: ENUM_COMPONENTTRANSLATIONSPOSTS_STATUS title: String excerpt: String thumbnail: ID body: String language: ID + status: ENUM_COMPONENTTRANSLATIONSPOSTS_STATUS } type ComponentTranslationsPosts { id: ID! - Status: ENUM_COMPONENTTRANSLATIONSPOSTS_STATUS! title: String! excerpt: String thumbnail: UploadFileEntityResponse body: String language: LanguageEntityResponse + status: ENUM_COMPONENTTRANSLATIONSPOSTS_STATUS! } enum ENUM_COMPONENTTRANSLATIONSSCANSET_STATUS { @@ -2126,7 +2125,6 @@ input PostFiltersInput { hidden: BooleanFilterInput createdAt: DateTimeFilterInput updatedAt: DateTimeFilterInput - publishedAt: DateTimeFilterInput and: [PostFiltersInput] or: [PostFiltersInput] not: PostFiltersInput @@ -2138,7 +2136,7 @@ input PostInput { categories: [ID] translations: [ComponentTranslationsPostsInput] hidden: Boolean - publishedAt: DateTime + thumbnail: ID } type Post { @@ -2159,9 +2157,9 @@ type Post { sort: [String] = [] ): [ComponentTranslationsPosts] hidden: Boolean! + thumbnail: UploadFileEntityResponse createdAt: DateTime updatedAt: DateTime - publishedAt: DateTime } type PostEntity { @@ -3206,7 +3204,6 @@ type Query { filters: PostFiltersInput pagination: PaginationArg = {} sort: [String] = [] - publicationState: PublicationState = LIVE ): PostEntityResponseCollection rangedContent(id: ID): RangedContentEntityResponse rangedContents( diff --git a/src/pages/contents/[slug]/index.tsx b/src/pages/contents/[slug]/index.tsx index 241be91..82ff621 100644 --- a/src/pages/contents/[slug]/index.tsx +++ b/src/pages/contents/[slug]/index.tsx @@ -40,7 +40,28 @@ export default function ContentIndex(props: ContentIndexProps): JSX.Element { className="mb-10" />
- + 0 ? content.titles[0].pre_title : undefined + } + title={ + content.titles.length > 0 + ? content.titles[0].title + : prettySlug(content.slug) + } + subtitle={ + content.titles.length > 0 ? content.titles[0].subtitle : undefined + } + description={ + content.titles.length > 0 + ? content.titles[0].description + : undefined + } + type={content.type} + categories={content.categories} + langui={langui} + /> diff --git a/src/pages/contents/[slug]/read.tsx b/src/pages/contents/[slug]/read.tsx index 09ba673..6ef51ed 100644 --- a/src/pages/contents/[slug]/read.tsx +++ b/src/pages/contents/[slug]/read.tsx @@ -1,9 +1,6 @@ import { GetStaticPaths, GetStaticProps } from "next"; import { getContentsSlugs, getContentText } from "graphql/operations"; -import { - Enum_Componentsetstextset_Status, - GetContentTextQuery, -} from "graphql/operations-types"; +import { GetContentTextQuery } from "graphql/operations-types"; import ContentPanel from "components/Panels/ContentPanel"; import HorizontalLine from "components/HorizontalLine"; import SubPanel from "components/Panels/SubPanel"; @@ -158,13 +155,34 @@ export default function ContentRead(props: ContentReadProps): JSX.Element {
- + 0 ? content.titles[0].pre_title : undefined + } + title={ + content.titles.length > 0 + ? content.titles[0].title + : prettySlug(content.slug) + } + subtitle={ + content.titles.length > 0 ? content.titles[0].subtitle : undefined + } + description={ + content.titles.length > 0 + ? content.titles[0].description + : undefined + } + type={content.type} + categories={content.categories} + langui={langui} + /> diff --git a/src/pages/news/[slug].tsx b/src/pages/news/[slug].tsx new file mode 100644 index 0000000..3abc4c3 --- /dev/null +++ b/src/pages/news/[slug].tsx @@ -0,0 +1,165 @@ +import AppLayout from "components/AppLayout"; +import Chip from "components/Chip"; +import ThumbnailHeader from "components/Content/ThumbnailHeader"; +import HorizontalLine from "components/HorizontalLine"; +import Markdawn from "components/Markdown/Markdawn"; +import TOC from "components/Markdown/TOC"; +import ReturnButton, { + ReturnButtonType, +} from "components/PanelComponents/ReturnButton"; +import ContentPanel from "components/Panels/ContentPanel"; +import SubPanel from "components/Panels/SubPanel"; +import RecorderChip from "components/RecorderChip"; +import ToolTip from "components/ToolTip"; +import { getPost, getPostsSlugs } from "graphql/operations"; +import { GetPostQuery } from "graphql/operations-types"; +import { GetStaticPaths, GetStaticProps } from "next"; +import { useRouter } from "next/router"; +import { AppStaticProps, getAppStaticProps } from "queries/getAppStaticProps"; +import { prettySlug, getStatusDescription } from "queries/helpers"; + +interface PostProps extends AppStaticProps { + post: GetPostQuery["posts"]["data"][number]["attributes"]; + postId: GetPostQuery["posts"]["data"][number]["id"]; +} + +export default function LibrarySlug(props: PostProps): JSX.Element { + const { post, postId, langui } = props; + const router = useRouter(); + + const subPanel = ( + + + + {post.translations.length > 0 && ( +
+

{langui.status}:

+ + + {post.translations[0].status} + +
+ )} + + {post.authors.data.length > 0 && ( +
+

{"Authors"}:

+
+ {post.authors.data.map((author) => ( + + ))} +
+
+ )} + + + + {post.translations.length > 0 && post.translations[0].body && ( + + )} +
+ ); + const contentPanel = ( + + + + 0 && post.translations[0].thumbnail.data + ? post.translations[0].thumbnail + : post.thumbnail + } + title={ + post.translations.length > 0 + ? post.translations[0].title + : prettySlug(post.slug) + } + description={ + post.translations.length > 0 + ? post.translations[0].excerpt + : undefined + } + langui={langui} + categories={post.categories} + /> + + + + {post.translations.length > 0 && post.translations[0].body && ( + + )} + + ); + + return ( + 0 + ? post.translations[0].title + : prettySlug(post.slug) + } + contentPanel={contentPanel} + subPanel={subPanel} + thumbnail={post.translations[0].thumbnail.data?.attributes} + {...props} + /> + ); +} + +export const getStaticProps: GetStaticProps = async (context) => { + const post = ( + await getPost({ + slug: context.params?.slug?.toString() || "", + language_code: context.locale || "en", + }) + ).posts.data[0]; + const props: PostProps = { + ...(await getAppStaticProps(context)), + post: post.attributes, + postId: post.id, + }; + return { + props: props, + }; +}; + +export const getStaticPaths: GetStaticPaths = async (context) => { + type Path = { + params: { + slug: string; + }; + locale: string; + }; + + const data = await getPostsSlugs({}); + const paths: Path[] = []; + data.posts.data.map((item) => { + context.locales?.map((local) => { + paths.push({ params: { slug: item.attributes.slug }, locale: local }); + }); + }); + return { + paths, + fallback: false, + }; +}; diff --git a/src/pages/news/index.tsx b/src/pages/news/index.tsx index 9f26104..81de104 100644 --- a/src/pages/news/index.tsx +++ b/src/pages/news/index.tsx @@ -3,11 +3,17 @@ import PanelHeader from "components/PanelComponents/PanelHeader"; import { GetStaticProps } from "next"; import AppLayout from "components/AppLayout"; import { AppStaticProps, getAppStaticProps } from "queries/getAppStaticProps"; +import { GetPostsPreviewQuery } from "graphql/operations-types"; +import { getPostsPreview } from "graphql/operations"; +import ContentPanel, { ContentPanelWidthSizes } from "components/Panels/ContentPanel"; +import PostsPreview from "components/News/PostsPreview"; -interface NewsProps extends AppStaticProps {} +interface NewsProps extends AppStaticProps { + posts: GetPostsPreviewQuery["posts"]["data"]; +} export default function News(props: NewsProps): JSX.Element { - const { langui } = props; + const { langui, posts } = props; const subPanel = ( ); - return ; + const contentPanel = ( + +
+ {posts.map((post) => ( + + ))} +
+
+ ); + + return ( + + ); } export const getStaticProps: GetStaticProps = async (context) => { const props: NewsProps = { ...(await getAppStaticProps(context)), + posts: await ( + await getPostsPreview({ language_code: context.locale || "en" }) + ).posts.data, }; return { props: props,