update useEntityTypeFilter too
Signed-off-by: Fredrik Adelöw <freben@gmail.com>
This commit is contained in:
@@ -8,6 +8,7 @@
|
||||
'@backstage/plugin-catalog-react': patch
|
||||
'@backstage/plugin-explore': patch
|
||||
'@backstage/plugin-fossa': patch
|
||||
'@backstage/plugin-scaffolder': patch
|
||||
'@backstage/plugin-todo-backend': patch
|
||||
---
|
||||
|
||||
|
||||
@@ -26,6 +26,7 @@ import { EntityKindFilter, EntityTypeFilter } from '../../filters';
|
||||
import { alertApiRef } from '@backstage/core-plugin-api';
|
||||
import { ApiProvider } from '@backstage/core-app-api';
|
||||
import { renderWithEffects, TestApiRegistry } from '@backstage/test-utils';
|
||||
import { GetEntityFacetsResponse } from '@backstage/catalog-client';
|
||||
|
||||
const entities: Entity[] = [
|
||||
{
|
||||
@@ -64,7 +65,14 @@ const apis = TestApiRegistry.from(
|
||||
[
|
||||
catalogApiRef,
|
||||
{
|
||||
getEntities: jest.fn().mockResolvedValue({ items: entities }),
|
||||
getEntityFacets: jest.fn().mockResolvedValue({
|
||||
facets: {
|
||||
'spec.type': entities.map(e => ({
|
||||
value: (e.spec as any).type,
|
||||
count: 1,
|
||||
})),
|
||||
},
|
||||
} as GetEntityFacetsResponse),
|
||||
},
|
||||
],
|
||||
[
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
import { useEffect, useMemo, useRef, useState } from 'react';
|
||||
import useAsync from 'react-use/lib/useAsync';
|
||||
import isEqual from 'lodash/isEqual';
|
||||
import sortBy from 'lodash/sortBy';
|
||||
import { useApi } from '@backstage/core-plugin-api';
|
||||
import { catalogApiRef } from '../api';
|
||||
import { useEntityListProvider } from './useEntityListProvider';
|
||||
@@ -67,51 +68,34 @@ export function useEntityTypeFilter(): EntityTypeReturn {
|
||||
const {
|
||||
error,
|
||||
loading,
|
||||
value: entities,
|
||||
value: facets,
|
||||
} = useAsync(async () => {
|
||||
if (kind) {
|
||||
const items = await catalogApi
|
||||
.getEntities({
|
||||
.getEntityFacets({
|
||||
filter: { kind },
|
||||
fields: ['spec.type'],
|
||||
facets: ['spec.type'],
|
||||
})
|
||||
.then(response => response.items);
|
||||
.then(response => response.facets['spec.type'] || []);
|
||||
return items;
|
||||
}
|
||||
return [];
|
||||
}, [kind, catalogApi]);
|
||||
|
||||
const entitiesRef = useRef(entities);
|
||||
const facetsRef = useRef(facets);
|
||||
useEffect(() => {
|
||||
const oldEntities = entitiesRef.current;
|
||||
entitiesRef.current = entities;
|
||||
// Delay processing hook until kind and entity load updates have settled to generate list of types;
|
||||
// This prevents reseting the type filter due to saved type value from query params not matching the
|
||||
const oldFacets = facetsRef.current;
|
||||
facetsRef.current = facets;
|
||||
// Delay processing hook until kind and facets load updates have settled to generate list of types;
|
||||
// This prevents resetting the type filter due to saved type value from query params not matching the
|
||||
// empty set of type values while values are still being loaded; also only run this hook on changes
|
||||
// to entities
|
||||
if (loading || !kind || oldEntities === entities) {
|
||||
// to facets
|
||||
if (loading || !kind || oldFacets === facets || !facets) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Resolve the unique set of types from returned entities; could be optimized by a new endpoint
|
||||
// in the catalog-backend that does this, rather than loading entities with redundant types.
|
||||
if (!entities) return;
|
||||
|
||||
// Sort by entity count descending, so the most common types appear on top
|
||||
const countByType = entities.reduce((acc, entity) => {
|
||||
if (typeof entity.spec?.type !== 'string') return acc;
|
||||
|
||||
const entityType = entity.spec.type.toLocaleLowerCase('en-US');
|
||||
if (!acc[entityType]) {
|
||||
acc[entityType] = 0;
|
||||
}
|
||||
acc[entityType] += 1;
|
||||
return acc;
|
||||
}, {} as Record<string, number>);
|
||||
|
||||
const newTypes = Object.entries(countByType)
|
||||
.sort(([, count1], [, count2]) => count2 - count1)
|
||||
.map(([type]) => type);
|
||||
// Sort by facet count descending, so the most common types appear on top
|
||||
const newTypes = sortBy(facets, f => -f.count).map(f => f.value);
|
||||
setAvailableTypes(newTypes);
|
||||
|
||||
// Update type filter to only valid values when the list of available types has changed
|
||||
@@ -121,7 +105,7 @@ export function useEntityTypeFilter(): EntityTypeReturn {
|
||||
if (!isEqual(selectedTypes, stillValidTypes)) {
|
||||
setSelectedTypes(stillValidTypes);
|
||||
}
|
||||
}, [loading, kind, selectedTypes, setSelectedTypes, entities]);
|
||||
}, [loading, kind, selectedTypes, setSelectedTypes, facets]);
|
||||
|
||||
useEffect(() => {
|
||||
updateFilters({
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
import React from 'react';
|
||||
import { fireEvent } from '@testing-library/react';
|
||||
import { GetEntityFacetsResponse } from '@backstage/catalog-client';
|
||||
import { Entity } from '@backstage/catalog-model';
|
||||
import {
|
||||
catalogApiRef,
|
||||
@@ -60,7 +61,15 @@ const entities: Entity[] = [
|
||||
const apis = TestApiRegistry.from([
|
||||
catalogApiRef,
|
||||
{
|
||||
getEntities: jest.fn().mockResolvedValue({ items: entities }),
|
||||
getEntityFacets: jest.fn().mockResolvedValue({
|
||||
facets: {
|
||||
kind: [
|
||||
{ value: 'Component', count: 2 },
|
||||
{ value: 'Template', count: 1 },
|
||||
{ value: 'System', count: 1 },
|
||||
],
|
||||
},
|
||||
} as GetEntityFacetsResponse),
|
||||
},
|
||||
]);
|
||||
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
import React from 'react';
|
||||
import { fireEvent } from '@testing-library/react';
|
||||
import { capitalize } from 'lodash';
|
||||
import { CatalogApi } from '@backstage/catalog-client';
|
||||
import { Entity } from '@backstage/catalog-model';
|
||||
import { TemplateTypePicker } from './TemplateTypePicker';
|
||||
import {
|
||||
@@ -28,6 +27,7 @@ import {
|
||||
import { AlertApi, alertApiRef } from '@backstage/core-plugin-api';
|
||||
import { ApiProvider } from '@backstage/core-app-api';
|
||||
import { renderWithEffects, TestApiRegistry } from '@backstage/test-utils';
|
||||
import { GetEntityFacetsResponse } from '@backstage/catalog-client';
|
||||
|
||||
const entities: Entity[] = [
|
||||
{
|
||||
@@ -66,10 +66,15 @@ const apis = TestApiRegistry.from(
|
||||
[
|
||||
catalogApiRef,
|
||||
{
|
||||
getEntities: jest
|
||||
.fn()
|
||||
.mockImplementation(() => Promise.resolve({ items: entities })),
|
||||
} as unknown as CatalogApi,
|
||||
getEntityFacets: jest.fn().mockResolvedValue({
|
||||
facets: {
|
||||
'spec.type': entities.map(e => ({
|
||||
value: (e.spec as any).type,
|
||||
count: 1,
|
||||
})),
|
||||
},
|
||||
} as GetEntityFacetsResponse),
|
||||
},
|
||||
],
|
||||
[
|
||||
alertApiRef,
|
||||
|
||||
Reference in New Issue
Block a user