catalog-react: rename entity card "area" to "type"

Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
This commit is contained in:
Patrik Oldsberg
2025-02-20 21:17:48 +01:00
parent 4b8e2c2509
commit bc1d8815ff
16 changed files with 184 additions and 175 deletions
+4 -4
View File
@@ -7,7 +7,7 @@ Introduces a new `EntityContentLayoutBlueprint` that creates custom entity conte
The layout components receive card elements and can render them as they see fit. Cards is an array of objects with the following properties:
- element: `JSx.Element`;
- area: `"peek" | "info" | "full" | undefined`;
- type: `"peek" | "info" | "full" | undefined`;
### Usage example
@@ -33,7 +33,7 @@ function StickyEntityContentOverviewLayout(props: EntityContentLayoutProps) {
>
<Grid container spacing={3}>
{cards
.filter(card => card.area === 'info')
.filter(card => card.type === 'info')
.map((card, index) => (
<Grid key={index} xs={12} item>
{card.element}
@@ -44,14 +44,14 @@ function StickyEntityContentOverviewLayout(props: EntityContentLayoutProps) {
<Grid xs={12} md={8} item>
<Grid container spacing={3}>
{cards
.filter(card => card.area === 'peek')
.filter(card => card.type === 'peek')
.map((card, index) => (
<Grid key={index} className={classes.card} xs={12} md={6} item>
{card.element}
</Grid>
))}
{cards
.filter(card => !card.area || card.area === 'full')
.filter(card => !card.type || card.type === 'full')
.map((card, index) => (
<Grid key={index} className={classes.card} xs={12} md={6} item>
{card.element}
+9 -9
View File
@@ -2,34 +2,34 @@
'@backstage/plugin-catalog-react': minor
---
Add an optional `area` parameter to `EntityCard` extensions. A card's area value determines where it should be rendered by the entity content layout, as well as its maximum size.
Add an optional `type` parameter to `EntityCard` extensions. A card's type determines characteristics such as its expected size and where it will be rendered by the entity content layout.
We are initially supporting only three areas:
Initially the following three types are supported:
- `peek`: used for cards containing infrastucture information (e.g. last builds, deployments, etc.).
- `info`: used for cards that contain entity metadata (e.g. about, links);
- `full`: Contains information that plugins add to an entity (e.g. PagerDuty incidents and on-call escalation).
- `peek`: small vertical cards that provide information at a glance, for example recent builds, deployments, and service health.
- `info`: medium size cards with high priority and frequently used information such as common actions, entity metadata, and links.
- `full`: Large cards that are more feature rich with more information, typically used by plugins that don't quite need the full content view and want to show a card instead.
### Usage examples
Defining a default area when creating a card:
Defining a default type when creating a card:
```diff
const myCard = EntityCardBlueprint.make({
name: 'myCard',
params: {
+ defaultArea: 'info',
+ type: 'info',
loader: import('./MyCard).then(m => { default: m.MyCard }),
},
});
```
Changing the card area via `app-config.yaml` file:
Changing the card type via `app-config.yaml` file:
```diff
app:
extensions:
+ - entity-card:myPlugin/myCard:
+ config:
+ area: info
+ type: info
```
+2 -2
View File
@@ -28,12 +28,12 @@ app:
# Entity page cards
- entity-card:catalog/about:
config:
area: info
type: info
- entity-card:catalog/labels
- entity-card:catalog/links:
config:
filter: kind:component has:links
area: info
type: info
# - entity-card:linguist/languages
- entity-card:catalog-graph/relations:
config:
+3 -3
View File
@@ -56,7 +56,7 @@ function StickyEntityContentOverviewLayout(props: EntityContentLayoutProps) {
>
<Grid container spacing={3}>
{cards
.filter(card => card.area === 'info')
.filter(card => card.type === 'info')
.map((card, index) => (
<Grid key={index} xs={12} item>
{card.element}
@@ -67,14 +67,14 @@ function StickyEntityContentOverviewLayout(props: EntityContentLayoutProps) {
<Grid xs={12} md={8} item>
<Grid container spacing={3}>
{cards
.filter(card => card.area === 'peek')
.filter(card => card.type === 'peek')
.map((card, index) => (
<Grid key={index} className={classes.card} xs={12} md={6} item>
{card.element}
</Grid>
))}
{cards
.filter(card => !card.area || card.area === 'full')
.filter(card => !card.type || card.type === 'full')
.map((card, index) => (
<Grid key={index} className={classes.card} xs={12} md={6} item>
{card.element}
+31 -30
View File
@@ -8,6 +8,7 @@ import { AnyExtensionDataRef } from '@backstage/frontend-plugin-api';
import { AnyRouteRefParams } from '@backstage/frontend-plugin-api';
import { ConfigurableExtensionDataRef } from '@backstage/frontend-plugin-api';
import { Entity } from '@backstage/catalog-model';
import { EntityCardType } from '@backstage/plugin-catalog-react/alpha';
import { ExtensionDefinition } from '@backstage/frontend-plugin-api';
import { ExtensionInput } from '@backstage/frontend-plugin-api';
import { ExternalRouteRef } from '@backstage/frontend-plugin-api';
@@ -108,11 +109,11 @@ const _default: FrontendPlugin<
name: 'has-apis';
config: {
filter: string | undefined;
area: 'full' | 'info' | 'peek' | undefined;
type: 'full' | 'info' | 'peek' | undefined;
};
configInput: {
filter?: string | undefined;
area?: 'full' | 'info' | 'peek' | undefined;
type?: 'full' | 'info' | 'peek' | undefined;
};
output:
| ConfigurableExtensionDataRef<
@@ -135,8 +136,8 @@ const _default: FrontendPlugin<
}
>
| ConfigurableExtensionDataRef<
'full' | 'info' | 'peek',
'catalog.entity-card-area',
EntityCardType,
'catalog.entity-card-type',
{
optional: true;
}
@@ -145,7 +146,7 @@ const _default: FrontendPlugin<
params: {
loader: () => Promise<JSX.Element>;
filter?: string | ((entity: Entity) => boolean) | undefined;
defaultArea?: 'full' | 'info' | 'peek' | undefined;
type?: EntityCardType | undefined;
};
}>;
'entity-card:api-docs/definition': ExtensionDefinition<{
@@ -153,11 +154,11 @@ const _default: FrontendPlugin<
name: 'definition';
config: {
filter: string | undefined;
area: 'full' | 'info' | 'peek' | undefined;
type: 'full' | 'info' | 'peek' | undefined;
};
configInput: {
filter?: string | undefined;
area?: 'full' | 'info' | 'peek' | undefined;
type?: 'full' | 'info' | 'peek' | undefined;
};
output:
| ConfigurableExtensionDataRef<
@@ -180,8 +181,8 @@ const _default: FrontendPlugin<
}
>
| ConfigurableExtensionDataRef<
'full' | 'info' | 'peek',
'catalog.entity-card-area',
EntityCardType,
'catalog.entity-card-type',
{
optional: true;
}
@@ -190,7 +191,7 @@ const _default: FrontendPlugin<
params: {
loader: () => Promise<JSX.Element>;
filter?: string | ((entity: Entity) => boolean) | undefined;
defaultArea?: 'full' | 'info' | 'peek' | undefined;
type?: EntityCardType | undefined;
};
}>;
'entity-card:api-docs/consumed-apis': ExtensionDefinition<{
@@ -198,11 +199,11 @@ const _default: FrontendPlugin<
name: 'consumed-apis';
config: {
filter: string | undefined;
area: 'full' | 'info' | 'peek' | undefined;
type: 'full' | 'info' | 'peek' | undefined;
};
configInput: {
filter?: string | undefined;
area?: 'full' | 'info' | 'peek' | undefined;
type?: 'full' | 'info' | 'peek' | undefined;
};
output:
| ConfigurableExtensionDataRef<
@@ -225,8 +226,8 @@ const _default: FrontendPlugin<
}
>
| ConfigurableExtensionDataRef<
'full' | 'info' | 'peek',
'catalog.entity-card-area',
EntityCardType,
'catalog.entity-card-type',
{
optional: true;
}
@@ -235,7 +236,7 @@ const _default: FrontendPlugin<
params: {
loader: () => Promise<JSX.Element>;
filter?: string | ((entity: Entity) => boolean) | undefined;
defaultArea?: 'full' | 'info' | 'peek' | undefined;
type?: EntityCardType | undefined;
};
}>;
'entity-card:api-docs/provided-apis': ExtensionDefinition<{
@@ -243,11 +244,11 @@ const _default: FrontendPlugin<
name: 'provided-apis';
config: {
filter: string | undefined;
area: 'full' | 'info' | 'peek' | undefined;
type: 'full' | 'info' | 'peek' | undefined;
};
configInput: {
filter?: string | undefined;
area?: 'full' | 'info' | 'peek' | undefined;
type?: 'full' | 'info' | 'peek' | undefined;
};
output:
| ConfigurableExtensionDataRef<
@@ -270,8 +271,8 @@ const _default: FrontendPlugin<
}
>
| ConfigurableExtensionDataRef<
'full' | 'info' | 'peek',
'catalog.entity-card-area',
EntityCardType,
'catalog.entity-card-type',
{
optional: true;
}
@@ -280,7 +281,7 @@ const _default: FrontendPlugin<
params: {
loader: () => Promise<JSX.Element>;
filter?: string | ((entity: Entity) => boolean) | undefined;
defaultArea?: 'full' | 'info' | 'peek' | undefined;
type?: EntityCardType | undefined;
};
}>;
'entity-card:api-docs/consuming-components': ExtensionDefinition<{
@@ -288,11 +289,11 @@ const _default: FrontendPlugin<
name: 'consuming-components';
config: {
filter: string | undefined;
area: 'full' | 'info' | 'peek' | undefined;
type: 'full' | 'info' | 'peek' | undefined;
};
configInput: {
filter?: string | undefined;
area?: 'full' | 'info' | 'peek' | undefined;
type?: 'full' | 'info' | 'peek' | undefined;
};
output:
| ConfigurableExtensionDataRef<
@@ -315,8 +316,8 @@ const _default: FrontendPlugin<
}
>
| ConfigurableExtensionDataRef<
'full' | 'info' | 'peek',
'catalog.entity-card-area',
EntityCardType,
'catalog.entity-card-type',
{
optional: true;
}
@@ -325,7 +326,7 @@ const _default: FrontendPlugin<
params: {
loader: () => Promise<JSX.Element>;
filter?: string | ((entity: Entity) => boolean) | undefined;
defaultArea?: 'full' | 'info' | 'peek' | undefined;
type?: EntityCardType | undefined;
};
}>;
'entity-card:api-docs/providing-components': ExtensionDefinition<{
@@ -333,11 +334,11 @@ const _default: FrontendPlugin<
name: 'providing-components';
config: {
filter: string | undefined;
area: 'full' | 'info' | 'peek' | undefined;
type: 'full' | 'info' | 'peek' | undefined;
};
configInput: {
filter?: string | undefined;
area?: 'full' | 'info' | 'peek' | undefined;
type?: 'full' | 'info' | 'peek' | undefined;
};
output:
| ConfigurableExtensionDataRef<
@@ -360,8 +361,8 @@ const _default: FrontendPlugin<
}
>
| ConfigurableExtensionDataRef<
'full' | 'info' | 'peek',
'catalog.entity-card-area',
EntityCardType,
'catalog.entity-card-type',
{
optional: true;
}
@@ -370,7 +371,7 @@ const _default: FrontendPlugin<
params: {
loader: () => Promise<JSX.Element>;
filter?: string | ((entity: Entity) => boolean) | undefined;
defaultArea?: 'full' | 'info' | 'peek' | undefined;
type?: EntityCardType | undefined;
};
}>;
'entity-content:api-docs/definition': ExtensionDefinition<{
+6 -5
View File
@@ -8,6 +8,7 @@ import { AnyRouteRefParams } from '@backstage/frontend-plugin-api';
import { ConfigurableExtensionDataRef } from '@backstage/frontend-plugin-api';
import { Direction } from '@backstage/plugin-catalog-graph';
import { Entity } from '@backstage/catalog-model';
import { EntityCardType } from '@backstage/plugin-catalog-react/alpha';
import { ExtensionDefinition } from '@backstage/frontend-plugin-api';
import { ExtensionInput } from '@backstage/frontend-plugin-api';
import { ExternalRouteRef } from '@backstage/frontend-plugin-api';
@@ -43,7 +44,7 @@ const _default: FrontendPlugin<
height: number | undefined;
} & {
filter: string | undefined;
area: 'full' | 'info' | 'peek' | undefined;
type: 'full' | 'info' | 'peek' | undefined;
};
configInput: {
height?: number | undefined;
@@ -59,7 +60,7 @@ const _default: FrontendPlugin<
relationPairs?: [string, string][] | undefined;
} & {
filter?: string | undefined;
area?: 'full' | 'info' | 'peek' | undefined;
type?: 'full' | 'info' | 'peek' | undefined;
};
output:
| ConfigurableExtensionDataRef<
@@ -82,8 +83,8 @@ const _default: FrontendPlugin<
}
>
| ConfigurableExtensionDataRef<
'full' | 'info' | 'peek',
'catalog.entity-card-area',
EntityCardType,
'catalog.entity-card-type',
{
optional: true;
}
@@ -102,7 +103,7 @@ const _default: FrontendPlugin<
params: {
loader: () => Promise<JSX.Element>;
filter?: string | ((entity: Entity) => boolean) | undefined;
defaultArea?: 'full' | 'info' | 'peek' | undefined;
type?: EntityCardType | undefined;
};
}>;
'page:catalog-graph': ExtensionDefinition<{
+14 -14
View File
@@ -99,9 +99,6 @@ export function convertLegacyEntityContentExtension(
},
): ExtensionDefinition;
// @alpha
export const defaultEntityCardAreas: readonly ['peek', 'info', 'full'];
// @alpha
export const defaultEntityContentGroups: {
documentation: string;
@@ -117,7 +114,7 @@ export const EntityCardBlueprint: ExtensionBlueprint<{
params: {
loader: () => Promise<JSX.Element>;
filter?: string | ((entity: Entity) => boolean) | undefined;
defaultArea?: 'full' | 'info' | 'peek' | undefined;
type?: EntityCardType | undefined;
};
output:
| ConfigurableExtensionDataRef<JSX_2.Element, 'core.reactElement', {}>
@@ -136,8 +133,8 @@ export const EntityCardBlueprint: ExtensionBlueprint<{
}
>
| ConfigurableExtensionDataRef<
'full' | 'info' | 'peek',
'catalog.entity-card-area',
EntityCardType,
'catalog.entity-card-type',
{
optional: true;
}
@@ -145,11 +142,11 @@ export const EntityCardBlueprint: ExtensionBlueprint<{
inputs: {};
config: {
filter: string | undefined;
area: 'full' | 'info' | 'peek' | undefined;
type: 'full' | 'info' | 'peek' | undefined;
};
configInput: {
filter?: string | undefined;
area?: 'full' | 'info' | 'peek' | undefined;
type?: 'full' | 'info' | 'peek' | undefined;
};
dataRefs: {
filterFunction: ConfigurableExtensionDataRef<
@@ -162,14 +159,17 @@ export const EntityCardBlueprint: ExtensionBlueprint<{
'catalog.entity-filter-expression',
{}
>;
area: ConfigurableExtensionDataRef<
'full' | 'info' | 'peek',
'catalog.entity-card-area',
type: ConfigurableExtensionDataRef<
EntityCardType,
'catalog.entity-card-type',
{}
>;
};
}>;
// @alpha (undocumented)
export type EntityCardType = 'peek' | 'info' | 'full';
// @alpha
export const EntityContentBlueprint: ExtensionBlueprint<{
kind: 'entity-content';
@@ -289,12 +289,12 @@ export const EntityContentLayoutBlueprint: ExtensionBlueprint<{
>;
inputs: {};
config: {
area: string | undefined;
type: string | undefined;
filter: string | undefined;
};
configInput: {
filter?: string | undefined;
area?: string | undefined;
type?: string | undefined;
};
dataRefs: {
filterFunction: ConfigurableExtensionDataRef<
@@ -319,7 +319,7 @@ export const EntityContentLayoutBlueprint: ExtensionBlueprint<{
export interface EntityContentLayoutProps {
// (undocumented)
cards: Array<{
area?: (typeof defaultEntityCardAreas)[number];
type?: EntityCardType;
element: React_2.JSX.Element;
}>;
}
@@ -51,7 +51,10 @@ describe('EntityCardBlueprint', () => {
"$schema": "http://json-schema.org/draft-07/schema#",
"additionalProperties": false,
"properties": {
"area": {
"filter": {
"type": "string",
},
"type": {
"enum": [
"peek",
"info",
@@ -59,9 +62,6 @@ describe('EntityCardBlueprint', () => {
],
"type": "string",
},
"filter": {
"type": "string",
},
},
"type": "object",
},
@@ -96,7 +96,7 @@ describe('EntityCardBlueprint', () => {
"config": {
"optional": true,
},
"id": "catalog.entity-card-area",
"id": "catalog.entity-card-type",
"optional": [Function],
"toString": [Function],
},
@@ -22,8 +22,9 @@ import {
import {
entityFilterFunctionDataRef,
entityFilterExpressionDataRef,
entityCardAreaDataRef,
defaultEntityCardAreas,
entityCardTypeDataRef,
entityCardTypes,
EntityCardType,
} from './extensionData';
/**
@@ -37,30 +38,30 @@ export const EntityCardBlueprint = createExtensionBlueprint({
coreExtensionData.reactElement,
entityFilterFunctionDataRef.optional(),
entityFilterExpressionDataRef.optional(),
entityCardAreaDataRef.optional(),
entityCardTypeDataRef.optional(),
],
dataRefs: {
filterFunction: entityFilterFunctionDataRef,
filterExpression: entityFilterExpressionDataRef,
area: entityCardAreaDataRef,
type: entityCardTypeDataRef,
},
config: {
schema: {
filter: z => z.string().optional(),
area: z => z.enum(defaultEntityCardAreas).optional(),
type: z => z.enum(entityCardTypes).optional(),
},
},
*factory(
{
loader,
filter,
defaultArea,
type,
}: {
loader: () => Promise<JSX.Element>;
filter?:
| typeof entityFilterFunctionDataRef.T
| typeof entityFilterExpressionDataRef.T;
defaultArea?: (typeof defaultEntityCardAreas)[number];
type?: EntityCardType;
},
{ node, config },
) {
@@ -74,13 +75,13 @@ export const EntityCardBlueprint = createExtensionBlueprint({
yield entityFilterFunctionDataRef(filter);
}
const area = config.area ?? defaultArea;
if (area) {
yield entityCardAreaDataRef(area);
const finalType = config.type ?? type;
if (finalType) {
yield entityCardTypeDataRef(finalType);
} else {
// eslint-disable-next-line no-console
console.warn(
`DEPRECATION WARNING: Not providing defaultArea for entity cards is deprecated. Missing from '${node.spec.id}'`,
`DEPRECATION WARNING: Not providing type for entity cards is deprecated. Missing from '${node.spec.id}'`,
);
}
},
@@ -22,14 +22,14 @@ import {
import {
entityFilterExpressionDataRef,
entityFilterFunctionDataRef,
defaultEntityCardAreas,
EntityCardType,
} from './extensionData';
import React from 'react';
/** @alpha */
export interface EntityContentLayoutProps {
cards: Array<{
area?: (typeof defaultEntityCardAreas)[number];
type?: EntityCardType;
element: React.JSX.Element;
}>;
}
@@ -56,7 +56,7 @@ export const EntityContentLayoutBlueprint = createExtensionBlueprint({
},
config: {
schema: {
area: z => z.string().optional(),
type: z => z.string().optional(),
filter: z => z.string().optional(),
},
},
@@ -50,14 +50,20 @@ export const entityContentGroupDataRef = createExtensionDataRef<string>().with({
});
/**
* @alpha
* Default entity content groups.
* @internal
* Available entity card types
*/
export const defaultEntityCardAreas = ['peek', 'info', 'full'] as const;
export const entityCardTypes = [
'peek',
'info',
'full',
] as const satisfies readonly EntityCardType[];
/** @alpha */
export type EntityCardType = 'peek' | 'info' | 'full';
/** @internal */
export const entityCardAreaDataRef = createExtensionDataRef<
(typeof defaultEntityCardAreas)[number]
>().with({
id: 'catalog.entity-card-area',
});
export const entityCardTypeDataRef =
createExtensionDataRef<EntityCardType>().with({
id: 'catalog.entity-card-type',
});
@@ -19,7 +19,5 @@ export {
EntityContentLayoutBlueprint,
type EntityContentLayoutProps,
} from './EntityContentLayoutBlueprint';
export {
defaultEntityContentGroups,
defaultEntityCardAreas,
} from './extensionData';
export { defaultEntityContentGroups } from './extensionData';
export type { EntityCardType } from './extensionData';
+53 -52
View File
@@ -10,6 +10,7 @@ import { AnyExtensionDataRef } from '@backstage/frontend-plugin-api';
import { AnyRouteRefParams } from '@backstage/frontend-plugin-api';
import { ConfigurableExtensionDataRef } from '@backstage/frontend-plugin-api';
import { Entity } from '@backstage/catalog-model';
import { EntityCardType } from '@backstage/plugin-catalog-react/alpha';
import { EntityContentLayoutProps } from '@backstage/plugin-catalog-react/alpha';
import { ExtensionBlueprint } from '@backstage/frontend-plugin-api';
import { ExtensionDefinition } from '@backstage/frontend-plugin-api';
@@ -218,11 +219,11 @@ const _default: FrontendPlugin<
name: 'about';
config: {
filter: string | undefined;
area: 'full' | 'info' | 'peek' | undefined;
type: 'full' | 'info' | 'peek' | undefined;
};
configInput: {
filter?: string | undefined;
area?: 'full' | 'info' | 'peek' | undefined;
type?: 'full' | 'info' | 'peek' | undefined;
};
output:
| ConfigurableExtensionDataRef<JSX_2.Element, 'core.reactElement', {}>
@@ -241,8 +242,8 @@ const _default: FrontendPlugin<
}
>
| ConfigurableExtensionDataRef<
'full' | 'info' | 'peek',
'catalog.entity-card-area',
EntityCardType,
'catalog.entity-card-type',
{
optional: true;
}
@@ -251,7 +252,7 @@ const _default: FrontendPlugin<
params: {
loader: () => Promise<JSX.Element>;
filter?: string | ((entity: Entity) => boolean) | undefined;
defaultArea?: 'full' | 'info' | 'peek' | undefined;
type?: EntityCardType | undefined;
};
}>;
'entity-card:catalog/links': ExtensionDefinition<{
@@ -259,11 +260,11 @@ const _default: FrontendPlugin<
name: 'links';
config: {
filter: string | undefined;
area: 'full' | 'info' | 'peek' | undefined;
type: 'full' | 'info' | 'peek' | undefined;
};
configInput: {
filter?: string | undefined;
area?: 'full' | 'info' | 'peek' | undefined;
type?: 'full' | 'info' | 'peek' | undefined;
};
output:
| ConfigurableExtensionDataRef<JSX_2.Element, 'core.reactElement', {}>
@@ -282,8 +283,8 @@ const _default: FrontendPlugin<
}
>
| ConfigurableExtensionDataRef<
'full' | 'info' | 'peek',
'catalog.entity-card-area',
EntityCardType,
'catalog.entity-card-type',
{
optional: true;
}
@@ -292,7 +293,7 @@ const _default: FrontendPlugin<
params: {
loader: () => Promise<JSX.Element>;
filter?: string | ((entity: Entity) => boolean) | undefined;
defaultArea?: 'full' | 'info' | 'peek' | undefined;
type?: EntityCardType | undefined;
};
}>;
'entity-card:catalog/labels': ExtensionDefinition<{
@@ -300,11 +301,11 @@ const _default: FrontendPlugin<
name: 'labels';
config: {
filter: string | undefined;
area: 'full' | 'info' | 'peek' | undefined;
type: 'full' | 'info' | 'peek' | undefined;
};
configInput: {
filter?: string | undefined;
area?: 'full' | 'info' | 'peek' | undefined;
type?: 'full' | 'info' | 'peek' | undefined;
};
output:
| ConfigurableExtensionDataRef<JSX_2.Element, 'core.reactElement', {}>
@@ -323,8 +324,8 @@ const _default: FrontendPlugin<
}
>
| ConfigurableExtensionDataRef<
'full' | 'info' | 'peek',
'catalog.entity-card-area',
EntityCardType,
'catalog.entity-card-type',
{
optional: true;
}
@@ -333,7 +334,7 @@ const _default: FrontendPlugin<
params: {
loader: () => Promise<JSX.Element>;
filter?: string | ((entity: Entity) => boolean) | undefined;
defaultArea?: 'full' | 'info' | 'peek' | undefined;
type?: EntityCardType | undefined;
};
}>;
'entity-card:catalog/depends-on-components': ExtensionDefinition<{
@@ -341,11 +342,11 @@ const _default: FrontendPlugin<
name: 'depends-on-components';
config: {
filter: string | undefined;
area: 'full' | 'info' | 'peek' | undefined;
type: 'full' | 'info' | 'peek' | undefined;
};
configInput: {
filter?: string | undefined;
area?: 'full' | 'info' | 'peek' | undefined;
type?: 'full' | 'info' | 'peek' | undefined;
};
output:
| ConfigurableExtensionDataRef<JSX_2.Element, 'core.reactElement', {}>
@@ -364,8 +365,8 @@ const _default: FrontendPlugin<
}
>
| ConfigurableExtensionDataRef<
'full' | 'info' | 'peek',
'catalog.entity-card-area',
EntityCardType,
'catalog.entity-card-type',
{
optional: true;
}
@@ -374,7 +375,7 @@ const _default: FrontendPlugin<
params: {
loader: () => Promise<JSX.Element>;
filter?: string | ((entity: Entity) => boolean) | undefined;
defaultArea?: 'full' | 'info' | 'peek' | undefined;
type?: EntityCardType | undefined;
};
}>;
'entity-card:catalog/depends-on-resources': ExtensionDefinition<{
@@ -382,11 +383,11 @@ const _default: FrontendPlugin<
name: 'depends-on-resources';
config: {
filter: string | undefined;
area: 'full' | 'info' | 'peek' | undefined;
type: 'full' | 'info' | 'peek' | undefined;
};
configInput: {
filter?: string | undefined;
area?: 'full' | 'info' | 'peek' | undefined;
type?: 'full' | 'info' | 'peek' | undefined;
};
output:
| ConfigurableExtensionDataRef<JSX_2.Element, 'core.reactElement', {}>
@@ -405,8 +406,8 @@ const _default: FrontendPlugin<
}
>
| ConfigurableExtensionDataRef<
'full' | 'info' | 'peek',
'catalog.entity-card-area',
EntityCardType,
'catalog.entity-card-type',
{
optional: true;
}
@@ -415,7 +416,7 @@ const _default: FrontendPlugin<
params: {
loader: () => Promise<JSX.Element>;
filter?: string | ((entity: Entity) => boolean) | undefined;
defaultArea?: 'full' | 'info' | 'peek' | undefined;
type?: EntityCardType | undefined;
};
}>;
'entity-card:catalog/has-components': ExtensionDefinition<{
@@ -423,11 +424,11 @@ const _default: FrontendPlugin<
name: 'has-components';
config: {
filter: string | undefined;
area: 'full' | 'info' | 'peek' | undefined;
type: 'full' | 'info' | 'peek' | undefined;
};
configInput: {
filter?: string | undefined;
area?: 'full' | 'info' | 'peek' | undefined;
type?: 'full' | 'info' | 'peek' | undefined;
};
output:
| ConfigurableExtensionDataRef<JSX_2.Element, 'core.reactElement', {}>
@@ -446,8 +447,8 @@ const _default: FrontendPlugin<
}
>
| ConfigurableExtensionDataRef<
'full' | 'info' | 'peek',
'catalog.entity-card-area',
EntityCardType,
'catalog.entity-card-type',
{
optional: true;
}
@@ -456,7 +457,7 @@ const _default: FrontendPlugin<
params: {
loader: () => Promise<JSX.Element>;
filter?: string | ((entity: Entity) => boolean) | undefined;
defaultArea?: 'full' | 'info' | 'peek' | undefined;
type?: EntityCardType | undefined;
};
}>;
'entity-card:catalog/has-resources': ExtensionDefinition<{
@@ -464,11 +465,11 @@ const _default: FrontendPlugin<
name: 'has-resources';
config: {
filter: string | undefined;
area: 'full' | 'info' | 'peek' | undefined;
type: 'full' | 'info' | 'peek' | undefined;
};
configInput: {
filter?: string | undefined;
area?: 'full' | 'info' | 'peek' | undefined;
type?: 'full' | 'info' | 'peek' | undefined;
};
output:
| ConfigurableExtensionDataRef<JSX_2.Element, 'core.reactElement', {}>
@@ -487,8 +488,8 @@ const _default: FrontendPlugin<
}
>
| ConfigurableExtensionDataRef<
'full' | 'info' | 'peek',
'catalog.entity-card-area',
EntityCardType,
'catalog.entity-card-type',
{
optional: true;
}
@@ -497,7 +498,7 @@ const _default: FrontendPlugin<
params: {
loader: () => Promise<JSX.Element>;
filter?: string | ((entity: Entity) => boolean) | undefined;
defaultArea?: 'full' | 'info' | 'peek' | undefined;
type?: EntityCardType | undefined;
};
}>;
'entity-card:catalog/has-subcomponents': ExtensionDefinition<{
@@ -505,11 +506,11 @@ const _default: FrontendPlugin<
name: 'has-subcomponents';
config: {
filter: string | undefined;
area: 'full' | 'info' | 'peek' | undefined;
type: 'full' | 'info' | 'peek' | undefined;
};
configInput: {
filter?: string | undefined;
area?: 'full' | 'info' | 'peek' | undefined;
type?: 'full' | 'info' | 'peek' | undefined;
};
output:
| ConfigurableExtensionDataRef<JSX_2.Element, 'core.reactElement', {}>
@@ -528,8 +529,8 @@ const _default: FrontendPlugin<
}
>
| ConfigurableExtensionDataRef<
'full' | 'info' | 'peek',
'catalog.entity-card-area',
EntityCardType,
'catalog.entity-card-type',
{
optional: true;
}
@@ -538,7 +539,7 @@ const _default: FrontendPlugin<
params: {
loader: () => Promise<JSX.Element>;
filter?: string | ((entity: Entity) => boolean) | undefined;
defaultArea?: 'full' | 'info' | 'peek' | undefined;
type?: EntityCardType | undefined;
};
}>;
'entity-card:catalog/has-subdomains': ExtensionDefinition<{
@@ -546,11 +547,11 @@ const _default: FrontendPlugin<
name: 'has-subdomains';
config: {
filter: string | undefined;
area: 'full' | 'info' | 'peek' | undefined;
type: 'full' | 'info' | 'peek' | undefined;
};
configInput: {
filter?: string | undefined;
area?: 'full' | 'info' | 'peek' | undefined;
type?: 'full' | 'info' | 'peek' | undefined;
};
output:
| ConfigurableExtensionDataRef<JSX_2.Element, 'core.reactElement', {}>
@@ -569,8 +570,8 @@ const _default: FrontendPlugin<
}
>
| ConfigurableExtensionDataRef<
'full' | 'info' | 'peek',
'catalog.entity-card-area',
EntityCardType,
'catalog.entity-card-type',
{
optional: true;
}
@@ -579,7 +580,7 @@ const _default: FrontendPlugin<
params: {
loader: () => Promise<JSX.Element>;
filter?: string | ((entity: Entity) => boolean) | undefined;
defaultArea?: 'full' | 'info' | 'peek' | undefined;
type?: EntityCardType | undefined;
};
}>;
'entity-card:catalog/has-systems': ExtensionDefinition<{
@@ -587,11 +588,11 @@ const _default: FrontendPlugin<
name: 'has-systems';
config: {
filter: string | undefined;
area: 'full' | 'info' | 'peek' | undefined;
type: 'full' | 'info' | 'peek' | undefined;
};
configInput: {
filter?: string | undefined;
area?: 'full' | 'info' | 'peek' | undefined;
type?: 'full' | 'info' | 'peek' | undefined;
};
output:
| ConfigurableExtensionDataRef<JSX_2.Element, 'core.reactElement', {}>
@@ -610,8 +611,8 @@ const _default: FrontendPlugin<
}
>
| ConfigurableExtensionDataRef<
'full' | 'info' | 'peek',
'catalog.entity-card-area',
EntityCardType,
'catalog.entity-card-type',
{
optional: true;
}
@@ -620,7 +621,7 @@ const _default: FrontendPlugin<
params: {
loader: () => Promise<JSX.Element>;
filter?: string | ((entity: Entity) => boolean) | undefined;
defaultArea?: 'full' | 'info' | 'peek' | undefined;
type?: EntityCardType | undefined;
};
}>;
'entity-content:catalog/overview': ExtensionDefinition<{
@@ -715,8 +716,8 @@ const _default: FrontendPlugin<
}
>
| ConfigurableExtensionDataRef<
'full' | 'info' | 'peek',
'catalog.entity-card-area',
EntityCardType,
'catalog.entity-card-type',
{
optional: true;
}
@@ -113,7 +113,7 @@ describe('Overview content', () => {
const infoCard = EntityCardBlueprint.make({
name: 'info-card',
params: {
defaultArea: 'info',
type: 'info',
loader: async () => <div>Info card</div>,
},
});
@@ -136,14 +136,14 @@ describe('Overview content', () => {
<h3>Custom layout</h3>
<div id="info">
{cards
.filter(card => card.area === 'info')
.filter(card => card.type === 'info')
.map((card, index) => (
<Fragment key={index}>{card.element}</Fragment>
))}
</div>
<div id="other">
{cards
.filter(card => card.area !== 'info')
.filter(card => card.type !== 'info')
.map((card, index) => (
<Fragment key={index}>{card.element}</Fragment>
))}
+2 -2
View File
@@ -42,7 +42,7 @@ export const catalogOverviewEntityContent =
coreExtensionData.reactElement,
EntityContentBlueprint.dataRefs.filterFunction.optional(),
EntityContentBlueprint.dataRefs.filterExpression.optional(),
EntityCardBlueprint.dataRefs.area.optional(),
EntityCardBlueprint.dataRefs.type.optional(),
]),
},
factory: (originalFactory, { node, inputs }) => {
@@ -86,7 +86,7 @@ export const catalogOverviewEntityContent =
const cards = inputs.cards.map(card => ({
element: card.get(coreExtensionData.reactElement),
area: card.get(EntityCardBlueprint.dataRefs.area),
type: card.get(EntityCardBlueprint.dataRefs.type),
filter: buildFilterFn(
card.get(EntityContentBlueprint.dataRefs.filterFunction),
card.get(EntityContentBlueprint.dataRefs.filterExpression),
+21 -20
View File
@@ -5,6 +5,7 @@
```ts
import { ConfigurableExtensionDataRef } from '@backstage/frontend-plugin-api';
import { Entity } from '@backstage/catalog-model';
import { EntityCardType } from '@backstage/plugin-catalog-react/alpha';
import { ExtensionDefinition } from '@backstage/frontend-plugin-api';
import { ExternalRouteRef } from '@backstage/frontend-plugin-api';
import { FrontendPlugin } from '@backstage/frontend-plugin-api';
@@ -22,11 +23,11 @@ const _default: FrontendPlugin<
name: 'group-profile';
config: {
filter: string | undefined;
area: 'full' | 'info' | 'peek' | undefined;
type: 'full' | 'info' | 'peek' | undefined;
};
configInput: {
filter?: string | undefined;
area?: 'full' | 'info' | 'peek' | undefined;
type?: 'full' | 'info' | 'peek' | undefined;
};
output:
| ConfigurableExtensionDataRef<
@@ -49,8 +50,8 @@ const _default: FrontendPlugin<
}
>
| ConfigurableExtensionDataRef<
'full' | 'info' | 'peek',
'catalog.entity-card-area',
EntityCardType,
'catalog.entity-card-type',
{
optional: true;
}
@@ -59,7 +60,7 @@ const _default: FrontendPlugin<
params: {
loader: () => Promise<JSX.Element>;
filter?: string | ((entity: Entity) => boolean) | undefined;
defaultArea?: 'full' | 'info' | 'peek' | undefined;
type?: EntityCardType | undefined;
};
}>;
'entity-card:org/members-list': ExtensionDefinition<{
@@ -67,11 +68,11 @@ const _default: FrontendPlugin<
name: 'members-list';
config: {
filter: string | undefined;
area: 'full' | 'info' | 'peek' | undefined;
type: 'full' | 'info' | 'peek' | undefined;
};
configInput: {
filter?: string | undefined;
area?: 'full' | 'info' | 'peek' | undefined;
type?: 'full' | 'info' | 'peek' | undefined;
};
output:
| ConfigurableExtensionDataRef<
@@ -94,8 +95,8 @@ const _default: FrontendPlugin<
}
>
| ConfigurableExtensionDataRef<
'full' | 'info' | 'peek',
'catalog.entity-card-area',
EntityCardType,
'catalog.entity-card-type',
{
optional: true;
}
@@ -104,7 +105,7 @@ const _default: FrontendPlugin<
params: {
loader: () => Promise<JSX.Element>;
filter?: string | ((entity: Entity) => boolean) | undefined;
defaultArea?: 'full' | 'info' | 'peek' | undefined;
type?: EntityCardType | undefined;
};
}>;
'entity-card:org/ownership': ExtensionDefinition<{
@@ -112,11 +113,11 @@ const _default: FrontendPlugin<
name: 'ownership';
config: {
filter: string | undefined;
area: 'full' | 'info' | 'peek' | undefined;
type: 'full' | 'info' | 'peek' | undefined;
};
configInput: {
filter?: string | undefined;
area?: 'full' | 'info' | 'peek' | undefined;
type?: 'full' | 'info' | 'peek' | undefined;
};
output:
| ConfigurableExtensionDataRef<
@@ -139,8 +140,8 @@ const _default: FrontendPlugin<
}
>
| ConfigurableExtensionDataRef<
'full' | 'info' | 'peek',
'catalog.entity-card-area',
EntityCardType,
'catalog.entity-card-type',
{
optional: true;
}
@@ -149,7 +150,7 @@ const _default: FrontendPlugin<
params: {
loader: () => Promise<JSX.Element>;
filter?: string | ((entity: Entity) => boolean) | undefined;
defaultArea?: 'full' | 'info' | 'peek' | undefined;
type?: EntityCardType | undefined;
};
}>;
'entity-card:org/user-profile': ExtensionDefinition<{
@@ -157,11 +158,11 @@ const _default: FrontendPlugin<
name: 'user-profile';
config: {
filter: string | undefined;
area: 'full' | 'info' | 'peek' | undefined;
type: 'full' | 'info' | 'peek' | undefined;
};
configInput: {
filter?: string | undefined;
area?: 'full' | 'info' | 'peek' | undefined;
type?: 'full' | 'info' | 'peek' | undefined;
};
output:
| ConfigurableExtensionDataRef<
@@ -184,8 +185,8 @@ const _default: FrontendPlugin<
}
>
| ConfigurableExtensionDataRef<
'full' | 'info' | 'peek',
'catalog.entity-card-area',
EntityCardType,
'catalog.entity-card-type',
{
optional: true;
}
@@ -194,7 +195,7 @@ const _default: FrontendPlugin<
params: {
loader: () => Promise<JSX.Element>;
filter?: string | ((entity: Entity) => boolean) | undefined;
defaultArea?: 'full' | 'info' | 'peek' | undefined;
type?: EntityCardType | undefined;
};
}>;
}