chore: simplify logic a little more and use getComponentData

Signed-off-by: blam <ben@blam.sh>
This commit is contained in:
blam
2021-05-18 22:08:40 +02:00
parent 1124804744
commit bcead6b799
6 changed files with 51 additions and 54 deletions
+6 -11
View File
@@ -45,8 +45,8 @@ import { NewRelicPage } from '@backstage/plugin-newrelic';
import {
ScaffolderPage,
scaffolderPlugin,
OwnerPicker,
RepoUrlPicker,
OwnerPickerFieldExtension,
RepoUrlPickerFieldExtension,
} from '@backstage/plugin-scaffolder';
import { SearchPage, SearchPageNext } from '@backstage/plugin-search';
import { TechRadarPage } from '@backstage/plugin-tech-radar';
@@ -112,15 +112,10 @@ const routes = (
</Route>
<Route path="/catalog-import" element={<CatalogImportPage />} />
<Route path="/docs" element={<TechdocsPage />} />
<Route
path="/create"
element={
<ScaffolderPage>
<RepoUrlPicker />
<OwnerPicker />
</ScaffolderPage>
}
/>
<Route path="/create" element={<ScaffolderPage />}>
<RepoUrlPickerFieldExtension />
<OwnerPickerFieldExtension />
</Route>
<Route path="/explore" element={<ExplorePage />} />
<Route
path="/tech-radar"
-26
View File
@@ -82,13 +82,6 @@ export interface ScaffolderApi {
// Returns a list of all installed actions.
listActions(): Promise<ListActionsResponse>;
// Register Custom Fields
registerCustomField(field: CustomField): void;
getCustomFields(): {
components: Map<string, Field>;
validators: Map<string, (data: JsonValue, field: FieldValidation) => void>;
};
streamLogs({
taskId,
after,
@@ -102,7 +95,6 @@ export class ScaffolderClient implements ScaffolderApi {
private readonly discoveryApi: DiscoveryApi;
private readonly identityApi: IdentityApi;
private readonly scmIntegrationsApi: ScmIntegrationRegistry;
private readonly customFields: Map<string, CustomField> = new Map();
constructor(options: {
discoveryApi: DiscoveryApi;
@@ -151,24 +143,6 @@ export class ScaffolderClient implements ScaffolderApi {
return schema;
}
registerCustomField(field: CustomField) {
this.customFields.set(field.name, field);
}
getCustomFields() {
return [...this.customFields.entries()].reduce(
(previous, [name, field]) => {
previous.components.set(name, field.component);
previous.validators.set(name, field.validation);
return previous;
},
{
components: new Map(),
validators: new Map(),
},
);
}
/**
* Executes the scaffolding of a component, given a template and its
* parameter values.
+26 -9
View File
@@ -15,21 +15,38 @@
*/
import React from 'react';
import { Routes, Route } from 'react-router';
import { Routes, Route, useOutlet } from 'react-router';
import { ScaffolderPage } from './ScaffolderPage';
import { TemplatePage } from './TemplatePage';
import { TaskPage } from './TaskPage';
import { ActionsPage } from './ActionsPage';
import { getComponentData } from '@backstage/core';
import { FieldExtensionOptions } from '../extensions';
export const Router = () => {
const children = useOutlet();
const fieldExtensions = React.Children.map(children ?? [], child => {
if (!React.isValidElement(child)) {
return null;
}
const data = getComponentData<FieldExtensionOptions<unknown>>(
child,
'scaffolder.extensions.field.v1',
);
return data;
}).filter(Boolean);
return (
<>
<Routes>
<Route path="/" element={<ScaffolderPage />} />
<Route path="/templates/:templateName" element={<TemplatePage />} />
<Route path="/tasks/:taskId" element={<TaskPage />} />
<Route path="/actions" element={<ActionsPage />} />
</Routes>
</>
<Routes>
<Route path="/" element={<ScaffolderPage />} />
<Route
path="/templates/:templateName"
element={<TemplatePage customFieldExtensions={fieldExtensions} />}
/>
<Route path="/tasks/:taskId" element={<TaskPage />} />
<Route path="/actions" element={<ActionsPage />} />
</Routes>
);
};
@@ -34,6 +34,7 @@ import { scaffolderApiRef } from '../../api';
import { rootRouteRef } from '../../routes';
import { MultistepJsonForm } from '../MultistepJsonForm';
import { JsonObject, JsonValue } from '@backstage/config';
import { FieldExtensionOptions } from '../../extensions';
const useTemplateParameterSchema = (templateName: string) => {
const scaffolderApi = useApi(scaffolderApiRef);
@@ -132,7 +133,11 @@ const storePathValidator = (
return errors;
};
export const TemplatePage = () => {
export const TemplatePage = ({
customFieldExtensions = [],
}: {
customFieldExtensions: FieldExtensionOptions[];
}) => {
const errorApi = useApi(errorApiRef);
const scaffolderApi = useApi(scaffolderApiRef);
const { templateName } = useParams();
@@ -141,7 +146,6 @@ export const TemplatePage = () => {
const { schema, loading, error } = useTemplateParameterSchema(templateName);
const [formState, setFormState] = useState({});
const handleFormReset = () => setFormState({});
const handleChange = useCallback(
(e: IChangeEvent) => setFormState(e.formData),
[setFormState],
@@ -166,7 +170,14 @@ export const TemplatePage = () => {
return <Navigate to={rootLink()} />;
}
const { components, validators } = scaffolderApi.getCustomFields();
const customFieldComponents = Object.fromEntries(
customFieldExtensions.map(({ name, component }) => [name, component]),
);
const customFieldValidators = Object.fromEntries(
customFieldExtensions.map(({ name, validation }) => [name, validation]),
);
return (
<Page themeId="home">
<Header
@@ -188,7 +199,7 @@ export const TemplatePage = () => {
>
<MultistepJsonForm
formData={formState}
fields={Object.fromEntries(components.entries())}
fields={customFieldComponents}
onChange={handleChange}
onReset={handleFormReset}
onFinish={handleCreate}
@@ -204,7 +215,7 @@ export const TemplatePage = () => {
return {
...step,
validate: createValidator(step.schema, validators),
validate: createValidator(step.schema, customFieldValidators),
};
})}
/>
+1 -1
View File
@@ -24,7 +24,7 @@ export type FieldExtensionOptions<T = any> = {
export function createScaffolderFieldExtension<T = any>(
options: FieldExtensionOptions<T>,
): Extension<void> {
): Extension<() => null> {
return {
expose() {
const FieldExtensionDataHolder: any = () => null;
+2 -2
View File
@@ -18,8 +18,8 @@ export {
scaffolderPlugin,
scaffolderPlugin as plugin,
ScaffolderPage,
OwnerPicker,
RepoUrlPicker,
OwnerPickerFieldExtension,
RepoUrlPickerFieldExtension,
} from './plugin';
export type { ScaffolderApi } from './api';
export { ScaffolderClient, scaffolderApiRef } from './api';