From 6735bd3ea14cd3ba16472a5939b6632de556dc8a Mon Sep 17 00:00:00 2001 From: Rakesh Thera Date: Fri, 22 Apr 2022 19:44:29 +0530 Subject: [PATCH 01/36] New PR with right sign off Signed-off-by: Rakesh Thera --- .../core-components/src/layout/Sidebar/Items.tsx | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/packages/core-components/src/layout/Sidebar/Items.tsx b/packages/core-components/src/layout/Sidebar/Items.tsx index 4a0376946a..b227d81dc1 100644 --- a/packages/core-components/src/layout/Sidebar/Items.tsx +++ b/packages/core-components/src/layout/Sidebar/Items.tsx @@ -369,6 +369,18 @@ const SidebarItemBase = forwardRef((props, ref) => { // Still waiting on a Q answered to fine tune the implementation const { isOpen } = useContext(SidebarContext); + const divStyle = + !isOpen && children ? { marginLeft: '24px', marginBottom: '4px' } : {}; + + const displayItemIcon = ( + <> +
+ + {!isOpen && children ? : <>} +
+ + ); + const itemIcon = ( ((props, ref) => { className={classnames({ [classes.closedItemIcon]: !isOpen })} > + {displayItemIcon} ); From aaffa18d8a9cdac5b1800b74430a1942b85245b9 Mon Sep 17 00:00:00 2001 From: Rakesh Thera Date: Mon, 25 Apr 2022 17:07:17 +0530 Subject: [PATCH 02/36] minor fixes Signed-off-by: Rakesh Thera --- packages/core-components/src/layout/Sidebar/Items.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/core-components/src/layout/Sidebar/Items.tsx b/packages/core-components/src/layout/Sidebar/Items.tsx index b227d81dc1..d2e2c22689 100644 --- a/packages/core-components/src/layout/Sidebar/Items.tsx +++ b/packages/core-components/src/layout/Sidebar/Items.tsx @@ -389,7 +389,6 @@ const SidebarItemBase = forwardRef((props, ref) => { invisible={!hasNotifications} className={classnames({ [classes.closedItemIcon]: !isOpen })} > - {displayItemIcon} ); From 521293b22e10e079fd3721ca6ee9b029ac05f41a Mon Sep 17 00:00:00 2001 From: Rakesh Thera Date: Tue, 26 Apr 2022 20:07:57 +0530 Subject: [PATCH 03/36] Inclued the changeset Signed-off-by: Rakesh Thera --- .changeset/tough-queens-hope.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/tough-queens-hope.md diff --git a/.changeset/tough-queens-hope.md b/.changeset/tough-queens-hope.md new file mode 100644 index 0000000000..c86d7f39b0 --- /dev/null +++ b/.changeset/tough-queens-hope.md @@ -0,0 +1,5 @@ +--- +'@backstage/core-components': patch +--- + +Added a chevron Indicator when the sidebar is collapsed and has a submenu From 42bdeb514fd408af71b5d9ed71547fd790862a62 Mon Sep 17 00:00:00 2001 From: Rakesh Thera Date: Wed, 27 Apr 2022 16:33:59 +0530 Subject: [PATCH 04/36] Corrected Spell checks Signed-off-by: Rakesh Thera --- .changeset/tough-queens-hope.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/tough-queens-hope.md b/.changeset/tough-queens-hope.md index c86d7f39b0..6816893611 100644 --- a/.changeset/tough-queens-hope.md +++ b/.changeset/tough-queens-hope.md @@ -2,4 +2,4 @@ '@backstage/core-components': patch --- -Added a chevron Indicator when the sidebar is collapsed and has a submenu +Added a chevron Indicator when the sidebar is collapsed and has a sub-menu From 3c0fca400105ebc284dbbb1eae6d2e49f2dd3c9a Mon Sep 17 00:00:00 2001 From: Suzanne Daniels Date: Wed, 11 May 2022 12:34:09 +0200 Subject: [PATCH 05/36] Updating community session content: - past sessions & upcoming in on-demand - Updated /live to embed the upcoming session Signed-off-by: Suzanne Daniels --- microsite/data/on-demand/20220420-1.yaml | 4 ++-- microsite/data/on-demand/20220427-1.yaml | 4 ++-- microsite/data/on-demand/20220518-01.yaml | 9 +++++++++ microsite/pages/en/live.js | 4 ++-- 4 files changed, 15 insertions(+), 6 deletions(-) create mode 100644 microsite/data/on-demand/20220518-01.yaml diff --git a/microsite/data/on-demand/20220420-1.yaml b/microsite/data/on-demand/20220420-1.yaml index a32402aa68..96560ec436 100644 --- a/microsite/data/on-demand/20220420-1.yaml +++ b/microsite/data/on-demand/20220420-1.yaml @@ -1,9 +1,9 @@ --- title: Adopters Community Sessions date: April 20, 2022 -category: Upcoming +category: Meetup description: Adopters Community Session ✨. It's the monthly meetup where we all come together to listen to the latest maintainer updates, learn from each other about adopting, share exciting new demos or discuss any relevant topic like developer effectiveness, developer experience, developer portals, etc. youtubeUrl: https://youtu.be/mFi_X58igzk youtubeImgUrl: https://backstage.io/img/b-sessions.png rsvpUrl: https://calendar.google.com/calendar/embed?src=c_qup9gbhn9sqpuao6trttd8mk5s@group.calendar.google.com -eventUrl: https://github.com/backstage/community/issues +eventUrl: https://github.com/backstage/community/issues/44 diff --git a/microsite/data/on-demand/20220427-1.yaml b/microsite/data/on-demand/20220427-1.yaml index f6b8873bb8..80ec8eae00 100644 --- a/microsite/data/on-demand/20220427-1.yaml +++ b/microsite/data/on-demand/20220427-1.yaml @@ -1,9 +1,9 @@ --- title: Contributor Community Sessions date: April 27, 2022 -category: Upcoming +category: Meetup description: Join the maintainers and contributors for the Contributor Community Sessions youtubeUrl: https://youtu.be/evf_LV0KzIk youtubeImgUrl: https://backstage.io/img/b-sessions.png rsvpUrl: https://calendar.google.com/calendar/embed?src=c_qup9gbhn9sqpuao6trttd8mk5s@group.calendar.google.com -eventUrl: https://github.com/backstage/community/issues +eventUrl: https://github.com/backstage/community/issues/44 diff --git a/microsite/data/on-demand/20220518-01.yaml b/microsite/data/on-demand/20220518-01.yaml new file mode 100644 index 0000000000..e98c79005a --- /dev/null +++ b/microsite/data/on-demand/20220518-01.yaml @@ -0,0 +1,9 @@ +--- +title: Adopters Community Sessions +date: May 18, 2022 +category: Upcoming +description: Adopters Community Session ✨. It's the monthly meetup where we all come together to listen to the latest maintainer updates, learn from each other about adopting, share exciting new demos or discuss any relevant topic like developer effectiveness, developer experience, developer portals, etc. +youtubeUrl: https://youtu.be/dEd1fl3wRv +youtubeImgUrl: https://backstage.io/img/b-sessions.png +rsvpUrl: https://calendar.google.com/calendar/embed?src=c_qup9gbhn9sqpuao6trttd8mk5s@group.calendar.google.com +eventUrl: https://github.com/backstage/community/issues/46 diff --git a/microsite/pages/en/live.js b/microsite/pages/en/live.js index 374b690d89..9f8a0e24b0 100644 --- a/microsite/pages/en/live.js +++ b/microsite/pages/en/live.js @@ -34,7 +34,7 @@ const Background = props => { From 201d0d31bb879703ef0865633620794b756947f2 Mon Sep 17 00:00:00 2001 From: Chris Trombley Date: Wed, 11 May 2022 11:36:23 -0700 Subject: [PATCH 06/36] fix(techdocs): update proxy endpoint for `serve` command Signed-off-by: Chris Trombley --- .changeset/stupid-radios-approve.md | 5 +++++ packages/techdocs-cli/src/lib/httpServer.ts | 9 ++++----- 2 files changed, 9 insertions(+), 5 deletions(-) create mode 100644 .changeset/stupid-radios-approve.md diff --git a/.changeset/stupid-radios-approve.md b/.changeset/stupid-radios-approve.md new file mode 100644 index 0000000000..813e895611 --- /dev/null +++ b/.changeset/stupid-radios-approve.md @@ -0,0 +1,5 @@ +--- +'@techdocs/cli': patch +--- + +Update `techdocs-cli serve`'s `proxyEndpoint` to match the base URL of the embedded techdocs app. diff --git a/packages/techdocs-cli/src/lib/httpServer.ts b/packages/techdocs-cli/src/lib/httpServer.ts index 92fc5abc87..c4bd5b823a 100644 --- a/packages/techdocs-cli/src/lib/httpServer.ts +++ b/packages/techdocs-cli/src/lib/httpServer.ts @@ -32,7 +32,7 @@ export default class HTTPServer { mkdocsPort: number, verbose: boolean, ) { - this.proxyEndpoint = '/api/'; + this.proxyEndpoint = '/api/techdocs/'; this.backstageBundleDir = backstageBundleDir; this.backstagePort = backstagePort; this.mkdocsPort = mkdocsPort; @@ -46,10 +46,9 @@ export default class HTTPServer { }); return (request: http.IncomingMessage): [httpProxy, string] => { - // If the request goes to /api/ we want to remove /api/ from the prefix of the request URL. - // e.g. ['/', 'api', pathChunks] - const [, , ...pathChunks] = request.url?.split('/') ?? []; - const forwardPath = pathChunks.join('/'); + // If the request path is prefixed with this.proxyEndpoint, remove it. + const proxyEndpointPath = new RegExp(`^${this.proxyEndpoint}`, 'i'); + const forwardPath = request.url?.replace(proxyEndpointPath, '') || ''; return [proxy, forwardPath]; }; From 79d25dfdf3e97e21957b6cdb7e2cb166d402ec04 Mon Sep 17 00:00:00 2001 From: Renovate Bot Date: Thu, 12 May 2022 12:00:24 +0000 Subject: [PATCH 07/36] fix(deps): update dependency immer to v9.0.14 Signed-off-by: Renovate Bot --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index 03a992be5e..c0df2328bd 100644 --- a/yarn.lock +++ b/yarn.lock @@ -14111,9 +14111,9 @@ immer@9.0.7: integrity sha512-KGllzpbamZDvOIxnmJ0jI840g7Oikx58lBPWV0hUh7dtAyZpFqqrBZdKka5GlTwMTZ1Tjc/bKKW4VSFAt6BqMA== immer@^9.0.1, immer@^9.0.7: - version "9.0.13" - resolved "https://registry.npmjs.org/immer/-/immer-9.0.13.tgz#cee90eb7d46513d58daab0d7c2e6ef69aa4c1786" - integrity sha512-LufFIoBO2q3CZoUiObiV6ICK7QsrxOIo8ReQHggmYHA7aSbQdsAiZ+mkR3cjRD5ZxC/0P6EMdx2kk6oj1qyFLw== + version "9.0.14" + resolved "https://registry.npmjs.org/immer/-/immer-9.0.14.tgz#e05b83b63999d26382bb71676c9d827831248a48" + integrity sha512-ubBeqQutOSLIFCUBN03jGeOS6a3DoYlSYwYJTa+gSKEZKU5redJIqkIdZ3JVv/4RZpfcXdAWH5zCNLWPRv2WDw== immutable@^3.x.x: version "3.8.2" From 2df2f01a293756e87af34a8f693af0f435cbabbc Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Thu, 12 May 2022 14:51:19 +0200 Subject: [PATCH 08/36] auth-backend: remove disableRefresh option Signed-off-by: Patrik Oldsberg --- .changeset/nervous-bears-brush.md | 5 ++ .changeset/unlucky-bobcats-fold.md | 5 ++ docs/auth/add-auth-provider.md | 1 - plugins/auth-backend/api-report.md | 6 +-- .../src/lib/oauth/OAuthAdapter.test.ts | 52 ------------------- .../src/lib/oauth/OAuthAdapter.ts | 11 ++-- .../src/providers/auth0/provider.ts | 1 - .../src/providers/bitbucket/provider.ts | 1 - .../src/providers/gitlab/provider.ts | 1 - .../src/providers/google/provider.ts | 1 - .../src/providers/microsoft/provider.ts | 1 - .../src/providers/oauth2/provider.ts | 9 +++- .../src/providers/oidc/provider.ts | 1 - .../src/providers/okta/provider.ts | 1 - .../src/providers/onelogin/provider.ts | 1 - 15 files changed, 22 insertions(+), 75 deletions(-) create mode 100644 .changeset/nervous-bears-brush.md create mode 100644 .changeset/unlucky-bobcats-fold.md diff --git a/.changeset/nervous-bears-brush.md b/.changeset/nervous-bears-brush.md new file mode 100644 index 0000000000..f3b0c7db78 --- /dev/null +++ b/.changeset/nervous-bears-brush.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-auth-backend': patch +--- + +The Auth0 adapter no longer disables session refreshing. diff --git a/.changeset/unlucky-bobcats-fold.md b/.changeset/unlucky-bobcats-fold.md new file mode 100644 index 0000000000..6dd820db8d --- /dev/null +++ b/.changeset/unlucky-bobcats-fold.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-auth-backend': minor +--- + +Removed the explicit `disableRefresh` option from `OAuthAdapter`. Refresh can still be disabled for a provider by not implementing the `refresh` method. diff --git a/docs/auth/add-auth-provider.md b/docs/auth/add-auth-provider.md index 282088fef9..bd2bcd1694 100644 --- a/docs/auth/add-auth-provider.md +++ b/docs/auth/add-auth-provider.md @@ -153,7 +153,6 @@ export const createOktaProvider: AuthProviderFactory = ({ // Wrap the OAuthProviderHandlers with OAuthProvider, which implements AuthProviderRouteHandlers return OAuthProvider.fromConfig(globalConfig, provider, { - disableRefresh: false, providerId, tokenIssuer, }); diff --git a/plugins/auth-backend/api-report.md b/plugins/auth-backend/api-report.md index a38197668e..bb25ff6d57 100644 --- a/plugins/auth-backend/api-report.md +++ b/plugins/auth-backend/api-report.md @@ -586,11 +586,7 @@ export class OAuthAdapter implements AuthProviderRouteHandlers { handlers: OAuthHandlers, options: Pick< Options, - | 'providerId' - | 'persistScopes' - | 'disableRefresh' - | 'tokenIssuer' - | 'callbackUrl' + 'providerId' | 'persistScopes' | 'tokenIssuer' | 'callbackUrl' >, ): OAuthAdapter; // (undocumented) diff --git a/plugins/auth-backend/src/lib/oauth/OAuthAdapter.test.ts b/plugins/auth-backend/src/lib/oauth/OAuthAdapter.test.ts index 0ce9dff66c..d6d346745a 100644 --- a/plugins/auth-backend/src/lib/oauth/OAuthAdapter.test.ts +++ b/plugins/auth-backend/src/lib/oauth/OAuthAdapter.test.ts @@ -60,7 +60,6 @@ describe('OAuthAdapter', () => { const oAuthProviderOptions = { providerId: 'test-provider', secure: false, - disableRefresh: true, appOrigin: 'http://localhost:3000', cookieDomain: 'example.com', cookiePath: '/auth/test-provider', @@ -110,7 +109,6 @@ describe('OAuthAdapter', () => { it('sets the refresh cookie if refresh is enabled', async () => { const oauthProvider = new OAuthAdapter(providerInstance, { ...oAuthProviderOptions, - disableRefresh: false, isOriginAllowed: () => false, }); @@ -153,7 +151,6 @@ describe('OAuthAdapter', () => { }; const oauthProvider = new OAuthAdapter(handlers, { ...oAuthProviderOptions, - disableRefresh: false, persistScopes: true, }); @@ -238,36 +235,9 @@ describe('OAuthAdapter', () => { ); }); - it('does not set the refresh cookie if refresh is disabled', async () => { - const oauthProvider = new OAuthAdapter(providerInstance, { - ...oAuthProviderOptions, - disableRefresh: true, - isOriginAllowed: () => false, - }); - - const mockRequest = { - cookies: { - 'test-provider-nonce': 'nonce', - }, - query: { - state: 'nonce', - }, - } as unknown as express.Request; - - const mockResponse = { - cookie: jest.fn().mockReturnThis(), - setHeader: jest.fn().mockReturnThis(), - end: jest.fn().mockReturnThis(), - } as unknown as express.Response; - - await oauthProvider.frameHandler(mockRequest, mockResponse); - expect(mockResponse.cookie).toHaveBeenCalledTimes(0); - }); - it('removes refresh cookie when logging out', async () => { const oauthProvider = new OAuthAdapter(providerInstance, { ...oAuthProviderOptions, - disableRefresh: false, isOriginAllowed: () => false, }); @@ -292,10 +262,8 @@ describe('OAuthAdapter', () => { }); it('gets new access-token when refreshing', async () => { - oAuthProviderOptions.disableRefresh = false; const oauthProvider = new OAuthAdapter(providerInstance, { ...oAuthProviderOptions, - disableRefresh: false, isOriginAllowed: () => false, }); @@ -327,26 +295,6 @@ describe('OAuthAdapter', () => { }); }); - it('handles refresh without capabilities', async () => { - const oauthProvider = new OAuthAdapter(providerInstance, { - ...oAuthProviderOptions, - disableRefresh: true, - isOriginAllowed: () => false, - }); - - const mockRequest = { - header: () => 'XMLHttpRequest', - } as unknown as express.Request; - - const mockResponse = {} as unknown as express.Response; - - await expect( - oauthProvider.refresh(mockRequest, mockResponse), - ).rejects.toThrow( - 'Refresh token is not supported for provider test-provider', - ); - }); - it('sets the correct cookie configuration using a callbackUrl', async () => { const config = { baseUrl: 'http://domain.org/auth', diff --git a/plugins/auth-backend/src/lib/oauth/OAuthAdapter.ts b/plugins/auth-backend/src/lib/oauth/OAuthAdapter.ts index 637dc1cff2..5be4b7e3c0 100644 --- a/plugins/auth-backend/src/lib/oauth/OAuthAdapter.ts +++ b/plugins/auth-backend/src/lib/oauth/OAuthAdapter.ts @@ -48,7 +48,6 @@ export const TEN_MINUTES_MS = 600 * 1000; export type Options = { providerId: string; secure: boolean; - disableRefresh?: boolean; persistScopes?: boolean; cookieDomain: string; cookiePath: string; @@ -64,11 +63,7 @@ export class OAuthAdapter implements AuthProviderRouteHandlers { handlers: OAuthHandlers, options: Pick< Options, - | 'providerId' - | 'persistScopes' - | 'disableRefresh' - | 'tokenIssuer' - | 'callbackUrl' + 'providerId' | 'persistScopes' | 'tokenIssuer' | 'callbackUrl' >, ): OAuthAdapter { const { origin: appOrigin } = new URL(config.appUrl); @@ -170,7 +165,7 @@ export class OAuthAdapter implements AuthProviderRouteHandlers { response.providerInfo.scope = state.scope; } - if (refreshToken && !this.options.disableRefresh) { + if (refreshToken) { // set new refresh token this.setRefreshTokenCookie(res, refreshToken); } @@ -210,7 +205,7 @@ export class OAuthAdapter implements AuthProviderRouteHandlers { throw new AuthenticationError('Invalid X-Requested-With header'); } - if (!this.handlers.refresh || this.options.disableRefresh) { + if (!this.handlers.refresh) { throw new InputError( `Refresh token is not supported for provider ${this.options.providerId}`, ); diff --git a/plugins/auth-backend/src/providers/auth0/provider.ts b/plugins/auth-backend/src/providers/auth0/provider.ts index 3181314540..9ddd587508 100644 --- a/plugins/auth-backend/src/providers/auth0/provider.ts +++ b/plugins/auth-backend/src/providers/auth0/provider.ts @@ -243,7 +243,6 @@ export const auth0 = createAuthProviderIntegration({ }); return OAuthAdapter.fromConfig(globalConfig, provider, { - disableRefresh: true, providerId, callbackUrl, }); diff --git a/plugins/auth-backend/src/providers/bitbucket/provider.ts b/plugins/auth-backend/src/providers/bitbucket/provider.ts index 905181333a..5b9919764b 100644 --- a/plugins/auth-backend/src/providers/bitbucket/provider.ts +++ b/plugins/auth-backend/src/providers/bitbucket/provider.ts @@ -261,7 +261,6 @@ export const bitbucket = createAuthProviderIntegration({ }); return OAuthAdapter.fromConfig(globalConfig, provider, { - disableRefresh: false, providerId, callbackUrl, }); diff --git a/plugins/auth-backend/src/providers/gitlab/provider.ts b/plugins/auth-backend/src/providers/gitlab/provider.ts index 23867f6990..868357bcda 100644 --- a/plugins/auth-backend/src/providers/gitlab/provider.ts +++ b/plugins/auth-backend/src/providers/gitlab/provider.ts @@ -248,7 +248,6 @@ export const gitlab = createAuthProviderIntegration({ }); return OAuthAdapter.fromConfig(globalConfig, provider, { - disableRefresh: false, providerId, callbackUrl, }); diff --git a/plugins/auth-backend/src/providers/google/provider.ts b/plugins/auth-backend/src/providers/google/provider.ts index 233e28f750..2d58bc2aa6 100644 --- a/plugins/auth-backend/src/providers/google/provider.ts +++ b/plugins/auth-backend/src/providers/google/provider.ts @@ -238,7 +238,6 @@ export const google = createAuthProviderIntegration({ }); return OAuthAdapter.fromConfig(globalConfig, provider, { - disableRefresh: false, providerId, callbackUrl, }); diff --git a/plugins/auth-backend/src/providers/microsoft/provider.ts b/plugins/auth-backend/src/providers/microsoft/provider.ts index 0a4b67d667..0c58049619 100644 --- a/plugins/auth-backend/src/providers/microsoft/provider.ts +++ b/plugins/auth-backend/src/providers/microsoft/provider.ts @@ -267,7 +267,6 @@ export const microsoft = createAuthProviderIntegration({ }); return OAuthAdapter.fromConfig(globalConfig, provider, { - disableRefresh: false, providerId, callbackUrl, }); diff --git a/plugins/auth-backend/src/providers/oauth2/provider.ts b/plugins/auth-backend/src/providers/oauth2/provider.ts index 8e0250cf2f..6b4787e985 100644 --- a/plugins/auth-backend/src/providers/oauth2/provider.ts +++ b/plugins/auth-backend/src/providers/oauth2/provider.ts @@ -43,6 +43,7 @@ import { SignInResolver, } from '../types'; import { createAuthProviderIntegration } from '../createAuthProviderIntegration'; +import { InputError } from '@backstage/errors'; type PrivateInfo = { refreshToken: string; @@ -56,6 +57,7 @@ export type OAuth2AuthProviderOptions = OAuthProviderOptions & { scope?: string; resolverContext: AuthResolverContext; includeBasicAuth?: boolean; + disableRefresh?: boolean; }; export class OAuth2AuthProvider implements OAuthHandlers { @@ -63,11 +65,13 @@ export class OAuth2AuthProvider implements OAuthHandlers { private readonly signInResolver?: SignInResolver; private readonly authHandler: AuthHandler; private readonly resolverContext: AuthResolverContext; + private readonly disableRefresh: boolean; constructor(options: OAuth2AuthProviderOptions) { this.signInResolver = options.signInResolver; this.authHandler = options.authHandler; this.resolverContext = options.resolverContext; + this.disableRefresh = options.disableRefresh ?? false; this._strategy = new OAuth2Strategy( { @@ -132,6 +136,9 @@ export class OAuth2AuthProvider implements OAuthHandlers { } async refresh(req: OAuthRefreshRequest) { + if (this.disableRefresh) { + throw new InputError('Session refreshes have been disabled'); + } const refreshTokenResponse = await executeRefreshTokenStrategy( this._strategy, req.refreshToken, @@ -243,10 +250,10 @@ export const oauth2 = createAuthProviderIntegration({ scope, includeBasicAuth, resolverContext, + disableRefresh, }); return OAuthAdapter.fromConfig(globalConfig, provider, { - disableRefresh, providerId, callbackUrl, }); diff --git a/plugins/auth-backend/src/providers/oidc/provider.ts b/plugins/auth-backend/src/providers/oidc/provider.ts index aba9048cc7..69a65d1cae 100644 --- a/plugins/auth-backend/src/providers/oidc/provider.ts +++ b/plugins/auth-backend/src/providers/oidc/provider.ts @@ -262,7 +262,6 @@ export const oidc = createAuthProviderIntegration({ }); return OAuthAdapter.fromConfig(globalConfig, provider, { - disableRefresh: false, providerId, callbackUrl, }); diff --git a/plugins/auth-backend/src/providers/okta/provider.ts b/plugins/auth-backend/src/providers/okta/provider.ts index 4e05ff4487..98cec6df3a 100644 --- a/plugins/auth-backend/src/providers/okta/provider.ts +++ b/plugins/auth-backend/src/providers/okta/provider.ts @@ -271,7 +271,6 @@ export const okta = createAuthProviderIntegration({ }); return OAuthAdapter.fromConfig(globalConfig, provider, { - disableRefresh: false, providerId, callbackUrl, }); diff --git a/plugins/auth-backend/src/providers/onelogin/provider.ts b/plugins/auth-backend/src/providers/onelogin/provider.ts index 7dcc6455ac..d81eb3d83c 100644 --- a/plugins/auth-backend/src/providers/onelogin/provider.ts +++ b/plugins/auth-backend/src/providers/onelogin/provider.ts @@ -238,7 +238,6 @@ export const onelogin = createAuthProviderIntegration({ }); return OAuthAdapter.fromConfig(globalConfig, provider, { - disableRefresh: false, providerId, callbackUrl, }); From 7dd858b4b8f5e3c8daca66adcce7ee126a41ce58 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Thu, 12 May 2022 14:57:36 +0200 Subject: [PATCH 09/36] workflows/verify_dco: stronger wording Signed-off-by: Patrik Oldsberg --- .github/workflows/verify_dco.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/verify_dco.yaml b/.github/workflows/verify_dco.yaml index 71bd322eca..2094327d23 100644 --- a/.github/workflows/verify_dco.yaml +++ b/.github/workflows/verify_dco.yaml @@ -54,7 +54,7 @@ jobs: console.log(`creating comment on PR #${pull.number}`); const body = ` Thanks for the contribution! - All commits need to be DCO signed before merging. Please refer to the the [DCO section in CONTRIBUTING.md](https://github.com/backstage/backstage/blob/master/CONTRIBUTING.md#developer-certificate-of-origin) or the [DCO](${checks.data.check_runs[0].html_url}) status for more info. + All commits need to be DCO signed before they are reviewed. Please refer to the the [DCO section in CONTRIBUTING.md](https://github.com/backstage/backstage/blob/master/CONTRIBUTING.md#developer-certificate-of-origin) or the [DCO](${checks.data.check_runs[0].html_url}) status for more info. `; await github.rest.issues.createComment({ repo, From 3d80cff34a42e9aed101b6ade5da9849f9e684dc Mon Sep 17 00:00:00 2001 From: Renovate Bot Date: Thu, 12 May 2022 13:00:39 +0000 Subject: [PATCH 10/36] fix(deps): update dependency aws-sdk to v2.1133.0 Signed-off-by: Renovate Bot --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index c0df2328bd..b2d6ea7d76 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7914,9 +7914,9 @@ aws-sdk-mock@^5.2.1: traverse "^0.6.6" aws-sdk@^2.1122.0, aws-sdk@^2.840.0, aws-sdk@^2.948.0: - version "2.1132.0" - resolved "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.1132.0.tgz#0cb615e97db5a5133914ba0f2bdc8ea10eef4069" - integrity sha512-NPDesfTrNx8UMQ5VuosQNlFFFhswJ8cGVcVltZBXKVl1kW0BCp52XQBySSruIznaRX7vG6Ir2+nox0NdL05qBQ== + version "2.1133.0" + resolved "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.1133.0.tgz#db530faaa8dbe98503fd600b4e95efdd1c3996c7" + integrity sha512-TK7lcDxkrAc15Lmx030u4Wn3P798oxBVs79DBsD8+cZcW5Y8Gvat+evIZpkDoqh8YsfegvlI2jFg4ECQxKYPVA== dependencies: buffer "4.9.2" events "1.1.1" From 1b3ba5d198a2e1ab5d2521c9b949eeaba7d87994 Mon Sep 17 00:00:00 2001 From: Eric Peterson Date: Thu, 12 May 2022 15:24:18 +0200 Subject: [PATCH 11/36] Work around node-fetch 2.x bug in TechDocs collator Signed-off-by: Eric Peterson --- .changeset/techdocs-seal-deal.md | 5 +++++ .../src/search/DefaultTechDocsCollatorFactory.ts | 13 ++++++++++++- 2 files changed, 17 insertions(+), 1 deletion(-) create mode 100644 .changeset/techdocs-seal-deal.md diff --git a/.changeset/techdocs-seal-deal.md b/.changeset/techdocs-seal-deal.md new file mode 100644 index 0000000000..865d1fc837 --- /dev/null +++ b/.changeset/techdocs-seal-deal.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-techdocs-backend': patch +--- + +Fixed a bug that could cause TechDocs index generation to hang and fail when an underlying TechDocs site's `search_index.json` was empty. diff --git a/plugins/techdocs-backend/src/search/DefaultTechDocsCollatorFactory.ts b/plugins/techdocs-backend/src/search/DefaultTechDocsCollatorFactory.ts index 915b027854..d458eeaba0 100644 --- a/plugins/techdocs-backend/src/search/DefaultTechDocsCollatorFactory.ts +++ b/plugins/techdocs-backend/src/search/DefaultTechDocsCollatorFactory.ts @@ -179,7 +179,18 @@ export class DefaultTechDocsCollatorFactory implements DocumentCollatorFactory { }, }, ); - const searchIndex = await searchIndexResponse.json(); + + // todo(@backstage/techdocs-core): remove Promise.race() when node-fetch is 3.x+ + // workaround for fetch().json() hanging in node-fetch@2.x.x, fixed in 3.x.x + // https://github.com/node-fetch/node-fetch/issues/665 + const searchIndex = await Promise.race([ + searchIndexResponse.json(), + new Promise((_resolve, reject) => { + setTimeout(() => { + reject('Could not parse JSON in 5 seconds.'); + }, 5000); + }), + ]); return searchIndex.docs.map((doc: MkSearchIndexDoc) => ({ title: unescape(doc.title), From 88105bcec115064dfeee5b0ea6f2c0a62fa5c4ca Mon Sep 17 00:00:00 2001 From: Renovate Bot Date: Thu, 12 May 2022 13:47:53 +0000 Subject: [PATCH 12/36] fix(deps): update dependency zod to v3.16.0 Signed-off-by: Renovate Bot --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index b2d6ea7d76..c1f374323b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -25857,9 +25857,9 @@ zip-stream@^4.1.0: readable-stream "^3.6.0" zod@^3.11.6, zod@^3.9.5: - version "3.15.1" - resolved "https://registry.npmjs.org/zod/-/zod-3.15.1.tgz#9e404cd8002ccffb03baa94cff2e1638ed49d82f" - integrity sha512-WAdjcoOxa4S9oc/u7fTbC3CC7uVqptLLU0LKqS8RDBOrCXp2t5avM8BUfgNVZJymGWAx6SEUYxWPPoYuQ5rgwQ== + version "3.16.0" + resolved "https://registry.npmjs.org/zod/-/zod-3.16.0.tgz#edfdbf77fcc9a5af13a2630a44bdda5b90e759b7" + integrity sha512-szrIkryADbTM+xBt2a1KoS2CJQXec4f9xG78bj5MJeEH/XqmmHpnO+fG3IE115AKBJak+2HrbxLZkc9mhdbDKA== zustand@3.6.9: version "3.6.9" From 7cf39c6788e91f580cca450ceb2ebf9824375dcc Mon Sep 17 00:00:00 2001 From: Christopher Fry Date: Fri, 13 May 2022 00:33:17 +0000 Subject: [PATCH 13/36] Add configuration as data to plugin marketplace Signed-off-by: Christopher Fry --- microsite/data/plugins/kpt-config-as-data.yaml | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 microsite/data/plugins/kpt-config-as-data.yaml diff --git a/microsite/data/plugins/kpt-config-as-data.yaml b/microsite/data/plugins/kpt-config-as-data.yaml new file mode 100644 index 0000000000..03d5d66947 --- /dev/null +++ b/microsite/data/plugins/kpt-config-as-data.yaml @@ -0,0 +1,9 @@ +--- +title: Configuration as Data +author: kpt +authorUrl: https://kpt.dev +category: Configuration +description: Configuration GUI over GitOps using kpt, with WYSIWYG editing, review and approval, versioning and undo, and package cloning and upgrades. +documentation: https://github.com/GoogleContainerTools/kpt-backstage-plugins/tree/main/plugins/cad +iconUrl: https://github.com/GoogleContainerTools/kpt/blob/main/logo/KptLogoSmall.png?raw=true +npmPackageName: '@kpt/backstage-plugin-cad' From 9eef9c9db478831a4d427a8d9bbf1c348fb1b19f Mon Sep 17 00:00:00 2001 From: Phil Kuang Date: Thu, 12 May 2022 21:32:44 -0400 Subject: [PATCH 14/36] fix(elasticSearch): do not define pageCursor on last page Signed-off-by: Phil Kuang --- .changeset/pretty-hornets-listen.md | 5 +++ .../engines/ElasticSearchSearchEngine.test.ts | 44 +++++++++++++++++++ .../src/engines/ElasticSearchSearchEngine.ts | 2 +- 3 files changed, 50 insertions(+), 1 deletion(-) create mode 100644 .changeset/pretty-hornets-listen.md diff --git a/.changeset/pretty-hornets-listen.md b/.changeset/pretty-hornets-listen.md new file mode 100644 index 0000000000..6e0701e617 --- /dev/null +++ b/.changeset/pretty-hornets-listen.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-search-backend-module-elasticsearch': patch +--- + +Fix issue where `nextPageCursor` is defined on the last page of results diff --git a/plugins/search-backend-module-elasticsearch/src/engines/ElasticSearchSearchEngine.test.ts b/plugins/search-backend-module-elasticsearch/src/engines/ElasticSearchSearchEngine.test.ts index 134de5a9f6..24ceec2875 100644 --- a/plugins/search-backend-module-elasticsearch/src/engines/ElasticSearchSearchEngine.test.ts +++ b/plugins/search-backend-module-elasticsearch/src/engines/ElasticSearchSearchEngine.test.ts @@ -438,6 +438,50 @@ describe('ElasticSearchSearchEngine', () => { }); }); + it('should perform search query with less results than one page', async () => { + mock.clear({ + method: 'POST', + path: '/*__search/_search', + }); + mock.add( + { + method: 'POST', + path: '/*__search/_search', + }, + () => { + return { + hits: { + total: { value: 20, relation: 'eq' }, + hits: Array(20) + .fill(null) + .map((_, i) => ({ + _index: 'mytype-index__', + _source: { + value: `${i}`, + }, + })), + }, + }; + }, + ); + + const mockedSearchResult = await testSearchEngine.query({ + term: 'testTerm', + filters: {}, + }); + + expect(mockedSearchResult).toMatchObject({ + results: expect.arrayContaining( + Array(20) + .fill(null) + .map((_, i) => ({ + type: 'mytype', + document: { value: `${i}` }, + })), + ), + }); + }); + it('should perform search query with more results than one page', async () => { mock.clear({ method: 'POST', diff --git a/plugins/search-backend-module-elasticsearch/src/engines/ElasticSearchSearchEngine.ts b/plugins/search-backend-module-elasticsearch/src/engines/ElasticSearchSearchEngine.ts index 5ec33a95e3..00c25905c3 100644 --- a/plugins/search-backend-module-elasticsearch/src/engines/ElasticSearchSearchEngine.ts +++ b/plugins/search-backend-module-elasticsearch/src/engines/ElasticSearchSearchEngine.ts @@ -268,7 +268,7 @@ export class ElasticSearchSearchEngine implements SearchEngine { body: elasticSearchQuery, }); const { page } = decodePageCursor(query.pageCursor); - const hasNextPage = result.body.hits.total.value > page * pageSize; + const hasNextPage = result.body.hits.total.value > (page + 1) * pageSize; const hasPreviousPage = page > 0; const nextPageCursor = hasNextPage ? encodePageCursor({ page: page + 1 }) From b660479ac47bb00f83df8f516b40a7b21354f1ad Mon Sep 17 00:00:00 2001 From: blam Date: Fri, 13 May 2022 12:45:38 +0200 Subject: [PATCH 15/36] chore: add explicit toolkit dep in this package Signed-off-by: blam --- plugins/graphiql/package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/plugins/graphiql/package.json b/plugins/graphiql/package.json index e19a3e40d1..d43b5f2267 100644 --- a/plugins/graphiql/package.json +++ b/plugins/graphiql/package.json @@ -41,6 +41,7 @@ "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.57", "graphiql": "^1.5.12", + "@graphiql/toolkit": "0.4.4", "graphql": "^16.0.0", "react-use": "^17.2.4" }, From 91d0c9d18692cbd6e9e54a558fea9c45d01e0b4b Mon Sep 17 00:00:00 2001 From: blam Date: Fri, 13 May 2022 12:58:17 +0200 Subject: [PATCH 16/36] chore: added changeset for reverting the package Signed-off-by: blam --- .changeset/tall-tables-smash.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/tall-tables-smash.md diff --git a/.changeset/tall-tables-smash.md b/.changeset/tall-tables-smash.md new file mode 100644 index 0000000000..25595c9c54 --- /dev/null +++ b/.changeset/tall-tables-smash.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-graphiql': patch +--- + +Lock the dependency of `@graphiql/toolkit` because of broken release From 8462ccbc65d346c0190f478ef95c84cf9349372c Mon Sep 17 00:00:00 2001 From: blam Date: Fri, 13 May 2022 13:20:48 +0200 Subject: [PATCH 17/36] chore: add the dependency Signed-off-by: blam --- plugins/graphiql/package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/plugins/graphiql/package.json b/plugins/graphiql/package.json index d43b5f2267..67855607d6 100644 --- a/plugins/graphiql/package.json +++ b/plugins/graphiql/package.json @@ -41,7 +41,7 @@ "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.57", "graphiql": "^1.5.12", - "@graphiql/toolkit": "0.4.4", + "graphql-ws": "5.5.5", "graphql": "^16.0.0", "react-use": "^17.2.4" }, diff --git a/yarn.lock b/yarn.lock index c1f374323b..6ec8648cac 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2246,9 +2246,9 @@ xdg-basedir "^4.0.0" "@graphiql/toolkit@^0.4.4": - version "0.4.4" - resolved "https://registry.npmjs.org/@graphiql/toolkit/-/toolkit-0.4.4.tgz#c5f2cd0d7fc47707f68406655836aedc5e6ca2b1" - integrity sha512-HrppQ5u0uJPYpImLqQUJWNrS9E97Cmz8DO3Dn0dXeCg1iBoKjRnZoFf2rjFF5ge9Uc9RihL181Uph/Iw9YYMFg== + version "0.4.5" + resolved "https://registry.npmjs.org/@graphiql/toolkit/-/toolkit-0.4.5.tgz#9fb5020444712562eae9581724695c235f610836" + integrity sha512-QXuuMSSK/0GfBS7tltrGZdyhIvm6oe9TK4VW9pfa8dALYttpzyJ64Q4Sx9I1Ng++yOMJWziM/ksa043zkNHsjQ== dependencies: "@n1ru4l/push-pull-async-iterable-iterator" "^3.1.0" meros "^1.1.4" @@ -13485,7 +13485,7 @@ graphql-type-json@^0.3.2: resolved "https://registry.npmjs.org/graphql-type-json/-/graphql-type-json-0.3.2.tgz#f53a851dbfe07bd1c8157d24150064baab41e115" integrity sha512-J+vjof74oMlCWXSvt0DOf2APEdZOCdubEvGDUAlqH//VBYcOYsGgRW7Xzorr44LvkjiuvecWc8fChxuZZbChtg== -graphql-ws@^5.4.1: +graphql-ws@5.5.5, graphql-ws@^5.4.1: version "5.5.5" resolved "https://registry.npmjs.org/graphql-ws/-/graphql-ws-5.5.5.tgz#f375486d3f196e2a2527b503644693ae3a8670a9" integrity sha512-hvyIS71vs4Tu/yUYHPvGXsTgo0t3arU820+lT5VjZS2go0ewp2LqyCgxEN56CzOG7Iys52eRhHBiD1gGRdiQtw== From 0ca550ddc73f737e29114c515dc18e66e59d8866 Mon Sep 17 00:00:00 2001 From: blam Date: Fri, 13 May 2022 13:22:19 +0200 Subject: [PATCH 18/36] chore: updating changeset Signed-off-by: blam --- .changeset/tall-tables-smash.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/tall-tables-smash.md b/.changeset/tall-tables-smash.md index 25595c9c54..e06914af71 100644 --- a/.changeset/tall-tables-smash.md +++ b/.changeset/tall-tables-smash.md @@ -2,4 +2,4 @@ '@backstage/plugin-graphiql': patch --- -Lock the dependency of `@graphiql/toolkit` because of broken release +Add the dependency `graphql-ws` to fix the latest release of `@graphiql/toolkit` that has a missing dependency From a4a6a72a95f24dd947881db8fdfe56e8253d3b21 Mon Sep 17 00:00:00 2001 From: blam Date: Fri, 13 May 2022 13:37:19 +0200 Subject: [PATCH 19/36] chore: pull any version Signed-off-by: blam --- packages/backend/src/plugins/auth.ts | 6 +----- plugins/graphiql/package.json | 2 +- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/packages/backend/src/plugins/auth.ts b/packages/backend/src/plugins/auth.ts index cd0c42afe5..984ddd9651 100644 --- a/packages/backend/src/plugins/auth.ts +++ b/packages/backend/src/plugins/auth.ts @@ -42,11 +42,7 @@ export default async function createPlugin( // It is important that each real user always gets resolved to // the same sign-in identity. The code below will not do that. // It is here for demo purposes only. - github: providers.github.create({ - signIn: { - resolver: providers.github.resolvers.usernameMatchingUserEntityName(), - }, - }), + github: providers.github.create(), gitlab: providers.gitlab.create({ signIn: { async resolver({ result: { fullProfile } }, ctx) { diff --git a/plugins/graphiql/package.json b/plugins/graphiql/package.json index 67855607d6..99903cb63c 100644 --- a/plugins/graphiql/package.json +++ b/plugins/graphiql/package.json @@ -41,7 +41,7 @@ "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.57", "graphiql": "^1.5.12", - "graphql-ws": "5.5.5", + "graphql-ws": "^5.4.1", "graphql": "^16.0.0", "react-use": "^17.2.4" }, From cf58f3415a5b2ce5c764e90f6c9b54136affd585 Mon Sep 17 00:00:00 2001 From: blam Date: Fri, 13 May 2022 13:39:32 +0200 Subject: [PATCH 20/36] chore: bump api-docs too Signed-off-by: blam --- .changeset/tall-tables-smash.md | 1 + plugins/api-docs/package.json | 1 + 2 files changed, 2 insertions(+) diff --git a/.changeset/tall-tables-smash.md b/.changeset/tall-tables-smash.md index e06914af71..2bf277879e 100644 --- a/.changeset/tall-tables-smash.md +++ b/.changeset/tall-tables-smash.md @@ -1,5 +1,6 @@ --- '@backstage/plugin-graphiql': patch +'@backstage/plugin-api-docs': patch --- Add the dependency `graphql-ws` to fix the latest release of `@graphiql/toolkit` that has a missing dependency diff --git a/plugins/api-docs/package.json b/plugins/api-docs/package.json index 1c00a4b01e..ddf837493b 100644 --- a/plugins/api-docs/package.json +++ b/plugins/api-docs/package.json @@ -44,6 +44,7 @@ "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.57", "graphiql": "^1.8.8", + "graphql-ws": "^5.4.1", "graphql": "^16.0.0", "isomorphic-form-data": "^2.0.0", "react-router": "6.0.0-beta.0", From 2658e9420f6a2a530f7d0e9d37a5765549bf014a Mon Sep 17 00:00:00 2001 From: blam Date: Fri, 13 May 2022 13:40:00 +0200 Subject: [PATCH 21/36] chore: reset Signed-off-by: blam --- packages/backend/src/plugins/auth.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/packages/backend/src/plugins/auth.ts b/packages/backend/src/plugins/auth.ts index 984ddd9651..cd0c42afe5 100644 --- a/packages/backend/src/plugins/auth.ts +++ b/packages/backend/src/plugins/auth.ts @@ -42,7 +42,11 @@ export default async function createPlugin( // It is important that each real user always gets resolved to // the same sign-in identity. The code below will not do that. // It is here for demo purposes only. - github: providers.github.create(), + github: providers.github.create({ + signIn: { + resolver: providers.github.resolvers.usernameMatchingUserEntityName(), + }, + }), gitlab: providers.gitlab.create({ signIn: { async resolver({ result: { fullProfile } }, ctx) { From 22713888851847a978fcaeda35bc24660d783a8e Mon Sep 17 00:00:00 2001 From: rthera7 Date: Fri, 13 May 2022 18:32:58 +0530 Subject: [PATCH 22/36] Removed unwanted fragment, centered the Chevron indicator Signed-off-by: rthera7 --- .../core-components/src/layout/Sidebar/Items.tsx | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/packages/core-components/src/layout/Sidebar/Items.tsx b/packages/core-components/src/layout/Sidebar/Items.tsx index d2e2c22689..c004f6904c 100644 --- a/packages/core-components/src/layout/Sidebar/Items.tsx +++ b/packages/core-components/src/layout/Sidebar/Items.tsx @@ -370,15 +370,13 @@ const SidebarItemBase = forwardRef((props, ref) => { const { isOpen } = useContext(SidebarContext); const divStyle = - !isOpen && children ? { marginLeft: '24px', marginBottom: '4px' } : {}; + !isOpen && children ? { display: 'flex', marginLeft: '24px' } : {}; const displayItemIcon = ( - <> -
- - {!isOpen && children ? : <>} -
- +
+ + {!isOpen && children ? : <>} +
); const itemIcon = ( From f0f1ca741af8a2888f66e309c3e16e4562934aa7 Mon Sep 17 00:00:00 2001 From: Renovate Bot Date: Fri, 13 May 2022 16:53:37 +0000 Subject: [PATCH 23/36] fix(deps): update dependency dompurify to v2.3.8 Signed-off-by: Renovate Bot --- yarn.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/yarn.lock b/yarn.lock index 6ec8648cac..e6b3e6f0f1 100644 --- a/yarn.lock +++ b/yarn.lock @@ -11108,9 +11108,9 @@ dompurify@=2.3.3: integrity sha512-dqnqRkPMAjOZE0FogZ+ceJNM2dZ3V/yNOuFB7+39qpO93hHhfRpHw3heYQC7DPK9FqbQTfBKUJhiSfz4MvXYwg== dompurify@^2.2.7, dompurify@^2.2.9, dompurify@^2.3.6: - version "2.3.6" - resolved "https://registry.npmjs.org/dompurify/-/dompurify-2.3.6.tgz#2e019d7d7617aacac07cbbe3d88ae3ad354cf875" - integrity sha512-OFP2u/3T1R5CEgWCEONuJ1a5+MFKnOYpkywpUSxv/dj1LeBT1erK+JwM7zK0ROy2BRhqVCf0LRw/kHqKuMkVGg== + version "2.3.8" + resolved "https://registry.npmjs.org/dompurify/-/dompurify-2.3.8.tgz#224fe9ae57d7ebd9a1ae1ac18c1c1ca3f532226f" + integrity sha512-eVhaWoVibIzqdGYjwsBWodIQIaXFSB+cKDf4cfxLMsK0xiud6SE+/WCVx/Xw/UwQsa4cS3T2eITcdtmTg2UKcw== domutils@^2.5.2, domutils@^2.6.0: version "2.8.0" @@ -13485,7 +13485,7 @@ graphql-type-json@^0.3.2: resolved "https://registry.npmjs.org/graphql-type-json/-/graphql-type-json-0.3.2.tgz#f53a851dbfe07bd1c8157d24150064baab41e115" integrity sha512-J+vjof74oMlCWXSvt0DOf2APEdZOCdubEvGDUAlqH//VBYcOYsGgRW7Xzorr44LvkjiuvecWc8fChxuZZbChtg== -graphql-ws@5.5.5, graphql-ws@^5.4.1: +graphql-ws@^5.4.1: version "5.5.5" resolved "https://registry.npmjs.org/graphql-ws/-/graphql-ws-5.5.5.tgz#f375486d3f196e2a2527b503644693ae3a8670a9" integrity sha512-hvyIS71vs4Tu/yUYHPvGXsTgo0t3arU820+lT5VjZS2go0ewp2LqyCgxEN56CzOG7Iys52eRhHBiD1gGRdiQtw== From b880c0e0920d2ce599d4e5fd8e69c1300df0eb79 Mon Sep 17 00:00:00 2001 From: Phil Kuang Date: Fri, 13 May 2022 13:39:48 -0400 Subject: [PATCH 24/36] fix(entityTypeFilter): generate unique available types Signed-off-by: Phil Kuang --- .changeset/sweet-icons-sneeze.md | 5 +++++ plugins/catalog-react/src/hooks/useEntityTypeFilter.tsx | 8 +++++++- 2 files changed, 12 insertions(+), 1 deletion(-) create mode 100644 .changeset/sweet-icons-sneeze.md diff --git a/.changeset/sweet-icons-sneeze.md b/.changeset/sweet-icons-sneeze.md new file mode 100644 index 0000000000..b12424c7a8 --- /dev/null +++ b/.changeset/sweet-icons-sneeze.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog-react': patch +--- + +Fix `EntityTypeFilter` so generating available types is case insensitive diff --git a/plugins/catalog-react/src/hooks/useEntityTypeFilter.tsx b/plugins/catalog-react/src/hooks/useEntityTypeFilter.tsx index 8e8c1b24d7..464531a4d9 100644 --- a/plugins/catalog-react/src/hooks/useEntityTypeFilter.tsx +++ b/plugins/catalog-react/src/hooks/useEntityTypeFilter.tsx @@ -96,7 +96,13 @@ export function useEntityTypeFilter(): { } // Sort by facet count descending, so the most common types appear on top - const newTypes = sortBy(facets, f => -f.count).map(f => f.value); + const newTypes = [ + ...new Set( + sortBy(facets, f => -f.count).map(f => + f.value.toLocaleLowerCase('en-US'), + ), + ), + ]; setAvailableTypes(newTypes); // Update type filter to only valid values when the list of available types has changed From e210c0cab8a8efbdef19957aca1a43c8ed21e7f6 Mon Sep 17 00:00:00 2001 From: Sergey Shevchenko Date: Tue, 10 May 2022 16:45:37 +0300 Subject: [PATCH 25/36] feat: Add ability to customize Read More button destination in MissingAnnotationEmptyState component Signed-off-by: Sergey Shevchenko --- .changeset/fresh-beans-call.md | 5 +++++ .../EmptyState/MissingAnnotationEmptyState.tsx | 12 ++++++------ 2 files changed, 11 insertions(+), 6 deletions(-) create mode 100644 .changeset/fresh-beans-call.md diff --git a/.changeset/fresh-beans-call.md b/.changeset/fresh-beans-call.md new file mode 100644 index 0000000000..7327f9a3c9 --- /dev/null +++ b/.changeset/fresh-beans-call.md @@ -0,0 +1,5 @@ +--- +'@backstage/core-components': patch +--- + +Add ability to customize `Read More` destination with `readMoreUrl` prop for `MissingAnnotationEmptyState` component. diff --git a/packages/core-components/src/components/EmptyState/MissingAnnotationEmptyState.tsx b/packages/core-components/src/components/EmptyState/MissingAnnotationEmptyState.tsx index 61131bad9b..8d8416a241 100644 --- a/packages/core-components/src/components/EmptyState/MissingAnnotationEmptyState.tsx +++ b/packages/core-components/src/components/EmptyState/MissingAnnotationEmptyState.tsx @@ -37,6 +37,7 @@ spec: type Props = { annotation: string; + readMoreUrl?: string; }; export type MissingAnnotationEmptyStateClassKey = 'code'; @@ -53,7 +54,10 @@ const useStyles = makeStyles( ); export function MissingAnnotationEmptyState(props: Props) { - const { annotation } = props; + const { annotation, readMoreUrl } = props; + const url = + readMoreUrl || + 'https://backstage.io/docs/features/software-catalog/well-known-annotations'; const classes = useStyles(); const description = ( <> @@ -81,11 +85,7 @@ export function MissingAnnotationEmptyState(props: Props) { customStyle={{ background: 'inherit', fontSize: '115%' }} /> - From 8767710f1fc5a78e4ac8e258b059408d5b02450c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Anders=20N=C3=A4sman?= Date: Fri, 29 Apr 2022 11:44:21 +0200 Subject: [PATCH 26/36] techdocs expandable nav addon MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Anders Näsman --- packages/app/src/App.tsx | 2 + .../api-report.md | 3 + .../package.json | 1 + .../ExpandableNavigation.tsx | 103 ++++++++++++++++++ .../src/ExpandableNavigation/index.ts | 17 +++ .../src/index.ts | 1 + .../src/plugin.ts | 15 +++ 7 files changed, 142 insertions(+) create mode 100644 plugins/techdocs-module-addons-contrib/src/ExpandableNavigation/ExpandableNavigation.tsx create mode 100644 plugins/techdocs-module-addons-contrib/src/ExpandableNavigation/index.ts diff --git a/packages/app/src/App.tsx b/packages/app/src/App.tsx index 089900fb77..35c61f2f16 100644 --- a/packages/app/src/App.tsx +++ b/packages/app/src/App.tsx @@ -71,6 +71,7 @@ import { } from '@backstage/plugin-techdocs'; import { TechDocsAddons } from '@backstage/plugin-techdocs-react'; import { + ExpandableNavigation, ReportIssue, TextSize, } from '@backstage/plugin-techdocs-module-addons-contrib'; @@ -185,6 +186,7 @@ const routes = ( > {techDocsPage} + diff --git a/plugins/techdocs-module-addons-contrib/api-report.md b/plugins/techdocs-module-addons-contrib/api-report.md index 19d2f70a2b..4a93356365 100644 --- a/plugins/techdocs-module-addons-contrib/api-report.md +++ b/plugins/techdocs-module-addons-contrib/api-report.md @@ -7,6 +7,9 @@ import { BackstagePlugin } from '@backstage/core-plugin-api'; +// @public +export const ExpandableNavigation: (props: unknown) => JSX.Element | null; + // @public export const ReportIssue: (props: ReportIssueProps) => JSX.Element | null; diff --git a/plugins/techdocs-module-addons-contrib/package.json b/plugins/techdocs-module-addons-contrib/package.json index 8a1801f0ba..074d12a505 100644 --- a/plugins/techdocs-module-addons-contrib/package.json +++ b/plugins/techdocs-module-addons-contrib/package.json @@ -43,6 +43,7 @@ "@material-ui/core": "^4.9.13", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.57", + "@react-hookz/web": "^13.0.0", "git-url-parse": "^11.6.0", "react-use": "^17.2.4" }, diff --git a/plugins/techdocs-module-addons-contrib/src/ExpandableNavigation/ExpandableNavigation.tsx b/plugins/techdocs-module-addons-contrib/src/ExpandableNavigation/ExpandableNavigation.tsx new file mode 100644 index 0000000000..486ddcd267 --- /dev/null +++ b/plugins/techdocs-module-addons-contrib/src/ExpandableNavigation/ExpandableNavigation.tsx @@ -0,0 +1,103 @@ +/* + * 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, { useEffect, useState } from 'react'; +import { useLocalStorageValue } from '@react-hookz/web'; +import { Button, withStyles } from '@material-ui/core'; +import ChevronRightIcon from '@material-ui/icons/ChevronRight'; +import ExpandMoreIcon from '@material-ui/icons/ExpandMore'; + +import { useShadowRoot } from '@backstage/plugin-techdocs-react'; + +const NESTED_LIST_TOGGLE = '.md-nav__item--nested .md-toggle'; + +const EXPANDABLE_NAVIGATION_LOCAL_STORAGE = + '@backstage/techdocs-addons/nav-expanded'; + +const StyledButton = withStyles({ + root: { + position: 'absolute', + left: '220px', + top: '19px', + padding: 0, + minWidth: 0, + }, +})(Button); + +const CollapsedIcon = withStyles({ + root: { + height: '20px', + width: '20px', + }, +})(ChevronRightIcon); + +const ExpandedIcon = withStyles({ + root: { + height: '20px', + width: '20px', + }, +})(ExpandMoreIcon); + +type expandableNavigationLocalStorage = { + navExpanded: boolean; +}; + +export const ExpandableNavigationAddon = () => { + const shadowRoot = useShadowRoot(); + const defaultValue = { navExpanded: false }; + const [expanded, setExpanded] = + useLocalStorageValue( + EXPANDABLE_NAVIGATION_LOCAL_STORAGE, + defaultValue, + ); + const [hasNavSubLevels, setHasNavSubLevels] = useState(false); + + useEffect(() => { + const checkboxToggles = + shadowRoot?.querySelectorAll(NESTED_LIST_TOGGLE); + if (!checkboxToggles || (checkboxToggles && checkboxToggles.length === 0)) + return; + setHasNavSubLevels(true); + checkboxToggles.forEach(item => { + if ( + (expanded?.navExpanded && !item.checked) || + (!expanded?.navExpanded && item.checked) + ) { + item.click(); + } + }); + }, [shadowRoot, expanded]); + + const handleState = () => { + setExpanded(prevState => ({ + navExpanded: !prevState?.navExpanded, + })); + }; + + return ( + <> + {hasNavSubLevels ? ( + + {expanded?.navExpanded ? : } + + ) : null} + + ); +}; diff --git a/plugins/techdocs-module-addons-contrib/src/ExpandableNavigation/index.ts b/plugins/techdocs-module-addons-contrib/src/ExpandableNavigation/index.ts new file mode 100644 index 0000000000..8f1c131d08 --- /dev/null +++ b/plugins/techdocs-module-addons-contrib/src/ExpandableNavigation/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 './ExpandableNavigation'; diff --git a/plugins/techdocs-module-addons-contrib/src/index.ts b/plugins/techdocs-module-addons-contrib/src/index.ts index e2e57b15d1..528afe5c0d 100644 --- a/plugins/techdocs-module-addons-contrib/src/index.ts +++ b/plugins/techdocs-module-addons-contrib/src/index.ts @@ -22,6 +22,7 @@ export { techdocsModuleAddonsContribPlugin, + ExpandableNavigation, ReportIssue, TextSize, } from './plugin'; diff --git a/plugins/techdocs-module-addons-contrib/src/plugin.ts b/plugins/techdocs-module-addons-contrib/src/plugin.ts index 0d7743da9e..dbef119da8 100644 --- a/plugins/techdocs-module-addons-contrib/src/plugin.ts +++ b/plugins/techdocs-module-addons-contrib/src/plugin.ts @@ -19,6 +19,7 @@ import { createTechDocsAddonExtension, TechDocsAddonLocations, } from '@backstage/plugin-techdocs-react'; +import { ExpandableNavigationAddon } from './ExpandableNavigation'; import { ReportIssueAddon, ReportIssueProps } from './ReportIssue'; import { TextSizeAddon } from './TextSize'; @@ -32,6 +33,20 @@ export const techdocsModuleAddonsContribPlugin = createPlugin({ id: 'techdocsModuleAddonsContrib', }); +/** + * TechDocs addon that lets you expand/collapse the TechDocs main navigation. + * + * @public + */ + +export const ExpandableNavigation = techdocsModuleAddonsContribPlugin.provide( + createTechDocsAddonExtension({ + name: 'ExpandableNavigation', + location: TechDocsAddonLocations.PrimarySidebar, + component: ExpandableNavigationAddon, + }), +); + /** * TechDocs addon that lets you select text and open GitHub/Gitlab issues * From 206c7ccca0583b6301cdbd183bcb771a6163a4f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Anders=20N=C3=A4sman?= Date: Tue, 3 May 2022 23:16:44 +0200 Subject: [PATCH 27/36] apply review feedback MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Anders Näsman --- .../api-report.md | 2 +- .../ExpandableNavigation.tsx | 61 +++++++++++++------ .../src/plugin.ts | 34 ++++++++++- plugins/techdocs-react/src/addons.tsx | 8 +++ 4 files changed, 84 insertions(+), 21 deletions(-) diff --git a/plugins/techdocs-module-addons-contrib/api-report.md b/plugins/techdocs-module-addons-contrib/api-report.md index 4a93356365..b40d8fe76c 100644 --- a/plugins/techdocs-module-addons-contrib/api-report.md +++ b/plugins/techdocs-module-addons-contrib/api-report.md @@ -8,7 +8,7 @@ import { BackstagePlugin } from '@backstage/core-plugin-api'; // @public -export const ExpandableNavigation: (props: unknown) => JSX.Element | null; +export const ExpandableNavigation: () => JSX.Element | null; // @public export const ReportIssue: (props: ReportIssueProps) => JSX.Element | null; diff --git a/plugins/techdocs-module-addons-contrib/src/ExpandableNavigation/ExpandableNavigation.tsx b/plugins/techdocs-module-addons-contrib/src/ExpandableNavigation/ExpandableNavigation.tsx index 486ddcd267..5ef76187e3 100644 --- a/plugins/techdocs-module-addons-contrib/src/ExpandableNavigation/ExpandableNavigation.tsx +++ b/plugins/techdocs-module-addons-contrib/src/ExpandableNavigation/ExpandableNavigation.tsx @@ -14,13 +14,13 @@ * limitations under the License. */ -import React, { useEffect, useState } from 'react'; +import React, { useEffect, useCallback, useState } from 'react'; import { useLocalStorageValue } from '@react-hookz/web'; import { Button, withStyles } from '@material-ui/core'; import ChevronRightIcon from '@material-ui/icons/ChevronRight'; import ExpandMoreIcon from '@material-ui/icons/ExpandMore'; -import { useShadowRoot } from '@backstage/plugin-techdocs-react'; +import { useShadowRootElements } from '@backstage/plugin-techdocs-react'; const NESTED_LIST_TOGGLE = '.md-nav__item--nested .md-toggle'; @@ -52,12 +52,15 @@ const ExpandedIcon = withStyles({ })(ExpandMoreIcon); type expandableNavigationLocalStorage = { - navExpanded: boolean; + expandAllNestedNavs: boolean; }; +/** + * Show expand/collapse navigation button next to site name in main + * navigation menu if documentation site has nested navigation. + */ export const ExpandableNavigationAddon = () => { - const shadowRoot = useShadowRoot(); - const defaultValue = { navExpanded: false }; + const defaultValue = { expandAllNestedNavs: false }; const [expanded, setExpanded] = useLocalStorageValue( EXPANDABLE_NAVIGATION_LOCAL_STORAGE, @@ -65,25 +68,43 @@ export const ExpandableNavigationAddon = () => { ); const [hasNavSubLevels, setHasNavSubLevels] = useState(false); + const [...checkboxToggles] = useShadowRootElements([ + NESTED_LIST_TOGGLE, + ]); + + const shouldToggle = useCallback( + (item: HTMLInputElement) => { + const isExpanded = item.checked; + const shouldExpand = expanded?.expandAllNestedNavs; + + // Is collapsed but should expand + if (shouldExpand && !isExpanded) { + return true; + } + + // Is expanded but should collapse + if (!shouldExpand && isExpanded) { + return true; + } + + return false; + }, + [expanded], + ); + useEffect(() => { - const checkboxToggles = - shadowRoot?.querySelectorAll(NESTED_LIST_TOGGLE); - if (!checkboxToggles || (checkboxToggles && checkboxToggles.length === 0)) - return; + // There is no nested navs + if (!checkboxToggles?.length) return; + setHasNavSubLevels(true); checkboxToggles.forEach(item => { - if ( - (expanded?.navExpanded && !item.checked) || - (!expanded?.navExpanded && item.checked) - ) { - item.click(); - } + if (shouldToggle(item)) item.click(); }); - }, [shadowRoot, expanded]); + }, [expanded, shouldToggle, checkboxToggles]); const handleState = () => { setExpanded(prevState => ({ - navExpanded: !prevState?.navExpanded, + expandAllNestedNavs: !prevState?.expandAllNestedNavs, })); }; @@ -93,9 +114,11 @@ export const ExpandableNavigationAddon = () => { - {expanded?.navExpanded ? : } + {expanded?.expandAllNestedNavs ? : } ) : null} diff --git a/plugins/techdocs-module-addons-contrib/src/plugin.ts b/plugins/techdocs-module-addons-contrib/src/plugin.ts index dbef119da8..06fa7db07d 100644 --- a/plugins/techdocs-module-addons-contrib/src/plugin.ts +++ b/plugins/techdocs-module-addons-contrib/src/plugin.ts @@ -34,7 +34,39 @@ export const techdocsModuleAddonsContribPlugin = createPlugin({ }); /** - * TechDocs addon that lets you expand/collapse the TechDocs main navigation. + * TechDocs addon that lets you expand/collapse the TechDocs main navigation + * and keep the preferred state in local storage. The addon will render as + * a button next to the site name if the documentation has nested navigation. + * + * @example + * Here's a simple example: + * ``` + * import { + * DefaultTechDocsHome, + * TechDocsIndexPage, + * TechDocsReaderPage, + * } from '@backstage/plugin-techdocs'; + * import { TechDocsAddons } from '@backstage/plugin-techdocs-react/alpha'; + * import { ExpandableNavigation } from '@backstage/plugin-techdocs-module-addons-contrib'; + * + * + * const AppRoutes = () => { + * + * // other plugin routes + * }> + * + * + * } + * > + * + * + * + * + * ; + * }; + * ``` * * @public */ diff --git a/plugins/techdocs-react/src/addons.tsx b/plugins/techdocs-react/src/addons.tsx index 49aa5b1bcc..7629c94858 100644 --- a/plugins/techdocs-react/src/addons.tsx +++ b/plugins/techdocs-react/src/addons.tsx @@ -51,6 +51,14 @@ const getDataKeyByName = (name: string) => { * Create a TechDocs addon. * @public */ +export function createTechDocsAddonExtension( + options: TechDocsAddonOptions, +): Extension<() => JSX.Element | null>; + +export function createTechDocsAddonExtension( + options: TechDocsAddonOptions, +): Extension<(props: TComponentProps) => JSX.Element | null>; + export function createTechDocsAddonExtension( options: TechDocsAddonOptions, ): Extension<(props: TComponentProps) => JSX.Element | null> { From c555e294e0fbd300f91d8e84cceeb53d858598a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Anders=20N=C3=A4sman?= Date: Tue, 3 May 2022 23:30:19 +0200 Subject: [PATCH 28/36] add test MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Anders Näsman --- .../ExpandableNavigation.test.tsx | 146 ++++++++++++++++++ 1 file changed, 146 insertions(+) create mode 100644 plugins/techdocs-module-addons-contrib/src/ExpandableNavigation/ExpandableNavigation.test.tsx diff --git a/plugins/techdocs-module-addons-contrib/src/ExpandableNavigation/ExpandableNavigation.test.tsx b/plugins/techdocs-module-addons-contrib/src/ExpandableNavigation/ExpandableNavigation.test.tsx new file mode 100644 index 0000000000..f2fead4fe6 --- /dev/null +++ b/plugins/techdocs-module-addons-contrib/src/ExpandableNavigation/ExpandableNavigation.test.tsx @@ -0,0 +1,146 @@ +/* + * 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 { TechDocsAddonTester } from '@backstage/plugin-techdocs-addons-test-utils'; + +import React from 'react'; +import { fireEvent, waitFor } from '@testing-library/react'; + +import { ExpandableNavigation } from '..'; + +const mockNavWithSublevels = ( +
+ +
+); + +const mockNavWithoutSublevels = ( + +); + +describe('ExpandableNavigation', () => { + it('renders without exploding', async () => { + const { getByRole } = await TechDocsAddonTester.buildAddonsInTechDocs([ + , + ]) + .withDom(mockNavWithSublevels) + .renderWithEffects(); + + expect(getByRole('button', { name: 'expand-nav' })).toBeInTheDocument(); + }); + + it('expands and collapses navigation', async () => { + const { getByRole, shadowRoot } = + await TechDocsAddonTester.buildAddonsInTechDocs([ + , + ]) + .withDom(mockNavWithSublevels) + .renderWithEffects(); + + const toggles = + shadowRoot!.querySelectorAll('.md-toggle'); + + expect(toggles).toHaveLength(2); + toggles.forEach(item => { + expect(item).not.toBeChecked(); + }); + + const expandButton = getByRole('button', { name: 'expand-nav' }); + + fireEvent.click(expandButton); + + await waitFor(() => { + expect(getByRole('button', { name: 'collapse-nav' })).toBeInTheDocument(); + toggles.forEach(item => { + expect(item).toBeChecked(); + }); + }); + + const collapseButton = getByRole('button', { name: 'collapse-nav' }); + + fireEvent.click(collapseButton); + + await waitFor(() => { + toggles.forEach(item => { + expect(item).not.toBeChecked(); + }); + }); + }); + + it('does not render when navigation has no sublevels', async () => { + const { queryByRole } = await TechDocsAddonTester.buildAddonsInTechDocs([ + , + ]) + .withDom(mockNavWithoutSublevels) + .renderWithEffects(); + + expect( + queryByRole('button', { name: 'expand-nav' }), + ).not.toBeInTheDocument(); + }); +}); From 84717cf5eac46860df8972fd3ae6f19aca5f765f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Anders=20N=C3=A4sman?= Date: Tue, 3 May 2022 23:49:42 +0200 Subject: [PATCH 29/36] api report fix MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Anders Näsman --- plugins/techdocs-react/api-report.md | 5 +++++ plugins/techdocs-react/src/addons.tsx | 10 +++++++++- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/plugins/techdocs-react/api-report.md b/plugins/techdocs-react/api-report.md index e96cbebd1c..b3ee9168a6 100644 --- a/plugins/techdocs-react/api-report.md +++ b/plugins/techdocs-react/api-report.md @@ -14,6 +14,11 @@ import { default as React_2 } from 'react'; import { ReactNode } from 'react'; import { SetStateAction } from 'react'; +// @public +export function createTechDocsAddonExtension( + options: TechDocsAddonOptions, +): Extension<() => JSX.Element | null>; + // @public export function createTechDocsAddonExtension( options: TechDocsAddonOptions, diff --git a/plugins/techdocs-react/src/addons.tsx b/plugins/techdocs-react/src/addons.tsx index 7629c94858..ce5b3eb5cd 100644 --- a/plugins/techdocs-react/src/addons.tsx +++ b/plugins/techdocs-react/src/addons.tsx @@ -48,17 +48,25 @@ const getDataKeyByName = (name: string) => { }; /** - * Create a TechDocs addon. + * Create a TechDocs addon overload signature without props. * @public */ export function createTechDocsAddonExtension( options: TechDocsAddonOptions, ): Extension<() => JSX.Element | null>; +/** + * Create a TechDocs addon overload signature with props. + * @public + */ export function createTechDocsAddonExtension( options: TechDocsAddonOptions, ): Extension<(props: TComponentProps) => JSX.Element | null>; +/** + * Create a TechDocs addon implementation. + * @public + */ export function createTechDocsAddonExtension( options: TechDocsAddonOptions, ): Extension<(props: TComponentProps) => JSX.Element | null> { From 1e186be521f7080153bc64232783fed7241d61db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Anders=20N=C3=A4sman?= Date: Wed, 4 May 2022 12:07:48 +0200 Subject: [PATCH 30/36] add addon to available addons table MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Anders Näsman --- docs/features/techdocs/addons.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/features/techdocs/addons.md b/docs/features/techdocs/addons.md index e8af56d3fc..b4fd517e0e 100644 --- a/docs/features/techdocs/addons.md +++ b/docs/features/techdocs/addons.md @@ -113,6 +113,7 @@ discover available Addons, we've compiled a list of them here: | Addon | Package/Plugin | Description | | ---------------------------------------------------------------------------------------------------------- | -------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| [``](https://backstage.io/docs/reference/plugin-techdocs-module-addons-contrib.expandablenavigation) | `@backstage/plugin-techdocs-module-addons-contrib` | Allows TechDocs users to expand or collapse the entire TechDocs main navigation, and keeps the user's preferred state between documentation sites. | | [``](https://backstage.io/docs/reference/plugin-techdocs-module-addons-contrib.reportissue) | `@backstage/plugin-techdocs-module-addons-contrib` | Allows TechDocs users to select a portion of text on a TechDocs page and open an issue against the repository that contains the documentation, populating the issue description with the selected text according to a configurable template. | | [``](https://backstage.io/docs/reference/plugin-techdocs-module-addons-contrib.textsize) | `@backstage/plugin-techdocs-module-addons-contrib` | This TechDocs addon allows users to customize text size on documentation pages, they can select how much they want to increase or decrease the font size via slider or buttons. The default value for font size is 100% and this setting is kept in the browser's local storage whenever it is changed. | From c25e880e36f9383000008fba34729af876ed67bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Anders=20N=C3=A4sman?= Date: Wed, 4 May 2022 13:39:32 +0200 Subject: [PATCH 31/36] add changesets MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Anders Näsman --- .changeset/techdocs-khaki-cheetahs-clap.md | 5 +++++ .changeset/techdocs-weak-boats-work.md | 5 +++++ 2 files changed, 10 insertions(+) create mode 100644 .changeset/techdocs-khaki-cheetahs-clap.md create mode 100644 .changeset/techdocs-weak-boats-work.md diff --git a/.changeset/techdocs-khaki-cheetahs-clap.md b/.changeset/techdocs-khaki-cheetahs-clap.md new file mode 100644 index 0000000000..5aba436534 --- /dev/null +++ b/.changeset/techdocs-khaki-cheetahs-clap.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-techdocs-react': patch +--- + +Added overload signatures for `createTechDocsAddonExtension` to handle TechDocs addons without props. diff --git a/.changeset/techdocs-weak-boats-work.md b/.changeset/techdocs-weak-boats-work.md new file mode 100644 index 0000000000..ec4f089592 --- /dev/null +++ b/.changeset/techdocs-weak-boats-work.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-techdocs-module-addons-contrib': patch +--- + +Introducing the Expandable Navigation addon, which lets you expand and collapse the TechDocs main navigation and store your preference in local storage. From dd1844eb213c66b3c91d61cd50d34cea9a2e193b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Anders=20N=C3=A4sman?= Date: Fri, 13 May 2022 11:28:48 +0200 Subject: [PATCH 32/36] update api report MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Anders Näsman --- plugins/techdocs-module-addons-contrib/api-report.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/techdocs-module-addons-contrib/api-report.md b/plugins/techdocs-module-addons-contrib/api-report.md index b40d8fe76c..efe88e2d5c 100644 --- a/plugins/techdocs-module-addons-contrib/api-report.md +++ b/plugins/techdocs-module-addons-contrib/api-report.md @@ -36,5 +36,5 @@ export type ReportIssueTemplateBuilder = ({ export const techdocsModuleAddonsContribPlugin: BackstagePlugin<{}, {}>; // @public -export const TextSize: (props: unknown) => JSX.Element | null; +export const TextSize: () => JSX.Element | null; ``` From 1904b9c9ccf341865dd979fcc358bb9bad729a9e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Anders=20N=C3=A4sman?= Date: Fri, 13 May 2022 11:39:35 +0200 Subject: [PATCH 33/36] prettier MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Anders Näsman --- docs/features/techdocs/addons.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/features/techdocs/addons.md b/docs/features/techdocs/addons.md index b4fd517e0e..5305e3bc68 100644 --- a/docs/features/techdocs/addons.md +++ b/docs/features/techdocs/addons.md @@ -111,11 +111,11 @@ page header, TechDocs Addons whose location is `Header` will not be rendered. Addons can, in principle, be provided by any plugin! To make it easier to discover available Addons, we've compiled a list of them here: -| Addon | Package/Plugin | Description | -| ---------------------------------------------------------------------------------------------------------- | -------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| [``](https://backstage.io/docs/reference/plugin-techdocs-module-addons-contrib.expandablenavigation) | `@backstage/plugin-techdocs-module-addons-contrib` | Allows TechDocs users to expand or collapse the entire TechDocs main navigation, and keeps the user's preferred state between documentation sites. | -| [``](https://backstage.io/docs/reference/plugin-techdocs-module-addons-contrib.reportissue) | `@backstage/plugin-techdocs-module-addons-contrib` | Allows TechDocs users to select a portion of text on a TechDocs page and open an issue against the repository that contains the documentation, populating the issue description with the selected text according to a configurable template. | -| [``](https://backstage.io/docs/reference/plugin-techdocs-module-addons-contrib.textsize) | `@backstage/plugin-techdocs-module-addons-contrib` | This TechDocs addon allows users to customize text size on documentation pages, they can select how much they want to increase or decrease the font size via slider or buttons. The default value for font size is 100% and this setting is kept in the browser's local storage whenever it is changed. | +| Addon | Package/Plugin | Description | +| ---------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| [``](https://backstage.io/docs/reference/plugin-techdocs-module-addons-contrib.expandablenavigation) | `@backstage/plugin-techdocs-module-addons-contrib` | Allows TechDocs users to expand or collapse the entire TechDocs main navigation, and keeps the user's preferred state between documentation sites. | +| [``](https://backstage.io/docs/reference/plugin-techdocs-module-addons-contrib.reportissue) | `@backstage/plugin-techdocs-module-addons-contrib` | Allows TechDocs users to select a portion of text on a TechDocs page and open an issue against the repository that contains the documentation, populating the issue description with the selected text according to a configurable template. | +| [``](https://backstage.io/docs/reference/plugin-techdocs-module-addons-contrib.textsize) | `@backstage/plugin-techdocs-module-addons-contrib` | This TechDocs addon allows users to customize text size on documentation pages, they can select how much they want to increase or decrease the font size via slider or buttons. The default value for font size is 100% and this setting is kept in the browser's local storage whenever it is changed. | Got an Addon to contribute? Feel free to add a row above! From c14e78a36772830b9e2399177fb54562c00599a1 Mon Sep 17 00:00:00 2001 From: Eric Peterson Date: Mon, 16 May 2022 09:25:33 +0200 Subject: [PATCH 34/36] Rename changeset Signed-off-by: Eric Peterson --- ...stupid-radios-approve.md => techdocs-stupid-radios-approve.md} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename .changeset/{stupid-radios-approve.md => techdocs-stupid-radios-approve.md} (100%) diff --git a/.changeset/stupid-radios-approve.md b/.changeset/techdocs-stupid-radios-approve.md similarity index 100% rename from .changeset/stupid-radios-approve.md rename to .changeset/techdocs-stupid-radios-approve.md From 005ee625ae4f1f3887ec2e0143091c3bf1dce44f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Anders=20N=C3=A4sman?= Date: Mon, 16 May 2022 14:13:40 +0200 Subject: [PATCH 35/36] use module name in imports MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Anders Näsman --- .../src/ExpandableNavigation/ExpandableNavigation.test.tsx | 2 +- .../src/ReportIssue/ReportIssue.test.tsx | 2 +- .../src/TextSize/TextSize.test.tsx | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/plugins/techdocs-module-addons-contrib/src/ExpandableNavigation/ExpandableNavigation.test.tsx b/plugins/techdocs-module-addons-contrib/src/ExpandableNavigation/ExpandableNavigation.test.tsx index f2fead4fe6..3efc923145 100644 --- a/plugins/techdocs-module-addons-contrib/src/ExpandableNavigation/ExpandableNavigation.test.tsx +++ b/plugins/techdocs-module-addons-contrib/src/ExpandableNavigation/ExpandableNavigation.test.tsx @@ -19,7 +19,7 @@ import { TechDocsAddonTester } from '@backstage/plugin-techdocs-addons-test-util import React from 'react'; import { fireEvent, waitFor } from '@testing-library/react'; -import { ExpandableNavigation } from '..'; +import { ExpandableNavigation } from '../plugin'; const mockNavWithSublevels = (
diff --git a/plugins/techdocs-module-addons-contrib/src/ReportIssue/ReportIssue.test.tsx b/plugins/techdocs-module-addons-contrib/src/ReportIssue/ReportIssue.test.tsx index 68bde5c762..459fa1b65e 100644 --- a/plugins/techdocs-module-addons-contrib/src/ReportIssue/ReportIssue.test.tsx +++ b/plugins/techdocs-module-addons-contrib/src/ReportIssue/ReportIssue.test.tsx @@ -20,7 +20,7 @@ import React from 'react'; import { fireEvent, waitFor } from '@testing-library/react'; import { scmIntegrationsApiRef } from '@backstage/integration-react'; -import { ReportIssue } from '..'; +import { ReportIssue } from '../plugin'; const byUrl = jest.fn(); diff --git a/plugins/techdocs-module-addons-contrib/src/TextSize/TextSize.test.tsx b/plugins/techdocs-module-addons-contrib/src/TextSize/TextSize.test.tsx index 282d54a0b6..6b4a055c2a 100644 --- a/plugins/techdocs-module-addons-contrib/src/TextSize/TextSize.test.tsx +++ b/plugins/techdocs-module-addons-contrib/src/TextSize/TextSize.test.tsx @@ -20,7 +20,7 @@ import React from 'react'; import { fireEvent, waitFor } from '@testing-library/react'; -import { TextSize } from '..'; +import { TextSize } from '../plugin'; describe('TextSize', () => { it('renders without exploding', async () => { From aabc5e08d17053e0129481f2c201599e3d22c9dd Mon Sep 17 00:00:00 2001 From: Renovate Bot Date: Mon, 16 May 2022 13:22:55 +0000 Subject: [PATCH 36/36] chore(deps): update dependency @types/node to v16.11.35 Signed-off-by: Renovate Bot --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index e6b3e6f0f1..2d54d645f1 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6284,9 +6284,9 @@ integrity sha512-qjd88DrCxupx/kJD5yQgZdcYKZKSIGBVDIBE1/LTGcNm3d2Np/jxojkdePDdfnBHJc5W7vSMpbJ1aB7p/Py69A== "@types/node@^16.0.0", "@types/node@^16.11.26", "@types/node@^16.9.2": - version "16.11.34" - resolved "https://registry.npmjs.org/@types/node/-/node-16.11.34.tgz#520224e4be4448c279ecad09639ab460cc441a50" - integrity sha512-UrWGDyLAlQ2Z8bNOGWTsqbP9ZcBeTYBVuTRNxXTztBy5KhWUFI3BaeDWoCP/CzV/EVGgO1NTYzv9ZytBI9GAEw== + version "16.11.35" + resolved "https://registry.npmjs.org/@types/node/-/node-16.11.35.tgz#6642bdce5b5cee23314b91a7c069981c6bd68791" + integrity sha512-QXu45LyepgnhUfnIAj/FyT4uM87ug5KpIrgXfQtUPNAlx8w5hmd8z8emqCLNvG11QkpRSCG9Qg2buMxvqfjfsQ== "@types/normalize-package-data@^2.4.0": version "2.4.1"