diff --git a/.changeset/healthy-shirts-fold.md b/.changeset/healthy-shirts-fold.md new file mode 100644 index 0000000000..f2ac0a9e83 --- /dev/null +++ b/.changeset/healthy-shirts-fold.md @@ -0,0 +1,6 @@ +--- +'@backstage/plugin-catalog': patch +'@backstage/plugin-techdocs': patch +--- + +The `spec.lifecycle' field in entities will now always be rendered as a string. diff --git a/.changeset/popular-bikes-do.md b/.changeset/popular-bikes-do.md new file mode 100644 index 0000000000..b1cc5c2cdd --- /dev/null +++ b/.changeset/popular-bikes-do.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-code-coverage': patch +--- + +The warning for missing code coverage will now render the entity as a reference. diff --git a/.changeset/pretty-swans-worry.md b/.changeset/pretty-swans-worry.md new file mode 100644 index 0000000000..621ae98fe5 --- /dev/null +++ b/.changeset/pretty-swans-worry.md @@ -0,0 +1,5 @@ +--- +'@backstage/core-components': patch +--- + +Fixed the type declaration of `DependencyGraphProps`, the `defs` prop now expects `JSX.Element`s. diff --git a/.changeset/sweet-buckets-fry.md b/.changeset/sweet-buckets-fry.md new file mode 100644 index 0000000000..8f17617645 --- /dev/null +++ b/.changeset/sweet-buckets-fry.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog-react': patch +--- + +The `spec.type` field in entities will now always be rendered as a string. diff --git a/.changeset/thick-dolphins-boil.md b/.changeset/thick-dolphins-boil.md new file mode 100644 index 0000000000..dd562e620c --- /dev/null +++ b/.changeset/thick-dolphins-boil.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog-import': patch +--- + +The `app.title` configuration is now properly required to be a string. diff --git a/.changeset/wet-cows-brake.md b/.changeset/wet-cows-brake.md new file mode 100644 index 0000000000..9e694d8452 --- /dev/null +++ b/.changeset/wet-cows-brake.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-search-react': patch +--- + +The filter options passed to `SearchResultGroupLayout` are now always explicitly rendered as strings by default. diff --git a/.changeset/wild-geese-occur.md b/.changeset/wild-geese-occur.md new file mode 100644 index 0000000000..b97620e7f5 --- /dev/null +++ b/.changeset/wild-geese-occur.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-search': patch +--- + +Minor internal code cleanup. diff --git a/packages/core-app-api/src/routing/RouteResolver.beta.test.ts b/packages/core-app-api/src/routing/RouteResolver.beta.test.ts index c0ee452d28..09e6389e7f 100644 --- a/packages/core-app-api/src/routing/RouteResolver.beta.test.ts +++ b/packages/core-app-api/src/routing/RouteResolver.beta.test.ts @@ -31,9 +31,8 @@ jest.mock('react-router-dom', () => jest.requireActual('react-router-dom-beta'), ); -const element = () => null; const rest = { - element, + element: null, caseSensitive: false, children: [MATCH_ALL_ROUTE], plugins: new Set(), diff --git a/packages/core-app-api/src/routing/RouteResolver.compat.test.ts b/packages/core-app-api/src/routing/RouteResolver.compat.test.ts index 0b4bf588a2..39949b4cd6 100644 --- a/packages/core-app-api/src/routing/RouteResolver.compat.test.ts +++ b/packages/core-app-api/src/routing/RouteResolver.compat.test.ts @@ -25,9 +25,8 @@ import { } from '@backstage/core-plugin-api'; import { MATCH_ALL_ROUTE } from './collectors'; -const element = () => null; const rest = { - element, + element: null, caseSensitive: false, children: [MATCH_ALL_ROUTE], plugins: new Set(), diff --git a/packages/core-app-api/src/routing/RouteResolver.stable.test.ts b/packages/core-app-api/src/routing/RouteResolver.stable.test.ts index 05f7678078..f1f9ec7137 100644 --- a/packages/core-app-api/src/routing/RouteResolver.stable.test.ts +++ b/packages/core-app-api/src/routing/RouteResolver.stable.test.ts @@ -31,9 +31,8 @@ jest.mock('react-router-dom', () => jest.requireActual('react-router-dom-stable'), ); -const element = () => null; const rest = { - element, + element: null, caseSensitive: false, children: [MATCH_ALL_ROUTE], plugins: new Set(), diff --git a/packages/core-app-api/src/routing/RoutingProvider.beta.test.tsx b/packages/core-app-api/src/routing/RoutingProvider.beta.test.tsx index c3a5bab89e..0f7a5cd3ad 100644 --- a/packages/core-app-api/src/routing/RoutingProvider.beta.test.tsx +++ b/packages/core-app-api/src/routing/RoutingProvider.beta.test.tsx @@ -353,7 +353,9 @@ describe('v1 consumer', () => { initialProps: { routeRef: routeRef1 as AnyRouteRef, }, - wrapper: ({ children }: React.PropsWithChildren<{}>) => ( + wrapper: ({ + children, + }: React.PropsWithChildren<{ routeRef: AnyRouteRef }>) => ( , string>([ diff --git a/packages/core-app-api/src/routing/RoutingProvider.stable.test.tsx b/packages/core-app-api/src/routing/RoutingProvider.stable.test.tsx index 84a33842c9..495fc20b15 100644 --- a/packages/core-app-api/src/routing/RoutingProvider.stable.test.tsx +++ b/packages/core-app-api/src/routing/RoutingProvider.stable.test.tsx @@ -385,7 +385,9 @@ describe('v1 consumer', () => { initialProps: { routeRef: routeRef1 as AnyRouteRef, }, - wrapper: ({ children }: React.PropsWithChildren<{}>) => ( + wrapper: ({ + children, + }: React.PropsWithChildren<{ routeRef: AnyRouteRef }>) => ( , string>([ diff --git a/packages/core-components/api-report.md b/packages/core-components/api-report.md index 44a8b33e04..d40179dc62 100644 --- a/packages/core-components/api-report.md +++ b/packages/core-components/api-report.md @@ -249,7 +249,7 @@ export interface DependencyGraphProps acyclicer?: 'greedy'; align?: DependencyGraphTypes.Alignment; curve?: 'curveStepBefore' | 'curveMonotoneX'; - defs?: SVGDefsElement | SVGDefsElement[]; + defs?: JSX.Element | JSX.Element[]; direction?: DependencyGraphTypes.Direction; edgeMargin?: number; edgeRanks?: number; diff --git a/packages/core-components/src/components/DependencyGraph/DependencyGraph.tsx b/packages/core-components/src/components/DependencyGraph/DependencyGraph.tsx index 4928292424..3dd1025b8f 100644 --- a/packages/core-components/src/components/DependencyGraph/DependencyGraph.tsx +++ b/packages/core-components/src/components/DependencyGraph/DependencyGraph.tsx @@ -144,7 +144,7 @@ export interface DependencyGraphProps * {@link https://developer.mozilla.org/en-US/docs/Web/SVG/Element/defs | Defs} shared by rendered SVG to be used by * {@link DependencyGraphProps.renderNode} and/or {@link DependencyGraphProps.renderLabel} */ - defs?: SVGDefsElement | SVGDefsElement[]; + defs?: JSX.Element | JSX.Element[]; /** * Controls zoom behavior of graph * diff --git a/packages/core-components/src/components/Table/Table.tsx b/packages/core-components/src/components/Table/Table.tsx index 9f2b04c214..e4ee9b5995 100644 --- a/packages/core-components/src/components/Table/Table.tsx +++ b/packages/core-components/src/components/Table/Table.tsx @@ -455,7 +455,7 @@ export function Table(props: TableProps) { const hasFilters = !!filters?.length; const Toolbar = useCallback( - toolbarProps => { + (toolbarProps: any /* no type for this in material-table */) => { return ( (props: TableProps) { const hasNoRows = typeof data !== 'function' && data.length === 0; const columnCount = columns.length; const Body = useCallback( - bodyProps => { + (bodyProps: any /* no type for this in material-table */) => { if (isLoading) { return ( diff --git a/packages/core-components/src/layout/Sidebar/Items.tsx b/packages/core-components/src/layout/Sidebar/Items.tsx index c40d45f8b4..aba4c79181 100644 --- a/packages/core-components/src/layout/Sidebar/Items.tsx +++ b/packages/core-components/src/layout/Sidebar/Items.tsx @@ -312,7 +312,11 @@ const sidebarSubmenuType = React.createElement(SidebarSubmenu).type; // properly yet, matching for example /foobar with /foo. export const WorkaroundNavLink = React.forwardRef< HTMLAnchorElement, - NavLinkProps & { activeStyle?: CSSProperties; activeClassName?: string } + NavLinkProps & { + children?: ReactNode; + activeStyle?: CSSProperties; + activeClassName?: string; + } >(function WorkaroundNavLinkWithRef( { to, @@ -361,7 +365,10 @@ export const WorkaroundNavLink = React.forwardRef< /** * Common component used by SidebarItem & SidebarItemWithSubmenu */ -const SidebarItemBase = forwardRef((props, ref) => { +const SidebarItemBase = forwardRef< + any, + SidebarItemProps & { children: ReactNode } +>((props, ref) => { const { icon: Icon, text, @@ -553,7 +560,10 @@ const SidebarItemWithSubmenu = ({ * @remarks * If children contain a `SidebarSubmenu` component the `SidebarItem` will have a expandable submenu */ -export const SidebarItem = forwardRef((props, ref) => { +export const SidebarItem = forwardRef< + any, + SidebarItemProps & { children: ReactNode } +>((props, ref) => { // Filter children for SidebarSubmenu components const [submenu] = useElementFilter(props.children, elements => // Directly comparing child.type with SidebarSubmenu will not work with in diff --git a/packages/core-components/src/layout/Sidebar/MobileSidebar.tsx b/packages/core-components/src/layout/Sidebar/MobileSidebar.tsx index e124036648..88d653cea5 100644 --- a/packages/core-components/src/layout/Sidebar/MobileSidebar.tsx +++ b/packages/core-components/src/layout/Sidebar/MobileSidebar.tsx @@ -25,7 +25,7 @@ import Typography from '@material-ui/core/Typography'; import CloseIcon from '@material-ui/icons/Close'; import MenuIcon from '@material-ui/icons/Menu'; import { orderBy } from 'lodash'; -import React, { useEffect, useState, useContext } from 'react'; +import React, { useEffect, useState, useContext, ReactNode } from 'react'; import { useLocation } from 'react-router-dom'; import { SidebarOpenStateProvider } from './SidebarOpenStateContext'; import { SidebarGroup } from './SidebarGroup'; @@ -206,8 +206,7 @@ export const MobileSidebar = (props: MobileSidebarProps) => { onClose={() => setSelectedMenuItemIndex(-1)} > {sidebarGroups[selectedMenuItemIndex] && - (sidebarGroups[selectedMenuItemIndex].props - .children as React.ReactChildren)} + (sidebarGroups[selectedMenuItemIndex].props.children as ReactNode)} { export const SampleSidebar = () => ( - + }> diff --git a/packages/core-components/src/layout/TabbedCard/TabbedCard.tsx b/packages/core-components/src/layout/TabbedCard/TabbedCard.tsx index a09ea11b3d..4e75878a7d 100644 --- a/packages/core-components/src/layout/TabbedCard/TabbedCard.tsx +++ b/packages/core-components/src/layout/TabbedCard/TabbedCard.tsx @@ -96,7 +96,9 @@ export function TabbedCard(props: PropsWithChildren) { } else { React.Children.map(children, child => { if ( - React.isValidElement<{ children?: unknown; value?: unknown }>(child) && + React.isValidElement<{ children?: ReactNode; value?: unknown }>( + child, + ) && child?.props.value === value ) { selectedTabContent = child?.props.children; diff --git a/packages/core-plugin-api/src/extensions/useElementFilter.test.tsx b/packages/core-plugin-api/src/extensions/useElementFilter.test.tsx index 8795ecdded..9a3760d019 100644 --- a/packages/core-plugin-api/src/extensions/useElementFilter.test.tsx +++ b/packages/core-plugin-api/src/extensions/useElementFilter.test.tsx @@ -41,7 +41,12 @@ const FeatureFlagComponent = (_props: { }) => null; attachComponentData(FeatureFlagComponent, 'core.featureFlagged', true); const mockFeatureFlagsApi = new LocalStorageFeatureFlags(); -const Wrapper = ({ children }: { children?: React.ReactNode }) => ( +const Wrapper = ({ + children, +}: { + children?: React.ReactNode; + tree?: ReactNode; +}) => ( {children} diff --git a/packages/core-plugin-api/src/translation/useTranslationRef.test.tsx b/packages/core-plugin-api/src/translation/useTranslationRef.test.tsx index a8dbdc0402..19f0516906 100644 --- a/packages/core-plugin-api/src/translation/useTranslationRef.test.tsx +++ b/packages/core-plugin-api/src/translation/useTranslationRef.test.tsx @@ -303,7 +303,12 @@ describe('useTranslationRef', () => { const translationApi = I18nextTranslationApi.create({ languageApi }); const { result, rerender } = renderHook( - ({ translationRef }) => useTranslationRef(translationRef), + ({ + translationRef, + }: { + translationRef: TranslationRef; + children?: ReactNode; + }) => useTranslationRef(translationRef), { wrapper: ({ children }) => ( = ['curveMonotoneX', 'curveStepBefore']; export const CurveFilter = ({ value, onChange }: Props) => { - const handleChange = useCallback(v => onChange(v as Curve), [onChange]); + const handleChange = useCallback( + (v: SelectedItems) => onChange(v as Curve), + [onChange], + ); return ( diff --git a/plugins/catalog-graph/src/components/CatalogGraphPage/DirectionFilter.tsx b/plugins/catalog-graph/src/components/CatalogGraphPage/DirectionFilter.tsx index 815ed1f292..c614ed2b58 100644 --- a/plugins/catalog-graph/src/components/CatalogGraphPage/DirectionFilter.tsx +++ b/plugins/catalog-graph/src/components/CatalogGraphPage/DirectionFilter.tsx @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { Select } from '@backstage/core-components'; +import { Select, SelectedItems } from '@backstage/core-components'; import { Box } from '@material-ui/core'; import React, { useCallback } from 'react'; import { Direction } from '../EntityRelationsGraph'; @@ -31,7 +31,10 @@ export type Props = { }; export const DirectionFilter = ({ value, onChange }: Props) => { - const handleChange = useCallback(v => onChange(v as Direction), [onChange]); + const handleChange = useCallback( + (v: SelectedItems) => onChange(v as Direction), + [onChange], + ); return ( diff --git a/plugins/catalog-import/src/components/DefaultImportPage/DefaultImportPage.tsx b/plugins/catalog-import/src/components/DefaultImportPage/DefaultImportPage.tsx index c777953808..16000465b9 100644 --- a/plugins/catalog-import/src/components/DefaultImportPage/DefaultImportPage.tsx +++ b/plugins/catalog-import/src/components/DefaultImportPage/DefaultImportPage.tsx @@ -36,7 +36,7 @@ export const DefaultImportPage = () => { const theme = useTheme(); const configApi = useApi(configApiRef); const isMobile = useMediaQuery(theme.breakpoints.down('sm')); - const appTitle = configApi.getOptional('app.title') || 'Backstage'; + const appTitle = configApi.getOptionalString('app.title') || 'Backstage'; const contentItems = [ diff --git a/plugins/catalog-import/src/components/ImportInfoCard/ImportInfoCard.tsx b/plugins/catalog-import/src/components/ImportInfoCard/ImportInfoCard.tsx index f7086fce19..26b6b8eb52 100644 --- a/plugins/catalog-import/src/components/ImportInfoCard/ImportInfoCard.tsx +++ b/plugins/catalog-import/src/components/ImportInfoCard/ImportInfoCard.tsx @@ -43,7 +43,7 @@ export const ImportInfoCard = (props: ImportInfoCardProps) => { } = props; const configApi = useApi(configApiRef); - const appTitle = configApi.getOptional('app.title') || 'Backstage'; + const appTitle = configApi.getOptionalString('app.title') || 'Backstage'; const catalogImportApi = useApi(catalogImportApiRef); const hasGithubIntegration = configApi.has('integrations.github'); diff --git a/plugins/catalog-import/src/components/StepReviewLocation/StepReviewLocation.tsx b/plugins/catalog-import/src/components/StepReviewLocation/StepReviewLocation.tsx index 74ebd973d0..b0db174787 100644 --- a/plugins/catalog-import/src/components/StepReviewLocation/StepReviewLocation.tsx +++ b/plugins/catalog-import/src/components/StepReviewLocation/StepReviewLocation.tsx @@ -42,7 +42,7 @@ export const StepReviewLocation = ({ const configApi = useApi(configApiRef); const analytics = useAnalytics(); - const appTitle = configApi.getOptional('app.title') || 'Backstage'; + const appTitle = configApi.getOptionalString('app.title') || 'Backstage'; const [submitted, setSubmitted] = useState(false); const [error, setError] = useState(); diff --git a/plugins/catalog-react/src/components/EntityPeekAheadPopover/EntityPeekAheadPopover.tsx b/plugins/catalog-react/src/components/EntityPeekAheadPopover/EntityPeekAheadPopover.tsx index 91d60d4f13..077274a6e9 100644 --- a/plugins/catalog-react/src/components/EntityPeekAheadPopover/EntityPeekAheadPopover.tsx +++ b/plugins/catalog-react/src/components/EntityPeekAheadPopover/EntityPeekAheadPopover.tsx @@ -164,7 +164,7 @@ export const EntityPeekAheadPopover = (props: EntityPeekAheadPopoverProps) => { {entity.metadata.description} )} - {entity.spec?.type} + {entity.spec?.type?.toString()} {(entity.metadata.tags || []) .slice(0, maxTagChips) diff --git a/plugins/catalog-react/src/components/InspectEntityDialog/components/OverviewPage.tsx b/plugins/catalog-react/src/components/InspectEntityDialog/components/OverviewPage.tsx index 09b944605f..d2eb6d4266 100644 --- a/plugins/catalog-react/src/components/InspectEntityDialog/components/OverviewPage.tsx +++ b/plugins/catalog-react/src/components/InspectEntityDialog/components/OverviewPage.tsx @@ -74,7 +74,10 @@ export function OverviewPage(props: { entity: AlphaEntity }) { {spec?.type && ( - + )} {metadata.uid && ( diff --git a/plugins/catalog-react/src/components/UnregisterEntityDialog/useUnregisterEntityDialogState.test.tsx b/plugins/catalog-react/src/components/UnregisterEntityDialog/useUnregisterEntityDialogState.test.tsx index e458e7d157..8591cdad93 100644 --- a/plugins/catalog-react/src/components/UnregisterEntityDialog/useUnregisterEntityDialogState.test.tsx +++ b/plugins/catalog-react/src/components/UnregisterEntityDialog/useUnregisterEntityDialogState.test.tsx @@ -22,7 +22,7 @@ import { renderHook, RenderHookResult, } from '@testing-library/react-hooks'; -import React from 'react'; +import React, { ReactNode } from 'react'; import { UseUnregisterEntityDialogState, useUnregisterEntityDialogState, @@ -85,7 +85,10 @@ describe('useUnregisterEntityDialogState', () => { }); it('goes through the happy unregister path', async () => { - let rendered: RenderHookResult; + let rendered: RenderHookResult< + { children?: ReactNode }, + UseUnregisterEntityDialogState + >; act(() => { rendered = renderHook(() => useUnregisterEntityDialogState(entity), { wrapper: Wrapper, @@ -114,7 +117,10 @@ describe('useUnregisterEntityDialogState', () => { entity.metadata.annotations![ANNOTATION_ORIGIN_LOCATION] = 'bootstrap:bootstrap'; - let rendered: RenderHookResult; + let rendered: RenderHookResult< + { children?: ReactNode }, + UseUnregisterEntityDialogState + >; act(() => { rendered = renderHook(() => useUnregisterEntityDialogState(entity), { wrapper: Wrapper, @@ -137,7 +143,10 @@ describe('useUnregisterEntityDialogState', () => { it('chooses only-delete when there was no location annotation', async () => { delete entity.metadata.annotations![ANNOTATION_ORIGIN_LOCATION]; - let rendered: RenderHookResult; + let rendered: RenderHookResult< + { children?: ReactNode }, + UseUnregisterEntityDialogState + >; act(() => { rendered = renderHook(() => useUnregisterEntityDialogState(entity), { wrapper: Wrapper, @@ -157,7 +166,10 @@ describe('useUnregisterEntityDialogState', () => { }); it('chooses only-delete when the location could not be found', async () => { - let rendered: RenderHookResult; + let rendered: RenderHookResult< + { children?: ReactNode }, + UseUnregisterEntityDialogState + >; act(() => { rendered = renderHook(() => useUnregisterEntityDialogState(entity), { wrapper: Wrapper, diff --git a/plugins/catalog/src/components/EntityLayout/EntityLayout.tsx b/plugins/catalog/src/components/EntityLayout/EntityLayout.tsx index a190984ffe..9505dad889 100644 --- a/plugins/catalog/src/components/EntityLayout/EntityLayout.tsx +++ b/plugins/catalog/src/components/EntityLayout/EntityLayout.tsx @@ -128,7 +128,10 @@ function EntityLabels(props: { entity: Entity }) { /> )} {entity.spec?.lifecycle && ( - + )} ); diff --git a/plugins/code-coverage/src/components/FileExplorer/FileExplorer.tsx b/plugins/code-coverage/src/components/FileExplorer/FileExplorer.tsx index 4017ba8264..57bb9a2be0 100644 --- a/plugins/code-coverage/src/components/FileExplorer/FileExplorer.tsx +++ b/plugins/code-coverage/src/components/FileExplorer/FileExplorer.tsx @@ -14,7 +14,7 @@ * limitations under the License. */ -import { useEntity } from '@backstage/plugin-catalog-react'; +import { humanizeEntityRef, useEntity } from '@backstage/plugin-catalog-react'; import { Box, Modal, makeStyles } from '@material-ui/core'; import FolderIcon from '@material-ui/icons/Folder'; import FileOutlinedIcon from '@material-ui/icons/InsertDriveFileOutlined'; @@ -181,7 +181,9 @@ export const FileExplorer = () => { } if (!value) { return ( - No code coverage found for ${entity} + + No code coverage found for {humanizeEntityRef(entity)} + ); } diff --git a/plugins/cost-insights/src/components/BarChart/BarChartTooltip.test.tsx b/plugins/cost-insights/src/components/BarChart/BarChartTooltip.test.tsx index 3a6dca9417..4e255917d8 100644 --- a/plugins/cost-insights/src/components/BarChart/BarChartTooltip.test.tsx +++ b/plugins/cost-insights/src/components/BarChart/BarChartTooltip.test.tsx @@ -33,8 +33,9 @@ const items = [ }, ]; -const tooltipItems = () => - items.map(item => ); +const tooltipItems = items.map(item => ( + +)); describe('', () => { it('formats label and tooltip item text correctly', async () => { diff --git a/plugins/cost-insights/src/components/ProjectSelect/ProjectSelect.test.tsx b/plugins/cost-insights/src/components/ProjectSelect/ProjectSelect.test.tsx index 7dd5b4253f..3a2f30bbfe 100644 --- a/plugins/cost-insights/src/components/ProjectSelect/ProjectSelect.test.tsx +++ b/plugins/cost-insights/src/components/ProjectSelect/ProjectSelect.test.tsx @@ -14,7 +14,7 @@ * limitations under the License. */ -import React from 'react'; +import React, { ComponentType } from 'react'; import { getByRole, screen, waitFor } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import { ProjectSelect } from './ProjectSelect'; @@ -28,7 +28,7 @@ const mockProjects = [ ]; describe('', () => { - let Component: React.ReactNode; + let Component: ComponentType; beforeEach(() => { Component = () => ( diff --git a/plugins/lighthouse/src/components/AuditList/index.tsx b/plugins/lighthouse/src/components/AuditList/index.tsx index c433bb1900..f030ec4708 100644 --- a/plugins/lighthouse/src/components/AuditList/index.tsx +++ b/plugins/lighthouse/src/components/AuditList/index.tsx @@ -44,7 +44,9 @@ import { useApi } from '@backstage/core-plugin-api'; export const LIMIT = 10; const AuditList = () => { - const [dismissedStored] = useLocalStorage(LIGHTHOUSE_INTRO_LOCAL_STORAGE); + const [dismissedStored] = useLocalStorage( + LIGHTHOUSE_INTRO_LOCAL_STORAGE, + ); const [dismissed, setDismissed] = useState(dismissedStored); const query = useQuery(); diff --git a/plugins/org-react/src/components/GroupListPicker/GroupListPicker.tsx b/plugins/org-react/src/components/GroupListPicker/GroupListPicker.tsx index a47c346390..57a93ce0fe 100644 --- a/plugins/org-react/src/components/GroupListPicker/GroupListPicker.tsx +++ b/plugins/org-react/src/components/GroupListPicker/GroupListPicker.tsx @@ -74,7 +74,7 @@ export const GroupListPicker = (props: GroupListPickerProps) => { }, [catalogApi, groupTypes]); const handleChange = useCallback( - (_, v: GroupEntity | null) => { + (_: unknown, v: GroupEntity | null) => { onChange(v ?? undefined); setAnchorEl(null); }, diff --git a/plugins/playlist/package.json b/plugins/playlist/package.json index 5169e4828d..a479c2946d 100644 --- a/plugins/playlist/package.json +++ b/plugins/playlist/package.json @@ -59,6 +59,7 @@ "@backstage/cli": "workspace:^", "@backstage/core-app-api": "workspace:^", "@backstage/dev-utils": "workspace:^", + "@backstage/plugin-search-common": "workspace:^", "@backstage/test-utils": "workspace:^", "@testing-library/dom": "^9.0.0", "@testing-library/jest-dom": "^6.0.0", diff --git a/plugins/playlist/src/components/PlaylistPage/AddEntitiesDrawer.tsx b/plugins/playlist/src/components/PlaylistPage/AddEntitiesDrawer.tsx index d5a52dc83c..529327776e 100644 --- a/plugins/playlist/src/components/PlaylistPage/AddEntitiesDrawer.tsx +++ b/plugins/playlist/src/components/PlaylistPage/AddEntitiesDrawer.tsx @@ -15,6 +15,7 @@ */ import { + CompoundEntityRef, Entity, getCompoundEntityRef, stringifyEntityRef, @@ -22,6 +23,7 @@ import { import { useApi, useRouteRef } from '@backstage/core-plugin-api'; import { CatalogEntityDocument } from '@backstage/plugin-catalog-common'; import { catalogApiRef, entityRouteRef } from '@backstage/plugin-catalog-react'; +import type { SearchDocument } from '@backstage/plugin-search-common'; import { SearchBar, SearchContextProvider, @@ -131,13 +133,13 @@ export const AddEntitiesDrawer = ({ }; const addEntity = useCallback( - entityResult => { + (entityResult: SearchDocument) => { // TODO(kuangp): this parsing of the location is not great. Ideally `CatalogEntityDocument` // contains the `metadata.name` field so we can derive the full ref and we only fall back to // parsing location if it's missing (ie. for older versions) const match = entityResult.location.match(entityLocationRegex); if (match?.groups) { - onAdd(stringifyEntityRef(match?.groups)); + onAdd(stringifyEntityRef(match?.groups as CompoundEntityRef)); } else { // eslint-disable-next-line no-console console.error( diff --git a/plugins/playlist/src/components/PlaylistPage/PlaylistEntitiesTable.tsx b/plugins/playlist/src/components/PlaylistPage/PlaylistEntitiesTable.tsx index c74859ce20..72d50506b0 100644 --- a/plugins/playlist/src/components/PlaylistPage/PlaylistEntitiesTable.tsx +++ b/plugins/playlist/src/components/PlaylistPage/PlaylistEntitiesTable.tsx @@ -72,7 +72,7 @@ export const PlaylistEntitiesTable = ({ ); const removeEntity = useCallback( - async (_, entity: Entity | Entity[]) => { + async (_: unknown, entity: Entity | Entity[]) => { try { const entityArray = [entity].flat(); const entityNames = entityArray.map( diff --git a/plugins/scaffolder/src/components/MultistepJsonForm/MultistepJsonForm.tsx b/plugins/scaffolder/src/components/MultistepJsonForm/MultistepJsonForm.tsx index ec95bad0e5..d8299a9b5f 100644 --- a/plugins/scaffolder/src/components/MultistepJsonForm/MultistepJsonForm.tsx +++ b/plugins/scaffolder/src/components/MultistepJsonForm/MultistepJsonForm.tsx @@ -29,7 +29,7 @@ import { useRouteRefParams, useApi, } from '@backstage/core-plugin-api'; -import { FormProps, IChangeEvent, withTheme } from '@rjsf/core'; +import { FormProps, IChangeEvent, ISubmitEvent, withTheme } from '@rjsf/core'; import { Theme as MuiTheme } from '@rjsf/material-ui'; import React, { ComponentType, useState } from 'react'; import { transformSchemaToProps } from './schema'; @@ -185,7 +185,7 @@ export const MultistepJsonForm = (props: MultistepJsonFormProps) => { formData={formData} formContext={{ formData }} onChange={onChange} - onSubmit={e => { + onSubmit={(e: ISubmitEvent) => { if (e.errors.length === 0) handleNext(); }} {...formProps} diff --git a/plugins/scaffolder/src/components/TemplateEditorPage/CustomFieldExplorer.tsx b/plugins/scaffolder/src/components/TemplateEditorPage/CustomFieldExplorer.tsx index 43b3b49bcf..e470267b23 100644 --- a/plugins/scaffolder/src/components/TemplateEditorPage/CustomFieldExplorer.tsx +++ b/plugins/scaffolder/src/components/TemplateEditorPage/CustomFieldExplorer.tsx @@ -28,7 +28,7 @@ import { Select, } from '@material-ui/core'; import CloseIcon from '@material-ui/icons/Close'; -import { withTheme } from '@rjsf/core'; +import { ISubmitEvent, withTheme } from '@rjsf/core'; import { Theme as MuiTheme } from '@rjsf/material-ui'; import CodeMirror from '@uiw/react-codemirror'; import React, { useCallback, useMemo, useState } from 'react'; @@ -104,7 +104,7 @@ export const CustomFieldExplorer = ({ }, [customFieldExtensions]); const handleSelectionChange = useCallback( - selection => { + (selection: FieldExtensionOptions) => { setSelectedField(selection); setFieldFormState({}); setFormState({}); @@ -113,7 +113,7 @@ export const CustomFieldExplorer = ({ ); const handleFieldConfigChange = useCallback( - state => { + (state: {}) => { setFieldFormState(state); setFormState({}); // Force TemplateEditorForm to re-render since some fields @@ -134,7 +134,9 @@ export const CustomFieldExplorer = ({ value={selectedField} label="Choose Custom Field Extension" labelId="select-field-label" - onChange={e => handleSelectionChange(e.target.value)} + onChange={e => + handleSelectionChange(e.target.value as FieldExtensionOptions) + } > {fieldOptions.map((option, idx) => ( @@ -158,7 +160,9 @@ export const CustomFieldExplorer = ({ noHtml5Validate formData={fieldFormState} formContext={{ fieldFormState }} - onSubmit={e => handleFieldConfigChange(e.formData)} + onSubmit={(e: ISubmitEvent) => + handleFieldConfigChange(e.formData) + } schema={selectedField.schema?.uiOptions || {}} >