From d48165dde8f136805f379b7f4ee3c06daa1f27d1 Mon Sep 17 00:00:00 2001 From: Gustaf Lundh Date: Thu, 1 Dec 2022 14:15:17 +0100 Subject: [PATCH] Add useAllKinds & filterKinds() to both plugin-catalog and plugin-catalog-react We really don't want to expose and export the helper functions, hence some code duplication is needed (for now). Signed-off-by: Gustaf Lundh --- .../EntityKindPicker/EntityKindPicker.tsx | 2 +- .../EntityKindPicker}/kindFilterUtils.ts | 2 +- plugins/catalog-react/src/utils/index.ts | 1 - .../CatalogKindHeader/CatalogKindHeader.tsx | 5 +- .../CatalogKindHeader/kindFilterUtils.ts | 82 +++++++++++++++++++ 5 files changed, 85 insertions(+), 7 deletions(-) rename plugins/catalog-react/src/{utils => components/EntityKindPicker}/kindFilterUtils.ts (98%) create mode 100644 plugins/catalog/src/components/CatalogKindHeader/kindFilterUtils.ts diff --git a/plugins/catalog-react/src/components/EntityKindPicker/EntityKindPicker.tsx b/plugins/catalog-react/src/components/EntityKindPicker/EntityKindPicker.tsx index e0564d170e..65ec949b4a 100644 --- a/plugins/catalog-react/src/components/EntityKindPicker/EntityKindPicker.tsx +++ b/plugins/catalog-react/src/components/EntityKindPicker/EntityKindPicker.tsx @@ -20,7 +20,7 @@ import { Box } from '@material-ui/core'; import React, { useEffect, useMemo, useState } from 'react'; import { EntityKindFilter } from '../../filters'; import { useEntityList } from '../../hooks'; -import { filterKinds, useAllKinds } from '../../utils/kindFilterUtils'; +import { filterKinds, useAllKinds } from './kindFilterUtils'; function useEntityKindFilter(opts: { initialFilter: string }): { loading: boolean; diff --git a/plugins/catalog-react/src/utils/kindFilterUtils.ts b/plugins/catalog-react/src/components/EntityKindPicker/kindFilterUtils.ts similarity index 98% rename from plugins/catalog-react/src/utils/kindFilterUtils.ts rename to plugins/catalog-react/src/components/EntityKindPicker/kindFilterUtils.ts index 851dcfb702..aed4c41295 100644 --- a/plugins/catalog-react/src/utils/kindFilterUtils.ts +++ b/plugins/catalog-react/src/components/EntityKindPicker/kindFilterUtils.ts @@ -16,7 +16,7 @@ import { useApi } from '@backstage/core-plugin-api'; import useAsync from 'react-use/lib/useAsync'; -import { catalogApiRef } from '../api'; +import { catalogApiRef } from '../../api'; /** * Fetch and return all availible kinds. diff --git a/plugins/catalog-react/src/utils/index.ts b/plugins/catalog-react/src/utils/index.ts index 8262d1cc81..5afc32af63 100644 --- a/plugins/catalog-react/src/utils/index.ts +++ b/plugins/catalog-react/src/utils/index.ts @@ -18,4 +18,3 @@ export { getEntityRelations } from './getEntityRelations'; export { getEntitySourceLocation } from './getEntitySourceLocation'; export type { EntitySourceLocation } from './getEntitySourceLocation'; export { isOwnerOf } from './isOwnerOf'; -export { useAllKinds, filterKinds } from './kindFilterUtils'; diff --git a/plugins/catalog/src/components/CatalogKindHeader/CatalogKindHeader.tsx b/plugins/catalog/src/components/CatalogKindHeader/CatalogKindHeader.tsx index 0b27cf9ccb..8247116e4a 100644 --- a/plugins/catalog/src/components/CatalogKindHeader/CatalogKindHeader.tsx +++ b/plugins/catalog/src/components/CatalogKindHeader/CatalogKindHeader.tsx @@ -27,11 +27,8 @@ import { EntityKindFilter, useEntityList, } from '@backstage/plugin-catalog-react'; -import { - filterKinds, - useAllKinds, -} from '@backstage/plugin-catalog-react/src/utils'; import pluralize from 'pluralize'; +import { filterKinds, useAllKinds } from './kindFilterUtils'; const useStyles = makeStyles((theme: Theme) => createStyles({ diff --git a/plugins/catalog/src/components/CatalogKindHeader/kindFilterUtils.ts b/plugins/catalog/src/components/CatalogKindHeader/kindFilterUtils.ts new file mode 100644 index 0000000000..4f74d10a6c --- /dev/null +++ b/plugins/catalog/src/components/CatalogKindHeader/kindFilterUtils.ts @@ -0,0 +1,82 @@ +/* + * Copyright 2022 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 { useApi } from '@backstage/core-plugin-api'; +import { catalogApiRef } from '@backstage/plugin-catalog-react'; +import useAsync from 'react-use/lib/useAsync'; + +/** + * Fetch and return all availible kinds. + */ +export function useAllKinds(): { + loading: boolean; + error?: Error; + allKinds: string[]; +} { + const catalogApi = useApi(catalogApiRef); + + const { + error, + loading, + value: allKinds, + } = useAsync(async () => { + const items = await catalogApi + .getEntityFacets({ facets: ['kind'] }) + .then(response => response.facets.kind?.map(f => f.value).sort() || []); + return items; + }, [catalogApi]); + + return { loading, error, allKinds: allKinds ?? [] }; +} + +/** + * Filter and capitalize accessible kinds. + */ +export function filterKinds( + allKinds: string[], + allowedKinds?: string[], + forcedKinds?: string, +): Record { + // Before allKinds is loaded, or when a kind is entered manually in the URL, selectedKind may not + // be present in allKinds. It should still be shown in the dropdown, but may not have the nice + // enforced casing from the catalog-backend. This makes a key/value record for the Select options, + // including selectedKind if it's unknown - but allows the selectedKind to get clobbered by the + // more proper catalog kind if it exists. + let availableKinds = allKinds; + if (allowedKinds) { + availableKinds = availableKinds.filter(k => + allowedKinds.some( + a => a.toLocaleLowerCase('en-US') === k.toLocaleLowerCase('en-US'), + ), + ); + } + if ( + forcedKinds && + !allKinds.some( + a => + a.toLocaleLowerCase('en-US') === forcedKinds.toLocaleLowerCase('en-US'), + ) + ) { + availableKinds = availableKinds.concat([forcedKinds]); + } + + const kindsMap = availableKinds.sort().reduce((acc, kind) => { + acc[kind.toLocaleLowerCase('en-US')] = kind; + return acc; + }, {} as Record); + + return kindsMap; +}