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}