Merge pull request #27705 from autodesk-forks/nikolarAutodesk/contribfestHomePageQuickStart

[plugins/home] Add Home Page Quick Start Card
This commit is contained in:
Patrik Oldsberg
2024-11-29 11:01:28 +01:00
committed by GitHub
11 changed files with 434 additions and 0 deletions
+44
View File
@@ -0,0 +1,44 @@
---
'@backstage/plugin-home': patch
---
Added a new Quick Start Card to `plugin-home`, which can display basic info to get users the info they need to onboard to the Catalog.
```
import { QuickStartCard } from '@backstage/plugin-home';
<QuickStartCard
title="Onboarding to the Catalog"
modalTitle="Onboarding Quick Start"
docsLinkTitle="Learn more with getting started docs"
docsLink="https://backstage.io/docs/getting-started"
image={
<img
src={ContentImage}
alt="quick start"
width="100%"
height="100%"
/>
}
cardDescription="Backstage system model will help you create new entities"
video={
<video
controls
preload="auto"
poster={"./videoPoster.png"}
>
<source src={"OnboardingDemo.mp4"} type="video/mp4" />
</video>
}
downloadImage={
<Button
href={QuickStartPDF}
target={'_blank'}
download={true}
>
Download infographic button
</Button>
}
/>
```
See the [storybook examples](https://backstage.io/storybook/?path=/story/plugins-home-components-quickstartcard--default)
+11
View File
@@ -187,6 +187,17 @@ export type LayoutConfiguration = {
// @public
export type Operators = '<' | '<=' | '==' | '!=' | '>' | '>=' | 'contains';
// @public
export type QuickStartCardProps = {
modalTitle?: string | React_2.JSX.Element;
docsLinkTitle?: string;
docsLink?: string;
video?: React_2.JSX.Element;
image: React_2.JSX.Element;
cardDescription?: string;
downloadImage?: React_2.JSX.Element;
};
// @public @deprecated (undocumented)
export type RendererProps = RendererProps_2;
@@ -0,0 +1,69 @@
/*
* Copyright 2022 The Backstage Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { Content } from './Content';
import React from 'react';
import userEvent from '@testing-library/user-event';
import { renderInTestApp } from '@backstage/test-utils';
import ContentImage from './static/backstageSystemModel.png';
describe('<QuickStartCard />', () => {
const renderContent = async () => {
return await renderInTestApp(
<Content
image={
<img
src={ContentImage}
data-testid="quick-start-image"
alt="quick start"
width="100%"
height="100%"
/>
}
docsLinkTitle="Testing docs link"
/>,
);
};
it('should have expected card content', async () => {
const { getByTestId } = await renderContent();
const docsLink = getByTestId('quick-start-link-to-docs');
expect(docsLink).toHaveTextContent('Testing docs link');
expect(docsLink).toHaveAttribute('target', '_blank');
});
it('clicking the link opens the modal', async () => {
const { getByTestId, getByText } = await renderContent();
// Find the link element
const link = getByText('Onboarding');
// Simulate a click event on the link
await userEvent.click(link);
// Assert that the modal is visible
const modal = getByTestId('content-modal-open');
expect(modal).toBeVisible();
});
it('clicking the image opens the modal', async () => {
const { getByTestId } = await renderContent();
// Find the link element
const link = getByTestId('quick-start-image');
// Simulate a click event on the link
await userEvent.click(link);
// Assert that the modal is visible
const modal = getByTestId('content-modal-open');
expect(modal).toBeVisible();
});
});
@@ -0,0 +1,84 @@
/*
* Copyright 2022 The Backstage Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import React from 'react';
import { Link } from '@backstage/core-components';
import Typography from '@material-ui/core/Typography';
import Grid from '@material-ui/core/Grid';
import { ContentModal } from './ContentModal';
import { useStyles } from './styles';
/**
* Props customizing the <QuickStartCard/> component.
*
* @public
*/
export type QuickStartCardProps = {
/** The modal link title */
modalTitle?: string | React.JSX.Element;
/** The link to docs title */
docsLinkTitle?: string;
/** The link to docs */
docsLink?: string;
/** The video to play on the card */
video?: React.JSX.Element;
/** A quickstart image to display on the card */
image: React.JSX.Element;
/** The card description*/
cardDescription?: string;
/** A component used to download a quickStart image*/
downloadImage?: React.JSX.Element;
};
/**
* A component to display Quick Start info on the homepage.
*
* @public
*/
export const Content = (props: QuickStartCardProps): JSX.Element => {
const styles = useStyles();
return (
<>
<ContentModal
modalContent={props.image}
linkContent={props.modalTitle || 'Onboarding'}
/>
<Typography variant="body1" paragraph>
{props.cardDescription || 'Get started with Backstage'}
</Typography>
<ContentModal modalContent={props.image} linkContent={props.image} />
<Grid
container
alignItems="center"
className={styles.contentActionContainer}
>
{props.downloadImage && <Grid item>{props.downloadImage}</Grid>}
<Grid item>
<Link
to={props.docsLink || 'https://backstage.io/docs/getting-started/'}
data-testid="quick-start-link-to-docs"
underline="none"
variant="h6"
className={styles.link}
>
{props.docsLinkTitle || 'Learn more'}
</Link>
</Grid>
</Grid>
{props.video && props.video}
</>
);
};
@@ -0,0 +1,57 @@
/*
* Copyright 2022 The Backstage Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import React, { useState } from 'react';
import { Link } from '@backstage/core-components';
import Modal from '@material-ui/core/Modal';
import Box from '@material-ui/core/Box';
import { useStyles } from './styles';
export type ContentModalProps = {
modalContent: React.JSX.Element;
linkContent: string | React.JSX.Element;
};
export const ContentModal = (props: ContentModalProps) => {
const { modalContent, linkContent } = props;
const styles = useStyles();
const [open, setOpen] = useState(false);
return (
<div className={styles.linkText} data-testid="content-modal-container">
<Link
to="#"
component="button"
variant="h6"
underline="none"
onClick={() => setOpen(true)}
>
{linkContent}
</Link>
<Modal
open={open}
onClose={() => setOpen(false)}
aria-labelledby="content-modal"
data-testid="content-modal"
>
<Box className={styles.contentModal} data-testid="content-modal-open">
{modalContent}
</Box>
</Modal>
</div>
);
};
@@ -0,0 +1,67 @@
/*
* Copyright 2022 The Backstage Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { QuickStartCard } from '../../plugin';
import React, { ComponentType, PropsWithChildren } from 'react';
import { wrapInTestApp } from '@backstage/test-utils';
import Grid from '@material-ui/core/Grid';
import ContentImage from './static/backstageSystemModel.png';
export default {
title: 'Plugins/Home/Components/QuickStartCard',
decorators: [
(Story: ComponentType<PropsWithChildren<{}>>) => wrapInTestApp(<Story />),
],
};
export const Default = () => {
return (
<Grid item xs={12} md={6}>
<QuickStartCard
image={
<img
src={ContentImage}
alt="quick start"
width="100%"
height="100%"
/>
}
/>
</Grid>
);
};
export const Customized = () => {
return (
<Grid item xs={12} md={6}>
<QuickStartCard
title="Onboarding to the Catalog"
modalTitle="Onboarding Quick Start"
docsLinkTitle="Learn more with getting started docs"
docsLink="https://backstage.io/docs/getting-started"
image={
<img
src={ContentImage}
alt="quick start"
width="100%"
height="100%"
/>
}
cardDescription="Backstage system model will help you create new entities"
/>
</Grid>
);
};
@@ -0,0 +1,19 @@
/*
* Copyright 2022 The Backstage Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
export { Content } from './Content';
export type { QuickStartCardProps } from './Content';
export type { QuickStartCardClassKey } from './styles';
Binary file not shown.

After

Width:  |  Height:  |  Size: 269 KiB

@@ -0,0 +1,68 @@
/*
* Copyright 2022 The Backstage Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { makeStyles, Theme } from '@material-ui/core/styles';
/** @public */
export type QuickStartCardClassKey =
| 'cardTitleIcon'
| 'contentActionContainer'
| 'contentModal'
| 'imageSize'
| 'link'
| 'linkText'
| 'videoContainer';
export const useStyles = makeStyles(
(theme: Theme) => ({
cardTitleIcon: {
verticalAlign: 'bottom',
marginLeft: '-4px',
},
contentActionContainer: {
marginTop: theme.spacing(1.5),
marginBottom: theme.spacing(1.5),
},
contentModal: {
position: 'absolute',
top: '50%',
left: '50%',
transform: 'translate(-50%, -50%)',
width: '80%',
height: 'auto',
},
imageSize: { width: '100%', height: '100%' },
link: {
display: 'inline-flex',
alignItems: 'center',
textDecoration: 'none',
color: `${theme.palette.link}`,
'&:hover': {
background: 'transparent',
},
},
linkText: {
marginBottom: theme.spacing(1.5),
},
videoContainer: {
borderRadius: '10px',
width: '100%',
height: 'auto',
background: `${theme.palette.background.default}`,
},
}),
{ name: 'HomeQuickStartCard' },
);
@@ -20,3 +20,4 @@ export type { WelcomeTitleLanguageProps } from './WelcomeTitle';
export type { VisitedByTypeProps, VisitedByTypeKind } from './VisitedByType';
export type { FeaturedDocsCardProps } from './FeaturedDocsCard';
export type { StarredEntitiesProps } from './StarredEntities';
export type { QuickStartCardProps } from './QuickStart';
+14
View File
@@ -27,6 +27,7 @@ import {
ToolkitContentProps,
VisitedByTypeProps,
FeaturedDocsCardProps,
QuickStartCardProps,
} from './homePageComponents';
import { rootRouteRef } from './routes';
import { VisitsStorageApi, visitsApiRef } from './api';
@@ -230,3 +231,16 @@ export const FeaturedDocsCard = homePlugin.provide(
components: () => import('./homePageComponents/FeaturedDocsCard'),
}),
);
/**
* A component to display Quick Start information.
*
* @public
*/
export const QuickStartCard = homePlugin.provide(
createCardExtension<QuickStartCardProps>({
name: 'QuickStartCard',
title: 'Quick Start',
components: () => import('./homePageComponents/QuickStart'),
}),
);