From ff2277eafe2df585f2cdad5f121ed6ed4afe1947 Mon Sep 17 00:00:00 2001 From: Paul Cowan Date: Wed, 11 Jan 2023 14:49:31 +0000 Subject: [PATCH] move layouts into scaffolder-react Signed-off-by: Paul Cowan --- plugins/scaffolder-react/src/hooks/index.ts | 1 + .../src/hooks/useCustomLayouts.ts | 36 +++++++++++++ .../src/next/components/Stepper/Stepper.tsx | 3 +- .../hooks}/useTransformSchemaToProps.test.tsx | 4 +- .../useTransformSchemaToProps.ts | 2 +- .../src/next/layouts/index.tsx | 50 +++++++++++++++++++ .../scaffolder-react/src/next/layouts/keys.ts | 17 +++++++ plugins/scaffolder-react/src/next/types.ts | 3 +- plugins/scaffolder/src/next/Router/Router.tsx | 14 ++---- .../TemplateWizardPage/TemplateWizardPage.tsx | 8 +++ 10 files changed, 120 insertions(+), 18 deletions(-) create mode 100644 plugins/scaffolder-react/src/hooks/useCustomLayouts.ts rename plugins/{scaffolder/src/next/TemplateWizardPage => scaffolder-react/src/next/hooks}/useTransformSchemaToProps.test.tsx (91%) rename plugins/scaffolder-react/src/next/{components/Stepper => hooks}/useTransformSchemaToProps.ts (95%) create mode 100644 plugins/scaffolder-react/src/next/layouts/index.tsx create mode 100644 plugins/scaffolder-react/src/next/layouts/keys.ts diff --git a/plugins/scaffolder-react/src/hooks/index.ts b/plugins/scaffolder-react/src/hooks/index.ts index 022fe7c38c..af64a9eebc 100644 --- a/plugins/scaffolder-react/src/hooks/index.ts +++ b/plugins/scaffolder-react/src/hooks/index.ts @@ -15,3 +15,4 @@ */ export { useCustomFieldExtensions } from './useCustomFieldExtensions'; +export { useCustomLayouts } from './useCustomLayouts'; diff --git a/plugins/scaffolder-react/src/hooks/useCustomLayouts.ts b/plugins/scaffolder-react/src/hooks/useCustomLayouts.ts new file mode 100644 index 0000000000..f1511cebdb --- /dev/null +++ b/plugins/scaffolder-react/src/hooks/useCustomLayouts.ts @@ -0,0 +1,36 @@ +/* + * Copyright 2023 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { useElementFilter } from '@backstage/core-plugin-api'; +import { LAYOUTS_KEY, LAYOUTS_WRAPPER_KEY } from '../next/layouts/keys'; +import { type NextLayoutOptions } from '../next/types'; + +/** + * Hook that returns all custom field extensions from the current outlet. + * @public + */ +export const useCustomLayouts = ( + outlet: React.ReactNode, +) => { + return useElementFilter(outlet, elements => + elements + .selectByComponentData({ + key: LAYOUTS_WRAPPER_KEY, + }) + .findComponentData({ + key: LAYOUTS_KEY, + }), + ); +}; diff --git a/plugins/scaffolder-react/src/next/components/Stepper/Stepper.tsx b/plugins/scaffolder-react/src/next/components/Stepper/Stepper.tsx index 43253a319c..5b7c92ea62 100644 --- a/plugins/scaffolder-react/src/next/components/Stepper/Stepper.tsx +++ b/plugins/scaffolder-react/src/next/components/Stepper/Stepper.tsx @@ -33,8 +33,7 @@ import { ReviewState, type ReviewStateProps } from '../ReviewState'; import { useTemplateSchema } from '../../hooks/useTemplateSchema'; import validator from '@rjsf/validator-ajv6'; import { useFormDataFromQuery } from '../../hooks'; -import type { FormProps, NextLayoutOptions } from '../../types'; -import { useTransformSchemaToProps } from './useTransformSchemaToProps'; +import { useTransformSchemaToProps } from '../../hooks/useTransformSchemaToProps'; const useStyles = makeStyles(theme => ({ backButton: { diff --git a/plugins/scaffolder/src/next/TemplateWizardPage/useTransformSchemaToProps.test.tsx b/plugins/scaffolder-react/src/next/hooks/useTransformSchemaToProps.test.tsx similarity index 91% rename from plugins/scaffolder/src/next/TemplateWizardPage/useTransformSchemaToProps.test.tsx rename to plugins/scaffolder-react/src/next/hooks/useTransformSchemaToProps.test.tsx index 69a685f4e8..9081a5843e 100644 --- a/plugins/scaffolder/src/next/TemplateWizardPage/useTransformSchemaToProps.test.tsx +++ b/plugins/scaffolder-react/src/next/hooks/useTransformSchemaToProps.test.tsx @@ -16,8 +16,8 @@ import React from 'react'; import { renderHook } from '@testing-library/react-hooks'; import { TestApiProvider } from '@backstage/test-utils'; -import { type ParsedTemplateSchema } from './Stepper/useTemplateSchema'; -import { useTransformSchemaToProps } from './Stepper/useTransformSchemaToProps'; +import { type ParsedTemplateSchema } from './useTemplateSchema'; +import { useTransformSchemaToProps } from './useTransformSchemaToProps'; describe('useTransformSchemaToProps', () => { it('should replace ui:ObjectFieldTemplate with actual component', () => { diff --git a/plugins/scaffolder-react/src/next/components/Stepper/useTransformSchemaToProps.ts b/plugins/scaffolder-react/src/next/hooks/useTransformSchemaToProps.ts similarity index 95% rename from plugins/scaffolder-react/src/next/components/Stepper/useTransformSchemaToProps.ts rename to plugins/scaffolder-react/src/next/hooks/useTransformSchemaToProps.ts index 3c71f4c14b..8ba48a8803 100644 --- a/plugins/scaffolder-react/src/next/components/Stepper/useTransformSchemaToProps.ts +++ b/plugins/scaffolder-react/src/next/hooks/useTransformSchemaToProps.ts @@ -13,8 +13,8 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { type NextLayoutOptions } from '../../types'; import { type ParsedTemplateSchema } from './useTemplateSchema'; +import { type NextLayoutOptions } from '../types'; export const useTransformSchemaToProps = ( step: ParsedTemplateSchema, diff --git a/plugins/scaffolder-react/src/next/layouts/index.tsx b/plugins/scaffolder-react/src/next/layouts/index.tsx new file mode 100644 index 0000000000..c0db1256f4 --- /dev/null +++ b/plugins/scaffolder-react/src/next/layouts/index.tsx @@ -0,0 +1,50 @@ +import { NextLayoutOptions } from '../types'; +import { LAYOUTS_KEY, LAYOUTS_WRAPPER_KEY } from './keys'; + +/* + * Copyright 2023 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { attachComponentData, Extension } from '@backstage/core-plugin-api'; + +export type LayoutComponent<_TInputProps> = () => null; + +/** + * Method for creating custom Layouts that can be used in the scaffolder frontend form + * + * @public + */ +export function createScaffolderLayout( + options: NextLayoutOptions, +): Extension> { + return { + expose() { + const LayoutDataHolder: any = () => null; + + attachComponentData(LayoutDataHolder, LAYOUTS_KEY, options); + + return LayoutDataHolder; + }, + }; +} + +/** + * The wrapping component for defining scaffolder layouts as children + * + * @public + */ +export const ScaffolderLayouts: React.ComponentType = (): JSX.Element | null => + null; + +attachComponentData(ScaffolderLayouts, LAYOUTS_WRAPPER_KEY, true); diff --git a/plugins/scaffolder-react/src/next/layouts/keys.ts b/plugins/scaffolder-react/src/next/layouts/keys.ts new file mode 100644 index 0000000000..a82b1597f4 --- /dev/null +++ b/plugins/scaffolder-react/src/next/layouts/keys.ts @@ -0,0 +1,17 @@ +/* + * Copyright 2023 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +export const LAYOUTS_KEY = 'scaffolder.layout.v1'; +export const LAYOUTS_WRAPPER_KEY = 'scaffolder.layouts.wrapper.v1'; diff --git a/plugins/scaffolder-react/src/next/types.ts b/plugins/scaffolder-react/src/next/types.ts index 7e74ce93a1..40ba511dbe 100644 --- a/plugins/scaffolder-react/src/next/types.ts +++ b/plugins/scaffolder-react/src/next/types.ts @@ -14,11 +14,10 @@ * limitations under the License. */ import type { FormProps as SchemaFormProps } from '@rjsf/core-v5'; - /** * Any `@rjsf/core` form properties that are publicly exposed to the `NextScaffolderpage` * - * @alpha + * @public */ export type FormProps = Pick< SchemaFormProps, diff --git a/plugins/scaffolder/src/next/Router/Router.tsx b/plugins/scaffolder/src/next/Router/Router.tsx index fab64e8677..d87b76a495 100644 --- a/plugins/scaffolder/src/next/Router/Router.tsx +++ b/plugins/scaffolder/src/next/Router/Router.tsx @@ -21,14 +21,14 @@ import { NextFieldExtensionOptions, SecretsContextProvider, useCustomFieldExtensions, + useCustomLayouts, + type FormProps, } from '@backstage/plugin-scaffolder-react'; import { TemplateEntityV1beta3 } from '@backstage/plugin-scaffolder-common'; import { TemplateGroupFilter } from '../TemplateListPage/TemplateGroups'; import { DEFAULT_SCAFFOLDER_FIELD_EXTENSIONS } from '../../extensions/default'; import { nextSelectedTemplateRouteRef } from '../routes'; -import { LAYOUTS_KEY, LAYOUTS_WRAPPER_KEY } from '../../layouts'; -import type { FormProps, NextLayoutOptions } from '../types'; /** * The Props for the Scaffolder Router @@ -66,15 +66,7 @@ export const Router = (props: PropsWithChildren) => { ), ] as NextFieldExtensionOptions[]; - const customLayouts = useElementFilter(outlet, elements => - elements - .selectByComponentData({ - key: LAYOUTS_WRAPPER_KEY, - }) - .findComponentData({ - key: LAYOUTS_KEY, - }), - ); + const customLayouts = useCustomLayouts(outlet); return ( diff --git a/plugins/scaffolder/src/next/TemplateWizardPage/TemplateWizardPage.tsx b/plugins/scaffolder/src/next/TemplateWizardPage/TemplateWizardPage.tsx index 8fdb3d8e66..d11ada45b5 100644 --- a/plugins/scaffolder/src/next/TemplateWizardPage/TemplateWizardPage.tsx +++ b/plugins/scaffolder/src/next/TemplateWizardPage/TemplateWizardPage.tsx @@ -27,6 +27,14 @@ import { useTemplateSecrets, type NextFieldExtensionOptions, Workflow + type NextLayoutOptions, +} from '@backstage/plugin-scaffolder-react'; +import useAsync from 'react-use/lib/useAsync'; +import { makeStyles } from '@material-ui/core'; +import { BackstageTheme } from '@backstage/theme'; +import { + Stepper, + NextFieldExtensionOptions, } from '@backstage/plugin-scaffolder-react'; import { JsonValue } from '@backstage/types'; import { type FormProps } from '../types';