diff --git a/plugins/scaffolder/src/components/ScaffolderPage/ScaffolderPage.tsx b/plugins/scaffolder/src/components/ScaffolderPage/ScaffolderPage.tsx index df537600c4..10468b07e0 100644 --- a/plugins/scaffolder/src/components/ScaffolderPage/ScaffolderPage.tsx +++ b/plugins/scaffolder/src/components/ScaffolderPage/ScaffolderPage.tsx @@ -35,12 +35,12 @@ import StarIcon from '@material-ui/icons/Star'; import React, { useEffect, useMemo, useState } from 'react'; import { Link as RouterLink } from 'react-router-dom'; import { EntityFilterGroupsProvider, useFilteredEntities } from '../../filter'; +import { registerComponentRouteRef } from '../../routes'; import { ResultsFilter } from '../ResultsFilter/ResultsFilter'; import { ScaffolderFilter } from '../ScaffolderFilter'; import { ButtonGroup } from '../ScaffolderFilter/ScaffolderFilter'; import SearchToolbar from '../SearchToolbar/SearchToolbar'; import { TemplateCard } from '../TemplateCard'; -import { registerComponentRouteRef } from '../../routes'; const useStyles = makeStyles(theme => ({ contentWrapper: { @@ -174,7 +174,7 @@ export const ScaffolderPageContents = () => { {matchingEntities && matchingEntities?.length > 0 && - matchingEntities.map(template => ( + matchingEntities.map((template, i) => ( { +}: FieldProps) => { const allowedKinds = uiSchema['ui:options']?.allowedKinds as string[]; const defaultKind = uiSchema['ui:options']?.defaultKind as string | undefined; const catalogApi = useApi(catalogApiRef); diff --git a/plugins/scaffolder/src/components/fields/EntityPicker/index.ts b/plugins/scaffolder/src/components/fields/EntityPicker/index.ts index d307940e2f..4f7d543afb 100644 --- a/plugins/scaffolder/src/components/fields/EntityPicker/index.ts +++ b/plugins/scaffolder/src/components/fields/EntityPicker/index.ts @@ -13,4 +13,4 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -export * from './EntityPicker'; +export { EntityPicker } from './EntityPicker'; diff --git a/plugins/scaffolder/src/components/fields/OwnerPicker/OwnerPicker.test.tsx b/plugins/scaffolder/src/components/fields/OwnerPicker/OwnerPicker.test.tsx index 5d98fcdd9f..d618b66504 100644 --- a/plugins/scaffolder/src/components/fields/OwnerPicker/OwnerPicker.test.tsx +++ b/plugins/scaffolder/src/components/fields/OwnerPicker/OwnerPicker.test.tsx @@ -14,14 +14,12 @@ * limitations under the License. */ -import React from 'react'; +import { Entity } from '@backstage/catalog-model'; import { ApiProvider, ApiRegistry } from '@backstage/core'; import { CatalogApi, catalogApiRef } from '@backstage/plugin-catalog-react'; import { renderInTestApp } from '@backstage/test-utils'; -import userEvent from '@testing-library/user-event'; -import { Entity } from '@backstage/catalog-model'; import { FieldProps } from '@rjsf/core'; - +import React from 'react'; import { OwnerPicker } from './OwnerPicker'; const makeEntity = (kind: string, namespace: string, name: string): Entity => ({ @@ -93,20 +91,6 @@ describe('', () => { }, }); }); - - it('updates even if there is not an exact match', async () => { - const { getByLabelText } = await renderInTestApp( - - - , - ); - const input = getByLabelText('Owner'); - - userEvent.type(input, 'squ'); - input.blur(); - - expect(onChange).toHaveBeenCalledWith('squ'); - }); }); describe('with allowedKinds', () => { diff --git a/plugins/scaffolder/src/components/fields/OwnerPicker/OwnerPicker.tsx b/plugins/scaffolder/src/components/fields/OwnerPicker/OwnerPicker.tsx index 39183a856f..bbcb141b05 100644 --- a/plugins/scaffolder/src/components/fields/OwnerPicker/OwnerPicker.tsx +++ b/plugins/scaffolder/src/components/fields/OwnerPicker/OwnerPicker.tsx @@ -13,81 +13,31 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import React from 'react'; import { FieldProps } from '@rjsf/core'; -import { catalogApiRef } from '@backstage/plugin-catalog-react'; -import { useApi } from '@backstage/core'; -import { useAsync } from 'react-use'; -import Autocomplete from '@material-ui/lab/Autocomplete'; -import FormControl from '@material-ui/core/FormControl'; -import { Entity } from '@backstage/catalog-model'; -import { TextField } from '@material-ui/core'; - -const entityRef = (entity: Entity | undefined): string => { - if (!entity) { - return ''; - } - const { - kind, - metadata: { namespace, name }, - } = entity; - - const namespacePart = - !namespace || namespace === 'default' ? '' : `${namespace}/`; - const kindPart = kind.toLowerCase() === 'group' ? '' : `${kind}:`; - - return `${kindPart}${namespacePart}${name}`; -}; +import React from 'react'; +import { EntityPicker } from '../EntityPicker'; export const OwnerPicker = ({ - onChange, schema: { title = 'Owner', description = 'The owner of the component' }, - required, uiSchema, - rawErrors, - formData, + ...props }: FieldProps) => { - const allowedKinds = (uiSchema['ui:options']?.allowedKinds || [ - 'Group', - 'User', - ]) as string[]; - const catalogApi = useApi(catalogApiRef); - - const { value: owners, loading } = useAsync(() => - catalogApi.getEntities({ filter: { kind: allowedKinds } }), - ); - - const ownerRefs = owners?.items.map(entityRef); - - const onSelect = (_: any, value: string | null) => { - onChange(value || ''); + const ownerUiSchema = { + ...uiSchema, + 'ui:options': { + allowedKinds: (uiSchema['ui:options']?.allowedKinds || [ + 'Group', + 'User', + ]) as string[], + defaultKind: 'Group', + }, }; return ( - 0 && !formData} - > - ( - - )} - /> - + ); }; diff --git a/plugins/scaffolder/src/components/fields/OwnerPicker/index.ts b/plugins/scaffolder/src/components/fields/OwnerPicker/index.ts index 5202e5cd64..d8e793b964 100644 --- a/plugins/scaffolder/src/components/fields/OwnerPicker/index.ts +++ b/plugins/scaffolder/src/components/fields/OwnerPicker/index.ts @@ -13,4 +13,4 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -export * from './OwnerPicker'; +export { OwnerPicker } from './OwnerPicker'; diff --git a/plugins/scaffolder/src/extensions/default.ts b/plugins/scaffolder/src/extensions/default.ts index 2da0dc57ba..da8160e4df 100644 --- a/plugins/scaffolder/src/extensions/default.ts +++ b/plugins/scaffolder/src/extensions/default.ts @@ -13,14 +13,19 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +import { EntityPicker } from '../components/fields/EntityPicker'; import { OwnerPicker } from '../components/fields/OwnerPicker'; import { - RepoUrlPicker, repoPickerValidation, + RepoUrlPicker, } from '../components/fields/RepoUrlPicker'; import { FieldExtensionOptions } from './types'; export const DEFAULT_SCAFFOLDER_FIELD_EXTENSIONS: FieldExtensionOptions[] = [ + { + component: EntityPicker, + name: 'EntityPicker', + }, { component: RepoUrlPicker, name: 'RepoUrlPicker', diff --git a/plugins/scaffolder/src/index.ts b/plugins/scaffolder/src/index.ts index c22597f373..2e0fd96f08 100644 --- a/plugins/scaffolder/src/index.ts +++ b/plugins/scaffolder/src/index.ts @@ -14,13 +14,14 @@ * limitations under the License. */ +export { scaffolderApiRef, ScaffolderClient } from './api'; +export type { ScaffolderApi } from './api'; +export { ScaffolderFieldExtensions } from './extensions'; export { - scaffolderPlugin, - scaffolderPlugin as plugin, - ScaffolderPage, + EntityPickerFieldExtension, OwnerPickerFieldExtension, RepoUrlPickerFieldExtension, + ScaffolderPage, + scaffolderPlugin as plugin, + scaffolderPlugin, } from './plugin'; -export { ScaffolderFieldExtensions } from './extensions'; -export type { ScaffolderApi } from './api'; -export { ScaffolderClient, scaffolderApiRef } from './api'; diff --git a/plugins/scaffolder/src/plugin.ts b/plugins/scaffolder/src/plugin.ts index 5991ae4bc3..9e751e1bb6 100644 --- a/plugins/scaffolder/src/plugin.ts +++ b/plugins/scaffolder/src/plugin.ts @@ -21,15 +21,16 @@ import { discoveryApiRef, identityApiRef, } from '@backstage/core'; -import { OwnerPicker } from './components/fields/OwnerPicker'; -import { - RepoUrlPicker, - repoPickerValidation, -} from './components/fields/RepoUrlPicker'; import { scmIntegrationsApiRef } from '@backstage/integration-react'; import { scaffolderApiRef, ScaffolderClient } from './api'; +import { EntityPicker } from './components/fields/EntityPicker'; +import { OwnerPicker } from './components/fields/OwnerPicker'; +import { + repoPickerValidation, + RepoUrlPicker, +} from './components/fields/RepoUrlPicker'; import { createScaffolderFieldExtension } from './extensions'; -import { rootRouteRef, registerComponentRouteRef } from './routes'; +import { registerComponentRouteRef, rootRouteRef } from './routes'; export const scaffolderPlugin = createPlugin({ id: 'scaffolder', @@ -53,6 +54,13 @@ export const scaffolderPlugin = createPlugin({ }, }); +export const EntityPickerFieldExtension = scaffolderPlugin.provide( + createScaffolderFieldExtension({ + component: EntityPicker, + name: 'EntityPicker', + }), +); + export const RepoUrlPickerFieldExtension = scaffolderPlugin.provide( createScaffolderFieldExtension({ component: RepoUrlPicker,