From dd5aa39d61a4ae91cdd9b28ff8e40f9f1cf7525a Mon Sep 17 00:00:00 2001 From: Ivan Shmidt Date: Mon, 29 Jun 2020 22:42:39 +0200 Subject: [PATCH] feat(scaffolder): working end-to-end flow with hardcoded params --- .../component-info.yaml | 9 ++ .../src/scaffolder/stages/store/github.ts | 1 - .../scaffolder-backend/src/service/router.ts | 3 +- .../src/components/CreatePage/CreatePage.tsx | 114 ++++++++++-------- .../JobStatusModal/JobStatusModal.tsx | 40 +++++- .../MultistepJsonForm/MultistepJsonForm.tsx | 91 ++++++++++++++ .../src/components/MultistepJsonForm/index.ts | 1 + 7 files changed, 204 insertions(+), 55 deletions(-) create mode 100644 plugins/scaffolder-backend/sample-templates/react-ssr-template/{{cookiecutter.component_id}}/component-info.yaml create mode 100644 plugins/scaffolder/src/components/MultistepJsonForm/MultistepJsonForm.tsx create mode 100644 plugins/scaffolder/src/components/MultistepJsonForm/index.ts diff --git a/plugins/scaffolder-backend/sample-templates/react-ssr-template/{{cookiecutter.component_id}}/component-info.yaml b/plugins/scaffolder-backend/sample-templates/react-ssr-template/{{cookiecutter.component_id}}/component-info.yaml new file mode 100644 index 0000000000..5f479d9e47 --- /dev/null +++ b/plugins/scaffolder-backend/sample-templates/react-ssr-template/{{cookiecutter.component_id}}/component-info.yaml @@ -0,0 +1,9 @@ +apiVersion: backstage.io/v1alpha1 +kind: Component +metadata: + name: {{cookiecutter.component_id}} + description: {{cookiecutter.description}} +spec: + type: website + lifecycle: experimental + owner: {{cookiecutter.owner}} diff --git a/plugins/scaffolder-backend/src/scaffolder/stages/store/github.ts b/plugins/scaffolder-backend/src/scaffolder/stages/store/github.ts index a59e6c90cd..11e7d19796 100644 --- a/plugins/scaffolder-backend/src/scaffolder/stages/store/github.ts +++ b/plugins/scaffolder-backend/src/scaffolder/stages/store/github.ts @@ -20,7 +20,6 @@ import { TemplateEntityV1alpha1 } from '@backstage/catalog-model'; import { JsonValue } from '@backstage/config'; import { RequiredTemplateValues } from '../templater'; import { Repository, Remote, Signature, Cred } from 'nodegit'; -import gitUrlParse from 'git-url-parse'; export class GithubStorer implements Storer { private client: Octokit; diff --git a/plugins/scaffolder-backend/src/service/router.ts b/plugins/scaffolder-backend/src/service/router.ts index e9f644bcc7..c0ab5a8fa8 100644 --- a/plugins/scaffolder-backend/src/service/router.ts +++ b/plugins/scaffolder-backend/src/service/router.ts @@ -94,8 +94,9 @@ export async function createRouter( entity: template, values: { component_id: `blob${Date.now()}`, - org: 'hojden', + org: 'shmidt-i-test', description: 'test', + owner: 'somebody', }, stages: [ { diff --git a/plugins/scaffolder/src/components/CreatePage/CreatePage.tsx b/plugins/scaffolder/src/components/CreatePage/CreatePage.tsx index 23b7232cf4..6c69ce975b 100644 --- a/plugins/scaffolder/src/components/CreatePage/CreatePage.tsx +++ b/plugins/scaffolder/src/components/CreatePage/CreatePage.tsx @@ -16,26 +16,25 @@ import React, { useState } from 'react'; import useStaleWhileRevalidate from 'swr'; import { useParams } from 'react-router-dom'; -import { LinearProgress, Button } from '@material-ui/core'; +import { LinearProgress } from '@material-ui/core'; import { catalogApiRef } from '@backstage/plugin-catalog'; import { useApi, - SimpleStepper, - SimpleStepperStep, Page, Content, - ContentHeader, Header, Lifecycle, + InfoCard, } from '@backstage/core'; -import { TemplateEntityV1alpha1 } from '@backstage/catalog-model'; -import { withTheme, IChangeEvent } from '@rjsf/core'; -import { Theme as MuiTheme } from '@rjsf/material-ui'; +import { + TemplateEntityV1alpha1, + ComponentEntityV1alpha1, +} from '@backstage/catalog-model'; +import { IChangeEvent } from '@rjsf/core'; import { JobStatusModal } from '../JobStatusModal'; import { scaffolderApiRef } from '../../api'; - -const Form = withTheme(MuiTheme); - +import { MultistepJsonForm } from '../MultistepJsonForm'; +import { Job } from '../JobStatusModal/types'; export const CreatePage = () => { const catalogApi = useApi(catalogApiRef); const scaffolderApi = useApi(scaffolderApiRef); @@ -53,6 +52,7 @@ export const CreatePage = () => { ); const [formState, setFormState] = useState({}); + const handleFormReset = () => setFormState({}); const handleChange = (e: IChangeEvent) => setFormState({ ...formState, ...e.formData }); @@ -67,6 +67,22 @@ export const CreatePage = () => { setJobId(job); }; + const [entity, setEntity] = React.useState( + null, + ); + const handleCreateComplete = async (job: Job) => { + console.log('DEBUG:', { job }); + const { + entities: [createdEntity], + } = await catalogApi.addLocation( + 'github', + job.metadata.remoteUrl.replace( + /\.git$/, + '/blob/master/component-info.yaml', + ), + ); + setEntity(createdEntity); + }; return (
{ subtitle="Create new software components using standard templates" /> - - {jobId && } - {/* { - if (nextStep === 2) { - handleCreate(); - } - }} - > - -
-
+ + )} ); }; diff --git a/plugins/scaffolder/src/components/MultistepJsonForm/MultistepJsonForm.tsx b/plugins/scaffolder/src/components/MultistepJsonForm/MultistepJsonForm.tsx new file mode 100644 index 0000000000..7e8f470fd9 --- /dev/null +++ b/plugins/scaffolder/src/components/MultistepJsonForm/MultistepJsonForm.tsx @@ -0,0 +1,91 @@ +import React, { useState } from 'react'; +import { withTheme, FormProps, IChangeEvent } from '@rjsf/core'; +import { Theme as MuiTheme } from '@rjsf/material-ui'; +import { + Stepper, + Step, + StepLabel, + StepContent, + Button, + Paper, + Typography, + Box, +} from '@material-ui/core'; +import { Content, StructuredMetadataTable } from '@backstage/core'; + +const Form = withTheme(MuiTheme); +type Step = { + schema: FormProps['schema']; + label: string; +}; +type Props = { + steps: Step[]; + formData: Record; + onChange: (e: IChangeEvent) => void; + onReset: () => void; + onFinish: () => void; +}; +export const MultistepJsonForm = ({ + steps, + formData, + onChange, + onReset, + onFinish, +}: Props) => { + const [activeStep, setActiveStep] = useState(0); + + const handleReset = () => { + setActiveStep(0); + onReset(); + }; + const handleNext = () => + setActiveStep(Math.min(activeStep + 1, steps.length)); + const handleBack = () => setActiveStep(Math.max(activeStep - 1, 0)); + return ( + <> + + {steps.map(({ label, schema }) => ( + + {label} + +
{ + if (e.errors.length === 0) handleNext(); + }} + > +
+
+ + +
+
+
+
+
+ ))} +
+ {activeStep === steps.length && ( + + + Review and create + + + + + + + + )} + + ); +}; diff --git a/plugins/scaffolder/src/components/MultistepJsonForm/index.ts b/plugins/scaffolder/src/components/MultistepJsonForm/index.ts new file mode 100644 index 0000000000..6cb93273a6 --- /dev/null +++ b/plugins/scaffolder/src/components/MultistepJsonForm/index.ts @@ -0,0 +1 @@ +export { MultistepJsonForm } from './MultistepJsonForm';