feat(microsite-next): Add on demand page with basic styles
Signed-off-by: Carlos Esteban Lopez <lcarlosesteb@vmware.com>
This commit is contained in:
@@ -0,0 +1,17 @@
|
||||
import React from 'react';
|
||||
|
||||
export interface ICardData {
|
||||
header: React.ReactNode;
|
||||
body: React.ReactNode;
|
||||
footer: React.ReactNode;
|
||||
}
|
||||
|
||||
export const SimpleCard = ({ header, body, footer }: ICardData) => (
|
||||
<div className="card">
|
||||
<div className="card__header">{header}</div>
|
||||
|
||||
<div className="card__body">{body}</div>
|
||||
|
||||
<div className="card__footer">{footer}</div>
|
||||
</div>
|
||||
);
|
||||
@@ -0,0 +1,66 @@
|
||||
import Link from '@docusaurus/Link';
|
||||
import { SimpleCard } from '@site/src/components/simpleCard/simpleCard';
|
||||
import React from 'react';
|
||||
|
||||
export interface IOnDemandData {
|
||||
title: string;
|
||||
category: string;
|
||||
description: string;
|
||||
date: string;
|
||||
youtubeUrl: string;
|
||||
youtubeImgUrl: string;
|
||||
rsvpUrl: string;
|
||||
eventUrl: string;
|
||||
}
|
||||
|
||||
export const OnDemandCard = ({
|
||||
title,
|
||||
category,
|
||||
description,
|
||||
date,
|
||||
youtubeUrl,
|
||||
youtubeImgUrl,
|
||||
rsvpUrl,
|
||||
eventUrl,
|
||||
}: IOnDemandData) => (
|
||||
<SimpleCard
|
||||
header={
|
||||
<>
|
||||
<h3>{title}</h3>
|
||||
|
||||
<p className="PluginCardAuthor">on {date}</p>
|
||||
|
||||
<span className="badge badge--primary">{category}</span>
|
||||
|
||||
<img src={youtubeImgUrl} alt={title} />
|
||||
</>
|
||||
}
|
||||
body={<p>{description}</p>}
|
||||
footer={
|
||||
category.toLowerCase() === 'upcoming' ? (
|
||||
<>
|
||||
<Link
|
||||
to={eventUrl}
|
||||
className="button button--outline button--sm button--primary"
|
||||
>
|
||||
Event page
|
||||
</Link>
|
||||
|
||||
<Link
|
||||
to={rsvpUrl}
|
||||
className="button button--outline button--sm button--primary"
|
||||
>
|
||||
Remind me
|
||||
</Link>
|
||||
</>
|
||||
) : (
|
||||
<Link
|
||||
to={youtubeUrl}
|
||||
className="button button--outline button--primary button--block"
|
||||
>
|
||||
Watch on YouTube
|
||||
</Link>
|
||||
)
|
||||
}
|
||||
/>
|
||||
);
|
||||
@@ -0,0 +1,78 @@
|
||||
import Layout from '@theme/Layout';
|
||||
import clsx from 'clsx';
|
||||
import React from 'react';
|
||||
|
||||
import { IOnDemandData, OnDemandCard } from './_onDemandCard';
|
||||
import pluginsStyles from './onDemand.module.scss';
|
||||
import { truncateDescription } from '@site/src/util/truncateDescription';
|
||||
import Link from '@docusaurus/Link';
|
||||
|
||||
//#region Plugin data import
|
||||
const onDemandContext = require.context(
|
||||
'../../../../microsite/data/on-demand',
|
||||
false,
|
||||
/\.ya?ml/,
|
||||
);
|
||||
|
||||
const onDemandData = onDemandContext.keys().reduce(
|
||||
(acum, id) => {
|
||||
const pluginData: IOnDemandData = onDemandContext(id).default;
|
||||
|
||||
acum[
|
||||
pluginData.category === 'Upcoming' ? 'upcomingEvents' : 'onDemandEvents'
|
||||
].push(truncateDescription(pluginData));
|
||||
|
||||
return acum;
|
||||
},
|
||||
{
|
||||
upcomingEvents: [] as IOnDemandData[],
|
||||
onDemandEvents: [] as IOnDemandData[],
|
||||
},
|
||||
);
|
||||
//#endregion
|
||||
|
||||
const Plugins = () => (
|
||||
<Layout>
|
||||
<div
|
||||
className={clsx('container', 'padding--lg', pluginsStyles.onDemandPage)}
|
||||
>
|
||||
<div className="marketplaceBanner">
|
||||
<div className="marketplaceContent">
|
||||
<h2>Community sessions</h2>
|
||||
|
||||
<p>
|
||||
Upcoming events and recorded sessions about updates, demos and
|
||||
discussions.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<Link
|
||||
to="/docs/overview/support"
|
||||
className="button button--outline button--primary"
|
||||
>
|
||||
Add an event or recording
|
||||
</Link>
|
||||
</div>
|
||||
|
||||
<div className="bulletLine margin-bottom--lg"></div>
|
||||
|
||||
<h2>Upcoming live events</h2>
|
||||
|
||||
<div className="cardsContainer margin-bottom--lg">
|
||||
{onDemandData.upcomingEvents.map(eventData => (
|
||||
<OnDemandCard key={eventData.title} {...eventData}></OnDemandCard>
|
||||
))}
|
||||
</div>
|
||||
|
||||
<h2>Community on demand</h2>
|
||||
|
||||
<div className="cardsContainer margin-bottom--lg">
|
||||
{onDemandData.onDemandEvents.map(eventData => (
|
||||
<OnDemandCard key={eventData.title} {...eventData}></OnDemandCard>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</Layout>
|
||||
);
|
||||
|
||||
export default Plugins;
|
||||
@@ -0,0 +1,44 @@
|
||||
.onDemandPage {
|
||||
:global(.marketplaceBanner) {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
:global(.marketplaceContent) {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
:global(.card) {
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
:global(.card .card__header) {
|
||||
display: grid;
|
||||
row-gap: 0.25rem;
|
||||
column-gap: 1rem;
|
||||
justify-items: start;
|
||||
|
||||
> * {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
:global(img) {
|
||||
width: 250px;
|
||||
max-width: 100%;
|
||||
justify-self: center;
|
||||
}
|
||||
}
|
||||
|
||||
:global(.card .card__footer) {
|
||||
gap: 1rem;
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(100px, 1fr));
|
||||
}
|
||||
|
||||
:global(.cardsContainer) {
|
||||
gap: 1rem;
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
|
||||
justify-items: start;
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
import Link from '@docusaurus/Link';
|
||||
import { SimpleCard } from '@site/src/components/simpleCard/simpleCard';
|
||||
import React from 'react';
|
||||
|
||||
export interface IPluginData {
|
||||
@@ -23,32 +24,30 @@ export const PluginCard = ({
|
||||
iconUrl,
|
||||
title,
|
||||
}: IPluginData) => (
|
||||
<div className="card">
|
||||
<div className="card__header">
|
||||
<img src={iconUrl || defaultIconUrl} alt={title} />
|
||||
<SimpleCard
|
||||
header={
|
||||
<>
|
||||
<img src={iconUrl || defaultIconUrl} alt={title} />
|
||||
|
||||
<h3>{title}</h3>
|
||||
<h3>{title}</h3>
|
||||
|
||||
<p className="PluginCardAuthor">
|
||||
by <a href={authorUrl}>{author}</a>
|
||||
</p>
|
||||
<p className="PluginCardAuthor">
|
||||
by <a href={authorUrl}>{author}</a>
|
||||
</p>
|
||||
|
||||
<span className="button button--sm button--outline button--primary">
|
||||
{category}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div className="card__body">
|
||||
<p>{description}</p>
|
||||
</div>
|
||||
|
||||
<div className="card__footer">
|
||||
<span className="button button--sm button--outline button--primary">
|
||||
{category}
|
||||
</span>
|
||||
</>
|
||||
}
|
||||
body={<p>{description}</p>}
|
||||
footer={
|
||||
<Link
|
||||
to={documentation}
|
||||
className="button button--outline button--primary button--block"
|
||||
>
|
||||
Explore
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
/>
|
||||
);
|
||||
|
||||
@@ -5,18 +5,9 @@ import React from 'react';
|
||||
|
||||
import { IPluginData, PluginCard } from './_pluginCard';
|
||||
import pluginsStyles from './plugins.module.scss';
|
||||
import { truncateDescription } from '@site/src/util/truncateDescription';
|
||||
|
||||
//#region Plugin data import
|
||||
const maxDescLength = 160;
|
||||
|
||||
const truncatePluginDescription = (pluginData: IPluginData) =>
|
||||
pluginData.description.length > maxDescLength
|
||||
? {
|
||||
...pluginData,
|
||||
description: pluginData.description.slice(0, maxDescLength) + '...',
|
||||
}
|
||||
: pluginData;
|
||||
|
||||
const pluginsContext = require.context(
|
||||
'../../../../microsite/data/plugins',
|
||||
false,
|
||||
@@ -29,7 +20,7 @@ const plugins = pluginsContext.keys().reduce(
|
||||
|
||||
acum[
|
||||
pluginData.category === 'Core Feature' ? 'corePlugins' : 'otherPlugins'
|
||||
].push(truncatePluginDescription(pluginData));
|
||||
].push(truncateDescription(pluginData));
|
||||
|
||||
return acum;
|
||||
},
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
export const maxDescLength = 160;
|
||||
|
||||
export const truncateDescription = <T extends { description: string }>(
|
||||
itemData: T,
|
||||
) =>
|
||||
itemData.description.length > maxDescLength
|
||||
? {
|
||||
...itemData,
|
||||
description: itemData.description.slice(0, maxDescLength) + '...',
|
||||
}
|
||||
: itemData;
|
||||
Reference in New Issue
Block a user