From 26c27f4f808eaeab6ed7d6249ef25205d023174b Mon Sep 17 00:00:00 2001 From: Aramis Sennyey Date: Thu, 23 Feb 2023 10:44:10 -0500 Subject: [PATCH] Update EntityPicker to use stringifyEntityRef. Signed-off-by: Aramis Sennyey --- .../src/components/EntityRefLink/humanize.ts | 8 --- .../fields/EntityPicker/EntityPicker.test.tsx | 50 +++++++++++++++++++ .../fields/EntityPicker/EntityPicker.tsx | 38 ++++++++++---- 3 files changed, 79 insertions(+), 17 deletions(-) diff --git a/plugins/catalog-react/src/components/EntityRefLink/humanize.ts b/plugins/catalog-react/src/components/EntityRefLink/humanize.ts index 9abf0d7978..9bbfcbc1ed 100644 --- a/plugins/catalog-react/src/components/EntityRefLink/humanize.ts +++ b/plugins/catalog-react/src/components/EntityRefLink/humanize.ts @@ -37,19 +37,11 @@ export function humanizeEntityRef( let kind; let namespace; let name; - console.log(entityRef); if ('metadata' in entityRef) { kind = entityRef.kind; namespace = entityRef.metadata.namespace; name = entityRef.metadata.name; - - // Escapes when we know more about an entity. - if (entityRef.metadata.title) { - return entityRef.metadata.title; - } else if ((entityRef as UserEntity).spec?.profile?.displayName) { - return (entityRef as UserEntity).spec?.profile?.displayName; - } } else { kind = entityRef.kind; namespace = entityRef.namespace; diff --git a/plugins/scaffolder/src/components/fields/EntityPicker/EntityPicker.test.tsx b/plugins/scaffolder/src/components/fields/EntityPicker/EntityPicker.test.tsx index b6d6688a09..3cc45e6412 100644 --- a/plugins/scaffolder/src/components/fields/EntityPicker/EntityPicker.test.tsx +++ b/plugins/scaffolder/src/components/fields/EntityPicker/EntityPicker.test.tsx @@ -236,4 +236,54 @@ describe('', () => { }); }); }); + + describe('uses full entity ref', () => { + beforeEach(() => { + uiSchema = { + 'ui:options': { + defaultKind: 'Group', + }, + }; + props = { + onChange, + schema, + required, + uiSchema, + rawErrors, + formData, + } as unknown as FieldProps; + + catalogApi.getEntities.mockResolvedValue({ items: entities }); + }); + + it('returns the full entityRef when entity exists in the list', async () => { + const { getByRole } = await renderInTestApp( + + + , + ); + + const input = getByRole('textbox'); + + fireEvent.change(input, { target: { value: 'team-a' } }); + fireEvent.blur(input); + + expect(onChange).toHaveBeenCalledWith('group:default/team-a'); + }); + + it('returns the full entityRef when entity does not exist in the list', async () => { + const { getByRole } = await renderInTestApp( + + + , + ); + + const input = getByRole('textbox'); + + fireEvent.change(input, { target: { value: 'team-b' } }); + fireEvent.blur(input); + + expect(onChange).toHaveBeenCalledWith('group:default/team-b'); + }); + }); }); diff --git a/plugins/scaffolder/src/components/fields/EntityPicker/EntityPicker.tsx b/plugins/scaffolder/src/components/fields/EntityPicker/EntityPicker.tsx index 2a36b9f8ef..48d6453ab9 100644 --- a/plugins/scaffolder/src/components/fields/EntityPicker/EntityPicker.tsx +++ b/plugins/scaffolder/src/components/fields/EntityPicker/EntityPicker.tsx @@ -58,7 +58,8 @@ export const EntityPicker = (props: EntityPickerProps) => { (allowedKinds && { kind: allowedKinds }); const defaultKind = uiSchema['ui:options']?.defaultKind; - const defaultNamespace = uiSchema['ui:options']?.defaultNamespace; + const defaultNamespace = + uiSchema['ui:options']?.defaultNamespace || undefined; const catalogApi = useApi(catalogApiRef); @@ -71,13 +72,30 @@ export const EntityPicker = (props: EntityPickerProps) => { const allowArbitraryValues = uiSchema['ui:options']?.allowArbitraryValues ?? true; + const getLabel = useCallback( + (ref: string) => { + try { + return humanizeEntityRef( + parseEntityRef(ref, { defaultKind, defaultNamespace }), + { + defaultKind, + defaultNamespace, + }, + ); + } catch (err) { + return ref; + } + }, + [defaultKind, defaultNamespace], + ); + const onSelect = useCallback( (_: any, ref: string | Entity | null, reason: AutocompleteChangeReason) => { - // if ref == string + // ref can either be a string from free solo entry or if (typeof ref !== 'string') { onChange(ref ? stringifyEntityRef(ref as Entity) : ''); } else { - if (reason === 'blur') { + if (reason === 'blur' || reason === 'create-option') { // Add in default namespace, etc. let entityRef = ref; try { @@ -85,19 +103,20 @@ export const EntityPicker = (props: EntityPickerProps) => { entityRef = stringifyEntityRef( parseEntityRef(ref as string, { defaultKind, - defaultNamespace: defaultNamespace || undefined, + defaultNamespace, }), ); } catch (err) { // If the passed in value isn't an entity ref, do nothing. } - if (formData !== entityRef) { - onChange(ref); + // We need to check against formData here as that's the previous value for this field. + if (formData !== ref || allowArbitraryValues) { + onChange(entityRef); } } } }, - [onChange, formData, defaultKind, defaultNamespace], + [onChange, formData, defaultKind, defaultNamespace, allowArbitraryValues], ); useEffect(() => { @@ -116,9 +135,10 @@ export const EntityPicker = (props: EntityPickerProps) => { disabled={entities?.length === 1} id={idSchema?.$id} value={ - // Since free solo is usually enabled, attempt to + // Since free solo can be enabled, attempt to parse as a full entity ref first, then fall + // back to the given value. entities?.find(e => stringifyEntityRef(e) === formData) ?? - (allowArbitraryValues ? formData : '') + (allowArbitraryValues && formData ? getLabel(formData) : '') } loading={loading} onChange={onSelect}