From 00c87518042b269101079ad63f6fbea2fadd84ab Mon Sep 17 00:00:00 2001 From: Philipp Hugenroth Date: Thu, 8 Jul 2021 13:17:40 +0200 Subject: [PATCH 01/28] Wrap catalog filters in accordion for smaller screens Signed-off-by: Philipp Hugenroth --- .../CatalogFilter/CatalogFilter.tsx | 76 +++++++++++++++++++ .../src/components/CatalogFilter/index.ts | 17 +++++ .../components/CatalogPage/CatalogPage.tsx | 64 ++++++---------- 3 files changed, 117 insertions(+), 40 deletions(-) create mode 100644 plugins/catalog/src/components/CatalogFilter/CatalogFilter.tsx create mode 100644 plugins/catalog/src/components/CatalogFilter/index.ts diff --git a/plugins/catalog/src/components/CatalogFilter/CatalogFilter.tsx b/plugins/catalog/src/components/CatalogFilter/CatalogFilter.tsx new file mode 100644 index 0000000000..a8673b395a --- /dev/null +++ b/plugins/catalog/src/components/CatalogFilter/CatalogFilter.tsx @@ -0,0 +1,76 @@ +/* + * Copyright 2020 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 { + EntityKindPicker, + EntityLifecyclePicker, + EntityOwnerPicker, + EntityTagPicker, + EntityTypePicker, + UserListFilterKind, + UserListPicker, +} from '@backstage/plugin-catalog-react'; +import { + Accordion, + AccordionDetails, + AccordionSummary, + Grid, + isWidthDown, + Typography, + withWidth, +} from '@material-ui/core'; +import { Breakpoint } from '@material-ui/core/styles/createBreakpoints'; +import ExpandMore from '@material-ui/icons/ExpandMore'; +import React, { PropsWithChildren } from 'react'; + +interface IProps { + initiallySelectedFilter?: UserListFilterKind; +} + +const CatalogFilterWrapper = withWidth()( + ({ width, children }: PropsWithChildren<{ width: Breakpoint }>) => + isWidthDown('md', width) ? ( + + }> + Filters + + {children} + + ) : ( + {children} + ), +); + +export const CatalogFilter = ({ + initiallySelectedFilter = 'owned', +}: IProps) => ( + + + + + + + + + + + + + + +); diff --git a/plugins/catalog/src/components/CatalogFilter/index.ts b/plugins/catalog/src/components/CatalogFilter/index.ts new file mode 100644 index 0000000000..dc57ef02e2 --- /dev/null +++ b/plugins/catalog/src/components/CatalogFilter/index.ts @@ -0,0 +1,17 @@ +/* + * Copyright 2020 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 { CatalogFilter } from './CatalogFilter'; diff --git a/plugins/catalog/src/components/CatalogPage/CatalogPage.tsx b/plugins/catalog/src/components/CatalogPage/CatalogPage.tsx index 089e61f0fb..6f8dd0dd2b 100644 --- a/plugins/catalog/src/components/CatalogPage/CatalogPage.tsx +++ b/plugins/catalog/src/components/CatalogPage/CatalogPage.tsx @@ -15,16 +15,10 @@ */ import React from 'react'; -import { Grid } from '@material-ui/core'; +import { Grid, withWidth } from '@material-ui/core'; import { - EntityKindPicker, - EntityLifecyclePicker, EntityListProvider, - EntityOwnerPicker, - EntityTagPicker, - EntityTypePicker, UserListFilterKind, - UserListPicker, } from '@backstage/plugin-catalog-react'; import { CatalogTable } from '../CatalogTable'; @@ -38,6 +32,7 @@ import { TableColumn, TableProps, } from '@backstage/core-components'; +import { CatalogFilter } from '../CatalogFilter'; export type CatalogPageProps = { initiallySelectedFilter?: UserListFilterKind; @@ -45,40 +40,29 @@ export type CatalogPageProps = { actions?: TableProps['actions']; }; -export const CatalogPage = ({ - initiallySelectedFilter = 'owned', - columns, - actions, -}: CatalogPageProps) => ( - - - - - All your software catalog entities - - - - - - - - - - + + + ); + }, ); From 4fe222ff389841655682ea5e4e050751d95b2139 Mon Sep 17 00:00:00 2001 From: Philipp Hugenroth Date: Thu, 8 Jul 2021 13:37:00 +0200 Subject: [PATCH 02/28] Add changeset Signed-off-by: Philipp Hugenroth --- .changeset/fuzzy-wolves-travel.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/fuzzy-wolves-travel.md diff --git a/.changeset/fuzzy-wolves-travel.md b/.changeset/fuzzy-wolves-travel.md new file mode 100644 index 0000000000..6b51be64c0 --- /dev/null +++ b/.changeset/fuzzy-wolves-travel.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog': patch +--- + +Move filter to CatalogFilter component & wrap them in an accordion on smaller screens to improve the UX From 9eaabc365509451a89227589c63cbb2e6c0d05ef Mon Sep 17 00:00:00 2001 From: Philipp Hugenroth Date: Thu, 8 Jul 2021 13:54:27 +0200 Subject: [PATCH 03/28] Remove unused theme HOC Signed-off-by: Philipp Hugenroth --- .../components/CatalogPage/CatalogPage.tsx | 56 ++++++++++--------- 1 file changed, 29 insertions(+), 27 deletions(-) diff --git a/plugins/catalog/src/components/CatalogPage/CatalogPage.tsx b/plugins/catalog/src/components/CatalogPage/CatalogPage.tsx index 6f8dd0dd2b..a97116dd80 100644 --- a/plugins/catalog/src/components/CatalogPage/CatalogPage.tsx +++ b/plugins/catalog/src/components/CatalogPage/CatalogPage.tsx @@ -15,7 +15,7 @@ */ import React from 'react'; -import { Grid, withWidth } from '@material-ui/core'; +import { Grid } from '@material-ui/core'; import { EntityListProvider, UserListFilterKind, @@ -40,29 +40,31 @@ export type CatalogPageProps = { actions?: TableProps['actions']; }; -export const CatalogPage = withWidth()( - ({ columns, actions, initiallySelectedFilter }: CatalogPageProps) => { - return ( - - - - - All your software catalog entities - - - - - - - - - - - - - - ); - }, -); +export const CatalogPage = ({ + columns, + actions, + initiallySelectedFilter, +}: CatalogPageProps) => { + return ( + + + + + All your software catalog entities + + + + + + + + + + + + + + ); +}; From 713949231f33689b4cddfaeb2afaf294f0897815 Mon Sep 17 00:00:00 2001 From: Philipp Hugenroth Date: Fri, 9 Jul 2021 11:51:19 +0200 Subject: [PATCH 04/28] Fix tests to support window.matchMedia & add tests for responsiveness Signed-off-by: Philipp Hugenroth --- .../src/testUtils/mockBreakpoint.ts | 34 ++++++++++---- .../CatalogPage/CatalogPage.test.tsx | 9 ++++ .../components/CatalogPage/CatalogPage.tsx | 46 +++++++++---------- 3 files changed, 55 insertions(+), 34 deletions(-) diff --git a/packages/test-utils/src/testUtils/mockBreakpoint.ts b/packages/test-utils/src/testUtils/mockBreakpoint.ts index 37f0e761b6..0e04f58f70 100644 --- a/packages/test-utils/src/testUtils/mockBreakpoint.ts +++ b/packages/test-utils/src/testUtils/mockBreakpoint.ts @@ -18,6 +18,8 @@ import { act } from '@testing-library/react'; type Breakpoint = 'xs' | 'sm' | 'md' | 'lg' | 'xl'; +const defaultBreakpoint: Breakpoint = 'xl'; + const queryToBreakpoint = { '(min-width:1920px)': 'xl', '(min-width:1280px)': 'lg', @@ -26,14 +28,17 @@ const queryToBreakpoint = { '(min-width:0px)': 'xs', } as Record; -function toBreakpoint(query: string) { - const breakpoint = queryToBreakpoint[query]; - if (!breakpoint) { - throw new Error( - `received unknown media query in breakpoint mock: '${query}'`, - ); - } - return breakpoint; +/** + * Converts media query string to Breakpoint. + * Chooses the default breakpoint if no breakpoint is set in the media query. + * + * @param query media query string + * @returns Breakpoint + */ +function toBreakpoint(query: string): Breakpoint { + return queryToBreakpoint[query] + ? queryToBreakpoint[query] + : defaultBreakpoint; } type Listener = (event: { matches: boolean }) => void; @@ -41,6 +46,8 @@ type Listener = (event: { matches: boolean }) => void; interface QueryList { addListener(listener: Listener): void; removeListener(listener: Listener): void; + addEventListener(listener: Listener): void; + removeEventListener(listener: Listener): void; matches: boolean; } @@ -50,12 +57,15 @@ interface Query { listeners: Set; } -export default function mockBreakpoint(initialBreakpoint: Breakpoint = 'xl') { +export default function mockBreakpoint( + initialBreakpoint: Breakpoint = defaultBreakpoint, +) { let currentBreakpoint = initialBreakpoint; const queries = Array(); const previousMatchMedia: any = (window as any).matchMedia; + // https://jestjs.io/docs/manual-mocks#mocking-methods-which-are-not-implemented-in-jsdom (window as any).matchMedia = (query: string): QueryList => { const listeners = new Set(); @@ -66,6 +76,12 @@ export default function mockBreakpoint(initialBreakpoint: Breakpoint = 'xl') { removeListener(listener) { listeners.delete(listener); }, + addEventListener(listener) { + listeners.add(listener); + }, + removeEventListener(listener) { + listeners.delete(listener); + }, matches: toBreakpoint(query) === currentBreakpoint, }; diff --git a/plugins/catalog/src/components/CatalogPage/CatalogPage.test.tsx b/plugins/catalog/src/components/CatalogPage/CatalogPage.test.tsx index 584eea0850..d5e31a16a7 100644 --- a/plugins/catalog/src/components/CatalogPage/CatalogPage.test.tsx +++ b/plugins/catalog/src/components/CatalogPage/CatalogPage.test.tsx @@ -26,6 +26,7 @@ import { MockStorageApi, renderWithEffects, wrapInTestApp, + mockBreakpoint, } from '@backstage/test-utils'; import { fireEvent, screen } from '@testing-library/react'; import React from 'react'; @@ -111,6 +112,8 @@ describe('CatalogPage', () => { getProfile: () => testProfile, }; + const { set: setBreakpoint } = mockBreakpoint(); + const renderWrapped = (children: React.ReactNode) => renderWithEffects( wrapInTestApp( @@ -244,4 +247,10 @@ describe('CatalogPage', () => { screen.findByText(/Starred \(1\)/), ).resolves.toBeInTheDocument(); }); + + it('should wrap filter in accordion on smaller screens', async () => { + setBreakpoint('sm'); + const { findByText } = await renderWrapped(); + await expect(findByText(/Filters/)).resolves.toBeInTheDocument(); + }); }); diff --git a/plugins/catalog/src/components/CatalogPage/CatalogPage.tsx b/plugins/catalog/src/components/CatalogPage/CatalogPage.tsx index a97116dd80..9eeb91ca3c 100644 --- a/plugins/catalog/src/components/CatalogPage/CatalogPage.tsx +++ b/plugins/catalog/src/components/CatalogPage/CatalogPage.tsx @@ -43,28 +43,24 @@ export type CatalogPageProps = { export const CatalogPage = ({ columns, actions, - initiallySelectedFilter, -}: CatalogPageProps) => { - return ( - - - - - All your software catalog entities - - - - - - - - - - - - - - ); -}; + initiallySelectedFilter = 'owned', +}: CatalogPageProps) => ( + + + + + All your software catalog entities + + + + + + + + + + + + + +); From 84feb21147018aa37d2e0a6105216fd2fa11c10f Mon Sep 17 00:00:00 2001 From: Philipp Hugenroth Date: Thu, 8 Jul 2021 13:17:40 +0200 Subject: [PATCH 05/28] Wrap catalog filters in accordion for smaller screens Signed-off-by: Philipp Hugenroth --- .../CatalogFilter/CatalogFilter.tsx | 76 +++++++++++++++++++ .../src/components/CatalogFilter/index.ts | 17 +++++ .../components/CatalogPage/CatalogPage.tsx | 64 ++++++---------- 3 files changed, 117 insertions(+), 40 deletions(-) create mode 100644 plugins/catalog/src/components/CatalogFilter/CatalogFilter.tsx create mode 100644 plugins/catalog/src/components/CatalogFilter/index.ts diff --git a/plugins/catalog/src/components/CatalogFilter/CatalogFilter.tsx b/plugins/catalog/src/components/CatalogFilter/CatalogFilter.tsx new file mode 100644 index 0000000000..a8673b395a --- /dev/null +++ b/plugins/catalog/src/components/CatalogFilter/CatalogFilter.tsx @@ -0,0 +1,76 @@ +/* + * Copyright 2020 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 { + EntityKindPicker, + EntityLifecyclePicker, + EntityOwnerPicker, + EntityTagPicker, + EntityTypePicker, + UserListFilterKind, + UserListPicker, +} from '@backstage/plugin-catalog-react'; +import { + Accordion, + AccordionDetails, + AccordionSummary, + Grid, + isWidthDown, + Typography, + withWidth, +} from '@material-ui/core'; +import { Breakpoint } from '@material-ui/core/styles/createBreakpoints'; +import ExpandMore from '@material-ui/icons/ExpandMore'; +import React, { PropsWithChildren } from 'react'; + +interface IProps { + initiallySelectedFilter?: UserListFilterKind; +} + +const CatalogFilterWrapper = withWidth()( + ({ width, children }: PropsWithChildren<{ width: Breakpoint }>) => + isWidthDown('md', width) ? ( + + }> + Filters + + {children} + + ) : ( + {children} + ), +); + +export const CatalogFilter = ({ + initiallySelectedFilter = 'owned', +}: IProps) => ( + + + + + + + + + + + + + + +); diff --git a/plugins/catalog/src/components/CatalogFilter/index.ts b/plugins/catalog/src/components/CatalogFilter/index.ts new file mode 100644 index 0000000000..dc57ef02e2 --- /dev/null +++ b/plugins/catalog/src/components/CatalogFilter/index.ts @@ -0,0 +1,17 @@ +/* + * Copyright 2020 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 { CatalogFilter } from './CatalogFilter'; diff --git a/plugins/catalog/src/components/CatalogPage/CatalogPage.tsx b/plugins/catalog/src/components/CatalogPage/CatalogPage.tsx index 089e61f0fb..6f8dd0dd2b 100644 --- a/plugins/catalog/src/components/CatalogPage/CatalogPage.tsx +++ b/plugins/catalog/src/components/CatalogPage/CatalogPage.tsx @@ -15,16 +15,10 @@ */ import React from 'react'; -import { Grid } from '@material-ui/core'; +import { Grid, withWidth } from '@material-ui/core'; import { - EntityKindPicker, - EntityLifecyclePicker, EntityListProvider, - EntityOwnerPicker, - EntityTagPicker, - EntityTypePicker, UserListFilterKind, - UserListPicker, } from '@backstage/plugin-catalog-react'; import { CatalogTable } from '../CatalogTable'; @@ -38,6 +32,7 @@ import { TableColumn, TableProps, } from '@backstage/core-components'; +import { CatalogFilter } from '../CatalogFilter'; export type CatalogPageProps = { initiallySelectedFilter?: UserListFilterKind; @@ -45,40 +40,29 @@ export type CatalogPageProps = { actions?: TableProps['actions']; }; -export const CatalogPage = ({ - initiallySelectedFilter = 'owned', - columns, - actions, -}: CatalogPageProps) => ( - - - - - All your software catalog entities - - - - - - - - - - + + + ); + }, ); From e50d7bf9ac62bbb6944ba76ab29523266eb2bc58 Mon Sep 17 00:00:00 2001 From: Philipp Hugenroth Date: Thu, 8 Jul 2021 13:37:00 +0200 Subject: [PATCH 06/28] Add changeset Signed-off-by: Philipp Hugenroth --- .changeset/fuzzy-wolves-travel.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/fuzzy-wolves-travel.md diff --git a/.changeset/fuzzy-wolves-travel.md b/.changeset/fuzzy-wolves-travel.md new file mode 100644 index 0000000000..6b51be64c0 --- /dev/null +++ b/.changeset/fuzzy-wolves-travel.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog': patch +--- + +Move filter to CatalogFilter component & wrap them in an accordion on smaller screens to improve the UX From 9cf8779ddafdf465e0857c725c118f2f82941ee5 Mon Sep 17 00:00:00 2001 From: Philipp Hugenroth Date: Thu, 8 Jul 2021 13:54:27 +0200 Subject: [PATCH 07/28] Remove unused theme HOC Signed-off-by: Philipp Hugenroth --- .../components/CatalogPage/CatalogPage.tsx | 56 ++++++++++--------- 1 file changed, 29 insertions(+), 27 deletions(-) diff --git a/plugins/catalog/src/components/CatalogPage/CatalogPage.tsx b/plugins/catalog/src/components/CatalogPage/CatalogPage.tsx index 6f8dd0dd2b..a97116dd80 100644 --- a/plugins/catalog/src/components/CatalogPage/CatalogPage.tsx +++ b/plugins/catalog/src/components/CatalogPage/CatalogPage.tsx @@ -15,7 +15,7 @@ */ import React from 'react'; -import { Grid, withWidth } from '@material-ui/core'; +import { Grid } from '@material-ui/core'; import { EntityListProvider, UserListFilterKind, @@ -40,29 +40,31 @@ export type CatalogPageProps = { actions?: TableProps['actions']; }; -export const CatalogPage = withWidth()( - ({ columns, actions, initiallySelectedFilter }: CatalogPageProps) => { - return ( - - - - - All your software catalog entities - - - - - - - - - - - - - - ); - }, -); +export const CatalogPage = ({ + columns, + actions, + initiallySelectedFilter, +}: CatalogPageProps) => { + return ( + + + + + All your software catalog entities + + + + + + + + + + + + + + ); +}; From db935a4c102d1e629c98c387ca1cf9879561be7b Mon Sep 17 00:00:00 2001 From: Philipp Hugenroth Date: Fri, 9 Jul 2021 11:51:19 +0200 Subject: [PATCH 08/28] Fix tests to support window.matchMedia & add tests for responsiveness Signed-off-by: Philipp Hugenroth --- .../src/testUtils/mockBreakpoint.ts | 34 ++++++++++---- .../CatalogPage/CatalogPage.test.tsx | 9 ++++ .../components/CatalogPage/CatalogPage.tsx | 46 +++++++++---------- 3 files changed, 55 insertions(+), 34 deletions(-) diff --git a/packages/test-utils/src/testUtils/mockBreakpoint.ts b/packages/test-utils/src/testUtils/mockBreakpoint.ts index 37f0e761b6..0e04f58f70 100644 --- a/packages/test-utils/src/testUtils/mockBreakpoint.ts +++ b/packages/test-utils/src/testUtils/mockBreakpoint.ts @@ -18,6 +18,8 @@ import { act } from '@testing-library/react'; type Breakpoint = 'xs' | 'sm' | 'md' | 'lg' | 'xl'; +const defaultBreakpoint: Breakpoint = 'xl'; + const queryToBreakpoint = { '(min-width:1920px)': 'xl', '(min-width:1280px)': 'lg', @@ -26,14 +28,17 @@ const queryToBreakpoint = { '(min-width:0px)': 'xs', } as Record; -function toBreakpoint(query: string) { - const breakpoint = queryToBreakpoint[query]; - if (!breakpoint) { - throw new Error( - `received unknown media query in breakpoint mock: '${query}'`, - ); - } - return breakpoint; +/** + * Converts media query string to Breakpoint. + * Chooses the default breakpoint if no breakpoint is set in the media query. + * + * @param query media query string + * @returns Breakpoint + */ +function toBreakpoint(query: string): Breakpoint { + return queryToBreakpoint[query] + ? queryToBreakpoint[query] + : defaultBreakpoint; } type Listener = (event: { matches: boolean }) => void; @@ -41,6 +46,8 @@ type Listener = (event: { matches: boolean }) => void; interface QueryList { addListener(listener: Listener): void; removeListener(listener: Listener): void; + addEventListener(listener: Listener): void; + removeEventListener(listener: Listener): void; matches: boolean; } @@ -50,12 +57,15 @@ interface Query { listeners: Set; } -export default function mockBreakpoint(initialBreakpoint: Breakpoint = 'xl') { +export default function mockBreakpoint( + initialBreakpoint: Breakpoint = defaultBreakpoint, +) { let currentBreakpoint = initialBreakpoint; const queries = Array(); const previousMatchMedia: any = (window as any).matchMedia; + // https://jestjs.io/docs/manual-mocks#mocking-methods-which-are-not-implemented-in-jsdom (window as any).matchMedia = (query: string): QueryList => { const listeners = new Set(); @@ -66,6 +76,12 @@ export default function mockBreakpoint(initialBreakpoint: Breakpoint = 'xl') { removeListener(listener) { listeners.delete(listener); }, + addEventListener(listener) { + listeners.add(listener); + }, + removeEventListener(listener) { + listeners.delete(listener); + }, matches: toBreakpoint(query) === currentBreakpoint, }; diff --git a/plugins/catalog/src/components/CatalogPage/CatalogPage.test.tsx b/plugins/catalog/src/components/CatalogPage/CatalogPage.test.tsx index 584eea0850..d5e31a16a7 100644 --- a/plugins/catalog/src/components/CatalogPage/CatalogPage.test.tsx +++ b/plugins/catalog/src/components/CatalogPage/CatalogPage.test.tsx @@ -26,6 +26,7 @@ import { MockStorageApi, renderWithEffects, wrapInTestApp, + mockBreakpoint, } from '@backstage/test-utils'; import { fireEvent, screen } from '@testing-library/react'; import React from 'react'; @@ -111,6 +112,8 @@ describe('CatalogPage', () => { getProfile: () => testProfile, }; + const { set: setBreakpoint } = mockBreakpoint(); + const renderWrapped = (children: React.ReactNode) => renderWithEffects( wrapInTestApp( @@ -244,4 +247,10 @@ describe('CatalogPage', () => { screen.findByText(/Starred \(1\)/), ).resolves.toBeInTheDocument(); }); + + it('should wrap filter in accordion on smaller screens', async () => { + setBreakpoint('sm'); + const { findByText } = await renderWrapped(); + await expect(findByText(/Filters/)).resolves.toBeInTheDocument(); + }); }); diff --git a/plugins/catalog/src/components/CatalogPage/CatalogPage.tsx b/plugins/catalog/src/components/CatalogPage/CatalogPage.tsx index a97116dd80..9eeb91ca3c 100644 --- a/plugins/catalog/src/components/CatalogPage/CatalogPage.tsx +++ b/plugins/catalog/src/components/CatalogPage/CatalogPage.tsx @@ -43,28 +43,24 @@ export type CatalogPageProps = { export const CatalogPage = ({ columns, actions, - initiallySelectedFilter, -}: CatalogPageProps) => { - return ( - - - - - All your software catalog entities - - - - - - - - - - - - - - ); -}; + initiallySelectedFilter = 'owned', +}: CatalogPageProps) => ( + + + + + All your software catalog entities + + + + + + + + + + + + + +); From 2a295bcec92f465900c48d95be06b10029570842 Mon Sep 17 00:00:00 2001 From: Philipp Hugenroth Date: Mon, 12 Jul 2021 14:41:30 +0200 Subject: [PATCH 09/28] Add TablePage components - Change CatalogPage to use generic TablePage Signed-off-by: Philipp Hugenroth --- .../src/layout/Header/Header.tsx | 2 +- .../src/layout/TablePage/Layout.tsx | 37 ++++------ .../src/layout/TablePage/TablePage.tsx | 68 +++++++++++++++++++ .../src/layout/TablePage}/index.ts | 5 +- packages/core-components/src/layout/index.ts | 1 + .../components/CatalogPage/CatalogPage.tsx | 57 ++++++++-------- .../src/components/CatalogPage/index.ts | 1 - .../CreateComponentButton.tsx | 38 ----------- 8 files changed, 115 insertions(+), 94 deletions(-) rename plugins/catalog/src/components/CatalogPage/CatalogLayout.tsx => packages/core-components/src/layout/TablePage/Layout.tsx (52%) create mode 100644 packages/core-components/src/layout/TablePage/TablePage.tsx rename {plugins/catalog/src/components/CreateComponentButton => packages/core-components/src/layout/TablePage}/index.ts (84%) delete mode 100644 plugins/catalog/src/components/CreateComponentButton/CreateComponentButton.tsx diff --git a/packages/core-components/src/layout/Header/Header.tsx b/packages/core-components/src/layout/Header/Header.tsx index 96d024f524..8c51f2f7fc 100644 --- a/packages/core-components/src/layout/Header/Header.tsx +++ b/packages/core-components/src/layout/Header/Header.tsx @@ -88,7 +88,7 @@ const useStyles = makeStyles(theme => ({ type HeaderStyles = ReturnType; -type Props = { +export type Props = { component?: ReactNode; pageTitleOverride?: string; style?: CSSProperties; diff --git a/plugins/catalog/src/components/CatalogPage/CatalogLayout.tsx b/packages/core-components/src/layout/TablePage/Layout.tsx similarity index 52% rename from plugins/catalog/src/components/CatalogPage/CatalogLayout.tsx rename to packages/core-components/src/layout/TablePage/Layout.tsx index 2471ac9df2..79ad9c24b8 100644 --- a/plugins/catalog/src/components/CatalogPage/CatalogLayout.tsx +++ b/packages/core-components/src/layout/TablePage/Layout.tsx @@ -16,27 +16,20 @@ import React from 'react'; -import { configApiRef, useApi } from '@backstage/core-plugin-api'; -import { Header, Page } from '@backstage/core-components'; +import { Header, Page } from '../../'; +import { Props as HeaderProps } from '../../layout/Header/Header'; -type Props = { - children?: React.ReactNode; -}; +export interface IProps extends HeaderProps { + themeId: string; +} -export const CatalogLayout = ({ children }: Props) => { - const orgName = - useApi(configApiRef).getOptionalString('organization.name') ?? 'Backstage'; - - return ( - -
- {children} - - ); -}; - -export default CatalogLayout; +export const Layout = ({ + themeId, + children, + ...props +}: React.PropsWithChildren) => ( + +
+ {children} + +); diff --git a/packages/core-components/src/layout/TablePage/TablePage.tsx b/packages/core-components/src/layout/TablePage/TablePage.tsx new file mode 100644 index 0000000000..f58da0b553 --- /dev/null +++ b/packages/core-components/src/layout/TablePage/TablePage.tsx @@ -0,0 +1,68 @@ +/* + * Copyright 2020 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 { Grid } from '@material-ui/core'; + +import { Content, ContentHeader, SupportButton, Button } from '../..'; +import { Layout, IProps as LayoutProps } from './Layout'; +import { Link as RouterLink } from 'react-router-dom'; + +interface IProps extends LayoutProps { + supportMessage: string; + filter: React.ReactNode; + header: string; + headerLink?: string; +} + +const TablePageLink = ({ link }: { link?: string }) => { + return link ? ( + + ) : null; +}; + +export const TablePage = ({ + supportMessage, + filter, + children, + header, + headerLink, + ...props +}: React.PropsWithChildren) => ( + + + + + {supportMessage} + + + + {filter} + + + {children} + + + + +); diff --git a/plugins/catalog/src/components/CreateComponentButton/index.ts b/packages/core-components/src/layout/TablePage/index.ts similarity index 84% rename from plugins/catalog/src/components/CreateComponentButton/index.ts rename to packages/core-components/src/layout/TablePage/index.ts index e525bef782..5df8aa4c40 100644 --- a/plugins/catalog/src/components/CreateComponentButton/index.ts +++ b/packages/core-components/src/layout/TablePage/index.ts @@ -1,5 +1,5 @@ /* - * Copyright 2021 The Backstage Authors + * Copyright 2020 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. @@ -13,4 +13,5 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -export { CreateComponentButton } from './CreateComponentButton'; + +export { TablePage } from './TablePage'; diff --git a/packages/core-components/src/layout/index.ts b/packages/core-components/src/layout/index.ts index 4abde642dc..dce33c7f2a 100644 --- a/packages/core-components/src/layout/index.ts +++ b/packages/core-components/src/layout/index.ts @@ -29,3 +29,4 @@ export * from './Sidebar'; export * from './SignInPage'; export * from './TabbedCard'; export * from './Breadcrumbs'; +export * from './TablePage'; diff --git a/plugins/catalog/src/components/CatalogPage/CatalogPage.tsx b/plugins/catalog/src/components/CatalogPage/CatalogPage.tsx index 9eeb91ca3c..bd23e5ccdb 100644 --- a/plugins/catalog/src/components/CatalogPage/CatalogPage.tsx +++ b/plugins/catalog/src/components/CatalogPage/CatalogPage.tsx @@ -15,24 +15,17 @@ */ import React from 'react'; -import { Grid } from '@material-ui/core'; import { EntityListProvider, UserListFilterKind, } from '@backstage/plugin-catalog-react'; import { CatalogTable } from '../CatalogTable'; +import { configApiRef, useApi, useRouteRef } from '@backstage/core-plugin-api'; import { EntityRow } from '../CatalogTable/types'; -import CatalogLayout from './CatalogLayout'; -import { CreateComponentButton } from '../CreateComponentButton'; -import { - Content, - ContentHeader, - SupportButton, - TableColumn, - TableProps, -} from '@backstage/core-components'; +import { TableColumn, TableProps, TablePage } from '@backstage/core-components'; import { CatalogFilter } from '../CatalogFilter'; +import { createComponentRouteRef } from '../../routes'; export type CatalogPageProps = { initiallySelectedFilter?: UserListFilterKind; @@ -44,23 +37,27 @@ export const CatalogPage = ({ columns, actions, initiallySelectedFilter = 'owned', -}: CatalogPageProps) => ( - - - - - All your software catalog entities - - - - - - - - - - - - - -); +}: CatalogPageProps) => { + const orgName = + useApi(configApiRef).getOptionalString('organization.name') ?? 'Backstage'; + const createComponentLink = useRouteRef(createComponentRouteRef); + + return ( + + + } + title={`${orgName} Catalog`} + subtitle={`Catalog of software components at ${orgName}`} + themeId="home" + pageTitleOverride="Home" + headerLink={createComponentLink ? createComponentLink() : ''} + > + + + + ); +}; diff --git a/plugins/catalog/src/components/CatalogPage/index.ts b/plugins/catalog/src/components/CatalogPage/index.ts index 66c3c2f4b3..dc7ed68229 100644 --- a/plugins/catalog/src/components/CatalogPage/index.ts +++ b/plugins/catalog/src/components/CatalogPage/index.ts @@ -13,5 +13,4 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -export { CatalogLayout } from './CatalogLayout'; export { CatalogPage } from './CatalogPage'; diff --git a/plugins/catalog/src/components/CreateComponentButton/CreateComponentButton.tsx b/plugins/catalog/src/components/CreateComponentButton/CreateComponentButton.tsx deleted file mode 100644 index 482a0c0a3c..0000000000 --- a/plugins/catalog/src/components/CreateComponentButton/CreateComponentButton.tsx +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright 2021 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 as RouterLink } from 'react-router-dom'; -import { Button } from '@material-ui/core'; -import { createComponentRouteRef } from '../../routes'; -import { useRouteRef } from '@backstage/core-plugin-api'; - -export const CreateComponentButton = () => { - const createComponentLink = useRouteRef(createComponentRouteRef); - - if (!createComponentLink) return null; - - return ( - - ); -}; From 48ec80da3ac8caec10b8529fd579610fb3cb6880 Mon Sep 17 00:00:00 2001 From: Philipp Hugenroth Date: Mon, 12 Jul 2021 17:27:44 +0200 Subject: [PATCH 10/28] Apply generic table page to ApiExplorer Signed-off-by: Philipp Hugenroth --- .../src/layout/TablePage/TablePage.tsx | 35 ++++--- .../ApiExplorerPage/ApiExplorerLayout.tsx | 40 -------- .../ApiExplorerPage/ApiExplorerPage.tsx | 94 +++++++------------ .../CatalogFilter/CatalogFilter.tsx | 4 +- .../components/CatalogPage/CatalogPage.tsx | 13 +-- plugins/catalog/src/index.ts | 3 +- 6 files changed, 68 insertions(+), 121 deletions(-) delete mode 100644 plugins/api-docs/src/components/ApiExplorerPage/ApiExplorerLayout.tsx diff --git a/packages/core-components/src/layout/TablePage/TablePage.tsx b/packages/core-components/src/layout/TablePage/TablePage.tsx index f58da0b553..5bf69f4e64 100644 --- a/packages/core-components/src/layout/TablePage/TablePage.tsx +++ b/packages/core-components/src/layout/TablePage/TablePage.tsx @@ -21,22 +21,27 @@ import { Content, ContentHeader, SupportButton, Button } from '../..'; import { Layout, IProps as LayoutProps } from './Layout'; import { Link as RouterLink } from 'react-router-dom'; -interface IProps extends LayoutProps { - supportMessage: string; - filter: React.ReactNode; - header: string; - headerLink?: string; +interface ILinkProps { + contentLink?: string; + contentLinkText?: string; } -const TablePageLink = ({ link }: { link?: string }) => { - return link ? ( +type IProps = LayoutProps & + ILinkProps & { + contentTitle: string; + supportMessage: string; + filter: React.ReactNode; + }; + +const TablePageLink = ({ contentLink, contentLinkText }: ILinkProps) => { + return contentLink && contentLinkText ? ( ) : null; }; @@ -45,14 +50,18 @@ export const TablePage = ({ supportMessage, filter, children, - header, - headerLink, + contentTitle, + contentLink, + contentLinkText, ...props }: React.PropsWithChildren) => ( - - + + {supportMessage} diff --git a/plugins/api-docs/src/components/ApiExplorerPage/ApiExplorerLayout.tsx b/plugins/api-docs/src/components/ApiExplorerPage/ApiExplorerLayout.tsx deleted file mode 100644 index 5638c23634..0000000000 --- a/plugins/api-docs/src/components/ApiExplorerPage/ApiExplorerLayout.tsx +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright 2020 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 { Header, Page } from '@backstage/core-components'; -import { useApi, configApiRef } from '@backstage/core-plugin-api'; - -type Props = { - children?: React.ReactNode; -}; -export const ApiExplorerLayout = ({ children }: Props) => { - const configApi = useApi(configApiRef); - const generatedSubtitle = `${ - configApi.getOptionalString('organization.name') ?? 'Backstage' - } API Explorer`; - return ( - -
- {children} - - ); -}; diff --git a/plugins/api-docs/src/components/ApiExplorerPage/ApiExplorerPage.tsx b/plugins/api-docs/src/components/ApiExplorerPage/ApiExplorerPage.tsx index 9a8b725ffc..bcc18e4021 100644 --- a/plugins/api-docs/src/components/ApiExplorerPage/ApiExplorerPage.tsx +++ b/plugins/api-docs/src/components/ApiExplorerPage/ApiExplorerPage.tsx @@ -14,39 +14,19 @@ * limitations under the License. */ +import { TableColumn, TablePage } from '@backstage/core-components'; +import { configApiRef, useApi, useRouteRef } from '@backstage/core-plugin-api'; +import { + CatalogFilter, + CatalogTable, + CatalogTableRow, +} from '@backstage/plugin-catalog'; import { - EntityKindPicker, - EntityLifecyclePicker, EntityListProvider, - EntityOwnerPicker, - EntityTagPicker, - EntityTypePicker, UserListFilterKind, - UserListPicker, } from '@backstage/plugin-catalog-react'; -import { CatalogTable, CatalogTableRow } from '@backstage/plugin-catalog'; -import { Button, makeStyles } from '@material-ui/core'; import React from 'react'; -import { Link as RouterLink } from 'react-router-dom'; import { createComponentRouteRef } from '../../routes'; -import { ApiExplorerLayout } from './ApiExplorerLayout'; - -import { - Content, - ContentHeader, - SupportButton, - TableColumn, -} from '@backstage/core-components'; -import { useRouteRef } from '@backstage/core-plugin-api'; - -const useStyles = makeStyles(theme => ({ - contentWrapper: { - display: 'grid', - gridTemplateAreas: "'filters' 'table'", - gridTemplateColumns: '250px 1fr', - gridColumnGap: theme.spacing(2), - }, -})); const defaultColumns: TableColumn[] = [ CatalogTable.columns.createNameColumn({ defaultKind: 'API' }), @@ -58,8 +38,11 @@ const defaultColumns: TableColumn[] = [ CatalogTable.columns.createTagsColumn(), ]; -export type ApiExplorerPageProps = { +interface IApiExplorerePageFilterProps { initiallySelectedFilter?: UserListFilterKind; +} + +export type ApiExplorerPageProps = IApiExplorerePageFilterProps & { columns?: TableColumn[]; }; @@ -67,39 +50,32 @@ export const ApiExplorerPage = ({ initiallySelectedFilter = 'all', columns, }: ApiExplorerPageProps) => { - const styles = useStyles(); const createComponentLink = useRouteRef(createComponentRouteRef); + const configApi = useApi(configApiRef); + const generatedSubtitle = `${ + configApi.getOptionalString('organization.name') ?? 'Backstage' + } API Explorer`; return ( - - - - {createComponentLink && ( - - )} - All your APIs - -
- -
-
- -
-
-
-
+ + + } + > + + + ); }; diff --git a/plugins/catalog/src/components/CatalogFilter/CatalogFilter.tsx b/plugins/catalog/src/components/CatalogFilter/CatalogFilter.tsx index a8673b395a..6704f429ee 100644 --- a/plugins/catalog/src/components/CatalogFilter/CatalogFilter.tsx +++ b/plugins/catalog/src/components/CatalogFilter/CatalogFilter.tsx @@ -38,6 +38,7 @@ import React, { PropsWithChildren } from 'react'; interface IProps { initiallySelectedFilter?: UserListFilterKind; + initialFilter?: 'component' | 'api'; } const CatalogFilterWrapper = withWidth()( @@ -56,11 +57,12 @@ const CatalogFilterWrapper = withWidth()( export const CatalogFilter = ({ initiallySelectedFilter = 'owned', + initialFilter = 'component', }: IProps) => ( - diff --git a/plugins/catalog/src/components/CatalogPage/CatalogPage.tsx b/plugins/catalog/src/components/CatalogPage/CatalogPage.tsx index bd23e5ccdb..702d9f2ed3 100644 --- a/plugins/catalog/src/components/CatalogPage/CatalogPage.tsx +++ b/plugins/catalog/src/components/CatalogPage/CatalogPage.tsx @@ -45,16 +45,17 @@ export const CatalogPage = ({ return ( } - title={`${orgName} Catalog`} - subtitle={`Catalog of software components at ${orgName}`} - themeId="home" - pageTitleOverride="Home" - headerLink={createComponentLink ? createComponentLink() : ''} > diff --git a/plugins/catalog/src/index.ts b/plugins/catalog/src/index.ts index f2f28679a5..7c8d7ac122 100644 --- a/plugins/catalog/src/index.ts +++ b/plugins/catalog/src/index.ts @@ -15,11 +15,9 @@ */ export * from './components/AboutCard'; -export { CatalogLayout } from './components/CatalogPage'; export { CatalogResultListItem } from './components/CatalogResultListItem'; export { CatalogTable } from './components/CatalogTable'; export type { EntityRow as CatalogTableRow } from './components/CatalogTable'; -export { CreateComponentButton } from './components/CreateComponentButton'; export { EntityLayout } from './components/EntityLayout'; export * from './components/EntityOrphanWarning'; export { EntityPageLayout } from './components/EntityPageLayout'; @@ -42,3 +40,4 @@ export { EntitySystemDiagramCard, } from './plugin'; export * from './components/CatalogTable/columns'; +export * from './components/CatalogFilter'; From 45b5fc3a83ef6fd4b87422d09ab9e1aba2865a4f Mon Sep 17 00:00:00 2001 From: Philipp Hugenroth Date: Mon, 12 Jul 2021 17:57:37 +0200 Subject: [PATCH 11/28] Add changeset for combined PR Signed-off-by: Philipp Hugenroth --- .changeset/fuzzy-wolves-travel.md | 5 ----- .changeset/green-lies-hammer.md | 8 ++++++++ 2 files changed, 8 insertions(+), 5 deletions(-) delete mode 100644 .changeset/fuzzy-wolves-travel.md create mode 100644 .changeset/green-lies-hammer.md diff --git a/.changeset/fuzzy-wolves-travel.md b/.changeset/fuzzy-wolves-travel.md deleted file mode 100644 index 6b51be64c0..0000000000 --- a/.changeset/fuzzy-wolves-travel.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/plugin-catalog': patch ---- - -Move filter to CatalogFilter component & wrap them in an accordion on smaller screens to improve the UX diff --git a/.changeset/green-lies-hammer.md b/.changeset/green-lies-hammer.md new file mode 100644 index 0000000000..bf0a9a3995 --- /dev/null +++ b/.changeset/green-lies-hammer.md @@ -0,0 +1,8 @@ +--- +'@backstage/core-components': patch +'@backstage/test-utils': patch +'@backstage/plugin-api-docs': patch +'@backstage/plugin-catalog': patch +--- + +Build a general TablePage component to enforce a more responsive layout for the Catalog & API page. Filters are now wrapped in an accordion on smaller screens, enabling the user to see & interact better with the table. Additionally, a test was added, to check that the responsive wrapping is working for the Catalog page. From 2934eb3a5036e25505ab7f220fba86b66ee27af9 Mon Sep 17 00:00:00 2001 From: Philipp Hugenroth Date: Tue, 13 Jul 2021 20:33:33 +0200 Subject: [PATCH 12/28] [DRAFT] Drawer Filters Signed-off-by: Philipp Hugenroth --- .../layout/ContentHeader/ContentHeader.tsx | 6 +- .../src/layout/ContentHeader/index.ts | 2 +- .../Layout.tsx => Page/PageWithHeader.tsx} | 2 +- .../core-components/src/layout/Page/index.ts | 1 + .../src/layout/TablePage/TablePage.tsx | 77 ----------- packages/core-components/src/layout/index.ts | 1 - .../ApiExplorerPage/ApiExplorerPage.tsx | 61 +-------- .../components/CatalogPage/CatalogPage.tsx | 120 ++++++++++++++---- .../CreateComponentButton.tsx | 38 ++++++ .../CreateComponentButton/indext.ts | 17 +++ .../FilterContainer/FilterContainer.tsx | 57 +++++++++ .../src/components/FilterContainer}/index.ts | 4 +- .../FilteredTableLayout.tsx | 30 +++++ .../components/FilteredTableLayout/index.ts | 17 +++ 14 files changed, 269 insertions(+), 164 deletions(-) rename packages/core-components/src/layout/{TablePage/Layout.tsx => Page/PageWithHeader.tsx} (96%) delete mode 100644 packages/core-components/src/layout/TablePage/TablePage.tsx create mode 100644 plugins/catalog/src/components/CreateComponentButton/CreateComponentButton.tsx create mode 100644 plugins/catalog/src/components/CreateComponentButton/indext.ts create mode 100644 plugins/catalog/src/components/FilterContainer/FilterContainer.tsx rename {packages/core-components/src/layout/TablePage => plugins/catalog/src/components/FilterContainer}/index.ts (85%) create mode 100644 plugins/catalog/src/components/FilteredTableLayout/FilteredTableLayout.tsx create mode 100644 plugins/catalog/src/components/FilteredTableLayout/index.ts diff --git a/packages/core-components/src/layout/ContentHeader/ContentHeader.tsx b/packages/core-components/src/layout/ContentHeader/ContentHeader.tsx index 1e2ad0b5d4..5c773770be 100644 --- a/packages/core-components/src/layout/ContentHeader/ContentHeader.tsx +++ b/packages/core-components/src/layout/ContentHeader/ContentHeader.tsx @@ -59,10 +59,10 @@ const useStyles = (props: ContentHeaderProps) => type DefaultTitleProps = { title?: string; - className: string; + className?: string; }; -const DefaultTitle = ({ +export const ContentHeaderTitle = ({ title = 'Unknown page', className, }: DefaultTitleProps) => ( @@ -95,7 +95,7 @@ export const ContentHeader = ({ const renderedTitle = TitleComponent ? ( ) : ( - + ); return ( diff --git a/packages/core-components/src/layout/ContentHeader/index.ts b/packages/core-components/src/layout/ContentHeader/index.ts index 537a2b6ed9..1a4aacd305 100644 --- a/packages/core-components/src/layout/ContentHeader/index.ts +++ b/packages/core-components/src/layout/ContentHeader/index.ts @@ -14,4 +14,4 @@ * limitations under the License. */ -export { ContentHeader } from './ContentHeader'; +export { ContentHeader, ContentHeaderTitle } from './ContentHeader'; diff --git a/packages/core-components/src/layout/TablePage/Layout.tsx b/packages/core-components/src/layout/Page/PageWithHeader.tsx similarity index 96% rename from packages/core-components/src/layout/TablePage/Layout.tsx rename to packages/core-components/src/layout/Page/PageWithHeader.tsx index 79ad9c24b8..e20788e2e2 100644 --- a/packages/core-components/src/layout/TablePage/Layout.tsx +++ b/packages/core-components/src/layout/Page/PageWithHeader.tsx @@ -23,7 +23,7 @@ export interface IProps extends HeaderProps { themeId: string; } -export const Layout = ({ +export const PageWithHeader = ({ themeId, children, ...props diff --git a/packages/core-components/src/layout/Page/index.ts b/packages/core-components/src/layout/Page/index.ts index d2523e8467..91db73657e 100644 --- a/packages/core-components/src/layout/Page/index.ts +++ b/packages/core-components/src/layout/Page/index.ts @@ -15,3 +15,4 @@ */ export { Page } from './Page'; +export { PageWithHeader } from './PageWithHeader'; diff --git a/packages/core-components/src/layout/TablePage/TablePage.tsx b/packages/core-components/src/layout/TablePage/TablePage.tsx deleted file mode 100644 index 5bf69f4e64..0000000000 --- a/packages/core-components/src/layout/TablePage/TablePage.tsx +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright 2020 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 { Grid } from '@material-ui/core'; - -import { Content, ContentHeader, SupportButton, Button } from '../..'; -import { Layout, IProps as LayoutProps } from './Layout'; -import { Link as RouterLink } from 'react-router-dom'; - -interface ILinkProps { - contentLink?: string; - contentLinkText?: string; -} - -type IProps = LayoutProps & - ILinkProps & { - contentTitle: string; - supportMessage: string; - filter: React.ReactNode; - }; - -const TablePageLink = ({ contentLink, contentLinkText }: ILinkProps) => { - return contentLink && contentLinkText ? ( - - ) : null; -}; - -export const TablePage = ({ - supportMessage, - filter, - children, - contentTitle, - contentLink, - contentLinkText, - ...props -}: React.PropsWithChildren) => ( - - - - - {supportMessage} - - - - {filter} - - - {children} - - - - -); diff --git a/packages/core-components/src/layout/index.ts b/packages/core-components/src/layout/index.ts index dce33c7f2a..4abde642dc 100644 --- a/packages/core-components/src/layout/index.ts +++ b/packages/core-components/src/layout/index.ts @@ -29,4 +29,3 @@ export * from './Sidebar'; export * from './SignInPage'; export * from './TabbedCard'; export * from './Breadcrumbs'; -export * from './TablePage'; diff --git a/plugins/api-docs/src/components/ApiExplorerPage/ApiExplorerPage.tsx b/plugins/api-docs/src/components/ApiExplorerPage/ApiExplorerPage.tsx index bcc18e4021..32fab2c1ec 100644 --- a/plugins/api-docs/src/components/ApiExplorerPage/ApiExplorerPage.tsx +++ b/plugins/api-docs/src/components/ApiExplorerPage/ApiExplorerPage.tsx @@ -14,29 +14,10 @@ * limitations under the License. */ -import { TableColumn, TablePage } from '@backstage/core-components'; -import { configApiRef, useApi, useRouteRef } from '@backstage/core-plugin-api'; -import { - CatalogFilter, - CatalogTable, - CatalogTableRow, -} from '@backstage/plugin-catalog'; -import { - EntityListProvider, - UserListFilterKind, -} from '@backstage/plugin-catalog-react'; +import { TableColumn } from '@backstage/core-components'; +import { CatalogTableRow } from '@backstage/plugin-catalog'; +import { UserListFilterKind } from '@backstage/plugin-catalog-react'; import React from 'react'; -import { createComponentRouteRef } from '../../routes'; - -const defaultColumns: TableColumn[] = [ - CatalogTable.columns.createNameColumn({ defaultKind: 'API' }), - CatalogTable.columns.createSystemColumn(), - CatalogTable.columns.createOwnerColumn(), - CatalogTable.columns.createSpecTypeColumn(), - CatalogTable.columns.createSpecLifecycleColumn(), - CatalogTable.columns.createMetadataDescriptionColumn(), - CatalogTable.columns.createTagsColumn(), -]; interface IApiExplorerePageFilterProps { initiallySelectedFilter?: UserListFilterKind; @@ -46,36 +27,6 @@ export type ApiExplorerPageProps = IApiExplorerePageFilterProps & { columns?: TableColumn[]; }; -export const ApiExplorerPage = ({ - initiallySelectedFilter = 'all', - columns, -}: ApiExplorerPageProps) => { - const createComponentLink = useRouteRef(createComponentRouteRef); - const configApi = useApi(configApiRef); - const generatedSubtitle = `${ - configApi.getOptionalString('organization.name') ?? 'Backstage' - } API Explorer`; - - return ( - - - } - > - - - - ); -}; +export const ApiExplorerPage = ({}: ApiExplorerPageProps) => ( +
Please revert me...
+); diff --git a/plugins/catalog/src/components/CatalogPage/CatalogPage.tsx b/plugins/catalog/src/components/CatalogPage/CatalogPage.tsx index 702d9f2ed3..50fb2433df 100644 --- a/plugins/catalog/src/components/CatalogPage/CatalogPage.tsx +++ b/plugins/catalog/src/components/CatalogPage/CatalogPage.tsx @@ -14,18 +14,35 @@ * limitations under the License. */ -import React from 'react'; import { + Content, + ContentHeader, + ContentHeaderTitle, + PageWithHeader, + SupportButton, + TableColumn, + TableProps, +} from '@backstage/core-components'; +import { configApiRef, useApi } from '@backstage/core-plugin-api'; +import { + EntityKindPicker, + EntityLifecyclePicker, EntityListProvider, + EntityOwnerPicker, + EntityTagPicker, + EntityTypePicker, UserListFilterKind, + UserListPicker, } from '@backstage/plugin-catalog-react'; +import { BackstageTheme } from '@backstage/theme'; +import { Box, Grid, IconButton, useMediaQuery } from '@material-ui/core'; +import FilterListIcon from '@material-ui/icons/FilterList'; +import React, { useState } from 'react'; import { CatalogTable } from '../CatalogTable'; -import { configApiRef, useApi, useRouteRef } from '@backstage/core-plugin-api'; - import { EntityRow } from '../CatalogTable/types'; -import { TableColumn, TableProps, TablePage } from '@backstage/core-components'; -import { CatalogFilter } from '../CatalogFilter'; -import { createComponentRouteRef } from '../../routes'; +import { CreateComponentButton } from '../CreateComponentButton/CreateComponentButton'; +import { FilterContainer } from '../FilterContainer'; +import { FilteredTableLayout } from '../FilteredTableLayout'; export type CatalogPageProps = { initiallySelectedFilter?: UserListFilterKind; @@ -33,32 +50,87 @@ export type CatalogPageProps = { actions?: TableProps['actions']; }; +const CatalogPageHeaderAction = ({ + showFilter, + toggleFilter, + isMidSizeScreen, +}: { + showFilter: boolean; + toggleFilter: (showFilter: boolean) => void; + isMidSizeScreen: boolean; +}) => + isMidSizeScreen ? ( + + + toggleFilter(!showFilter)}> + + + + ) : ( + + ); + +const CatalogPageHeader = ({ + children, + ...props +}: React.PropsWithChildren<{ + showFilter: boolean; + toggleFilter: (showFilter: boolean) => void; + isMidSizeScreen: boolean; +}>) => { + return ( + } + > + {children} + + ); +}; + export const CatalogPage = ({ columns, actions, initiallySelectedFilter = 'owned', }: CatalogPageProps) => { + const [showFilter, toggleFilter] = useState(false); + const isMidSizeScreen = useMediaQuery(theme => + theme.breakpoints.down('md'), + ); + const orgName = useApi(configApiRef).getOptionalString('organization.name') ?? 'Backstage'; - const createComponentLink = useRouteRef(createComponentRouteRef); return ( - - - } - > - - - + + + + + All your software catalog entities + + + + + + + + + + + + ); }; diff --git a/plugins/catalog/src/components/CreateComponentButton/CreateComponentButton.tsx b/plugins/catalog/src/components/CreateComponentButton/CreateComponentButton.tsx new file mode 100644 index 0000000000..482a0c0a3c --- /dev/null +++ b/plugins/catalog/src/components/CreateComponentButton/CreateComponentButton.tsx @@ -0,0 +1,38 @@ +/* + * Copyright 2021 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 as RouterLink } from 'react-router-dom'; +import { Button } from '@material-ui/core'; +import { createComponentRouteRef } from '../../routes'; +import { useRouteRef } from '@backstage/core-plugin-api'; + +export const CreateComponentButton = () => { + const createComponentLink = useRouteRef(createComponentRouteRef); + + if (!createComponentLink) return null; + + return ( + + ); +}; diff --git a/plugins/catalog/src/components/CreateComponentButton/indext.ts b/plugins/catalog/src/components/CreateComponentButton/indext.ts new file mode 100644 index 0000000000..edf59d18a6 --- /dev/null +++ b/plugins/catalog/src/components/CreateComponentButton/indext.ts @@ -0,0 +1,17 @@ +/* + * Copyright 2021 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 { CreateComponentButton } from './CreateComponentButton'; diff --git a/plugins/catalog/src/components/FilterContainer/FilterContainer.tsx b/plugins/catalog/src/components/FilterContainer/FilterContainer.tsx new file mode 100644 index 0000000000..4083062478 --- /dev/null +++ b/plugins/catalog/src/components/FilterContainer/FilterContainer.tsx @@ -0,0 +1,57 @@ +/* + * Copyright 2021 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 { Box, Drawer, Grid } from '@material-ui/core'; +import React from 'react'; + +interface IProps { + showFilter: boolean; + toggleFilter: (showFilter: boolean) => void; + isMidSizeScreen: boolean; +} + +export const FilterContainer = ({ + children, + showFilter, + toggleFilter, + isMidSizeScreen, +}: React.PropsWithChildren) => + isMidSizeScreen ? ( + { + toggleFilter(false); + }} + elevation={0} + disableAutoFocus + PaperProps={{ + style: { position: 'absolute', width: '250px' }, + }} + BackdropProps={{ style: { position: 'absolute' } }} + ModalProps={{ + container: document.getElementById('drawer-container'), + disableEnforceFocus: true, + style: { position: 'absolute' }, + }} + variant="temporary" + > + {children} + + ) : ( + + {children} + + ); diff --git a/packages/core-components/src/layout/TablePage/index.ts b/plugins/catalog/src/components/FilterContainer/index.ts similarity index 85% rename from packages/core-components/src/layout/TablePage/index.ts rename to plugins/catalog/src/components/FilterContainer/index.ts index 5df8aa4c40..a25071e3c5 100644 --- a/packages/core-components/src/layout/TablePage/index.ts +++ b/plugins/catalog/src/components/FilterContainer/index.ts @@ -1,5 +1,5 @@ /* - * Copyright 2020 The Backstage Authors + * Copyright 2021 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. @@ -14,4 +14,4 @@ * limitations under the License. */ -export { TablePage } from './TablePage'; +export { FilterContainer } from './FilterContainer'; diff --git a/plugins/catalog/src/components/FilteredTableLayout/FilteredTableLayout.tsx b/plugins/catalog/src/components/FilteredTableLayout/FilteredTableLayout.tsx new file mode 100644 index 0000000000..a0debe618f --- /dev/null +++ b/plugins/catalog/src/components/FilteredTableLayout/FilteredTableLayout.tsx @@ -0,0 +1,30 @@ +/* + * Copyright 2021 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 { Grid } from '@material-ui/core'; + +interface IProps {} + +export const FilteredTableLayout = ({ + children, +}: React.PropsWithChildren) => { + return ( + + {children} + + ); +}; diff --git a/plugins/catalog/src/components/FilteredTableLayout/index.ts b/plugins/catalog/src/components/FilteredTableLayout/index.ts new file mode 100644 index 0000000000..77d49a773a --- /dev/null +++ b/plugins/catalog/src/components/FilteredTableLayout/index.ts @@ -0,0 +1,17 @@ +/* + * Copyright 2021 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 { FilteredTableLayout } from './FilteredTableLayout'; From f3b58ecd8ea57df25ccae137672e47bebdf38d1c Mon Sep 17 00:00:00 2001 From: Philipp Hugenroth Date: Wed, 14 Jul 2021 11:10:08 +0200 Subject: [PATCH 13/28] Reorganize Drawer & move drawer state to EntityListProvider Signed-off-by: Philipp Hugenroth --- .../src/hooks/useEntityListProvider.tsx | 7 ++ .../components/CatalogPage/CatalogPage.tsx | 79 ++++--------------- .../CatalogPage/CatalogPageHeader.tsx | 50 ++++++++++++ .../CreateComponentButton.tsx | 4 +- .../FilterContainer.tsx | 40 ++++------ .../TableContainer.tsx} | 9 ++- .../components/FilteredTableLayout/index.ts | 2 + 7 files changed, 97 insertions(+), 94 deletions(-) create mode 100644 plugins/catalog/src/components/CatalogPage/CatalogPageHeader.tsx rename plugins/catalog/src/components/{FilterContainer => FilteredTableLayout}/FilterContainer.tsx (53%) rename plugins/catalog/src/components/{FilterContainer/index.ts => FilteredTableLayout/TableContainer.tsx} (74%) diff --git a/plugins/catalog-react/src/hooks/useEntityListProvider.tsx b/plugins/catalog-react/src/hooks/useEntityListProvider.tsx index 8ca3efd243..7db2205deb 100644 --- a/plugins/catalog-react/src/hooks/useEntityListProvider.tsx +++ b/plugins/catalog-react/src/hooks/useEntityListProvider.tsx @@ -84,6 +84,9 @@ export type EntityListContextProps< */ queryParameters: Partial>; + showFiltersDrawer: boolean; + toggleFiltersDrawer: (showFiltersDrawer: boolean) => void; + loading: boolean; error?: Error; }; @@ -108,6 +111,8 @@ export const EntityListProvider = ({ const [requestedFilters, setRequestedFilters] = useState( {} as EntityFilters, ); + // Show + const [showFiltersDrawer, toggleFiltersDrawer] = useState(false); const [outputState, setOutputState] = useState>({ appliedFilters: {} as EntityFilters, entities: [], @@ -203,6 +208,8 @@ export const EntityListProvider = ({ updateFilters, queryParameters: outputState.queryParameters, loading, + showFiltersDrawer, + toggleFiltersDrawer, error, }} > diff --git a/plugins/catalog/src/components/CatalogPage/CatalogPage.tsx b/plugins/catalog/src/components/CatalogPage/CatalogPage.tsx index 50fb2433df..3df46ff0c0 100644 --- a/plugins/catalog/src/components/CatalogPage/CatalogPage.tsx +++ b/plugins/catalog/src/components/CatalogPage/CatalogPage.tsx @@ -16,8 +16,6 @@ import { Content, - ContentHeader, - ContentHeaderTitle, PageWithHeader, SupportButton, TableColumn, @@ -34,15 +32,16 @@ import { UserListFilterKind, UserListPicker, } from '@backstage/plugin-catalog-react'; -import { BackstageTheme } from '@backstage/theme'; -import { Box, Grid, IconButton, useMediaQuery } from '@material-ui/core'; -import FilterListIcon from '@material-ui/icons/FilterList'; -import React, { useState } from 'react'; +import React from 'react'; import { CatalogTable } from '../CatalogTable'; import { EntityRow } from '../CatalogTable/types'; import { CreateComponentButton } from '../CreateComponentButton/CreateComponentButton'; -import { FilterContainer } from '../FilterContainer'; -import { FilteredTableLayout } from '../FilteredTableLayout'; +import { + FilteredTableLayout, + TableContainer, + FilterContainer, +} from '../FilteredTableLayout'; +import { CatalogPageHeader } from './CatalogPageHeader'; export type CatalogPageProps = { initiallySelectedFilter?: UserListFilterKind; @@ -50,74 +49,24 @@ export type CatalogPageProps = { actions?: TableProps['actions']; }; -const CatalogPageHeaderAction = ({ - showFilter, - toggleFilter, - isMidSizeScreen, -}: { - showFilter: boolean; - toggleFilter: (showFilter: boolean) => void; - isMidSizeScreen: boolean; -}) => - isMidSizeScreen ? ( - - - toggleFilter(!showFilter)}> - - - - ) : ( - - ); - -const CatalogPageHeader = ({ - children, - ...props -}: React.PropsWithChildren<{ - showFilter: boolean; - toggleFilter: (showFilter: boolean) => void; - isMidSizeScreen: boolean; -}>) => { - return ( - } - > - {children} - - ); -}; - export const CatalogPage = ({ columns, actions, initiallySelectedFilter = 'owned', }: CatalogPageProps) => { - const [showFilter, toggleFilter] = useState(false); - const isMidSizeScreen = useMediaQuery(theme => - theme.breakpoints.down('md'), - ); - const orgName = useApi(configApiRef).getOptionalString('organization.name') ?? 'Backstage'; return ( - - - All your software catalog entities - + + + All your software catalog entities + - + - + - + diff --git a/plugins/catalog/src/components/CatalogPage/CatalogPageHeader.tsx b/plugins/catalog/src/components/CatalogPage/CatalogPageHeader.tsx new file mode 100644 index 0000000000..f628aef596 --- /dev/null +++ b/plugins/catalog/src/components/CatalogPage/CatalogPageHeader.tsx @@ -0,0 +1,50 @@ +/* + * Copyright 2021 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 { ContentHeader, ContentHeaderTitle } from '@backstage/core-components'; +import { useEntityListProvider } from '@backstage/plugin-catalog-react'; +import { BackstageTheme } from '@backstage/theme'; +import { Box, IconButton, useMediaQuery } from '@material-ui/core'; +import FilterListIcon from '@material-ui/icons/FilterList'; +import React from 'react'; + +const CatalogPageHeaderAction = () => { + const isMidSizeScreen = useMediaQuery(theme => + theme.breakpoints.down('md'), + ); + const { showFiltersDrawer, toggleFiltersDrawer } = useEntityListProvider(); + + return isMidSizeScreen ? ( + + + toggleFiltersDrawer(!showFiltersDrawer)}> + + + + ) : ( + + ); +}; + +export const CatalogPageHeader = ({ + children, +}: React.PropsWithChildren<{}>) => { + return ( + }> + {children} + + ); +}; diff --git a/plugins/catalog/src/components/CreateComponentButton/CreateComponentButton.tsx b/plugins/catalog/src/components/CreateComponentButton/CreateComponentButton.tsx index 482a0c0a3c..4be93c1aa0 100644 --- a/plugins/catalog/src/components/CreateComponentButton/CreateComponentButton.tsx +++ b/plugins/catalog/src/components/CreateComponentButton/CreateComponentButton.tsx @@ -23,9 +23,7 @@ import { useRouteRef } from '@backstage/core-plugin-api'; export const CreateComponentButton = () => { const createComponentLink = useRouteRef(createComponentRouteRef); - if (!createComponentLink) return null; - - return ( + return !createComponentLink ? null : ( ( diff --git a/plugins/catalog/src/components/CatalogPage/CatalogPage.tsx b/plugins/catalog/src/components/CatalogPage/CatalogPage.tsx index 3df46ff0c0..5da46eec97 100644 --- a/plugins/catalog/src/components/CatalogPage/CatalogPage.tsx +++ b/plugins/catalog/src/components/CatalogPage/CatalogPage.tsx @@ -16,6 +16,7 @@ import { Content, + ContentHeader, PageWithHeader, SupportButton, TableColumn, @@ -41,7 +42,6 @@ import { TableContainer, FilterContainer, } from '../FilteredTableLayout'; -import { CatalogPageHeader } from './CatalogPageHeader'; export type CatalogPageProps = { initiallySelectedFilter?: UserListFilterKind; @@ -60,11 +60,11 @@ export const CatalogPage = ({ return ( + + + All your software catalog entities + - - - All your software catalog entities - + + + + + - + ); }; ``` @@ -141,14 +143,18 @@ export const CustomCatalogPage = () => { return ( ... -
-
- + + +
... }; diff --git a/packages/core-components/src/components/SupportButton/SupportButton.tsx b/packages/core-components/src/components/SupportButton/SupportButton.tsx index 53c9b20273..45012e50a4 100644 --- a/packages/core-components/src/components/SupportButton/SupportButton.tsx +++ b/packages/core-components/src/components/SupportButton/SupportButton.tsx @@ -100,8 +100,9 @@ export const SupportButton = ({ title, children }: SupportButtonProps) => { color="primary" onClick={onClickHandler} > - - + + + Support }, })); -type DefaultTitleProps = { +type ContentHeaderTitleProps = { title?: string; className?: string; }; @@ -65,7 +65,7 @@ type DefaultTitleProps = { const ContentHeaderTitle = ({ title = 'Unknown page', className, -}: DefaultTitleProps) => ( +}: ContentHeaderTitleProps) => ( { +type ThemedHeaderProps = ComponentProps & { themeId: string; -} +}; export const PageWithHeader = ({ themeId, children, ...props -}: React.PropsWithChildren) => ( +}: React.PropsWithChildren) => (
{children} diff --git a/plugins/api-docs/src/components/ApiExplorerPage/ApiExplorerPage.tsx b/plugins/api-docs/src/components/ApiExplorerPage/ApiExplorerPage.tsx index bf62d06b44..361ce7b55b 100644 --- a/plugins/api-docs/src/components/ApiExplorerPage/ApiExplorerPage.tsx +++ b/plugins/api-docs/src/components/ApiExplorerPage/ApiExplorerPage.tsx @@ -25,8 +25,8 @@ import { configApiRef, useApi, useRouteRef } from '@backstage/core-plugin-api'; import { CatalogTable, CatalogTableRow, - FilteredTableLayout, - TableContainer, + FilteredEntityLayout, + EntityListContainer, FilterContainer, } from '@backstage/plugin-catalog'; import { @@ -54,11 +54,8 @@ const defaultColumns: TableColumn[] = [ CatalogTable.columns.createTagsColumn(), ]; -interface IApiExplorerePageFilterProps { +type ApiExplorerPageProps = { initiallySelectedFilter?: UserListFilterKind; -} - -export type ApiExplorerPageProps = IApiExplorerePageFilterProps & { columns?: TableColumn[]; }; @@ -94,7 +91,7 @@ export const ApiExplorerPage = ({ All your APIs - + - + - - + + diff --git a/plugins/catalog-react/src/hooks/useEntityListProvider.tsx b/plugins/catalog-react/src/hooks/useEntityListProvider.tsx index 7db2205deb..8ca3efd243 100644 --- a/plugins/catalog-react/src/hooks/useEntityListProvider.tsx +++ b/plugins/catalog-react/src/hooks/useEntityListProvider.tsx @@ -84,9 +84,6 @@ export type EntityListContextProps< */ queryParameters: Partial>; - showFiltersDrawer: boolean; - toggleFiltersDrawer: (showFiltersDrawer: boolean) => void; - loading: boolean; error?: Error; }; @@ -111,8 +108,6 @@ export const EntityListProvider = ({ const [requestedFilters, setRequestedFilters] = useState( {} as EntityFilters, ); - // Show - const [showFiltersDrawer, toggleFiltersDrawer] = useState(false); const [outputState, setOutputState] = useState>({ appliedFilters: {} as EntityFilters, entities: [], @@ -208,8 +203,6 @@ export const EntityListProvider = ({ updateFilters, queryParameters: outputState.queryParameters, loading, - showFiltersDrawer, - toggleFiltersDrawer, error, }} > diff --git a/plugins/catalog-react/src/testUtils/providers.tsx b/plugins/catalog-react/src/testUtils/providers.tsx index b8fdd3d8fe..1f9e4f40d6 100644 --- a/plugins/catalog-react/src/testUtils/providers.tsx +++ b/plugins/catalog-react/src/testUtils/providers.tsx @@ -32,7 +32,6 @@ export const MockEntityListContextProvider = ({ const [filters, setFilters] = useState( value.filters ?? {}, ); - const [showFiltersDrawer, toggleFiltersDrawer] = useState(false); const updateFilters = useCallback( ( update: @@ -57,8 +56,6 @@ export const MockEntityListContextProvider = ({ filters, loading: false, queryParameters: {}, - showFiltersDrawer, - toggleFiltersDrawer, }; // Extract value.filters to avoid overwriting it; some tests exercise filter updates. The value diff --git a/plugins/catalog/src/components/CatalogFilter/CatalogFilter.tsx b/plugins/catalog/src/components/CatalogFilter/CatalogFilter.tsx deleted file mode 100644 index 6704f429ee..0000000000 --- a/plugins/catalog/src/components/CatalogFilter/CatalogFilter.tsx +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright 2020 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 { - EntityKindPicker, - EntityLifecyclePicker, - EntityOwnerPicker, - EntityTagPicker, - EntityTypePicker, - UserListFilterKind, - UserListPicker, -} from '@backstage/plugin-catalog-react'; -import { - Accordion, - AccordionDetails, - AccordionSummary, - Grid, - isWidthDown, - Typography, - withWidth, -} from '@material-ui/core'; -import { Breakpoint } from '@material-ui/core/styles/createBreakpoints'; -import ExpandMore from '@material-ui/icons/ExpandMore'; -import React, { PropsWithChildren } from 'react'; - -interface IProps { - initiallySelectedFilter?: UserListFilterKind; - initialFilter?: 'component' | 'api'; -} - -const CatalogFilterWrapper = withWidth()( - ({ width, children }: PropsWithChildren<{ width: Breakpoint }>) => - isWidthDown('md', width) ? ( - - }> - Filters - - {children} - - ) : ( - {children} - ), -); - -export const CatalogFilter = ({ - initiallySelectedFilter = 'owned', - initialFilter = 'component', -}: IProps) => ( - - - - - - - - - - - - - - -); diff --git a/plugins/catalog/src/components/CatalogPage/CatalogPage.tsx b/plugins/catalog/src/components/CatalogPage/CatalogPage.tsx index 5da46eec97..0fe3504c6d 100644 --- a/plugins/catalog/src/components/CatalogPage/CatalogPage.tsx +++ b/plugins/catalog/src/components/CatalogPage/CatalogPage.tsx @@ -38,10 +38,10 @@ import { CatalogTable } from '../CatalogTable'; import { EntityRow } from '../CatalogTable/types'; import { CreateComponentButton } from '../CreateComponentButton/CreateComponentButton'; import { - FilteredTableLayout, - TableContainer, + FilteredEntityLayout, + EntityListContainer, FilterContainer, -} from '../FilteredTableLayout'; +} from '../FilteredEntityLayout'; export type CatalogPageProps = { initiallySelectedFilter?: UserListFilterKind; @@ -65,7 +65,7 @@ export const CatalogPage = ({ All your software catalog entities - + - + - - + + diff --git a/plugins/catalog/src/components/CreateComponentButton/CreateComponentButton.tsx b/plugins/catalog/src/components/CreateComponentButton/CreateComponentButton.tsx index 4be93c1aa0..ae2fc4b718 100644 --- a/plugins/catalog/src/components/CreateComponentButton/CreateComponentButton.tsx +++ b/plugins/catalog/src/components/CreateComponentButton/CreateComponentButton.tsx @@ -23,7 +23,7 @@ import { useRouteRef } from '@backstage/core-plugin-api'; export const CreateComponentButton = () => { const createComponentLink = useRouteRef(createComponentRouteRef); - return !createComponentLink ? null : ( + return createComponentLink ? ( - ); + ) : null; }; diff --git a/plugins/catalog/src/components/CreateComponentButton/indext.ts b/plugins/catalog/src/components/CreateComponentButton/index.ts similarity index 100% rename from plugins/catalog/src/components/CreateComponentButton/indext.ts rename to plugins/catalog/src/components/CreateComponentButton/index.ts diff --git a/plugins/catalog/src/components/FilteredTableLayout/TableContainer.tsx b/plugins/catalog/src/components/FilteredEntityLayout/EntityListContainer.tsx similarity index 84% rename from plugins/catalog/src/components/FilteredTableLayout/TableContainer.tsx rename to plugins/catalog/src/components/FilteredEntityLayout/EntityListContainer.tsx index f5f5ae0de6..a39ef76b87 100644 --- a/plugins/catalog/src/components/FilteredTableLayout/TableContainer.tsx +++ b/plugins/catalog/src/components/FilteredEntityLayout/EntityListContainer.tsx @@ -15,9 +15,9 @@ */ import { Grid } from '@material-ui/core'; -import React from 'react'; +import React, { PropsWithChildren } from 'react'; -export const TableContainer = ({ children }: React.PropsWithChildren<{}>) => ( +export const EntityListContainer = ({ children }: PropsWithChildren<{}>) => ( {children} diff --git a/plugins/catalog/src/components/FilteredEntityLayout/FilterContainer.tsx b/plugins/catalog/src/components/FilteredEntityLayout/FilterContainer.tsx new file mode 100644 index 0000000000..6502811332 --- /dev/null +++ b/plugins/catalog/src/components/FilteredEntityLayout/FilterContainer.tsx @@ -0,0 +1,68 @@ +/* + * Copyright 2021 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 { BackstageTheme } from '@backstage/theme'; +import { + Box, + Button, + Drawer, + Grid, + useMediaQuery, + useTheme, +} from '@material-ui/core'; +import FilterListIcon from '@material-ui/icons/FilterList'; +import React, { useState } from 'react'; + +export const FilterContainer = ({ children }: React.PropsWithChildren<{}>) => { + const isMidSizeScreen = useMediaQuery(theme => + theme.breakpoints.down('md'), + ); + const theme = useTheme(); + const [showFiltersDrawer, toggleFiltersDrawer] = useState(false); + + return isMidSizeScreen ? ( + <> + + { + toggleFiltersDrawer(false); + }} + elevation={0} + anchor="left" + disableAutoFocus + keepMounted + variant="temporary" + > + {children} + + + ) : ( + + {children} + + ); +}; diff --git a/plugins/catalog/src/components/CatalogFilter/index.ts b/plugins/catalog/src/components/FilteredEntityLayout/FilteredEntityLayout.tsx similarity index 65% rename from plugins/catalog/src/components/CatalogFilter/index.ts rename to plugins/catalog/src/components/FilteredEntityLayout/FilteredEntityLayout.tsx index dc57ef02e2..628ad9fee6 100644 --- a/plugins/catalog/src/components/CatalogFilter/index.ts +++ b/plugins/catalog/src/components/FilteredEntityLayout/FilteredEntityLayout.tsx @@ -1,5 +1,5 @@ /* - * Copyright 2020 The Backstage Authors + * Copyright 2021 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. @@ -14,4 +14,11 @@ * limitations under the License. */ -export { CatalogFilter } from './CatalogFilter'; +import { Grid } from '@material-ui/core'; +import React, { PropsWithChildren } from 'react'; + +export const FilteredEntityLayout = ({ children }: PropsWithChildren<{}>) => ( + + {children} + +); diff --git a/plugins/catalog/src/components/FilteredTableLayout/index.ts b/plugins/catalog/src/components/FilteredEntityLayout/index.ts similarity index 84% rename from plugins/catalog/src/components/FilteredTableLayout/index.ts rename to plugins/catalog/src/components/FilteredEntityLayout/index.ts index 9fa89259ab..ded61a4edc 100644 --- a/plugins/catalog/src/components/FilteredTableLayout/index.ts +++ b/plugins/catalog/src/components/FilteredEntityLayout/index.ts @@ -14,6 +14,6 @@ * limitations under the License. */ -export { FilteredTableLayout } from './FilteredTableLayout'; +export { FilteredEntityLayout } from './FilteredEntityLayout'; export { FilterContainer } from './FilterContainer'; -export { TableContainer } from './TableContainer'; +export { EntityListContainer } from './EntityListContainer'; diff --git a/plugins/catalog/src/components/FilteredTableLayout/FilterContainer.tsx b/plugins/catalog/src/components/FilteredTableLayout/FilterContainer.tsx deleted file mode 100644 index 0fa26f6c66..0000000000 --- a/plugins/catalog/src/components/FilteredTableLayout/FilterContainer.tsx +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright 2021 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 { Box, Drawer, Grid, useMediaQuery } from '@material-ui/core'; -import { useEntityListProvider } from '@backstage/plugin-catalog-react'; -import { BackstageTheme } from '@backstage/theme'; -import React from 'react'; - -export const FilterContainer = ({ children }: React.PropsWithChildren<{}>) => { - const isMidSizeScreen = useMediaQuery(theme => - theme.breakpoints.down('md'), - ); - const { showFiltersDrawer, toggleFiltersDrawer } = useEntityListProvider(); - - return isMidSizeScreen ? ( - { - toggleFiltersDrawer(false); - }} - PaperProps={{ - style: { width: '300px' }, - }} - elevation={0} - anchor="left" - disableAutoFocus - keepMounted - variant="temporary" - > - {children} - - ) : ( - - {children} - - ); -}; diff --git a/plugins/catalog/src/components/FilteredTableLayout/FilteredTableLayout.tsx b/plugins/catalog/src/components/FilteredTableLayout/FilteredTableLayout.tsx deleted file mode 100644 index 0820a4d865..0000000000 --- a/plugins/catalog/src/components/FilteredTableLayout/FilteredTableLayout.tsx +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright 2021 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 { useEntityListProvider } from '@backstage/plugin-catalog-react'; -import { BackstageTheme } from '@backstage/theme'; -import { Box, Button, Grid, useMediaQuery, useTheme } from '@material-ui/core'; -import FilterListIcon from '@material-ui/icons/FilterList'; -import React, { Fragment } from 'react'; - -interface IProps {} - -export const FilteredTableLayout = ({ - children, -}: React.PropsWithChildren) => { - const isMidSizeScreen = useMediaQuery(theme => - theme.breakpoints.down('md'), - ); - const { showFiltersDrawer, toggleFiltersDrawer } = useEntityListProvider(); - const theme = useTheme(); - - return ( - - {isMidSizeScreen && ( - - )} - - {children} - - - ); -}; diff --git a/plugins/catalog/src/index.ts b/plugins/catalog/src/index.ts index 8585177cd9..4b348580f7 100644 --- a/plugins/catalog/src/index.ts +++ b/plugins/catalog/src/index.ts @@ -40,5 +40,4 @@ export { EntitySystemDiagramCard, } from './plugin'; export * from './components/CatalogTable/columns'; -export * from './components/CatalogFilter'; -export * from './components/FilteredTableLayout'; +export * from './components/FilteredEntityLayout'; From 5858056f793659f2809913806b34a74240939694 Mon Sep 17 00:00:00 2001 From: Philipp Hugenroth Date: Fri, 16 Jul 2021 13:53:49 +0200 Subject: [PATCH 22/28] Update API reports Add Title to Filters Drawer Signed-off-by: Philipp Hugenroth --- packages/core-components/api-report.md | 4 +-- .../src/layout/Page/PageWithHeader.tsx | 6 ++-- plugins/api-docs/api-report.md | 6 ++-- plugins/catalog/api-report.md | 30 +++++++------------ .../FilteredEntityLayout/FilterContainer.tsx | 12 +++++++- 5 files changed, 30 insertions(+), 28 deletions(-) diff --git a/packages/core-components/api-report.md b/packages/core-components/api-report.md index bfc6852a97..e8d3214beb 100644 --- a/packages/core-components/api-report.md +++ b/packages/core-components/api-report.md @@ -1202,7 +1202,7 @@ export const Page: ({ children, }: PropsWithChildren) => JSX.Element; -// Warning: (ae-forgotten-export) The symbol "IProps" needs to be exported by the entry point index.d.ts +// Warning: (ae-forgotten-export) The symbol "ThemedHeaderProps" needs to be exported by the entry point index.d.ts // Warning: (ae-missing-release-tag) "PageWithHeader" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) @@ -1210,7 +1210,7 @@ export const PageWithHeader: ({ themeId, children, ...props -}: React_2.PropsWithChildren) => JSX.Element; +}: React_2.PropsWithChildren) => JSX.Element; // Warning: (ae-missing-release-tag) "Progress" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // diff --git a/packages/core-components/src/layout/Page/PageWithHeader.tsx b/packages/core-components/src/layout/Page/PageWithHeader.tsx index 4155805476..6095b4df16 100644 --- a/packages/core-components/src/layout/Page/PageWithHeader.tsx +++ b/packages/core-components/src/layout/Page/PageWithHeader.tsx @@ -14,12 +14,12 @@ * limitations under the License. */ -import React, { ComponentProps } from 'react'; +import React, { PropsWithChildren, ComponentProps } from 'react'; import { Header } from '../Header'; import { Page } from './Page'; -type ThemedHeaderProps = ComponentProps & { +export type ThemedHeaderProps = ComponentProps & { themeId: string; }; @@ -27,7 +27,7 @@ export const PageWithHeader = ({ themeId, children, ...props -}: React.PropsWithChildren) => ( +}: PropsWithChildren) => (
{children} diff --git a/plugins/api-docs/api-report.md b/plugins/api-docs/api-report.md index a368cf5675..639485a42d 100644 --- a/plugins/api-docs/api-report.md +++ b/plugins/api-docs/api-report.md @@ -52,14 +52,16 @@ const apiDocsPlugin: BackstagePlugin< export { apiDocsPlugin }; export { apiDocsPlugin as plugin }; -// Warning: (ae-forgotten-export) The symbol "ApiExplorerPageProps" needs to be exported by the entry point index.d.ts // Warning: (ae-missing-release-tag) "ApiExplorerPage" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) export const ApiExplorerPage: ({ initiallySelectedFilter, columns, -}: ApiExplorerPageProps) => JSX.Element; +}: { + initiallySelectedFilter?: UserListFilterKind | undefined; + columns?: TableColumn[] | undefined; +}) => JSX.Element; // Warning: (ae-missing-release-tag) "ApiTypeTitle" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // diff --git a/plugins/catalog/api-report.md b/plugins/catalog/api-report.md index b3169d5c29..4ed69230ec 100644 --- a/plugins/catalog/api-report.md +++ b/plugins/catalog/api-report.md @@ -48,15 +48,6 @@ export const AboutField: ({ // @public (undocumented) export const CatalogEntityPage: () => JSX.Element; -// Warning: (ae-forgotten-export) The symbol "IProps" needs to be exported by the entry point index.d.ts -// Warning: (ae-missing-release-tag) "CatalogFilter" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public (undocumented) -export const CatalogFilter: ({ - initiallySelectedFilter, - initialFilter, -}: IProps) => JSX.Element; - // Warning: (ae-forgotten-export) The symbol "CatalogPageProps" needs to be exported by the entry point index.d.ts // Warning: (ae-missing-release-tag) "CatalogIndexPage" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // @@ -247,6 +238,13 @@ export const EntityLinksCard: ({ variant?: 'gridItem' | undefined; }) => JSX.Element; +// Warning: (ae-missing-release-tag) "EntityListContainer" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export const EntityListContainer: ({ + children, +}: PropsWithChildren<{}>) => JSX.Element; + // Warning: (ae-missing-release-tag) "EntityOrphanWarning" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public @@ -292,13 +290,12 @@ export const FilterContainer: ({ children, }: React_2.PropsWithChildren<{}>) => JSX.Element; -// Warning: (ae-forgotten-export) The symbol "IProps" needs to be exported by the entry point index.d.ts -// Warning: (ae-missing-release-tag) "FilteredTableLayout" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// Warning: (ae-missing-release-tag) "FilteredEntityLayout" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) -export const FilteredTableLayout: ({ +export const FilteredEntityLayout: ({ children, -}: React_2.PropsWithChildren) => JSX.Element; +}: PropsWithChildren<{}>) => JSX.Element; // Warning: (ae-missing-release-tag) "isComponentType" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // @@ -329,13 +326,6 @@ export const Router: ({ EntityPage?: React_2.ComponentType<{}> | undefined; }) => JSX.Element; -// Warning: (ae-missing-release-tag) "TableContainer" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public (undocumented) -export const TableContainer: ({ - children, -}: React_2.PropsWithChildren<{}>) => JSX.Element; - // Warnings were encountered during analysis: // // src/components/CatalogTable/CatalogTable.d.ts:10:5 - (ae-forgotten-export) The symbol "CatalogTableProps" needs to be exported by the entry point index.d.ts diff --git a/plugins/catalog/src/components/FilteredEntityLayout/FilterContainer.tsx b/plugins/catalog/src/components/FilteredEntityLayout/FilterContainer.tsx index 6502811332..693d2f23b3 100644 --- a/plugins/catalog/src/components/FilteredEntityLayout/FilterContainer.tsx +++ b/plugins/catalog/src/components/FilteredEntityLayout/FilterContainer.tsx @@ -20,6 +20,7 @@ import { Button, Drawer, Grid, + Typography, useMediaQuery, useTheme, } from '@material-ui/core'; @@ -57,7 +58,16 @@ export const FilterContainer = ({ children }: React.PropsWithChildren<{}>) => { keepMounted variant="temporary" > - {children} + + + Filters + + {children} + ) : ( From 4e1b7d5cd7a7da1c8f75b4b3aee7cc921302c710 Mon Sep 17 00:00:00 2001 From: Philipp Hugenroth Date: Fri, 16 Jul 2021 14:13:43 +0200 Subject: [PATCH 23/28] Update API report Signed-off-by: Philipp Hugenroth --- packages/core-components/api-report.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/core-components/api-report.md b/packages/core-components/api-report.md index e8d3214beb..7f381deb4b 100644 --- a/packages/core-components/api-report.md +++ b/packages/core-components/api-report.md @@ -1210,7 +1210,7 @@ export const PageWithHeader: ({ themeId, children, ...props -}: React_2.PropsWithChildren) => JSX.Element; +}: PropsWithChildren) => JSX.Element; // Warning: (ae-missing-release-tag) "Progress" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // From d488326303b353ddfbcf2223c693240154e59745 Mon Sep 17 00:00:00 2001 From: Philipp Hugenroth Date: Fri, 16 Jul 2021 14:53:25 +0200 Subject: [PATCH 24/28] Fix test Signed-off-by: Philipp Hugenroth --- .../catalog/src/components/CatalogPage/CatalogPage.test.tsx | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/plugins/catalog/src/components/CatalogPage/CatalogPage.test.tsx b/plugins/catalog/src/components/CatalogPage/CatalogPage.test.tsx index db0613dc47..598f534d14 100644 --- a/plugins/catalog/src/components/CatalogPage/CatalogPage.test.tsx +++ b/plugins/catalog/src/components/CatalogPage/CatalogPage.test.tsx @@ -248,9 +248,8 @@ describe('CatalogPage', () => { it('should wrap filter in drawer on smaller screens', async () => { mockBreakpoint({ matches: true }); - const { findByText, getByTestId } = await renderWrapped(); + const { getByTestId } = await renderWrapped(); expect(getByTestId('entity-filters-drawer')).toBeInTheDocument(); - await expect(findByText('Filters')).resolves.toBeInTheDocument(); }); it('should wrap filter in grid on larger screens', async () => { From f39ee49343286c9221bb2819e385b914208da130 Mon Sep 17 00:00:00 2001 From: Philipp Hugenroth Date: Mon, 19 Jul 2021 12:23:05 +0200 Subject: [PATCH 25/28] Adjust props to fit general conventions Signed-off-by: Philipp Hugenroth --- packages/core-components/api-report.md | 4 ++-- packages/core-components/src/layout/Page/PageWithHeader.tsx | 4 ++-- plugins/catalog/api-report.md | 2 +- .../src/components/FilteredEntityLayout/FilterContainer.tsx | 4 ++-- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/packages/core-components/api-report.md b/packages/core-components/api-report.md index 7f381deb4b..ccafa4cfa7 100644 --- a/packages/core-components/api-report.md +++ b/packages/core-components/api-report.md @@ -1202,7 +1202,7 @@ export const Page: ({ children, }: PropsWithChildren) => JSX.Element; -// Warning: (ae-forgotten-export) The symbol "ThemedHeaderProps" needs to be exported by the entry point index.d.ts +// Warning: (ae-forgotten-export) The symbol "PageWithHeaderProps" needs to be exported by the entry point index.d.ts // Warning: (ae-missing-release-tag) "PageWithHeader" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) @@ -1210,7 +1210,7 @@ export const PageWithHeader: ({ themeId, children, ...props -}: PropsWithChildren) => JSX.Element; +}: PropsWithChildren) => JSX.Element; // Warning: (ae-missing-release-tag) "Progress" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // diff --git a/packages/core-components/src/layout/Page/PageWithHeader.tsx b/packages/core-components/src/layout/Page/PageWithHeader.tsx index 6095b4df16..70a6c1f693 100644 --- a/packages/core-components/src/layout/Page/PageWithHeader.tsx +++ b/packages/core-components/src/layout/Page/PageWithHeader.tsx @@ -19,7 +19,7 @@ import React, { PropsWithChildren, ComponentProps } from 'react'; import { Header } from '../Header'; import { Page } from './Page'; -export type ThemedHeaderProps = ComponentProps & { +type PageWithHeaderProps = ComponentProps & { themeId: string; }; @@ -27,7 +27,7 @@ export const PageWithHeader = ({ themeId, children, ...props -}: PropsWithChildren) => ( +}: PropsWithChildren) => (
{children} diff --git a/plugins/catalog/api-report.md b/plugins/catalog/api-report.md index 4ed69230ec..5a4ddefaca 100644 --- a/plugins/catalog/api-report.md +++ b/plugins/catalog/api-report.md @@ -288,7 +288,7 @@ export const EntitySystemDiagramCard: SystemDiagramCard; // @public (undocumented) export const FilterContainer: ({ children, -}: React_2.PropsWithChildren<{}>) => JSX.Element; +}: PropsWithChildren<{}>) => JSX.Element; // Warning: (ae-missing-release-tag) "FilteredEntityLayout" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // diff --git a/plugins/catalog/src/components/FilteredEntityLayout/FilterContainer.tsx b/plugins/catalog/src/components/FilteredEntityLayout/FilterContainer.tsx index 693d2f23b3..d38e800f46 100644 --- a/plugins/catalog/src/components/FilteredEntityLayout/FilterContainer.tsx +++ b/plugins/catalog/src/components/FilteredEntityLayout/FilterContainer.tsx @@ -25,9 +25,9 @@ import { useTheme, } from '@material-ui/core'; import FilterListIcon from '@material-ui/icons/FilterList'; -import React, { useState } from 'react'; +import React, { useState, PropsWithChildren } from 'react'; -export const FilterContainer = ({ children }: React.PropsWithChildren<{}>) => { +export const FilterContainer = ({ children }: PropsWithChildren<{}>) => { const isMidSizeScreen = useMediaQuery(theme => theme.breakpoints.down('md'), ); From 249cbfc893d7f96cd948d39e7e5e33158ecaef83 Mon Sep 17 00:00:00 2001 From: Tim Hansen Date: Mon, 19 Jul 2021 12:18:29 -0600 Subject: [PATCH 26/28] Minor tweaks, button fixes Signed-off-by: Tim Hansen --- .changeset/green-lies-hammer.md | 4 +- .../software-catalog/catalog-customization.md | 40 +++++++++++-------- .../SupportButton/SupportButton.tsx | 26 ++++++------ .../layout/ContentHeader/ContentHeader.tsx | 6 +-- plugins/catalog/api-report.md | 5 +++ .../components/CatalogPage/CatalogPage.tsx | 2 +- .../FilteredEntityLayout/FilterContainer.tsx | 18 +++------ plugins/catalog/src/index.ts | 11 ++--- 8 files changed, 59 insertions(+), 53 deletions(-) diff --git a/.changeset/green-lies-hammer.md b/.changeset/green-lies-hammer.md index fc7f6e301d..af1c2e6e92 100644 --- a/.changeset/green-lies-hammer.md +++ b/.changeset/green-lies-hammer.md @@ -5,6 +5,4 @@ '@backstage/plugin-catalog': patch --- -Changing the layout of the Catalog & API page to use responsive wrappers for table & filters. The goal is to enforce a responsive layout & that the Catalog & API page are better useable on smaller screens by showing more of the main content. To apply this changes to your custom catalog page, you can add the wrappers following the updated documentation on catalog customization. - -Additionally, the tests for Material UI breakpoints were adjusted & used to test the responsive wrappers. +Updated the layout of catalog and API index pages to handle smaller screen sizes. This adds responsive wrappers to the entity tables, and switches filters to a drawer when width-constrained. If you have created a custom catalog or API index page, you will need to update the page structure to match the updated [catalog customization](https://backstage.io/docs/features/software-catalog/catalog-customization) documentation. diff --git a/docs/features/software-catalog/catalog-customization.md b/docs/features/software-catalog/catalog-customization.md index 4049b005f1..0c11d8f476 100644 --- a/docs/features/software-catalog/catalog-customization.md +++ b/docs/features/software-catalog/catalog-customization.md @@ -27,7 +27,11 @@ default catalog page and create a component in a ```tsx // imports, etc omitted for brevity. for full source see: // https://github.com/backstage/backstage/blob/master/plugins/catalog/src/components/CatalogPage/CatalogPage.tsx -export const CustomCatalogPage = () => { +export const CustomCatalogPage = ({ + columns, + actions, + initiallySelectedFilter = 'owned', +}: CatalogPageProps) => { return ( @@ -139,23 +143,27 @@ export const EntitySecurityTierPicker = () => { Now we can add the component to `CustomCatalogPage`: ```diff -export const CustomCatalogPage = () => { +export const CustomCatalogPage = ({ + columns, + actions, + initiallySelectedFilter = 'owned', +}: CatalogPageProps) => { return ( ... - - - - - + + + + + ... }; ``` diff --git a/packages/core-components/src/components/SupportButton/SupportButton.tsx b/packages/core-components/src/components/SupportButton/SupportButton.tsx index 45012e50a4..3e719acb95 100644 --- a/packages/core-components/src/components/SupportButton/SupportButton.tsx +++ b/packages/core-components/src/components/SupportButton/SupportButton.tsx @@ -28,7 +28,7 @@ import { makeStyles, Popover, } from '@material-ui/core'; -import React, { Fragment, MouseEventHandler, useState } from 'react'; +import React, { MouseEventHandler, useState } from 'react'; import { SupportItem, SupportItemLink, useSupportConfig } from '../../hooks'; import { Link } from '../Link'; @@ -94,17 +94,17 @@ export const SupportButton = ({ title, children }: SupportButtonProps) => { }; return ( - - + <> + + + { - + ); }; diff --git a/packages/core-components/src/layout/ContentHeader/ContentHeader.tsx b/packages/core-components/src/layout/ContentHeader/ContentHeader.tsx index 0bd377e5af..62cb80cffa 100644 --- a/packages/core-components/src/layout/ContentHeader/ContentHeader.tsx +++ b/packages/core-components/src/layout/ContentHeader/ContentHeader.tsx @@ -18,7 +18,7 @@ * TODO favoriteable capability */ -import React, { ComponentType, Fragment, PropsWithChildren } from 'react'; +import React, { ComponentType, PropsWithChildren } from 'react'; import { Typography, makeStyles } from '@material-ui/core'; import { Helmet } from 'react-helmet'; @@ -98,7 +98,7 @@ export const ContentHeader = ({ ); return ( - + <>
@@ -111,6 +111,6 @@ export const ContentHeader = ({
{children}
-
+ ); }; diff --git a/plugins/catalog/api-report.md b/plugins/catalog/api-report.md index 5a4ddefaca..1b6e2cd4d0 100644 --- a/plugins/catalog/api-report.md +++ b/plugins/catalog/api-report.md @@ -104,6 +104,11 @@ export type CatalogTableRow = { }; }; +// Warning: (ae-missing-release-tag) "CreateComponentButton" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export const CreateComponentButton: () => JSX.Element | null; + // Warning: (ae-missing-release-tag) "createMetadataDescriptionColumn" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) diff --git a/plugins/catalog/src/components/CatalogPage/CatalogPage.tsx b/plugins/catalog/src/components/CatalogPage/CatalogPage.tsx index 0fe3504c6d..963e04e5e2 100644 --- a/plugins/catalog/src/components/CatalogPage/CatalogPage.tsx +++ b/plugins/catalog/src/components/CatalogPage/CatalogPage.tsx @@ -36,7 +36,7 @@ import { import React from 'react'; import { CatalogTable } from '../CatalogTable'; import { EntityRow } from '../CatalogTable/types'; -import { CreateComponentButton } from '../CreateComponentButton/CreateComponentButton'; +import { CreateComponentButton } from '../CreateComponentButton'; import { FilteredEntityLayout, EntityListContainer, diff --git a/plugins/catalog/src/components/FilteredEntityLayout/FilterContainer.tsx b/plugins/catalog/src/components/FilteredEntityLayout/FilterContainer.tsx index d38e800f46..f21f9c77a3 100644 --- a/plugins/catalog/src/components/FilteredEntityLayout/FilterContainer.tsx +++ b/plugins/catalog/src/components/FilteredEntityLayout/FilterContainer.tsx @@ -32,27 +32,21 @@ export const FilterContainer = ({ children }: PropsWithChildren<{}>) => { theme.breakpoints.down('md'), ); const theme = useTheme(); - const [showFiltersDrawer, toggleFiltersDrawer] = useState(false); + const [filterDrawerOpen, setFilterDrawerOpen] = useState(false); return isMidSizeScreen ? ( <> { - toggleFiltersDrawer(false); - }} - elevation={0} + open={filterDrawerOpen} + onClose={() => setFilterDrawerOpen(false)} anchor="left" disableAutoFocus keepMounted diff --git a/plugins/catalog/src/index.ts b/plugins/catalog/src/index.ts index 4b348580f7..2ac7f10227 100644 --- a/plugins/catalog/src/index.ts +++ b/plugins/catalog/src/index.ts @@ -15,13 +15,16 @@ */ export * from './components/AboutCard'; -export { CatalogResultListItem } from './components/CatalogResultListItem'; +export * from './components/CatalogResultListItem'; export { CatalogTable } from './components/CatalogTable'; export type { EntityRow as CatalogTableRow } from './components/CatalogTable'; -export { EntityLayout } from './components/EntityLayout'; +export * from './components/CatalogTable/columns'; +export * from './components/CreateComponentButton'; +export * from './components/EntityLayout'; export * from './components/EntityOrphanWarning'; -export { EntityPageLayout } from './components/EntityPageLayout'; +export * from './components/EntityPageLayout'; export * from './components/EntitySwitch'; +export * from './components/FilteredEntityLayout'; export { Router } from './components/Router'; export { CatalogEntityPage, @@ -39,5 +42,3 @@ export { EntityLinksCard, EntitySystemDiagramCard, } from './plugin'; -export * from './components/CatalogTable/columns'; -export * from './components/FilteredEntityLayout'; From 8d6408d05cbc26862fa82fcb524f252acee724ee Mon Sep 17 00:00:00 2001 From: Philipp Hugenroth Date: Mon, 19 Jul 2021 21:57:18 +0200 Subject: [PATCH 27/28] Adjust tests to use only text & test drawer visibility Signed-off-by: Philipp Hugenroth --- .../src/components/CatalogPage/CatalogPage.test.tsx | 12 ++++++++---- .../FilteredEntityLayout/FilterContainer.tsx | 3 +-- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/plugins/catalog/src/components/CatalogPage/CatalogPage.test.tsx b/plugins/catalog/src/components/CatalogPage/CatalogPage.test.tsx index 598f534d14..b462cfb6b6 100644 --- a/plugins/catalog/src/components/CatalogPage/CatalogPage.test.tsx +++ b/plugins/catalog/src/components/CatalogPage/CatalogPage.test.tsx @@ -248,13 +248,17 @@ describe('CatalogPage', () => { it('should wrap filter in drawer on smaller screens', async () => { mockBreakpoint({ matches: true }); - const { getByTestId } = await renderWrapped(); - expect(getByTestId('entity-filters-drawer')).toBeInTheDocument(); + const { getAllByText } = await renderWrapped(); + const elems = getAllByText('Filters'); + expect(elems[0]).toBeVisible(); + expect(elems[1]).not.toBeVisible(); + fireEvent.click(elems[0]); + expect(elems[1]).toBeVisible(); }); it('should wrap filter in grid on larger screens', async () => { mockBreakpoint({ matches: false }); - const { getByTestId } = await renderWrapped(); - expect(getByTestId('entity-filters-grid')).toBeInTheDocument(); + const { queryAllByText } = await renderWrapped(); + expect(queryAllByText('Filters').length).toBe(0); }); }); diff --git a/plugins/catalog/src/components/FilteredEntityLayout/FilterContainer.tsx b/plugins/catalog/src/components/FilteredEntityLayout/FilterContainer.tsx index f21f9c77a3..683dbf8b40 100644 --- a/plugins/catalog/src/components/FilteredEntityLayout/FilterContainer.tsx +++ b/plugins/catalog/src/components/FilteredEntityLayout/FilterContainer.tsx @@ -44,7 +44,6 @@ export const FilterContainer = ({ children }: PropsWithChildren<{}>) => { Filters setFilterDrawerOpen(false)} anchor="left" @@ -65,7 +64,7 @@ export const FilterContainer = ({ children }: PropsWithChildren<{}>) => { ) : ( - + {children} ); From f5067d16609e7690d6fe9e5abb957d8048f47232 Mon Sep 17 00:00:00 2001 From: Philipp Hugenroth Date: Tue, 20 Jul 2021 11:02:28 +0200 Subject: [PATCH 28/28] Adjust test to be more specific Signed-off-by: Philipp Hugenroth --- .../components/CatalogPage/CatalogPage.test.tsx | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/plugins/catalog/src/components/CatalogPage/CatalogPage.test.tsx b/plugins/catalog/src/components/CatalogPage/CatalogPage.test.tsx index b462cfb6b6..e09aec55e7 100644 --- a/plugins/catalog/src/components/CatalogPage/CatalogPage.test.tsx +++ b/plugins/catalog/src/components/CatalogPage/CatalogPage.test.tsx @@ -248,17 +248,10 @@ describe('CatalogPage', () => { it('should wrap filter in drawer on smaller screens', async () => { mockBreakpoint({ matches: true }); - const { getAllByText } = await renderWrapped(); - const elems = getAllByText('Filters'); - expect(elems[0]).toBeVisible(); - expect(elems[1]).not.toBeVisible(); - fireEvent.click(elems[0]); - expect(elems[1]).toBeVisible(); - }); - - it('should wrap filter in grid on larger screens', async () => { - mockBreakpoint({ matches: false }); - const { queryAllByText } = await renderWrapped(); - expect(queryAllByText('Filters').length).toBe(0); + const { getByRole } = await renderWrapped(); + const button = getByRole('button', { name: 'Filters' }); + expect(getByRole('presentation', { hidden: true })).toBeInTheDocument(); + fireEvent.click(button); + expect(getByRole('presentation')).toBeVisible(); }); });