type fixes for React 18
Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
This commit is contained in:
@@ -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.
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/plugin-code-coverage': patch
|
||||
---
|
||||
|
||||
The warning for missing code coverage will now render the entity as a reference.
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/core-components': patch
|
||||
---
|
||||
|
||||
Fixed the type declaration of `DependencyGraphProps`, the `defs` prop now expects `JSX.Element`s.
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/plugin-catalog-react': patch
|
||||
---
|
||||
|
||||
The `spec.type` field in entities will now always be rendered as a string.
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/plugin-catalog-import': patch
|
||||
---
|
||||
|
||||
The `app.title` configuration is now properly required to be a string.
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/plugin-search-react': patch
|
||||
---
|
||||
|
||||
The filter options passed to `SearchResultGroupLayout` are now always explicitly rendered as strings by default.
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/plugin-search': patch
|
||||
---
|
||||
|
||||
Minor internal code cleanup.
|
||||
@@ -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<BackstagePlugin>(),
|
||||
|
||||
@@ -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<BackstagePlugin>(),
|
||||
|
||||
@@ -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<BackstagePlugin>(),
|
||||
|
||||
@@ -353,7 +353,9 @@ describe('v1 consumer', () => {
|
||||
initialProps: {
|
||||
routeRef: routeRef1 as AnyRouteRef,
|
||||
},
|
||||
wrapper: ({ children }: React.PropsWithChildren<{}>) => (
|
||||
wrapper: ({
|
||||
children,
|
||||
}: React.PropsWithChildren<{ routeRef: AnyRouteRef }>) => (
|
||||
<RoutingProvider
|
||||
routePaths={
|
||||
new Map<RouteRef<any>, string>([
|
||||
|
||||
@@ -385,7 +385,9 @@ describe('v1 consumer', () => {
|
||||
initialProps: {
|
||||
routeRef: routeRef1 as AnyRouteRef,
|
||||
},
|
||||
wrapper: ({ children }: React.PropsWithChildren<{}>) => (
|
||||
wrapper: ({
|
||||
children,
|
||||
}: React.PropsWithChildren<{ routeRef: AnyRouteRef }>) => (
|
||||
<RoutingProvider
|
||||
routePaths={
|
||||
new Map<RouteRef<any>, string>([
|
||||
|
||||
@@ -249,7 +249,7 @@ export interface DependencyGraphProps<NodeData, EdgeData>
|
||||
acyclicer?: 'greedy';
|
||||
align?: DependencyGraphTypes.Alignment;
|
||||
curve?: 'curveStepBefore' | 'curveMonotoneX';
|
||||
defs?: SVGDefsElement | SVGDefsElement[];
|
||||
defs?: JSX.Element | JSX.Element[];
|
||||
direction?: DependencyGraphTypes.Direction;
|
||||
edgeMargin?: number;
|
||||
edgeRanks?: number;
|
||||
|
||||
@@ -144,7 +144,7 @@ export interface DependencyGraphProps<NodeData, EdgeData>
|
||||
* {@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
|
||||
*
|
||||
|
||||
@@ -455,7 +455,7 @@ export function Table<T extends object = {}>(props: TableProps<T>) {
|
||||
|
||||
const hasFilters = !!filters?.length;
|
||||
const Toolbar = useCallback(
|
||||
toolbarProps => {
|
||||
(toolbarProps: any /* no type for this in material-table */) => {
|
||||
return (
|
||||
<TableToolbar
|
||||
setSearch={setSearch}
|
||||
@@ -472,7 +472,7 @@ export function Table<T extends object = {}>(props: TableProps<T>) {
|
||||
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 (
|
||||
<tbody data-testid="loading-indicator">
|
||||
|
||||
@@ -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<any, SidebarItemProps>((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<any, SidebarItemProps>((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
|
||||
|
||||
@@ -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)}
|
||||
</OverlayMenu>
|
||||
<BottomNavigation
|
||||
className={classes.root}
|
||||
|
||||
@@ -59,7 +59,7 @@ const handleSearch = (input: string) => {
|
||||
export const SampleSidebar = () => (
|
||||
<SidebarPage>
|
||||
<Sidebar>
|
||||
<SidebarGroup label="Menu" icon={MenuIcon}>
|
||||
<SidebarGroup label="Menu" icon={<MenuIcon />}>
|
||||
<SidebarSearchField onSearch={handleSearch} to="/search" />
|
||||
<SidebarDivider />
|
||||
<SidebarItem icon={HomeOutlinedIcon} to="#" text="Plugins" />
|
||||
|
||||
@@ -96,7 +96,9 @@ export function TabbedCard(props: PropsWithChildren<Props>) {
|
||||
} 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;
|
||||
|
||||
@@ -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;
|
||||
}) => (
|
||||
<TestApiProvider apis={[[featureFlagsApiRef, mockFeatureFlagsApi]]}>
|
||||
{children}
|
||||
</TestApiProvider>
|
||||
|
||||
@@ -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 }) => (
|
||||
<TestApiProvider
|
||||
|
||||
@@ -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';
|
||||
|
||||
@@ -31,7 +31,10 @@ export type Props = {
|
||||
const curves: Array<Curve> = ['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 (
|
||||
<Box pb={1} pt={1}>
|
||||
|
||||
@@ -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 (
|
||||
<Box pb={1} pt={1}>
|
||||
|
||||
@@ -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 = [
|
||||
<Grid item xs={12} md={4} lg={6} xl={8}>
|
||||
|
||||
@@ -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');
|
||||
|
||||
@@ -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<string>();
|
||||
|
||||
+1
-1
@@ -164,7 +164,7 @@ export const EntityPeekAheadPopover = (props: EntityPeekAheadPopoverProps) => {
|
||||
{entity.metadata.description}
|
||||
</Typography>
|
||||
)}
|
||||
<Typography>{entity.spec?.type}</Typography>
|
||||
<Typography>{entity.spec?.type?.toString()}</Typography>
|
||||
<Box marginTop="0.5em">
|
||||
{(entity.metadata.tags || [])
|
||||
.slice(0, maxTagChips)
|
||||
|
||||
+4
-1
@@ -74,7 +74,10 @@ export function OverviewPage(props: { entity: AlphaEntity }) {
|
||||
</ListItem>
|
||||
{spec?.type && (
|
||||
<ListItem>
|
||||
<ListItemText primary="spec.type" secondary={spec.type} />
|
||||
<ListItemText
|
||||
primary="spec.type"
|
||||
secondary={spec.type?.toString()}
|
||||
/>
|
||||
</ListItem>
|
||||
)}
|
||||
{metadata.uid && (
|
||||
|
||||
+17
-5
@@ -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<unknown, UseUnregisterEntityDialogState>;
|
||||
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<unknown, UseUnregisterEntityDialogState>;
|
||||
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<unknown, UseUnregisterEntityDialogState>;
|
||||
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<unknown, UseUnregisterEntityDialogState>;
|
||||
let rendered: RenderHookResult<
|
||||
{ children?: ReactNode },
|
||||
UseUnregisterEntityDialogState
|
||||
>;
|
||||
act(() => {
|
||||
rendered = renderHook(() => useUnregisterEntityDialogState(entity), {
|
||||
wrapper: Wrapper,
|
||||
|
||||
@@ -128,7 +128,10 @@ function EntityLabels(props: { entity: Entity }) {
|
||||
/>
|
||||
)}
|
||||
{entity.spec?.lifecycle && (
|
||||
<HeaderLabel label="Lifecycle" value={entity.spec.lifecycle} />
|
||||
<HeaderLabel
|
||||
label="Lifecycle"
|
||||
value={entity.spec.lifecycle?.toString()}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
|
||||
@@ -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 (
|
||||
<Alert severity="warning">No code coverage found for ${entity}</Alert>
|
||||
<Alert severity="warning">
|
||||
No code coverage found for {humanizeEntityRef(entity)}
|
||||
</Alert>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -33,8 +33,9 @@ const items = [
|
||||
},
|
||||
];
|
||||
|
||||
const tooltipItems = () =>
|
||||
items.map(item => <BarChartTooltipItem key={item.label} item={item} />);
|
||||
const tooltipItems = items.map(item => (
|
||||
<BarChartTooltipItem key={item.label} item={item} />
|
||||
));
|
||||
|
||||
describe('<BarChartTooltip/>', () => {
|
||||
it('formats label and tooltip item text correctly', async () => {
|
||||
|
||||
@@ -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('<ProjectSelect />', () => {
|
||||
let Component: React.ReactNode;
|
||||
let Component: ComponentType;
|
||||
beforeEach(() => {
|
||||
Component = () => (
|
||||
<MockFilterProvider>
|
||||
|
||||
@@ -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<boolean>(
|
||||
LIGHTHOUSE_INTRO_LOCAL_STORAGE,
|
||||
);
|
||||
const [dismissed, setDismissed] = useState(dismissedStored);
|
||||
|
||||
const query = useQuery();
|
||||
|
||||
@@ -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);
|
||||
},
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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<any>) => {
|
||||
if (e.errors.length === 0) handleNext();
|
||||
}}
|
||||
{...formProps}
|
||||
|
||||
@@ -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) => (
|
||||
<MenuItem key={idx} value={option as any}>
|
||||
@@ -158,7 +160,9 @@ export const CustomFieldExplorer = ({
|
||||
noHtml5Validate
|
||||
formData={fieldFormState}
|
||||
formContext={{ fieldFormState }}
|
||||
onSubmit={e => handleFieldConfigChange(e.formData)}
|
||||
onSubmit={(e: ISubmitEvent<any>) =>
|
||||
handleFieldConfigChange(e.formData)
|
||||
}
|
||||
schema={selectedField.schema?.uiOptions || {}}
|
||||
>
|
||||
<Button
|
||||
|
||||
@@ -164,7 +164,8 @@ export const TemplateFormPreviewer = ({
|
||||
);
|
||||
|
||||
const handleSelectChange = useCallback(
|
||||
selected => {
|
||||
// TODO(Rugvip): Afaik this should be Entity, but didn't want to make runtime changes while fixing types
|
||||
(selected: any) => {
|
||||
setSelectedTemplate(selected);
|
||||
setTemplateYaml(yaml.stringify(selected.spec));
|
||||
},
|
||||
|
||||
@@ -102,7 +102,7 @@ export const CustomFieldExplorer = ({
|
||||
}, [customFieldExtensions]);
|
||||
|
||||
const handleSelectionChange = useCallback(
|
||||
selection => {
|
||||
(selection: NextFieldExtensionOptions) => {
|
||||
setSelectedField(selection);
|
||||
setFieldFormState({});
|
||||
},
|
||||
@@ -110,7 +110,7 @@ export const CustomFieldExplorer = ({
|
||||
);
|
||||
|
||||
const handleFieldConfigChange = useCallback(
|
||||
state => {
|
||||
(state: {}) => {
|
||||
setFieldFormState(state);
|
||||
// Force TemplateEditorForm to re-render since some fields
|
||||
// may not be responsive to ui:option changes
|
||||
@@ -130,7 +130,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 NextFieldExtensionOptions)
|
||||
}
|
||||
>
|
||||
{fieldOptions.map((option, idx) => (
|
||||
<MenuItem key={idx} value={option as any}>
|
||||
|
||||
@@ -161,7 +161,8 @@ export const TemplateFormPreviewer = ({
|
||||
);
|
||||
|
||||
const handleSelectChange = useCallback(
|
||||
selected => {
|
||||
// TODO(Rugvip): Afaik this should be Entity, but didn't want to make runtime changes while fixing types
|
||||
(selected: any) => {
|
||||
setSelectedTemplate(selected);
|
||||
setTemplateYaml(yaml.stringify(selected.spec));
|
||||
},
|
||||
|
||||
@@ -29,7 +29,7 @@ const SearchContextFilterSpy = ({ name }: { name: string }) => {
|
||||
const value = filters[name];
|
||||
return (
|
||||
<span data-testid={`${name}-filter-spy`}>
|
||||
{Array.isArray(value) ? value.join(',') : value}
|
||||
{Array.isArray(value) ? value.join(',') : value?.toString()}
|
||||
</span>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -193,7 +193,7 @@ export const SearchResultGroupTextFilterField = (
|
||||
contentEditable
|
||||
suppressContentEditableWarning
|
||||
>
|
||||
{value}
|
||||
{value?.toString()}
|
||||
</Typography>
|
||||
</SearchResultGroupFilterFieldLayout>
|
||||
);
|
||||
@@ -377,7 +377,7 @@ export function SearchResultGroupLayout<FilterOption>(
|
||||
filterOptions,
|
||||
renderFilterOption = filterOption => (
|
||||
<MenuItem key={String(filterOption)} value={String(filterOption)}>
|
||||
{filterOption}
|
||||
{String(filterOption)}
|
||||
</MenuItem>
|
||||
),
|
||||
filterFields,
|
||||
|
||||
@@ -198,22 +198,24 @@ export const SearchPage = createPageExtension({
|
||||
<Grid item xs>
|
||||
<SearchPagination />
|
||||
<SearchResults>
|
||||
{({ results }) =>
|
||||
results.map((result, index) => {
|
||||
const { noTrack } = config;
|
||||
const { document, ...rest } = result;
|
||||
const SearchResultListItem =
|
||||
getResultItemComponent(result);
|
||||
return (
|
||||
<SearchResultListItem
|
||||
{...rest}
|
||||
key={index}
|
||||
result={document}
|
||||
noTrack={noTrack}
|
||||
/>
|
||||
);
|
||||
})
|
||||
}
|
||||
{({ results }) => (
|
||||
<>
|
||||
{results.map((result, index) => {
|
||||
const { noTrack } = config;
|
||||
const { document, ...rest } = result;
|
||||
const SearchResultListItem =
|
||||
getResultItemComponent(result);
|
||||
return (
|
||||
<SearchResultListItem
|
||||
{...rest}
|
||||
key={index}
|
||||
result={document}
|
||||
noTrack={noTrack}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
</>
|
||||
)}
|
||||
</SearchResults>
|
||||
<SearchResultPager />
|
||||
</Grid>
|
||||
|
||||
@@ -57,18 +57,11 @@ export const HomePageSearchBar = (props: HomePageSearchBarProps) => {
|
||||
handleSearch({ query: ref.current?.value ?? '' });
|
||||
}, [handleSearch]);
|
||||
|
||||
const handleChange = useCallback(
|
||||
value => {
|
||||
setQuery(value);
|
||||
},
|
||||
[setQuery],
|
||||
);
|
||||
|
||||
return (
|
||||
<SearchBarBase
|
||||
value={query}
|
||||
onSubmit={handleSubmit}
|
||||
onChange={handleChange}
|
||||
onChange={setQuery}
|
||||
inputProps={{ ref }}
|
||||
InputProps={{
|
||||
...props.InputProps,
|
||||
|
||||
@@ -74,12 +74,15 @@ const SentryIssuesTable = (props: SentryIssuesTableProps) => {
|
||||
const { sentryIssues, statsFor, tableOptions } = props;
|
||||
const [selected, setSelected] = useState(ONE_DAY_IN_MILLIS);
|
||||
|
||||
const filterByDate = useCallback((issue, selectedFilter) => {
|
||||
return (
|
||||
DateTime.fromISO(issue.lastSeen) >
|
||||
DateTime.now().minus(Duration.fromMillis(selectedFilter))
|
||||
);
|
||||
}, []);
|
||||
const filterByDate = useCallback(
|
||||
(issue: SentryIssue, selectedFilter: number) => {
|
||||
return (
|
||||
DateTime.fromISO(issue.lastSeen) >
|
||||
DateTime.now().minus(Duration.fromMillis(selectedFilter))
|
||||
);
|
||||
},
|
||||
[],
|
||||
);
|
||||
const [filteredIssues, setFilteredIssues] = useState(
|
||||
sentryIssues.filter(i => filterByDate(i, selected)),
|
||||
);
|
||||
|
||||
+3
-1
@@ -133,7 +133,9 @@ export const TechDocsReaderPageHeader = (
|
||||
}
|
||||
/>
|
||||
)}
|
||||
{lifecycle ? <HeaderLabel label="Lifecycle" value={lifecycle} /> : null}
|
||||
{lifecycle ? (
|
||||
<HeaderLabel label="Lifecycle" value={String(lifecycle)} />
|
||||
) : null}
|
||||
{locationMetadata &&
|
||||
locationMetadata.type !== 'dir' &&
|
||||
locationMetadata.type !== 'file' ? (
|
||||
|
||||
@@ -8516,6 +8516,7 @@ __metadata:
|
||||
"@backstage/plugin-permission-common": "workspace:^"
|
||||
"@backstage/plugin-permission-react": "workspace:^"
|
||||
"@backstage/plugin-playlist-common": "workspace:^"
|
||||
"@backstage/plugin-search-common": "workspace:^"
|
||||
"@backstage/plugin-search-react": "workspace:^"
|
||||
"@backstage/test-utils": "workspace:^"
|
||||
"@backstage/theme": "workspace:^"
|
||||
|
||||
Reference in New Issue
Block a user