diff --git a/plugins/home/src/homePageComponents/QuickStart/Content.test.tsx b/plugins/home/src/homePageComponents/QuickStart/Content.test.tsx new file mode 100644 index 0000000000..9a923f2481 --- /dev/null +++ b/plugins/home/src/homePageComponents/QuickStart/Content.test.tsx @@ -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 { Content } from './Content'; +import React from 'react'; +import { catalogApiRef, entityRouteRef } from '@backstage/plugin-catalog-react'; +import { renderInTestApp, TestApiProvider } from '@backstage/test-utils'; +import { catalogApiMock } from '@backstage/plugin-catalog-react/testUtils'; + +const docsEntities = [ + { + apiVersion: '1', + kind: 'Location', + metadata: { + name: 'getting-started-with-idp', + title: 'Getting Started Docs', + }, + spec: { + type: 'documentation', + }, + }, +]; + +describe('', () => { + const Wrapper = ({ children }: { children?: React.ReactNode }) => ( + + {children} + + ); + + it('should show expected featured doc and title', async () => { + const { getByTestId, getByText } = await renderInTestApp( + + + , + { + mountedRoutes: { + '/home': entityRouteRef, + }, + }, + ); + const docsCardContent = getByTestId('docs-card-content'); + const docsEntity = getByText('getting-started-with-idp'); + expect(docsCardContent).toContainElement(docsEntity); + }); +}); diff --git a/plugins/home/src/homePageComponents/QuickStart/Content.tsx b/plugins/home/src/homePageComponents/QuickStart/Content.tsx new file mode 100644 index 0000000000..f6c103a1fc --- /dev/null +++ b/plugins/home/src/homePageComponents/QuickStart/Content.tsx @@ -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 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 ( + <> + + + {props.cardDescription || "Get started with Backstage's Catalog"} + + + + {props.downloadImage && {props.downloadImage}} + + + {props.docsLinkTitle || 'Learn more'} + + + + {props.video && props.video} + + ); +}; diff --git a/plugins/home/src/homePageComponents/QuickStart/ContentModal.tsx b/plugins/home/src/homePageComponents/QuickStart/ContentModal.tsx new file mode 100644 index 0000000000..dc3addfea1 --- /dev/null +++ b/plugins/home/src/homePageComponents/QuickStart/ContentModal.tsx @@ -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 Props = { + modalContent: React.JSX.Element; + linkContent: string | React.JSX.Element; +}; + +export const ContentModal = (props: Props) => { + const { modalContent, linkContent } = props; + const styles = useStyles(); + const [open, setOpen] = useState(false); + + return ( +
+ setOpen(true)} + > + {linkContent} + + setOpen(false)} + aria-labelledby="content-modal" + data-cy="content-modal" + > + + {modalContent} + + +
+ ); +}; diff --git a/plugins/home/src/homePageComponents/QuickStart/QuickStart.stories.tsx b/plugins/home/src/homePageComponents/QuickStart/QuickStart.stories.tsx new file mode 100644 index 0000000000..7211ecf368 --- /dev/null +++ b/plugins/home/src/homePageComponents/QuickStart/QuickStart.stories.tsx @@ -0,0 +1,72 @@ +/* + * 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, TestApiProvider } 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>) => + wrapInTestApp( + + + , + ), + ], +}; + +export const Default = () => { + return ( + + + } + /> + + ); +}; + +export const Customized = () => { + return ( + + + } + cardDescription="Backstage system model will help you create new entities" + /> + + ); +}; diff --git a/plugins/home/src/homePageComponents/QuickStart/index.ts b/plugins/home/src/homePageComponents/QuickStart/index.ts new file mode 100644 index 0000000000..2c2e0ed2f2 --- /dev/null +++ b/plugins/home/src/homePageComponents/QuickStart/index.ts @@ -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'; diff --git a/plugins/home/src/homePageComponents/QuickStart/static/backstageSystemModel.png b/plugins/home/src/homePageComponents/QuickStart/static/backstageSystemModel.png new file mode 100644 index 0000000000..ad784060bb Binary files /dev/null and b/plugins/home/src/homePageComponents/QuickStart/static/backstageSystemModel.png differ diff --git a/plugins/home/src/homePageComponents/QuickStart/styles.ts b/plugins/home/src/homePageComponents/QuickStart/styles.ts new file mode 100644 index 0000000000..203b84f244 --- /dev/null +++ b/plugins/home/src/homePageComponents/QuickStart/styles.ts @@ -0,0 +1,61 @@ +/* + * 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 = 'link' | 'contentActionContainer'; + +export const useStyles = makeStyles( + (theme: Theme) => ({ + link: { + display: 'inline-flex', + alignItems: 'center', + textDecoration: 'none', + color: `${theme.palette.link}!important`, + '&:hover': { + background: 'transparent!important', + }, + }, + linkText: { + marginBottom: theme.spacing(1.5), + }, + contentActionContainer: { + marginTop: theme.spacing(1.5), + marginBottom: theme.spacing(1.5), + }, + cardTitleIcon: { + verticalAlign: 'bottom', + marginLeft: '-4px', + }, + videoContainer: { + borderRadius: '10px', + width: '100%', + height: 'auto', + background: '#000000', + }, + imageSize: { width: '100%', height: '100%' }, + contentModal: { + position: 'absolute', + top: '50%', + left: '50%', + transform: 'translate(-50%, -50%)', + width: '80%', + height: 'auto', + }, + }), + { name: 'HomeQuickStartCard' }, +); diff --git a/plugins/home/src/homePageComponents/index.ts b/plugins/home/src/homePageComponents/index.ts index e260982e8e..f2eb39b070 100644 --- a/plugins/home/src/homePageComponents/index.ts +++ b/plugins/home/src/homePageComponents/index.ts @@ -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'; diff --git a/plugins/home/src/plugin.ts b/plugins/home/src/plugin.ts index c3fa938197..6892db2231 100644 --- a/plugins/home/src/plugin.ts +++ b/plugins/home/src/plugin.ts @@ -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({ + name: 'QuickStartCard', + title: 'Quick Start', + components: () => import('./homePageComponents/QuickStart'), + }), +);