catalog-react: remove deprecated extension creators

Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
This commit is contained in:
Patrik Oldsberg
2024-08-19 15:11:35 +02:00
parent 44ea4b9571
commit bf92da98bc
5 changed files with 67 additions and 237 deletions
@@ -19,7 +19,10 @@ import {
coreExtensionData,
createExtensionBlueprint,
} from '@backstage/frontend-plugin-api';
import { catalogExtensionData } from '../extensions';
import {
entityFilterFunctionDataRef,
entityFilterExpressionDataRef,
} from './extensionData';
/**
* @alpha
@@ -30,12 +33,12 @@ export const EntityCardBlueprint = createExtensionBlueprint({
attachTo: { id: 'entity-content:catalog/overview', input: 'cards' },
output: [
coreExtensionData.reactElement,
catalogExtensionData.entityFilterFunction.optional(),
catalogExtensionData.entityFilterExpression.optional(),
entityFilterFunctionDataRef.optional(),
entityFilterExpressionDataRef.optional(),
],
dataRefs: {
filterFunction: catalogExtensionData.entityFilterFunction,
filterExpression: catalogExtensionData.entityFilterExpression,
filterFunction: entityFilterFunctionDataRef,
filterExpression: entityFilterExpressionDataRef,
},
config: {
schema: {
@@ -49,19 +52,19 @@ export const EntityCardBlueprint = createExtensionBlueprint({
}: {
loader: () => Promise<JSX.Element>;
filter?:
| typeof catalogExtensionData.entityFilterFunction.T
| typeof catalogExtensionData.entityFilterExpression.T;
| typeof entityFilterFunctionDataRef.T
| typeof entityFilterExpressionDataRef.T;
},
{ node, config },
) {
yield coreExtensionData.reactElement(ExtensionBoundary.lazy(node, loader));
if (config.filter) {
yield catalogExtensionData.entityFilterExpression(config.filter);
yield entityFilterExpressionDataRef(config.filter);
} else if (typeof filter === 'string') {
yield catalogExtensionData.entityFilterExpression(filter);
yield entityFilterExpressionDataRef(filter);
} else if (typeof filter === 'function') {
yield catalogExtensionData.entityFilterFunction(filter);
yield entityFilterFunctionDataRef(filter);
}
},
});
@@ -20,7 +20,11 @@ import {
ExtensionBoundary,
RouteRef,
} from '@backstage/frontend-plugin-api';
import { catalogExtensionData } from '../extensions';
import {
entityContentTitleDataRef,
entityFilterFunctionDataRef,
entityFilterExpressionDataRef,
} from './extensionData';
/**
* @alpha
@@ -32,15 +36,15 @@ export const EntityContentBlueprint = createExtensionBlueprint({
output: [
coreExtensionData.reactElement,
coreExtensionData.routePath,
catalogExtensionData.entityContentTitle,
entityContentTitleDataRef,
coreExtensionData.routeRef.optional(),
catalogExtensionData.entityFilterFunction.optional(),
catalogExtensionData.entityFilterExpression.optional(),
entityFilterFunctionDataRef.optional(),
entityFilterExpressionDataRef.optional(),
],
dataRefs: {
title: catalogExtensionData.entityContentTitle,
filterFunction: catalogExtensionData.entityFilterFunction,
filterExpression: catalogExtensionData.entityFilterExpression,
title: entityContentTitleDataRef,
filterFunction: entityFilterFunctionDataRef,
filterExpression: entityFilterExpressionDataRef,
},
config: {
schema: {
@@ -62,8 +66,8 @@ export const EntityContentBlueprint = createExtensionBlueprint({
defaultTitle: string;
routeRef?: RouteRef;
filter?:
| typeof catalogExtensionData.entityFilterFunction.T
| typeof catalogExtensionData.entityFilterExpression.T;
| typeof entityFilterFunctionDataRef.T
| typeof entityFilterExpressionDataRef.T;
},
{ node, config },
) {
@@ -74,18 +78,18 @@ export const EntityContentBlueprint = createExtensionBlueprint({
yield coreExtensionData.routePath(path);
yield catalogExtensionData.entityContentTitle(title);
yield entityContentTitleDataRef(title);
if (routeRef) {
yield coreExtensionData.routeRef(routeRef);
}
if (config.filter) {
yield catalogExtensionData.entityFilterExpression(config.filter);
yield entityFilterExpressionDataRef(config.filter);
} else if (typeof filter === 'string') {
yield catalogExtensionData.entityFilterExpression(filter);
yield entityFilterExpressionDataRef(filter);
} else if (typeof filter === 'function') {
yield catalogExtensionData.entityFilterFunction(filter);
yield entityFilterFunctionDataRef(filter);
}
},
});
@@ -0,0 +1,34 @@
/*
* Copyright 2023 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 { Entity } from '@backstage/catalog-model';
import { createExtensionDataRef } from '@backstage/frontend-plugin-api';
/** @internal */
export const entityContentTitleDataRef = createExtensionDataRef<string>().with({
id: 'catalog.entity-content-title',
});
/** @internal */
export const entityFilterFunctionDataRef = createExtensionDataRef<
(entity: Entity) => boolean
>().with({ id: 'catalog.entity-filter-function' });
/** @internal */
export const entityFilterExpressionDataRef =
createExtensionDataRef<string>().with({
id: 'catalog.entity-filter-expression',
});
@@ -1,213 +0,0 @@
/*
* Copyright 2023 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 {
AnyExtensionInputMap,
ExtensionBoundary,
PortableSchema,
ResolvedExtensionInputs,
RouteRef,
coreExtensionData,
createExtension,
createExtensionDataRef,
createSchemaFromZod,
} from '@backstage/frontend-plugin-api';
import React, { lazy } from 'react';
import { Entity } from '@backstage/catalog-model';
// eslint-disable-next-line @backstage/no-relative-monorepo-imports
import { Expand } from '../../../../packages/frontend-plugin-api/src/types';
export { useEntityPermission } from '../hooks/useEntityPermission';
export { isOwnerOf } from '../utils';
export * from '../translation';
/**
* @alpha
* @deprecated use `dataRefs` property on either {@link EntityCardBlueprint} or {@link EntityContentBlueprint} instead
*/
export const catalogExtensionData = {
entityContentTitle: createExtensionDataRef<string>().with({
id: 'catalog.entity-content-title',
}),
entityFilterFunction: createExtensionDataRef<
(entity: Entity) => boolean
>().with({ id: 'catalog.entity-filter-function' }),
entityFilterExpression: createExtensionDataRef<string>().with({
id: 'catalog.entity-filter-expression',
}),
};
// TODO: Figure out how to merge with provided config schema
/**
* @alpha
* @deprecated use {@link EntityCardBlueprint} instead
*/
export function createEntityCardExtension<
TConfig extends { filter?: string },
TInputs extends AnyExtensionInputMap,
>(options: {
namespace?: string;
name?: string;
attachTo?: { id: string; input: string };
disabled?: boolean;
inputs?: TInputs;
configSchema?: PortableSchema<TConfig>;
filter?:
| typeof catalogExtensionData.entityFilterFunction.T
| typeof catalogExtensionData.entityFilterExpression.T;
loader: (options: {
config: TConfig;
inputs: Expand<ResolvedExtensionInputs<TInputs>>;
}) => Promise<JSX.Element>;
}) {
const configSchema =
'configSchema' in options
? options.configSchema
: (createSchemaFromZod(z =>
z.object({
filter: z.string().optional(),
}),
) as PortableSchema<TConfig>);
return createExtension({
kind: 'entity-card',
namespace: options.namespace,
name: options.name,
attachTo: options.attachTo ?? {
id: 'entity-content:catalog/overview',
input: 'cards',
},
disabled: options.disabled,
output: {
element: coreExtensionData.reactElement,
filterFunction: catalogExtensionData.entityFilterFunction.optional(),
filterExpression: catalogExtensionData.entityFilterExpression.optional(),
},
inputs: options.inputs,
configSchema,
factory({ config, inputs, node }) {
const ExtensionComponent = lazy(() =>
options
.loader({ inputs, config })
.then(element => ({ default: () => element })),
);
return {
element: (
<ExtensionBoundary node={node}>
<ExtensionComponent />
</ExtensionBoundary>
),
...mergeFilters({ config, options }),
};
},
});
}
/**
* @alpha
* @deprecated use {@link EntityContentBlueprint} instead
*/
export function createEntityContentExtension<
TInputs extends AnyExtensionInputMap,
>(options: {
namespace?: string;
name?: string;
attachTo?: { id: string; input: string };
disabled?: boolean;
inputs?: TInputs;
routeRef?: RouteRef;
defaultPath: string;
defaultTitle: string;
filter?:
| typeof catalogExtensionData.entityFilterFunction.T
| typeof catalogExtensionData.entityFilterExpression.T;
loader: (options: {
inputs: Expand<ResolvedExtensionInputs<TInputs>>;
}) => Promise<JSX.Element>;
}) {
return createExtension({
kind: 'entity-content',
namespace: options.namespace,
name: options.name,
attachTo: options.attachTo ?? {
id: 'page:catalog/entity',
input: 'contents',
},
disabled: options.disabled,
output: {
element: coreExtensionData.reactElement,
path: coreExtensionData.routePath,
routeRef: coreExtensionData.routeRef.optional(),
title: catalogExtensionData.entityContentTitle,
filterFunction: catalogExtensionData.entityFilterFunction.optional(),
filterExpression: catalogExtensionData.entityFilterExpression.optional(),
},
inputs: options.inputs,
configSchema: createSchemaFromZod(z =>
z.object({
path: z.string().default(options.defaultPath),
title: z.string().default(options.defaultTitle),
filter: z.string().optional(),
}),
),
factory({ config, inputs, node }) {
const ExtensionComponent = lazy(() =>
options
.loader({ inputs })
.then(element => ({ default: () => element })),
);
return {
path: config.path,
title: config.title,
routeRef: options.routeRef,
element: (
<ExtensionBoundary node={node}>
<ExtensionComponent />
</ExtensionBoundary>
),
...mergeFilters({ config, options }),
};
},
});
}
/**
* Decides what filter outputs to produce, given some options and config
*/
function mergeFilters(inputs: {
options: {
filter?:
| typeof catalogExtensionData.entityFilterFunction.T
| typeof catalogExtensionData.entityFilterExpression.T;
};
config: {
filter?: string;
};
}): {
filterFunction?: typeof catalogExtensionData.entityFilterFunction.T;
filterExpression?: typeof catalogExtensionData.entityFilterExpression.T;
} {
const { options, config } = inputs;
if (config.filter) {
return { filterExpression: config.filter };
} else if (typeof options.filter === 'string') {
return { filterExpression: options.filter };
} else if (typeof options.filter === 'function') {
return { filterFunction: options.filter };
}
return {};
}
+3 -1
View File
@@ -15,5 +15,7 @@
*/
export * from './blueprints';
export * from './extensions';
export * from './converters';
export { catalogReactTranslationRef } from '../translation';
export { isOwnerOf } from '../utils/isOwnerOf';
export { useEntityPermission } from '../hooks/useEntityPermission';