From fc141d6b0ecd801e275a8e749bb243a4074905e8 Mon Sep 17 00:00:00 2001 From: David Schwarzmann <david.schwarzmann@codecentric.de> Date: Mon, 7 Feb 2022 10:32:05 +0100 Subject: [PATCH] Unify services and suites --- lib/contentful/index.ts | 40 +-- pages/index.tsx | 35 +-- pages/services/index.tsx | 157 ----------- pages/suites/[name].tsx | 8 - pages/{services => suites}/[serviceName].tsx | 3 +- pages/suites/index.tsx | 266 ++++++++++++++++++- views/layout/Navbar.tsx | 18 +- 7 files changed, 292 insertions(+), 235 deletions(-) delete mode 100644 pages/services/index.tsx delete mode 100644 pages/suites/[name].tsx rename pages/{services => suites}/[serviceName].tsx (97%) diff --git a/lib/contentful/index.ts b/lib/contentful/index.ts index 49630bb..e13adaf 100644 --- a/lib/contentful/index.ts +++ b/lib/contentful/index.ts @@ -1,42 +1,48 @@ -import {ContentfulClientApi, createClient, Entry, EntryCollection} from 'contentful' +import { + ContentfulClientApi, + createClient, + Entry, + EntryCollection, +} from 'contentful' const space = process.env.NEXT_PUBLIC_CONTENTFUL_SPACE_ID const accessToken = process.env.NEXT_PUBLIC_CONTENTFUL_ACCESS_TOKEN -const client : ContentfulClientApi = createClient({ +const client: ContentfulClientApi = createClient({ space: space, accessToken: accessToken, }) - export type ServiceType = { - name: string, - slug: string, - logo: object, - shortDescription: object, - developer: object, - contactInformation: object, - status: string, - documentationURL: string, + name: string + slug: string + logo: object + shortDescription: object + developer: object + contactInformation: object + status: string + documentationURL: string sourcecodeURL?: string - tosURL?: string, + tosURL?: string description: object } -export async function fetchServices() : Promise<Entry<any>[]>{ +export async function fetchServices(): Promise<Entry<any>[]> { const services = await client.getEntries({ - content_type: 'service' + content_type: 'service', }) if (services.items) return services.items console.log(`Error getting Entries for services.`) } -export async function fetchService(slug) : Promise<Entry<any>> { +export async function fetchService(slug): Promise<Entry<any>> { const services = await client.getEntries({ - content_type: 'service' + content_type: 'service', }) - return services.items.find((service: Entry<ServiceType>) => service.fields.slug === slug ) + return services.items.find( + (service: Entry<ServiceType>) => service.fields.slug === slug + ) } export default { fetchServices, fetchService } diff --git a/pages/index.tsx b/pages/index.tsx index dabd39a..5ed2e13 100644 --- a/pages/index.tsx +++ b/pages/index.tsx @@ -1,5 +1,4 @@ -import Head from "next/head" -import { GetStaticPropsResult } from "next" +import Head from 'next/head' import Hero from '@/views/Hero' import FeaturedApiModules from '@/views/FeaturedApiModules' @@ -9,41 +8,17 @@ export default function IndexPage({ nodes }) { return ( <> <Head> - <title>Next.js for Drupal</title> + <title>Föderales Entwicklungsportal</title> <meta name="description" content="A Next.js site powered by a Drupal backend." /> </Head> - <Hero /> + <Hero /> - <Organisators /> + <Organisators /> - <FeaturedApiModules /> + <FeaturedApiModules /> </> ) } - -/* -export async function getStaticProps( - context -): Promise<GetStaticPropsResult<IndexPageProps>> { - const nodes = await getResourceCollectionFromContext<DrupalNode[]>( - "node--services", - context, - { - params: { - include: "field_image,uid", - sort: "-created", - }, - } - ) - - return { - props: { - nodes, - }, - revalidate: 10, - } -} -*/ diff --git a/pages/services/index.tsx b/pages/services/index.tsx deleted file mode 100644 index 67ee7e9..0000000 --- a/pages/services/index.tsx +++ /dev/null @@ -1,157 +0,0 @@ -import Link from 'next/link' -import { fetchServices } from '@/lib/contentful' -import { documentToHtmlString } from '@contentful/rich-text-html-renderer' -import { IconArrowBigRight, IconSearch } from '@tabler/icons' - -export default function ({ services }) { - return ( - <div className="py-10"> - <div className="max-w-3xl mx-auto sm:px-6 lg:max-w-7xl lg:px-8 lg:grid lg:grid-cols-12 lg:gap-8"> - <header - className={ - 'lg:col-start-3 xl:col-start-3 lg:col-span-9 xl:col-span-9' - } - > - <h1> - <span className="mt-1 block text-4xl tracking-tight font-extrabold sm:text-5xl xl:text-7xl"> - <span className="block text-gray-900">Gelistete Services</span> - </span> - </h1> - </header> - <div className="hidden lg:block lg:col-span-3 xl:col-span-2"> - <nav - aria-label="Sidebar" - className="sticky top-4 divide-y divide-gray-300" - > - <div className="pt-10"> - <p - className="px-3 text-xs font-semibold text-gray-500 uppercase tracking-wider" - id="communities-headline" - > - Filter - </p> - <div - className="mt-3 space-y-2" - aria-labelledby="communities-headline" - > - {/* Filter Options - communities.map((community) => ( - <a - key={community.name} - href={community.href} - className="group flex items-center px-3 py-2 text-sm font-medium text-gray-600 rounded-md hover:text-gray-900 hover:bg-gray-50" - > - <span className="truncate">{community.name}</span> - </a> - ))*/} - </div> - </div> - </nav> - </div> - <main className="lg:col-span-9 xl:col-span-9"> - {/* - <div className="px-4 sm:px-0"> - <div className="w-full"> - <label htmlFor="search" className="sr-only"> - Durchsuchen - </label> - <div className="relative"> - <div className="pointer-events-none absolute inset-y-0 left-0 pl-3 flex items-center"> - <IconSearch - className="h-5 w-5 text-gray-400" - aria-hidden="true" - /> - </div> - <input - id="search" - name="search" - className="block w-full bg-white border border-gray-300 rounded-md py-2 pl-10 pr-3 text-sm placeholder-gray-500 focus:outline-none focus:text-gray-900 focus:placeholder-gray-400 focus:ring-1 focus:ring-rose-500 focus:border-rose-500 sm:text-sm" - placeholder="Search" - type="search" - /> - </div> - </div> - </div> - */} - <div className="mt-4"> - <h1 className="sr-only">Gelistete Services</h1> - <ul role="list" className="space-y-4"> - {services.map((service, key) => ( - <li - key={key} - className="bg-white px-4 py-6 shadow sm:p-6 sm:rounded-lg" - > - <div aria-labelledby={'service-' + key}> - <div> - <div className="flex space-x-3"> - <div className="flex-shrink-0"> - <img - className="h-10 w-10" - src={service.logo.fields.file.url} - alt={service.logo.fields.name} - /> - </div> - <div className="min-w-0 flex-1"> - <p className="text-sm font-medium text-gray-900"> - <Link - href={`/services/${service.slug}`} - passHref - > - <a - href={service.developer.fields.link} - className="hover:underline" - > - {service.name} - </a> - </Link> - </p> - <p className="text-sm text-gray-500"> - entwickelt durch {service.developer.fields.name} - </p> - </div> - </div> - </div> - <div - className="mt-2 text-sm text-gray-700 space-y-4" - dangerouslySetInnerHTML={{ - __html: documentToHtmlString(service.shortDescription), - }} - /> - <div className="mt-6 flex justify-end space-x-8"> - <div className="flex text-sm"> - <span className="inline-flex items-center text-sm"> - <Link - href={`/services/${service.slug}`} - passHref - > - <a className="inline-flex space-x-2 text-gray-400 hover:text-gray-800"> - <span className="font-medium">Mehr</span> - <IconArrowBigRight - className="h-5 w-5" - aria-hidden="true" - /> - </a> - </Link> - </span> - </div> - </div> - </div> - </li> - ))} - </ul> - </div> - </main> - </div> - </div> - ) -} - -export async function getStaticProps(context) { - const services = (await fetchServices()).map((service) => service.fields) - - return { - props: { - services, - }, - } -} diff --git a/pages/suites/[name].tsx b/pages/suites/[name].tsx deleted file mode 100644 index ae948bc..0000000 --- a/pages/suites/[name].tsx +++ /dev/null @@ -1,8 +0,0 @@ -// Will be a Copy cat from service with minor adaptions - -export default function () { - return ( - <> - </> - ) -} diff --git a/pages/services/[serviceName].tsx b/pages/suites/[serviceName].tsx similarity index 97% rename from pages/services/[serviceName].tsx rename to pages/suites/[serviceName].tsx index f4f52f1..f664c89 100644 --- a/pages/services/[serviceName].tsx +++ b/pages/suites/[serviceName].tsx @@ -2,7 +2,6 @@ import { Header } from '@/views/Service' import { fetchServices, fetchService } from '@/lib/contentful' import { documentToHtmlString } from '@contentful/rich-text-html-renderer' -import serviceName from './[serviceName]' export default function ({ service }) { return ( @@ -38,6 +37,8 @@ export default function ({ service }) { export async function getStaticProps({ params }) { const service = await fetchService(params.serviceName) + console.log(service.fields) + return { props: { service: service.fields, diff --git a/pages/suites/index.tsx b/pages/suites/index.tsx index 238e7a2..4d41f5b 100644 --- a/pages/suites/index.tsx +++ b/pages/suites/index.tsx @@ -1,9 +1,263 @@ -// An index Page has to be defined +import Link from 'next/link' +import { fetchServices } from '@/lib/contentful' +import { documentToHtmlString } from '@contentful/rich-text-html-renderer' +import { IconArrowBigRight, IconSearch } from '@tabler/icons' +export default function ({ services }) { -export default function () { - return ( - <> - </> - ) + const filters = [ + { + label: 'Art des Dienstes', + id: 'type', + options: [{ + label: 'Plattformen', + id: 'platform', + },{ + label: 'Basisdienste', + id: '', + value: '', + },{ + label: 'Software', + id: '', + value: '', + },{ + label: 'APIs', + id: '', + value: '', + }] + }, + { + label: 'Use Cases', + id: 'use-case', + options: [{ + label: 'Bezahlsystem', + id: 'platform', + },{ + label: 'Übertragungssystem', + id: '', + value: '', + },{ + label: 'Referenzarchitektur', + id: '', + value: '', + }] + }, + { + label: 'Region', + id: 'region', + options: [{ + label: 'Niedersachsen', + id: 'platform', + },{ + label: 'Baden-Württemberg', + id: '', + value: '', + },{ + label: 'Bayern', + id: '', + value: '', + },{ + label: 'Thüringen', + id: '', + value: '', + },{ + label: 'Hessen', + id: '', + value: '', + },{ + label: 'Nordrhein-Westfalen', + id: '', + value: '', + }] + }, + { + label: 'Status', + id: 'status', + options: [{ + label: 'Produktiv', + id: 'production', + },{ + label: 'Beta', + id: '', + value: '', + },{ + label: 'In Entwicklung', + id: '', + value: '', + }] + } + ] + + + + return ( + <div className="py-10"> + <div className="max-w-3xl mx-auto sm:px-6 lg:max-w-7xl lg:px-8 lg:grid lg:grid-cols-12 lg:gap-8"> + <header + className={ + 'lg:col-start-3 xl:col-start-3 lg:col-span-9 xl:col-span-9' + } + > + <h1> + <span className="mt-1 block text-4xl tracking-tight font-extrabold sm:text-5xl xl:text-7xl"> + <span className="block text-gray-900">Verfügbare Plattformen & Basisdienste</span> + </span> + </h1> + </header> + <div className="hidden lg:block lg:col-span-3 xl:col-span-2"> + <nav + aria-label="Sidebar" + className="sticky top-4 divide-y divide-gray-300" + > + {filters.map((filter) => ( + <div className="pt-10 mt-10" key={filter.id}> + <p + className="px-3 text-xs font-semibold text-gray-500 uppercase tracking-wider" + id={`${filter.id}-headline`} + > + {filter.label} + </p> + <div + className="mt-3 space-y-2" + aria-labelledby={`${filter.id}-headline`} + > + {filter.options.map((option) => ( + <div key={option.value} className="flex items-center"> + <input + id={`${filter.id}-${option.id}`} + name={`${filter.id}[]`} + defaultValue={option.value} + type="checkbox" + className="h-4 w-4 border-gray-300 rounded text-indigo-600 focus:ring-indigo-500" + /> + <label + htmlFor={`${filter.id}-${option.id}`} + className="ml-3 text-sm text-gray-500" + > + {option.label} + </label> + </div> + ))} + </div> + </div> + ))} + </nav> + </div> + <main className="lg:col-span-9 xl:col-span-9"> + {/* + <div className="px-4 sm:px-0"> + <div className="w-full"> + <label htmlFor="search" className="sr-only"> + Durchsuchen + </label> + <div className="relative"> + <div className="pointer-events-none absolute inset-y-0 left-0 pl-3 flex items-center"> + <IconSearch + className="h-5 w-5 text-gray-400" + aria-hidden="true" + /> + </div> + <input + id="search" + name="search" + className="block w-full bg-white border border-gray-300 rounded-md py-2 pl-10 pr-3 text-sm placeholder-gray-500 focus:outline-none focus:text-gray-900 focus:placeholder-gray-400 focus:ring-1 focus:ring-rose-500 focus:border-rose-500 sm:text-sm" + placeholder="Search" + type="search" + /> + </div> + </div> + </div> + */} + <div className="mt-4"> + <h1 className="sr-only">Gelistete Services</h1> + <ul role="list" className="space-y-4"> + {services.map((service, key) => ( + <li + key={key} + className="bg-white px-4 py-6 shadow sm:p-6 sm:rounded-lg" + > + <div aria-labelledby={'service-' + key}> + <div> + <div className="flex space-x-3"> + <div className="flex-shrink-0"> + <img + className="h-10 w-10" + src={service.logo.fields.file.url} + alt={service.logo.fields.name} + /> + </div> + <div className="min-w-0 flex-1"> + <p className="text-sm font-medium text-gray-900"> + <Link + href={`/suites/${service.slug}`} + passHref + > + <a + href={service.developer.fields.link} + className="hover:underline" + > + {service.name} + </a> + </Link> + </p> + <p className="text-sm text-gray-500"> + entwickelt durch {service.developer.fields.name} + </p> + </div> + </div> + </div> + <div + className="mt-2 text-sm text-gray-700 space-y-4" + dangerouslySetInnerHTML={{ + __html: documentToHtmlString(service.shortDescription), + }} + /> + <div className="mt-6 flex justify-end space-x-8"> + <div className="flex text-sm"> + <span className="inline-flex items-center text-sm"> + <Link + href={`/suites/${service.slug}`} + passHref + > + <a className="inline-flex space-x-2 text-gray-400 hover:text-gray-800"> + <span className="font-medium">Mehr</span> + <IconArrowBigRight + className="h-5 w-5" + aria-hidden="true" + /> + </a> + </Link> + </span> + </div> + </div> + </div> + </li> + ))} + </ul> + </div> + </main> + </div> + </div> + ) +} + +export async function getStaticProps(context) { + const services = (await fetchServices()).map((service) => service.fields) + + return { + props: { + services, + }, + } } + + +/* +<a + key={community.name} + href={community.href} + className="group flex items-center px-3 py-2 text-sm font-medium text-gray-600 rounded-md hover:text-gray-900 hover:bg-gray-50" + > + <span className="truncate">{community.name}</span> + </a> + */ diff --git a/views/layout/Navbar.tsx b/views/layout/Navbar.tsx index 32bc721..42e2964 100644 --- a/views/layout/Navbar.tsx +++ b/views/layout/Navbar.tsx @@ -44,14 +44,7 @@ function Navbar({ logo }: NavbarConfig): JSX.Element { <a className={'font-medium text-gray-500 hover:text-gray-900'} > - Komplettlösungen - </a> - </Link> - <Link href={'/services'} passHref> - <a - className={'font-medium text-gray-500 hover:text-gray-900'} - > - Service APIs + Plattformen & Basisdienste </a> </Link> </div> @@ -105,14 +98,7 @@ function Navbar({ logo }: NavbarConfig): JSX.Element { <a className={'font-medium text-gray-500 hover:text-gray-900'} > - Komplettlösungen - </a> - </Link> - <Link href={'/services'} passHref> - <a - className={'font-medium text-gray-500 hover:text-gray-900'} - > - Service APIs + Plattformen & Basisdienste </a> </Link> </div> -- GitLab