diff --git a/plugins/catalog-react/src/alpha/blueprints/EntityCardBlueprint.ts b/plugins/catalog-react/src/alpha/blueprints/EntityCardBlueprint.ts index d13fd2f2c0..82ff2df44a 100644 --- a/plugins/catalog-react/src/alpha/blueprints/EntityCardBlueprint.ts +++ b/plugins/catalog-react/src/alpha/blueprints/EntityCardBlueprint.ts @@ -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; 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); } }, }); diff --git a/plugins/catalog-react/src/alpha/blueprints/EntityContentBlueprint.ts b/plugins/catalog-react/src/alpha/blueprints/EntityContentBlueprint.ts index 36bca99ecc..54cd476a90 100644 --- a/plugins/catalog-react/src/alpha/blueprints/EntityContentBlueprint.ts +++ b/plugins/catalog-react/src/alpha/blueprints/EntityContentBlueprint.ts @@ -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); } }, }); diff --git a/plugins/catalog-react/src/alpha/blueprints/extensionData.tsx b/plugins/catalog-react/src/alpha/blueprints/extensionData.tsx new file mode 100644 index 0000000000..09aac809cb --- /dev/null +++ b/plugins/catalog-react/src/alpha/blueprints/extensionData.tsx @@ -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().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().with({ + id: 'catalog.entity-filter-expression', + }); diff --git a/plugins/catalog-react/src/alpha/extensions.tsx b/plugins/catalog-react/src/alpha/extensions.tsx deleted file mode 100644 index e527edc355..0000000000 --- a/plugins/catalog-react/src/alpha/extensions.tsx +++ /dev/null @@ -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().with({ - id: 'catalog.entity-content-title', - }), - entityFilterFunction: createExtensionDataRef< - (entity: Entity) => boolean - >().with({ id: 'catalog.entity-filter-function' }), - entityFilterExpression: createExtensionDataRef().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; - filter?: - | typeof catalogExtensionData.entityFilterFunction.T - | typeof catalogExtensionData.entityFilterExpression.T; - loader: (options: { - config: TConfig; - inputs: Expand>; - }) => Promise; -}) { - const configSchema = - 'configSchema' in options - ? options.configSchema - : (createSchemaFromZod(z => - z.object({ - filter: z.string().optional(), - }), - ) as PortableSchema); - 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: ( - - - - ), - ...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>; - }) => Promise; -}) { - 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: ( - - - - ), - ...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 {}; -} diff --git a/plugins/catalog-react/src/alpha/index.ts b/plugins/catalog-react/src/alpha/index.ts index 3930fbde87..a46fec0615 100644 --- a/plugins/catalog-react/src/alpha/index.ts +++ b/plugins/catalog-react/src/alpha/index.ts @@ -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';