chore: starting to add EntityAncestorsProcessingErrorsPanel
Signed-off-by: blam <ben@blam.sh>
This commit is contained in:
@@ -33,6 +33,8 @@ import {
|
||||
CatalogEntitiesRequest,
|
||||
CatalogListResponse,
|
||||
CatalogRequestOptions,
|
||||
CatalogEntityAncestorsRequest,
|
||||
CatalogEntityAncestorsResponse,
|
||||
} from './types/api';
|
||||
import { DiscoveryApi } from './types/discovery';
|
||||
|
||||
@@ -44,6 +46,24 @@ export class CatalogClient implements CatalogApi {
|
||||
this.discoveryApi = options.discoveryApi;
|
||||
}
|
||||
|
||||
async getEntityAncestors(
|
||||
request: CatalogEntityAncestorsRequest,
|
||||
options?: CatalogRequestOptions,
|
||||
): Promise<CatalogEntityAncestorsResponse> {
|
||||
const { kind, namespace, name } = Object.fromEntries(
|
||||
Object.entries(request.entityName).map(([k, v]) => [
|
||||
k,
|
||||
encodeURIComponent(v),
|
||||
]),
|
||||
);
|
||||
|
||||
return await this.requestRequired(
|
||||
'GET',
|
||||
`/entity/by-name/${kind}/${namespace}/${name}/ancestry`,
|
||||
options,
|
||||
);
|
||||
}
|
||||
|
||||
async getLocationById(
|
||||
id: string,
|
||||
options?: CatalogRequestOptions,
|
||||
|
||||
@@ -28,6 +28,17 @@ export type CatalogEntitiesRequest = {
|
||||
fields?: string[] | undefined;
|
||||
};
|
||||
|
||||
/** @public */
|
||||
export type CatalogEntityAncestorsRequest = {
|
||||
entityName: EntityName;
|
||||
};
|
||||
|
||||
/** @public */
|
||||
export type CatalogEntityAncestorsResponse = {
|
||||
root: EntityName;
|
||||
items: { entity: Entity; parents: EntityName[] }[];
|
||||
};
|
||||
|
||||
/** @public */
|
||||
export type CatalogListResponse<T> = {
|
||||
items: T[];
|
||||
@@ -45,6 +56,10 @@ export interface CatalogApi {
|
||||
request?: CatalogEntitiesRequest,
|
||||
options?: CatalogRequestOptions,
|
||||
): Promise<CatalogListResponse<Entity>>;
|
||||
getEntityAncestors(
|
||||
request: CatalogEntityAncestorsRequest,
|
||||
options?: CatalogRequestOptions,
|
||||
): Promise<CatalogEntityAncestorsResponse>;
|
||||
getEntityByName(
|
||||
name: EntityName,
|
||||
options?: CatalogRequestOptions,
|
||||
|
||||
+64
-15
@@ -14,20 +14,30 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { Entity, UNSTABLE_EntityStatusItem } from '@backstage/catalog-model';
|
||||
import { useEntity } from '@backstage/plugin-catalog-react';
|
||||
import {
|
||||
Entity,
|
||||
getEntityName,
|
||||
UNSTABLE_EntityStatusItem,
|
||||
} from '@backstage/catalog-model';
|
||||
import { catalogApiRef, useEntity } from '@backstage/plugin-catalog-react';
|
||||
import { Box } from '@material-ui/core';
|
||||
import React from 'react';
|
||||
import { ResponseErrorPanel } from '@backstage/core-components';
|
||||
import { ENTITY_STATUS_CATALOG_PROCESSING_TYPE } from '@backstage/catalog-client';
|
||||
import { useApi } from '@backstage/core-plugin-api';
|
||||
import { useAsync } from 'react-use';
|
||||
|
||||
const errorfilter = (i: UNSTABLE_EntityStatusItem) =>
|
||||
const errorFilter = (i: UNSTABLE_EntityStatusItem) =>
|
||||
i.error &&
|
||||
i.level === 'error' &&
|
||||
i.type === ENTITY_STATUS_CATALOG_PROCESSING_TYPE;
|
||||
|
||||
export const hasCatalogProcessingErrors = (entity: Entity) =>
|
||||
entity?.status?.items?.filter(errorfilter).length! > 0;
|
||||
export const hasCatalogProcessingErrors = async (entity: Entity) => {
|
||||
return entity?.status?.items?.filter(errorFilter).length! > 0;
|
||||
const catalogApi = useApi(catalogApiRef);
|
||||
const { status } = await catalogApi.getEntityStatus(entity.id);
|
||||
return status.some(errorFilter);
|
||||
};
|
||||
|
||||
/**
|
||||
* Displays a list of errors if the entity is invalid.
|
||||
@@ -36,16 +46,55 @@ export const EntityProcessingErrorsPanel = () => {
|
||||
const { entity } = useEntity();
|
||||
const catalogProcessingErrors =
|
||||
(entity?.status?.items?.filter(
|
||||
errorfilter,
|
||||
errorFilter,
|
||||
) as Required<UNSTABLE_EntityStatusItem>[]) || [];
|
||||
|
||||
return (
|
||||
<>
|
||||
{catalogProcessingErrors.map(({ error }, index) => (
|
||||
<Box key={index} mb={1}>
|
||||
<ResponseErrorPanel error={error} />
|
||||
</Box>
|
||||
))}
|
||||
</>
|
||||
);
|
||||
return catalogProcessingErrors.map(({ error }, index) => (
|
||||
<Box key={index} mb={1}>
|
||||
<ResponseErrorPanel error={error} />
|
||||
</Box>
|
||||
));
|
||||
};
|
||||
|
||||
/**
|
||||
* Displays a list of errors from the ancestors of the current entity.
|
||||
*/
|
||||
export const EntityAncestorsProcessingErrorsPanel = () => {
|
||||
const { entity } = useEntity();
|
||||
const catalogApi = useApi(catalogApiRef);
|
||||
|
||||
const { loading, value, error } = useAsync(() =>
|
||||
catalogApi.getEntityAncestors({ entityName: getEntityName(entity) }),
|
||||
);
|
||||
|
||||
if (loading) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (error) {
|
||||
return (
|
||||
<Box mb={1}>
|
||||
<ResponseErrorPanel error={error} />
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
|
||||
const ancestorErrors =
|
||||
value?.items.flatMap(({ entity: ancestor }) =>
|
||||
ancestor?.status?.items?.filter?.(errorFilter),
|
||||
) ?? [];
|
||||
|
||||
if (ancestorErrors.length === 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const filteredAncestors = ancestorErrors.filter(
|
||||
(e): e is UNSTABLE_EntityStatusItem => Boolean(e),
|
||||
);
|
||||
|
||||
return filteredAncestors.map(({ error: ancestorError }, index) => (
|
||||
<Box key={index} mb={1}>
|
||||
<ResponseErrorPanel error={ancestorError!} />
|
||||
</Box>
|
||||
));
|
||||
};
|
||||
|
||||
@@ -32,7 +32,7 @@ const EntitySwitchCase = (_: {
|
||||
attachComponentData(EntitySwitchCase, ENTITY_SWITCH_KEY, true);
|
||||
|
||||
type SwitchCase = {
|
||||
if?: (entity: Entity) => boolean;
|
||||
if?: (entity: Entity) => boolean | Promise<boolean>;
|
||||
children: JSX.Element;
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user