From 016c574b5137d20f0fac516afb178351e6ea27b5 Mon Sep 17 00:00:00 2001 From: Yousif Al-Raheem Date: Mon, 7 Mar 2022 18:31:16 +0100 Subject: [PATCH 01/19] enable adding extra setting tabs Signed-off-by: Yousif Al-Raheem --- .changeset/three-rivers-remain.md | 6 ++ packages/app/src/App.tsx | 13 +++- .../advancedSettings/AdvancedSettings.tsx | 63 +++++++++++++++++++ .../src/components/advancedSettings/index.ts | 17 +++++ plugins/user-settings/README.md | 28 +++++++++ .../src/components/SettingsPage.test.tsx | 43 +++++++++++++ .../src/components/SettingsPage.tsx | 17 ++++- plugins/user-settings/src/components/index.ts | 1 + 8 files changed, 184 insertions(+), 4 deletions(-) create mode 100644 .changeset/three-rivers-remain.md create mode 100644 packages/app/src/components/advancedSettings/AdvancedSettings.tsx create mode 100644 packages/app/src/components/advancedSettings/index.ts create mode 100644 plugins/user-settings/src/components/SettingsPage.test.tsx diff --git a/.changeset/three-rivers-remain.md b/.changeset/three-rivers-remain.md new file mode 100644 index 0000000000..3bd4b43ff7 --- /dev/null +++ b/.changeset/three-rivers-remain.md @@ -0,0 +1,6 @@ +--- +'example-app': minor +'@backstage/plugin-user-settings': minor +--- + +Added the ability to render extra setting tabs diff --git a/packages/app/src/App.tsx b/packages/app/src/App.tsx index 374d637b2e..9151e55e51 100644 --- a/packages/app/src/App.tsx +++ b/packages/app/src/App.tsx @@ -69,7 +69,7 @@ import { techdocsPlugin, TechDocsReaderPage, } from '@backstage/plugin-techdocs'; -import { UserSettingsPage } from '@backstage/plugin-user-settings'; +import { UserSettingsPage, SettingsTab } from '@backstage/plugin-user-settings'; import AlarmIcon from '@material-ui/icons/Alarm'; import React from 'react'; import { hot } from 'react-hot-loader/root'; @@ -82,7 +82,7 @@ import { LowerCaseValuePickerFieldExtension } from './components/scaffolder/cust import { searchPage } from './components/search/SearchPage'; import { providers } from './identityProviders'; import * as plugins from './plugins'; - +import { AdvancedSettings } from './components/advancedSettings'; import { techDocsPage } from './components/techdocs/TechDocsPage'; import { ApacheAirflowPage } from '@backstage/plugin-apache-airflow'; import { PermissionedRoute } from '@backstage/plugin-permission-react'; @@ -127,6 +127,10 @@ const app = createApp({ const AppProvider = app.getProvider(); const AppRouter = app.getRouter(); +const extraSettingTabs: SettingsTab[] = [ + { title: 'Advanced', content: }, +]; + const routes = ( @@ -215,7 +219,10 @@ const routes = ( path="/cost-insights/labeling-jobs" element={} /> - } /> + } + /> } /> } /> diff --git a/packages/app/src/components/advancedSettings/AdvancedSettings.tsx b/packages/app/src/components/advancedSettings/AdvancedSettings.tsx new file mode 100644 index 0000000000..324605c1e8 --- /dev/null +++ b/packages/app/src/components/advancedSettings/AdvancedSettings.tsx @@ -0,0 +1,63 @@ +/* + * Copyright 2022 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import React from 'react'; +import { InfoCard } from '@backstage/core-components'; +import { + List, + Grid, + ListItem, + ListItemText, + ListItemSecondaryAction, + Switch, +} from '@material-ui/core'; +import { useLocalStorage } from 'react-use'; + +export function AdvancedSettings() { + const [value, setValue] = useLocalStorage<'on' | 'off'>( + 'advanced-option', + 'off', + ); + + const toggleValue = (ev: React.ChangeEvent) => { + setValue(ev.currentTarget.checked ? 'on' : 'off'); + }; + + return ( + + + + + + + + + + + + + + + ); +} diff --git a/packages/app/src/components/advancedSettings/index.ts b/packages/app/src/components/advancedSettings/index.ts new file mode 100644 index 0000000000..9d5e946e99 --- /dev/null +++ b/packages/app/src/components/advancedSettings/index.ts @@ -0,0 +1,17 @@ +/* + * Copyright 2022 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export * from './AdvancedSettings'; diff --git a/plugins/user-settings/README.md b/plugins/user-settings/README.md index db0b01681f..ed6c648648 100644 --- a/plugins/user-settings/README.md +++ b/plugins/user-settings/README.md @@ -63,3 +63,31 @@ const AppRoutes = () => ( ``` > **Note that the list of providers expects to be rendered within a MUI [``](https://material-ui.com/components/lists/)** + +**Tabs** +By default, the plugin renders 3 tabs of settings; GENERAL, AUTHENTICATION PROVIDERS, and FEATURE FLAGS. + +If you want to add more options for your users, use the `tabs` prop: + +```tsx +import { UserSettingsPage, SettingsTab } from '@backstage/plugin-user-settings'; + +const extraSettingTabs: SettingsTab[] = [ + { title: 'Advanced', content: }, +]; + +const AppRoutes = () => ( + + } + /> + +); +``` + +To standardize the UI of all setting tabs, +make sure you use a similar component structure as the other tabs. +You can take a look at +[the example extra tab](https://github.com/backstage/backstage/blob/master/packages/app/src/components/advancedSettings/AdvancedSettings.tsx) +we have created in Backstage's demo app. diff --git a/plugins/user-settings/src/components/SettingsPage.test.tsx b/plugins/user-settings/src/components/SettingsPage.test.tsx new file mode 100644 index 0000000000..846f120a6b --- /dev/null +++ b/plugins/user-settings/src/components/SettingsPage.test.tsx @@ -0,0 +1,43 @@ +/* + * Copyright 2022 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import React from 'react'; +import { renderWithEffects, wrapInTestApp } from '@backstage/test-utils'; +import { SettingsPage, SettingsTab } from './SettingsPage'; + +describe('', () => { + it('should render the settings page with 3 tabs', async () => { + const { container } = await renderWithEffects( + wrapInTestApp(), + ); + + const tabs = container.querySelectorAll('[class*=MuiTabs-root] button'); + expect(tabs).toHaveLength(3); + }); + + it('should render the settings page with 4 tabs when extra tabs are provided', async () => { + const extraTabs: SettingsTab[] = [ + { title: 'Advanced', content:
advanced content
}, + ]; + const { container } = await renderWithEffects( + wrapInTestApp(), + ); + + const tabs = container.querySelectorAll('[class*=MuiTabs-root] button'); + expect(tabs).toHaveLength(4); + expect(tabs[3].textContent).toEqual(extraTabs[0].title); + }); +}); diff --git a/plugins/user-settings/src/components/SettingsPage.tsx b/plugins/user-settings/src/components/SettingsPage.tsx index 88b46fc372..a8ef1bda8f 100644 --- a/plugins/user-settings/src/components/SettingsPage.tsx +++ b/plugins/user-settings/src/components/SettingsPage.tsx @@ -25,11 +25,17 @@ import { UserSettingsAuthProviders } from './AuthProviders'; import { UserSettingsFeatureFlags } from './FeatureFlags'; import { UserSettingsGeneral } from './General'; +export interface SettingsTab { + title: string; + content: React.ReactElement; +} + type Props = { providerSettings?: JSX.Element; + tabs?: SettingsTab[]; }; -export const SettingsPage = ({ providerSettings }: Props) => { +export const SettingsPage = ({ providerSettings, tabs }: Props) => { const { isMobile } = useContext(SidebarPinStateContext); return ( @@ -48,6 +54,15 @@ export const SettingsPage = ({ providerSettings }: Props) => { + {tabs?.map(({ title, content }) => { + // Hyphenated the title + const path = title.toLocaleLowerCase().replace(/\s/, '-'); + return ( + + {content} + + ); + })} ); diff --git a/plugins/user-settings/src/components/index.ts b/plugins/user-settings/src/components/index.ts index cb058f9c5e..a1dae855d8 100644 --- a/plugins/user-settings/src/components/index.ts +++ b/plugins/user-settings/src/components/index.ts @@ -15,6 +15,7 @@ */ export { Settings } from './Settings'; export { SettingsPage as Router } from './SettingsPage'; +export type { SettingsTab } from './SettingsPage'; export * from './AuthProviders'; export * from './General'; export * from './FeatureFlags'; From 8f769adebf9e23368300b9738ce1b5ce64cfbd7c Mon Sep 17 00:00:00 2001 From: Yousif Al-Raheem Date: Fri, 11 Mar 2022 14:10:09 +0100 Subject: [PATCH 02/19] use direct import of useLocalStorage hook from react-use in AdvancedSettings component Signed-off-by: Yousif Al-Raheem --- .../app/src/components/advancedSettings/AdvancedSettings.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/app/src/components/advancedSettings/AdvancedSettings.tsx b/packages/app/src/components/advancedSettings/AdvancedSettings.tsx index 324605c1e8..9a1e0fd162 100644 --- a/packages/app/src/components/advancedSettings/AdvancedSettings.tsx +++ b/packages/app/src/components/advancedSettings/AdvancedSettings.tsx @@ -24,7 +24,7 @@ import { ListItemSecondaryAction, Switch, } from '@material-ui/core'; -import { useLocalStorage } from 'react-use'; +import useLocalStorage from 'react-use/lib/useLocalStorage'; export function AdvancedSettings() { const [value, setValue] = useLocalStorage<'on' | 'off'>( From fc7473b037d8bf0a8d7fc599921bb9065ab8eca7 Mon Sep 17 00:00:00 2001 From: Yousif Al-Raheem Date: Fri, 11 Mar 2022 14:40:38 +0100 Subject: [PATCH 03/19] updated api reports for user-settings for adding extra tabs Signed-off-by: Yousif Al-Raheem --- plugins/user-settings/api-report.md | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/plugins/user-settings/api-report.md b/plugins/user-settings/api-report.md index 0d8f132f37..6a37e2530f 100644 --- a/plugins/user-settings/api-report.md +++ b/plugins/user-settings/api-report.md @@ -9,6 +9,7 @@ import { ApiRef } from '@backstage/core-plugin-api'; import { BackstagePlugin } from '@backstage/core-plugin-api'; import { IconComponent } from '@backstage/core-plugin-api'; import { ProfileInfo } from '@backstage/core-plugin-api'; +import { default as React_2 } from 'react'; import { RouteRef } from '@backstage/core-plugin-api'; import { SessionApi } from '@backstage/core-plugin-api'; @@ -35,7 +36,7 @@ export const ProviderSettingsItem: ({ // Warning: (ae-missing-release-tag) "SettingsPage" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) -export const Router: ({ providerSettings }: Props) => JSX.Element; +export const Router: ({ providerSettings, tabs }: Props) => JSX.Element; // Warning: (ae-forgotten-export) The symbol "SettingsProps" needs to be exported by the entry point index.d.ts // Warning: (ae-missing-release-tag) "Settings" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) @@ -43,6 +44,16 @@ export const Router: ({ providerSettings }: Props) => JSX.Element; // @public (undocumented) export const Settings: (props: SettingsProps) => JSX.Element; +// Warning: (ae-missing-release-tag) "SettingsTab" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export interface SettingsTab { + // (undocumented) + content: React_2.ReactElement; + // (undocumented) + title: string; +} + // Warning: (ae-missing-release-tag) "UserSettingsAppearanceCard" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) @@ -76,8 +87,10 @@ export const UserSettingsMenu: () => JSX.Element; // @public (undocumented) export const UserSettingsPage: ({ providerSettings, + tabs, }: { providerSettings?: JSX.Element | undefined; + tabs?: SettingsTab[] | undefined; }) => JSX.Element; // Warning: (ae-missing-release-tag) "UserSettingsPinToggle" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) From 141d3ac62cf62fafb706f87a69dabb7b6d46b676 Mon Sep 17 00:00:00 2001 From: Yousif Al-Raheem Date: Fri, 11 Mar 2022 15:33:20 +0100 Subject: [PATCH 04/19] removed example-app from changelog Signed-off-by: Yousif Al-Raheem --- .changeset/three-rivers-remain.md | 1 - 1 file changed, 1 deletion(-) diff --git a/.changeset/three-rivers-remain.md b/.changeset/three-rivers-remain.md index 3bd4b43ff7..8fa3893e28 100644 --- a/.changeset/three-rivers-remain.md +++ b/.changeset/three-rivers-remain.md @@ -1,5 +1,4 @@ --- -'example-app': minor '@backstage/plugin-user-settings': minor --- From 59ef975a4d5fbd1d6c16a0eb69b82f5947d29b49 Mon Sep 17 00:00:00 2001 From: Yousif Al-Raheem Date: Fri, 11 Mar 2022 16:26:14 +0100 Subject: [PATCH 05/19] added missing react types dependency in plugin-user-settings Signed-off-by: Yousif Al-Raheem --- plugins/user-settings/package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/plugins/user-settings/package.json b/plugins/user-settings/package.json index fe78e19ce6..89fab2bfaa 100644 --- a/plugins/user-settings/package.json +++ b/plugins/user-settings/package.json @@ -56,6 +56,7 @@ "@testing-library/user-event": "^13.1.8", "@types/jest": "^26.0.7", "@types/node": "^14.14.32", + "@types/react": "^16.13.1 || ^17.0.0", "cross-fetch": "^3.1.5", "msw": "^0.35.0" }, From 53c4d7d516513b654d1ead002ae82d39a0aa91df Mon Sep 17 00:00:00 2001 From: Yousif Al-Raheem Date: Fri, 11 Mar 2022 16:37:16 +0100 Subject: [PATCH 06/19] =?UTF-8?q?moved=20react=20types=20to=20dependencies?= =?UTF-8?q?=20instead=20of=20devDependencies=20=F0=9F=98=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Yousif Al-Raheem --- plugins/user-settings/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/user-settings/package.json b/plugins/user-settings/package.json index 89fab2bfaa..b2926235e6 100644 --- a/plugins/user-settings/package.json +++ b/plugins/user-settings/package.json @@ -40,6 +40,7 @@ "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.57", + "@types/react": "^16.13.1 || ^17.0.0", "react-router": "6.0.0-beta.0", "react-use": "^17.2.4" }, @@ -56,7 +57,6 @@ "@testing-library/user-event": "^13.1.8", "@types/jest": "^26.0.7", "@types/node": "^14.14.32", - "@types/react": "^16.13.1 || ^17.0.0", "cross-fetch": "^3.1.5", "msw": "^0.35.0" }, From 7ad0cd18aaec3460f40949136b3b3e76704fb2c2 Mon Sep 17 00:00:00 2001 From: Yousif Al-Raheem Date: Wed, 16 Mar 2022 10:14:58 +0100 Subject: [PATCH 07/19] correct tabs title in user-settings readme Signed-off-by: Yousif Al-Raheem --- plugins/user-settings/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/plugins/user-settings/README.md b/plugins/user-settings/README.md index ed6c648648..71440ebfaf 100644 --- a/plugins/user-settings/README.md +++ b/plugins/user-settings/README.md @@ -65,6 +65,7 @@ const AppRoutes = () => ( > **Note that the list of providers expects to be rendered within a MUI [``](https://material-ui.com/components/lists/)** **Tabs** + By default, the plugin renders 3 tabs of settings; GENERAL, AUTHENTICATION PROVIDERS, and FEATURE FLAGS. If you want to add more options for your users, use the `tabs` prop: From b66ae2b542434c12d80430b90c738addf98c428f Mon Sep 17 00:00:00 2001 From: Yousif Al-Raheem Date: Wed, 16 Mar 2022 11:44:40 +0100 Subject: [PATCH 08/19] use outlet to render extra tabs instead of tabs prop Signed-off-by: Yousif Al-Raheem --- packages/app/src/App.tsx | 17 +++---- plugins/user-settings/README.md | 25 +++++------ .../src/components/SettingsPage.test.tsx | 45 ++++++++++++++++--- .../src/components/SettingsPage.tsx | 35 +++++++++------ 4 files changed, 78 insertions(+), 44 deletions(-) diff --git a/packages/app/src/App.tsx b/packages/app/src/App.tsx index 9151e55e51..b3bb511c90 100644 --- a/packages/app/src/App.tsx +++ b/packages/app/src/App.tsx @@ -69,7 +69,8 @@ import { techdocsPlugin, TechDocsReaderPage, } from '@backstage/plugin-techdocs'; -import { UserSettingsPage, SettingsTab } from '@backstage/plugin-user-settings'; +import { UserSettingsPage } from '@backstage/plugin-user-settings'; +import { AdvancedSettings } from './components/advancedSettings'; import AlarmIcon from '@material-ui/icons/Alarm'; import React from 'react'; import { hot } from 'react-hot-loader/root'; @@ -82,7 +83,6 @@ import { LowerCaseValuePickerFieldExtension } from './components/scaffolder/cust import { searchPage } from './components/search/SearchPage'; import { providers } from './identityProviders'; import * as plugins from './plugins'; -import { AdvancedSettings } from './components/advancedSettings'; import { techDocsPage } from './components/techdocs/TechDocsPage'; import { ApacheAirflowPage } from '@backstage/plugin-apache-airflow'; import { PermissionedRoute } from '@backstage/plugin-permission-react'; @@ -127,10 +127,6 @@ const app = createApp({ const AppProvider = app.getProvider(); const AppRouter = app.getRouter(); -const extraSettingTabs: SettingsTab[] = [ - { title: 'Advanced', content: }, -]; - const routes = ( @@ -219,10 +215,11 @@ const routes = ( path="/cost-insights/labeling-jobs" element={} /> - } - /> + }> + }> + Advanced + + } /> } /> diff --git a/plugins/user-settings/README.md b/plugins/user-settings/README.md index 71440ebfaf..689b11880d 100644 --- a/plugins/user-settings/README.md +++ b/plugins/user-settings/README.md @@ -68,23 +68,18 @@ const AppRoutes = () => ( By default, the plugin renders 3 tabs of settings; GENERAL, AUTHENTICATION PROVIDERS, and FEATURE FLAGS. -If you want to add more options for your users, use the `tabs` prop: +If you want to add more options for your users, +just pass the extra tabs as children of the `UserSettingsPage` route +where the children of that route represents the title of the tab. +The path is in this case a child of the settings path, +in the example below it would be `/settings/advanced` so that you can easily link to it. ```tsx -import { UserSettingsPage, SettingsTab } from '@backstage/plugin-user-settings'; - -const extraSettingTabs: SettingsTab[] = [ - { title: 'Advanced', content: }, -]; - -const AppRoutes = () => ( - - } - /> - -); +}> + }> + Advanced + + ``` To standardize the UI of all setting tabs, diff --git a/plugins/user-settings/src/components/SettingsPage.test.tsx b/plugins/user-settings/src/components/SettingsPage.test.tsx index 846f120a6b..bee395a2fa 100644 --- a/plugins/user-settings/src/components/SettingsPage.test.tsx +++ b/plugins/user-settings/src/components/SettingsPage.test.tsx @@ -16,7 +16,14 @@ import React from 'react'; import { renderWithEffects, wrapInTestApp } from '@backstage/test-utils'; -import { SettingsPage, SettingsTab } from './SettingsPage'; +import { SettingsPage } from './SettingsPage'; + +jest.mock('react-router', () => ({ + ...jest.requireActual('react-router'), + useOutlet: jest.fn().mockReturnValue(undefined), +})); + +import { useOutlet, Route } from 'react-router'; describe('', () => { it('should render the settings page with 3 tabs', async () => { @@ -29,15 +36,41 @@ describe('', () => { }); it('should render the settings page with 4 tabs when extra tabs are provided', async () => { - const extraTabs: SettingsTab[] = [ - { title: 'Advanced', content:
advanced content
}, - ]; + const advancedTabRoute = ( + <> + Advanced settings}> + Advanced + + + ); + (useOutlet as jest.Mock).mockReturnValueOnce(advancedTabRoute); const { container } = await renderWithEffects( - wrapInTestApp(), + wrapInTestApp(), ); const tabs = container.querySelectorAll('[class*=MuiTabs-root] button'); expect(tabs).toHaveLength(4); - expect(tabs[3].textContent).toEqual(extraTabs[0].title); + expect(tabs[3].textContent).toEqual('Advanced'); + }); + + it('should throw error if non compliant route is passed to settings routes', async () => { + const advancedTabRoute = ( + <> + Advanced settings}> + Advanced + +
Non compliant element
+ + ); + (useOutlet as jest.Mock).mockReturnValueOnce(advancedTabRoute); + let error: Error; + try { + await renderWithEffects(wrapInTestApp()); + } catch (err) { + error = err; + } + expect(error!.message).toEqual( + expect.stringContaining('Invalid element passed'), + ); }); }); diff --git a/plugins/user-settings/src/components/SettingsPage.tsx b/plugins/user-settings/src/components/SettingsPage.tsx index a8ef1bda8f..0e21241ddf 100644 --- a/plugins/user-settings/src/components/SettingsPage.tsx +++ b/plugins/user-settings/src/components/SettingsPage.tsx @@ -20,23 +20,30 @@ import { SidebarPinStateContext, TabbedLayout, } from '@backstage/core-components'; -import React, { useContext } from 'react'; +import React, { useContext, ReactElement } from 'react'; +import { useOutlet } from 'react-router'; import { UserSettingsAuthProviders } from './AuthProviders'; import { UserSettingsFeatureFlags } from './FeatureFlags'; import { UserSettingsGeneral } from './General'; -export interface SettingsTab { - title: string; - content: React.ReactElement; -} - type Props = { providerSettings?: JSX.Element; - tabs?: SettingsTab[]; }; -export const SettingsPage = ({ providerSettings, tabs }: Props) => { +export const SettingsPage = ({ providerSettings }: Props) => { const { isMobile } = useContext(SidebarPinStateContext); + const outlet = useOutlet(); + + const extraTabs = (React.Children.toArray(outlet?.props?.children) || + []) as Array; + const notCompliantTab = Array.from(extraTabs).some( + child => (child.type as any)?.displayName !== 'Route', + ); + if (notCompliantTab) { + throw new Error( + 'Invalid element passed to SettingsPage Outlet. You may only pass children of type Route.', + ); + } return ( @@ -54,12 +61,14 @@ export const SettingsPage = ({ providerSettings, tabs }: Props) => { - {tabs?.map(({ title, content }) => { - // Hyphenated the title - const path = title.toLocaleLowerCase().replace(/\s/, '-'); + + {extraTabs.map((child, i) => { + const path: string = child.props.path; + const title: string = child.props.children; + return ( - - {content} + + {child} ); })} From ad270bad1363a51bb3085131fec851d2f8b8e22b Mon Sep 17 00:00:00 2001 From: Yousif Al-Raheem Date: Wed, 16 Mar 2022 11:55:00 +0100 Subject: [PATCH 09/19] revert back the api reports Signed-off-by: Yousif Al-Raheem --- plugins/user-settings/api-report.md | 15 +-------------- plugins/user-settings/src/components/index.ts | 1 - 2 files changed, 1 insertion(+), 15 deletions(-) diff --git a/plugins/user-settings/api-report.md b/plugins/user-settings/api-report.md index 6a37e2530f..0d8f132f37 100644 --- a/plugins/user-settings/api-report.md +++ b/plugins/user-settings/api-report.md @@ -9,7 +9,6 @@ import { ApiRef } from '@backstage/core-plugin-api'; import { BackstagePlugin } from '@backstage/core-plugin-api'; import { IconComponent } from '@backstage/core-plugin-api'; import { ProfileInfo } from '@backstage/core-plugin-api'; -import { default as React_2 } from 'react'; import { RouteRef } from '@backstage/core-plugin-api'; import { SessionApi } from '@backstage/core-plugin-api'; @@ -36,7 +35,7 @@ export const ProviderSettingsItem: ({ // Warning: (ae-missing-release-tag) "SettingsPage" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) -export const Router: ({ providerSettings, tabs }: Props) => JSX.Element; +export const Router: ({ providerSettings }: Props) => JSX.Element; // Warning: (ae-forgotten-export) The symbol "SettingsProps" needs to be exported by the entry point index.d.ts // Warning: (ae-missing-release-tag) "Settings" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) @@ -44,16 +43,6 @@ export const Router: ({ providerSettings, tabs }: Props) => JSX.Element; // @public (undocumented) export const Settings: (props: SettingsProps) => JSX.Element; -// Warning: (ae-missing-release-tag) "SettingsTab" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public (undocumented) -export interface SettingsTab { - // (undocumented) - content: React_2.ReactElement; - // (undocumented) - title: string; -} - // Warning: (ae-missing-release-tag) "UserSettingsAppearanceCard" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) @@ -87,10 +76,8 @@ export const UserSettingsMenu: () => JSX.Element; // @public (undocumented) export const UserSettingsPage: ({ providerSettings, - tabs, }: { providerSettings?: JSX.Element | undefined; - tabs?: SettingsTab[] | undefined; }) => JSX.Element; // Warning: (ae-missing-release-tag) "UserSettingsPinToggle" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) diff --git a/plugins/user-settings/src/components/index.ts b/plugins/user-settings/src/components/index.ts index a1dae855d8..cb058f9c5e 100644 --- a/plugins/user-settings/src/components/index.ts +++ b/plugins/user-settings/src/components/index.ts @@ -15,7 +15,6 @@ */ export { Settings } from './Settings'; export { SettingsPage as Router } from './SettingsPage'; -export type { SettingsTab } from './SettingsPage'; export * from './AuthProviders'; export * from './General'; export * from './FeatureFlags'; From 904983882053c0809cad4948e277574c47fa4515 Mon Sep 17 00:00:00 2001 From: Yousif Al-Raheem Date: Thu, 17 Mar 2022 11:46:41 +0100 Subject: [PATCH 10/19] moved react types to devdependencies in user settings Signed-off-by: Yousif Al-Raheem --- plugins/user-settings/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/user-settings/package.json b/plugins/user-settings/package.json index b2926235e6..89fab2bfaa 100644 --- a/plugins/user-settings/package.json +++ b/plugins/user-settings/package.json @@ -40,7 +40,6 @@ "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.57", - "@types/react": "^16.13.1 || ^17.0.0", "react-router": "6.0.0-beta.0", "react-use": "^17.2.4" }, @@ -57,6 +56,7 @@ "@testing-library/user-event": "^13.1.8", "@types/jest": "^26.0.7", "@types/node": "^14.14.32", + "@types/react": "^16.13.1 || ^17.0.0", "cross-fetch": "^3.1.5", "msw": "^0.35.0" }, From 100a7e14dd0b2c267c687f89eacfefb521940eb5 Mon Sep 17 00:00:00 2001 From: Yousif Al-Raheem Date: Wed, 23 Mar 2022 14:25:17 +0100 Subject: [PATCH 11/19] Use custom UserSettingsTab component to render extra tabs in settings Signed-off-by: Yousif Al-Raheem --- packages/app/src/App.tsx | 11 +++++--- .../src/components/SettingsPage.test.tsx | 15 ++++++----- .../src/components/SettingsPage.tsx | 6 ++--- .../UserSettingsTab/UserSettingsTab.tsx | 27 +++++++++++++++++++ .../src/components/UserSettingsTab/index.ts | 16 +++++++++++ plugins/user-settings/src/components/index.ts | 1 + 6 files changed, 62 insertions(+), 14 deletions(-) create mode 100644 plugins/user-settings/src/components/UserSettingsTab/UserSettingsTab.tsx create mode 100644 plugins/user-settings/src/components/UserSettingsTab/index.ts diff --git a/packages/app/src/App.tsx b/packages/app/src/App.tsx index b3bb511c90..d8303db97b 100644 --- a/packages/app/src/App.tsx +++ b/packages/app/src/App.tsx @@ -69,7 +69,10 @@ import { techdocsPlugin, TechDocsReaderPage, } from '@backstage/plugin-techdocs'; -import { UserSettingsPage } from '@backstage/plugin-user-settings'; +import { + UserSettingsPage, + UserSettingsTab, +} from '@backstage/plugin-user-settings'; import { AdvancedSettings } from './components/advancedSettings'; import AlarmIcon from '@material-ui/icons/Alarm'; import React from 'react'; @@ -216,9 +219,9 @@ const routes = ( element={} /> }> - }> - Advanced - + + + } /> } /> diff --git a/plugins/user-settings/src/components/SettingsPage.test.tsx b/plugins/user-settings/src/components/SettingsPage.test.tsx index bee395a2fa..865d0918e7 100644 --- a/plugins/user-settings/src/components/SettingsPage.test.tsx +++ b/plugins/user-settings/src/components/SettingsPage.test.tsx @@ -17,13 +17,14 @@ import React from 'react'; import { renderWithEffects, wrapInTestApp } from '@backstage/test-utils'; import { SettingsPage } from './SettingsPage'; +import { UserSettingsTab } from './UserSettingsTab'; jest.mock('react-router', () => ({ ...jest.requireActual('react-router'), useOutlet: jest.fn().mockReturnValue(undefined), })); -import { useOutlet, Route } from 'react-router'; +import { useOutlet } from 'react-router'; describe('', () => { it('should render the settings page with 3 tabs', async () => { @@ -38,9 +39,9 @@ describe('', () => { it('should render the settings page with 4 tabs when extra tabs are provided', async () => { const advancedTabRoute = ( <> - Advanced settings}> - Advanced - + +
Advanced settings
+
); (useOutlet as jest.Mock).mockReturnValueOnce(advancedTabRoute); @@ -56,9 +57,9 @@ describe('', () => { it('should throw error if non compliant route is passed to settings routes', async () => { const advancedTabRoute = ( <> - Advanced settings}> - Advanced - + +
Advanced settings
+
Non compliant element
); diff --git a/plugins/user-settings/src/components/SettingsPage.tsx b/plugins/user-settings/src/components/SettingsPage.tsx index 0e21241ddf..5be5851c16 100644 --- a/plugins/user-settings/src/components/SettingsPage.tsx +++ b/plugins/user-settings/src/components/SettingsPage.tsx @@ -37,11 +37,11 @@ export const SettingsPage = ({ providerSettings }: Props) => { const extraTabs = (React.Children.toArray(outlet?.props?.children) || []) as Array; const notCompliantTab = Array.from(extraTabs).some( - child => (child.type as any)?.displayName !== 'Route', + child => (child.type as any)?.displayName !== 'UserSettingsTab', ); if (notCompliantTab) { throw new Error( - 'Invalid element passed to SettingsPage Outlet. You may only pass children of type Route.', + 'Invalid element passed to SettingsPage Outlet. You may only pass children of type UserSettingsTab.', ); } @@ -64,7 +64,7 @@ export const SettingsPage = ({ providerSettings }: Props) => { {extraTabs.map((child, i) => { const path: string = child.props.path; - const title: string = child.props.children; + const title: string = child.props.title; return ( diff --git a/plugins/user-settings/src/components/UserSettingsTab/UserSettingsTab.tsx b/plugins/user-settings/src/components/UserSettingsTab/UserSettingsTab.tsx new file mode 100644 index 0000000000..a0716ed88d --- /dev/null +++ b/plugins/user-settings/src/components/UserSettingsTab/UserSettingsTab.tsx @@ -0,0 +1,27 @@ +/* + * 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'; + +interface Props { + path: string; + title: React.ReactNode; +} + +export const UserSettingsTab: React.FC = ({ children }) => { + return <>{children}; +}; + +UserSettingsTab.displayName = 'UserSettingsTab'; diff --git a/plugins/user-settings/src/components/UserSettingsTab/index.ts b/plugins/user-settings/src/components/UserSettingsTab/index.ts new file mode 100644 index 0000000000..ec7228b7a6 --- /dev/null +++ b/plugins/user-settings/src/components/UserSettingsTab/index.ts @@ -0,0 +1,16 @@ +/* + * 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 * from './UserSettingsTab'; diff --git a/plugins/user-settings/src/components/index.ts b/plugins/user-settings/src/components/index.ts index cb058f9c5e..90a7105876 100644 --- a/plugins/user-settings/src/components/index.ts +++ b/plugins/user-settings/src/components/index.ts @@ -19,3 +19,4 @@ export * from './AuthProviders'; export * from './General'; export * from './FeatureFlags'; export { useUserProfile } from './useUserProfileInfo'; +export * from './UserSettingsTab'; From 366168e45a386cc1c8fc14271ceca95a94ffb661 Mon Sep 17 00:00:00 2001 From: Yousif Al-Raheem Date: Wed, 23 Mar 2022 14:29:19 +0100 Subject: [PATCH 12/19] update README in user settings plugin to introduce UserSettingsTab Signed-off-by: Yousif Al-Raheem --- plugins/user-settings/README.md | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/plugins/user-settings/README.md b/plugins/user-settings/README.md index 689b11880d..13cfe720c8 100644 --- a/plugins/user-settings/README.md +++ b/plugins/user-settings/README.md @@ -69,17 +69,21 @@ const AppRoutes = () => ( By default, the plugin renders 3 tabs of settings; GENERAL, AUTHENTICATION PROVIDERS, and FEATURE FLAGS. If you want to add more options for your users, -just pass the extra tabs as children of the `UserSettingsPage` route -where the children of that route represents the title of the tab. +just pass the extra tabs using `UserSettingsTab` components as children of the `UserSettingsPage` route. The path is in this case a child of the settings path, in the example below it would be `/settings/advanced` so that you can easily link to it. ```tsx +import { + UserSettingsPage, + UserSettingsTab, +} from '@backstage/plugin-user-settings'; + }> - }> - Advanced - - + + + +
; ``` To standardize the UI of all setting tabs, From 2a2290b59a0e719dbb89297e3023375eeef10582 Mon Sep 17 00:00:00 2001 From: yousifalraheem Date: Wed, 23 Mar 2022 14:54:22 +0100 Subject: [PATCH 13/19] Generated api report for user settings extra tab Signed-off-by: Yousif Al-Raheem --- plugins/user-settings/api-report.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/plugins/user-settings/api-report.md b/plugins/user-settings/api-report.md index 0d8f132f37..e95d0d9fe3 100644 --- a/plugins/user-settings/api-report.md +++ b/plugins/user-settings/api-report.md @@ -9,6 +9,7 @@ import { ApiRef } from '@backstage/core-plugin-api'; import { BackstagePlugin } from '@backstage/core-plugin-api'; import { IconComponent } from '@backstage/core-plugin-api'; import { ProfileInfo } from '@backstage/core-plugin-api'; +import { default as React_2 } from 'react'; import { RouteRef } from '@backstage/core-plugin-api'; import { SessionApi } from '@backstage/core-plugin-api'; @@ -108,6 +109,12 @@ export const UserSettingsProfileCard: () => JSX.Element; // @public (undocumented) export const UserSettingsSignInAvatar: ({ size }: Props_5) => JSX.Element; +// Warning: (ae-forgotten-export) The symbol "Props" needs to be exported by the entry point index.d.ts +// Warning: (ae-missing-release-tag) "UserSettingsTab" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export const UserSettingsTab: React_2.FC; + // Warning: (ae-missing-release-tag) "UserSettingsThemeToggle" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) From 0d32a893f9c13922ad6e579665cd3051ff34de45 Mon Sep 17 00:00:00 2001 From: Yousif Al-Raheem Date: Wed, 23 Mar 2022 15:07:07 +0100 Subject: [PATCH 14/19] move react types from devdependencies to dependencies Signed-off-by: Yousif Al-Raheem --- plugins/user-settings/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/user-settings/package.json b/plugins/user-settings/package.json index 89fab2bfaa..b2926235e6 100644 --- a/plugins/user-settings/package.json +++ b/plugins/user-settings/package.json @@ -40,6 +40,7 @@ "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.57", + "@types/react": "^16.13.1 || ^17.0.0", "react-router": "6.0.0-beta.0", "react-use": "^17.2.4" }, @@ -56,7 +57,6 @@ "@testing-library/user-event": "^13.1.8", "@types/jest": "^26.0.7", "@types/node": "^14.14.32", - "@types/react": "^16.13.1 || ^17.0.0", "cross-fetch": "^3.1.5", "msw": "^0.35.0" }, From 0a0a4fa1784265f8ab1d0d998ceacdb863e57412 Mon Sep 17 00:00:00 2001 From: yousifalraheem Date: Mon, 4 Apr 2022 14:40:03 +0200 Subject: [PATCH 15/19] use attachComponentData instead of displayName in UserSettingsTab Signed-off-by: Yousif Al-Raheem --- .changeset/three-rivers-remain.md | 2 +- plugins/user-settings/api-report.md | 22 +++++++++--- .../src/components/SettingsPage.tsx | 34 ++++++++----------- .../UserSettingsTab/UserSettingsTab.tsx | 27 +++++++++++---- 4 files changed, 53 insertions(+), 32 deletions(-) diff --git a/.changeset/three-rivers-remain.md b/.changeset/three-rivers-remain.md index 8fa3893e28..d6bfeba093 100644 --- a/.changeset/three-rivers-remain.md +++ b/.changeset/three-rivers-remain.md @@ -1,5 +1,5 @@ --- -'@backstage/plugin-user-settings': minor +'@backstage/plugin-user-settings': patch --- Added the ability to render extra setting tabs diff --git a/plugins/user-settings/api-report.md b/plugins/user-settings/api-report.md index e95d0d9fe3..b2b57507aa 100644 --- a/plugins/user-settings/api-report.md +++ b/plugins/user-settings/api-report.md @@ -9,7 +9,7 @@ import { ApiRef } from '@backstage/core-plugin-api'; import { BackstagePlugin } from '@backstage/core-plugin-api'; import { IconComponent } from '@backstage/core-plugin-api'; import { ProfileInfo } from '@backstage/core-plugin-api'; -import { default as React_2 } from 'react'; +import { PropsWithChildren } from 'react'; import { RouteRef } from '@backstage/core-plugin-api'; import { SessionApi } from '@backstage/core-plugin-api'; @@ -44,6 +44,11 @@ export const Router: ({ providerSettings }: Props) => JSX.Element; // @public (undocumented) export const Settings: (props: SettingsProps) => JSX.Element; +// Warning: (ae-missing-release-tag) "USER_SETTINGS_TAB_KEY" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export const USER_SETTINGS_TAB_KEY = 'user-settings.tab'; + // Warning: (ae-missing-release-tag) "UserSettingsAppearanceCard" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) @@ -109,11 +114,16 @@ export const UserSettingsProfileCard: () => JSX.Element; // @public (undocumented) export const UserSettingsSignInAvatar: ({ size }: Props_5) => JSX.Element; -// Warning: (ae-forgotten-export) The symbol "Props" needs to be exported by the entry point index.d.ts -// Warning: (ae-missing-release-tag) "UserSettingsTab" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// @public +export const UserSettingsTab: (props: UserSettingsTabProps) => JSX.Element; + +// Warning: (ae-missing-release-tag) "UserSettingsTabProps" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) -export const UserSettingsTab: React_2.FC; +export type UserSettingsTabProps = PropsWithChildren<{ + path: string; + title: string; +}>; // Warning: (ae-missing-release-tag) "UserSettingsThemeToggle" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // @@ -128,4 +138,8 @@ export const useUserProfile: () => { displayName: string; loading: boolean; }; + +// Warnings were encountered during analysis: +// +// src/components/UserSettingsTab/UserSettingsTab.d.ts:6:17 - (tsdoc-code-span-missing-delimiter) The code span is missing its closing backtick ``` diff --git a/plugins/user-settings/src/components/SettingsPage.tsx b/plugins/user-settings/src/components/SettingsPage.tsx index 5be5851c16..8942235fda 100644 --- a/plugins/user-settings/src/components/SettingsPage.tsx +++ b/plugins/user-settings/src/components/SettingsPage.tsx @@ -20,11 +20,13 @@ import { SidebarPinStateContext, TabbedLayout, } from '@backstage/core-components'; -import React, { useContext, ReactElement } from 'react'; +import React, { useContext } from 'react'; import { useOutlet } from 'react-router'; +import { useElementFilter } from '@backstage/core-plugin-api'; import { UserSettingsAuthProviders } from './AuthProviders'; import { UserSettingsFeatureFlags } from './FeatureFlags'; import { UserSettingsGeneral } from './General'; +import { USER_SETTINGS_TAB_KEY, UserSettingsTabProps } from './UserSettingsTab'; type Props = { providerSettings?: JSX.Element; @@ -34,16 +36,13 @@ export const SettingsPage = ({ providerSettings }: Props) => { const { isMobile } = useContext(SidebarPinStateContext); const outlet = useOutlet(); - const extraTabs = (React.Children.toArray(outlet?.props?.children) || - []) as Array; - const notCompliantTab = Array.from(extraTabs).some( - child => (child.type as any)?.displayName !== 'UserSettingsTab', + const tabs = useElementFilter(outlet, elements => + elements + .selectByComponentData({ + key: USER_SETTINGS_TAB_KEY, + }) + .getElements(), ); - if (notCompliantTab) { - throw new Error( - 'Invalid element passed to SettingsPage Outlet. You may only pass children of type UserSettingsTab.', - ); - } return ( @@ -62,16 +61,11 @@ export const SettingsPage = ({ providerSettings }: Props) => {
- {extraTabs.map((child, i) => { - const path: string = child.props.path; - const title: string = child.props.title; - - return ( - - {child} - - ); - })} + {tabs.map((child, i) => ( + + {child} + + ))}
); diff --git a/plugins/user-settings/src/components/UserSettingsTab/UserSettingsTab.tsx b/plugins/user-settings/src/components/UserSettingsTab/UserSettingsTab.tsx index a0716ed88d..0da61feae6 100644 --- a/plugins/user-settings/src/components/UserSettingsTab/UserSettingsTab.tsx +++ b/plugins/user-settings/src/components/UserSettingsTab/UserSettingsTab.tsx @@ -13,15 +13,28 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import React from 'react'; +import React, { PropsWithChildren } from 'react'; +import { attachComponentData } from '@backstage/core-plugin-api'; -interface Props { +export const USER_SETTINGS_TAB_KEY = 'user-settings.tab'; + +export type UserSettingsTabProps = PropsWithChildren<{ + /** + * The path to the tab in the settings route + * @example `/settings/advanced + */ path: string; - title: React.ReactNode; -} + /** The title of the tab. It will also reflect in the document title when the tab is active */ + title: string; +}>; -export const UserSettingsTab: React.FC = ({ children }) => { - return <>{children}; +/** + * Renders a tab inside the settings page + * @param props - Component props + * @public + */ +export const UserSettingsTab = (props: UserSettingsTabProps) => { + return <>{props.children}; }; -UserSettingsTab.displayName = 'UserSettingsTab'; +attachComponentData(UserSettingsTab, USER_SETTINGS_TAB_KEY, 'UserSettingsTab'); From ff131b5fd33db84ae01d6067a996a50822223ba7 Mon Sep 17 00:00:00 2001 From: yousifalraheem Date: Mon, 4 Apr 2022 15:45:12 +0200 Subject: [PATCH 16/19] fix SettingsPage tests Signed-off-by: Yousif Al-Raheem --- .../src/components/SettingsPage.test.tsx | 35 +++++-------------- 1 file changed, 8 insertions(+), 27 deletions(-) diff --git a/plugins/user-settings/src/components/SettingsPage.test.tsx b/plugins/user-settings/src/components/SettingsPage.test.tsx index 865d0918e7..01810bcc8e 100644 --- a/plugins/user-settings/src/components/SettingsPage.test.tsx +++ b/plugins/user-settings/src/components/SettingsPage.test.tsx @@ -27,6 +27,10 @@ jest.mock('react-router', () => ({ import { useOutlet } from 'react-router'; describe('', () => { + beforeEach(() => { + (useOutlet as jest.Mock).mockReset(); + }); + it('should render the settings page with 3 tabs', async () => { const { container } = await renderWithEffects( wrapInTestApp(), @@ -38,13 +42,11 @@ describe('', () => { it('should render the settings page with 4 tabs when extra tabs are provided', async () => { const advancedTabRoute = ( - <> - -
Advanced settings
-
- + +
Advanced settings
+
); - (useOutlet as jest.Mock).mockReturnValueOnce(advancedTabRoute); + (useOutlet as jest.Mock).mockReturnValue(advancedTabRoute); const { container } = await renderWithEffects( wrapInTestApp(), ); @@ -53,25 +55,4 @@ describe('', () => { expect(tabs).toHaveLength(4); expect(tabs[3].textContent).toEqual('Advanced'); }); - - it('should throw error if non compliant route is passed to settings routes', async () => { - const advancedTabRoute = ( - <> - -
Advanced settings
-
-
Non compliant element
- - ); - (useOutlet as jest.Mock).mockReturnValueOnce(advancedTabRoute); - let error: Error; - try { - await renderWithEffects(wrapInTestApp()); - } catch (err) { - error = err; - } - expect(error!.message).toEqual( - expect.stringContaining('Invalid element passed'), - ); - }); }); From e7a2ed3f083a9399669342cec354209f1bb0f7a8 Mon Sep 17 00:00:00 2001 From: yousifalraheem Date: Mon, 4 Apr 2022 17:18:08 +0200 Subject: [PATCH 17/19] fix the warning in user-settings api-report Signed-off-by: Yousif Al-Raheem --- plugins/user-settings/api-report.md | 4 +--- .../src/components/UserSettingsTab/UserSettingsTab.tsx | 1 + 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/plugins/user-settings/api-report.md b/plugins/user-settings/api-report.md index b2b57507aa..5058fd5562 100644 --- a/plugins/user-settings/api-report.md +++ b/plugins/user-settings/api-report.md @@ -44,8 +44,6 @@ export const Router: ({ providerSettings }: Props) => JSX.Element; // @public (undocumented) export const Settings: (props: SettingsProps) => JSX.Element; -// Warning: (ae-missing-release-tag) "USER_SETTINGS_TAB_KEY" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) export const USER_SETTINGS_TAB_KEY = 'user-settings.tab'; @@ -141,5 +139,5 @@ export const useUserProfile: () => { // Warnings were encountered during analysis: // -// src/components/UserSettingsTab/UserSettingsTab.d.ts:6:17 - (tsdoc-code-span-missing-delimiter) The code span is missing its closing backtick +// src/components/UserSettingsTab/UserSettingsTab.d.ts:7:17 - (tsdoc-code-span-missing-delimiter) The code span is missing its closing backtick ``` diff --git a/plugins/user-settings/src/components/UserSettingsTab/UserSettingsTab.tsx b/plugins/user-settings/src/components/UserSettingsTab/UserSettingsTab.tsx index 0da61feae6..c1f29fe55c 100644 --- a/plugins/user-settings/src/components/UserSettingsTab/UserSettingsTab.tsx +++ b/plugins/user-settings/src/components/UserSettingsTab/UserSettingsTab.tsx @@ -16,6 +16,7 @@ import React, { PropsWithChildren } from 'react'; import { attachComponentData } from '@backstage/core-plugin-api'; +/** @public */ export const USER_SETTINGS_TAB_KEY = 'user-settings.tab'; export type UserSettingsTabProps = PropsWithChildren<{ From de47ed71ef713b26eadbbb0161f5504641590314 Mon Sep 17 00:00:00 2001 From: yousifalraheem Date: Mon, 4 Apr 2022 17:20:56 +0200 Subject: [PATCH 18/19] fix the warning in user-settings api-report Signed-off-by: Yousif Al-Raheem --- plugins/user-settings/api-report.md | 4 ---- .../src/components/UserSettingsTab/UserSettingsTab.tsx | 2 +- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/plugins/user-settings/api-report.md b/plugins/user-settings/api-report.md index 5058fd5562..89eb0e2f8b 100644 --- a/plugins/user-settings/api-report.md +++ b/plugins/user-settings/api-report.md @@ -136,8 +136,4 @@ export const useUserProfile: () => { displayName: string; loading: boolean; }; - -// Warnings were encountered during analysis: -// -// src/components/UserSettingsTab/UserSettingsTab.d.ts:7:17 - (tsdoc-code-span-missing-delimiter) The code span is missing its closing backtick ``` diff --git a/plugins/user-settings/src/components/UserSettingsTab/UserSettingsTab.tsx b/plugins/user-settings/src/components/UserSettingsTab/UserSettingsTab.tsx index c1f29fe55c..d916a9c12c 100644 --- a/plugins/user-settings/src/components/UserSettingsTab/UserSettingsTab.tsx +++ b/plugins/user-settings/src/components/UserSettingsTab/UserSettingsTab.tsx @@ -22,7 +22,7 @@ export const USER_SETTINGS_TAB_KEY = 'user-settings.tab'; export type UserSettingsTabProps = PropsWithChildren<{ /** * The path to the tab in the settings route - * @example `/settings/advanced + * @example `/settings/advanced` */ path: string; /** The title of the tab. It will also reflect in the document title when the tab is active */ From 6df5070a5290e10bccdcd33a270087077eb9c395 Mon Sep 17 00:00:00 2001 From: yousifalraheem Date: Mon, 4 Apr 2022 17:23:23 +0200 Subject: [PATCH 19/19] fix the warning in user-settings api-report Signed-off-by: Yousif Al-Raheem --- plugins/user-settings/api-report.md | 2 -- .../src/components/UserSettingsTab/UserSettingsTab.tsx | 1 + 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/plugins/user-settings/api-report.md b/plugins/user-settings/api-report.md index 89eb0e2f8b..136b23bd71 100644 --- a/plugins/user-settings/api-report.md +++ b/plugins/user-settings/api-report.md @@ -115,8 +115,6 @@ export const UserSettingsSignInAvatar: ({ size }: Props_5) => JSX.Element; // @public export const UserSettingsTab: (props: UserSettingsTabProps) => JSX.Element; -// Warning: (ae-missing-release-tag) "UserSettingsTabProps" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) export type UserSettingsTabProps = PropsWithChildren<{ path: string; diff --git a/plugins/user-settings/src/components/UserSettingsTab/UserSettingsTab.tsx b/plugins/user-settings/src/components/UserSettingsTab/UserSettingsTab.tsx index d916a9c12c..171c54ecf3 100644 --- a/plugins/user-settings/src/components/UserSettingsTab/UserSettingsTab.tsx +++ b/plugins/user-settings/src/components/UserSettingsTab/UserSettingsTab.tsx @@ -19,6 +19,7 @@ import { attachComponentData } from '@backstage/core-plugin-api'; /** @public */ export const USER_SETTINGS_TAB_KEY = 'user-settings.tab'; +/** @public */ export type UserSettingsTabProps = PropsWithChildren<{ /** * The path to the tab in the settings route