From 03f5d1c644859b33b2eba6d5abf9739d493b2e55 Mon Sep 17 00:00:00 2001 From: Juan Escalada Date: Fri, 25 Oct 2024 18:33:36 +0900 Subject: [PATCH 1/6] Add custom column example for existing Kind Signed-off-by: Juan Escalada --- .../software-catalog/catalog-customization.md | 46 ++++++++++++++++++- 1 file changed, 45 insertions(+), 1 deletion(-) diff --git a/docs/features/software-catalog/catalog-customization.md b/docs/features/software-catalog/catalog-customization.md index 0c8eb7bcda..2f97874336 100644 --- a/docs/features/software-catalog/catalog-customization.md +++ b/docs/features/software-catalog/catalog-customization.md @@ -63,7 +63,51 @@ There are many options that can be set using `tableOptions`, the full list of se ## Customize Columns -By default the columns you see in the `CatalogIndexPage` were selected to be a good starting point for most but there may be reasons that you would like to customize these with more or less columns. One primary use case for this customization is if you added a custom Kind. Support for this was added in v1.23.0 of Backstage, make sure you are on that version or newer to use this feature. Here's an example of how to make this customization: +The columns you see in the `CatalogIndexPage` were selected to be a good starting point for most, but there may be cases where you would like to add or remove columns from existing or custom Kinds. + +### Adding a column to an existing Kind + +Suppose we want to add a new User Email column to the `User` kind in the Catalog. We can do this by creating a new column factory in `/plugins/catalog/src/components/CatalogTable/columns.tsx`: + +```tsx title="packages/catalog/src/components/CatalogTable/columns.tsx" +export const columnFactories = Object.freeze({ + createNameColumn(options?: { + defaultKind?: string; + }): TableColumn { + // ... + createUserEmailColumn(): TableColumn { + return { + title: 'User Email', + field: 'entity.spec?.profile?.["email"]', + render: ({ entity }) => ( + + ), + }; + }, + } +}); +``` + +Then, we can call this new column factory in `/plugins/catalog/src/components/CatalogTable/defaultCatalogTableColumnsFunc.tsx`: + +```tsx title="packages/catalog/src/components/CatalogTable/defaultCatalogTableColumnsFunc.tsx" +// ... + switch (filters.kind?.value) { + case 'user': + return [ + ...descriptionTagColumns, + {/* highlight-add-next-line */} + columnFactories.createUserEmailColumn(), + ]; +// ... +``` + +### Adding columns to a custom or specific Kind + +Another use case for customization is when adding a custom `Kind`. This feature is available in Backstage >= `v1.23.0`. For example: ```tsx title="packages/app/src/App.tsx" import { From db32340cb130fcae9e0fc9e150c7e4dd1098e8d1 Mon Sep 17 00:00:00 2001 From: Juan Escalada Date: Fri, 25 Oct 2024 18:46:02 +0900 Subject: [PATCH 2/6] Improve wording Signed-off-by: Juan Escalada --- .../software-catalog/catalog-customization.md | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/docs/features/software-catalog/catalog-customization.md b/docs/features/software-catalog/catalog-customization.md index 2f97874336..8a66342aea 100644 --- a/docs/features/software-catalog/catalog-customization.md +++ b/docs/features/software-catalog/catalog-customization.md @@ -75,6 +75,7 @@ export const columnFactories = Object.freeze({ defaultKind?: string; }): TableColumn { // ... + {/* highlight-add-start */} createUserEmailColumn(): TableColumn { return { title: 'User Email', @@ -87,6 +88,7 @@ export const columnFactories = Object.freeze({ ), }; }, + {/* highlight-add-end */} } }); ``` @@ -141,7 +143,7 @@ const myColumnsFunc: CatalogTableColumnsFunc = entityListContext => { :::note Note -The above example has been simplified and you will most likely have more code then just this in your `App.tsx` file. +In the examples above, the contents of the files have been shortened for simplicity. ::: @@ -212,15 +214,15 @@ const customActions: TableProps['actions'] = [ :::note Note -The above example has been simplified and you will most likely have more code then just this in your `App.tsx` file. +In the example above, the contents of `App.tsx` has been shortened for simplicity. ::: -The above customization will override the existing actions. Currently the only way to keep them and add your own is to also include the existing actions in your array by copying them from the [`defaultActions`](https://github.com/backstage/backstage/blob/57397e7d6d2d725712c439f4ab93f2ac6aa27bf8/plugins/catalog/src/components/CatalogTable/CatalogTable.tsx#L113-L168). +The above customization will override the existing actions. Currently, the only way to keep them and add your own is to also include the existing actions in your array by copying them from the [`defaultActions`](https://github.com/backstage/backstage/blob/57397e7d6d2d725712c439f4ab93f2ac6aa27bf8/plugins/catalog/src/components/CatalogTable/CatalogTable.tsx#L113-L168). ## Customize Filters -There are three options you have for filters: adjusting the existing filters with props, adding or removing the default filters, or creating a brand new custom filter. The following sections cover these cases +There are various ways to customize filters: adjusting the existing filters with props, adding or removing default filters, creating brand-new custom filters, etc. The following sections cover these cases: ### Default Filter Props @@ -249,7 +251,7 @@ import { DefaultFilters } from '@backstage/plugin-catalog-react'; ### Removing Default Filters -You may have reasons not use the Lifecycle, Tag, and Processing Status filters, here's an example of how you would remove them: +If you have reasons not to use the Lifecycle, Tag, and Processing Status filters, here's an example of how to remove them: ```tsx title="packages/app/src/App.tsx" import { @@ -280,7 +282,7 @@ import { ### Custom Filters -You can add custom filters. For example, suppose that I want to allow filtering by a custom annotation added to entities, `company.com/security-tier`. Here is how we can build a filter to support that need. +You can add custom filters. For example, suppose that we want to allow filtering by a custom annotation added to entities, `company.com/security-tier`. Here is how we can build a filter to support that need. First we need to create a new filter that implements the `EntityFilter` interface: From 7a462f286ed339e9ab9ece1043b91fc867305062 Mon Sep 17 00:00:00 2001 From: Juan Escalada Date: Thu, 7 Nov 2024 13:12:49 +0900 Subject: [PATCH 3/6] Fix custom column example Signed-off-by: Juan Escalada --- .../software-catalog/catalog-customization.md | 103 ++++++++++++------ 1 file changed, 71 insertions(+), 32 deletions(-) diff --git a/docs/features/software-catalog/catalog-customization.md b/docs/features/software-catalog/catalog-customization.md index 8a66342aea..63556b1626 100644 --- a/docs/features/software-catalog/catalog-customization.md +++ b/docs/features/software-catalog/catalog-customization.md @@ -67,44 +67,83 @@ The columns you see in the `CatalogIndexPage` were selected to be a good startin ### Adding a column to an existing Kind -Suppose we want to add a new User Email column to the `User` kind in the Catalog. We can do this by creating a new column factory in `/plugins/catalog/src/components/CatalogTable/columns.tsx`: +Suppose we want to add a new User Email column to the `User` kind in the Catalog. We can do this by overriding the `columns` that we pass into the `CatalogIndexPage` component in our `App.tsx`. First, we need to match the entity kind that we want to override, and then define the columns to show: -```tsx title="packages/catalog/src/components/CatalogTable/columns.tsx" -export const columnFactories = Object.freeze({ - createNameColumn(options?: { - defaultKind?: string; - }): TableColumn { - // ... - {/* highlight-add-start */} - createUserEmailColumn(): TableColumn { - return { - title: 'User Email', - field: 'entity.spec?.profile?.["email"]', - render: ({ entity }) => ( - - ), - }; - }, - {/* highlight-add-end */} +```tsx title="packages/app/src/App.tsx" +{ + /* highlight-add-start */ +} +const myColumnsFunc: CatalogTableColumnsFunc = entityListContext => { + if (entityListContext.filters.kind?.value === 'user') { + return [ + // Existing columns (Name, Description, Tags) + CatalogTable.columns.createNameColumn(), + CatalogTable.columns.createMetadataDescriptionColumn(), + CatalogTable.columns.createTagsColumn(), + // Add new columns here + ]; } -}); + + return CatalogTable.defaultColumnsFunc(entityListContext); +}; +{ + /* highlight-add-end */ +} ``` -Then, we can call this new column factory in `/plugins/catalog/src/components/CatalogTable/defaultCatalogTableColumnsFunc.tsx`: +Some other possible values for the existing entity kinds are `user`, `domain`, `system`, `group`, `template` and `location`. -```tsx title="packages/catalog/src/components/CatalogTable/defaultCatalogTableColumnsFunc.tsx" -// ... - switch (filters.kind?.value) { - case 'user': - return [ - ...descriptionTagColumns, +Then, we can implement the `createUserEmailColumn` function and add it to the list of columns. `field` is used to access the data from the entity, while `render` lets us customize how we display the data: + +```tsx title="packages/app/src/App.tsx" +{/* highlight-add-start */} +const createUserEmailColumn = (): TableColumn => ({ + title: 'User Email', + field: 'entity.spec.profile.email', + render: ({ entity }) => ( + + ), +}); +{/* highlight-add-end */} + +const myColumnsFunc: CatalogTableColumnsFunc = entityListContext => { + if (entityListContext.filters.kind?.value === 'user') { + return [ + // Existing columns (Name, Description, Tags) + CatalogTable.columns.createNameColumn(), + CatalogTable.columns.createMetadataDescriptionColumn(), + CatalogTable.columns.createTagsColumn(), + // Add new columns here + {/* highlight-add-next-line */} + createUserEmailColumn(), + ]; + } + + return CatalogTable.defaultColumnsFunc(entityListContext); +}; +``` + +Finally, we can pass the `myColumnsFunc` to the `CatalogIndexPage` component: + +```tsx title="packages/app/src/App.tsx" +const routes = ( + + + } + /> + {/* Other routes */} + +) ``` ### Adding columns to a custom or specific Kind From 21af8faf5a119f86f1e416a74daa8a4ad9ba4ed3 Mon Sep 17 00:00:00 2001 From: Juan Escalada <97265671+jescalada@users.noreply.github.com> Date: Mon, 18 Nov 2024 19:28:16 -0800 Subject: [PATCH 4/6] Update docs/features/software-catalog/catalog-customization.md Co-authored-by: Vincenzo Scamporlino Signed-off-by: Juan Escalada <97265671+jescalada@users.noreply.github.com> --- docs/features/software-catalog/catalog-customization.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/docs/features/software-catalog/catalog-customization.md b/docs/features/software-catalog/catalog-customization.md index 63556b1626..c3355f53b4 100644 --- a/docs/features/software-catalog/catalog-customization.md +++ b/docs/features/software-catalog/catalog-customization.md @@ -91,8 +91,6 @@ const myColumnsFunc: CatalogTableColumnsFunc = entityListContext => { } ``` -Some other possible values for the existing entity kinds are `user`, `domain`, `system`, `group`, `template` and `location`. - Then, we can implement the `createUserEmailColumn` function and add it to the list of columns. `field` is used to access the data from the entity, while `render` lets us customize how we display the data: ```tsx title="packages/app/src/App.tsx" From 63d121cc56d19bc2a5ba6f6989c8ee678288c43b Mon Sep 17 00:00:00 2001 From: Juan Escalada <97265671+jescalada@users.noreply.github.com> Date: Mon, 18 Nov 2024 19:28:59 -0800 Subject: [PATCH 5/6] Update docs/features/software-catalog/catalog-customization.md Co-authored-by: Vincenzo Scamporlino Signed-off-by: Juan Escalada <97265671+jescalada@users.noreply.github.com> --- docs/features/software-catalog/catalog-customization.md | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/docs/features/software-catalog/catalog-customization.md b/docs/features/software-catalog/catalog-customization.md index c3355f53b4..98d1af9b3d 100644 --- a/docs/features/software-catalog/catalog-customization.md +++ b/docs/features/software-catalog/catalog-customization.md @@ -76,10 +76,8 @@ Suppose we want to add a new User Email column to the `User` kind in the Catalog const myColumnsFunc: CatalogTableColumnsFunc = entityListContext => { if (entityListContext.filters.kind?.value === 'user') { return [ - // Existing columns (Name, Description, Tags) - CatalogTable.columns.createNameColumn(), - CatalogTable.columns.createMetadataDescriptionColumn(), - CatalogTable.columns.createTagsColumn(), + // Render existing columns + ...CatalogTable.defaultColumnsFunc(entityListContext), // Add new columns here ]; } From 6d0b7bc126d3dbc30ef8139b3545787bbd46cc89 Mon Sep 17 00:00:00 2001 From: Juan Escalada <97265671+jescalada@users.noreply.github.com> Date: Mon, 18 Nov 2024 19:29:30 -0800 Subject: [PATCH 6/6] Update docs/features/software-catalog/catalog-customization.md Co-authored-by: Vincenzo Scamporlino Signed-off-by: Juan Escalada <97265671+jescalada@users.noreply.github.com> --- docs/features/software-catalog/catalog-customization.md | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/docs/features/software-catalog/catalog-customization.md b/docs/features/software-catalog/catalog-customization.md index 98d1af9b3d..c56f763a4e 100644 --- a/docs/features/software-catalog/catalog-customization.md +++ b/docs/features/software-catalog/catalog-customization.md @@ -108,10 +108,9 @@ const createUserEmailColumn = (): TableColumn => ({ const myColumnsFunc: CatalogTableColumnsFunc = entityListContext => { if (entityListContext.filters.kind?.value === 'user') { return [ - // Existing columns (Name, Description, Tags) - CatalogTable.columns.createNameColumn(), - CatalogTable.columns.createMetadataDescriptionColumn(), - CatalogTable.columns.createTagsColumn(), + return [ + // Render existing columns + ...CatalogTable.defaultColumnsFunc(entityListContext), // Add new columns here {/* highlight-add-next-line */} createUserEmailColumn(),