diff --git a/plugins/techdocs/src/plugin.ts b/plugins/techdocs/src/plugin.ts index 89a5ddeb73..a96f7e5502 100644 --- a/plugins/techdocs/src/plugin.ts +++ b/plugins/techdocs/src/plugin.ts @@ -30,6 +30,7 @@ */ import { createPlugin, createRouteRef } from '@backstage/core'; +import { TechDocsHome } from './reader/components/TechDocsHome'; import { Reader } from './reader/components/Reader'; export const rootRouteRef = createRouteRef({ @@ -45,7 +46,7 @@ export const rootDocsRouteRef = createRouteRef({ export const plugin = createPlugin({ id: 'techdocs', register({ router }) { - router.addRoute(rootRouteRef, Reader); + router.addRoute(rootRouteRef, TechDocsHome); router.addRoute(rootDocsRouteRef, Reader); }, }); diff --git a/plugins/techdocs/src/reader/components/Reader.tsx b/plugins/techdocs/src/reader/components/Reader.tsx index 6398d86515..995d9dc99f 100644 --- a/plugins/techdocs/src/reader/components/Reader.tsx +++ b/plugins/techdocs/src/reader/components/Reader.tsx @@ -17,10 +17,9 @@ import React from 'react'; import { useShadowDom } from '..'; import { useAsync } from 'react-use'; -import { useLocation, useParams, useNavigate } from 'react-router-dom'; +import { AsyncState } from 'react-use/lib/useAsync'; -import { Grid } from '@material-ui/core'; -import { Header, Content, ItemCard } from '@backstage/core'; +import { useLocation, useParams, useNavigate } from 'react-router-dom'; import transformer, { addBaseUrl, @@ -31,10 +30,15 @@ import transformer, { } from '../transformers'; import { docStorageURL } from '../../config'; import URLFormatter from '../urlFormatter'; +import { TechDocsNotFound } from './TechDocsNotFound'; +import { TechDocsPageWrapper } from './TechDocsPageWrapper'; -const useFetch = (url: string) => { +const useFetch = (url: string): AsyncState => { const state = useAsync(async () => { const response = await fetch(url); + if (response.status === 404) { + return new Error('Page not found'); + } const raw = await response.text(); return raw; }, [url]); @@ -67,7 +71,11 @@ export const Reader = () => { React.useEffect(() => { const divElement = shadowDomRef.current; - if (divElement?.shadowRoot && state.value) { + if ( + divElement?.shadowRoot && + state.value && + !(state.value instanceof Error) + ) { const transformedElement = transformer(state.value, [ addBaseUrl({ docStorageURL, @@ -116,39 +124,13 @@ export const Reader = () => { } }, [shadowDomRef, state, componentId, path, navigate]); + if (state.value instanceof Error) return ; + return ( <> -
- - - {componentId ? ( -
- ) : ( - - - navigate('/docs/mkdocs')} - tags={['Developer Tool']} - title="MkDocs" - label="Read Docs" - description="MkDocs is a fast, simple and downright gorgeous static site generator that's geared towards building project documentation. " - /> - - - navigate('/docs/backstage-microsite')} - tags={['Service']} - title="Backstage" - label="Read Docs" - description="Getting started guides, API Overview, documentation around how to Create a Plugin and more. " - /> - - - )} - + +
+ ); }; diff --git a/plugins/techdocs/src/reader/components/TechDocsHome.test.tsx b/plugins/techdocs/src/reader/components/TechDocsHome.test.tsx new file mode 100644 index 0000000000..dd31e6a318 --- /dev/null +++ b/plugins/techdocs/src/reader/components/TechDocsHome.test.tsx @@ -0,0 +1,36 @@ +/* + * Copyright 2020 Spotify AB + * + * 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 { TechDocsHome } from './TechDocsHome'; +import React from 'react'; +import { render } from '@testing-library/react'; +import { wrapInTestApp } from '@backstage/test-utils'; + +describe('TechDocs Home', () => { + it('should render a TechDocs home page', () => { + const { getByTestId, queryByText } = render( + wrapInTestApp(), + ); + + // Header + expect(queryByText('Documentation')).toBeInTheDocument(); + expect( + queryByText(/Documentation available in Backstage/i), + ).toBeInTheDocument(); + + // Explore Content + expect(getByTestId('docs-explore')).toBeDefined(); + }); +}); diff --git a/plugins/techdocs/src/reader/components/TechDocsHome.tsx b/plugins/techdocs/src/reader/components/TechDocsHome.tsx new file mode 100644 index 0000000000..3f9763912c --- /dev/null +++ b/plugins/techdocs/src/reader/components/TechDocsHome.tsx @@ -0,0 +1,74 @@ +/* + * Copyright 2020 Spotify AB + * + * 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 { useNavigate } from 'react-router-dom'; +import { Grid } from '@material-ui/core'; +import { ItemCard } from '@backstage/core'; +import { TechDocsPageWrapper } from './TechDocsPageWrapper'; + +type DocumentationSite = { + title: string; + description: string; + tags: Array; + path: string; + btnLabel: string; +}; + +const documentationSites: Array = [ + { + title: 'MkDocs', + description: + "MkDocs is a fast, simple and downright gorgeous static site generator that's geared towards building project documentation. ", + tags: ['Developer Tool'], + path: '/docs/mkdocs', + btnLabel: 'Read Docs', + }, + { + title: 'Backstage Docs', + description: + 'Getting started guides, API Overview, documentation around how to Create a Plugin and more. ', + tags: ['Service'], + path: '/docs/backstage-microsite', + btnLabel: 'Read Docs', + }, +]; +export const TechDocsHome = () => { + const navigate = useNavigate(); + + return ( + <> + + + {documentationSites.map((site: DocumentationSite, index: number) => ( + + navigate(site.path)} + tags={site.tags} + title={site.title} + label={site.btnLabel} + description={site.description} + /> + + ))} + + + + ); +}; diff --git a/plugins/techdocs/src/reader/components/TechDocsNotFound.test.tsx b/plugins/techdocs/src/reader/components/TechDocsNotFound.test.tsx new file mode 100644 index 0000000000..7792164b14 --- /dev/null +++ b/plugins/techdocs/src/reader/components/TechDocsNotFound.test.tsx @@ -0,0 +1,26 @@ +/* + * Copyright 2020 Spotify AB + * + * 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 { TechDocsNotFound } from './TechDocsNotFound'; +import React from 'react'; +import { render } from '@testing-library/react'; +import { wrapInTestApp } from '@backstage/test-utils'; + +describe('TechDocs Not Found', () => { + it('should render a Documentation not found page', async () => { + const { queryByText } = render(wrapInTestApp()); + expect(queryByText(/error: documentation not found/i)).toBeInTheDocument(); + }); +}); diff --git a/plugins/techdocs/src/reader/components/TechDocsNotFound.tsx b/plugins/techdocs/src/reader/components/TechDocsNotFound.tsx new file mode 100644 index 0000000000..2a961b5bc0 --- /dev/null +++ b/plugins/techdocs/src/reader/components/TechDocsNotFound.tsx @@ -0,0 +1,34 @@ +/* + * Copyright 2020 Spotify AB + * + * 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 { Typography, Button } from '@material-ui/core'; +import { TechDocsPageWrapper } from './TechDocsPageWrapper'; + +export const TechDocsNotFound = () => { + return ( + + Error: Documentation not found + Path: {window.location.pathname} + + + ); +}; diff --git a/plugins/techdocs/src/reader/components/TechDocsPageWrapper.test.tsx b/plugins/techdocs/src/reader/components/TechDocsPageWrapper.test.tsx new file mode 100644 index 0000000000..d4cc49c919 --- /dev/null +++ b/plugins/techdocs/src/reader/components/TechDocsPageWrapper.test.tsx @@ -0,0 +1,34 @@ +/* + * Copyright 2020 Spotify AB + * + * 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 { TechDocsPageWrapper } from './TechDocsPageWrapper'; +import { TechDocsHome } from './TechDocsHome'; +import React from 'react'; +import { render } from '@testing-library/react'; +import { wrapInTestApp } from '@backstage/test-utils'; + +describe('TechDocs Page Wrapper', () => { + it('should render a TechDocs Page Wrapper', async () => { + const { queryByText } = render( + wrapInTestApp( + + + , + ), + ); + expect(queryByText(/test-title/i)).toBeInTheDocument(); + expect(queryByText(/test-subtitle/i)).toBeInTheDocument(); + }); +}); diff --git a/plugins/techdocs/src/reader/components/TechDocsPageWrapper.tsx b/plugins/techdocs/src/reader/components/TechDocsPageWrapper.tsx new file mode 100644 index 0000000000..abb702535b --- /dev/null +++ b/plugins/techdocs/src/reader/components/TechDocsPageWrapper.tsx @@ -0,0 +1,37 @@ +/* + * Copyright 2020 Spotify AB + * + * 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 { Header, Content } from '@backstage/core'; + +type TechDocsPageWrapperProps = { + title: string; + subtitle: string; + children: any; +}; + +export const TechDocsPageWrapper = ({ + children, + title, + subtitle, +}: TechDocsPageWrapperProps) => { + return ( + <> +
+ {children} + + ); +};