From acade3184909dd131d4ba1c23fd0536ca6270230 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20=C3=85lund?= Date: Mon, 25 May 2020 10:24:51 +0200 Subject: [PATCH] Service Catalog improvements (#976) * Service Catalog improvements * Example table data * Add Create button * ContentHeader margin * Fix test * Checking components value * Wrap tests in wrapInThemedTestApp * tests use toBeInTheDocument --- packages/core/src/index.ts | 1 + .../layout/ContentHeader/ContentHeader.tsx | 1 + .../layout}/HomepageTimer/HomepageTimer.tsx | 2 +- .../core/src/layout}/HomepageTimer/index.ts | 0 .../CatalogPage/CatalogPage.test.tsx | 4 +- .../components/CatalogPage/CatalogPage.tsx | 21 +++++- .../CatalogTable/CatalogTable.test.tsx | 31 +++++--- .../components/CatalogTable/CatalogTable.tsx | 36 ++++++++- .../ComponentContextMenu.test.tsx | 2 +- .../ComponentMetadataCard.test.tsx | 4 +- .../src/components/HomePage/HomePage.tsx | 14 +++- .../welcome/src/components/Timer/Timer.tsx | 74 ------------------- plugins/welcome/src/components/Timer/index.ts | 17 ----- .../components/WelcomePage/WelcomePage.tsx | 4 +- 14 files changed, 93 insertions(+), 118 deletions(-) rename {plugins/home-page/src/components => packages/core/src/layout}/HomepageTimer/HomepageTimer.tsx (97%) rename {plugins/home-page/src/components => packages/core/src/layout}/HomepageTimer/index.ts (100%) delete mode 100644 plugins/welcome/src/components/Timer/Timer.tsx delete mode 100644 plugins/welcome/src/components/Timer/index.ts diff --git a/packages/core/src/index.ts b/packages/core/src/index.ts index 7a75c72ede..415f167067 100644 --- a/packages/core/src/index.ts +++ b/packages/core/src/index.ts @@ -23,6 +23,7 @@ export { default as Content } from './layout/Content/Content'; export { default as ContentHeader } from './layout/ContentHeader/ContentHeader'; export { default as Header } from './layout/Header/Header'; export { default as HeaderLabel } from './layout/HeaderLabel'; +export { default as HomepageTimer } from './layout/HomepageTimer'; export { default as InfoCard } from './layout/InfoCard'; export { CardTab, TabbedCard } from './layout/TabbedCard'; export { default as ErrorBoundary } from './layout/ErrorBoundary'; diff --git a/packages/core/src/layout/ContentHeader/ContentHeader.tsx b/packages/core/src/layout/ContentHeader/ContentHeader.tsx index 61bea92639..409cfe6b90 100644 --- a/packages/core/src/layout/ContentHeader/ContentHeader.tsx +++ b/packages/core/src/layout/ContentHeader/ContentHeader.tsx @@ -30,6 +30,7 @@ const useStyles = makeStyles(theme => ({ flexWrap: 'wrap', justifyContent: 'flex-end', alignItems: 'center', + marginBottom: theme.spacing(1), }, leftItemsBox: { flex: '1 1 auto', diff --git a/plugins/home-page/src/components/HomepageTimer/HomepageTimer.tsx b/packages/core/src/layout/HomepageTimer/HomepageTimer.tsx similarity index 97% rename from plugins/home-page/src/components/HomepageTimer/HomepageTimer.tsx rename to packages/core/src/layout/HomepageTimer/HomepageTimer.tsx index 770f98e762..9fe0aaa344 100644 --- a/plugins/home-page/src/components/HomepageTimer/HomepageTimer.tsx +++ b/packages/core/src/layout/HomepageTimer/HomepageTimer.tsx @@ -15,7 +15,7 @@ */ import React, { FC } from 'react'; -import { HeaderLabel } from '@backstage/core'; +import HeaderLabel from '../HeaderLabel'; const timeFormat = { hour: '2-digit', minute: '2-digit' }; const utcOptions = { timeZone: 'UTC', ...timeFormat }; diff --git a/plugins/home-page/src/components/HomepageTimer/index.ts b/packages/core/src/layout/HomepageTimer/index.ts similarity index 100% rename from plugins/home-page/src/components/HomepageTimer/index.ts rename to packages/core/src/layout/HomepageTimer/index.ts diff --git a/plugins/catalog/src/components/CatalogPage/CatalogPage.test.tsx b/plugins/catalog/src/components/CatalogPage/CatalogPage.test.tsx index d018d59837..60af5f7d24 100644 --- a/plugins/catalog/src/components/CatalogPage/CatalogPage.test.tsx +++ b/plugins/catalog/src/components/CatalogPage/CatalogPage.test.tsx @@ -34,6 +34,8 @@ describe('CatalogPage', () => { , ); - expect(await rendered.findByText('Your components')).toBeInTheDocument(); + expect( + await rendered.findByText('Keep track of your software'), + ).toBeInTheDocument(); }); }); diff --git a/plugins/catalog/src/components/CatalogPage/CatalogPage.tsx b/plugins/catalog/src/components/CatalogPage/CatalogPage.tsx index 7889c5e0c6..ec6c1cf09f 100644 --- a/plugins/catalog/src/components/CatalogPage/CatalogPage.tsx +++ b/plugins/catalog/src/components/CatalogPage/CatalogPage.tsx @@ -15,10 +15,19 @@ */ import React, { FC } from 'react'; -import { Content, Header, Page, pageTheme } from '@backstage/core'; +import { + Content, + ContentHeader, + Header, + HomepageTimer, + SupportButton, + Page, + pageTheme, +} from '@backstage/core'; import { useAsync } from 'react-use'; import { ComponentFactory } from '../../data/component'; import CatalogTable from '../CatalogTable/CatalogTable'; +import { Button } from '@material-ui/core'; type CatalogPageProps = { componentFactory: ComponentFactory; @@ -27,8 +36,16 @@ const CatalogPage: FC = ({ componentFactory }) => { const { value, error, loading } = useAsync(componentFactory.getAllComponents); return ( -
+
+ +
+ + + All your components + { it('should render loading when loading prop it set to true', async () => { - const rendered = render(); + const rendered = render( + wrapInThemedTestApp(), + ); const progress = await rendered.findByTestId('progress'); - expect(progress).toBeInTheDOM(); + expect(progress).toBeInTheDocument(); }); it('should render error message when error is passed in props', async () => { const rendered = render( - , + wrapInThemedTestApp( + , + ), ); const errorMessage = await rendered.findByText( 'Error encountered while fetching components.', ); - expect(errorMessage).toBeInTheDOM(); + expect(errorMessage).toBeInTheDocument(); }); it('should display component names when loading has finished and no error occurred', async () => { const rendered = render( - , + wrapInThemedTestApp( + , + ), ); - expect(await rendered.findByText('component1')).toBeInTheDOM(); - expect(await rendered.findByText('component2')).toBeInTheDOM(); - expect(await rendered.findByText('component3')).toBeInTheDOM(); + expect(await rendered.findByText('component1')).toBeInTheDocument(); + expect(await rendered.findByText('component2')).toBeInTheDocument(); + expect(await rendered.findByText('component3')).toBeInTheDocument(); }); }); diff --git a/plugins/catalog/src/components/CatalogTable/CatalogTable.tsx b/plugins/catalog/src/components/CatalogTable/CatalogTable.tsx index ea23281262..57f1dfe7f5 100644 --- a/plugins/catalog/src/components/CatalogTable/CatalogTable.tsx +++ b/plugins/catalog/src/components/CatalogTable/CatalogTable.tsx @@ -15,7 +15,13 @@ */ import React, { FC } from 'react'; import { Component } from '../../data/component'; -import { InfoCard, Progress, Table, TableColumn } from '@backstage/core'; +import { + InfoCard, + Progress, + Table, + TableColumn, + StatusOK, +} from '@backstage/core'; import { Typography, Link } from '@material-ui/core'; const columns: TableColumn[] = [ @@ -27,6 +33,32 @@ const columns: TableColumn[] = [ {componentData.name} ), }, + { + title: 'System', + field: 'system', + }, + { + title: 'Owner', + field: 'owner', + }, + { + title: 'Lifecycle', + field: 'lifecycle', + }, + { + title: 'Status', + field: 'status', + render: (componentData: any) => ( + <> + + {componentData.status || 'Up and running'} + + ), + }, + { + title: 'Description', + field: 'description', + }, ]; type CatalogTableProps = { @@ -55,7 +87,7 @@ const CatalogTable: FC = ({ ); diff --git a/plugins/catalog/src/components/ComponentContextMenu/ComponentContextMenu.test.tsx b/plugins/catalog/src/components/ComponentContextMenu/ComponentContextMenu.test.tsx index cd9bb95b23..12dc9774c1 100644 --- a/plugins/catalog/src/components/ComponentContextMenu/ComponentContextMenu.test.tsx +++ b/plugins/catalog/src/components/ComponentContextMenu/ComponentContextMenu.test.tsx @@ -28,7 +28,7 @@ describe('ComponentContextMenu', () => { const button = await menu.findByTestId('menu-button'); button.click(); const unregister = await menu.findByText('Unregister component'); - expect(unregister).toBeInTheDOM(); + expect(unregister).toBeInTheDocument(); }); }); }); diff --git a/plugins/catalog/src/components/ComponentMetadataCard/ComponentMetadataCard.test.tsx b/plugins/catalog/src/components/ComponentMetadataCard/ComponentMetadataCard.test.tsx index e190ee6994..f4b07c020a 100644 --- a/plugins/catalog/src/components/ComponentMetadataCard/ComponentMetadataCard.test.tsx +++ b/plugins/catalog/src/components/ComponentMetadataCard/ComponentMetadataCard.test.tsx @@ -26,12 +26,12 @@ describe('ComponentMetadataCard component', () => { const rendered = await render( , ); - expect(await rendered.findByText('test')).toBeInTheDOM(); + expect(await rendered.findByText('test')).toBeInTheDocument(); }); it('should display loader when loading is set to true', async () => { const rendered = await render( , ); - expect(await rendered.findByRole('progressbar')).toBeInTheDOM(); + expect(await rendered.findByRole('progressbar')).toBeInTheDocument(); }); }); diff --git a/plugins/home-page/src/components/HomePage/HomePage.tsx b/plugins/home-page/src/components/HomePage/HomePage.tsx index 60b271892f..0da5d77bd5 100644 --- a/plugins/home-page/src/components/HomePage/HomePage.tsx +++ b/plugins/home-page/src/components/HomePage/HomePage.tsx @@ -16,8 +16,14 @@ import React, { FC } from 'react'; import { Typography, Link, Grid } from '@material-ui/core'; -import HomePageTimer from '../HomepageTimer'; -import { Content, InfoCard, Header, Page, pageTheme } from '@backstage/core'; +import { + Content, + InfoCard, + Header, + HomepageTimer, + Page, + pageTheme, +} from '@backstage/core'; import SquadTechHealth from './SquadTechHealth'; import Table from '@material-ui/core/Table'; import TableBody from '@material-ui/core/TableBody'; @@ -52,7 +58,7 @@ const HomePage: FC<{}> = () => { title={profile ? `Hello, ${profile.givenName}` : 'Hello'} subtitle="Welcome to Backstage" > - + @@ -68,7 +74,7 @@ const HomePage: FC<{}> = () => { - {data.map((d) => ( + {data.map(d => ( {d.entity} {d.kind} diff --git a/plugins/welcome/src/components/Timer/Timer.tsx b/plugins/welcome/src/components/Timer/Timer.tsx deleted file mode 100644 index 770f98e762..0000000000 --- a/plugins/welcome/src/components/Timer/Timer.tsx +++ /dev/null @@ -1,74 +0,0 @@ -/* - * 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, { FC } from 'react'; -import { HeaderLabel } from '@backstage/core'; - -const timeFormat = { hour: '2-digit', minute: '2-digit' }; -const utcOptions = { timeZone: 'UTC', ...timeFormat }; -const nycOptions = { timeZone: 'America/New_York', ...timeFormat }; -const tyoOptions = { timeZone: 'Asia/Tokyo', ...timeFormat }; -const stoOptions = { timeZone: 'Europe/Stockholm', ...timeFormat }; - -const defaultTimes = { - timeNY: '', - timeUTC: '', - timeTYO: '', - timeSTO: '', -}; - -function getTimes() { - const d = new Date(); - const lang = window.navigator.language; - - // Using the browser native toLocaleTimeString instead of huge moment-tz - // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toLocaleTimeString - const timeNY = d.toLocaleTimeString(lang, nycOptions); - const timeUTC = d.toLocaleTimeString(lang, utcOptions); - const timeTYO = d.toLocaleTimeString(lang, tyoOptions); - const timeSTO = d.toLocaleTimeString(lang, stoOptions); - - return { timeNY, timeUTC, timeTYO, timeSTO }; -} - -const HomePageTimer: FC<{}> = () => { - const [{ timeNY, timeUTC, timeTYO, timeSTO }, setTimes] = React.useState( - defaultTimes, - ); - - React.useEffect(() => { - setTimes(getTimes()); - - const intervalId = setInterval(() => { - setTimes(getTimes()); - }, 1000); - - return () => { - clearInterval(intervalId); - }; - }, []); - - return ( - <> - - - - - - ); -}; - -export default HomePageTimer; diff --git a/plugins/welcome/src/components/Timer/index.ts b/plugins/welcome/src/components/Timer/index.ts deleted file mode 100644 index a67293c20e..0000000000 --- a/plugins/welcome/src/components/Timer/index.ts +++ /dev/null @@ -1,17 +0,0 @@ -/* - * 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. - */ - -export { default } from './Timer'; diff --git a/plugins/welcome/src/components/WelcomePage/WelcomePage.tsx b/plugins/welcome/src/components/WelcomePage/WelcomePage.tsx index b9f416150d..1036096ae5 100644 --- a/plugins/welcome/src/components/WelcomePage/WelcomePage.tsx +++ b/plugins/welcome/src/components/WelcomePage/WelcomePage.tsx @@ -24,11 +24,11 @@ import { ListItemText, Link, } from '@material-ui/core'; -import Timer from '../Timer'; import { Content, InfoCard, Header, + HomepageTimer, Page, pageTheme, ContentHeader, @@ -45,7 +45,7 @@ const WelcomePage: FC<{}> = () => { title={`Welcome ${profile.givenName || 'to Backstage'}`} subtitle="Let's start building a better developer experience" > - +