-
-
Notifications
You must be signed in to change notification settings - Fork 750
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Co-authored-by: Akshat Nema <[email protected]>
- Loading branch information
1 parent
bd230d2
commit 727dfb4
Showing
2 changed files
with
377 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,259 @@ | ||
import Link from 'next/link'; | ||
import type { MDXRemoteSerializeResult } from 'next-mdx-remote'; | ||
import { MDXRemote } from 'next-mdx-remote'; | ||
import { serialize } from 'next-mdx-remote/serialize'; | ||
|
||
import type { ICaseStudy } from '@/types/post'; | ||
import { HeadingTypeStyle } from '@/types/typography/Heading'; | ||
import { ParagraphTypeStyle } from '@/types/typography/Paragraph'; | ||
|
||
import CaseTOC from '../../components/CaseTOC'; | ||
import GenericLayout from '../../components/layout/GenericLayout'; | ||
import { getMDXComponents } from '../../components/MDX'; | ||
import Heading from '../../components/typography/Heading'; | ||
import Paragraph from '../../components/typography/Paragraph'; | ||
import CaseStudiesList from '../../config/case-studies.json'; | ||
import { generateCaseStudyContent } from '../../utils/staticHelpers'; | ||
|
||
interface IndexProps { | ||
casestudy: ICaseStudy; | ||
challenges: MDXRemoteSerializeResult; | ||
solution: MDXRemoteSerializeResult; | ||
usecase: MDXRemoteSerializeResult; | ||
architecture: MDXRemoteSerializeResult; | ||
testing: MDXRemoteSerializeResult; | ||
codegen: MDXRemoteSerializeResult; | ||
schemaStorage: MDXRemoteSerializeResult; | ||
registry: MDXRemoteSerializeResult; | ||
versioning: MDXRemoteSerializeResult; | ||
validation: MDXRemoteSerializeResult; | ||
asyncapiStorage: MDXRemoteSerializeResult; | ||
asyncapiEditing: MDXRemoteSerializeResult; | ||
asyncapiExtensions: MDXRemoteSerializeResult; | ||
asyncapiDocumentation: MDXRemoteSerializeResult; | ||
asyncapiBindings: MDXRemoteSerializeResult; | ||
asyncapiTools: MDXRemoteSerializeResult; | ||
additionalResources: MDXRemoteSerializeResult; | ||
} | ||
|
||
const renderContent = ( | ||
content: any[], | ||
allComponents: Record<string, React.ComponentType<any>>, | ||
level: number | ||
): JSX.Element[] => { | ||
let typeStyle; | ||
|
||
if (level === 0) { | ||
typeStyle = HeadingTypeStyle.lg; | ||
} else if (level === 1) { | ||
typeStyle = HeadingTypeStyle.md; | ||
} else { | ||
typeStyle = HeadingTypeStyle.sm; | ||
} | ||
|
||
return content.map((item) => { | ||
return ( | ||
<div className='mt-10' key={item.title}> | ||
<Heading | ||
typeStyle={typeStyle} | ||
className='mt-8' | ||
id={item.title | ||
.replace(/<|>|"|\\|\/|=/gi, '') | ||
.replace(/\s/gi, '-') | ||
.toLowerCase()} | ||
> | ||
{item.title} | ||
</Heading> | ||
{item.content && ( | ||
<Paragraph typeStyle={ParagraphTypeStyle.md} className='my-4'> | ||
<MDXRemote {...item.content} components={allComponents} /> | ||
</Paragraph> | ||
)} | ||
{item.items && ( | ||
<div className='mt-4 items-center'> | ||
<div className='flex flex-wrap gap-2'> | ||
{item.items.map((subItem: string) => ( | ||
<span | ||
key={subItem} | ||
className='rounded-md border border-green-600 bg-green-100 p-1 text-center text-xs text-green-600 ' | ||
> | ||
{subItem} | ||
</span> | ||
))} | ||
</div> | ||
{item.children && renderContent(item.children, allComponents, level + 1)} | ||
</div> | ||
)} | ||
</div> | ||
); | ||
}); | ||
}; | ||
|
||
/** | ||
* @description Fetches static props for the page. | ||
* @param {object} params - Parameters object containing the id. | ||
* @param {string} params.id - The id of the case study.. | ||
*/ | ||
export async function getStaticProps({ params }: { params: { id: string } }) { | ||
const data = CaseStudiesList.filter((p: { id: string }) => p.id === params.id); | ||
|
||
return { | ||
props: { | ||
casestudy: data[0], | ||
challenges: await serialize(data[0].challenges), | ||
solution: await serialize(data[0].solution), | ||
usecase: await serialize(data[0].asyncapi.usecase), | ||
architecture: await serialize(data[0].technical.architecture), | ||
testing: await serialize(data[0].technical.testing), | ||
codegen: await serialize(data[0].technical.codegen), | ||
schemaStorage: await serialize(data[0].schemas.storage), | ||
registry: await serialize(data[0].schemas.registry), | ||
versioning: await serialize(data[0].schemas.versioning), | ||
validation: await serialize(data[0].schemas.validation), | ||
asyncapiStorage: await serialize(data[0].asyncapi.storage), | ||
asyncapiEditing: await serialize(data[0].asyncapi.editing), | ||
asyncapiExtensions: await serialize(data[0].asyncapi.extensions), | ||
asyncapiDocumentation: await serialize(data[0].asyncapi.documentation), | ||
asyncapiBindings: await serialize(data[0].asyncapi.bindings), | ||
asyncapiTools: await serialize(data[0].asyncapi.tools), | ||
additionalResources: await serialize(data[0].additionalResources) | ||
} | ||
}; | ||
} | ||
|
||
/** | ||
* @description Retrieves the static paths for the page. | ||
*/ | ||
export async function getStaticPaths() { | ||
const paths = CaseStudiesList.map((study: { id: string }) => ({ | ||
params: { id: study.id } | ||
})); | ||
|
||
return { | ||
paths, | ||
fallback: false | ||
}; | ||
} | ||
|
||
const Index: React.FC<IndexProps> = ({ | ||
casestudy, | ||
challenges, | ||
solution, | ||
architecture, | ||
testing, | ||
codegen, | ||
usecase, | ||
schemaStorage, | ||
registry, | ||
versioning, | ||
validation, | ||
asyncapiStorage, | ||
asyncapiEditing, | ||
asyncapiExtensions, | ||
asyncapiDocumentation, | ||
asyncapiBindings, | ||
asyncapiTools, | ||
additionalResources | ||
}) => { | ||
const image = '/img/social/website-card.png'; | ||
const allComponents = getMDXComponents(); | ||
const contacts = casestudy.company.contact; | ||
|
||
const content = generateCaseStudyContent({ | ||
challenges, | ||
solution, | ||
usecase, | ||
architecture, | ||
testing, | ||
codegen, | ||
schemaStorage, | ||
registry, | ||
versioning, | ||
validation, | ||
asyncapiStorage, | ||
asyncapiEditing, | ||
asyncapiExtensions, | ||
asyncapiDocumentation, | ||
asyncapiBindings, | ||
asyncapiTools, | ||
additionalResources, | ||
casestudy | ||
}); | ||
|
||
return ( | ||
<GenericLayout | ||
title='AsyncAPI Case Studies' | ||
description='The home for all case studies related to AsyncAPI.' | ||
image={image} | ||
hideBanner={true} | ||
wide | ||
> | ||
<div className='max-w-screen lg:flex lg:flex-row-reverse lg:justify-between'> | ||
<CaseTOC | ||
toc={content} | ||
cssBreakingPoint='lg' | ||
className='sticky top-20 mt-4 max-h-screen overflow-y-auto bg-blue-100 p-4 lg:top-24 lg:-mr-14 lg:mt-2 lg:max-h-(screen-16) lg:min-w-[265px] lg:max-w-72 lg:flex-1 lg:border-l lg:border-gray-200 lg:bg-transparent lg:pb-8 lg:pt-0' | ||
/> | ||
<div className='case-study px-4 sm:px-6 lg:max-w-[812px] lg:flex-1 xl:max-w-5xl xl:px-0'> | ||
<div className='mt-10 flex flex-col items-center justify-between md:mt-20 md:flex-row'> | ||
<div className='w-full md:w-[65%]'> | ||
<Heading typeStyle={HeadingTypeStyle.xl} className='countdown-text-gradient'> | ||
{casestudy.company.name} | ||
</Heading> | ||
<div className='flex flex-wrap gap-1' id='Contacts'> | ||
{contacts.map((item, index) => ( | ||
<div key={index}> | ||
<Heading typeStyle={HeadingTypeStyle.bodyLg}> | ||
<Link | ||
href={item.link} | ||
className='text-md font-medium leading-5 text-gray-900 hover:underline' | ||
target='_blank' | ||
> | ||
<span> | ||
{item.name} | ||
{index !== contacts.length - 1 && ', '} | ||
</span> | ||
</Link> | ||
</Heading> | ||
</div> | ||
))} | ||
</div> | ||
<div className='mt-4 flex flex-wrap gap-2'> | ||
<span className='rounded-md border border-green-600 bg-green-100 p-1 text-center text-xs text-green-600 '> | ||
Industry: {casestudy.company.industry} | ||
</span> | ||
<span className='rounded-md border border-green-600 bg-green-100 p-1 text-center text-xs text-green-600 '> | ||
Customers: {casestudy.company.customers} | ||
</span> | ||
<span className='rounded-md border border-green-600 bg-green-100 p-1 text-center text-xs text-green-600 '> | ||
Revenue: {casestudy.company.revenue} | ||
</span> | ||
</div> | ||
<div className='mt-10'> | ||
<Heading typeStyle={HeadingTypeStyle.bodyLg}>{casestudy.company.description}</Heading> | ||
<Heading className='mt-10' typeStyle={HeadingTypeStyle.bodyLg}> | ||
tl;dr just go and have a look at | ||
<Link | ||
href={`/${casestudy.asyncapi.fullExample}`} | ||
className='ml-2 font-medium text-secondary-500 underline transition duration-300 ease-in-out hover:text-gray-800' | ||
target='_blank' | ||
> | ||
full production-used AsyncAPI document | ||
</Link> | ||
</Heading> | ||
</div> | ||
</div> | ||
<img | ||
src={casestudy.company.logo} | ||
alt={casestudy.company.name} | ||
className='mx-auto mt-5 w-[250px] rounded-lg md:mt-0' | ||
/> | ||
</div> | ||
{renderContent(content, allComponents, 0)} | ||
</div> | ||
</div> | ||
</GenericLayout> | ||
); | ||
}; | ||
|
||
export default Index; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,118 @@ | ||
import type { ICaseStudies } from '@/types/post'; | ||
import { HeadingLevel, HeadingTypeStyle } from '@/types/typography/Heading'; | ||
import { ParagraphTypeStyle } from '@/types/typography/Paragraph'; | ||
|
||
import CaseStudyCard from '../../components/CaseStudyCard'; | ||
import GenericLayout from '../../components/layout/GenericLayout'; | ||
import Heading from '../../components/typography/Heading'; | ||
import Paragraph from '../../components/typography/Paragraph'; | ||
import TextLink from '../../components/typography/TextLink'; | ||
import AdoptersList from '../../config/adopters.json'; | ||
import CaseStudiesList from '../../config/case-studies.json'; | ||
|
||
interface Resource { | ||
title: string; | ||
link: string; | ||
} | ||
|
||
interface Adopter { | ||
companyName: string; | ||
useCase: string; | ||
resources: Resource[]; | ||
} | ||
|
||
/** | ||
* @description Renders the Case Studies page. | ||
*/ | ||
export default function Casestudies() { | ||
const description: string = 'Learn about different case studies based on AsyncAPI spec and related tools.'; | ||
const image: string = '/img/social/case-studies.webp'; | ||
const title: string = 'Case Studies'; | ||
|
||
return ( | ||
<GenericLayout title={title} description={description} image={image} wide> | ||
<div | ||
className='relative mx-auto max-w-xl px-4 py-10 sm:px-6 lg:max-w-screen-xl lg:px-8' | ||
data-testid='CaseStudy-main' | ||
> | ||
<div className='grid lg:grid-cols-9 lg:gap-8 lg:text-center'> | ||
<div className='col-span-5 col-start-3'> | ||
<Heading level={HeadingLevel.h1} typeStyle={HeadingTypeStyle.lg}> | ||
{title} | ||
</Heading> | ||
<Paragraph typeStyle={ParagraphTypeStyle.md} className='my-4 max-w-4xl'> | ||
The best way to learn how to use AsyncAPI is not only through documentation that usually is focused on | ||
recommendations and best practices. It is also good to confront with real-life case studies that explain | ||
how people really use AsyncAPI and what are their flows. | ||
</Paragraph> | ||
<Paragraph typeStyle={ParagraphTypeStyle.md} className='my-4 max-w-4xl'> | ||
Feel free to submit your case study. We have a template for you. For more details | ||
<TextLink href='https://github.com/asyncapi/website/blob/master/README.md#case-studies' target='_blank'> | ||
read our FAQ | ||
</TextLink> | ||
. | ||
</Paragraph> | ||
</div> | ||
</div> | ||
<div data-testid='CaseStudy-card'> | ||
<CaseStudyCard studies={CaseStudiesList as ICaseStudies} /> | ||
</div> | ||
|
||
<div className='adopters'> | ||
<div className='mt-8 grid lg:grid-cols-9 lg:gap-8 lg:text-center'> | ||
<div className='col-span-5 col-start-3'> | ||
<Heading level={HeadingLevel.h1} typeStyle={HeadingTypeStyle.lg}> | ||
Adopters | ||
</Heading> | ||
<Paragraph typeStyle={ParagraphTypeStyle.md} className='my-4 max-w-4xl'> | ||
Check out how different companies use AsyncAPI and what problems they solve. | ||
</Paragraph> | ||
<Paragraph typeStyle={ParagraphTypeStyle.md} className='my-4 max-w-4xl'> | ||
Feel free to{' '} | ||
<a className='underline' href='https://github.com/asyncapi/website/blob/master/config/adopters.yml'> | ||
submit a pull request | ||
</a>{' '} | ||
with information about how your company uses AsyncAPI. We know that writing an official case study might | ||
be time consuming and requires too much internal paper work. Let's make sure we can at least | ||
capture a use case that is already a great learning information for the community. | ||
</Paragraph> | ||
</div> | ||
</div> | ||
</div> | ||
|
||
<center> | ||
<div className='overflow-x-auto'> | ||
<table className='my-8 w-full max-w-full border-collapse border'> | ||
<thead> | ||
<tr> | ||
<th className='border p-2 font-bold'>Company name</th> | ||
<th className='border-2 p-2 font-bold'>Use Case</th> | ||
<th className='border-2 p-2 font-bold'>Resources</th> | ||
</tr> | ||
</thead> | ||
<tbody> | ||
{AdoptersList.map((entry: Adopter, index: number) => ( | ||
<tr key={index} data-testid='Adopters'> | ||
<td className='border-2 p-2'>{entry.companyName}</td> | ||
<td className='border-2 p-2'>{entry.useCase}</td> | ||
<td className='border-2 p-2'> | ||
<ul> | ||
{entry.resources.map((resource: Resource, resourceIndex: number) => ( | ||
<li className='p-2' key={resourceIndex}> | ||
<a className='text-cyan-500 underline' href={resource.link}> | ||
{resource.title} | ||
</a> | ||
</li> | ||
))} | ||
</ul> | ||
</td> | ||
</tr> | ||
))} | ||
</tbody> | ||
</table> | ||
</div> | ||
</center> | ||
</div> | ||
</GenericLayout> | ||
); | ||
} |