fix: revert deleting of fields and deprecate them instead

Signed-off-by: Ben Keil <benkeil.pub@pm.me>
This commit is contained in:
Ben Keil
2023-11-07 20:40:32 +01:00
parent a0a284ab74
commit 8469a03c2f
7 changed files with 157 additions and 1 deletions
+12 -1
View File
@@ -2,4 +2,15 @@
'@backstage/plugin-catalog-graph': minor
---
Add the entire `Entity` to `EntityNodeData`
Add the entire `Entity` to `EntityNodeData` and deprecate `name`, `kind`, `title`, `namespace` and `spec`.
To get the deprecated properties in your custom component you can use:
```typescript
import { DEFAULT_NAMESPACE } from '@backstage/catalog-model';
const {
kind,
metadata: { name, namespace = DEFAULT_NAMESPACE, title },
} = entity;
```
+49
View File
@@ -85,6 +85,55 @@ To use the catalog graph plugin, you have to add some things to your Backstage a
</Grid>
```
### Customization
Copy the default implementation `DefaultRenderNode.tsx` and add more classes to the styles:
```typescript
const useStyles = makeStyles<Theme>(
theme => ({
node: {
'&.system': {
fill: '#F5DC70',
stroke: '#F2CE34',
},
'&.domain': {
fill: '#F5DC70',
stroke: '#F2CE34',
},
);
```
Now you can use the new classes in your component with `className={classNames(classes.node, kind?.toLowerCase(), type?.toLowerCase())}`
```tsx
return (
<g onClick={onClick} className={classNames(onClick && classes.clickable)}>
<rect
className={classNames(
classes.node,
kind?.toLowerCase(),
type?.toLowerCase(),
)}
width={paddedWidth}
height={paddedHeight}
/>
<text
ref={idRef}
className={classNames(classes.text, focused && 'focused')}
y={paddedHeight / 2}
x={paddedWidth / 2}
textAnchor="middle"
alignmentBaseline="middle"
>
{displayTitle}
</text>
</g>
);
```
## Development
Run `yarn` in the root of this plugin to install all dependencies and then `yarn start` to run a [development version](./dev/index.tsx) of this plugin.
+6
View File
@@ -11,6 +11,7 @@ import { DependencyGraphTypes } from '@backstage/core-components';
import { Entity } from '@backstage/catalog-model';
import { ExternalRouteRef } from '@backstage/core-plugin-api';
import { InfoCardVariants } from '@backstage/core-components';
import { JsonObject } from '@backstage/types';
import { JSX as JSX_2 } from 'react';
import { MouseEvent as MouseEvent_2 } from 'react';
import { MouseEventHandler } from 'react';
@@ -94,6 +95,11 @@ export type EntityNodeData = {
focused?: boolean;
color?: 'primary' | 'secondary' | 'default';
onClick?: MouseEventHandler<unknown>;
name: string;
kind?: string;
title?: string;
namespace: string;
spec?: JsonObject;
};
// @public
@@ -37,6 +37,10 @@ describe('<CustomNode />', () => {
},
focused: false,
color: 'primary',
// @deprecated
kind: 'kind',
name: 'name',
namespace: 'namespace',
}}
/>
</svg>,
@@ -60,6 +64,10 @@ describe('<CustomNode />', () => {
},
},
focused: false,
// @deprecated
kind: 'kind',
name: 'name',
namespace: 'default',
}}
/>
</svg>,
@@ -85,6 +93,10 @@ describe('<CustomNode />', () => {
},
focused: false,
onClick,
// @deprecated
kind: 'kind',
name: 'name',
namespace: 'namespace',
}}
/>
</svg>,
@@ -111,6 +123,11 @@ describe('<CustomNode />', () => {
},
},
focused: false,
// @deprecated
kind: 'kind',
name: 'name',
namespace: 'namespace',
title: 'Custom Title',
}}
/>
</svg>,
@@ -17,6 +17,7 @@
import { DependencyGraphTypes } from '@backstage/core-components';
import { MouseEventHandler } from 'react';
import { Entity } from '@backstage/catalog-model';
import { JsonObject } from '@backstage/types';
/**
* Additional Data for entities.
@@ -65,6 +66,33 @@ export type EntityNodeData = {
* Optional click handler.
*/
onClick?: MouseEventHandler<unknown>;
/**
* Name of the entity.
* @deprecated use {@link EntityNodeData#entity} instead
*/
name: string;
/**
* Optional kind of the entity.
* @deprecated use {@link EntityNodeData#entity} instead
*/
kind?: string;
/**
* Optional title of the entity.
* @deprecated use {@link EntityNodeData#entity} instead
*/
title?: string;
/**
* Namespace of the entity.
* @deprecated use {@link EntityNodeData#entity} instead
* The Entity
*/
namespace: string;
/**
* Optional spec of the entity.
* @deprecated use {@link EntityNodeData#entity} instead
*/
spec?: JsonObject;
};
/**
@@ -14,6 +14,7 @@
* limitations under the License.
*/
import {
DEFAULT_NAMESPACE,
Entity,
RELATION_HAS_PART,
RELATION_OWNED_BY,
@@ -25,6 +26,7 @@ import { renderHook, waitFor } from '@testing-library/react';
import { filter, keyBy } from 'lodash';
import { useEntityRelationGraph as useEntityRelationGraphMocked } from './useEntityRelationGraph';
import { useEntityRelationNodesAndEdges } from './useEntityRelationNodesAndEdges';
import { EntityNode } from './types';
jest.mock('./useEntityRelationGraph');
@@ -107,6 +109,15 @@ const entities: { [ref: string]: Entity } = {
},
};
function deprecatedProperties(entity: Entity): Partial<EntityNode> {
return {
kind: entity.kind,
name: entity.metadata.name,
namespace: entity.metadata.namespace || DEFAULT_NAMESPACE,
title: entity.metadata.title,
};
}
describe('useEntityRelationNodesAndEdges', () => {
beforeEach(() => {
useEntityRelationGraph.mockImplementation(({ filter: { kinds } }) => ({
@@ -185,24 +196,28 @@ describe('useEntityRelationNodesAndEdges', () => {
focused: true,
id: 'b:d/c',
entity: entities['b:d/c'],
...deprecatedProperties(entities['b:d/c']),
},
{
color: 'primary',
focused: false,
id: 'k:d/a1',
entity: entities['k:d/a1'],
...deprecatedProperties(entities['k:d/a1']),
},
{
color: 'primary',
focused: false,
id: 'b:d/c1',
entity: entities['b:d/c1'],
...deprecatedProperties(entities['b:d/c1']),
},
{
color: 'primary',
focused: false,
id: 'b:d/c2',
entity: entities['b:d/c2'],
...deprecatedProperties(entities['b:d/c2']),
},
]);
expect(edges).toEqual([
@@ -250,24 +265,28 @@ describe('useEntityRelationNodesAndEdges', () => {
focused: true,
id: 'b:d/c',
entity: entities['b:d/c'],
...deprecatedProperties(entities['b:d/c']),
},
{
color: 'primary',
focused: false,
id: 'k:d/a1',
entity: entities['k:d/a1'],
...deprecatedProperties(entities['k:d/a1']),
},
{
color: 'primary',
focused: false,
id: 'b:d/c1',
entity: entities['b:d/c1'],
...deprecatedProperties(entities['b:d/c1']),
},
{
color: 'primary',
focused: false,
id: 'b:d/c2',
entity: entities['b:d/c2'],
...deprecatedProperties(entities['b:d/c2']),
},
]);
expect(edges).toEqual([
@@ -315,24 +334,28 @@ describe('useEntityRelationNodesAndEdges', () => {
focused: true,
id: 'b:d/c',
entity: entities['b:d/c'],
...deprecatedProperties(entities['b:d/c']),
},
{
color: 'primary',
focused: false,
id: 'k:d/a1',
entity: entities['k:d/a1'],
...deprecatedProperties(entities['k:d/a1']),
},
{
color: 'primary',
focused: false,
id: 'b:d/c1',
entity: entities['b:d/c1'],
...deprecatedProperties(entities['b:d/c1']),
},
{
color: 'primary',
focused: false,
id: 'b:d/c2',
entity: entities['b:d/c2'],
...deprecatedProperties(entities['b:d/c2']),
},
]);
expect(edges).toEqual([
@@ -410,24 +433,28 @@ describe('useEntityRelationNodesAndEdges', () => {
focused: true,
id: 'b:d/c',
entity: entities['b:d/c'],
...deprecatedProperties(entities['b:d/c']),
},
{
color: 'primary',
focused: false,
id: 'k:d/a1',
entity: entities['k:d/a1'],
...deprecatedProperties(entities['k:d/a1']),
},
{
color: 'primary',
focused: false,
id: 'b:d/c1',
entity: entities['b:d/c1'],
...deprecatedProperties(entities['b:d/c1']),
},
{
color: 'primary',
focused: false,
id: 'b:d/c2',
entity: entities['b:d/c2'],
...deprecatedProperties(entities['b:d/c2']),
},
]);
expect(edges).toEqual([
@@ -503,24 +530,28 @@ describe('useEntityRelationNodesAndEdges', () => {
focused: true,
id: 'b:d/c',
entity: entities['b:d/c'],
...deprecatedProperties(entities['b:d/c']),
},
{
color: 'primary',
focused: false,
id: 'k:d/a1',
entity: entities['k:d/a1'],
...deprecatedProperties(entities['k:d/a1']),
},
{
color: 'primary',
focused: false,
id: 'b:d/c1',
entity: entities['b:d/c1'],
...deprecatedProperties(entities['b:d/c1']),
},
{
color: 'secondary',
focused: true,
id: 'b:d/c2',
entity: entities['b:d/c2'],
...deprecatedProperties(entities['b:d/c2']),
},
]);
expect(edges).toEqual([
@@ -567,24 +598,28 @@ describe('useEntityRelationNodesAndEdges', () => {
focused: true,
id: 'b:d/c',
entity: entities['b:d/c'],
...deprecatedProperties(entities['b:d/c']),
},
{
color: 'primary',
focused: false,
id: 'k:d/a1',
entity: entities['k:d/a1'],
...deprecatedProperties(entities['k:d/a1']),
},
{
color: 'primary',
focused: false,
id: 'b:d/c1',
entity: entities['b:d/c1'],
...deprecatedProperties(entities['b:d/c1']),
},
{
color: 'primary',
focused: false,
id: 'b:d/c2',
entity: entities['b:d/c2'],
...deprecatedProperties(entities['b:d/c2']),
},
]);
expect(edges).toEqual([
@@ -620,18 +655,21 @@ describe('useEntityRelationNodesAndEdges', () => {
focused: true,
id: 'b:d/c',
entity: entities['b:d/c'],
...deprecatedProperties(entities['b:d/c']),
},
{
color: 'primary',
focused: false,
id: 'b:d/c1',
entity: entities['b:d/c1'],
...deprecatedProperties(entities['b:d/c1']),
},
{
color: 'primary',
focused: false,
id: 'b:d/c2',
entity: entities['b:d/c2'],
...deprecatedProperties(entities['b:d/c2']),
},
]);
expect(edges).toEqual([
@@ -18,6 +18,7 @@ import useDebounce from 'react-use/lib/useDebounce';
import { RelationPairs, ALL_RELATION_PAIRS } from './relations';
import { EntityEdge, EntityNode } from './types';
import { useEntityRelationGraph } from './useEntityRelationGraph';
import { DEFAULT_NAMESPACE } from '@backstage/catalog-model';
/**
* Generate nodes and edges to render the entity graph.
@@ -73,6 +74,12 @@ export function useEntityRelationNodesAndEdges({
entity,
focused,
color: focused ? 'secondary' : 'primary',
// @deprecated
kind: entity.kind,
name: entity.metadata.name,
namespace: entity.metadata.namespace || DEFAULT_NAMESPACE,
title: entity.metadata.title,
spec: entity.spec,
};
if (onNodeClick) {