From c888887b65308af6e16d6b63a6d13a84a7a853ec Mon Sep 17 00:00:00 2001 From: Camila Belo Date: Tue, 30 Jan 2024 14:06:30 +0100 Subject: [PATCH] feat(catalog-graph): create entity card extension Signed-off-by: Camila Belo --- plugins/catalog-graph/src/alpha.tsx | 80 ++++++++++++++++++++++++----- 1 file changed, 68 insertions(+), 12 deletions(-) diff --git a/plugins/catalog-graph/src/alpha.tsx b/plugins/catalog-graph/src/alpha.tsx index bf2b0ffce8..00be9e8e69 100644 --- a/plugins/catalog-graph/src/alpha.tsx +++ b/plugins/catalog-graph/src/alpha.tsx @@ -24,29 +24,85 @@ import { compatWrapper, convertLegacyRouteRef, } from '@backstage/core-compat-api'; +import { createEntityCardExtension } from '@backstage/plugin-catalog-react/alpha'; import { catalogGraphRouteRef, catalogEntityRouteRef } from './routes'; import { Direction } from './components'; +type Zod = Parameters[0]>[0]; + +function getCompoundEntityRefConfigSchema(z: Zod) { + return z.object({ + kind: z.string(), + namespace: z.string(), + name: z.string(), + }); +} + +function getEntityGraphRelationsConfigSchema(z: Zod) { + // Mapping EntityRelationsGraphProps to config + // TODO: Define how className and render functions will be configured + return z.object({ + rootEntityRef: getCompoundEntityRefConfigSchema(z) + .or(z.array(getCompoundEntityRefConfigSchema(z))) + .optional(), + kinds: z.array(z.string()).optional(), + relations: z.array(z.string()).optional(), + maxDepth: z.number().optional(), + unidirectional: z.boolean().optional(), + mergeRelations: z.boolean().optional(), + direction: z.nativeEnum(Direction).optional(), + relationPairs: z.array(z.tuple([z.string(), z.string()])).optional(), + zoom: z.enum(['enabled', 'disabled', 'enable-on-click']).optional(), + curve: z.enum(['curveStepBefore', 'curveMonotoneX']).optional(), + }); +} + +const CatalogGraphEntityCard = createEntityCardExtension({ + name: 'catalog-graph', + configSchema: createSchemaFromZod(z => + z + .object({ + // Filter is a config required to all entity cards + filter: z.string().optional(), + title: z.string().optional(), + height: z.number().optional(), + variant: z.enum(['flex', 'fullHeight', 'gridItem']).optional(), + }) + .merge(getEntityGraphRelationsConfigSchema(z)), + ), + loader: async ({ config: { filter, ...props } }) => + import('./components/CatalogGraphCard').then(m => + compatWrapper(), + ), +}); + const CatalogGraphPage = createPageExtension({ defaultPath: '/catalog-graph', routeRef: convertLegacyRouteRef(catalogGraphRouteRef), configSchema: createSchemaFromZod(z => z.object({ + // Path is a default config required to all pages path: z.string().default('/catalog-graph'), - selectedKinds: z.array(z.string()).optional(), - selectedRelations: z.array(z.string()).optional(), - rootEntityRefs: z.array(z.string()).optional(), - maxDepth: z.number().optional(), - unidirectional: z.boolean().optional(), - mergeRelations: z.boolean().optional(), - direction: z.nativeEnum(Direction).optional(), - showFilters: z.boolean().optional(), - curve: z.enum(['curveStepBefore', 'curveMonotoneX']).optional(), + // Mapping intialState prop to config + initialState: z + .object({ + selectedKinds: z.array(z.string()).optional(), + selectedRelations: z.array(z.string()).optional(), + rootEntityRefs: z.array(z.string()).optional(), + maxDepth: z.number().optional(), + unidirectional: z.boolean().optional(), + mergeRelations: z.boolean().optional(), + direction: z.nativeEnum(Direction).optional(), + showFilters: z.boolean().optional(), + curve: z.enum(['curveStepBefore', 'curveMonotoneX']).optional(), + }) + .merge(getEntityGraphRelationsConfigSchema(z)) + .optional(), }), ), - loader: ({ config: { path, ...initialState } }) => + loader: ({ config: { path, ...props } }) => import('./components/CatalogGraphPage').then(m => - compatWrapper(), + compatWrapper(), ), }); @@ -58,5 +114,5 @@ export default createPlugin({ externalRoutes: { catalogEntity: convertLegacyRouteRef(catalogEntityRouteRef), }, - extensions: [CatalogGraphPage], + extensions: [CatalogGraphPage, CatalogGraphEntityCard], });