@@ -29,7 +29,7 @@
|
||||
"sideEffects": false,
|
||||
"exports": {
|
||||
".": "./src/index.ts",
|
||||
"./alpha": "./src/alpha.tsx",
|
||||
"./alpha": "./src/alpha/index.ts",
|
||||
"./package.json": "./package.json"
|
||||
},
|
||||
"main": "src/index.ts",
|
||||
@@ -37,7 +37,7 @@
|
||||
"typesVersions": {
|
||||
"*": {
|
||||
"alpha": [
|
||||
"src/alpha.tsx"
|
||||
"src/alpha/index.ts"
|
||||
],
|
||||
"package.json": [
|
||||
"package.json"
|
||||
@@ -85,6 +85,7 @@
|
||||
"devDependencies": {
|
||||
"@backstage/cli": "workspace:^",
|
||||
"@backstage/core-app-api": "workspace:^",
|
||||
"@backstage/frontend-test-utils": "workspace:^",
|
||||
"@backstage/plugin-catalog-common": "workspace:^",
|
||||
"@backstage/plugin-scaffolder-common": "workspace:^",
|
||||
"@backstage/test-utils": "workspace:^",
|
||||
|
||||
@@ -0,0 +1,178 @@
|
||||
/*
|
||||
* Copyright 2024 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 { EntityCardBlueprint } from './EntityCardBlueprint';
|
||||
import {
|
||||
coreExtensionData,
|
||||
createExtension,
|
||||
createExtensionInput,
|
||||
} from '@backstage/frontend-plugin-api';
|
||||
import { createExtensionTester } from '@backstage/frontend-test-utils';
|
||||
import { waitFor, screen } from '@testing-library/react';
|
||||
import { Entity } from '@backstage/catalog-model';
|
||||
|
||||
describe('EntityCardBlueprint', () => {
|
||||
it('should return an extension with sensible defaults', () => {
|
||||
const extension = EntityCardBlueprint.make({
|
||||
name: 'test',
|
||||
params: {
|
||||
filter: 'has:labels',
|
||||
loader: async () => <div>im a card</div>,
|
||||
},
|
||||
});
|
||||
|
||||
expect(extension).toMatchInlineSnapshot(`
|
||||
{
|
||||
"$$type": "@backstage/ExtensionDefinition",
|
||||
"attachTo": {
|
||||
"id": "entity-content:catalog/overview",
|
||||
"input": "cards",
|
||||
},
|
||||
"configSchema": {
|
||||
"parse": [Function],
|
||||
"schema": {
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"filter": {
|
||||
"type": "string",
|
||||
},
|
||||
},
|
||||
"type": "object",
|
||||
},
|
||||
},
|
||||
"disabled": false,
|
||||
"factory": [Function],
|
||||
"inputs": {},
|
||||
"kind": "entity-card",
|
||||
"name": "test",
|
||||
"namespace": undefined,
|
||||
"output": [
|
||||
[Function],
|
||||
{
|
||||
"$$type": "@backstage/ExtensionDataRef",
|
||||
"config": {
|
||||
"optional": true,
|
||||
},
|
||||
"id": "catalog.entity-filter-function",
|
||||
"optional": [Function],
|
||||
"toString": [Function],
|
||||
},
|
||||
{
|
||||
"$$type": "@backstage/ExtensionDataRef",
|
||||
"config": {
|
||||
"optional": true,
|
||||
},
|
||||
"id": "catalog.entity-filter-expression",
|
||||
"optional": [Function],
|
||||
"toString": [Function],
|
||||
},
|
||||
],
|
||||
"override": [Function],
|
||||
"toString": [Function],
|
||||
"version": "v2",
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
it('should output the correct filter output', () => {
|
||||
const mockFilter = (_entity: Entity) => true;
|
||||
|
||||
expect(
|
||||
createExtensionTester(
|
||||
EntityCardBlueprint.make({
|
||||
name: 'test',
|
||||
params: {
|
||||
loader: async () => <div>Test!</div>,
|
||||
filter: 'test',
|
||||
},
|
||||
}),
|
||||
).data(EntityCardBlueprint.dataRefs.filterExpression),
|
||||
).toBe('test');
|
||||
|
||||
expect(
|
||||
createExtensionTester(
|
||||
EntityCardBlueprint.make({
|
||||
name: 'test',
|
||||
params: {
|
||||
loader: async () => <div>Test!</div>,
|
||||
},
|
||||
}),
|
||||
{ config: { filter: 'test' } },
|
||||
).data(EntityCardBlueprint.dataRefs.filterExpression),
|
||||
).toBe('test');
|
||||
|
||||
expect(
|
||||
createExtensionTester(
|
||||
EntityCardBlueprint.make({
|
||||
name: 'test',
|
||||
params: {
|
||||
filter: mockFilter,
|
||||
loader: async () => <div>Test!</div>,
|
||||
},
|
||||
}),
|
||||
).data(EntityCardBlueprint.dataRefs.filterFunction),
|
||||
).toBe(mockFilter);
|
||||
});
|
||||
|
||||
it('should allow overriding config and inputs', async () => {
|
||||
const extension = EntityCardBlueprint.makeWithOverrides({
|
||||
name: 'test',
|
||||
inputs: {
|
||||
mock: createExtensionInput([coreExtensionData.reactElement]),
|
||||
},
|
||||
config: {
|
||||
schema: {
|
||||
mock: z => z.string(),
|
||||
},
|
||||
},
|
||||
factory(originalFactory, { inputs, config }) {
|
||||
return originalFactory({
|
||||
loader: async () => (
|
||||
<div data-testid="test">
|
||||
config: {config.mock}
|
||||
<div data-testid="contents">
|
||||
{inputs.mock.map((i, k) => (
|
||||
<div key={k}>{i.get(coreExtensionData.reactElement)}</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
),
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
const mockExtension = createExtension({
|
||||
attachTo: { id: 'entity-card:test', input: 'mock' },
|
||||
output: [coreExtensionData.reactElement],
|
||||
factory() {
|
||||
return [coreExtensionData.reactElement(<div>im a mock</div>)];
|
||||
},
|
||||
});
|
||||
|
||||
createExtensionTester(extension, { config: { mock: 'mock test config' } })
|
||||
.add(mockExtension)
|
||||
.render();
|
||||
|
||||
await waitFor(() => {
|
||||
expect(screen.getByTestId('test')).toBeInTheDocument();
|
||||
expect(screen.getByTestId('test')).toHaveTextContent(
|
||||
'config: mock test config',
|
||||
);
|
||||
expect(screen.getByTestId('contents')).toHaveTextContent('im a mock');
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* Copyright 2024 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, { lazy } from 'react';
|
||||
import {
|
||||
ExtensionBoundary,
|
||||
coreExtensionData,
|
||||
createExtensionBlueprint,
|
||||
} from '@backstage/frontend-plugin-api';
|
||||
import { catalogExtensionData } from '../extensions';
|
||||
|
||||
/**
|
||||
* @alpha
|
||||
* A blueprint for creating cards for the entity pages in the catalog.
|
||||
*/
|
||||
export const EntityCardBlueprint = createExtensionBlueprint({
|
||||
kind: 'entity-card',
|
||||
attachTo: { id: 'entity-content:catalog/overview', input: 'cards' },
|
||||
output: [
|
||||
coreExtensionData.reactElement,
|
||||
catalogExtensionData.entityFilterFunction.optional(),
|
||||
catalogExtensionData.entityFilterExpression.optional(),
|
||||
],
|
||||
dataRefs: {
|
||||
filterFunction: catalogExtensionData.entityFilterFunction,
|
||||
filterExpression: catalogExtensionData.entityFilterExpression,
|
||||
},
|
||||
config: {
|
||||
schema: {
|
||||
filter: z => z.string().optional(),
|
||||
},
|
||||
},
|
||||
*factory(
|
||||
{
|
||||
loader,
|
||||
filter,
|
||||
}: {
|
||||
loader: () => Promise<JSX.Element>;
|
||||
filter?:
|
||||
| typeof catalogExtensionData.entityFilterFunction.T
|
||||
| typeof catalogExtensionData.entityFilterExpression.T;
|
||||
},
|
||||
{ node, config },
|
||||
) {
|
||||
const ExtensionComponent = lazy(() =>
|
||||
loader().then(element => ({ default: () => element })),
|
||||
);
|
||||
|
||||
yield coreExtensionData.reactElement(
|
||||
<ExtensionBoundary node={node}>
|
||||
<ExtensionComponent />
|
||||
</ExtensionBoundary>,
|
||||
);
|
||||
|
||||
if (config.filter) {
|
||||
yield catalogExtensionData.entityFilterExpression(config.filter);
|
||||
} else if (typeof filter === 'string') {
|
||||
yield catalogExtensionData.entityFilterExpression(filter);
|
||||
} else if (typeof filter === 'function') {
|
||||
yield catalogExtensionData.entityFilterFunction(filter);
|
||||
}
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,226 @@
|
||||
/*
|
||||
* Copyright 2024 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 { EntityContentBlueprint } from './EntityContentBlueprint';
|
||||
import { createExtensionTester } from '@backstage/frontend-test-utils';
|
||||
import {
|
||||
coreExtensionData,
|
||||
createExtension,
|
||||
createExtensionInput,
|
||||
createRouteRef,
|
||||
} from '@backstage/frontend-plugin-api';
|
||||
import { Entity } from '@backstage/catalog-model';
|
||||
import { waitFor, screen } from '@testing-library/react';
|
||||
|
||||
describe('EntityContentBlueprint', () => {
|
||||
it('should return an extension with sane defaults', () => {
|
||||
const extension = EntityContentBlueprint.make({
|
||||
name: 'test',
|
||||
params: {
|
||||
defaultPath: '/test',
|
||||
defaultTitle: 'Test',
|
||||
loader: async () => <div>Test!</div>,
|
||||
},
|
||||
});
|
||||
|
||||
expect(extension).toMatchInlineSnapshot(`
|
||||
{
|
||||
"$$type": "@backstage/ExtensionDefinition",
|
||||
"attachTo": {
|
||||
"id": "page:catalog/entity",
|
||||
"input": "contents",
|
||||
},
|
||||
"configSchema": {
|
||||
"parse": [Function],
|
||||
"schema": {
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"filter": {
|
||||
"type": "string",
|
||||
},
|
||||
"path": {
|
||||
"type": "string",
|
||||
},
|
||||
"title": {
|
||||
"type": "string",
|
||||
},
|
||||
},
|
||||
"type": "object",
|
||||
},
|
||||
},
|
||||
"disabled": false,
|
||||
"factory": [Function],
|
||||
"inputs": {},
|
||||
"kind": "entity-content",
|
||||
"name": "test",
|
||||
"namespace": undefined,
|
||||
"output": [
|
||||
[Function],
|
||||
[Function],
|
||||
[Function],
|
||||
{
|
||||
"$$type": "@backstage/ExtensionDataRef",
|
||||
"config": {
|
||||
"optional": true,
|
||||
},
|
||||
"id": "core.routing.ref",
|
||||
"optional": [Function],
|
||||
"toString": [Function],
|
||||
},
|
||||
{
|
||||
"$$type": "@backstage/ExtensionDataRef",
|
||||
"config": {
|
||||
"optional": true,
|
||||
},
|
||||
"id": "catalog.entity-filter-function",
|
||||
"optional": [Function],
|
||||
"toString": [Function],
|
||||
},
|
||||
{
|
||||
"$$type": "@backstage/ExtensionDataRef",
|
||||
"config": {
|
||||
"optional": true,
|
||||
},
|
||||
"id": "catalog.entity-filter-expression",
|
||||
"optional": [Function],
|
||||
"toString": [Function],
|
||||
},
|
||||
],
|
||||
"override": [Function],
|
||||
"toString": [Function],
|
||||
"version": "v2",
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
it('should emit the correct defaults', () => {
|
||||
const mockRouteRef = createRouteRef();
|
||||
const extension = EntityContentBlueprint.make({
|
||||
name: 'test',
|
||||
params: {
|
||||
defaultPath: '/test',
|
||||
defaultTitle: 'Test',
|
||||
routeRef: mockRouteRef,
|
||||
loader: async () => <div>Test!</div>,
|
||||
},
|
||||
});
|
||||
|
||||
const tester = createExtensionTester(extension);
|
||||
|
||||
// todo(blam): route paths are always set to / in the createExtensionTester. This will work eventually.
|
||||
// expect(tester.data(coreExtensionData.routePath)).toBe('/test');
|
||||
|
||||
expect(tester.data(coreExtensionData.routeRef)).toBe(mockRouteRef);
|
||||
expect(tester.data(EntityContentBlueprint.dataRefs.title)).toBe('Test');
|
||||
});
|
||||
|
||||
it('should emit the correct filter output', () => {
|
||||
const mockFilter = (_entity: Entity) => true;
|
||||
|
||||
expect(
|
||||
createExtensionTester(
|
||||
EntityContentBlueprint.make({
|
||||
name: 'test',
|
||||
params: {
|
||||
defaultPath: '/test',
|
||||
defaultTitle: 'Test',
|
||||
loader: async () => <div>Test!</div>,
|
||||
filter: 'test',
|
||||
},
|
||||
}),
|
||||
).data(EntityContentBlueprint.dataRefs.filterExpression),
|
||||
).toBe('test');
|
||||
|
||||
expect(
|
||||
createExtensionTester(
|
||||
EntityContentBlueprint.make({
|
||||
name: 'test',
|
||||
params: {
|
||||
defaultPath: '/test',
|
||||
defaultTitle: 'Test',
|
||||
loader: async () => <div>Test!</div>,
|
||||
},
|
||||
}),
|
||||
{ config: { filter: 'test' } },
|
||||
).data(EntityContentBlueprint.dataRefs.filterExpression),
|
||||
).toBe('test');
|
||||
|
||||
expect(
|
||||
createExtensionTester(
|
||||
EntityContentBlueprint.make({
|
||||
name: 'test',
|
||||
params: {
|
||||
defaultPath: '/test',
|
||||
defaultTitle: 'Test',
|
||||
filter: mockFilter,
|
||||
loader: async () => <div>Test!</div>,
|
||||
},
|
||||
}),
|
||||
).data(EntityContentBlueprint.dataRefs.filterFunction),
|
||||
).toBe(mockFilter);
|
||||
});
|
||||
|
||||
it('should allow overriding config and inputs', async () => {
|
||||
const extension = EntityContentBlueprint.makeWithOverrides({
|
||||
name: 'test',
|
||||
inputs: {
|
||||
mock: createExtensionInput([coreExtensionData.reactElement]),
|
||||
},
|
||||
config: {
|
||||
schema: {
|
||||
mock: z => z.string(),
|
||||
},
|
||||
},
|
||||
factory(originalFactory, { inputs, config }) {
|
||||
return originalFactory({
|
||||
defaultPath: '/test',
|
||||
defaultTitle: 'Test',
|
||||
loader: async () => (
|
||||
<div data-testid="test">
|
||||
config: {config.mock}
|
||||
<div data-testid="contents">
|
||||
{inputs.mock.map((i, k) => (
|
||||
<div key={k}>{i.get(coreExtensionData.reactElement)}</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
),
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
const mockExtension = createExtension({
|
||||
attachTo: { id: 'entity-content:test', input: 'mock' },
|
||||
output: [coreExtensionData.reactElement],
|
||||
factory() {
|
||||
return [coreExtensionData.reactElement(<div>im a mock</div>)];
|
||||
},
|
||||
});
|
||||
|
||||
createExtensionTester(extension, { config: { mock: 'mock test config' } })
|
||||
.add(mockExtension)
|
||||
.render();
|
||||
|
||||
await waitFor(() => {
|
||||
expect(screen.getByTestId('test')).toBeInTheDocument();
|
||||
expect(screen.getByTestId('test')).toHaveTextContent(
|
||||
'config: mock test config',
|
||||
);
|
||||
expect(screen.getByTestId('contents')).toHaveTextContent('im a mock');
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,99 @@
|
||||
/*
|
||||
* Copyright 2024 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, { lazy } from 'react';
|
||||
import {
|
||||
coreExtensionData,
|
||||
createExtensionBlueprint,
|
||||
ExtensionBoundary,
|
||||
RouteRef,
|
||||
} from '@backstage/frontend-plugin-api';
|
||||
import { catalogExtensionData } from '../extensions';
|
||||
|
||||
/**
|
||||
* @alpha
|
||||
* Creates an EntityContent extension.
|
||||
*/
|
||||
export const EntityContentBlueprint = createExtensionBlueprint({
|
||||
kind: 'entity-content',
|
||||
attachTo: { id: 'page:catalog/entity', input: 'contents' },
|
||||
output: [
|
||||
coreExtensionData.reactElement,
|
||||
coreExtensionData.routePath,
|
||||
catalogExtensionData.entityContentTitle,
|
||||
coreExtensionData.routeRef.optional(),
|
||||
catalogExtensionData.entityFilterFunction.optional(),
|
||||
catalogExtensionData.entityFilterExpression.optional(),
|
||||
],
|
||||
dataRefs: {
|
||||
title: catalogExtensionData.entityContentTitle,
|
||||
filterFunction: catalogExtensionData.entityFilterFunction,
|
||||
filterExpression: catalogExtensionData.entityFilterExpression,
|
||||
},
|
||||
config: {
|
||||
schema: {
|
||||
path: z => z.string().optional(),
|
||||
title: z => z.string().optional(),
|
||||
filter: z => z.string().optional(),
|
||||
},
|
||||
},
|
||||
*factory(
|
||||
{
|
||||
loader,
|
||||
defaultPath,
|
||||
defaultTitle,
|
||||
filter,
|
||||
routeRef,
|
||||
}: {
|
||||
loader: () => Promise<JSX.Element>;
|
||||
defaultPath: string;
|
||||
defaultTitle: string;
|
||||
routeRef?: RouteRef;
|
||||
filter?:
|
||||
| typeof catalogExtensionData.entityFilterFunction.T
|
||||
| typeof catalogExtensionData.entityFilterExpression.T;
|
||||
},
|
||||
{ node, config },
|
||||
) {
|
||||
const path = config.path ?? defaultPath;
|
||||
const title = config.title ?? defaultTitle;
|
||||
|
||||
const ExtensionComponent = lazy(() =>
|
||||
loader().then(element => ({ default: () => element })),
|
||||
);
|
||||
|
||||
yield coreExtensionData.reactElement(
|
||||
<ExtensionBoundary node={node}>
|
||||
<ExtensionComponent />
|
||||
</ExtensionBoundary>,
|
||||
);
|
||||
|
||||
yield coreExtensionData.routePath(path);
|
||||
|
||||
yield catalogExtensionData.entityContentTitle(title);
|
||||
|
||||
if (routeRef) {
|
||||
yield coreExtensionData.routeRef(routeRef);
|
||||
}
|
||||
|
||||
if (config.filter) {
|
||||
yield catalogExtensionData.entityFilterExpression(config.filter);
|
||||
} else if (typeof filter === 'string') {
|
||||
yield catalogExtensionData.entityFilterExpression(filter);
|
||||
} else if (typeof filter === 'function') {
|
||||
yield catalogExtensionData.entityFilterFunction(filter);
|
||||
}
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,17 @@
|
||||
/*
|
||||
* Copyright 2024 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.
|
||||
*/
|
||||
export { EntityCardBlueprint } from './EntityCardBlueprint';
|
||||
export { EntityContentBlueprint } from './EntityContentBlueprint';
|
||||
+16
-7
@@ -28,13 +28,16 @@ import {
|
||||
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';
|
||||
import { Expand } from '../../../../packages/frontend-plugin-api/src/types';
|
||||
|
||||
export { useEntityPermission } from './hooks/useEntityPermission';
|
||||
export { isOwnerOf } from './utils';
|
||||
export * from './translation';
|
||||
export { useEntityPermission } from '../hooks/useEntityPermission';
|
||||
export { isOwnerOf } from '../utils';
|
||||
export * from '../translation';
|
||||
|
||||
/** @alpha */
|
||||
/**
|
||||
* @alpha
|
||||
* @deprecated use `dataRefs` on the blueprints instead
|
||||
*/
|
||||
export const catalogExtensionData = {
|
||||
entityContentTitle: createExtensionDataRef<string>().with({
|
||||
id: 'catalog.entity-content-title',
|
||||
@@ -48,7 +51,10 @@ export const catalogExtensionData = {
|
||||
};
|
||||
|
||||
// TODO: Figure out how to merge with provided config schema
|
||||
/** @alpha */
|
||||
/**
|
||||
* @alpha
|
||||
* @deprecated use {@link EntityCardBlueprint} instead
|
||||
*/
|
||||
export function createEntityCardExtension<
|
||||
TConfig extends { filter?: string },
|
||||
TInputs extends AnyExtensionInputMap,
|
||||
@@ -110,7 +116,10 @@ export function createEntityCardExtension<
|
||||
});
|
||||
}
|
||||
|
||||
/** @alpha */
|
||||
/**
|
||||
* @alpha
|
||||
* @deprecated use {@link EntityContentBlueprint} instead
|
||||
*/
|
||||
export function createEntityContentExtension<
|
||||
TInputs extends AnyExtensionInputMap,
|
||||
>(options: {
|
||||
@@ -0,0 +1,17 @@
|
||||
/*
|
||||
* Copyright 2024 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.
|
||||
*/
|
||||
export * from './blueprints';
|
||||
export * from './extensions';
|
||||
@@ -15,3 +15,18 @@
|
||||
*/
|
||||
|
||||
import '@testing-library/jest-dom';
|
||||
|
||||
// eslint-disable-next-line no-console
|
||||
const originalConsoleWarn = console.warn;
|
||||
// eslint-disable-next-line no-console
|
||||
console.warn = (...args: any[]) => {
|
||||
const message = args[0];
|
||||
if (
|
||||
typeof message === 'string' &&
|
||||
(message.includes('CSSOM.parse is not a function') ||
|
||||
message.includes('[JSS]'))
|
||||
) {
|
||||
return;
|
||||
}
|
||||
originalConsoleWarn(...args);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user