From d996458580de4b63f9c07ebacac98626efab4125 Mon Sep 17 00:00:00 2001 From: sjeyaraman Date: Sun, 5 Jun 2022 12:40:43 -0700 Subject: [PATCH 01/12] customize unregister entity menuitem Signed-off-by: sjeyaraman --- .../app/src/components/catalog/EntityPage.tsx | 15 ++++++- .../EntityContextMenu.test.tsx | 25 ++++++++++- .../EntityContextMenu/EntityContextMenu.tsx | 43 +++++++++++++------ .../components/EntityLayout/EntityLayout.tsx | 4 +- 4 files changed, 70 insertions(+), 17 deletions(-) diff --git a/packages/app/src/components/catalog/EntityPage.tsx b/packages/app/src/components/catalog/EntityPage.tsx index 799fe3e4d9..ab8c02c168 100644 --- a/packages/app/src/components/catalog/EntityPage.tsx +++ b/packages/app/src/components/catalog/EntityPage.tsx @@ -161,9 +161,22 @@ const EntityLayoutWrapper = (props: { children?: ReactNode }) => { ]; }, []); + type VisibleType = 'visible' | 'hidden' | 'disabled'; + + type contextMenuOptions = { + disableUnregister: boolean | VisibleType; + }; + + const options: contextMenuOptions = { + disableUnregister: false, + }; + return ( <> - + {props.children} { it('should call onUnregisterEntity on button click', async () => { const mockCallback = jest.fn(); - await render( { expect(mockCallback).toBeCalled(); }); + it('check Unregister entity button is disabled', async () => { + const mockCallback = jest.fn(); + + const { getByText } = await render( + {}} + />, + ); + + const button = await screen.findByTestId('menu-button'); + expect(button).toBeInTheDocument(); + fireEvent.click(button); + + const unregister = await screen.getByText('Unregister entity'); + expect(unregister).toBeInTheDocument(); + + const unregisterSpanItem = getByText(/Unregister entity/); + const unregisterMenuListItem = + unregisterSpanItem?.parentElement?.parentElement; + expect(unregisterMenuListItem).toHaveAttribute('aria-disabled'); + }); + it('should call onInspectEntity on button click', async () => { const mockCallback = jest.fn(); diff --git a/plugins/catalog/src/components/EntityContextMenu/EntityContextMenu.tsx b/plugins/catalog/src/components/EntityContextMenu/EntityContextMenu.tsx index 5664186ab1..955c42b95a 100644 --- a/plugins/catalog/src/components/EntityContextMenu/EntityContextMenu.tsx +++ b/plugins/catalog/src/components/EntityContextMenu/EntityContextMenu.tsx @@ -47,9 +47,11 @@ interface ExtraContextMenuItem { onClick: () => void; } +type VisibleType = 'visible' | 'hidden' | 'disabled'; + // unstable context menu option, eg: disable the unregister entity menu interface contextMenuOptions { - disableUnregister: boolean; + disableUnregister: boolean | VisibleType; } interface EntityContextMenuProps { @@ -98,11 +100,35 @@ export function EntityContextMenu(props: EntityContextMenuProps) { , ]; + const isBoolean = + typeof UNSTABLE_contextMenuOptions?.disableUnregister === 'boolean'; + const disableUnregister = (!unregisterPermission.allowed || - UNSTABLE_contextMenuOptions?.disableUnregister) ?? + (isBoolean + ? UNSTABLE_contextMenuOptions?.disableUnregister + : UNSTABLE_contextMenuOptions?.disableUnregister === 'disabled')) ?? false; + let unregisterButton = <>; + + if (UNSTABLE_contextMenuOptions?.disableUnregister !== 'hidden') { + unregisterButton = ( + { + onClose(); + onUnregisterEntity(); + }} + disabled={disableUnregister} + > + + + + + + ); + } + return ( <> {extraItems} - { - onClose(); - onUnregisterEntity(); - }} - disabled={disableUnregister} - > - - - - - + {unregisterButton} { onClose(); diff --git a/plugins/catalog/src/components/EntityLayout/EntityLayout.tsx b/plugins/catalog/src/components/EntityLayout/EntityLayout.tsx index 693137fe21..4cbb72db5c 100644 --- a/plugins/catalog/src/components/EntityLayout/EntityLayout.tsx +++ b/plugins/catalog/src/components/EntityLayout/EntityLayout.tsx @@ -142,9 +142,11 @@ interface ExtraContextMenuItem { onClick: () => void; } +type VisibleType = 'visible' | 'hidden' | 'disabled'; + // unstable context menu option, eg: disable the unregister entity menu interface contextMenuOptions { - disableUnregister: boolean; + disableUnregister: boolean | VisibleType; } /** @public */ From 9083fae0885053988fed87d64c124f1a6e70ba47 Mon Sep 17 00:00:00 2001 From: sjeyaraman Date: Sun, 5 Jun 2022 17:10:23 -0700 Subject: [PATCH 02/12] add-change-set Signed-off-by: sjeyaraman --- .changeset/cold-apples-film.md | 9 +++++++++ packages/app/src/components/catalog/EntityPage.tsx | 2 +- 2 files changed, 10 insertions(+), 1 deletion(-) create mode 100644 .changeset/cold-apples-film.md diff --git a/.changeset/cold-apples-film.md b/.changeset/cold-apples-film.md new file mode 100644 index 0000000000..d8c7ec283d --- /dev/null +++ b/.changeset/cold-apples-film.md @@ -0,0 +1,9 @@ +--- +'example-app': patch +'@backstage/plugin-catalog': patch +--- + +Adding ability to customize the "unregister entity" menu item in the entity context menu on the entity page with options 'visible','hidden','disabled'. +With this three new options, one can hide the "unregister entity" menu item from the list, disable or keep it enabled. + +The boolean input for "unregister entity" will be deprecated later in favour of the above three options. diff --git a/packages/app/src/components/catalog/EntityPage.tsx b/packages/app/src/components/catalog/EntityPage.tsx index ab8c02c168..fc17ccf909 100644 --- a/packages/app/src/components/catalog/EntityPage.tsx +++ b/packages/app/src/components/catalog/EntityPage.tsx @@ -168,7 +168,7 @@ const EntityLayoutWrapper = (props: { children?: ReactNode }) => { }; const options: contextMenuOptions = { - disableUnregister: false, + disableUnregister: 'visible', }; return ( From 888731df92e6264a8f3325b8a4550bd2f76c7d7a Mon Sep 17 00:00:00 2001 From: sjeyaraman Date: Sun, 5 Jun 2022 12:40:43 -0700 Subject: [PATCH 03/12] customize unregister entity menuitem Signed-off-by: sjeyaraman --- .../app/src/components/catalog/EntityPage.tsx | 15 ++++++- .../EntityContextMenu.test.tsx | 25 ++++++++++- .../EntityContextMenu/EntityContextMenu.tsx | 43 +++++++++++++------ .../components/EntityLayout/EntityLayout.tsx | 4 +- 4 files changed, 70 insertions(+), 17 deletions(-) diff --git a/packages/app/src/components/catalog/EntityPage.tsx b/packages/app/src/components/catalog/EntityPage.tsx index 1958aabd2e..4318e68e74 100644 --- a/packages/app/src/components/catalog/EntityPage.tsx +++ b/packages/app/src/components/catalog/EntityPage.tsx @@ -165,9 +165,22 @@ const EntityLayoutWrapper = (props: { children?: ReactNode }) => { ]; }, []); + type VisibleType = 'visible' | 'hidden' | 'disabled'; + + type contextMenuOptions = { + disableUnregister: boolean | VisibleType; + }; + + const options: contextMenuOptions = { + disableUnregister: false, + }; + return ( <> - + {props.children} { it('should call onUnregisterEntity on button click', async () => { const mockCallback = jest.fn(); - await render( { expect(mockCallback).toBeCalled(); }); + it('check Unregister entity button is disabled', async () => { + const mockCallback = jest.fn(); + + const { getByText } = await render( + {}} + />, + ); + + const button = await screen.findByTestId('menu-button'); + expect(button).toBeInTheDocument(); + fireEvent.click(button); + + const unregister = await screen.getByText('Unregister entity'); + expect(unregister).toBeInTheDocument(); + + const unregisterSpanItem = getByText(/Unregister entity/); + const unregisterMenuListItem = + unregisterSpanItem?.parentElement?.parentElement; + expect(unregisterMenuListItem).toHaveAttribute('aria-disabled'); + }); + it('should call onInspectEntity on button click', async () => { const mockCallback = jest.fn(); diff --git a/plugins/catalog/src/components/EntityContextMenu/EntityContextMenu.tsx b/plugins/catalog/src/components/EntityContextMenu/EntityContextMenu.tsx index db50eeab84..0a5e2e1bfe 100644 --- a/plugins/catalog/src/components/EntityContextMenu/EntityContextMenu.tsx +++ b/plugins/catalog/src/components/EntityContextMenu/EntityContextMenu.tsx @@ -55,9 +55,11 @@ interface ExtraContextMenuItem { onClick: () => void; } +type VisibleType = 'visible' | 'hidden' | 'disabled'; + // unstable context menu option, eg: disable the unregister entity menu interface contextMenuOptions { - disableUnregister: boolean; + disableUnregister: boolean | VisibleType; } interface EntityContextMenuProps { @@ -106,11 +108,35 @@ export function EntityContextMenu(props: EntityContextMenuProps) { , ]; + const isBoolean = + typeof UNSTABLE_contextMenuOptions?.disableUnregister === 'boolean'; + const disableUnregister = (!unregisterPermission.allowed || - UNSTABLE_contextMenuOptions?.disableUnregister) ?? + (isBoolean + ? UNSTABLE_contextMenuOptions?.disableUnregister + : UNSTABLE_contextMenuOptions?.disableUnregister === 'disabled')) ?? false; + let unregisterButton = <>; + + if (UNSTABLE_contextMenuOptions?.disableUnregister !== 'hidden') { + unregisterButton = ( + { + onClose(); + onUnregisterEntity(); + }} + disabled={disableUnregister} + > + + + + + + ); + } + return ( <> {extraItems} - { - onClose(); - onUnregisterEntity(); - }} - disabled={disableUnregister} - > - - - - - + {unregisterButton} { onClose(); diff --git a/plugins/catalog/src/components/EntityLayout/EntityLayout.tsx b/plugins/catalog/src/components/EntityLayout/EntityLayout.tsx index 693137fe21..4cbb72db5c 100644 --- a/plugins/catalog/src/components/EntityLayout/EntityLayout.tsx +++ b/plugins/catalog/src/components/EntityLayout/EntityLayout.tsx @@ -142,9 +142,11 @@ interface ExtraContextMenuItem { onClick: () => void; } +type VisibleType = 'visible' | 'hidden' | 'disabled'; + // unstable context menu option, eg: disable the unregister entity menu interface contextMenuOptions { - disableUnregister: boolean; + disableUnregister: boolean | VisibleType; } /** @public */ From 06905f4ed0499034c24e276e156520043c53348b Mon Sep 17 00:00:00 2001 From: sjeyaraman Date: Sun, 5 Jun 2022 17:10:23 -0700 Subject: [PATCH 04/12] add-change-set Signed-off-by: sjeyaraman --- .changeset/cold-apples-film.md | 9 +++++++++ packages/app/src/components/catalog/EntityPage.tsx | 2 +- 2 files changed, 10 insertions(+), 1 deletion(-) create mode 100644 .changeset/cold-apples-film.md diff --git a/.changeset/cold-apples-film.md b/.changeset/cold-apples-film.md new file mode 100644 index 0000000000..d8c7ec283d --- /dev/null +++ b/.changeset/cold-apples-film.md @@ -0,0 +1,9 @@ +--- +'example-app': patch +'@backstage/plugin-catalog': patch +--- + +Adding ability to customize the "unregister entity" menu item in the entity context menu on the entity page with options 'visible','hidden','disabled'. +With this three new options, one can hide the "unregister entity" menu item from the list, disable or keep it enabled. + +The boolean input for "unregister entity" will be deprecated later in favour of the above three options. diff --git a/packages/app/src/components/catalog/EntityPage.tsx b/packages/app/src/components/catalog/EntityPage.tsx index 4318e68e74..24ca1b900b 100644 --- a/packages/app/src/components/catalog/EntityPage.tsx +++ b/packages/app/src/components/catalog/EntityPage.tsx @@ -172,7 +172,7 @@ const EntityLayoutWrapper = (props: { children?: ReactNode }) => { }; const options: contextMenuOptions = { - disableUnregister: false, + disableUnregister: 'visible', }; return ( From 258057a4b91ccfb3077790df48d5eba40f735b30 Mon Sep 17 00:00:00 2001 From: sjeyaraman Date: Fri, 24 Jun 2022 14:45:13 -0700 Subject: [PATCH 05/12] refactor-unregister-entity Signed-off-by: sjeyaraman --- ...cold-apples-film.md => thick-cats-kiss.md} | 4 +- .../app/src/components/catalog/EntityPage.tsx | 9 +-- .../EntityContextMenu.test.tsx | 24 ------ .../EntityContextMenu/EntityContextMenu.tsx | 49 +++--------- .../UnregisterEntity.test.tsx | 80 +++++++++++++++++++ .../EntityContextMenu/UnregisterEntity.tsx | 72 +++++++++++++++++ .../components/EntityLayout/EntityLayout.tsx | 6 +- .../src/components/EntityLayout/index.ts | 6 +- 8 files changed, 173 insertions(+), 77 deletions(-) rename .changeset/{cold-apples-film.md => thick-cats-kiss.md} (62%) create mode 100644 plugins/catalog/src/components/EntityContextMenu/UnregisterEntity.test.tsx create mode 100644 plugins/catalog/src/components/EntityContextMenu/UnregisterEntity.tsx diff --git a/.changeset/cold-apples-film.md b/.changeset/thick-cats-kiss.md similarity index 62% rename from .changeset/cold-apples-film.md rename to .changeset/thick-cats-kiss.md index d8c7ec283d..8817115ec3 100644 --- a/.changeset/cold-apples-film.md +++ b/.changeset/thick-cats-kiss.md @@ -1,9 +1,7 @@ --- -'example-app': patch '@backstage/plugin-catalog': patch --- -Adding ability to customize the "unregister entity" menu item in the entity context menu on the entity page with options 'visible','hidden','disabled'. -With this three new options, one can hide the "unregister entity" menu item from the list, disable or keep it enabled. +Adding ability to customize the "unregister entity" menu item in the entity context menu on the entity page with options 'visible','hidden','disabled'.With this three new options, one can hide the "unregister entity" menu item from the list, disable or keep it enabled. The boolean input for "unregister entity" will be deprecated later in favour of the above three options. diff --git a/packages/app/src/components/catalog/EntityPage.tsx b/packages/app/src/components/catalog/EntityPage.tsx index 24ca1b900b..c2ae001060 100644 --- a/packages/app/src/components/catalog/EntityPage.tsx +++ b/packages/app/src/components/catalog/EntityPage.tsx @@ -43,6 +43,7 @@ import { } from '@backstage/plugin-azure-devops'; import { EntityBadgesDialog } from '@backstage/plugin-badges'; import { + EntityContextMenuOptions, EntityAboutCard, EntityDependsOnComponentsCard, EntityDependsOnResourcesCard, @@ -165,13 +166,7 @@ const EntityLayoutWrapper = (props: { children?: ReactNode }) => { ]; }, []); - type VisibleType = 'visible' | 'hidden' | 'disabled'; - - type contextMenuOptions = { - disableUnregister: boolean | VisibleType; - }; - - const options: contextMenuOptions = { + const options: EntityContextMenuOptions = { disableUnregister: 'visible', }; diff --git a/plugins/catalog/src/components/EntityContextMenu/EntityContextMenu.test.tsx b/plugins/catalog/src/components/EntityContextMenu/EntityContextMenu.test.tsx index 9906cd9c12..5d995828e6 100644 --- a/plugins/catalog/src/components/EntityContextMenu/EntityContextMenu.test.tsx +++ b/plugins/catalog/src/components/EntityContextMenu/EntityContextMenu.test.tsx @@ -60,30 +60,6 @@ describe('ComponentContextMenu', () => { expect(mockCallback).toBeCalled(); }); - it('check Unregister entity button is disabled', async () => { - const mockCallback = jest.fn(); - - const { getByText } = await render( - {}} - />, - ); - - const button = await screen.findByTestId('menu-button'); - expect(button).toBeInTheDocument(); - fireEvent.click(button); - - const unregister = await screen.getByText('Unregister entity'); - expect(unregister).toBeInTheDocument(); - - const unregisterSpanItem = getByText(/Unregister entity/); - const unregisterMenuListItem = - unregisterSpanItem?.parentElement?.parentElement; - expect(unregisterMenuListItem).toHaveAttribute('aria-disabled'); - }); - it('should call onInspectEntity on button click', async () => { const mockCallback = jest.fn(); diff --git a/plugins/catalog/src/components/EntityContextMenu/EntityContextMenu.tsx b/plugins/catalog/src/components/EntityContextMenu/EntityContextMenu.tsx index 0a5e2e1bfe..94df8dac29 100644 --- a/plugins/catalog/src/components/EntityContextMenu/EntityContextMenu.tsx +++ b/plugins/catalog/src/components/EntityContextMenu/EntityContextMenu.tsx @@ -24,7 +24,6 @@ import { Popover, } from '@material-ui/core'; import { makeStyles } from '@material-ui/core/styles'; -import CancelIcon from '@material-ui/icons/Cancel'; import BugReportIcon from '@material-ui/icons/BugReport'; import MoreVert from '@material-ui/icons/MoreVert'; import React, { useState } from 'react'; @@ -32,6 +31,8 @@ import { IconComponent } from '@backstage/core-plugin-api'; import { useEntityPermission } from '@backstage/plugin-catalog-react'; import { catalogEntityDeletePermission } from '@backstage/plugin-catalog-common'; import { BackstageTheme } from '@backstage/theme'; +import { UnregisterEntity, UnregisterEntityOptions } from './UnregisterEntity'; + /** @public */ export type EntityContextMenuClassKey = 'button'; @@ -55,16 +56,9 @@ interface ExtraContextMenuItem { onClick: () => void; } -type VisibleType = 'visible' | 'hidden' | 'disabled'; - -// unstable context menu option, eg: disable the unregister entity menu -interface contextMenuOptions { - disableUnregister: boolean | VisibleType; -} - interface EntityContextMenuProps { UNSTABLE_extraContextMenuItems?: ExtraContextMenuItem[]; - UNSTABLE_contextMenuOptions?: contextMenuOptions; + UNSTABLE_contextMenuOptions?: UnregisterEntityOptions; onUnregisterEntity: () => void; onInspectEntity: () => void; } @@ -81,6 +75,7 @@ export function EntityContextMenu(props: EntityContextMenuProps) { const unregisterPermission = useEntityPermission( catalogEntityDeletePermission, ); + const isAllowed = unregisterPermission.allowed; const onOpen = (event: React.SyntheticEvent) => { setAnchorEl(event.currentTarget); @@ -108,35 +103,6 @@ export function EntityContextMenu(props: EntityContextMenuProps) { , ]; - const isBoolean = - typeof UNSTABLE_contextMenuOptions?.disableUnregister === 'boolean'; - - const disableUnregister = - (!unregisterPermission.allowed || - (isBoolean - ? UNSTABLE_contextMenuOptions?.disableUnregister - : UNSTABLE_contextMenuOptions?.disableUnregister === 'disabled')) ?? - false; - - let unregisterButton = <>; - - if (UNSTABLE_contextMenuOptions?.disableUnregister !== 'hidden') { - unregisterButton = ( - { - onClose(); - onUnregisterEntity(); - }} - disabled={disableUnregister} - > - - - - - - ); - } - return ( <> {extraItems} - {unregisterButton} + { onClose(); diff --git a/plugins/catalog/src/components/EntityContextMenu/UnregisterEntity.test.tsx b/plugins/catalog/src/components/EntityContextMenu/UnregisterEntity.test.tsx new file mode 100644 index 0000000000..70b75c7bae --- /dev/null +++ b/plugins/catalog/src/components/EntityContextMenu/UnregisterEntity.test.tsx @@ -0,0 +1,80 @@ +/* + * 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 { EntityProvider } from '@backstage/plugin-catalog-react'; +import { permissionApiRef } from '@backstage/plugin-permission-react'; +import { + MockPermissionApi, + renderInTestApp, + TestApiProvider, +} from '@backstage/test-utils'; +import { fireEvent, screen } from '@testing-library/react'; +import * as React from 'react'; +import { UnregisterEntity } from './UnregisterEntity'; + +const mockPermissionApi = new MockPermissionApi(); + +function render(children: React.ReactNode) { + return renderInTestApp( + + + , + ); +} + +describe('ComponentContextMenu', () => { + it('should call onUnregisterEntity on button click', async () => { + const mockCallback = jest.fn(); + await render( + {}} + />, + ); + + const unregister = await screen.findByText('Unregister entity'); + expect(unregister).toBeInTheDocument(); + fireEvent.click(unregister); + + expect(mockCallback).toBeCalled(); + }); + + it('check Unregister entity button is disabled', async () => { + const mockCallback = jest.fn(); + + const { getByText } = await render( + {}} + />, + ); + + const unregister = await screen.getByText('Unregister entity'); + expect(unregister).toBeInTheDocument(); + + const unregisterSpanItem = getByText(/Unregister entity/); + const unregisterMenuListItem = + unregisterSpanItem?.parentElement?.parentElement; + expect(unregisterMenuListItem).toHaveAttribute('aria-disabled'); + }); +}); diff --git a/plugins/catalog/src/components/EntityContextMenu/UnregisterEntity.tsx b/plugins/catalog/src/components/EntityContextMenu/UnregisterEntity.tsx new file mode 100644 index 0000000000..05044bf935 --- /dev/null +++ b/plugins/catalog/src/components/EntityContextMenu/UnregisterEntity.tsx @@ -0,0 +1,72 @@ +/* + * Copyright 2020 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import React from 'react'; +import { ListItemIcon, ListItemText, MenuItem } from '@material-ui/core'; +import CancelIcon from '@material-ui/icons/Cancel'; + +type VisibleType = 'visible' | 'hidden' | 'disable'; + +export type UnregisterEntityOptions = { + disableUnregister: boolean | VisibleType; +}; + +interface UnregisterEntityProps { + unregisterEntityOptions?: UnregisterEntityOptions; + isUnregisterAllowed: boolean; + onUnregisterEntity: () => void; + onClose: () => void; +} + +export function UnregisterEntity(props: UnregisterEntityProps) { + const { + unregisterEntityOptions, + isUnregisterAllowed, + onUnregisterEntity, + onClose, + } = props; + + const isBoolean = + typeof unregisterEntityOptions?.disableUnregister === 'boolean'; + + const isDisabled = + (!isUnregisterAllowed || + (isBoolean + ? !!unregisterEntityOptions?.disableUnregister + : unregisterEntityOptions?.disableUnregister === 'disable')) ?? + false; + + let unregisterButton = <>; + + if (unregisterEntityOptions?.disableUnregister !== 'hidden') { + unregisterButton = ( + { + onClose(); + onUnregisterEntity(); + }} + disabled={isDisabled} + > + + + + + + ); + } + + return <>{unregisterButton}; +} diff --git a/plugins/catalog/src/components/EntityLayout/EntityLayout.tsx b/plugins/catalog/src/components/EntityLayout/EntityLayout.tsx index 4cbb72db5c..5d82b5ccab 100644 --- a/plugins/catalog/src/components/EntityLayout/EntityLayout.tsx +++ b/plugins/catalog/src/components/EntityLayout/EntityLayout.tsx @@ -142,17 +142,17 @@ interface ExtraContextMenuItem { onClick: () => void; } -type VisibleType = 'visible' | 'hidden' | 'disabled'; +type VisibleType = 'visible' | 'hidden' | 'disable'; // unstable context menu option, eg: disable the unregister entity menu -interface contextMenuOptions { +export interface EntityContextMenuOptions { disableUnregister: boolean | VisibleType; } /** @public */ export interface EntityLayoutProps { UNSTABLE_extraContextMenuItems?: ExtraContextMenuItem[]; - UNSTABLE_contextMenuOptions?: contextMenuOptions; + UNSTABLE_contextMenuOptions?: EntityContextMenuOptions; children?: React.ReactNode; NotFoundComponent?: React.ReactNode; } diff --git a/plugins/catalog/src/components/EntityLayout/index.ts b/plugins/catalog/src/components/EntityLayout/index.ts index 251d213637..73a58dfddc 100644 --- a/plugins/catalog/src/components/EntityLayout/index.ts +++ b/plugins/catalog/src/components/EntityLayout/index.ts @@ -15,4 +15,8 @@ */ export { EntityLayout } from './EntityLayout'; -export type { EntityLayoutProps, EntityLayoutRouteProps } from './EntityLayout'; +export type { + EntityLayoutProps, + EntityLayoutRouteProps, + EntityContextMenuOptions, +} from './EntityLayout'; From 79b5110b99b520733dc00779558426ad7b3c941a Mon Sep 17 00:00:00 2001 From: sjeyaraman Date: Fri, 24 Jun 2022 15:09:54 -0700 Subject: [PATCH 06/12] fix-tsc Signed-off-by: sjeyaraman --- .../src/components/EntityContextMenu/EntityContextMenu.test.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/catalog/src/components/EntityContextMenu/EntityContextMenu.test.tsx b/plugins/catalog/src/components/EntityContextMenu/EntityContextMenu.test.tsx index 9906cd9c12..0e981bb1fc 100644 --- a/plugins/catalog/src/components/EntityContextMenu/EntityContextMenu.test.tsx +++ b/plugins/catalog/src/components/EntityContextMenu/EntityContextMenu.test.tsx @@ -65,7 +65,7 @@ describe('ComponentContextMenu', () => { const { getByText } = await render( {}} />, From 70de933e56739a231c0462fd570d52630aed55ce Mon Sep 17 00:00:00 2001 From: sjeyaraman Date: Sun, 5 Jun 2022 12:40:43 -0700 Subject: [PATCH 07/12] customize unregister entity menuitem Signed-off-by: sjeyaraman --- .../EntityContextMenu.test.tsx | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/plugins/catalog/src/components/EntityContextMenu/EntityContextMenu.test.tsx b/plugins/catalog/src/components/EntityContextMenu/EntityContextMenu.test.tsx index 5d995828e6..9906cd9c12 100644 --- a/plugins/catalog/src/components/EntityContextMenu/EntityContextMenu.test.tsx +++ b/plugins/catalog/src/components/EntityContextMenu/EntityContextMenu.test.tsx @@ -60,6 +60,30 @@ describe('ComponentContextMenu', () => { expect(mockCallback).toBeCalled(); }); + it('check Unregister entity button is disabled', async () => { + const mockCallback = jest.fn(); + + const { getByText } = await render( + {}} + />, + ); + + const button = await screen.findByTestId('menu-button'); + expect(button).toBeInTheDocument(); + fireEvent.click(button); + + const unregister = await screen.getByText('Unregister entity'); + expect(unregister).toBeInTheDocument(); + + const unregisterSpanItem = getByText(/Unregister entity/); + const unregisterMenuListItem = + unregisterSpanItem?.parentElement?.parentElement; + expect(unregisterMenuListItem).toHaveAttribute('aria-disabled'); + }); + it('should call onInspectEntity on button click', async () => { const mockCallback = jest.fn(); From ff5b2f99477bc530a66d3a2f05e6a0472794ba56 Mon Sep 17 00:00:00 2001 From: sjeyaraman Date: Sun, 5 Jun 2022 17:10:23 -0700 Subject: [PATCH 08/12] add-change-set Signed-off-by: sjeyaraman --- .changeset/cold-apples-film.md | 9 +++++++++ packages/app/src/components/catalog/EntityPage.tsx | 2 +- 2 files changed, 10 insertions(+), 1 deletion(-) create mode 100644 .changeset/cold-apples-film.md diff --git a/.changeset/cold-apples-film.md b/.changeset/cold-apples-film.md new file mode 100644 index 0000000000..d8c7ec283d --- /dev/null +++ b/.changeset/cold-apples-film.md @@ -0,0 +1,9 @@ +--- +'example-app': patch +'@backstage/plugin-catalog': patch +--- + +Adding ability to customize the "unregister entity" menu item in the entity context menu on the entity page with options 'visible','hidden','disabled'. +With this three new options, one can hide the "unregister entity" menu item from the list, disable or keep it enabled. + +The boolean input for "unregister entity" will be deprecated later in favour of the above three options. diff --git a/packages/app/src/components/catalog/EntityPage.tsx b/packages/app/src/components/catalog/EntityPage.tsx index c2ae001060..743dea29e4 100644 --- a/packages/app/src/components/catalog/EntityPage.tsx +++ b/packages/app/src/components/catalog/EntityPage.tsx @@ -165,7 +165,7 @@ const EntityLayoutWrapper = (props: { children?: ReactNode }) => { }, ]; }, []); - + const options: EntityContextMenuOptions = { disableUnregister: 'visible', }; From ba8b7f594045bf49748cd801d777f5a4161b2e9b Mon Sep 17 00:00:00 2001 From: sjeyaraman Date: Fri, 24 Jun 2022 15:09:54 -0700 Subject: [PATCH 09/12] fix-tsc Signed-off-by: sjeyaraman --- .../src/components/EntityContextMenu/EntityContextMenu.test.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/catalog/src/components/EntityContextMenu/EntityContextMenu.test.tsx b/plugins/catalog/src/components/EntityContextMenu/EntityContextMenu.test.tsx index 9906cd9c12..0e981bb1fc 100644 --- a/plugins/catalog/src/components/EntityContextMenu/EntityContextMenu.test.tsx +++ b/plugins/catalog/src/components/EntityContextMenu/EntityContextMenu.test.tsx @@ -65,7 +65,7 @@ describe('ComponentContextMenu', () => { const { getByText } = await render( {}} />, From 4235353f463734e42bf3aaf13c91ebc451167705 Mon Sep 17 00:00:00 2001 From: blam Date: Wed, 29 Jun 2022 13:37:09 +0200 Subject: [PATCH 10/12] chore: remove duplicate changeset Signed-off-by: blam --- .changeset/cold-apples-film.md | 9 --------- 1 file changed, 9 deletions(-) delete mode 100644 .changeset/cold-apples-film.md diff --git a/.changeset/cold-apples-film.md b/.changeset/cold-apples-film.md deleted file mode 100644 index d8c7ec283d..0000000000 --- a/.changeset/cold-apples-film.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -'example-app': patch -'@backstage/plugin-catalog': patch ---- - -Adding ability to customize the "unregister entity" menu item in the entity context menu on the entity page with options 'visible','hidden','disabled'. -With this three new options, one can hide the "unregister entity" menu item from the list, disable or keep it enabled. - -The boolean input for "unregister entity" will be deprecated later in favour of the above three options. From 6ecafa9d3b7fb251339eee77c10311778b949bbb Mon Sep 17 00:00:00 2001 From: blam Date: Wed, 29 Jun 2022 13:41:17 +0200 Subject: [PATCH 11/12] chore: make pretty Signed-off-by: blam --- packages/app/src/components/catalog/EntityPage.tsx | 2 +- .../src/components/EntityContextMenu/EntityContextMenu.tsx | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/app/src/components/catalog/EntityPage.tsx b/packages/app/src/components/catalog/EntityPage.tsx index 743dea29e4..c2ae001060 100644 --- a/packages/app/src/components/catalog/EntityPage.tsx +++ b/packages/app/src/components/catalog/EntityPage.tsx @@ -165,7 +165,7 @@ const EntityLayoutWrapper = (props: { children?: ReactNode }) => { }, ]; }, []); - + const options: EntityContextMenuOptions = { disableUnregister: 'visible', }; diff --git a/plugins/catalog/src/components/EntityContextMenu/EntityContextMenu.tsx b/plugins/catalog/src/components/EntityContextMenu/EntityContextMenu.tsx index 94df8dac29..e37362a1e3 100644 --- a/plugins/catalog/src/components/EntityContextMenu/EntityContextMenu.tsx +++ b/plugins/catalog/src/components/EntityContextMenu/EntityContextMenu.tsx @@ -33,7 +33,6 @@ import { catalogEntityDeletePermission } from '@backstage/plugin-catalog-common' import { BackstageTheme } from '@backstage/theme'; import { UnregisterEntity, UnregisterEntityOptions } from './UnregisterEntity'; - /** @public */ export type EntityContextMenuClassKey = 'button'; From 9d0db13c2245566ae49e0f223a7cfc5306894de8 Mon Sep 17 00:00:00 2001 From: blam Date: Wed, 29 Jun 2022 13:48:17 +0200 Subject: [PATCH 12/12] chore: dont export them as they're part of the unstable API, just reference inline for now Signed-off-by: blam --- packages/app/src/components/catalog/EntityPage.tsx | 9 +++------ plugins/catalog/api-report.md | 4 ++-- .../catalog/src/components/EntityLayout/EntityLayout.tsx | 3 ++- plugins/catalog/src/components/EntityLayout/index.ts | 6 +----- 4 files changed, 8 insertions(+), 14 deletions(-) diff --git a/packages/app/src/components/catalog/EntityPage.tsx b/packages/app/src/components/catalog/EntityPage.tsx index c2ae001060..155dc071ff 100644 --- a/packages/app/src/components/catalog/EntityPage.tsx +++ b/packages/app/src/components/catalog/EntityPage.tsx @@ -43,7 +43,6 @@ import { } from '@backstage/plugin-azure-devops'; import { EntityBadgesDialog } from '@backstage/plugin-badges'; import { - EntityContextMenuOptions, EntityAboutCard, EntityDependsOnComponentsCard, EntityDependsOnResourcesCard, @@ -166,15 +165,13 @@ const EntityLayoutWrapper = (props: { children?: ReactNode }) => { ]; }, []); - const options: EntityContextMenuOptions = { - disableUnregister: 'visible', - }; - return ( <> {props.children} diff --git a/plugins/catalog/api-report.md b/plugins/catalog/api-report.md index 0d2d611412..61dc503f2d 100644 --- a/plugins/catalog/api-report.md +++ b/plugins/catalog/api-report.md @@ -259,10 +259,10 @@ export interface EntityLayoutProps { children?: React_2.ReactNode; // (undocumented) NotFoundComponent?: React_2.ReactNode; - // Warning: (ae-forgotten-export) The symbol "contextMenuOptions" needs to be exported by the entry point index.d.ts + // Warning: (ae-forgotten-export) The symbol "EntityContextMenuOptions" needs to be exported by the entry point index.d.ts // // (undocumented) - UNSTABLE_contextMenuOptions?: contextMenuOptions; + UNSTABLE_contextMenuOptions?: EntityContextMenuOptions; // Warning: (ae-forgotten-export) The symbol "ExtraContextMenuItem" needs to be exported by the entry point index.d.ts // // (undocumented) diff --git a/plugins/catalog/src/components/EntityLayout/EntityLayout.tsx b/plugins/catalog/src/components/EntityLayout/EntityLayout.tsx index 5d82b5ccab..2295034905 100644 --- a/plugins/catalog/src/components/EntityLayout/EntityLayout.tsx +++ b/plugins/catalog/src/components/EntityLayout/EntityLayout.tsx @@ -144,8 +144,9 @@ interface ExtraContextMenuItem { type VisibleType = 'visible' | 'hidden' | 'disable'; +// NOTE(blam): Intentionally not exported at this point, since it's part of // unstable context menu option, eg: disable the unregister entity menu -export interface EntityContextMenuOptions { +interface EntityContextMenuOptions { disableUnregister: boolean | VisibleType; } diff --git a/plugins/catalog/src/components/EntityLayout/index.ts b/plugins/catalog/src/components/EntityLayout/index.ts index 73a58dfddc..251d213637 100644 --- a/plugins/catalog/src/components/EntityLayout/index.ts +++ b/plugins/catalog/src/components/EntityLayout/index.ts @@ -15,8 +15,4 @@ */ export { EntityLayout } from './EntityLayout'; -export type { - EntityLayoutProps, - EntityLayoutRouteProps, - EntityContextMenuOptions, -} from './EntityLayout'; +export type { EntityLayoutProps, EntityLayoutRouteProps } from './EntityLayout';