@backstage/plugin-scaffolder-react fixes
Signed-off-by: Paul Cowan <paul.cowan@cutting.scot>
This commit is contained in:
@@ -20,19 +20,16 @@ import {
|
||||
FIELD_EXTENSION_WRAPPER_KEY,
|
||||
} from '../extensions/keys';
|
||||
|
||||
type Extension = Omit<FieldExtensionOptions, 'validation'> & { validation?: unknown }
|
||||
|
||||
/**
|
||||
* Hook that returns all custom field extensions from the current outlet.
|
||||
* @public
|
||||
*/
|
||||
export const useCustomFieldExtensions = <
|
||||
TComponentDataType = FieldExtensionOptions
|
||||
TComponentDataType = FieldExtensionOptions,
|
||||
>(
|
||||
outlet: React.ReactNode,
|
||||
defaultScaffolderFieldExtensions: Extension[] = []
|
||||
) => {
|
||||
const customFieldExtensions = useElementFilter(outlet, elements =>
|
||||
return useElementFilter(outlet, elements =>
|
||||
elements
|
||||
.selectByComponentData({
|
||||
key: FIELD_EXTENSION_WRAPPER_KEY,
|
||||
@@ -40,15 +37,5 @@ export const useCustomFieldExtensions = <
|
||||
.findComponentData<TComponentDataType>({
|
||||
key: FIELD_EXTENSION_KEY,
|
||||
}),
|
||||
) as FieldExtensionOptions[];
|
||||
|
||||
return [
|
||||
...customFieldExtensions,
|
||||
...defaultScaffolderFieldExtensions.filter(
|
||||
({ name }) =>
|
||||
!customFieldExtensions.some(
|
||||
customFieldExtension => customFieldExtension.name === name,
|
||||
),
|
||||
),
|
||||
];
|
||||
);
|
||||
};
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
import { useAnalytics, useApiHolder, useRouteRefParams } from '@backstage/core-plugin-api';
|
||||
import { useAnalytics, useApiHolder } from '@backstage/core-plugin-api';
|
||||
import { JsonValue } from '@backstage/types';
|
||||
import {
|
||||
Stepper as MuiStepper,
|
||||
@@ -34,7 +34,6 @@ import { useTemplateSchema } from '../../hooks/useTemplateSchema';
|
||||
import { useFormDataFromQuery } from '../../hooks/useFormDataFromQuery';
|
||||
import validator from '@rjsf/validator-ajv6';
|
||||
|
||||
|
||||
const useStyles = makeStyles(theme => ({
|
||||
backButton: {
|
||||
marginRight: theme.spacing(1),
|
||||
@@ -64,7 +63,7 @@ export type StepperProps = {
|
||||
onComplete: (values: Record<string, JsonValue>) => Promise<void>;
|
||||
initialFormState?: Record<string, JsonValue>;
|
||||
ReviewStateWrapper?: (props: ReviewStateProps) => JSX.Element;
|
||||
}
|
||||
};
|
||||
|
||||
// TODO(blam): We require here, as the types in this package depend on @rjsf/core explicitly
|
||||
// which is what we're using here as the default types, it needs to depend on @rjsf/core-v5 because
|
||||
|
||||
@@ -93,7 +93,16 @@ export const Router = (props: RouterProps) => {
|
||||
const outlet = useOutlet();
|
||||
const TaskPageElement = TaskPageComponent ?? TaskPage;
|
||||
|
||||
const fieldExtensions = useCustomFieldExtensions(outlet, DEFAULT_SCAFFOLDER_FIELD_EXTENSIONS);
|
||||
const customFieldExtensions = useCustomFieldExtensions(outlet);
|
||||
const fieldExtensions = [
|
||||
...customFieldExtensions,
|
||||
...DEFAULT_SCAFFOLDER_FIELD_EXTENSIONS.filter(
|
||||
({ name }) =>
|
||||
!customFieldExtensions.some(
|
||||
customFieldExtension => customFieldExtension.name === name,
|
||||
),
|
||||
),
|
||||
] as FieldExtensionOptions[];
|
||||
|
||||
// todo(blam): this should also be moved to a hook in -react
|
||||
const customLayouts = useElementFilter(outlet, elements =>
|
||||
|
||||
@@ -49,16 +49,10 @@ export {
|
||||
EmbeddedScaffolderWorkflow,
|
||||
type EmbeddedScaffolderWorkflowProps,
|
||||
type WorkflowProps,
|
||||
type ReviewStateProps,
|
||||
type ParsedTemplateSchema,
|
||||
} from './next';
|
||||
export type { NextRouterProps } from './next';
|
||||
export type { TemplateGroupFilter } from './next';
|
||||
export {
|
||||
nextRouteRef,
|
||||
nextScaffolderTaskRouteRef,
|
||||
nextSelectedTemplateRouteRef,
|
||||
type TemplateGroupFilter,
|
||||
type NextRouterProps,
|
||||
type FormProps,
|
||||
} from './next';
|
||||
|
||||
+5
-2
@@ -23,8 +23,10 @@ import {
|
||||
import { act, fireEvent } from '@testing-library/react';
|
||||
import React from 'react';
|
||||
import { EmbeddedScaffolderWorkflow } from './EmbeddedScaffolderWorkflow';
|
||||
import { scaffolderApiRef } from '../../api';
|
||||
import { ScaffolderApi } from '../../types';
|
||||
import {
|
||||
scaffolderApiRef,
|
||||
type ScaffolderApi,
|
||||
} from '@backstage/plugin-scaffolder-react';
|
||||
import { analyticsApiRef } from '@backstage/core-plugin-api';
|
||||
|
||||
const scaffolderApiMock: jest.Mocked<ScaffolderApi> = {
|
||||
@@ -80,6 +82,7 @@ describe('<EmbeddedScaffolderWorkflow />', () => {
|
||||
initialFormState={{
|
||||
name: 'prefilled-name',
|
||||
}}
|
||||
customFieldExtensions={[]}
|
||||
frontPage={
|
||||
<>
|
||||
<h1>Security Insights</h1>
|
||||
|
||||
+7
-7
@@ -18,22 +18,21 @@ import React, { useState, useCallback } from 'react';
|
||||
import type { ReactNode } from 'react';
|
||||
import type { JsonValue } from '@backstage/types';
|
||||
import { EmbeddableWorkflow, type WorkflowProps } from '../Workflow/Workflow';
|
||||
import { FormProps, useCustomFieldExtensions } from '@backstage/plugin-scaffolder-react';
|
||||
import { FormProps } from '@backstage/plugin-scaffolder-react';
|
||||
import { Box, Button } from '@material-ui/core';
|
||||
import { DEFAULT_SCAFFOLDER_FIELD_EXTENSIONS } from '../../extensions/default';
|
||||
|
||||
/**
|
||||
* @alpha
|
||||
*/
|
||||
export type EmbeddedScaffolderWorkflowProps = Omit<
|
||||
WorkflowProps,
|
||||
'customFieldExtensions' | 'onComplete'
|
||||
'onComplete' | 'FormProps'
|
||||
> & {
|
||||
customExtensionsElement?: React.ReactNode;
|
||||
initialFormState?: Record<string, JsonValue>;
|
||||
onComplete: (values: Record<string, JsonValue>) => Promise<void>;
|
||||
onError(error: Error | undefined): JSX.Element | null;
|
||||
FormProps: FormProps
|
||||
FormProps?: FormProps;
|
||||
frontPage: ReactNode;
|
||||
finishPage: ReactNode;
|
||||
} & Partial<Pick<WorkflowProps, 'onComplete'>>;
|
||||
@@ -51,7 +50,6 @@ type OnCompleteArgs = Parameters<WorkflowProps['onComplete']>[0];
|
||||
export function EmbeddedScaffolderWorkflow({
|
||||
namespace,
|
||||
templateName,
|
||||
customExtensionsElement = <></>,
|
||||
frontPage,
|
||||
finishPage,
|
||||
onComplete = async (_values: OnCompleteArgs) => void 0,
|
||||
@@ -60,9 +58,10 @@ export function EmbeddedScaffolderWorkflow({
|
||||
description,
|
||||
ReviewStateWrapper,
|
||||
initialFormState,
|
||||
customFieldExtensions,
|
||||
FormProps: formProps = {},
|
||||
}: EmbeddedScaffolderWorkflowProps): JSX.Element {
|
||||
const [display, setDisplay] = useState<Display>('front');
|
||||
const fieldExtensions = useCustomFieldExtensions(customExtensionsElement, DEFAULT_SCAFFOLDER_FIELD_EXTENSIONS);
|
||||
|
||||
const startTemplate = useCallback(() => setDisplay('workflow'), []);
|
||||
|
||||
@@ -92,9 +91,10 @@ export function EmbeddedScaffolderWorkflow({
|
||||
templateName={templateName}
|
||||
onComplete={onWorkFlowComplete}
|
||||
onError={onError}
|
||||
customFieldExtensions={fieldExtensions}
|
||||
customFieldExtensions={customFieldExtensions}
|
||||
ReviewStateWrapper={ReviewStateWrapper}
|
||||
initialFormState={initialFormState}
|
||||
FormProps={formProps}
|
||||
/>
|
||||
),
|
||||
finish: (
|
||||
|
||||
@@ -30,7 +30,8 @@ import {
|
||||
import useAsync from 'react-use/lib/useAsync';
|
||||
import { JsonValue } from '@backstage/types';
|
||||
import { FormProps } from '@backstage/plugin-scaffolder-react';
|
||||
import { nextRouteRef, scaffolderTaskRouteRef, selectedTemplateRouteRef } from '../../routes';
|
||||
import { nextRouteRef } from '../routes';
|
||||
import { scaffolderTaskRouteRef, selectedTemplateRouteRef } from '../../routes';
|
||||
import { Header, Page } from '@backstage/core-components';
|
||||
import { Workflow } from '../Workflow/Workflow';
|
||||
|
||||
|
||||
@@ -67,6 +67,7 @@ export interface WorkflowProps {
|
||||
|
||||
export const Workflow = ({
|
||||
ReviewStateWrapper = ReviewState,
|
||||
FormProps = {},
|
||||
...props
|
||||
}: WorkflowProps): JSX.Element | null => {
|
||||
const styles = useStyles();
|
||||
@@ -111,7 +112,7 @@ export const Workflow = ({
|
||||
manifest={manifest}
|
||||
extensions={props.customFieldExtensions}
|
||||
onComplete={props.onComplete}
|
||||
FormProps={props.FormProps}
|
||||
FormProps={FormProps}
|
||||
initialFormState={props.initialFormState}
|
||||
ReviewStateWrapper={ReviewStateWrapper}
|
||||
/>
|
||||
|
||||
Reference in New Issue
Block a user