From 31f32bbebccada9045f3e387716cc283ea2ffeab Mon Sep 17 00:00:00 2001 From: blam Date: Tue, 20 Dec 2022 16:40:32 +0100 Subject: [PATCH 01/35] chore: moving the routeRefs to the new `scaffolder-react` package Signed-off-by: blam --- plugins/scaffolder-react/.eslintrc.js | 1 + plugins/scaffolder-react/README.md | 14 ++++ plugins/scaffolder-react/package.json | 68 +++++++++++++++++++ plugins/scaffolder-react/src/index.ts | 17 +++++ .../src/routes.ts | 0 plugins/scaffolder/package.json | 1 + .../ActionsPage/ActionsPage.test.tsx | 2 +- .../ListTasksPage/ListTaskPage.test.tsx | 2 +- .../ListTasksPage/ListTasksPage.tsx | 2 +- .../MultistepJsonForm/MultistepJsonForm.tsx | 2 +- plugins/scaffolder/src/components/Router.tsx | 2 +- .../ScaffolderPage/ScaffolderPage.tsx | 2 +- .../ScaffolderPageContextMenu.test.tsx | 2 +- .../ScaffolderPageContextMenu.tsx | 2 +- .../src/components/TaskPage/TaskPage.tsx | 2 +- .../components/TemplateCard/TemplateCard.tsx | 5 +- .../TemplatePage/TemplatePage.test.tsx | 2 +- .../components/TemplatePage/TemplatePage.tsx | 2 +- plugins/scaffolder/src/index.ts | 4 +- plugins/scaffolder/src/next/Router/Router.tsx | 2 +- .../TemplateCard/TemplateCard.test.tsx | 2 +- .../TemplateCard/TemplateCard.tsx | 2 +- .../TemplateListPage.test.tsx | 2 +- .../TemplateListPage/TemplateListPage.tsx | 2 +- .../TemplateWizardPage/Stepper/Stepper.tsx | 2 +- .../TemplateWizardPage.test.tsx | 2 +- .../TemplateWizardPage/TemplateWizardPage.tsx | 2 +- plugins/scaffolder/src/plugin.tsx | 2 +- yarn.lock | 32 +++++++++ 29 files changed, 160 insertions(+), 22 deletions(-) create mode 100644 plugins/scaffolder-react/.eslintrc.js create mode 100644 plugins/scaffolder-react/README.md create mode 100644 plugins/scaffolder-react/package.json create mode 100644 plugins/scaffolder-react/src/index.ts rename plugins/{scaffolder => scaffolder-react}/src/routes.ts (100%) diff --git a/plugins/scaffolder-react/.eslintrc.js b/plugins/scaffolder-react/.eslintrc.js new file mode 100644 index 0000000000..e2a53a6ad2 --- /dev/null +++ b/plugins/scaffolder-react/.eslintrc.js @@ -0,0 +1 @@ +module.exports = require('@backstage/cli/config/eslint-factory')(__dirname); diff --git a/plugins/scaffolder-react/README.md b/plugins/scaffolder-react/README.md new file mode 100644 index 0000000000..8e93bff28a --- /dev/null +++ b/plugins/scaffolder-react/README.md @@ -0,0 +1,14 @@ +# Scaffolder React + +WORK IN PROGRESS + +This is shared code of the frontend part of the default Scaffolder plugin. + +It will implement the core API for working with the Scaffolder, and +supplies components that can be reused by third-party plugins. + +## Links + +- [Frontend part of the plugin](https://github.com/backstage/backstage/tree/master/plugins/scaffolder) +- [Backend part of the plugin](https://github.com/backstage/backstage/tree/master/plugins/scaffolder-backend) +- [The Backstage homepage](https://backstage.io) diff --git a/plugins/scaffolder-react/package.json b/plugins/scaffolder-react/package.json new file mode 100644 index 0000000000..d87ebff860 --- /dev/null +++ b/plugins/scaffolder-react/package.json @@ -0,0 +1,68 @@ +{ + "name": "@backstage/plugin-scaffolder-react", + "description": "A frontend library that helps other Backstage plugins interact with the Scaffolder", + "version": "1.0.0", + "main": "src/index.ts", + "types": "src/index.ts", + "license": "Apache-2.0", + "publishConfig": { + "access": "public", + "main": "dist/index.esm.js", + "types": "dist/index.d.ts", + "alphaTypes": "dist/index.alpha.d.ts" + }, + "backstage": { + "role": "web-library" + }, + "homepage": "https://backstage.io", + "repository": { + "type": "git", + "url": "https://github.com/backstage/backstage", + "directory": "plugins/scaffolder-react" + }, + "keywords": [ + "backstage" + ], + "scripts": { + "build": "backstage-cli package build --experimental-type-build", + "lint": "backstage-cli package lint", + "test": "backstage-cli package test", + "prepack": "backstage-cli package prepack", + "postpack": "backstage-cli package postpack", + "clean": "backstage-cli package clean", + "start": "backstage-cli package start" + }, + "dependencies": { + "@backstage/catalog-client": "workspace:^", + "@backstage/catalog-model": "workspace:^", + "@backstage/core-components": "workspace:^", + "@backstage/core-plugin-api": "workspace:^", + "@backstage/errors": "workspace:^", + "@backstage/theme": "workspace:^", + "@backstage/types": "workspace:^", + "@backstage/version-bridge": "workspace:^", + "@material-ui/core": "^4.12.2", + "@material-ui/icons": "^4.9.1", + "@material-ui/lab": "4.0.0-alpha.57" + }, + "peerDependencies": { + "@types/react": "^16.13.1 || ^17.0.0", + "react": "^16.13.1 || ^17.0.0", + "react-router-dom": "6.0.0-beta.0 || ^6.3.0" + }, + "devDependencies": { + "@backstage/cli": "workspace:^", + "@backstage/core-app-api": "workspace:^", + "@backstage/plugin-catalog-common": "workspace:^", + "@backstage/plugin-scaffolder-common": "workspace:^", + "@backstage/test-utils": "workspace:^", + "@testing-library/jest-dom": "^5.10.1", + "@testing-library/react": "^12.1.3", + "@testing-library/react-hooks": "^8.0.0", + "@testing-library/user-event": "^14.0.0" + }, + "files": [ + "dist", + "alpha" + ] +} diff --git a/plugins/scaffolder-react/src/index.ts b/plugins/scaffolder-react/src/index.ts new file mode 100644 index 0000000000..3121231047 --- /dev/null +++ b/plugins/scaffolder-react/src/index.ts @@ -0,0 +1,17 @@ +/* + * Copyright 2022 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 * from './routes'; diff --git a/plugins/scaffolder/src/routes.ts b/plugins/scaffolder-react/src/routes.ts similarity index 100% rename from plugins/scaffolder/src/routes.ts rename to plugins/scaffolder-react/src/routes.ts diff --git a/plugins/scaffolder/package.json b/plugins/scaffolder/package.json index fd463c5d33..3431c46655 100644 --- a/plugins/scaffolder/package.json +++ b/plugins/scaffolder/package.json @@ -45,6 +45,7 @@ "@backstage/plugin-catalog-react": "workspace:^", "@backstage/plugin-permission-react": "workspace:^", "@backstage/plugin-scaffolder-common": "workspace:^", + "@backstage/plugin-scaffolder-react": "workspace:^", "@backstage/theme": "workspace:^", "@backstage/types": "workspace:^", "@codemirror/language": "^6.0.0", diff --git a/plugins/scaffolder/src/components/ActionsPage/ActionsPage.test.tsx b/plugins/scaffolder/src/components/ActionsPage/ActionsPage.test.tsx index 02f3c066ca..ee94c5ecd3 100644 --- a/plugins/scaffolder/src/components/ActionsPage/ActionsPage.test.tsx +++ b/plugins/scaffolder/src/components/ActionsPage/ActionsPage.test.tsx @@ -16,7 +16,7 @@ import React from 'react'; import { scaffolderApiRef } from '../../api'; import { ActionsPage } from './ActionsPage'; -import { rootRouteRef } from '../../routes'; +import { rootRouteRef } from '@backstage/plugin-scaffolder-react'; import { renderInTestApp, TestApiRegistry } from '@backstage/test-utils'; import { ApiProvider } from '@backstage/core-app-api'; import { ScaffolderApi } from '../../types'; diff --git a/plugins/scaffolder/src/components/ListTasksPage/ListTaskPage.test.tsx b/plugins/scaffolder/src/components/ListTasksPage/ListTaskPage.test.tsx index 57dde13a43..7188aed082 100644 --- a/plugins/scaffolder/src/components/ListTasksPage/ListTaskPage.test.tsx +++ b/plugins/scaffolder/src/components/ListTasksPage/ListTaskPage.test.tsx @@ -26,7 +26,7 @@ import { identityApiRef } from '@backstage/core-plugin-api'; import { ListTasksPage } from './ListTasksPage'; import { ScaffolderApi } from '../../types'; import { scaffolderApiRef } from '../../api'; -import { rootRouteRef } from '../../routes'; +import { rootRouteRef } from '@backstage/plugin-scaffolder-react'; import { act, fireEvent } from '@testing-library/react'; describe('', () => { diff --git a/plugins/scaffolder/src/components/ListTasksPage/ListTasksPage.tsx b/plugins/scaffolder/src/components/ListTasksPage/ListTasksPage.tsx index 0b00879d43..0685b42a59 100644 --- a/plugins/scaffolder/src/components/ListTasksPage/ListTasksPage.tsx +++ b/plugins/scaffolder/src/components/ListTasksPage/ListTasksPage.tsx @@ -29,7 +29,7 @@ import { CatalogFilterLayout } from '@backstage/plugin-catalog-react'; import useAsync from 'react-use/lib/useAsync'; import React, { useState } from 'react'; import { scaffolderApiRef } from '../../api'; -import { rootRouteRef } from '../../routes'; +import { rootRouteRef } from '@backstage/plugin-scaffolder-react'; import { ScaffolderTask } from '../../types'; import { OwnerListPicker } from './OwnerListPicker'; import { diff --git a/plugins/scaffolder/src/components/MultistepJsonForm/MultistepJsonForm.tsx b/plugins/scaffolder/src/components/MultistepJsonForm/MultistepJsonForm.tsx index 1fc63b2b61..0ca331ab52 100644 --- a/plugins/scaffolder/src/components/MultistepJsonForm/MultistepJsonForm.tsx +++ b/plugins/scaffolder/src/components/MultistepJsonForm/MultistepJsonForm.tsx @@ -39,7 +39,7 @@ import * as fieldOverrides from './FieldOverrides'; import { LayoutOptions } from '../../layouts'; import { ReviewStepProps } from '../types'; import { ReviewStep } from './ReviewStep'; -import { selectedTemplateRouteRef } from '../../routes'; +import { selectedTemplateRouteRef } from '@backstage/plugin-scaffolder-react'; import { extractSchemaFromStep } from '../../next/TemplateWizardPage/Stepper/schema'; const Form = withTheme(MuiTheme); diff --git a/plugins/scaffolder/src/components/Router.tsx b/plugins/scaffolder/src/components/Router.tsx index 644b26eeb8..13ef9ed43f 100644 --- a/plugins/scaffolder/src/components/Router.tsx +++ b/plugins/scaffolder/src/components/Router.tsx @@ -43,7 +43,7 @@ import { scaffolderListTaskRouteRef, scaffolderTaskRouteRef, selectedTemplateRouteRef, -} from '../routes'; +} from '@backstage/plugin-scaffolder-react'; import { ListTasksPage } from './ListTasksPage'; import { LayoutOptions, LAYOUTS_KEY, LAYOUTS_WRAPPER_KEY } from '../layouts'; import { ReviewStepProps } from './types'; diff --git a/plugins/scaffolder/src/components/ScaffolderPage/ScaffolderPage.tsx b/plugins/scaffolder/src/components/ScaffolderPage/ScaffolderPage.tsx index 9c13db72b1..7306ae8fd4 100644 --- a/plugins/scaffolder/src/components/ScaffolderPage/ScaffolderPage.tsx +++ b/plugins/scaffolder/src/components/ScaffolderPage/ScaffolderPage.tsx @@ -34,7 +34,7 @@ import { UserListPicker, } from '@backstage/plugin-catalog-react'; import React, { ComponentType } from 'react'; -import { registerComponentRouteRef } from '../../routes'; +import { registerComponentRouteRef } from '@backstage/plugin-scaffolder-react'; import { TemplateList } from '../TemplateList'; import { TemplateTypePicker } from '../TemplateTypePicker'; import { catalogEntityCreatePermission } from '@backstage/plugin-catalog-common'; diff --git a/plugins/scaffolder/src/components/ScaffolderPage/ScaffolderPageContextMenu.test.tsx b/plugins/scaffolder/src/components/ScaffolderPage/ScaffolderPageContextMenu.test.tsx index 02869bb6da..d9993c16e7 100644 --- a/plugins/scaffolder/src/components/ScaffolderPage/ScaffolderPageContextMenu.test.tsx +++ b/plugins/scaffolder/src/components/ScaffolderPage/ScaffolderPageContextMenu.test.tsx @@ -18,7 +18,7 @@ import userEvent from '@testing-library/user-event'; import { renderInTestApp } from '@backstage/test-utils'; import { screen } from '@testing-library/react'; import React from 'react'; -import { rootRouteRef } from '../../routes'; +import { rootRouteRef } from '@backstage/plugin-scaffolder-react'; import { ScaffolderPageContextMenu } from './ScaffolderPageContextMenu'; describe('ScaffolderPageContextMenu', () => { diff --git a/plugins/scaffolder/src/components/ScaffolderPage/ScaffolderPageContextMenu.tsx b/plugins/scaffolder/src/components/ScaffolderPage/ScaffolderPageContextMenu.tsx index 9e69fae68d..3c62a34e29 100644 --- a/plugins/scaffolder/src/components/ScaffolderPage/ScaffolderPageContextMenu.tsx +++ b/plugins/scaffolder/src/components/ScaffolderPage/ScaffolderPageContextMenu.tsx @@ -32,7 +32,7 @@ import { actionsRouteRef, editRouteRef, scaffolderListTaskRouteRef, -} from '../../routes'; +} from '@backstage/plugin-scaffolder-react'; const useStyles = makeStyles({ button: { diff --git a/plugins/scaffolder/src/components/TaskPage/TaskPage.tsx b/plugins/scaffolder/src/components/TaskPage/TaskPage.tsx index 699ce119fb..42f6e6fd30 100644 --- a/plugins/scaffolder/src/components/TaskPage/TaskPage.tsx +++ b/plugins/scaffolder/src/components/TaskPage/TaskPage.tsx @@ -51,7 +51,7 @@ import { rootRouteRef, scaffolderTaskRouteRef, selectedTemplateRouteRef, -} from '../../routes'; +} from '@backstage/plugin-scaffolder-react'; import { ScaffolderTaskStatus, ScaffolderTaskOutput } from '../../types'; import { useTaskEventStream } from '../hooks/useEventStream'; import { TaskErrors } from './TaskErrors'; diff --git a/plugins/scaffolder/src/components/TemplateCard/TemplateCard.tsx b/plugins/scaffolder/src/components/TemplateCard/TemplateCard.tsx index 984e51f3b5..bf9e022296 100644 --- a/plugins/scaffolder/src/components/TemplateCard/TemplateCard.tsx +++ b/plugins/scaffolder/src/components/TemplateCard/TemplateCard.tsx @@ -61,7 +61,10 @@ import { import LanguageIcon from '@material-ui/icons/Language'; import WarningIcon from '@material-ui/icons/Warning'; import React from 'react'; -import { selectedTemplateRouteRef, viewTechDocRouteRef } from '../../routes'; +import { + selectedTemplateRouteRef, + viewTechDocRouteRef, +} from '@backstage/plugin-scaffolder-react'; const useStyles = makeStyles(theme => ({ cardHeader: { diff --git a/plugins/scaffolder/src/components/TemplatePage/TemplatePage.test.tsx b/plugins/scaffolder/src/components/TemplatePage/TemplatePage.test.tsx index 0535df5ef4..7b54d047e7 100644 --- a/plugins/scaffolder/src/components/TemplatePage/TemplatePage.test.tsx +++ b/plugins/scaffolder/src/components/TemplatePage/TemplatePage.test.tsx @@ -24,7 +24,7 @@ import React from 'react'; import { Route, Routes } from 'react-router-dom'; import { scaffolderApiRef } from '../../api'; import { ScaffolderApi } from '../../types'; -import { rootRouteRef } from '../../routes'; +import { rootRouteRef } from '@backstage/plugin-scaffolder-react'; import { TemplatePage } from './TemplatePage'; import { featureFlagsApiRef, diff --git a/plugins/scaffolder/src/components/TemplatePage/TemplatePage.tsx b/plugins/scaffolder/src/components/TemplatePage/TemplatePage.tsx index e5dcc5d9bf..5d02bc436d 100644 --- a/plugins/scaffolder/src/components/TemplatePage/TemplatePage.tsx +++ b/plugins/scaffolder/src/components/TemplatePage/TemplatePage.tsx @@ -26,7 +26,7 @@ import { rootRouteRef, scaffolderTaskRouteRef, selectedTemplateRouteRef, -} from '../../routes'; +} from '@backstage/plugin-scaffolder-react'; import { MultistepJsonForm } from '../MultistepJsonForm'; import { createValidator } from './createValidator'; diff --git a/plugins/scaffolder/src/index.ts b/plugins/scaffolder/src/index.ts index 1ed1346176..c18abf92fd 100644 --- a/plugins/scaffolder/src/index.ts +++ b/plugins/scaffolder/src/index.ts @@ -62,12 +62,14 @@ export { scaffolderPlugin, } from './plugin'; export * from './components'; + export { rootRouteRef, nextRouteRef, selectedTemplateRouteRef, nextSelectedTemplateRouteRef, -} from './routes'; +} from '@backstage/plugin-scaffolder-react'; + export type { TaskPageProps } from './components/TaskPage'; /** next exports */ diff --git a/plugins/scaffolder/src/next/Router/Router.tsx b/plugins/scaffolder/src/next/Router/Router.tsx index 7a2d2826e7..97985642f9 100644 --- a/plugins/scaffolder/src/next/Router/Router.tsx +++ b/plugins/scaffolder/src/next/Router/Router.tsx @@ -28,7 +28,7 @@ import { import { useElementFilter } from '@backstage/core-plugin-api'; import { TemplateEntityV1beta3 } from '@backstage/plugin-scaffolder-common'; import { TemplateGroupFilter } from '../TemplateListPage/TemplateGroups'; -import { nextSelectedTemplateRouteRef } from '../../routes'; +import { nextSelectedTemplateRouteRef } from '@backstage/plugin-scaffolder-react'; import { SecretsContextProvider } from '../../components/secrets/SecretsContext'; import type { FormProps } from '../types'; diff --git a/plugins/scaffolder/src/next/TemplateListPage/TemplateCard/TemplateCard.test.tsx b/plugins/scaffolder/src/next/TemplateListPage/TemplateCard/TemplateCard.test.tsx index 4648d47af1..cb4e8428cd 100644 --- a/plugins/scaffolder/src/next/TemplateListPage/TemplateCard/TemplateCard.test.tsx +++ b/plugins/scaffolder/src/next/TemplateListPage/TemplateCard/TemplateCard.test.tsx @@ -25,7 +25,7 @@ import { } from '@backstage/test-utils'; import { TemplateCard } from './TemplateCard'; import React from 'react'; -import { nextRouteRef } from '../../../routes'; +import { nextRouteRef } from '@backstage/plugin-scaffolder-react'; import { TemplateEntityV1beta3 } from '@backstage/plugin-scaffolder-common'; import { RELATION_OWNED_BY } from '@backstage/catalog-model'; diff --git a/plugins/scaffolder/src/next/TemplateListPage/TemplateCard/TemplateCard.tsx b/plugins/scaffolder/src/next/TemplateListPage/TemplateCard/TemplateCard.tsx index 67b50ba8d6..b5c852949c 100644 --- a/plugins/scaffolder/src/next/TemplateListPage/TemplateCard/TemplateCard.tsx +++ b/plugins/scaffolder/src/next/TemplateListPage/TemplateCard/TemplateCard.tsx @@ -42,7 +42,7 @@ import React from 'react'; import { nextSelectedTemplateRouteRef, viewTechDocRouteRef, -} from '../../../routes'; +} from '@backstage/plugin-scaffolder-react'; import { CardHeader } from './CardHeader'; import { CardLink } from './CardLink'; diff --git a/plugins/scaffolder/src/next/TemplateListPage/TemplateListPage.test.tsx b/plugins/scaffolder/src/next/TemplateListPage/TemplateListPage.test.tsx index 26e2994c8a..16beeabd32 100644 --- a/plugins/scaffolder/src/next/TemplateListPage/TemplateListPage.test.tsx +++ b/plugins/scaffolder/src/next/TemplateListPage/TemplateListPage.test.tsx @@ -25,7 +25,7 @@ import { TestApiProvider, } from '@backstage/test-utils'; import React from 'react'; -import { nextRouteRef } from '../../routes'; +import { nextRouteRef } from '@backstage/plugin-scaffolder-react'; import { TemplateListPage } from './TemplateListPage'; describe('TemplateListPage', () => { diff --git a/plugins/scaffolder/src/next/TemplateListPage/TemplateListPage.tsx b/plugins/scaffolder/src/next/TemplateListPage/TemplateListPage.tsx index 003c3aa98b..bb77ed6479 100644 --- a/plugins/scaffolder/src/next/TemplateListPage/TemplateListPage.tsx +++ b/plugins/scaffolder/src/next/TemplateListPage/TemplateListPage.tsx @@ -35,7 +35,7 @@ import { import { CategoryPicker } from './CategoryPicker'; import { RegisterExistingButton } from './RegisterExistingButton'; import { useRouteRef } from '@backstage/core-plugin-api'; -import { registerComponentRouteRef } from '../../routes'; +import { registerComponentRouteRef } from '@backstage/plugin-scaffolder-react'; import { TemplateGroupFilter, TemplateGroups } from './TemplateGroups'; export type TemplateListPageProps = { diff --git a/plugins/scaffolder/src/next/TemplateWizardPage/Stepper/Stepper.tsx b/plugins/scaffolder/src/next/TemplateWizardPage/Stepper/Stepper.tsx index d4d57eed22..e285c21c6f 100644 --- a/plugins/scaffolder/src/next/TemplateWizardPage/Stepper/Stepper.tsx +++ b/plugins/scaffolder/src/next/TemplateWizardPage/Stepper/Stepper.tsx @@ -35,7 +35,7 @@ import { createAsyncValidators } from './createAsyncValidators'; import { useTemplateSchema } from './useTemplateSchema'; import { ReviewState } from './ReviewState'; import validator from '@rjsf/validator-ajv6'; -import { selectedTemplateRouteRef } from '../../../routes'; +import { selectedTemplateRouteRef } from '@backstage/plugin-scaffolder-react'; import { useFormData } from './useFormData'; import { FormProps } from '../../types'; diff --git a/plugins/scaffolder/src/next/TemplateWizardPage/TemplateWizardPage.test.tsx b/plugins/scaffolder/src/next/TemplateWizardPage/TemplateWizardPage.test.tsx index f36fae9aa3..854cfc6545 100644 --- a/plugins/scaffolder/src/next/TemplateWizardPage/TemplateWizardPage.test.tsx +++ b/plugins/scaffolder/src/next/TemplateWizardPage/TemplateWizardPage.test.tsx @@ -23,7 +23,7 @@ import { import { act, fireEvent } from '@testing-library/react'; import React from 'react'; import { scaffolderApiRef } from '../../api'; -import { nextRouteRef, rootRouteRef } from '../../routes'; +import { nextRouteRef, rootRouteRef } from '@backstage/plugin-scaffolder-react'; import { ScaffolderApi } from '../../types'; import { TemplateWizardPage } from './TemplateWizardPage'; diff --git a/plugins/scaffolder/src/next/TemplateWizardPage/TemplateWizardPage.tsx b/plugins/scaffolder/src/next/TemplateWizardPage/TemplateWizardPage.tsx index 92b6b005ea..aece4e427e 100644 --- a/plugins/scaffolder/src/next/TemplateWizardPage/TemplateWizardPage.tsx +++ b/plugins/scaffolder/src/next/TemplateWizardPage/TemplateWizardPage.tsx @@ -41,7 +41,7 @@ import { nextRouteRef, scaffolderTaskRouteRef, selectedTemplateRouteRef, -} from '../../routes'; +} from '@backstage/plugin-scaffolder-react'; import { SecretsContext } from '../../components/secrets/SecretsContext'; import { JsonValue } from '@backstage/types'; import type { FormProps } from '../types'; diff --git a/plugins/scaffolder/src/plugin.tsx b/plugins/scaffolder/src/plugin.tsx index cfa7af8128..f6a8915c48 100644 --- a/plugins/scaffolder/src/plugin.tsx +++ b/plugins/scaffolder/src/plugin.tsx @@ -40,7 +40,7 @@ import { registerComponentRouteRef, rootRouteRef, viewTechDocRouteRef, -} from './routes'; +} from '@backstage/plugin-scaffolder-react'; import { createApiFactory, createPlugin, diff --git a/yarn.lock b/yarn.lock index 588d41c776..0ad909a7a2 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7450,6 +7450,37 @@ __metadata: languageName: unknown linkType: soft +"@backstage/plugin-scaffolder-react@workspace:^, @backstage/plugin-scaffolder-react@workspace:plugins/scaffolder-react": + version: 0.0.0-use.local + resolution: "@backstage/plugin-scaffolder-react@workspace:plugins/scaffolder-react" + dependencies: + "@backstage/catalog-client": "workspace:^" + "@backstage/catalog-model": "workspace:^" + "@backstage/cli": "workspace:^" + "@backstage/core-app-api": "workspace:^" + "@backstage/core-components": "workspace:^" + "@backstage/core-plugin-api": "workspace:^" + "@backstage/errors": "workspace:^" + "@backstage/plugin-catalog-common": "workspace:^" + "@backstage/plugin-scaffolder-common": "workspace:^" + "@backstage/test-utils": "workspace:^" + "@backstage/theme": "workspace:^" + "@backstage/types": "workspace:^" + "@backstage/version-bridge": "workspace:^" + "@material-ui/core": ^4.12.2 + "@material-ui/icons": ^4.9.1 + "@material-ui/lab": 4.0.0-alpha.57 + "@testing-library/jest-dom": ^5.10.1 + "@testing-library/react": ^12.1.3 + "@testing-library/react-hooks": ^8.0.0 + "@testing-library/user-event": ^14.0.0 + peerDependencies: + "@types/react": ^16.13.1 || ^17.0.0 + react: ^16.13.1 || ^17.0.0 + react-router-dom: 6.0.0-beta.0 || ^6.3.0 + languageName: unknown + linkType: soft + "@backstage/plugin-scaffolder@workspace:^, @backstage/plugin-scaffolder@workspace:plugins/scaffolder": version: 0.0.0-use.local resolution: "@backstage/plugin-scaffolder@workspace:plugins/scaffolder" @@ -7470,6 +7501,7 @@ __metadata: "@backstage/plugin-catalog-react": "workspace:^" "@backstage/plugin-permission-react": "workspace:^" "@backstage/plugin-scaffolder-common": "workspace:^" + "@backstage/plugin-scaffolder-react": "workspace:^" "@backstage/test-utils": "workspace:^" "@backstage/theme": "workspace:^" "@backstage/types": "workspace:^" From 5f0fadc610939107d738f0b1bd0720d2fdf08281 Mon Sep 17 00:00:00 2001 From: blam Date: Thu, 22 Dec 2022 12:01:58 +0100 Subject: [PATCH 02/35] chore: starting to move some dependencies around a little bit Signed-off-by: blam --- plugins/scaffolder-react/package.json | 16 ++++- .../src/extensions/index.tsx | 35 ---------- .../src/extensions/types.ts | 45 ------------ plugins/scaffolder-react/src/index.ts | 3 + .../components}/Stepper/ReviewState.test.tsx | 0 .../next/components}/Stepper/ReviewState.tsx | 0 .../next/components}/Stepper/Stepper.test.tsx | 0 .../src/next/components}/Stepper/Stepper.tsx | 11 +-- .../Stepper/createAsyncValidators.test.ts | 0 .../Stepper/createAsyncValidators.ts | 0 .../src/next/components}/Stepper/index.ts | 0 .../next/components}/Stepper/schema.test.ts | 0 .../src/next/components}/Stepper/schema.ts | 0 .../src/next/components/index.ts | 16 +++++ .../src/next/extensions/index.tsx | 59 ++++++++++++++++ .../src/next/extensions/types.ts | 68 +++++++++++++++++++ .../src/next/hooks}/useFormData.ts | 0 .../next/hooks}/useTemplateSchema.test.tsx | 0 .../src/next/hooks}/useTemplateSchema.ts | 0 plugins/scaffolder-react/src/next/index.ts | 17 +++++ plugins/scaffolder-react/src/types.ts | 15 ++++ .../TemplateWizardPage/TemplateWizardPage.tsx | 2 +- yarn.lock | 14 ++++ 23 files changed, 215 insertions(+), 86 deletions(-) rename plugins/{scaffolder => scaffolder-react}/src/extensions/index.tsx (70%) rename plugins/{scaffolder => scaffolder-react}/src/extensions/types.ts (64%) rename plugins/{scaffolder/src/next/TemplateWizardPage => scaffolder-react/src/next/components}/Stepper/ReviewState.test.tsx (100%) rename plugins/{scaffolder/src/next/TemplateWizardPage => scaffolder-react/src/next/components}/Stepper/ReviewState.tsx (100%) rename plugins/{scaffolder/src/next/TemplateWizardPage => scaffolder-react/src/next/components}/Stepper/Stepper.test.tsx (100%) rename plugins/{scaffolder/src/next/TemplateWizardPage => scaffolder-react/src/next/components}/Stepper/Stepper.tsx (96%) rename plugins/{scaffolder/src/next/TemplateWizardPage => scaffolder-react/src/next/components}/Stepper/createAsyncValidators.test.ts (100%) rename plugins/{scaffolder/src/next/TemplateWizardPage => scaffolder-react/src/next/components}/Stepper/createAsyncValidators.ts (100%) rename plugins/{scaffolder/src/next/TemplateWizardPage => scaffolder-react/src/next/components}/Stepper/index.ts (100%) rename plugins/{scaffolder/src/next/TemplateWizardPage => scaffolder-react/src/next/components}/Stepper/schema.test.ts (100%) rename plugins/{scaffolder/src/next/TemplateWizardPage => scaffolder-react/src/next/components}/Stepper/schema.ts (100%) create mode 100644 plugins/scaffolder-react/src/next/components/index.ts create mode 100644 plugins/scaffolder-react/src/next/extensions/index.tsx create mode 100644 plugins/scaffolder-react/src/next/extensions/types.ts rename plugins/{scaffolder/src/next/TemplateWizardPage/Stepper => scaffolder-react/src/next/hooks}/useFormData.ts (100%) rename plugins/{scaffolder/src/next/TemplateWizardPage/Stepper => scaffolder-react/src/next/hooks}/useTemplateSchema.test.tsx (100%) rename plugins/{scaffolder/src/next/TemplateWizardPage/Stepper => scaffolder-react/src/next/hooks}/useTemplateSchema.ts (100%) create mode 100644 plugins/scaffolder-react/src/next/index.ts create mode 100644 plugins/scaffolder-react/src/types.ts diff --git a/plugins/scaffolder-react/package.json b/plugins/scaffolder-react/package.json index d87ebff860..17391aedfa 100644 --- a/plugins/scaffolder-react/package.json +++ b/plugins/scaffolder-react/package.json @@ -43,7 +43,21 @@ "@backstage/version-bridge": "workspace:^", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", - "@material-ui/lab": "4.0.0-alpha.57" + "@material-ui/lab": "4.0.0-alpha.57", + "@rjsf/core": "^3.2.1", + "@rjsf/core-v5": "npm:@rjsf/core@^5.0.0-beta.14", + "@rjsf/material-ui": "^3.2.1", + "@rjsf/material-ui-v5": "npm:@rjsf/material-ui@^5.0.0-beta.14", + "@rjsf/utils": "^5.0.0-beta.14", + "@rjsf/validator-ajv6": "^5.0.0-beta.14", + "@types/json-schema": "^7.0.9", + "classnames": "^2.2.6", + "json-schema": "^0.4.0", + "json-schema-library": "^7.3.9", + "lodash": "^4.17.21", + "qs": "^6.9.4", + "zod": "~3.18.0", + "zod-to-json-schema": "~3.18.0" }, "peerDependencies": { "@types/react": "^16.13.1 || ^17.0.0", diff --git a/plugins/scaffolder/src/extensions/index.tsx b/plugins/scaffolder-react/src/extensions/index.tsx similarity index 70% rename from plugins/scaffolder/src/extensions/index.tsx rename to plugins/scaffolder-react/src/extensions/index.tsx index 2b3126ac58..093c68c172 100644 --- a/plugins/scaffolder/src/extensions/index.tsx +++ b/plugins/scaffolder-react/src/extensions/index.tsx @@ -20,12 +20,8 @@ import { CustomFieldValidator, FieldExtensionOptions, FieldExtensionComponentProps, - NextCustomFieldValidator, - NextFieldExtensionOptions, - NextFieldExtensionComponentProps, } from './types'; import { Extension, attachComponentData } from '@backstage/core-plugin-api'; -import { UIOptionsType } from '@rjsf/utils'; export const FIELD_EXTENSION_WRAPPER_KEY = 'scaffolder.extensions.wrapper.v1'; export const FIELD_EXTENSION_KEY = 'scaffolder.extensions.field.v1'; @@ -63,32 +59,6 @@ export function createScaffolderFieldExtension< }; } -/** - * Method for creating field extensions that can be used in the scaffolder - * frontend form. - * @alpha - */ -export function createNextScaffolderFieldExtension< - TReturnValue = unknown, - TInputProps extends UIOptionsType = {}, ->( - options: NextFieldExtensionOptions, -): Extension> { - return { - expose() { - const FieldExtensionDataHolder: any = () => null; - - attachComponentData( - FieldExtensionDataHolder, - FIELD_EXTENSION_KEY, - options, - ); - - return FieldExtensionDataHolder; - }, - }; -} - /** * The Wrapping component for defining fields extensions inside * @@ -109,9 +79,4 @@ export type { CustomFieldValidator, FieldExtensionOptions, FieldExtensionComponentProps, - NextCustomFieldValidator, - NextFieldExtensionOptions, - NextFieldExtensionComponentProps, }; - -export { DEFAULT_SCAFFOLDER_FIELD_EXTENSIONS } from './default'; diff --git a/plugins/scaffolder/src/extensions/types.ts b/plugins/scaffolder-react/src/extensions/types.ts similarity index 64% rename from plugins/scaffolder/src/extensions/types.ts rename to plugins/scaffolder-react/src/extensions/types.ts index 5e133c676b..a2a1a8d69c 100644 --- a/plugins/scaffolder/src/extensions/types.ts +++ b/plugins/scaffolder-react/src/extensions/types.ts @@ -21,9 +21,7 @@ import { UiSchema as UiSchemaV5, FieldValidation as FieldValidationV5, } from '@rjsf/utils'; -import { PropsWithChildren } from 'react'; import { JSONSchema7 } from 'json-schema'; -import { JsonObject } from '@backstage/types'; /** * Field validation type for Custom Field Extensions. @@ -78,46 +76,3 @@ export interface FieldExtensionComponentProps< 'ui:options'?: TUiOptions; }; } - -/** - * Type for Field Extension Props for RJSF v5 - * - * @alpha - */ -export interface NextFieldExtensionComponentProps< - TFieldReturnValue, - TUiOptions = {}, -> extends PropsWithChildren> { - uiSchema?: UiSchemaV5 & { - 'ui:options'?: TUiOptions & UIOptionsType; - }; -} - -/** - * Field validation type for Custom Field Extensions. - * - * @alpha - */ -export type NextCustomFieldValidator = ( - data: TFieldReturnValue, - field: FieldValidationV5, - context: { apiHolder: ApiHolder; formData: JsonObject }, -) => void | Promise; - -/** - * Type for the Custom Field Extension with the - * name and components and validation function. - * - * @alpha - */ -export type NextFieldExtensionOptions< - TFieldReturnValue = unknown, - TInputProps = unknown, -> = { - name: string; - component: ( - props: NextFieldExtensionComponentProps, - ) => JSX.Element | null; - validation?: NextCustomFieldValidator; - schema?: CustomFieldExtensionSchema; -}; diff --git a/plugins/scaffolder-react/src/index.ts b/plugins/scaffolder-react/src/index.ts index 3121231047..42a2cebb19 100644 --- a/plugins/scaffolder-react/src/index.ts +++ b/plugins/scaffolder-react/src/index.ts @@ -15,3 +15,6 @@ */ export * from './routes'; +export * from './extensions'; + +export * from './next'; diff --git a/plugins/scaffolder/src/next/TemplateWizardPage/Stepper/ReviewState.test.tsx b/plugins/scaffolder-react/src/next/components/Stepper/ReviewState.test.tsx similarity index 100% rename from plugins/scaffolder/src/next/TemplateWizardPage/Stepper/ReviewState.test.tsx rename to plugins/scaffolder-react/src/next/components/Stepper/ReviewState.test.tsx diff --git a/plugins/scaffolder/src/next/TemplateWizardPage/Stepper/ReviewState.tsx b/plugins/scaffolder-react/src/next/components/Stepper/ReviewState.tsx similarity index 100% rename from plugins/scaffolder/src/next/TemplateWizardPage/Stepper/ReviewState.tsx rename to plugins/scaffolder-react/src/next/components/Stepper/ReviewState.tsx diff --git a/plugins/scaffolder/src/next/TemplateWizardPage/Stepper/Stepper.test.tsx b/plugins/scaffolder-react/src/next/components/Stepper/Stepper.test.tsx similarity index 100% rename from plugins/scaffolder/src/next/TemplateWizardPage/Stepper/Stepper.test.tsx rename to plugins/scaffolder-react/src/next/components/Stepper/Stepper.test.tsx diff --git a/plugins/scaffolder/src/next/TemplateWizardPage/Stepper/Stepper.tsx b/plugins/scaffolder-react/src/next/components/Stepper/Stepper.tsx similarity index 96% rename from plugins/scaffolder/src/next/TemplateWizardPage/Stepper/Stepper.tsx rename to plugins/scaffolder-react/src/next/components/Stepper/Stepper.tsx index e285c21c6f..72079d6f91 100644 --- a/plugins/scaffolder/src/next/TemplateWizardPage/Stepper/Stepper.tsx +++ b/plugins/scaffolder-react/src/next/components/Stepper/Stepper.tsx @@ -29,14 +29,14 @@ import { import { type IChangeEvent, withTheme } from '@rjsf/core-v5'; import { ErrorSchema, FieldValidation } from '@rjsf/utils'; import React, { useCallback, useMemo, useState } from 'react'; -import { NextFieldExtensionOptions } from '../../../extensions'; +import { NextFieldExtensionOptions } from '../../extensions'; import { TemplateParameterSchema } from '../../../types'; import { createAsyncValidators } from './createAsyncValidators'; -import { useTemplateSchema } from './useTemplateSchema'; +import { useTemplateSchema } from '../../hooks/useTemplateSchema'; import { ReviewState } from './ReviewState'; import validator from '@rjsf/validator-ajv6'; -import { selectedTemplateRouteRef } from '@backstage/plugin-scaffolder-react'; -import { useFormData } from './useFormData'; +import { selectedTemplateRouteRef } from '../../../routes'; +import { useFormData } from '../../hooks/useFormData'; import { FormProps } from '../../types'; const useStyles = makeStyles(theme => ({ @@ -66,6 +66,9 @@ export type StepperProps = { // of the re-writing we're doing. Once we've migrated, we can import this the exact same as before. const Form = withTheme(require('@rjsf/material-ui-v5').Theme); +/** + * @alpha + */ export const Stepper = (props: StepperProps) => { const { templateName } = useRouteRefParams(selectedTemplateRouteRef); const analytics = useAnalytics(); diff --git a/plugins/scaffolder/src/next/TemplateWizardPage/Stepper/createAsyncValidators.test.ts b/plugins/scaffolder-react/src/next/components/Stepper/createAsyncValidators.test.ts similarity index 100% rename from plugins/scaffolder/src/next/TemplateWizardPage/Stepper/createAsyncValidators.test.ts rename to plugins/scaffolder-react/src/next/components/Stepper/createAsyncValidators.test.ts diff --git a/plugins/scaffolder/src/next/TemplateWizardPage/Stepper/createAsyncValidators.ts b/plugins/scaffolder-react/src/next/components/Stepper/createAsyncValidators.ts similarity index 100% rename from plugins/scaffolder/src/next/TemplateWizardPage/Stepper/createAsyncValidators.ts rename to plugins/scaffolder-react/src/next/components/Stepper/createAsyncValidators.ts diff --git a/plugins/scaffolder/src/next/TemplateWizardPage/Stepper/index.ts b/plugins/scaffolder-react/src/next/components/Stepper/index.ts similarity index 100% rename from plugins/scaffolder/src/next/TemplateWizardPage/Stepper/index.ts rename to plugins/scaffolder-react/src/next/components/Stepper/index.ts diff --git a/plugins/scaffolder/src/next/TemplateWizardPage/Stepper/schema.test.ts b/plugins/scaffolder-react/src/next/components/Stepper/schema.test.ts similarity index 100% rename from plugins/scaffolder/src/next/TemplateWizardPage/Stepper/schema.test.ts rename to plugins/scaffolder-react/src/next/components/Stepper/schema.test.ts diff --git a/plugins/scaffolder/src/next/TemplateWizardPage/Stepper/schema.ts b/plugins/scaffolder-react/src/next/components/Stepper/schema.ts similarity index 100% rename from plugins/scaffolder/src/next/TemplateWizardPage/Stepper/schema.ts rename to plugins/scaffolder-react/src/next/components/Stepper/schema.ts diff --git a/plugins/scaffolder-react/src/next/components/index.ts b/plugins/scaffolder-react/src/next/components/index.ts new file mode 100644 index 0000000000..5532563e28 --- /dev/null +++ b/plugins/scaffolder-react/src/next/components/index.ts @@ -0,0 +1,16 @@ +/* + * Copyright 2022 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 { Stepper } from './Stepper'; diff --git a/plugins/scaffolder-react/src/next/extensions/index.tsx b/plugins/scaffolder-react/src/next/extensions/index.tsx new file mode 100644 index 0000000000..7bbf7d4112 --- /dev/null +++ b/plugins/scaffolder-react/src/next/extensions/index.tsx @@ -0,0 +1,59 @@ +/* + * Copyright 2021 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 { + NextCustomFieldValidator, + NextFieldExtensionOptions, + NextFieldExtensionComponentProps, +} from './types'; +import { Extension, attachComponentData } from '@backstage/core-plugin-api'; +import { UIOptionsType } from '@rjsf/utils'; +import { FieldExtensionComponent } from '../../extensions'; + +export const FIELD_EXTENSION_WRAPPER_KEY = 'scaffolder.extensions.wrapper.v1'; +export const FIELD_EXTENSION_KEY = 'scaffolder.extensions.field.v1'; + +/** + * Method for creating field extensions that can be used in the scaffolder + * frontend form. + * @alpha + */ +export function createNextScaffolderFieldExtension< + TReturnValue = unknown, + TInputProps extends UIOptionsType = {}, +>( + options: NextFieldExtensionOptions, +): Extension> { + return { + expose() { + const FieldExtensionDataHolder: any = () => null; + + attachComponentData( + FieldExtensionDataHolder, + FIELD_EXTENSION_KEY, + options, + ); + + return FieldExtensionDataHolder; + }, + }; +} + +export type { + NextCustomFieldValidator, + NextFieldExtensionOptions, + NextFieldExtensionComponentProps, +}; diff --git a/plugins/scaffolder-react/src/next/extensions/types.ts b/plugins/scaffolder-react/src/next/extensions/types.ts new file mode 100644 index 0000000000..27778b0420 --- /dev/null +++ b/plugins/scaffolder-react/src/next/extensions/types.ts @@ -0,0 +1,68 @@ +/* + * Copyright 2021 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 { ApiHolder } from '@backstage/core-plugin-api'; +import { + UIOptionsType, + FieldProps as FieldPropsV5, + UiSchema as UiSchemaV5, + FieldValidation as FieldValidationV5, +} from '@rjsf/utils'; +import { PropsWithChildren } from 'react'; +import { JsonObject } from '@backstage/types'; +import { CustomFieldExtensionSchema } from '../../extensions'; + +/** + * Type for Field Extension Props for RJSF v5 + * + * @alpha + */ +export interface NextFieldExtensionComponentProps< + TFieldReturnValue, + TUiOptions = {}, +> extends PropsWithChildren> { + uiSchema?: UiSchemaV5 & { + 'ui:options'?: TUiOptions & UIOptionsType; + }; +} + +/** + * Field validation type for Custom Field Extensions. + * + * @alpha + */ +export type NextCustomFieldValidator = ( + data: TFieldReturnValue, + field: FieldValidationV5, + context: { apiHolder: ApiHolder; formData: JsonObject }, +) => void | Promise; + +/** + * Type for the Custom Field Extension with the + * name and components and validation function. + * + * @alpha + */ +export type NextFieldExtensionOptions< + TFieldReturnValue = unknown, + TInputProps = unknown, +> = { + name: string; + component: ( + props: NextFieldExtensionComponentProps, + ) => JSX.Element | null; + validation?: NextCustomFieldValidator; + schema?: CustomFieldExtensionSchema; +}; diff --git a/plugins/scaffolder/src/next/TemplateWizardPage/Stepper/useFormData.ts b/plugins/scaffolder-react/src/next/hooks/useFormData.ts similarity index 100% rename from plugins/scaffolder/src/next/TemplateWizardPage/Stepper/useFormData.ts rename to plugins/scaffolder-react/src/next/hooks/useFormData.ts diff --git a/plugins/scaffolder/src/next/TemplateWizardPage/Stepper/useTemplateSchema.test.tsx b/plugins/scaffolder-react/src/next/hooks/useTemplateSchema.test.tsx similarity index 100% rename from plugins/scaffolder/src/next/TemplateWizardPage/Stepper/useTemplateSchema.test.tsx rename to plugins/scaffolder-react/src/next/hooks/useTemplateSchema.test.tsx diff --git a/plugins/scaffolder/src/next/TemplateWizardPage/Stepper/useTemplateSchema.ts b/plugins/scaffolder-react/src/next/hooks/useTemplateSchema.ts similarity index 100% rename from plugins/scaffolder/src/next/TemplateWizardPage/Stepper/useTemplateSchema.ts rename to plugins/scaffolder-react/src/next/hooks/useTemplateSchema.ts diff --git a/plugins/scaffolder-react/src/next/index.ts b/plugins/scaffolder-react/src/next/index.ts new file mode 100644 index 0000000000..aa46a7a6cd --- /dev/null +++ b/plugins/scaffolder-react/src/next/index.ts @@ -0,0 +1,17 @@ +/* + * Copyright 2022 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 * from './components'; +export * from './extensions'; diff --git a/plugins/scaffolder-react/src/types.ts b/plugins/scaffolder-react/src/types.ts new file mode 100644 index 0000000000..b61d59e88d --- /dev/null +++ b/plugins/scaffolder-react/src/types.ts @@ -0,0 +1,15 @@ +/* + * Copyright 2022 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. + */ diff --git a/plugins/scaffolder/src/next/TemplateWizardPage/TemplateWizardPage.tsx b/plugins/scaffolder/src/next/TemplateWizardPage/TemplateWizardPage.tsx index aece4e427e..75da592bba 100644 --- a/plugins/scaffolder/src/next/TemplateWizardPage/TemplateWizardPage.tsx +++ b/plugins/scaffolder/src/next/TemplateWizardPage/TemplateWizardPage.tsx @@ -35,7 +35,7 @@ import { import { scaffolderApiRef } from '../../api'; import useAsync from 'react-use/lib/useAsync'; import { makeStyles } from '@material-ui/core'; -import { Stepper } from './Stepper'; +import { Stepper } from '@backstage/plugin-scaffolder-react'; import { BackstageTheme } from '@backstage/theme'; import { nextRouteRef, diff --git a/yarn.lock b/yarn.lock index 0ad909a7a2..827fa3423a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7470,10 +7470,24 @@ __metadata: "@material-ui/core": ^4.12.2 "@material-ui/icons": ^4.9.1 "@material-ui/lab": 4.0.0-alpha.57 + "@rjsf/core": ^3.2.1 + "@rjsf/core-v5": "npm:@rjsf/core@^5.0.0-beta.14" + "@rjsf/material-ui": ^3.2.1 + "@rjsf/material-ui-v5": "npm:@rjsf/material-ui@^5.0.0-beta.14" + "@rjsf/utils": ^5.0.0-beta.14 + "@rjsf/validator-ajv6": ^5.0.0-beta.14 "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 "@testing-library/react-hooks": ^8.0.0 "@testing-library/user-event": ^14.0.0 + "@types/json-schema": ^7.0.9 + classnames: ^2.2.6 + json-schema: ^0.4.0 + json-schema-library: ^7.3.9 + lodash: ^4.17.21 + qs: ^6.9.4 + zod: ~3.18.0 + zod-to-json-schema: ~3.18.0 peerDependencies: "@types/react": ^16.13.1 || ^17.0.0 react: ^16.13.1 || ^17.0.0 From 33f069c805c53f631142eeefff34da59126adb60 Mon Sep 17 00:00:00 2001 From: blam Date: Thu, 22 Dec 2022 16:53:34 +0100 Subject: [PATCH 03/35] chore: more moving out into the other packages Signed-off-by: blam --- plugins/scaffolder-react/package.json | 5 ++- .../scaffolder-react/src/extensions/types.ts | 6 ---- plugins/scaffolder-react/src/index.ts | 2 +- .../ReviewState.test.tsx | 2 +- .../{Stepper => ReviewState}/ReviewState.tsx | 6 +++- .../src/next/components/ReviewState/index.ts | 16 +++++++++ .../src/next/components/Stepper/Stepper.tsx | 2 +- .../Stepper/createAsyncValidators.test.ts | 2 +- .../Stepper/createAsyncValidators.ts | 4 +-- .../TemplateCard/CardHeader.test.tsx | 0 .../components}/TemplateCard/CardHeader.tsx | 0 .../components}/TemplateCard/CardLink.tsx | 0 .../TemplateCard/TemplateCard.test.tsx | 2 +- .../components}/TemplateCard/TemplateCard.tsx | 2 +- .../next/components}/TemplateCard/index.ts | 0 .../src/next/components/index.ts | 4 ++- .../src/next/extensions/index.tsx | 5 +-- .../src/next/hooks/useTemplateSchema.test.tsx | 2 +- .../src/next/hooks/useTemplateSchema.ts | 5 +-- plugins/scaffolder-react/src/next/index.ts | 2 ++ .../scaffolder-react/src/next/lib/index.ts | 16 +++++++++ .../Stepper => lib}/schema.test.ts | 0 .../{components/Stepper => lib}/schema.ts | 0 .../src/next/types.ts | 0 plugins/scaffolder-react/src/types.ts | 18 ++++++++++ plugins/scaffolder/src/api.ts | 3 +- .../MultistepJsonForm/MultistepJsonForm.tsx | 6 ++-- plugins/scaffolder/src/components/Router.tsx | 11 +++---- .../CustomFieldExplorer.tsx | 2 +- .../TemplateEditorPage/TemplateEditor.tsx | 2 +- .../TemplateEditorPage/TemplateEditorForm.tsx | 6 ++-- .../TemplateEditorPage/TemplateEditorPage.tsx | 2 +- .../TemplateFormPreviewer.tsx | 2 +- .../components/TemplatePage/TemplatePage.tsx | 2 +- .../TemplatePage/createValidator.test.ts | 2 +- .../TemplatePage/createValidator.ts | 2 +- .../scaffolder/src/components/fields/utils.ts | 2 +- plugins/scaffolder/src/index.ts | 33 ++++++++----------- .../src/next/Router/Router.test.tsx | 2 +- plugins/scaffolder/src/next/Router/Router.tsx | 6 ++-- .../TemplateListPage/TemplateGroup.test.tsx | 2 +- .../next/TemplateListPage/TemplateGroup.tsx | 5 ++- .../TemplateWizardPage/TemplateWizardPage.tsx | 8 +++-- plugins/scaffolder/src/next/index.ts | 2 +- plugins/scaffolder/src/plugin.tsx | 14 ++++---- plugins/scaffolder/src/types.ts | 17 +--------- yarn.lock | 3 ++ 47 files changed, 139 insertions(+), 96 deletions(-) rename plugins/scaffolder-react/src/next/components/{Stepper => ReviewState}/ReviewState.test.tsx (98%) rename plugins/scaffolder-react/src/next/components/{Stepper => ReviewState}/ReviewState.tsx (93%) create mode 100644 plugins/scaffolder-react/src/next/components/ReviewState/index.ts rename plugins/{scaffolder/src/next/TemplateListPage => scaffolder-react/src/next/components}/TemplateCard/CardHeader.test.tsx (100%) rename plugins/{scaffolder/src/next/TemplateListPage => scaffolder-react/src/next/components}/TemplateCard/CardHeader.tsx (100%) rename plugins/{scaffolder/src/next/TemplateListPage => scaffolder-react/src/next/components}/TemplateCard/CardLink.tsx (100%) rename plugins/{scaffolder/src/next/TemplateListPage => scaffolder-react/src/next/components}/TemplateCard/TemplateCard.test.tsx (98%) rename plugins/{scaffolder/src/next/TemplateListPage => scaffolder-react/src/next/components}/TemplateCard/TemplateCard.tsx (99%) rename plugins/{scaffolder/src/next/TemplateListPage => scaffolder-react/src/next/components}/TemplateCard/index.ts (100%) create mode 100644 plugins/scaffolder-react/src/next/lib/index.ts rename plugins/scaffolder-react/src/next/{components/Stepper => lib}/schema.test.ts (100%) rename plugins/scaffolder-react/src/next/{components/Stepper => lib}/schema.ts (100%) rename plugins/{scaffolder => scaffolder-react}/src/next/types.ts (100%) diff --git a/plugins/scaffolder-react/package.json b/plugins/scaffolder-react/package.json index 17391aedfa..b115437e33 100644 --- a/plugins/scaffolder-react/package.json +++ b/plugins/scaffolder-react/package.json @@ -38,6 +38,8 @@ "@backstage/core-components": "workspace:^", "@backstage/core-plugin-api": "workspace:^", "@backstage/errors": "workspace:^", + "@backstage/plugin-catalog-react": "workspace:^", + "@backstage/plugin-scaffolder-common": "workspace:^", "@backstage/theme": "workspace:^", "@backstage/types": "workspace:^", "@backstage/version-bridge": "workspace:^", @@ -56,6 +58,7 @@ "json-schema-library": "^7.3.9", "lodash": "^4.17.21", "qs": "^6.9.4", + "zen-observable": "^0.10.0", "zod": "~3.18.0", "zod-to-json-schema": "~3.18.0" }, @@ -67,8 +70,8 @@ "devDependencies": { "@backstage/cli": "workspace:^", "@backstage/core-app-api": "workspace:^", + "@backstage/plugin-catalog": "workspace:^", "@backstage/plugin-catalog-common": "workspace:^", - "@backstage/plugin-scaffolder-common": "workspace:^", "@backstage/test-utils": "workspace:^", "@testing-library/jest-dom": "^5.10.1", "@testing-library/react": "^12.1.3", diff --git a/plugins/scaffolder-react/src/extensions/types.ts b/plugins/scaffolder-react/src/extensions/types.ts index a2a1a8d69c..a9ed854afa 100644 --- a/plugins/scaffolder-react/src/extensions/types.ts +++ b/plugins/scaffolder-react/src/extensions/types.ts @@ -15,12 +15,6 @@ */ import { ApiHolder } from '@backstage/core-plugin-api'; import { FieldValidation, FieldProps } from '@rjsf/core'; -import { - UIOptionsType, - FieldProps as FieldPropsV5, - UiSchema as UiSchemaV5, - FieldValidation as FieldValidationV5, -} from '@rjsf/utils'; import { JSONSchema7 } from 'json-schema'; /** diff --git a/plugins/scaffolder-react/src/index.ts b/plugins/scaffolder-react/src/index.ts index 42a2cebb19..cc0e67e969 100644 --- a/plugins/scaffolder-react/src/index.ts +++ b/plugins/scaffolder-react/src/index.ts @@ -16,5 +16,5 @@ export * from './routes'; export * from './extensions'; - export * from './next'; +export * from './types'; diff --git a/plugins/scaffolder-react/src/next/components/Stepper/ReviewState.test.tsx b/plugins/scaffolder-react/src/next/components/ReviewState/ReviewState.test.tsx similarity index 98% rename from plugins/scaffolder-react/src/next/components/Stepper/ReviewState.test.tsx rename to plugins/scaffolder-react/src/next/components/ReviewState/ReviewState.test.tsx index c03df8f73c..0f56a32d1d 100644 --- a/plugins/scaffolder-react/src/next/components/Stepper/ReviewState.test.tsx +++ b/plugins/scaffolder-react/src/next/components/ReviewState/ReviewState.test.tsx @@ -17,7 +17,7 @@ import React from 'react'; import { ReviewState } from './ReviewState'; import { render } from '@testing-library/react'; -import { ParsedTemplateSchema } from './useTemplateSchema'; +import { ParsedTemplateSchema } from '../../hooks/useTemplateSchema'; describe('ReviewState', () => { it('should render the text as normal with no options', () => { diff --git a/plugins/scaffolder-react/src/next/components/Stepper/ReviewState.tsx b/plugins/scaffolder-react/src/next/components/ReviewState/ReviewState.tsx similarity index 93% rename from plugins/scaffolder-react/src/next/components/Stepper/ReviewState.tsx rename to plugins/scaffolder-react/src/next/components/ReviewState/ReviewState.tsx index f39a26622a..9b69a898f2 100644 --- a/plugins/scaffolder-react/src/next/components/Stepper/ReviewState.tsx +++ b/plugins/scaffolder-react/src/next/components/ReviewState/ReviewState.tsx @@ -16,14 +16,18 @@ import React from 'react'; import { StructuredMetadataTable } from '@backstage/core-components'; import { JsonObject } from '@backstage/types'; -import { ParsedTemplateSchema } from './useTemplateSchema'; import { Draft07 as JSONSchema } from 'json-schema-library'; +import { ParsedTemplateSchema } from '../../hooks/useTemplateSchema'; interface ReviewStateProps { schemas: ParsedTemplateSchema[]; formState: JsonObject; } +/** + * The ReviewState component used by the Stepper + * @alpha + */ export const ReviewState = (props: ReviewStateProps) => { const reviewData = Object.fromEntries( Object.entries(props.formState).map(([key, value]) => { diff --git a/plugins/scaffolder-react/src/next/components/ReviewState/index.ts b/plugins/scaffolder-react/src/next/components/ReviewState/index.ts new file mode 100644 index 0000000000..c94d73ec35 --- /dev/null +++ b/plugins/scaffolder-react/src/next/components/ReviewState/index.ts @@ -0,0 +1,16 @@ +/* + * Copyright 2022 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 { ReviewState } from './ReviewState'; diff --git a/plugins/scaffolder-react/src/next/components/Stepper/Stepper.tsx b/plugins/scaffolder-react/src/next/components/Stepper/Stepper.tsx index 72079d6f91..79c6e4fc92 100644 --- a/plugins/scaffolder-react/src/next/components/Stepper/Stepper.tsx +++ b/plugins/scaffolder-react/src/next/components/Stepper/Stepper.tsx @@ -33,7 +33,7 @@ import { NextFieldExtensionOptions } from '../../extensions'; import { TemplateParameterSchema } from '../../../types'; import { createAsyncValidators } from './createAsyncValidators'; import { useTemplateSchema } from '../../hooks/useTemplateSchema'; -import { ReviewState } from './ReviewState'; +import { ReviewState } from '../ReviewState'; import validator from '@rjsf/validator-ajv6'; import { selectedTemplateRouteRef } from '../../../routes'; import { useFormData } from '../../hooks/useFormData'; diff --git a/plugins/scaffolder-react/src/next/components/Stepper/createAsyncValidators.test.ts b/plugins/scaffolder-react/src/next/components/Stepper/createAsyncValidators.test.ts index a4a937e6fe..6ad14e3cc4 100644 --- a/plugins/scaffolder-react/src/next/components/Stepper/createAsyncValidators.test.ts +++ b/plugins/scaffolder-react/src/next/components/Stepper/createAsyncValidators.test.ts @@ -14,7 +14,7 @@ * limitations under the License. */ import { JsonObject } from '@backstage/types'; -import { NextCustomFieldValidator } from '../../../extensions'; +import { NextCustomFieldValidator } from '../../extensions'; import { createAsyncValidators } from './createAsyncValidators'; describe('createAsyncValidators', () => { diff --git a/plugins/scaffolder-react/src/next/components/Stepper/createAsyncValidators.ts b/plugins/scaffolder-react/src/next/components/Stepper/createAsyncValidators.ts index 6483ce2393..79466ee602 100644 --- a/plugins/scaffolder-react/src/next/components/Stepper/createAsyncValidators.ts +++ b/plugins/scaffolder-react/src/next/components/Stepper/createAsyncValidators.ts @@ -17,9 +17,9 @@ import { FieldValidation } from '@rjsf/utils'; import { JsonObject } from '@backstage/types'; import { ApiHolder } from '@backstage/core-plugin-api'; -import { NextCustomFieldValidator } from '../../../extensions'; import { Draft07 as JSONSchema } from 'json-schema-library'; -import { createFieldValidation } from './schema'; +import { createFieldValidation } from '../../lib'; +import { NextCustomFieldValidator } from '../../extensions'; export const createAsyncValidators = ( rootSchema: JsonObject, diff --git a/plugins/scaffolder/src/next/TemplateListPage/TemplateCard/CardHeader.test.tsx b/plugins/scaffolder-react/src/next/components/TemplateCard/CardHeader.test.tsx similarity index 100% rename from plugins/scaffolder/src/next/TemplateListPage/TemplateCard/CardHeader.test.tsx rename to plugins/scaffolder-react/src/next/components/TemplateCard/CardHeader.test.tsx diff --git a/plugins/scaffolder/src/next/TemplateListPage/TemplateCard/CardHeader.tsx b/plugins/scaffolder-react/src/next/components/TemplateCard/CardHeader.tsx similarity index 100% rename from plugins/scaffolder/src/next/TemplateListPage/TemplateCard/CardHeader.tsx rename to plugins/scaffolder-react/src/next/components/TemplateCard/CardHeader.tsx diff --git a/plugins/scaffolder/src/next/TemplateListPage/TemplateCard/CardLink.tsx b/plugins/scaffolder-react/src/next/components/TemplateCard/CardLink.tsx similarity index 100% rename from plugins/scaffolder/src/next/TemplateListPage/TemplateCard/CardLink.tsx rename to plugins/scaffolder-react/src/next/components/TemplateCard/CardLink.tsx diff --git a/plugins/scaffolder/src/next/TemplateListPage/TemplateCard/TemplateCard.test.tsx b/plugins/scaffolder-react/src/next/components/TemplateCard/TemplateCard.test.tsx similarity index 98% rename from plugins/scaffolder/src/next/TemplateListPage/TemplateCard/TemplateCard.test.tsx rename to plugins/scaffolder-react/src/next/components/TemplateCard/TemplateCard.test.tsx index cb4e8428cd..a0fb1ad74e 100644 --- a/plugins/scaffolder/src/next/TemplateListPage/TemplateCard/TemplateCard.test.tsx +++ b/plugins/scaffolder-react/src/next/components/TemplateCard/TemplateCard.test.tsx @@ -25,9 +25,9 @@ import { } from '@backstage/test-utils'; import { TemplateCard } from './TemplateCard'; import React from 'react'; -import { nextRouteRef } from '@backstage/plugin-scaffolder-react'; import { TemplateEntityV1beta3 } from '@backstage/plugin-scaffolder-common'; import { RELATION_OWNED_BY } from '@backstage/catalog-model'; +import { nextRouteRef } from '../../../routes'; describe('TemplateCard', () => { it('should render the card title', async () => { diff --git a/plugins/scaffolder/src/next/TemplateListPage/TemplateCard/TemplateCard.tsx b/plugins/scaffolder-react/src/next/components/TemplateCard/TemplateCard.tsx similarity index 99% rename from plugins/scaffolder/src/next/TemplateListPage/TemplateCard/TemplateCard.tsx rename to plugins/scaffolder-react/src/next/components/TemplateCard/TemplateCard.tsx index b5c852949c..67b50ba8d6 100644 --- a/plugins/scaffolder/src/next/TemplateListPage/TemplateCard/TemplateCard.tsx +++ b/plugins/scaffolder-react/src/next/components/TemplateCard/TemplateCard.tsx @@ -42,7 +42,7 @@ import React from 'react'; import { nextSelectedTemplateRouteRef, viewTechDocRouteRef, -} from '@backstage/plugin-scaffolder-react'; +} from '../../../routes'; import { CardHeader } from './CardHeader'; import { CardLink } from './CardLink'; diff --git a/plugins/scaffolder/src/next/TemplateListPage/TemplateCard/index.ts b/plugins/scaffolder-react/src/next/components/TemplateCard/index.ts similarity index 100% rename from plugins/scaffolder/src/next/TemplateListPage/TemplateCard/index.ts rename to plugins/scaffolder-react/src/next/components/TemplateCard/index.ts diff --git a/plugins/scaffolder-react/src/next/components/index.ts b/plugins/scaffolder-react/src/next/components/index.ts index 5532563e28..0e3f7ce7fa 100644 --- a/plugins/scaffolder-react/src/next/components/index.ts +++ b/plugins/scaffolder-react/src/next/components/index.ts @@ -13,4 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -export { Stepper } from './Stepper'; +export * from './Stepper'; +export * from './TemplateCard'; +export * from './ReviewState'; diff --git a/plugins/scaffolder-react/src/next/extensions/index.tsx b/plugins/scaffolder-react/src/next/extensions/index.tsx index 7bbf7d4112..d4161867e4 100644 --- a/plugins/scaffolder-react/src/next/extensions/index.tsx +++ b/plugins/scaffolder-react/src/next/extensions/index.tsx @@ -21,10 +21,7 @@ import { } from './types'; import { Extension, attachComponentData } from '@backstage/core-plugin-api'; import { UIOptionsType } from '@rjsf/utils'; -import { FieldExtensionComponent } from '../../extensions'; - -export const FIELD_EXTENSION_WRAPPER_KEY = 'scaffolder.extensions.wrapper.v1'; -export const FIELD_EXTENSION_KEY = 'scaffolder.extensions.field.v1'; +import { FieldExtensionComponent, FIELD_EXTENSION_KEY } from '../../extensions'; /** * Method for creating field extensions that can be used in the scaffolder diff --git a/plugins/scaffolder-react/src/next/hooks/useTemplateSchema.test.tsx b/plugins/scaffolder-react/src/next/hooks/useTemplateSchema.test.tsx index 9be6faa0fa..153c48468d 100644 --- a/plugins/scaffolder-react/src/next/hooks/useTemplateSchema.test.tsx +++ b/plugins/scaffolder-react/src/next/hooks/useTemplateSchema.test.tsx @@ -13,12 +13,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { TemplateParameterSchema } from '../../../types'; import { useTemplateSchema } from './useTemplateSchema'; import { renderHook } from '@testing-library/react-hooks'; import { TestApiProvider } from '@backstage/test-utils'; import React from 'react'; import { featureFlagsApiRef } from '@backstage/core-plugin-api'; +import { TemplateParameterSchema } from '../../types'; describe('useTemplateSchema', () => { it('should generate the correct schema', () => { diff --git a/plugins/scaffolder-react/src/next/hooks/useTemplateSchema.ts b/plugins/scaffolder-react/src/next/hooks/useTemplateSchema.ts index 6aad6baa96..733c8960b9 100644 --- a/plugins/scaffolder-react/src/next/hooks/useTemplateSchema.ts +++ b/plugins/scaffolder-react/src/next/hooks/useTemplateSchema.ts @@ -16,8 +16,8 @@ import { featureFlagsApiRef, useApi } from '@backstage/core-plugin-api'; import { JsonObject } from '@backstage/types'; import { UiSchema } from '@rjsf/utils'; -import { TemplateParameterSchema } from '../../../types'; -import { extractSchemaFromStep } from './schema'; +import { TemplateParameterSchema } from '../../types'; +import { extractSchemaFromStep } from '../lib'; export interface ParsedTemplateSchema { uiSchema: UiSchema; @@ -26,6 +26,7 @@ export interface ParsedTemplateSchema { title: string; description?: string; } + export const useTemplateSchema = ( manifest: TemplateParameterSchema, ): { steps: ParsedTemplateSchema[] } => { diff --git a/plugins/scaffolder-react/src/next/index.ts b/plugins/scaffolder-react/src/next/index.ts index aa46a7a6cd..29992c26d5 100644 --- a/plugins/scaffolder-react/src/next/index.ts +++ b/plugins/scaffolder-react/src/next/index.ts @@ -15,3 +15,5 @@ */ export * from './components'; export * from './extensions'; +export * from './types'; +export * from './lib'; diff --git a/plugins/scaffolder-react/src/next/lib/index.ts b/plugins/scaffolder-react/src/next/lib/index.ts new file mode 100644 index 0000000000..f42c4c8ab3 --- /dev/null +++ b/plugins/scaffolder-react/src/next/lib/index.ts @@ -0,0 +1,16 @@ +/* + * Copyright 2022 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 { extractSchemaFromStep, createFieldValidation } from './schema'; diff --git a/plugins/scaffolder-react/src/next/components/Stepper/schema.test.ts b/plugins/scaffolder-react/src/next/lib/schema.test.ts similarity index 100% rename from plugins/scaffolder-react/src/next/components/Stepper/schema.test.ts rename to plugins/scaffolder-react/src/next/lib/schema.test.ts diff --git a/plugins/scaffolder-react/src/next/components/Stepper/schema.ts b/plugins/scaffolder-react/src/next/lib/schema.ts similarity index 100% rename from plugins/scaffolder-react/src/next/components/Stepper/schema.ts rename to plugins/scaffolder-react/src/next/lib/schema.ts diff --git a/plugins/scaffolder/src/next/types.ts b/plugins/scaffolder-react/src/next/types.ts similarity index 100% rename from plugins/scaffolder/src/next/types.ts rename to plugins/scaffolder-react/src/next/types.ts diff --git a/plugins/scaffolder-react/src/types.ts b/plugins/scaffolder-react/src/types.ts index b61d59e88d..f644fbeb64 100644 --- a/plugins/scaffolder-react/src/types.ts +++ b/plugins/scaffolder-react/src/types.ts @@ -13,3 +13,21 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + +import { JsonObject } from '@backstage/types'; + +/** + * The shape of each entry of parameters which gets rendered + * as a separate step in the wizard input + * + * @public + */ +export type TemplateParameterSchema = { + title: string; + description?: string; + steps: Array<{ + title: string; + description?: string; + schema: JsonObject; + }>; +}; diff --git a/plugins/scaffolder/src/api.ts b/plugins/scaffolder/src/api.ts index 64141dd83d..3a60f6b9a9 100644 --- a/plugins/scaffolder/src/api.ts +++ b/plugins/scaffolder/src/api.ts @@ -30,7 +30,6 @@ import { ListActionsResponse, LogEvent, ScaffolderApi, - TemplateParameterSchema, ScaffolderScaffoldOptions, ScaffolderScaffoldResponse, ScaffolderStreamLogsOptions, @@ -40,6 +39,8 @@ import { ScaffolderDryRunOptions, ScaffolderDryRunResponse, } from './types'; + +import { TemplateParameterSchema } from '@backstage/plugin-scaffolder-react'; import queryString from 'qs'; /** diff --git a/plugins/scaffolder/src/components/MultistepJsonForm/MultistepJsonForm.tsx b/plugins/scaffolder/src/components/MultistepJsonForm/MultistepJsonForm.tsx index 0ca331ab52..65db4217be 100644 --- a/plugins/scaffolder/src/components/MultistepJsonForm/MultistepJsonForm.tsx +++ b/plugins/scaffolder/src/components/MultistepJsonForm/MultistepJsonForm.tsx @@ -39,8 +39,10 @@ import * as fieldOverrides from './FieldOverrides'; import { LayoutOptions } from '../../layouts'; import { ReviewStepProps } from '../types'; import { ReviewStep } from './ReviewStep'; -import { selectedTemplateRouteRef } from '@backstage/plugin-scaffolder-react'; -import { extractSchemaFromStep } from '../../next/TemplateWizardPage/Stepper/schema'; +import { + selectedTemplateRouteRef, + extractSchemaFromStep, +} from '@backstage/plugin-scaffolder-react'; const Form = withTheme(MuiTheme); diff --git a/plugins/scaffolder/src/components/Router.tsx b/plugins/scaffolder/src/components/Router.tsx index 13ef9ed43f..0e865024bd 100644 --- a/plugins/scaffolder/src/components/Router.tsx +++ b/plugins/scaffolder/src/components/Router.tsx @@ -24,13 +24,7 @@ import { TaskPage } from './TaskPage'; import { ActionsPage } from './ActionsPage'; import { SecretsContextProvider } from './secrets/SecretsContext'; import { TemplateEditorPage } from './TemplateEditorPage'; - -import { - DEFAULT_SCAFFOLDER_FIELD_EXTENSIONS, - FIELD_EXTENSION_KEY, - FIELD_EXTENSION_WRAPPER_KEY, - FieldExtensionOptions, -} from '../extensions'; +import { DEFAULT_SCAFFOLDER_FIELD_EXTENSIONS } from '../extensions/default'; import { useElementFilter, useRouteRef, @@ -43,6 +37,9 @@ import { scaffolderListTaskRouteRef, scaffolderTaskRouteRef, selectedTemplateRouteRef, + FIELD_EXTENSION_KEY, + FIELD_EXTENSION_WRAPPER_KEY, + FieldExtensionOptions, } from '@backstage/plugin-scaffolder-react'; import { ListTasksPage } from './ListTasksPage'; import { LayoutOptions, LAYOUTS_KEY, LAYOUTS_WRAPPER_KEY } from '../layouts'; diff --git a/plugins/scaffolder/src/components/TemplateEditorPage/CustomFieldExplorer.tsx b/plugins/scaffolder/src/components/TemplateEditorPage/CustomFieldExplorer.tsx index 3510968acd..c7138efb97 100644 --- a/plugins/scaffolder/src/components/TemplateEditorPage/CustomFieldExplorer.tsx +++ b/plugins/scaffolder/src/components/TemplateEditorPage/CustomFieldExplorer.tsx @@ -33,7 +33,7 @@ import { Theme as MuiTheme } from '@rjsf/material-ui'; import CodeMirror from '@uiw/react-codemirror'; import React, { useCallback, useMemo, useState } from 'react'; import yaml from 'yaml'; -import { FieldExtensionOptions } from '../../extensions'; +import { FieldExtensionOptions } from '@backstage/plugin-scaffolder-react'; import * as fieldOverrides from '../MultistepJsonForm/FieldOverrides'; import { TemplateEditorForm } from './TemplateEditorForm'; diff --git a/plugins/scaffolder/src/components/TemplateEditorPage/TemplateEditor.tsx b/plugins/scaffolder/src/components/TemplateEditorPage/TemplateEditor.tsx index 7055e42c84..dc67f687bb 100644 --- a/plugins/scaffolder/src/components/TemplateEditorPage/TemplateEditor.tsx +++ b/plugins/scaffolder/src/components/TemplateEditorPage/TemplateEditor.tsx @@ -15,7 +15,7 @@ */ import { makeStyles } from '@material-ui/core'; import React, { useState } from 'react'; -import { FieldExtensionOptions } from '../../extensions'; +import { FieldExtensionOptions } from '@backstage/plugin-scaffolder-react'; import type { LayoutOptions } from '../../layouts'; import { TemplateDirectoryAccess } from '../../lib/filesystem'; import { DirectoryEditorProvider } from './DirectoryEditorContext'; diff --git a/plugins/scaffolder/src/components/TemplateEditorPage/TemplateEditorForm.tsx b/plugins/scaffolder/src/components/TemplateEditorPage/TemplateEditorForm.tsx index 192a9696cf..c62112a89c 100644 --- a/plugins/scaffolder/src/components/TemplateEditorPage/TemplateEditorForm.tsx +++ b/plugins/scaffolder/src/components/TemplateEditorPage/TemplateEditorForm.tsx @@ -19,9 +19,11 @@ import { makeStyles } from '@material-ui/core/styles'; import React, { Component, ReactNode, useMemo, useState } from 'react'; import useDebounce from 'react-use/lib/useDebounce'; import yaml from 'yaml'; -import { FieldExtensionOptions } from '../../extensions'; +import { + FieldExtensionOptions, + TemplateParameterSchema, +} from '@backstage/plugin-scaffolder-react'; import { LayoutOptions } from '../../layouts'; -import { TemplateParameterSchema } from '../../types'; import { MultistepJsonForm } from '../MultistepJsonForm'; import { createValidator } from '../TemplatePage'; import { useDirectoryEditor } from './DirectoryEditorContext'; diff --git a/plugins/scaffolder/src/components/TemplateEditorPage/TemplateEditorPage.tsx b/plugins/scaffolder/src/components/TemplateEditorPage/TemplateEditorPage.tsx index 8847b85373..20691a8e85 100644 --- a/plugins/scaffolder/src/components/TemplateEditorPage/TemplateEditorPage.tsx +++ b/plugins/scaffolder/src/components/TemplateEditorPage/TemplateEditorPage.tsx @@ -23,7 +23,7 @@ import { CustomFieldExplorer } from './CustomFieldExplorer'; import { TemplateEditorIntro } from './TemplateEditorIntro'; import { TemplateEditor } from './TemplateEditor'; import { TemplateFormPreviewer } from './TemplateFormPreviewer'; -import { FieldExtensionOptions } from '../../extensions'; +import { FieldExtensionOptions } from '@backstage/plugin-scaffolder-react'; import type { LayoutOptions } from '../../layouts'; type Selection = diff --git a/plugins/scaffolder/src/components/TemplateEditorPage/TemplateFormPreviewer.tsx b/plugins/scaffolder/src/components/TemplateEditorPage/TemplateFormPreviewer.tsx index 5bc32ed581..884305bf64 100644 --- a/plugins/scaffolder/src/components/TemplateEditorPage/TemplateFormPreviewer.tsx +++ b/plugins/scaffolder/src/components/TemplateEditorPage/TemplateFormPreviewer.tsx @@ -32,7 +32,7 @@ import CloseIcon from '@material-ui/icons/Close'; import React, { useCallback, useState } from 'react'; import useAsync from 'react-use/lib/useAsync'; import yaml from 'yaml'; -import { FieldExtensionOptions } from '../../extensions'; +import { FieldExtensionOptions } from '@backstage/plugin-scaffolder-react'; import { LayoutOptions } from '../../layouts'; import { TemplateEditorForm } from './TemplateEditorForm'; import { TemplateEditorTextArea } from './TemplateEditorTextArea'; diff --git a/plugins/scaffolder/src/components/TemplatePage/TemplatePage.tsx b/plugins/scaffolder/src/components/TemplatePage/TemplatePage.tsx index 5d02bc436d..5773691438 100644 --- a/plugins/scaffolder/src/components/TemplatePage/TemplatePage.tsx +++ b/plugins/scaffolder/src/components/TemplatePage/TemplatePage.tsx @@ -20,12 +20,12 @@ import React, { ComponentType, useCallback, useContext, useState } from 'react'; import { Navigate, useNavigate } from 'react-router-dom'; import useAsync from 'react-use/lib/useAsync'; import { scaffolderApiRef } from '../../api'; -import { FieldExtensionOptions } from '../../extensions'; import { SecretsContext } from '../secrets/SecretsContext'; import { rootRouteRef, scaffolderTaskRouteRef, selectedTemplateRouteRef, + FieldExtensionOptions, } from '@backstage/plugin-scaffolder-react'; import { MultistepJsonForm } from '../MultistepJsonForm'; import { createValidator } from './createValidator'; diff --git a/plugins/scaffolder/src/components/TemplatePage/createValidator.test.ts b/plugins/scaffolder/src/components/TemplatePage/createValidator.test.ts index f549c9e7f2..177697eda0 100644 --- a/plugins/scaffolder/src/components/TemplatePage/createValidator.test.ts +++ b/plugins/scaffolder/src/components/TemplatePage/createValidator.test.ts @@ -15,7 +15,7 @@ */ import { createValidator } from './createValidator'; -import { CustomFieldValidator } from '../../extensions'; +import { CustomFieldValidator } from '@backstage/plugin-scaffolder-react'; import { ApiHolder } from '@backstage/core-plugin-api'; import { FormValidation } from '@rjsf/core'; diff --git a/plugins/scaffolder/src/components/TemplatePage/createValidator.ts b/plugins/scaffolder/src/components/TemplatePage/createValidator.ts index 9cd1489a02..4a64481fc3 100644 --- a/plugins/scaffolder/src/components/TemplatePage/createValidator.ts +++ b/plugins/scaffolder/src/components/TemplatePage/createValidator.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import { CustomFieldValidator } from '../../extensions'; +import { CustomFieldValidator } from '@backstage/plugin-scaffolder-react'; import { FormValidation } from '@rjsf/core'; import { JsonObject, JsonValue } from '@backstage/types'; import { ApiHolder } from '@backstage/core-plugin-api'; diff --git a/plugins/scaffolder/src/components/fields/utils.ts b/plugins/scaffolder/src/components/fields/utils.ts index 2d3e2aab1e..7b59f1da90 100644 --- a/plugins/scaffolder/src/components/fields/utils.ts +++ b/plugins/scaffolder/src/components/fields/utils.ts @@ -19,7 +19,7 @@ import zodToJsonSchema from 'zod-to-json-schema'; import { CustomFieldExtensionSchema, FieldExtensionComponentProps, -} from '../../extensions'; +} from '@backstage/plugin-scaffolder-react'; /** * @public diff --git a/plugins/scaffolder/src/index.ts b/plugins/scaffolder/src/index.ts index c18abf92fd..a486f2ff8d 100644 --- a/plugins/scaffolder/src/index.ts +++ b/plugins/scaffolder/src/index.ts @@ -36,19 +36,8 @@ export type { ScaffolderTask, ScaffolderTaskOutput, ScaffolderTaskStatus, - TemplateParameterSchema, } from './types'; -export { - createScaffolderFieldExtension, - ScaffolderFieldExtensions, -} from './extensions'; -export type { - CustomFieldExtensionSchema, - CustomFieldValidator, - FieldExtensionOptions, - FieldExtensionComponentProps, - FieldExtensionComponent, -} from './extensions'; + export { createScaffolderLayout, ScaffolderLayouts } from './layouts'; export type { LayoutOptions, LayoutTemplate, LayoutComponent } from './layouts'; export { @@ -64,10 +53,23 @@ export { export * from './components'; export { + createScaffolderFieldExtension, + ScaffolderFieldExtensions, rootRouteRef, nextRouteRef, selectedTemplateRouteRef, nextSelectedTemplateRouteRef, + createNextScaffolderFieldExtension, + type TemplateParameterSchema, + type NextCustomFieldValidator, + type NextFieldExtensionOptions, + type NextFieldExtensionComponentProps, + type FormProps, + type CustomFieldExtensionSchema, + type CustomFieldValidator, + type FieldExtensionOptions, + type FieldExtensionComponentProps, + type FieldExtensionComponent, } from '@backstage/plugin-scaffolder-react'; export type { TaskPageProps } from './components/TaskPage'; @@ -76,10 +78,3 @@ export type { TaskPageProps } from './components/TaskPage'; export { NextScaffolderPage } from './plugin'; export type { NextRouterProps } from './next'; export type { TemplateGroupFilter } from './next'; -export type { FormProps } from './next'; -export { - createNextScaffolderFieldExtension, - type NextCustomFieldValidator, - type NextFieldExtensionOptions, - type NextFieldExtensionComponentProps, -} from './extensions'; diff --git a/plugins/scaffolder/src/next/Router/Router.test.tsx b/plugins/scaffolder/src/next/Router/Router.test.tsx index 89f8f6ecd3..4e5535be6c 100644 --- a/plugins/scaffolder/src/next/Router/Router.test.tsx +++ b/plugins/scaffolder/src/next/Router/Router.test.tsx @@ -21,7 +21,7 @@ import { renderInTestApp } from '@backstage/test-utils'; import { createScaffolderFieldExtension, ScaffolderFieldExtensions, -} from '../../extensions'; +} from '@backstage/plugin-scaffolder-react'; import { scaffolderPlugin } from '../../plugin'; jest.mock('../TemplateListPage', () => ({ diff --git a/plugins/scaffolder/src/next/Router/Router.tsx b/plugins/scaffolder/src/next/Router/Router.tsx index 97985642f9..ea620a7820 100644 --- a/plugins/scaffolder/src/next/Router/Router.tsx +++ b/plugins/scaffolder/src/next/Router/Router.tsx @@ -20,17 +20,17 @@ import { TemplateWizardPage } from '../TemplateWizardPage'; import { FIELD_EXTENSION_WRAPPER_KEY, FIELD_EXTENSION_KEY, - DEFAULT_SCAFFOLDER_FIELD_EXTENSIONS, NextFieldExtensionOptions, FieldExtensionOptions, -} from '../../extensions'; + type FormProps, +} from '@backstage/plugin-scaffolder-react'; import { useElementFilter } from '@backstage/core-plugin-api'; import { TemplateEntityV1beta3 } from '@backstage/plugin-scaffolder-common'; import { TemplateGroupFilter } from '../TemplateListPage/TemplateGroups'; import { nextSelectedTemplateRouteRef } from '@backstage/plugin-scaffolder-react'; import { SecretsContextProvider } from '../../components/secrets/SecretsContext'; -import type { FormProps } from '../types'; +import { DEFAULT_SCAFFOLDER_FIELD_EXTENSIONS } from '../../extensions/default'; /** * The Props for the Scaffolder Router diff --git a/plugins/scaffolder/src/next/TemplateListPage/TemplateGroup.test.tsx b/plugins/scaffolder/src/next/TemplateListPage/TemplateGroup.test.tsx index 59c6989c0d..681aea2c6f 100644 --- a/plugins/scaffolder/src/next/TemplateListPage/TemplateGroup.test.tsx +++ b/plugins/scaffolder/src/next/TemplateListPage/TemplateGroup.test.tsx @@ -18,7 +18,7 @@ jest.mock('./TemplateCard', () => ({ TemplateCard: jest.fn(() => null) })); import React from 'react'; import { TemplateGroup } from './TemplateGroup'; import { render } from '@testing-library/react'; -import { TemplateCard } from './TemplateCard'; +import { TemplateCard } from '@backstage/plugin-scaffolder-react'; import { TemplateEntityV1beta3 } from '@backstage/plugin-scaffolder-common'; describe('TemplateGroup', () => { diff --git a/plugins/scaffolder/src/next/TemplateListPage/TemplateGroup.tsx b/plugins/scaffolder/src/next/TemplateListPage/TemplateGroup.tsx index 4344c195ae..cd7e9bb6c4 100644 --- a/plugins/scaffolder/src/next/TemplateListPage/TemplateGroup.tsx +++ b/plugins/scaffolder/src/next/TemplateListPage/TemplateGroup.tsx @@ -22,7 +22,10 @@ import { Link, } from '@backstage/core-components'; import { Typography } from '@material-ui/core'; -import { TemplateCard, TemplateCardProps } from './TemplateCard'; +import { + TemplateCard, + TemplateCardProps, +} from '@backstage/plugin-scaffolder-react'; import { stringifyEntityRef } from '@backstage/catalog-model'; export interface TemplateGroupProps { diff --git a/plugins/scaffolder/src/next/TemplateWizardPage/TemplateWizardPage.tsx b/plugins/scaffolder/src/next/TemplateWizardPage/TemplateWizardPage.tsx index 75da592bba..2bb8eb5f8b 100644 --- a/plugins/scaffolder/src/next/TemplateWizardPage/TemplateWizardPage.tsx +++ b/plugins/scaffolder/src/next/TemplateWizardPage/TemplateWizardPage.tsx @@ -22,7 +22,6 @@ import { InfoCard, MarkdownContent, } from '@backstage/core-components'; -import { NextFieldExtensionOptions } from '../../extensions'; import { Navigate, useNavigate } from 'react-router-dom'; import { stringifyEntityRef } from '@backstage/catalog-model'; import { @@ -35,7 +34,10 @@ import { import { scaffolderApiRef } from '../../api'; import useAsync from 'react-use/lib/useAsync'; import { makeStyles } from '@material-ui/core'; -import { Stepper } from '@backstage/plugin-scaffolder-react'; +import { + Stepper, + NextFieldExtensionOptions, +} from '@backstage/plugin-scaffolder-react'; import { BackstageTheme } from '@backstage/theme'; import { nextRouteRef, @@ -44,7 +46,7 @@ import { } from '@backstage/plugin-scaffolder-react'; import { SecretsContext } from '../../components/secrets/SecretsContext'; import { JsonValue } from '@backstage/types'; -import type { FormProps } from '../types'; +import type { FormProps } from '@backstage/plugin-scaffolder-react'; export type TemplateWizardPageProps = { customFieldExtensions: NextFieldExtensionOptions[]; diff --git a/plugins/scaffolder/src/next/index.ts b/plugins/scaffolder/src/next/index.ts index 3a874e3b41..30fbb7ff15 100644 --- a/plugins/scaffolder/src/next/index.ts +++ b/plugins/scaffolder/src/next/index.ts @@ -17,4 +17,4 @@ export * from './Router'; export * from './TemplateListPage'; export * from './TemplateWizardPage'; -export type { FormProps } from './types'; +export type { FormProps } from '@backstage/plugin-scaffolder-react'; diff --git a/plugins/scaffolder/src/plugin.tsx b/plugins/scaffolder/src/plugin.tsx index f6a8915c48..5049f8a050 100644 --- a/plugins/scaffolder/src/plugin.tsx +++ b/plugins/scaffolder/src/plugin.tsx @@ -15,6 +15,13 @@ */ import { scmIntegrationsApiRef } from '@backstage/integration-react'; +import { + nextRouteRef, + registerComponentRouteRef, + rootRouteRef, + viewTechDocRouteRef, + createScaffolderFieldExtension, +} from '@backstage/plugin-scaffolder-react'; import { scaffolderApiRef, ScaffolderClient } from './api'; import { EntityPicker, @@ -34,13 +41,6 @@ import { RepoUrlPicker, RepoUrlPickerSchema, } from './components/fields/RepoUrlPicker/RepoUrlPicker'; -import { createScaffolderFieldExtension } from './extensions'; -import { - nextRouteRef, - registerComponentRouteRef, - rootRouteRef, - viewTechDocRouteRef, -} from '@backstage/plugin-scaffolder-react'; import { createApiFactory, createPlugin, diff --git a/plugins/scaffolder/src/types.ts b/plugins/scaffolder/src/types.ts index acb0f0e114..0bde515bda 100644 --- a/plugins/scaffolder/src/types.ts +++ b/plugins/scaffolder/src/types.ts @@ -14,6 +14,7 @@ * limitations under the License. */ import { TaskSpec, TaskStep } from '@backstage/plugin-scaffolder-common'; +import { TemplateParameterSchema } from '@backstage/plugin-scaffolder-react'; import { JsonObject, JsonValue, Observable } from '@backstage/types'; import { JSONSchema7 } from 'json-schema'; @@ -71,22 +72,6 @@ export type ScaffolderTaskOutput = { [key: string]: unknown; }; -/** - * The shape of each entry of parameters which gets rendered - * as a separate step in the wizard input - * - * @public - */ -export type TemplateParameterSchema = { - title: string; - description?: string; - steps: Array<{ - title: string; - description?: string; - schema: JsonObject; - }>; -}; - /** * The shape of a `LogEvent` message from the `scaffolder-backend` * diff --git a/yarn.lock b/yarn.lock index 827fa3423a..00f8355d8b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7461,7 +7461,9 @@ __metadata: "@backstage/core-components": "workspace:^" "@backstage/core-plugin-api": "workspace:^" "@backstage/errors": "workspace:^" + "@backstage/plugin-catalog": "workspace:^" "@backstage/plugin-catalog-common": "workspace:^" + "@backstage/plugin-catalog-react": "workspace:^" "@backstage/plugin-scaffolder-common": "workspace:^" "@backstage/test-utils": "workspace:^" "@backstage/theme": "workspace:^" @@ -7486,6 +7488,7 @@ __metadata: json-schema-library: ^7.3.9 lodash: ^4.17.21 qs: ^6.9.4 + zen-observable: ^0.10.0 zod: ~3.18.0 zod-to-json-schema: ~3.18.0 peerDependencies: From c2f1010f3c58abcb6503ee149590cfb1eacb5c8e Mon Sep 17 00:00:00 2001 From: blam Date: Thu, 22 Dec 2022 17:33:07 +0100 Subject: [PATCH 04/35] chore: fixing the re-exporting of the types with the alpha annotation Signed-off-by: blam --- plugins/scaffolder-react/api-report.md | 248 +++++++++++++++++++++++++ plugins/scaffolder/src/index.ts | 66 ++++++- plugins/scaffolder/src/next/index.ts | 2 - 3 files changed, 307 insertions(+), 9 deletions(-) create mode 100644 plugins/scaffolder-react/api-report.md diff --git a/plugins/scaffolder-react/api-report.md b/plugins/scaffolder-react/api-report.md new file mode 100644 index 0000000000..81259772b5 --- /dev/null +++ b/plugins/scaffolder-react/api-report.md @@ -0,0 +1,248 @@ +## API Report File for "@backstage/plugin-scaffolder-react" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts +/// + +import { ApiHolder } from '@backstage/core-plugin-api'; +import { Extension } from '@backstage/core-plugin-api'; +import { ExternalRouteRef } from '@backstage/core-plugin-api'; +import { FieldProps } from '@rjsf/core'; +import { FieldProps as FieldProps_2 } from '@rjsf/utils'; +import { FieldValidation } from '@rjsf/core'; +import { FieldValidation as FieldValidation_2 } from '@rjsf/utils'; +import type { FormProps as FormProps_2 } from '@rjsf/core-v5'; +import { JsonObject } from '@backstage/types'; +import { JSONSchema7 } from 'json-schema'; +import { JsonValue } from '@backstage/types'; +import { PathParams } from '@backstage/core-plugin-api'; +import { PropsWithChildren } from 'react'; +import { default as React_2 } from 'react'; +import { RouteRef } from '@backstage/core-plugin-api'; +import { SubRouteRef } from '@backstage/core-plugin-api'; +import { TemplateEntityV1beta3 } from '@backstage/plugin-scaffolder-common'; +import { UIOptionsType } from '@rjsf/utils'; +import { UiSchema } from '@rjsf/utils'; + +// Warning: (ae-missing-release-tag) "actionsRouteRef" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export const actionsRouteRef: SubRouteRef; + +// @alpha +export const createFieldValidation: () => FieldValidation_2; + +// @alpha +export function createNextScaffolderFieldExtension< + TReturnValue = unknown, + TInputProps extends UIOptionsType = {}, +>( + options: NextFieldExtensionOptions, +): Extension>; + +// @public +export function createScaffolderFieldExtension< + TReturnValue = unknown, + TInputProps = unknown, +>( + options: FieldExtensionOptions, +): Extension>; + +// @public +export type CustomFieldExtensionSchema = { + returnValue: JSONSchema7; + uiOptions?: JSONSchema7; +}; + +// @public +export type CustomFieldValidator = ( + data: TFieldReturnValue, + field: FieldValidation, + context: { + apiHolder: ApiHolder; + }, +) => void | Promise; + +// Warning: (ae-missing-release-tag) "editRouteRef" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export const editRouteRef: SubRouteRef; + +// @alpha +export const extractSchemaFromStep: (inputStep: JsonObject) => { + uiSchema: UiSchema; + schema: JsonObject; +}; + +// Warning: (ae-missing-release-tag) "FIELD_EXTENSION_KEY" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export const FIELD_EXTENSION_KEY = 'scaffolder.extensions.field.v1'; + +// Warning: (ae-missing-release-tag) "FIELD_EXTENSION_WRAPPER_KEY" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export const FIELD_EXTENSION_WRAPPER_KEY = 'scaffolder.extensions.wrapper.v1'; + +// @public +export type FieldExtensionComponent<_TReturnValue, _TInputProps> = () => null; + +// @public +export interface FieldExtensionComponentProps< + TFieldReturnValue, + TUiOptions extends {} = {}, +> extends FieldProps { + // (undocumented) + uiSchema: FieldProps['uiSchema'] & { + 'ui:options'?: TUiOptions; + }; +} + +// @public +export type FieldExtensionOptions< + TFieldReturnValue = unknown, + TInputProps = unknown, +> = { + name: string; + component: ( + props: FieldExtensionComponentProps, + ) => JSX.Element | null; + validation?: CustomFieldValidator; + schema?: CustomFieldExtensionSchema; +}; + +// @alpha +export type FormProps = Pick< + FormProps_2, + 'transformErrors' | 'noHtml5Validate' +>; + +// Warning: (ae-missing-release-tag) "legacySelectedTemplateRouteRef" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public @deprecated (undocumented) +export const legacySelectedTemplateRouteRef: SubRouteRef< + PathParams<'/templates/:templateName'> +>; + +// @alpha +export type NextCustomFieldValidator = ( + data: TFieldReturnValue, + field: FieldValidation_2, + context: { + apiHolder: ApiHolder; + formData: JsonObject; + }, +) => void | Promise; + +// @alpha +export interface NextFieldExtensionComponentProps< + TFieldReturnValue, + TUiOptions = {}, +> extends PropsWithChildren> { + // (undocumented) + uiSchema?: UiSchema & { + 'ui:options'?: TUiOptions & UIOptionsType; + }; +} + +// @alpha +export type NextFieldExtensionOptions< + TFieldReturnValue = unknown, + TInputProps = unknown, +> = { + name: string; + component: ( + props: NextFieldExtensionComponentProps, + ) => JSX.Element | null; + validation?: NextCustomFieldValidator; + schema?: CustomFieldExtensionSchema; +}; + +// @alpha (undocumented) +export const nextRouteRef: RouteRef; + +// Warning: (ae-missing-release-tag) "nextScaffolderTaskRouteRef" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export const nextScaffolderTaskRouteRef: SubRouteRef< + PathParams<'/tasks/:taskId'> +>; + +// @alpha (undocumented) +export const nextSelectedTemplateRouteRef: SubRouteRef< + PathParams<'/templates/:namespace/:templateName'> +>; + +// Warning: (ae-missing-release-tag) "registerComponentRouteRef" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export const registerComponentRouteRef: ExternalRouteRef; + +// Warning: (ae-forgotten-export) The symbol "ReviewStateProps" needs to be exported by the entry point index.d.ts +// +// @alpha +export const ReviewState: (props: ReviewStateProps) => JSX.Element; + +// @public (undocumented) +export const rootRouteRef: RouteRef; + +// @public +export const ScaffolderFieldExtensions: React_2.ComponentType; + +// Warning: (ae-missing-release-tag) "scaffolderListTaskRouteRef" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export const scaffolderListTaskRouteRef: SubRouteRef; + +// Warning: (ae-missing-release-tag) "scaffolderTaskRouteRef" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export const scaffolderTaskRouteRef: SubRouteRef>; + +// @public (undocumented) +export const selectedTemplateRouteRef: SubRouteRef< + PathParams<'/templates/:namespace/:templateName'> +>; + +// Warning: (ae-forgotten-export) The symbol "StepperProps" needs to be exported by the entry point index.d.ts +// +// @alpha (undocumented) +export const Stepper: (props: StepperProps) => JSX.Element; + +// @alpha +export const TemplateCard: (props: TemplateCardProps) => JSX.Element; + +// @alpha +export interface TemplateCardProps { + // (undocumented) + deprecated?: boolean; + // (undocumented) + template: TemplateEntityV1beta3; +} + +// @public +export type TemplateParameterSchema = { + title: string; + description?: string; + steps: Array<{ + title: string; + description?: string; + schema: JsonObject; + }>; +}; + +// Warning: (ae-missing-release-tag) "viewTechDocRouteRef" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export const viewTechDocRouteRef: ExternalRouteRef< + { + name: string; + kind: string; + namespace: string; + }, + true +>; + +// (No @packageDocumentation comment for this package) +``` diff --git a/plugins/scaffolder/src/index.ts b/plugins/scaffolder/src/index.ts index a486f2ff8d..9f993d2a13 100644 --- a/plugins/scaffolder/src/index.ts +++ b/plugins/scaffolder/src/index.ts @@ -56,15 +56,8 @@ export { createScaffolderFieldExtension, ScaffolderFieldExtensions, rootRouteRef, - nextRouteRef, selectedTemplateRouteRef, - nextSelectedTemplateRouteRef, - createNextScaffolderFieldExtension, type TemplateParameterSchema, - type NextCustomFieldValidator, - type NextFieldExtensionOptions, - type NextFieldExtensionComponentProps, - type FormProps, type CustomFieldExtensionSchema, type CustomFieldValidator, type FieldExtensionOptions, @@ -78,3 +71,62 @@ export type { TaskPageProps } from './components/TaskPage'; export { NextScaffolderPage } from './plugin'; export type { NextRouterProps } from './next'; export type { TemplateGroupFilter } from './next'; + +// These types in the future can be removed from being exported out of this package and be imported +// instead from @backstage/plugin-scaffolder-react. They have to be redeclared here to keep the alpha +// annotation in order to not polluted the main export surface. +import { + nextRouteRef as nextRouteRefTemp, + nextSelectedTemplateRouteRef as nextSelectedTemplateRouteRefTemp, + createNextScaffolderFieldExtension as createNextScaffolderFieldExtensionTemp, + type NextCustomFieldValidator as NextCustomFieldValidatorTemp, + type NextFieldExtensionOptions as NextFieldExtensionOptionsTemp, + type NextFieldExtensionComponentProps as NextFieldExtensionComponentPropsTemp, + type FormProps as FormPropsTemp, +} from '@backstage/plugin-scaffolder-react'; + +/** + * @alpha + */ +const nextRouteRef = nextRouteRefTemp; +/** + * @alpha + */ +const nextSelectedTemplateRouteRef = nextSelectedTemplateRouteRefTemp; +/** + * @alpha + */ +const createNextScaffolderFieldExtension = + createNextScaffolderFieldExtensionTemp; +/** + * @alpha + */ +type NextCustomFieldValidator = NextCustomFieldValidatorTemp; +/** + * @alpha + */ +type NextFieldExtensionOptions< + TFieldReturnValue = unknown, + TInputProps = unknown, +> = NextFieldExtensionOptionsTemp; +/** + * @alpha + */ +type NextFieldExtensionComponentProps< + TFieldReturnValue, + TUiOptions = {}, +> = NextFieldExtensionComponentPropsTemp; +/** + * @alpha + */ +type FormProps = FormPropsTemp; + +export { + nextRouteRef, + nextSelectedTemplateRouteRef, + createNextScaffolderFieldExtension, + type NextCustomFieldValidator, + type NextFieldExtensionOptions, + type NextFieldExtensionComponentProps, + type FormProps, +}; diff --git a/plugins/scaffolder/src/next/index.ts b/plugins/scaffolder/src/next/index.ts index 30fbb7ff15..089c268b0b 100644 --- a/plugins/scaffolder/src/next/index.ts +++ b/plugins/scaffolder/src/next/index.ts @@ -16,5 +16,3 @@ export * from './Router'; export * from './TemplateListPage'; export * from './TemplateWizardPage'; - -export type { FormProps } from '@backstage/plugin-scaffolder-react'; From 70beaaaa226cc6ff62cf3c6755797b14e14126d2 Mon Sep 17 00:00:00 2001 From: blam Date: Fri, 23 Dec 2022 11:05:49 +0100 Subject: [PATCH 05/35] chore: moving smaller components over from the next package Signed-off-by: blam --- .../TemplateGroup}/TemplateGroup.test.tsx | 4 ++-- .../components/TemplateGroup}/TemplateGroup.tsx | 5 +---- .../src/next/components/TemplateGroup/index.ts | 17 +++++++++++++++++ .../src/next/components/index.ts | 1 + plugins/scaffolder-react/src/setupTests.ts | 16 ++++++++++++++++ .../TemplateListPage/TemplateGroups.test.tsx | 4 ++-- .../next/TemplateListPage/TemplateGroups.tsx | 3 ++- .../TemplateWizardPage/TemplateWizardPage.tsx | 8 +++----- 8 files changed, 44 insertions(+), 14 deletions(-) rename plugins/{scaffolder/src/next/TemplateListPage => scaffolder-react/src/next/components/TemplateGroup}/TemplateGroup.test.tsx (96%) rename plugins/{scaffolder/src/next/TemplateListPage => scaffolder-react/src/next/components/TemplateGroup}/TemplateGroup.tsx (95%) create mode 100644 plugins/scaffolder-react/src/next/components/TemplateGroup/index.ts create mode 100644 plugins/scaffolder-react/src/setupTests.ts diff --git a/plugins/scaffolder/src/next/TemplateListPage/TemplateGroup.test.tsx b/plugins/scaffolder-react/src/next/components/TemplateGroup/TemplateGroup.test.tsx similarity index 96% rename from plugins/scaffolder/src/next/TemplateListPage/TemplateGroup.test.tsx rename to plugins/scaffolder-react/src/next/components/TemplateGroup/TemplateGroup.test.tsx index 681aea2c6f..63c06e778b 100644 --- a/plugins/scaffolder/src/next/TemplateListPage/TemplateGroup.test.tsx +++ b/plugins/scaffolder-react/src/next/components/TemplateGroup/TemplateGroup.test.tsx @@ -13,12 +13,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -jest.mock('./TemplateCard', () => ({ TemplateCard: jest.fn(() => null) })); +jest.mock('../TemplateCard', () => ({ TemplateCard: jest.fn(() => null) })); import React from 'react'; import { TemplateGroup } from './TemplateGroup'; import { render } from '@testing-library/react'; -import { TemplateCard } from '@backstage/plugin-scaffolder-react'; +import { TemplateCard } from '../TemplateCard'; import { TemplateEntityV1beta3 } from '@backstage/plugin-scaffolder-common'; describe('TemplateGroup', () => { diff --git a/plugins/scaffolder/src/next/TemplateListPage/TemplateGroup.tsx b/plugins/scaffolder-react/src/next/components/TemplateGroup/TemplateGroup.tsx similarity index 95% rename from plugins/scaffolder/src/next/TemplateListPage/TemplateGroup.tsx rename to plugins/scaffolder-react/src/next/components/TemplateGroup/TemplateGroup.tsx index cd7e9bb6c4..b45d0947f4 100644 --- a/plugins/scaffolder/src/next/TemplateListPage/TemplateGroup.tsx +++ b/plugins/scaffolder-react/src/next/components/TemplateGroup/TemplateGroup.tsx @@ -22,11 +22,8 @@ import { Link, } from '@backstage/core-components'; import { Typography } from '@material-ui/core'; -import { - TemplateCard, - TemplateCardProps, -} from '@backstage/plugin-scaffolder-react'; import { stringifyEntityRef } from '@backstage/catalog-model'; +import { TemplateCardProps, TemplateCard } from '../TemplateCard'; export interface TemplateGroupProps { templates: TemplateEntityV1beta3[]; diff --git a/plugins/scaffolder-react/src/next/components/TemplateGroup/index.ts b/plugins/scaffolder-react/src/next/components/TemplateGroup/index.ts new file mode 100644 index 0000000000..1515e12e45 --- /dev/null +++ b/plugins/scaffolder-react/src/next/components/TemplateGroup/index.ts @@ -0,0 +1,17 @@ +/* + * Copyright 2022 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 { TemplateGroup } from './TemplateGroup'; diff --git a/plugins/scaffolder-react/src/next/components/index.ts b/plugins/scaffolder-react/src/next/components/index.ts index 0e3f7ce7fa..c710bd8891 100644 --- a/plugins/scaffolder-react/src/next/components/index.ts +++ b/plugins/scaffolder-react/src/next/components/index.ts @@ -16,3 +16,4 @@ export * from './Stepper'; export * from './TemplateCard'; export * from './ReviewState'; +export * from './TemplateGroup'; diff --git a/plugins/scaffolder-react/src/setupTests.ts b/plugins/scaffolder-react/src/setupTests.ts new file mode 100644 index 0000000000..326d2ed212 --- /dev/null +++ b/plugins/scaffolder-react/src/setupTests.ts @@ -0,0 +1,16 @@ +/* + * Copyright 2022 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 '@testing-library/jest-dom'; diff --git a/plugins/scaffolder/src/next/TemplateListPage/TemplateGroups.test.tsx b/plugins/scaffolder/src/next/TemplateListPage/TemplateGroups.test.tsx index 2d8cdc3150..4abdd79463 100644 --- a/plugins/scaffolder/src/next/TemplateListPage/TemplateGroups.test.tsx +++ b/plugins/scaffolder/src/next/TemplateListPage/TemplateGroups.test.tsx @@ -18,7 +18,7 @@ jest.mock('@backstage/plugin-catalog-react', () => ({ useEntityList: jest.fn(), })); -jest.mock('./TemplateGroup', () => ({ +jest.mock('@backstage/plugin-scaffolder-react', () => ({ TemplateGroup: jest.fn(() => null), })); @@ -28,7 +28,7 @@ import { useEntityList } from '@backstage/plugin-catalog-react'; import { TemplateGroups } from './TemplateGroups'; import { TestApiProvider } from '@backstage/test-utils'; import { errorApiRef } from '@backstage/core-plugin-api'; -import { TemplateGroup } from './TemplateGroup'; +import { TemplateGroup } from '@backstage/plugin-scaffolder-react'; describe('TemplateGroups', () => { it('should return progress if the hook is loading', async () => { diff --git a/plugins/scaffolder/src/next/TemplateListPage/TemplateGroups.tsx b/plugins/scaffolder/src/next/TemplateListPage/TemplateGroups.tsx index f402c0ad19..e502bfd9a7 100644 --- a/plugins/scaffolder/src/next/TemplateListPage/TemplateGroups.tsx +++ b/plugins/scaffolder/src/next/TemplateListPage/TemplateGroups.tsx @@ -14,13 +14,14 @@ * limitations under the License. */ import React from 'react'; -import { TemplateGroup } from './TemplateGroup'; + import { Entity } from '@backstage/catalog-model'; import { useEntityList } from '@backstage/plugin-catalog-react'; import { TemplateEntityV1beta3 } from '@backstage/plugin-scaffolder-common'; import { Progress, Link } from '@backstage/core-components'; import { Typography } from '@material-ui/core'; import { errorApiRef, useApi } from '@backstage/core-plugin-api'; +import { TemplateGroup } from '@backstage/plugin-scaffolder-react'; /** * @alpha diff --git a/plugins/scaffolder/src/next/TemplateWizardPage/TemplateWizardPage.tsx b/plugins/scaffolder/src/next/TemplateWizardPage/TemplateWizardPage.tsx index 2bb8eb5f8b..fed587b0ae 100644 --- a/plugins/scaffolder/src/next/TemplateWizardPage/TemplateWizardPage.tsx +++ b/plugins/scaffolder/src/next/TemplateWizardPage/TemplateWizardPage.tsx @@ -34,19 +34,17 @@ import { import { scaffolderApiRef } from '../../api'; import useAsync from 'react-use/lib/useAsync'; import { makeStyles } from '@material-ui/core'; -import { - Stepper, - NextFieldExtensionOptions, -} from '@backstage/plugin-scaffolder-react'; import { BackstageTheme } from '@backstage/theme'; import { nextRouteRef, scaffolderTaskRouteRef, selectedTemplateRouteRef, + Stepper, + NextFieldExtensionOptions, + type FormProps, } from '@backstage/plugin-scaffolder-react'; import { SecretsContext } from '../../components/secrets/SecretsContext'; import { JsonValue } from '@backstage/types'; -import type { FormProps } from '@backstage/plugin-scaffolder-react'; export type TemplateWizardPageProps = { customFieldExtensions: NextFieldExtensionOptions[]; From ccba7df9acf79f8b547fef5bdccbf329c2faf2e6 Mon Sep 17 00:00:00 2001 From: blam Date: Fri, 23 Dec 2022 11:56:31 +0100 Subject: [PATCH 06/35] chore: fixing the api-report and making things green so far Signed-off-by: blam --- plugins/scaffolder-react/api-report.md | 88 +++++++++++++------ .../scaffolder-react/src/extensions/index.tsx | 9 +- .../components/ReviewState/ReviewState.tsx | 10 ++- .../src/next/components/ReviewState/index.ts | 2 +- .../src/next/components/Stepper/Stepper.tsx | 5 ++ .../src/next/components/Stepper/index.ts | 2 +- .../components/TemplateCard/TemplateCard.tsx | 4 +- .../src/next/components/TemplateCard/index.ts | 3 +- .../TemplateGroup/TemplateGroup.tsx | 8 ++ .../next/components/TemplateGroup/index.ts | 2 +- .../scaffolder-react/src/next/hooks/index.ts | 20 +++++ .../src/next/hooks/useFormData.ts | 4 + .../src/next/hooks/useTemplateSchema.ts | 10 +++ plugins/scaffolder-react/src/next/index.ts | 1 + .../scaffolder-react/src/next/lib/schema.ts | 4 +- plugins/scaffolder-react/src/routes.ts | 8 ++ plugins/scaffolder/src/index.ts | 7 ++ 17 files changed, 146 insertions(+), 41 deletions(-) create mode 100644 plugins/scaffolder-react/src/next/hooks/index.ts diff --git a/plugins/scaffolder-react/api-report.md b/plugins/scaffolder-react/api-report.md index 81259772b5..07d92530cb 100644 --- a/plugins/scaffolder-react/api-report.md +++ b/plugins/scaffolder-react/api-report.md @@ -6,6 +6,7 @@ /// import { ApiHolder } from '@backstage/core-plugin-api'; +import { Dispatch } from 'react'; import { Extension } from '@backstage/core-plugin-api'; import { ExternalRouteRef } from '@backstage/core-plugin-api'; import { FieldProps } from '@rjsf/core'; @@ -20,13 +21,12 @@ import { PathParams } from '@backstage/core-plugin-api'; import { PropsWithChildren } from 'react'; import { default as React_2 } from 'react'; import { RouteRef } from '@backstage/core-plugin-api'; +import { SetStateAction } from 'react'; import { SubRouteRef } from '@backstage/core-plugin-api'; import { TemplateEntityV1beta3 } from '@backstage/plugin-scaffolder-common'; import { UIOptionsType } from '@rjsf/utils'; import { UiSchema } from '@rjsf/utils'; -// Warning: (ae-missing-release-tag) "actionsRouteRef" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) export const actionsRouteRef: SubRouteRef; @@ -64,8 +64,6 @@ export type CustomFieldValidator = ( }, ) => void | Promise; -// Warning: (ae-missing-release-tag) "editRouteRef" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) export const editRouteRef: SubRouteRef; @@ -75,14 +73,10 @@ export const extractSchemaFromStep: (inputStep: JsonObject) => { schema: JsonObject; }; -// Warning: (ae-missing-release-tag) "FIELD_EXTENSION_KEY" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public (undocumented) +// @public export const FIELD_EXTENSION_KEY = 'scaffolder.extensions.field.v1'; -// Warning: (ae-missing-release-tag) "FIELD_EXTENSION_WRAPPER_KEY" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public (undocumented) +// @public export const FIELD_EXTENSION_WRAPPER_KEY = 'scaffolder.extensions.wrapper.v1'; // @public @@ -118,8 +112,6 @@ export type FormProps = Pick< 'transformErrors' | 'noHtml5Validate' >; -// Warning: (ae-missing-release-tag) "legacySelectedTemplateRouteRef" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public @deprecated (undocumented) export const legacySelectedTemplateRouteRef: SubRouteRef< PathParams<'/templates/:templateName'> @@ -162,9 +154,7 @@ export type NextFieldExtensionOptions< // @alpha (undocumented) export const nextRouteRef: RouteRef; -// Warning: (ae-missing-release-tag) "nextScaffolderTaskRouteRef" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// -// @public (undocumented) +// @alpha (undocumented) export const nextScaffolderTaskRouteRef: SubRouteRef< PathParams<'/tasks/:taskId'> >; @@ -174,29 +164,41 @@ export const nextSelectedTemplateRouteRef: SubRouteRef< PathParams<'/templates/:namespace/:templateName'> >; -// Warning: (ae-missing-release-tag) "registerComponentRouteRef" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// +// @alpha +export interface ParsedTemplateSchema { + // (undocumented) + description?: string; + // (undocumented) + mergedSchema: JsonObject; + // (undocumented) + schema: JsonObject; + // (undocumented) + title: string; + // (undocumented) + uiSchema: UiSchema; +} + // @public (undocumented) export const registerComponentRouteRef: ExternalRouteRef; -// Warning: (ae-forgotten-export) The symbol "ReviewStateProps" needs to be exported by the entry point index.d.ts -// // @alpha export const ReviewState: (props: ReviewStateProps) => JSX.Element; +// @alpha +export type ReviewStateProps = { + schemas: ParsedTemplateSchema[]; + formState: JsonObject; +}; + // @public (undocumented) export const rootRouteRef: RouteRef; // @public export const ScaffolderFieldExtensions: React_2.ComponentType; -// Warning: (ae-missing-release-tag) "scaffolderListTaskRouteRef" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) export const scaffolderListTaskRouteRef: SubRouteRef; -// Warning: (ae-missing-release-tag) "scaffolderTaskRouteRef" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// // @public (undocumented) export const scaffolderTaskRouteRef: SubRouteRef>; @@ -205,11 +207,17 @@ export const selectedTemplateRouteRef: SubRouteRef< PathParams<'/templates/:namespace/:templateName'> >; -// Warning: (ae-forgotten-export) The symbol "StepperProps" needs to be exported by the entry point index.d.ts -// -// @alpha (undocumented) +// @alpha export const Stepper: (props: StepperProps) => JSX.Element; +// @alpha +export type StepperProps = { + manifest: TemplateParameterSchema; + extensions: NextFieldExtensionOptions[]; + onComplete: (values: Record) => Promise; + FormProps?: FormProps; +}; + // @alpha export const TemplateCard: (props: TemplateCardProps) => JSX.Element; @@ -221,6 +229,21 @@ export interface TemplateCardProps { template: TemplateEntityV1beta3; } +// @alpha +export const TemplateGroup: (props: TemplateGroupProps) => JSX.Element; + +// @alpha +export interface TemplateGroupProps { + // (undocumented) + components?: { + CardComponent?: React_2.ComponentType; + }; + // (undocumented) + templates: TemplateEntityV1beta3[]; + // (undocumented) + title: React_2.ReactNode; +} + // @public export type TemplateParameterSchema = { title: string; @@ -232,8 +255,17 @@ export type TemplateParameterSchema = { }>; }; -// Warning: (ae-missing-release-tag) "viewTechDocRouteRef" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) -// +// @alpha +export const useFormData: () => [ + Record, + Dispatch>>, +]; + +// @alpha +export const useTemplateSchema: (manifest: TemplateParameterSchema) => { + steps: ParsedTemplateSchema[]; +}; + // @public (undocumented) export const viewTechDocRouteRef: ExternalRouteRef< { diff --git a/plugins/scaffolder-react/src/extensions/index.tsx b/plugins/scaffolder-react/src/extensions/index.tsx index 093c68c172..94bf8bad14 100644 --- a/plugins/scaffolder-react/src/extensions/index.tsx +++ b/plugins/scaffolder-react/src/extensions/index.tsx @@ -23,12 +23,19 @@ import { } from './types'; import { Extension, attachComponentData } from '@backstage/core-plugin-api'; +/** + * The key used to store the field extension data for the `` component + * @public + */ export const FIELD_EXTENSION_WRAPPER_KEY = 'scaffolder.extensions.wrapper.v1'; +/** + * The key used to store the field extension data for any `` component + * @public + */ export const FIELD_EXTENSION_KEY = 'scaffolder.extensions.field.v1'; /** * A type used to wrap up the FieldExtension to embed the ReturnValue and the InputProps - * * @public */ export type FieldExtensionComponent<_TReturnValue, _TInputProps> = () => null; diff --git a/plugins/scaffolder-react/src/next/components/ReviewState/ReviewState.tsx b/plugins/scaffolder-react/src/next/components/ReviewState/ReviewState.tsx index 9b69a898f2..52ad80c4c2 100644 --- a/plugins/scaffolder-react/src/next/components/ReviewState/ReviewState.tsx +++ b/plugins/scaffolder-react/src/next/components/ReviewState/ReviewState.tsx @@ -19,13 +19,17 @@ import { JsonObject } from '@backstage/types'; import { Draft07 as JSONSchema } from 'json-schema-library'; import { ParsedTemplateSchema } from '../../hooks/useTemplateSchema'; -interface ReviewStateProps { +/** + * The props for the {@link ReviewState} component. + * @alpha + */ +export type ReviewStateProps = { schemas: ParsedTemplateSchema[]; formState: JsonObject; -} +}; /** - * The ReviewState component used by the Stepper + * The component used by the {@link Stepper} to render the review step. * @alpha */ export const ReviewState = (props: ReviewStateProps) => { diff --git a/plugins/scaffolder-react/src/next/components/ReviewState/index.ts b/plugins/scaffolder-react/src/next/components/ReviewState/index.ts index c94d73ec35..1bde4685d8 100644 --- a/plugins/scaffolder-react/src/next/components/ReviewState/index.ts +++ b/plugins/scaffolder-react/src/next/components/ReviewState/index.ts @@ -13,4 +13,4 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -export { ReviewState } from './ReviewState'; +export { ReviewState, type ReviewStateProps } from './ReviewState'; diff --git a/plugins/scaffolder-react/src/next/components/Stepper/Stepper.tsx b/plugins/scaffolder-react/src/next/components/Stepper/Stepper.tsx index 79c6e4fc92..8ff4646d1c 100644 --- a/plugins/scaffolder-react/src/next/components/Stepper/Stepper.tsx +++ b/plugins/scaffolder-react/src/next/components/Stepper/Stepper.tsx @@ -54,6 +54,10 @@ const useStyles = makeStyles(theme => ({ }, })); +/** + * The Props for {@link Stepper} component + * @alpha + */ export type StepperProps = { manifest: TemplateParameterSchema; extensions: NextFieldExtensionOptions[]; @@ -67,6 +71,7 @@ export type StepperProps = { const Form = withTheme(require('@rjsf/material-ui-v5').Theme); /** + * The `Stepper` component is the Wizard that is rendered when a user selects a template * @alpha */ export const Stepper = (props: StepperProps) => { diff --git a/plugins/scaffolder-react/src/next/components/Stepper/index.ts b/plugins/scaffolder-react/src/next/components/Stepper/index.ts index 5532563e28..daa47f078e 100644 --- a/plugins/scaffolder-react/src/next/components/Stepper/index.ts +++ b/plugins/scaffolder-react/src/next/components/Stepper/index.ts @@ -13,4 +13,4 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -export { Stepper } from './Stepper'; +export { Stepper, type StepperProps } from './Stepper'; diff --git a/plugins/scaffolder-react/src/next/components/TemplateCard/TemplateCard.tsx b/plugins/scaffolder-react/src/next/components/TemplateCard/TemplateCard.tsx index 67b50ba8d6..b1e94b7b8e 100644 --- a/plugins/scaffolder-react/src/next/components/TemplateCard/TemplateCard.tsx +++ b/plugins/scaffolder-react/src/next/components/TemplateCard/TemplateCard.tsx @@ -83,7 +83,7 @@ const useStyles = makeStyles(theme => ({ })); /** - * The Props for the Template Card component + * The Props for the {@link TemplateCard} component * @alpha */ export interface TemplateCardProps { @@ -92,7 +92,7 @@ export interface TemplateCardProps { } /** - * The Template Card component that is rendered in a list for each template + * The `TemplateCard` component that is rendered in a list for each template * @alpha */ export const TemplateCard = (props: TemplateCardProps) => { diff --git a/plugins/scaffolder-react/src/next/components/TemplateCard/index.ts b/plugins/scaffolder-react/src/next/components/TemplateCard/index.ts index 99af0cbb50..529aa938e4 100644 --- a/plugins/scaffolder-react/src/next/components/TemplateCard/index.ts +++ b/plugins/scaffolder-react/src/next/components/TemplateCard/index.ts @@ -13,5 +13,4 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -export { TemplateCard } from './TemplateCard'; -export type { TemplateCardProps } from './TemplateCard'; +export { TemplateCard, type TemplateCardProps } from './TemplateCard'; diff --git a/plugins/scaffolder-react/src/next/components/TemplateGroup/TemplateGroup.tsx b/plugins/scaffolder-react/src/next/components/TemplateGroup/TemplateGroup.tsx index b45d0947f4..74d9242041 100644 --- a/plugins/scaffolder-react/src/next/components/TemplateGroup/TemplateGroup.tsx +++ b/plugins/scaffolder-react/src/next/components/TemplateGroup/TemplateGroup.tsx @@ -25,6 +25,10 @@ import { Typography } from '@material-ui/core'; import { stringifyEntityRef } from '@backstage/catalog-model'; import { TemplateCardProps, TemplateCard } from '../TemplateCard'; +/** + * The props for the {@link TemplateGroup} component. + * @alpha + */ export interface TemplateGroupProps { templates: TemplateEntityV1beta3[]; title: React.ReactNode; @@ -33,6 +37,10 @@ export interface TemplateGroupProps { }; } +/** + * The `TemplateGroup` component is used to display a group of templates with a title. + * @alpha + */ export const TemplateGroup = (props: TemplateGroupProps) => { const { templates, title, components: { CardComponent } = {} } = props; const titleComponent = diff --git a/plugins/scaffolder-react/src/next/components/TemplateGroup/index.ts b/plugins/scaffolder-react/src/next/components/TemplateGroup/index.ts index 1515e12e45..3fd27c84ed 100644 --- a/plugins/scaffolder-react/src/next/components/TemplateGroup/index.ts +++ b/plugins/scaffolder-react/src/next/components/TemplateGroup/index.ts @@ -14,4 +14,4 @@ * limitations under the License. */ -export { TemplateGroup } from './TemplateGroup'; +export { TemplateGroup, type TemplateGroupProps } from './TemplateGroup'; diff --git a/plugins/scaffolder-react/src/next/hooks/index.ts b/plugins/scaffolder-react/src/next/hooks/index.ts new file mode 100644 index 0000000000..ba79bf0e9a --- /dev/null +++ b/plugins/scaffolder-react/src/next/hooks/index.ts @@ -0,0 +1,20 @@ +/* + * Copyright 2022 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 { useFormData } from './useFormData'; +export { + useTemplateSchema, + type ParsedTemplateSchema, +} from './useTemplateSchema'; diff --git a/plugins/scaffolder-react/src/next/hooks/useFormData.ts b/plugins/scaffolder-react/src/next/hooks/useFormData.ts index 1500216688..0939630d1d 100644 --- a/plugins/scaffolder-react/src/next/hooks/useFormData.ts +++ b/plugins/scaffolder-react/src/next/hooks/useFormData.ts @@ -17,6 +17,10 @@ import qs from 'qs'; import { useState } from 'react'; +/** + * This hook is used to get the formData from the query string. + * @alpha + */ export const useFormData = () => { return useState>(() => { const query = qs.parse(window.location.search, { diff --git a/plugins/scaffolder-react/src/next/hooks/useTemplateSchema.ts b/plugins/scaffolder-react/src/next/hooks/useTemplateSchema.ts index 733c8960b9..2b2e48cf68 100644 --- a/plugins/scaffolder-react/src/next/hooks/useTemplateSchema.ts +++ b/plugins/scaffolder-react/src/next/hooks/useTemplateSchema.ts @@ -19,6 +19,10 @@ import { UiSchema } from '@rjsf/utils'; import { TemplateParameterSchema } from '../../types'; import { extractSchemaFromStep } from '../lib'; +/** + * This is the parsed template schema that is returned from the {@link useTemplateSchema} hook. + * @alpha + */ export interface ParsedTemplateSchema { uiSchema: UiSchema; mergedSchema: JsonObject; @@ -27,6 +31,12 @@ export interface ParsedTemplateSchema { description?: string; } +/** + * This hook will parse the template schema and return the steps with the + * parsed schema and uiSchema. Filtering out any steps or properties that + * are not enabled with feature flags. + * @alpha + */ export const useTemplateSchema = ( manifest: TemplateParameterSchema, ): { steps: ParsedTemplateSchema[] } => { diff --git a/plugins/scaffolder-react/src/next/index.ts b/plugins/scaffolder-react/src/next/index.ts index 29992c26d5..a18649f506 100644 --- a/plugins/scaffolder-react/src/next/index.ts +++ b/plugins/scaffolder-react/src/next/index.ts @@ -17,3 +17,4 @@ export * from './components'; export * from './extensions'; export * from './types'; export * from './lib'; +export * from './hooks'; diff --git a/plugins/scaffolder-react/src/next/lib/schema.ts b/plugins/scaffolder-react/src/next/lib/schema.ts index 4c647bc045..e8b819be4b 100644 --- a/plugins/scaffolder-react/src/next/lib/schema.ts +++ b/plugins/scaffolder-react/src/next/lib/schema.ts @@ -99,8 +99,8 @@ function extractUiSchema(schema: JsonObject, uiSchema: JsonObject) { } /** - * @alpha * Takes a step from a Backstage Template Manifest and converts it to a JSON Schema and UI Schema for rjsf + * @alpha */ export const extractSchemaFromStep = ( inputStep: JsonObject, @@ -112,8 +112,8 @@ export const extractSchemaFromStep = ( }; /** - * @alpha * Creates a field validation object for use in react jsonschema form + * @alpha */ export const createFieldValidation = (): FieldValidation => { const fieldValidation: FieldValidation = { diff --git a/plugins/scaffolder-react/src/routes.ts b/plugins/scaffolder-react/src/routes.ts index 7451a3a943..e8a003cfc1 100644 --- a/plugins/scaffolder-react/src/routes.ts +++ b/plugins/scaffolder-react/src/routes.ts @@ -19,11 +19,13 @@ import { createSubRouteRef, } from '@backstage/core-plugin-api'; +/** @public */ export const registerComponentRouteRef = createExternalRouteRef({ id: 'register-component', optional: true, }); +/** @public */ export const viewTechDocRouteRef = createExternalRouteRef({ id: 'view-techdoc', optional: true, @@ -37,6 +39,7 @@ export const rootRouteRef = createRouteRef({ /** * @deprecated This is the old template route, can be deleted before next major release + * @public */ export const legacySelectedTemplateRouteRef = createSubRouteRef({ id: 'scaffolder/legacy/selected-template', @@ -63,30 +66,35 @@ export const nextSelectedTemplateRouteRef = createSubRouteRef({ path: '/templates/:namespace/:templateName', }); +/** @public */ export const scaffolderTaskRouteRef = createSubRouteRef({ id: 'scaffolder/task', parent: rootRouteRef, path: '/tasks/:taskId', }); +/** @alpha */ export const nextScaffolderTaskRouteRef = createSubRouteRef({ id: 'scaffolder/next/task', parent: nextRouteRef, path: '/tasks/:taskId', }); +/** @public */ export const scaffolderListTaskRouteRef = createSubRouteRef({ id: 'scaffolder/list-tasks', parent: rootRouteRef, path: '/tasks', }); +/** @public */ export const actionsRouteRef = createSubRouteRef({ id: 'scaffolder/actions', parent: rootRouteRef, path: '/actions', }); +/** @public */ export const editRouteRef = createSubRouteRef({ id: 'scaffolder/edit', parent: rootRouteRef, diff --git a/plugins/scaffolder/src/index.ts b/plugins/scaffolder/src/index.ts index 9f993d2a13..28064721c5 100644 --- a/plugins/scaffolder/src/index.ts +++ b/plugins/scaffolder/src/index.ts @@ -87,23 +87,28 @@ import { /** * @alpha + * @deprecated Please import from `@backstage/plugin-scaffolder-react` instead */ const nextRouteRef = nextRouteRefTemp; /** * @alpha + * @deprecated Please import from `@backstage/plugin-scaffolder-react` instead */ const nextSelectedTemplateRouteRef = nextSelectedTemplateRouteRefTemp; /** * @alpha + * @deprecated Please import from `@backstage/plugin-scaffolder-react` instead */ const createNextScaffolderFieldExtension = createNextScaffolderFieldExtensionTemp; /** * @alpha + * @deprecated Please import from `@backstage/plugin-scaffolder-react` instead */ type NextCustomFieldValidator = NextCustomFieldValidatorTemp; /** * @alpha + * @deprecated Please import from `@backstage/plugin-scaffolder-react` instead */ type NextFieldExtensionOptions< TFieldReturnValue = unknown, @@ -111,6 +116,7 @@ type NextFieldExtensionOptions< > = NextFieldExtensionOptionsTemp; /** * @alpha + * @deprecated Please import from `@backstage/plugin-scaffolder-react` instead */ type NextFieldExtensionComponentProps< TFieldReturnValue, @@ -118,6 +124,7 @@ type NextFieldExtensionComponentProps< > = NextFieldExtensionComponentPropsTemp; /** * @alpha + * @deprecated Please import from `@backstage/plugin-scaffolder-react` instead */ type FormProps = FormPropsTemp; From 99819da87354f7f6535215f96c7bd6cc42c3ddc2 Mon Sep 17 00:00:00 2001 From: blam Date: Fri, 23 Dec 2022 12:04:34 +0100 Subject: [PATCH 07/35] chore: updating api-reports Signed-off-by: blam --- .../TemplateCard/TemplateCard.test.tsx | 2 +- .../components/TemplateCard/TemplateCard.tsx | 6 ++-- plugins/scaffolder-react/src/next/index.ts | 1 + plugins/scaffolder-react/src/next/routes.ts | 36 +++++++++++++++++++ plugins/scaffolder-react/src/routes.ts | 19 ---------- 5 files changed, 40 insertions(+), 24 deletions(-) create mode 100644 plugins/scaffolder-react/src/next/routes.ts diff --git a/plugins/scaffolder-react/src/next/components/TemplateCard/TemplateCard.test.tsx b/plugins/scaffolder-react/src/next/components/TemplateCard/TemplateCard.test.tsx index a0fb1ad74e..228d8af4e3 100644 --- a/plugins/scaffolder-react/src/next/components/TemplateCard/TemplateCard.test.tsx +++ b/plugins/scaffolder-react/src/next/components/TemplateCard/TemplateCard.test.tsx @@ -27,7 +27,7 @@ import { TemplateCard } from './TemplateCard'; import React from 'react'; import { TemplateEntityV1beta3 } from '@backstage/plugin-scaffolder-common'; import { RELATION_OWNED_BY } from '@backstage/catalog-model'; -import { nextRouteRef } from '../../../routes'; +import { nextRouteRef } from '../../routes'; describe('TemplateCard', () => { it('should render the card title', async () => { diff --git a/plugins/scaffolder-react/src/next/components/TemplateCard/TemplateCard.tsx b/plugins/scaffolder-react/src/next/components/TemplateCard/TemplateCard.tsx index b1e94b7b8e..1176b01e5d 100644 --- a/plugins/scaffolder-react/src/next/components/TemplateCard/TemplateCard.tsx +++ b/plugins/scaffolder-react/src/next/components/TemplateCard/TemplateCard.tsx @@ -39,10 +39,8 @@ import { } from '@material-ui/core'; import LanguageIcon from '@material-ui/icons/Language'; import React from 'react'; -import { - nextSelectedTemplateRouteRef, - viewTechDocRouteRef, -} from '../../../routes'; +import { nextSelectedTemplateRouteRef } from '../../routes'; +import { viewTechDocRouteRef } from '../../../routes'; import { CardHeader } from './CardHeader'; import { CardLink } from './CardLink'; diff --git a/plugins/scaffolder-react/src/next/index.ts b/plugins/scaffolder-react/src/next/index.ts index a18649f506..fe12e38ad9 100644 --- a/plugins/scaffolder-react/src/next/index.ts +++ b/plugins/scaffolder-react/src/next/index.ts @@ -18,3 +18,4 @@ export * from './extensions'; export * from './types'; export * from './lib'; export * from './hooks'; +export * from './routes'; diff --git a/plugins/scaffolder-react/src/next/routes.ts b/plugins/scaffolder-react/src/next/routes.ts new file mode 100644 index 0000000000..620122ee60 --- /dev/null +++ b/plugins/scaffolder-react/src/next/routes.ts @@ -0,0 +1,36 @@ +/* + * Copyright 2022 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 { createRouteRef, createSubRouteRef } from '@backstage/core-plugin-api'; + +/** @alpha */ +export const nextRouteRef = createRouteRef({ + id: 'scaffolder/next', +}); + +/** @alpha */ +export const nextSelectedTemplateRouteRef = createSubRouteRef({ + id: 'scaffolder/next/selected-template', + parent: nextRouteRef, + path: '/templates/:namespace/:templateName', +}); + +/** @alpha */ +export const nextScaffolderTaskRouteRef = createSubRouteRef({ + id: 'scaffolder/next/task', + parent: nextRouteRef, + path: '/tasks/:taskId', +}); diff --git a/plugins/scaffolder-react/src/routes.ts b/plugins/scaffolder-react/src/routes.ts index e8a003cfc1..93c194360a 100644 --- a/plugins/scaffolder-react/src/routes.ts +++ b/plugins/scaffolder-react/src/routes.ts @@ -47,11 +47,6 @@ export const legacySelectedTemplateRouteRef = createSubRouteRef({ path: '/templates/:templateName', }); -/** @alpha */ -export const nextRouteRef = createRouteRef({ - id: 'scaffolder/next', -}); - /** @public */ export const selectedTemplateRouteRef = createSubRouteRef({ id: 'scaffolder/selected-template', @@ -59,13 +54,6 @@ export const selectedTemplateRouteRef = createSubRouteRef({ path: '/templates/:namespace/:templateName', }); -/** @alpha */ -export const nextSelectedTemplateRouteRef = createSubRouteRef({ - id: 'scaffolder/next/selected-template', - parent: nextRouteRef, - path: '/templates/:namespace/:templateName', -}); - /** @public */ export const scaffolderTaskRouteRef = createSubRouteRef({ id: 'scaffolder/task', @@ -73,13 +61,6 @@ export const scaffolderTaskRouteRef = createSubRouteRef({ path: '/tasks/:taskId', }); -/** @alpha */ -export const nextScaffolderTaskRouteRef = createSubRouteRef({ - id: 'scaffolder/next/task', - parent: nextRouteRef, - path: '/tasks/:taskId', -}); - /** @public */ export const scaffolderListTaskRouteRef = createSubRouteRef({ id: 'scaffolder/list-tasks', From 562175cf783d2e4abb478f3e2a092dea2ad578da Mon Sep 17 00:00:00 2001 From: blam Date: Fri, 23 Dec 2022 12:25:39 +0100 Subject: [PATCH 08/35] chore: moving the secrets handling to the react package Signed-off-by: blam --- plugins/scaffolder-react/api-report.md | 25 +++++++++++++++++++ plugins/scaffolder-react/src/index.ts | 4 ++- .../src}/secrets/SecretsContext.test.tsx | 0 .../src}/secrets/SecretsContext.tsx | 13 +++++++--- .../src}/secrets/index.ts | 9 +++++-- plugins/scaffolder/src/components/Router.tsx | 2 +- .../components/TemplatePage/TemplatePage.tsx | 2 +- .../RepoUrlPicker/RepoUrlPicker.test.tsx | 2 +- .../fields/RepoUrlPicker/RepoUrlPicker.tsx | 2 +- plugins/scaffolder/src/components/index.ts | 1 - plugins/scaffolder/src/next/Router/Router.tsx | 4 +-- .../TemplateWizardPage/TemplateWizardPage.tsx | 2 +- 12 files changed, 51 insertions(+), 15 deletions(-) rename plugins/{scaffolder/src/components => scaffolder-react/src}/secrets/SecretsContext.test.tsx (100%) rename plugins/{scaffolder/src/components => scaffolder-react/src}/secrets/SecretsContext.tsx (88%) rename plugins/{scaffolder/src/components => scaffolder-react/src}/secrets/index.ts (78%) diff --git a/plugins/scaffolder-react/api-report.md b/plugins/scaffolder-react/api-report.md index 07d92530cb..1886ed96ee 100644 --- a/plugins/scaffolder-react/api-report.md +++ b/plugins/scaffolder-react/api-report.md @@ -202,6 +202,28 @@ export const scaffolderListTaskRouteRef: SubRouteRef; // @public (undocumented) export const scaffolderTaskRouteRef: SubRouteRef>; +// @public +export interface ScaffolderUseTemplateSecrets { + // (undocumented) + setSecrets: (input: Record) => void; +} + +// @public +export const SecretsContext: React_2.Context< + SecretsContextContents | undefined +>; + +// @public +export type SecretsContextContents = { + secrets: Record; + setSecrets: React_2.Dispatch>>; +}; + +// @public +export const SecretsContextProvider: ({ + children, +}: PropsWithChildren<{}>) => JSX.Element; + // @public (undocumented) export const selectedTemplateRouteRef: SubRouteRef< PathParams<'/templates/:namespace/:templateName'> @@ -266,6 +288,9 @@ export const useTemplateSchema: (manifest: TemplateParameterSchema) => { steps: ParsedTemplateSchema[]; }; +// @public +export const useTemplateSecrets: () => ScaffolderUseTemplateSecrets; + // @public (undocumented) export const viewTechDocRouteRef: ExternalRouteRef< { diff --git a/plugins/scaffolder-react/src/index.ts b/plugins/scaffolder-react/src/index.ts index cc0e67e969..e6395f151b 100644 --- a/plugins/scaffolder-react/src/index.ts +++ b/plugins/scaffolder-react/src/index.ts @@ -16,5 +16,7 @@ export * from './routes'; export * from './extensions'; -export * from './next'; export * from './types'; +export * from './secrets'; + +export * from './next'; diff --git a/plugins/scaffolder/src/components/secrets/SecretsContext.test.tsx b/plugins/scaffolder-react/src/secrets/SecretsContext.test.tsx similarity index 100% rename from plugins/scaffolder/src/components/secrets/SecretsContext.test.tsx rename to plugins/scaffolder-react/src/secrets/SecretsContext.test.tsx diff --git a/plugins/scaffolder/src/components/secrets/SecretsContext.tsx b/plugins/scaffolder-react/src/secrets/SecretsContext.tsx similarity index 88% rename from plugins/scaffolder/src/components/secrets/SecretsContext.tsx rename to plugins/scaffolder-react/src/secrets/SecretsContext.tsx index b425a72233..15548dfbc4 100644 --- a/plugins/scaffolder/src/components/secrets/SecretsContext.tsx +++ b/plugins/scaffolder-react/src/secrets/SecretsContext.tsx @@ -21,13 +21,18 @@ import React, { PropsWithChildren, } from 'react'; -type SecretsContextContents = { +/** + * The contents of the {@link SecretsContext}. + * @public + */ +export type SecretsContextContents = { secrets: Record; setSecrets: React.Dispatch>>; }; /** - * The actual context object. + * The context to hold the Secrets. + * @public */ export const SecretsContext = createContext( undefined, @@ -35,7 +40,6 @@ export const SecretsContext = createContext( /** * The Context Provider that holds the state for the secrets. - * * @public */ export const SecretsContextProvider = ({ children }: PropsWithChildren<{}>) => { @@ -57,7 +61,8 @@ export interface ScaffolderUseTemplateSecrets { } /** - * Hook to access the secrets context. + * Hook to access the secrets context to be able to set secrets that are + * passed to the Scaffolder backend. * @public */ export const useTemplateSecrets = (): ScaffolderUseTemplateSecrets => { diff --git a/plugins/scaffolder/src/components/secrets/index.ts b/plugins/scaffolder-react/src/secrets/index.ts similarity index 78% rename from plugins/scaffolder/src/components/secrets/index.ts rename to plugins/scaffolder-react/src/secrets/index.ts index c608834803..90aa69158a 100644 --- a/plugins/scaffolder/src/components/secrets/index.ts +++ b/plugins/scaffolder-react/src/secrets/index.ts @@ -13,5 +13,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -export { useTemplateSecrets } from './SecretsContext'; -export type { ScaffolderUseTemplateSecrets } from './SecretsContext'; +export { + useTemplateSecrets, + SecretsContext, + SecretsContextProvider, + type ScaffolderUseTemplateSecrets, + type SecretsContextContents, +} from './SecretsContext'; diff --git a/plugins/scaffolder/src/components/Router.tsx b/plugins/scaffolder/src/components/Router.tsx index 0e865024bd..fefb550aa7 100644 --- a/plugins/scaffolder/src/components/Router.tsx +++ b/plugins/scaffolder/src/components/Router.tsx @@ -22,7 +22,6 @@ import { ScaffolderPage } from './ScaffolderPage'; import { TemplatePage } from './TemplatePage'; import { TaskPage } from './TaskPage'; import { ActionsPage } from './ActionsPage'; -import { SecretsContextProvider } from './secrets/SecretsContext'; import { TemplateEditorPage } from './TemplateEditorPage'; import { DEFAULT_SCAFFOLDER_FIELD_EXTENSIONS } from '../extensions/default'; import { @@ -40,6 +39,7 @@ import { FIELD_EXTENSION_KEY, FIELD_EXTENSION_WRAPPER_KEY, FieldExtensionOptions, + SecretsContextProvider, } from '@backstage/plugin-scaffolder-react'; import { ListTasksPage } from './ListTasksPage'; import { LayoutOptions, LAYOUTS_KEY, LAYOUTS_WRAPPER_KEY } from '../layouts'; diff --git a/plugins/scaffolder/src/components/TemplatePage/TemplatePage.tsx b/plugins/scaffolder/src/components/TemplatePage/TemplatePage.tsx index 5773691438..1c0994db10 100644 --- a/plugins/scaffolder/src/components/TemplatePage/TemplatePage.tsx +++ b/plugins/scaffolder/src/components/TemplatePage/TemplatePage.tsx @@ -20,12 +20,12 @@ import React, { ComponentType, useCallback, useContext, useState } from 'react'; import { Navigate, useNavigate } from 'react-router-dom'; import useAsync from 'react-use/lib/useAsync'; import { scaffolderApiRef } from '../../api'; -import { SecretsContext } from '../secrets/SecretsContext'; import { rootRouteRef, scaffolderTaskRouteRef, selectedTemplateRouteRef, FieldExtensionOptions, + SecretsContext, } from '@backstage/plugin-scaffolder-react'; import { MultistepJsonForm } from '../MultistepJsonForm'; import { createValidator } from './createValidator'; diff --git a/plugins/scaffolder/src/components/fields/RepoUrlPicker/RepoUrlPicker.test.tsx b/plugins/scaffolder/src/components/fields/RepoUrlPicker/RepoUrlPicker.test.tsx index 7fac9f7840..32991f3757 100644 --- a/plugins/scaffolder/src/components/fields/RepoUrlPicker/RepoUrlPicker.test.tsx +++ b/plugins/scaffolder/src/components/fields/RepoUrlPicker/RepoUrlPicker.test.tsx @@ -29,7 +29,7 @@ import { ScaffolderApi } from '../../../types'; import { SecretsContextProvider, SecretsContext, -} from '../../secrets/SecretsContext'; +} from '@backstage/plugin-scaffolder-react'; import { act, fireEvent } from '@testing-library/react'; describe('RepoUrlPicker', () => { diff --git a/plugins/scaffolder/src/components/fields/RepoUrlPicker/RepoUrlPicker.tsx b/plugins/scaffolder/src/components/fields/RepoUrlPicker/RepoUrlPicker.tsx index 79b7f23da6..9cf61a5e40 100644 --- a/plugins/scaffolder/src/components/fields/RepoUrlPicker/RepoUrlPicker.tsx +++ b/plugins/scaffolder/src/components/fields/RepoUrlPicker/RepoUrlPicker.tsx @@ -30,7 +30,7 @@ import { parseRepoPickerUrl, serializeRepoPickerUrl } from './utils'; import { RepoUrlPickerProps } from './schema'; import { RepoUrlPickerState } from './types'; import useDebounce from 'react-use/lib/useDebounce'; -import { useTemplateSecrets } from '../../secrets'; +import { useTemplateSecrets } from '@backstage/plugin-scaffolder-react'; export { RepoUrlPickerSchema } from './schema'; diff --git a/plugins/scaffolder/src/components/index.ts b/plugins/scaffolder/src/components/index.ts index 23f49ea748..54d3a33d99 100644 --- a/plugins/scaffolder/src/components/index.ts +++ b/plugins/scaffolder/src/components/index.ts @@ -16,7 +16,6 @@ export * from './fields'; export type { RepoUrlPickerUiOptions } from './fields'; export { TemplateTypePicker } from './TemplateTypePicker'; -export * from './secrets'; export { TaskPage } from './TaskPage'; export type { RouterProps } from './Router'; export type { ReviewStepProps } from './types'; diff --git a/plugins/scaffolder/src/next/Router/Router.tsx b/plugins/scaffolder/src/next/Router/Router.tsx index ea620a7820..1c8e7ada6e 100644 --- a/plugins/scaffolder/src/next/Router/Router.tsx +++ b/plugins/scaffolder/src/next/Router/Router.tsx @@ -22,14 +22,14 @@ import { FIELD_EXTENSION_KEY, NextFieldExtensionOptions, FieldExtensionOptions, + nextSelectedTemplateRouteRef, + SecretsContextProvider, type FormProps, } from '@backstage/plugin-scaffolder-react'; import { useElementFilter } from '@backstage/core-plugin-api'; import { TemplateEntityV1beta3 } from '@backstage/plugin-scaffolder-common'; import { TemplateGroupFilter } from '../TemplateListPage/TemplateGroups'; -import { nextSelectedTemplateRouteRef } from '@backstage/plugin-scaffolder-react'; -import { SecretsContextProvider } from '../../components/secrets/SecretsContext'; import { DEFAULT_SCAFFOLDER_FIELD_EXTENSIONS } from '../../extensions/default'; /** diff --git a/plugins/scaffolder/src/next/TemplateWizardPage/TemplateWizardPage.tsx b/plugins/scaffolder/src/next/TemplateWizardPage/TemplateWizardPage.tsx index fed587b0ae..9ee5e89cab 100644 --- a/plugins/scaffolder/src/next/TemplateWizardPage/TemplateWizardPage.tsx +++ b/plugins/scaffolder/src/next/TemplateWizardPage/TemplateWizardPage.tsx @@ -41,9 +41,9 @@ import { selectedTemplateRouteRef, Stepper, NextFieldExtensionOptions, + SecretsContext, type FormProps, } from '@backstage/plugin-scaffolder-react'; -import { SecretsContext } from '../../components/secrets/SecretsContext'; import { JsonValue } from '@backstage/types'; export type TemplateWizardPageProps = { From 016b2238b267c964bed66fb69dad435fbe276940 Mon Sep 17 00:00:00 2001 From: blam Date: Fri, 23 Dec 2022 14:41:28 +0100 Subject: [PATCH 09/35] chore: revert exporting the next stuff for now as it's not gonna work with the repo setup Signed-off-by: blam Signed-off-by: blam --- packages/app/package.json | 1 + .../scaffolder/customScaffolderExtensions.tsx | 10 +-- plugins/scaffolder/src/index.ts | 68 +------------------ 3 files changed, 8 insertions(+), 71 deletions(-) diff --git a/packages/app/package.json b/packages/app/package.json index 553754a15d..86e0402d7d 100644 --- a/packages/app/package.json +++ b/packages/app/package.json @@ -49,6 +49,7 @@ "@backstage/plugin-playlist": "workspace:^", "@backstage/plugin-rollbar": "workspace:^", "@backstage/plugin-scaffolder": "workspace:^", + "@backstage/plugin-scaffolder-react": "workspace:^", "@backstage/plugin-search": "workspace:^", "@backstage/plugin-search-common": "workspace:^", "@backstage/plugin-search-react": "workspace:^", diff --git a/packages/app/src/components/scaffolder/customScaffolderExtensions.tsx b/packages/app/src/components/scaffolder/customScaffolderExtensions.tsx index 3265d347a2..c521bcf86c 100644 --- a/packages/app/src/components/scaffolder/customScaffolderExtensions.tsx +++ b/packages/app/src/components/scaffolder/customScaffolderExtensions.tsx @@ -15,15 +15,15 @@ */ import React from 'react'; import type { FieldValidation } from '@rjsf/utils'; +import { scaffolderPlugin } from '@backstage/plugin-scaffolder'; +import { TextField } from '@material-ui/core'; + import { + NextFieldExtensionComponentProps, createNextScaffolderFieldExtension, createScaffolderFieldExtension, FieldExtensionComponentProps, - NextFieldExtensionComponentProps, - scaffolderPlugin, -} from '@backstage/plugin-scaffolder'; - -import { TextField } from '@material-ui/core'; +} from '@backstage/plugin-scaffolder-react'; const TextValuePicker = (props: FieldExtensionComponentProps) => { const { diff --git a/plugins/scaffolder/src/index.ts b/plugins/scaffolder/src/index.ts index 28064721c5..a23324646f 100644 --- a/plugins/scaffolder/src/index.ts +++ b/plugins/scaffolder/src/index.ts @@ -57,6 +57,8 @@ export { ScaffolderFieldExtensions, rootRouteRef, selectedTemplateRouteRef, + useTemplateSecrets, + type ScaffolderUseTemplateSecrets, type TemplateParameterSchema, type CustomFieldExtensionSchema, type CustomFieldValidator, @@ -71,69 +73,3 @@ export type { TaskPageProps } from './components/TaskPage'; export { NextScaffolderPage } from './plugin'; export type { NextRouterProps } from './next'; export type { TemplateGroupFilter } from './next'; - -// These types in the future can be removed from being exported out of this package and be imported -// instead from @backstage/plugin-scaffolder-react. They have to be redeclared here to keep the alpha -// annotation in order to not polluted the main export surface. -import { - nextRouteRef as nextRouteRefTemp, - nextSelectedTemplateRouteRef as nextSelectedTemplateRouteRefTemp, - createNextScaffolderFieldExtension as createNextScaffolderFieldExtensionTemp, - type NextCustomFieldValidator as NextCustomFieldValidatorTemp, - type NextFieldExtensionOptions as NextFieldExtensionOptionsTemp, - type NextFieldExtensionComponentProps as NextFieldExtensionComponentPropsTemp, - type FormProps as FormPropsTemp, -} from '@backstage/plugin-scaffolder-react'; - -/** - * @alpha - * @deprecated Please import from `@backstage/plugin-scaffolder-react` instead - */ -const nextRouteRef = nextRouteRefTemp; -/** - * @alpha - * @deprecated Please import from `@backstage/plugin-scaffolder-react` instead - */ -const nextSelectedTemplateRouteRef = nextSelectedTemplateRouteRefTemp; -/** - * @alpha - * @deprecated Please import from `@backstage/plugin-scaffolder-react` instead - */ -const createNextScaffolderFieldExtension = - createNextScaffolderFieldExtensionTemp; -/** - * @alpha - * @deprecated Please import from `@backstage/plugin-scaffolder-react` instead - */ -type NextCustomFieldValidator = NextCustomFieldValidatorTemp; -/** - * @alpha - * @deprecated Please import from `@backstage/plugin-scaffolder-react` instead - */ -type NextFieldExtensionOptions< - TFieldReturnValue = unknown, - TInputProps = unknown, -> = NextFieldExtensionOptionsTemp; -/** - * @alpha - * @deprecated Please import from `@backstage/plugin-scaffolder-react` instead - */ -type NextFieldExtensionComponentProps< - TFieldReturnValue, - TUiOptions = {}, -> = NextFieldExtensionComponentPropsTemp; -/** - * @alpha - * @deprecated Please import from `@backstage/plugin-scaffolder-react` instead - */ -type FormProps = FormPropsTemp; - -export { - nextRouteRef, - nextSelectedTemplateRouteRef, - createNextScaffolderFieldExtension, - type NextCustomFieldValidator, - type NextFieldExtensionOptions, - type NextFieldExtensionComponentProps, - type FormProps, -}; From becf03a94ba59b8722a3b31448fd960b357a6d57 Mon Sep 17 00:00:00 2001 From: blam Date: Fri, 30 Dec 2022 12:17:25 +0100 Subject: [PATCH 10/35] chore: moving the `scaffolderApiRef` and types to `-react` Signed-off-by: blam --- plugins/scaffolder-react/src/api/index.ts | 17 +++++++++ plugins/scaffolder-react/src/api/ref.ts | 22 +++++++++++ .../src => scaffolder-react/src/api}/types.ts | 3 +- plugins/scaffolder-react/src/index.ts | 1 + plugins/scaffolder/src/api.ts | 14 +------ .../ActionsPage/ActionsPage.test.tsx | 8 ++-- .../components/ActionsPage/ActionsPage.tsx | 2 +- .../ListTasksPage/ListTaskPage.test.tsx | 8 ++-- .../ListTasksPage/ListTasksPage.tsx | 8 ++-- .../columns/TemplateTitleColumn.test.tsx | 6 ++- .../columns/TemplateTitleColumn.tsx | 2 +- .../src/components/TaskPage/TaskPage.tsx | 3 +- .../src/components/TaskPage/TaskPageLinks.tsx | 2 +- .../TemplateEditorPage/DryRunContext.tsx | 6 ++- .../DryRunResults/DryRunResults.test.tsx | 2 +- .../DryRunResults/DryRunResultsList.test.tsx | 2 +- .../DryRunResults/DryRunResultsView.test.tsx | 2 +- .../TemplatePage/TemplatePage.test.tsx | 8 ++-- .../components/TemplatePage/TemplatePage.tsx | 2 +- .../RepoUrlPicker/RepoUrlPicker.test.tsx | 4 +- .../RepoUrlPicker/RepoUrlPickerHost.test.tsx | 2 +- .../RepoUrlPicker/RepoUrlPickerHost.tsx | 2 +- .../src/components/hooks/useEventStream.ts | 4 +- plugins/scaffolder/src/index.ts | 37 ++++++++++--------- .../TemplateWizardPage.test.tsx | 9 +++-- .../TemplateWizardPage/TemplateWizardPage.tsx | 2 +- plugins/scaffolder/src/plugin.tsx | 3 +- yarn.lock | 1 + 28 files changed, 116 insertions(+), 66 deletions(-) create mode 100644 plugins/scaffolder-react/src/api/index.ts create mode 100644 plugins/scaffolder-react/src/api/ref.ts rename plugins/{scaffolder/src => scaffolder-react/src/api}/types.ts (98%) diff --git a/plugins/scaffolder-react/src/api/index.ts b/plugins/scaffolder-react/src/api/index.ts new file mode 100644 index 0000000000..fa8d758afb --- /dev/null +++ b/plugins/scaffolder-react/src/api/index.ts @@ -0,0 +1,17 @@ +/* + * Copyright 2022 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 * from './ref'; +export * from './types'; diff --git a/plugins/scaffolder-react/src/api/ref.ts b/plugins/scaffolder-react/src/api/ref.ts new file mode 100644 index 0000000000..bf0a5faddf --- /dev/null +++ b/plugins/scaffolder-react/src/api/ref.ts @@ -0,0 +1,22 @@ +/* + * Copyright 2022 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 { createApiRef } from '@backstage/core-plugin-api'; +import { ScaffolderApi } from './types'; + +export const scaffolderApiRef = createApiRef({ + id: 'plugin.scaffolder.service', +}); diff --git a/plugins/scaffolder/src/types.ts b/plugins/scaffolder-react/src/api/types.ts similarity index 98% rename from plugins/scaffolder/src/types.ts rename to plugins/scaffolder-react/src/api/types.ts index 0bde515bda..554dc08ef5 100644 --- a/plugins/scaffolder/src/types.ts +++ b/plugins/scaffolder-react/src/api/types.ts @@ -14,9 +14,9 @@ * limitations under the License. */ import { TaskSpec, TaskStep } from '@backstage/plugin-scaffolder-common'; -import { TemplateParameterSchema } from '@backstage/plugin-scaffolder-react'; import { JsonObject, JsonValue, Observable } from '@backstage/types'; import { JSONSchema7 } from 'json-schema'; +import { TemplateParameterSchema } from '../types'; /** * The status of each task in a Scaffolder Job @@ -156,7 +156,6 @@ export interface ScaffolderDryRunResponse { steps: TaskStep[]; output: ScaffolderTaskOutput; } - /** * An API to interact with the scaffolder backend. * diff --git a/plugins/scaffolder-react/src/index.ts b/plugins/scaffolder-react/src/index.ts index e6395f151b..14bcb1e44f 100644 --- a/plugins/scaffolder-react/src/index.ts +++ b/plugins/scaffolder-react/src/index.ts @@ -18,5 +18,6 @@ export * from './routes'; export * from './extensions'; export * from './types'; export * from './secrets'; +export * from './api'; export * from './next'; diff --git a/plugins/scaffolder/src/api.ts b/plugins/scaffolder/src/api.ts index 3a60f6b9a9..515496a363 100644 --- a/plugins/scaffolder/src/api.ts +++ b/plugins/scaffolder/src/api.ts @@ -16,7 +16,6 @@ import { parseEntityRef } from '@backstage/catalog-model'; import { - createApiRef, DiscoveryApi, FetchApi, IdentityApi, @@ -38,20 +37,11 @@ import { ScaffolderTask, ScaffolderDryRunOptions, ScaffolderDryRunResponse, -} from './types'; + TemplateParameterSchema, +} from '@backstage/plugin-scaffolder-react'; -import { TemplateParameterSchema } from '@backstage/plugin-scaffolder-react'; import queryString from 'qs'; -/** - * Utility API reference for the {@link ScaffolderApi}. - * - * @public - */ -export const scaffolderApiRef = createApiRef({ - id: 'plugin.scaffolder.service', -}); - /** * An API to interact with the scaffolder backend. * diff --git a/plugins/scaffolder/src/components/ActionsPage/ActionsPage.test.tsx b/plugins/scaffolder/src/components/ActionsPage/ActionsPage.test.tsx index ee94c5ecd3..a049959ae4 100644 --- a/plugins/scaffolder/src/components/ActionsPage/ActionsPage.test.tsx +++ b/plugins/scaffolder/src/components/ActionsPage/ActionsPage.test.tsx @@ -14,12 +14,14 @@ * limitations under the License. */ import React from 'react'; -import { scaffolderApiRef } from '../../api'; import { ActionsPage } from './ActionsPage'; -import { rootRouteRef } from '@backstage/plugin-scaffolder-react'; +import { + rootRouteRef, + scaffolderApiRef, + ScaffolderApi, +} from '@backstage/plugin-scaffolder-react'; import { renderInTestApp, TestApiRegistry } from '@backstage/test-utils'; import { ApiProvider } from '@backstage/core-app-api'; -import { ScaffolderApi } from '../../types'; const scaffolderApiMock: jest.Mocked = { scaffold: jest.fn(), diff --git a/plugins/scaffolder/src/components/ActionsPage/ActionsPage.tsx b/plugins/scaffolder/src/components/ActionsPage/ActionsPage.tsx index 1fca434a96..50ec86f2f5 100644 --- a/plugins/scaffolder/src/components/ActionsPage/ActionsPage.tsx +++ b/plugins/scaffolder/src/components/ActionsPage/ActionsPage.tsx @@ -15,7 +15,7 @@ */ import React from 'react'; import useAsync from 'react-use/lib/useAsync'; -import { scaffolderApiRef } from '../../api'; +import { scaffolderApiRef } from '@backstage/plugin-scaffolder-react'; import { Typography, Paper, diff --git a/plugins/scaffolder/src/components/ListTasksPage/ListTaskPage.test.tsx b/plugins/scaffolder/src/components/ListTasksPage/ListTaskPage.test.tsx index 7188aed082..4843d9bcc0 100644 --- a/plugins/scaffolder/src/components/ListTasksPage/ListTaskPage.test.tsx +++ b/plugins/scaffolder/src/components/ListTasksPage/ListTaskPage.test.tsx @@ -24,9 +24,11 @@ import { import React from 'react'; import { identityApiRef } from '@backstage/core-plugin-api'; import { ListTasksPage } from './ListTasksPage'; -import { ScaffolderApi } from '../../types'; -import { scaffolderApiRef } from '../../api'; -import { rootRouteRef } from '@backstage/plugin-scaffolder-react'; +import { + rootRouteRef, + scaffolderApiRef, + ScaffolderApi, +} from '@backstage/plugin-scaffolder-react'; import { act, fireEvent } from '@testing-library/react'; describe('', () => { diff --git a/plugins/scaffolder/src/components/ListTasksPage/ListTasksPage.tsx b/plugins/scaffolder/src/components/ListTasksPage/ListTasksPage.tsx index 0685b42a59..68dcedc99f 100644 --- a/plugins/scaffolder/src/components/ListTasksPage/ListTasksPage.tsx +++ b/plugins/scaffolder/src/components/ListTasksPage/ListTasksPage.tsx @@ -28,9 +28,11 @@ import { useApi, useRouteRef } from '@backstage/core-plugin-api'; import { CatalogFilterLayout } from '@backstage/plugin-catalog-react'; import useAsync from 'react-use/lib/useAsync'; import React, { useState } from 'react'; -import { scaffolderApiRef } from '../../api'; -import { rootRouteRef } from '@backstage/plugin-scaffolder-react'; -import { ScaffolderTask } from '../../types'; +import { + rootRouteRef, + ScaffolderTask, + scaffolderApiRef, +} from '@backstage/plugin-scaffolder-react'; import { OwnerListPicker } from './OwnerListPicker'; import { CreatedAtColumn, diff --git a/plugins/scaffolder/src/components/ListTasksPage/columns/TemplateTitleColumn.test.tsx b/plugins/scaffolder/src/components/ListTasksPage/columns/TemplateTitleColumn.test.tsx index 3dc20312aa..bf06c09436 100644 --- a/plugins/scaffolder/src/components/ListTasksPage/columns/TemplateTitleColumn.test.tsx +++ b/plugins/scaffolder/src/components/ListTasksPage/columns/TemplateTitleColumn.test.tsx @@ -18,9 +18,11 @@ import { renderInTestApp, TestApiProvider } from '@backstage/test-utils'; import React from 'react'; import { TemplateTitleColumn } from './TemplateTitleColumn'; -import { scaffolderApiRef } from '../../../api'; -import { ScaffolderApi } from '../../../types'; import { entityRouteRef } from '@backstage/plugin-catalog-react'; +import { + scaffolderApiRef, + ScaffolderApi, +} from '@backstage/plugin-scaffolder-react'; describe('', () => { const scaffolderApiMock: jest.Mocked = { diff --git a/plugins/scaffolder/src/components/ListTasksPage/columns/TemplateTitleColumn.tsx b/plugins/scaffolder/src/components/ListTasksPage/columns/TemplateTitleColumn.tsx index 0561b40392..cbac929a33 100644 --- a/plugins/scaffolder/src/components/ListTasksPage/columns/TemplateTitleColumn.tsx +++ b/plugins/scaffolder/src/components/ListTasksPage/columns/TemplateTitleColumn.tsx @@ -15,7 +15,7 @@ */ import { useApi } from '@backstage/core-plugin-api'; import React from 'react'; -import { scaffolderApiRef } from '../../../api'; +import { scaffolderApiRef } from '@backstage/plugin-scaffolder-react'; import useAsync from 'react-use/lib/useAsync'; import { parseEntityRef } from '@backstage/catalog-model'; import { EntityRefLink } from '@backstage/plugin-catalog-react'; diff --git a/plugins/scaffolder/src/components/TaskPage/TaskPage.tsx b/plugins/scaffolder/src/components/TaskPage/TaskPage.tsx index 42f6e6fd30..02f27bd0c0 100644 --- a/plugins/scaffolder/src/components/TaskPage/TaskPage.tsx +++ b/plugins/scaffolder/src/components/TaskPage/TaskPage.tsx @@ -51,8 +51,9 @@ import { rootRouteRef, scaffolderTaskRouteRef, selectedTemplateRouteRef, + ScaffolderTaskStatus, + ScaffolderTaskOutput, } from '@backstage/plugin-scaffolder-react'; -import { ScaffolderTaskStatus, ScaffolderTaskOutput } from '../../types'; import { useTaskEventStream } from '../hooks/useEventStream'; import { TaskErrors } from './TaskErrors'; import { TaskPageLinks } from './TaskPageLinks'; diff --git a/plugins/scaffolder/src/components/TaskPage/TaskPageLinks.tsx b/plugins/scaffolder/src/components/TaskPage/TaskPageLinks.tsx index 78d6a452ea..59c1515b79 100644 --- a/plugins/scaffolder/src/components/TaskPage/TaskPageLinks.tsx +++ b/plugins/scaffolder/src/components/TaskPage/TaskPageLinks.tsx @@ -19,7 +19,7 @@ import { entityRouteRef } from '@backstage/plugin-catalog-react'; import { Box } from '@material-ui/core'; import LanguageIcon from '@material-ui/icons/Language'; import React from 'react'; -import { ScaffolderTaskOutput } from '../../types'; +import { ScaffolderTaskOutput } from '@backstage/plugin-scaffolder-react'; import { IconLink } from './IconLink'; import { IconComponent, useApp, useRouteRef } from '@backstage/core-plugin-api'; diff --git a/plugins/scaffolder/src/components/TemplateEditorPage/DryRunContext.tsx b/plugins/scaffolder/src/components/TemplateEditorPage/DryRunContext.tsx index 3534b62c39..a617eebe1e 100644 --- a/plugins/scaffolder/src/components/TemplateEditorPage/DryRunContext.tsx +++ b/plugins/scaffolder/src/components/TemplateEditorPage/DryRunContext.tsx @@ -26,8 +26,10 @@ import React, { useRef, useState, } from 'react'; -import { scaffolderApiRef } from '../../api'; -import { ScaffolderDryRunResponse } from '../../types'; +import { + scaffolderApiRef, + ScaffolderDryRunResponse, +} from '@backstage/plugin-scaffolder-react'; const MAX_CONTENT_SIZE = 64 * 1024; const CHUNK_SIZE = 32 * 1024; diff --git a/plugins/scaffolder/src/components/TemplateEditorPage/DryRunResults/DryRunResults.test.tsx b/plugins/scaffolder/src/components/TemplateEditorPage/DryRunResults/DryRunResults.test.tsx index bc3354cc46..0267093ee6 100644 --- a/plugins/scaffolder/src/components/TemplateEditorPage/DryRunResults/DryRunResults.test.tsx +++ b/plugins/scaffolder/src/components/TemplateEditorPage/DryRunResults/DryRunResults.test.tsx @@ -18,7 +18,7 @@ import { renderInTestApp, TestApiProvider } from '@backstage/test-utils'; import { act, screen, waitFor } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import React, { useEffect } from 'react'; -import { scaffolderApiRef } from '../../../api'; +import { scaffolderApiRef } from '@backstage/plugin-scaffolder-react'; import { DryRunProvider, useDryRun } from '../DryRunContext'; import { DryRunResults } from './DryRunResults'; diff --git a/plugins/scaffolder/src/components/TemplateEditorPage/DryRunResults/DryRunResultsList.test.tsx b/plugins/scaffolder/src/components/TemplateEditorPage/DryRunResults/DryRunResultsList.test.tsx index 417c23c483..706f284db1 100644 --- a/plugins/scaffolder/src/components/TemplateEditorPage/DryRunResults/DryRunResultsList.test.tsx +++ b/plugins/scaffolder/src/components/TemplateEditorPage/DryRunResults/DryRunResultsList.test.tsx @@ -18,7 +18,7 @@ import { renderInTestApp, TestApiProvider } from '@backstage/test-utils'; import { act, screen } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import React, { useEffect } from 'react'; -import { scaffolderApiRef } from '../../../api'; +import { scaffolderApiRef } from '@backstage/plugin-scaffolder-react'; import { DryRunProvider, useDryRun } from '../DryRunContext'; import { DryRunResultsList } from './DryRunResultsList'; diff --git a/plugins/scaffolder/src/components/TemplateEditorPage/DryRunResults/DryRunResultsView.test.tsx b/plugins/scaffolder/src/components/TemplateEditorPage/DryRunResults/DryRunResultsView.test.tsx index c709adfd68..c2d8d3a2a4 100644 --- a/plugins/scaffolder/src/components/TemplateEditorPage/DryRunResults/DryRunResultsView.test.tsx +++ b/plugins/scaffolder/src/components/TemplateEditorPage/DryRunResults/DryRunResultsView.test.tsx @@ -19,7 +19,7 @@ import { renderInTestApp, TestApiProvider } from '@backstage/test-utils'; import { screen } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import React, { ReactNode, useEffect } from 'react'; -import { scaffolderApiRef } from '../../../api'; +import { scaffolderApiRef } from '@backstage/plugin-scaffolder-react'; import { DryRunProvider, useDryRun } from '../DryRunContext'; import { DryRunResultsView } from './DryRunResultsView'; diff --git a/plugins/scaffolder/src/components/TemplatePage/TemplatePage.test.tsx b/plugins/scaffolder/src/components/TemplatePage/TemplatePage.test.tsx index 7b54d047e7..5de29c42a5 100644 --- a/plugins/scaffolder/src/components/TemplatePage/TemplatePage.test.tsx +++ b/plugins/scaffolder/src/components/TemplatePage/TemplatePage.test.tsx @@ -22,9 +22,11 @@ import { import { act, fireEvent, screen, within } from '@testing-library/react'; import React from 'react'; import { Route, Routes } from 'react-router-dom'; -import { scaffolderApiRef } from '../../api'; -import { ScaffolderApi } from '../../types'; -import { rootRouteRef } from '@backstage/plugin-scaffolder-react'; +import { + rootRouteRef, + scaffolderApiRef, + ScaffolderApi, +} from '@backstage/plugin-scaffolder-react'; import { TemplatePage } from './TemplatePage'; import { featureFlagsApiRef, diff --git a/plugins/scaffolder/src/components/TemplatePage/TemplatePage.tsx b/plugins/scaffolder/src/components/TemplatePage/TemplatePage.tsx index 1c0994db10..08254491ce 100644 --- a/plugins/scaffolder/src/components/TemplatePage/TemplatePage.tsx +++ b/plugins/scaffolder/src/components/TemplatePage/TemplatePage.tsx @@ -19,13 +19,13 @@ import qs from 'qs'; import React, { ComponentType, useCallback, useContext, useState } from 'react'; import { Navigate, useNavigate } from 'react-router-dom'; import useAsync from 'react-use/lib/useAsync'; -import { scaffolderApiRef } from '../../api'; import { rootRouteRef, scaffolderTaskRouteRef, selectedTemplateRouteRef, FieldExtensionOptions, SecretsContext, + scaffolderApiRef, } from '@backstage/plugin-scaffolder-react'; import { MultistepJsonForm } from '../MultistepJsonForm'; import { createValidator } from './createValidator'; diff --git a/plugins/scaffolder/src/components/fields/RepoUrlPicker/RepoUrlPicker.test.tsx b/plugins/scaffolder/src/components/fields/RepoUrlPicker/RepoUrlPicker.test.tsx index 32991f3757..1cf8d91059 100644 --- a/plugins/scaffolder/src/components/fields/RepoUrlPicker/RepoUrlPicker.test.tsx +++ b/plugins/scaffolder/src/components/fields/RepoUrlPicker/RepoUrlPicker.test.tsx @@ -23,12 +23,12 @@ import { scmAuthApiRef, ScmAuthApi, } from '@backstage/integration-react'; -import { scaffolderApiRef } from '../../../api'; -import { ScaffolderApi } from '../../../types'; import { SecretsContextProvider, SecretsContext, + scaffolderApiRef, + ScaffolderApi, } from '@backstage/plugin-scaffolder-react'; import { act, fireEvent } from '@testing-library/react'; diff --git a/plugins/scaffolder/src/components/fields/RepoUrlPicker/RepoUrlPickerHost.test.tsx b/plugins/scaffolder/src/components/fields/RepoUrlPicker/RepoUrlPickerHost.test.tsx index bd71fb160f..0c7ca75990 100644 --- a/plugins/scaffolder/src/components/fields/RepoUrlPicker/RepoUrlPickerHost.test.tsx +++ b/plugins/scaffolder/src/components/fields/RepoUrlPicker/RepoUrlPickerHost.test.tsx @@ -16,7 +16,7 @@ import React from 'react'; import { RepoUrlPickerHost } from './RepoUrlPickerHost'; import { renderInTestApp, TestApiProvider } from '@backstage/test-utils'; -import { scaffolderApiRef } from '../../../api'; +import { scaffolderApiRef } from '@backstage/plugin-scaffolder-react'; import { fireEvent, within } from '@testing-library/react'; describe('RepoUrlPickerHostField', () => { diff --git a/plugins/scaffolder/src/components/fields/RepoUrlPicker/RepoUrlPickerHost.tsx b/plugins/scaffolder/src/components/fields/RepoUrlPicker/RepoUrlPickerHost.tsx index b9762cd69d..5a78cf6195 100644 --- a/plugins/scaffolder/src/components/fields/RepoUrlPicker/RepoUrlPickerHost.tsx +++ b/plugins/scaffolder/src/components/fields/RepoUrlPicker/RepoUrlPickerHost.tsx @@ -18,7 +18,7 @@ import { Progress, Select, SelectItem } from '@backstage/core-components'; import FormControl from '@material-ui/core/FormControl'; import FormHelperText from '@material-ui/core/FormHelperText'; import { useApi } from '@backstage/core-plugin-api'; -import { scaffolderApiRef } from '../../../api'; +import { scaffolderApiRef } from '@backstage/plugin-scaffolder-react'; import useAsync from 'react-use/lib/useAsync'; export const RepoUrlPickerHost = (props: { diff --git a/plugins/scaffolder/src/components/hooks/useEventStream.ts b/plugins/scaffolder/src/components/hooks/useEventStream.ts index bb24c0d612..0b36c85ad8 100644 --- a/plugins/scaffolder/src/components/hooks/useEventStream.ts +++ b/plugins/scaffolder/src/components/hooks/useEventStream.ts @@ -15,13 +15,13 @@ */ import { useImmerReducer } from 'use-immer'; import { useEffect } from 'react'; -import { scaffolderApiRef } from '../../api'; import { ScaffolderTask, ScaffolderTaskStatus, ScaffolderTaskOutput, LogEvent, -} from '../../types'; + scaffolderApiRef, +} from '@backstage/plugin-scaffolder-react'; import { useApi } from '@backstage/core-plugin-api'; import { Subscription } from '@backstage/types'; diff --git a/plugins/scaffolder/src/index.ts b/plugins/scaffolder/src/index.ts index a23324646f..85de61b667 100644 --- a/plugins/scaffolder/src/index.ts +++ b/plugins/scaffolder/src/index.ts @@ -20,23 +20,7 @@ * @packageDocumentation */ -export { scaffolderApiRef, ScaffolderClient } from './api'; -export type { - ListActionsResponse, - LogEvent, - ScaffolderApi, - ScaffolderDryRunOptions, - ScaffolderDryRunResponse, - ScaffolderGetIntegrationsListOptions, - ScaffolderGetIntegrationsListResponse, - ScaffolderOutputLink, - ScaffolderScaffoldOptions, - ScaffolderScaffoldResponse, - ScaffolderStreamLogsOptions, - ScaffolderTask, - ScaffolderTaskOutput, - ScaffolderTaskStatus, -} from './types'; +export { ScaffolderClient } from './api'; export { createScaffolderLayout, ScaffolderLayouts } from './layouts'; export type { LayoutOptions, LayoutTemplate, LayoutComponent } from './layouts'; @@ -52,19 +36,38 @@ export { } from './plugin'; export * from './components'; +/** @deprecated - use imports from @backstage/plugin-scaffolder-react instead */ export { createScaffolderFieldExtension, ScaffolderFieldExtensions, rootRouteRef, selectedTemplateRouteRef, useTemplateSecrets, + scaffolderApiRef, + /** @deprecated - use imports from @backstage/plugin-scaffolder-react instead */ + type ScaffolderApi, + /** @deprecated */ type ScaffolderUseTemplateSecrets, + /** @deprecated */ type TemplateParameterSchema, type CustomFieldExtensionSchema, type CustomFieldValidator, type FieldExtensionOptions, type FieldExtensionComponentProps, type FieldExtensionComponent, + type ListActionsResponse, + type LogEvent, + type ScaffolderDryRunOptions, + type ScaffolderDryRunResponse, + type ScaffolderGetIntegrationsListOptions, + type ScaffolderGetIntegrationsListResponse, + type ScaffolderOutputLink, + type ScaffolderScaffoldOptions, + type ScaffolderScaffoldResponse, + type ScaffolderStreamLogsOptions, + type ScaffolderTask, + type ScaffolderTaskOutput, + type ScaffolderTaskStatus, } from '@backstage/plugin-scaffolder-react'; export type { TaskPageProps } from './components/TaskPage'; diff --git a/plugins/scaffolder/src/next/TemplateWizardPage/TemplateWizardPage.test.tsx b/plugins/scaffolder/src/next/TemplateWizardPage/TemplateWizardPage.test.tsx index 854cfc6545..52b6451862 100644 --- a/plugins/scaffolder/src/next/TemplateWizardPage/TemplateWizardPage.test.tsx +++ b/plugins/scaffolder/src/next/TemplateWizardPage/TemplateWizardPage.test.tsx @@ -22,9 +22,12 @@ import { } from '@backstage/test-utils'; import { act, fireEvent } from '@testing-library/react'; import React from 'react'; -import { scaffolderApiRef } from '../../api'; -import { nextRouteRef, rootRouteRef } from '@backstage/plugin-scaffolder-react'; -import { ScaffolderApi } from '../../types'; +import { + nextRouteRef, + rootRouteRef, + ScaffolderApi, + scaffolderApiRef, +} from '@backstage/plugin-scaffolder-react'; import { TemplateWizardPage } from './TemplateWizardPage'; jest.mock('react-router-dom', () => { diff --git a/plugins/scaffolder/src/next/TemplateWizardPage/TemplateWizardPage.tsx b/plugins/scaffolder/src/next/TemplateWizardPage/TemplateWizardPage.tsx index 9ee5e89cab..d2ef72d4ae 100644 --- a/plugins/scaffolder/src/next/TemplateWizardPage/TemplateWizardPage.tsx +++ b/plugins/scaffolder/src/next/TemplateWizardPage/TemplateWizardPage.tsx @@ -31,7 +31,7 @@ import { useRouteRef, useRouteRefParams, } from '@backstage/core-plugin-api'; -import { scaffolderApiRef } from '../../api'; +import { scaffolderApiRef } from '@backstage/plugin-scaffolder-react'; import useAsync from 'react-use/lib/useAsync'; import { makeStyles } from '@material-ui/core'; import { BackstageTheme } from '@backstage/theme'; diff --git a/plugins/scaffolder/src/plugin.tsx b/plugins/scaffolder/src/plugin.tsx index 5049f8a050..5bbe51dd2d 100644 --- a/plugins/scaffolder/src/plugin.tsx +++ b/plugins/scaffolder/src/plugin.tsx @@ -21,8 +21,9 @@ import { rootRouteRef, viewTechDocRouteRef, createScaffolderFieldExtension, + scaffolderApiRef, } from '@backstage/plugin-scaffolder-react'; -import { scaffolderApiRef, ScaffolderClient } from './api'; +import { ScaffolderClient } from './api'; import { EntityPicker, EntityPickerSchema, diff --git a/yarn.lock b/yarn.lock index 00f8355d8b..371902d90e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -22430,6 +22430,7 @@ __metadata: "@backstage/plugin-playlist": "workspace:^" "@backstage/plugin-rollbar": "workspace:^" "@backstage/plugin-scaffolder": "workspace:^" + "@backstage/plugin-scaffolder-react": "workspace:^" "@backstage/plugin-search": "workspace:^" "@backstage/plugin-search-common": "workspace:^" "@backstage/plugin-search-react": "workspace:^" From de7e520a13b3a10df98b601a8b671efc30e355bf Mon Sep 17 00:00:00 2001 From: blam Date: Fri, 30 Dec 2022 14:02:35 +0100 Subject: [PATCH 11/35] chore: moving some more things around and updating the api reports Signed-off-by: blam --- plugins/scaffolder-react/api-report.md | 159 ++++++++++++++++++ plugins/scaffolder-react/src/api/ref.ts | 1 + .../next/components/Stepper/Stepper.test.tsx | 2 +- plugins/scaffolder/src/api.ts | 6 - 4 files changed, 161 insertions(+), 7 deletions(-) diff --git a/plugins/scaffolder-react/api-report.md b/plugins/scaffolder-react/api-report.md index 1886ed96ee..79e461a2ec 100644 --- a/plugins/scaffolder-react/api-report.md +++ b/plugins/scaffolder-react/api-report.md @@ -6,6 +6,7 @@ /// import { ApiHolder } from '@backstage/core-plugin-api'; +import { ApiRef } from '@backstage/core-plugin-api'; import { Dispatch } from 'react'; import { Extension } from '@backstage/core-plugin-api'; import { ExternalRouteRef } from '@backstage/core-plugin-api'; @@ -17,12 +18,15 @@ import type { FormProps as FormProps_2 } from '@rjsf/core-v5'; import { JsonObject } from '@backstage/types'; import { JSONSchema7 } from 'json-schema'; import { JsonValue } from '@backstage/types'; +import { Observable } from '@backstage/types'; import { PathParams } from '@backstage/core-plugin-api'; import { PropsWithChildren } from 'react'; import { default as React_2 } from 'react'; import { RouteRef } from '@backstage/core-plugin-api'; import { SetStateAction } from 'react'; import { SubRouteRef } from '@backstage/core-plugin-api'; +import { TaskSpec } from '@backstage/plugin-scaffolder-common'; +import { TaskStep } from '@backstage/plugin-scaffolder-common'; import { TemplateEntityV1beta3 } from '@backstage/plugin-scaffolder-common'; import { UIOptionsType } from '@rjsf/utils'; import { UiSchema } from '@rjsf/utils'; @@ -117,6 +121,29 @@ export const legacySelectedTemplateRouteRef: SubRouteRef< PathParams<'/templates/:templateName'> >; +// @public +export type ListActionsResponse = Array<{ + id: string; + description?: string; + schema?: { + input?: JSONSchema7; + output?: JSONSchema7; + }; +}>; + +// @public +export type LogEvent = { + type: 'log' | 'completion'; + body: { + message: string; + stepId?: string; + status?: ScaffolderTaskStatus; + }; + createdAt: string; + id: string; + taskId: string; +}; + // @alpha export type NextCustomFieldValidator = ( data: TFieldReturnValue, @@ -193,15 +220,147 @@ export type ReviewStateProps = { // @public (undocumented) export const rootRouteRef: RouteRef; +// @public +export interface ScaffolderApi { + // (undocumented) + dryRun?(options: ScaffolderDryRunOptions): Promise; + // (undocumented) + getIntegrationsList( + options: ScaffolderGetIntegrationsListOptions, + ): Promise; + // (undocumented) + getTask(taskId: string): Promise; + // (undocumented) + getTemplateParameterSchema( + templateRef: string, + ): Promise; + listActions(): Promise; + // (undocumented) + listTasks?(options: { filterByOwnership: 'owned' | 'all' }): Promise<{ + tasks: ScaffolderTask[]; + }>; + scaffold( + options: ScaffolderScaffoldOptions, + ): Promise; + // (undocumented) + streamLogs(options: ScaffolderStreamLogsOptions): Observable; +} + +// @public (undocumented) +export const scaffolderApiRef: ApiRef; + +// @public (undocumented) +export interface ScaffolderDryRunOptions { + // (undocumented) + directoryContents: { + path: string; + base64Content: string; + }[]; + // (undocumented) + secrets?: Record; + // (undocumented) + template: JsonValue; + // (undocumented) + values: JsonObject; +} + +// @public (undocumented) +export interface ScaffolderDryRunResponse { + // (undocumented) + directoryContents: Array<{ + path: string; + base64Content: string; + executable: boolean; + }>; + // (undocumented) + log: Array>; + // (undocumented) + output: ScaffolderTaskOutput; + // (undocumented) + steps: TaskStep[]; +} + // @public export const ScaffolderFieldExtensions: React_2.ComponentType; +// @public +export interface ScaffolderGetIntegrationsListOptions { + // (undocumented) + allowedHosts: string[]; +} + +// @public +export interface ScaffolderGetIntegrationsListResponse { + // (undocumented) + integrations: { + type: string; + title: string; + host: string; + }[]; +} + // @public (undocumented) export const scaffolderListTaskRouteRef: SubRouteRef; +// @public (undocumented) +export type ScaffolderOutputLink = { + title?: string; + icon?: string; + url?: string; + entityRef?: string; +}; + +// @public +export interface ScaffolderScaffoldOptions { + // (undocumented) + secrets?: Record; + // (undocumented) + templateRef: string; + // (undocumented) + values: Record; +} + +// @public +export interface ScaffolderScaffoldResponse { + // (undocumented) + taskId: string; +} + +// @public +export interface ScaffolderStreamLogsOptions { + // (undocumented) + after?: number; + // (undocumented) + taskId: string; +} + +// @public +export type ScaffolderTask = { + id: string; + spec: TaskSpec; + status: 'failed' | 'completed' | 'processing' | 'open' | 'cancelled'; + lastHeartbeatAt: string; + createdAt: string; +}; + +// @public (undocumented) +export type ScaffolderTaskOutput = { + links?: ScaffolderOutputLink[]; +} & { + [key: string]: unknown; +}; + // @public (undocumented) export const scaffolderTaskRouteRef: SubRouteRef>; +// @public +export type ScaffolderTaskStatus = + | 'open' + | 'processing' + | 'failed' + | 'completed' + | 'skipped'; + // @public export interface ScaffolderUseTemplateSecrets { // (undocumented) diff --git a/plugins/scaffolder-react/src/api/ref.ts b/plugins/scaffolder-react/src/api/ref.ts index bf0a5faddf..3dee426b09 100644 --- a/plugins/scaffolder-react/src/api/ref.ts +++ b/plugins/scaffolder-react/src/api/ref.ts @@ -17,6 +17,7 @@ import { createApiRef } from '@backstage/core-plugin-api'; import { ScaffolderApi } from './types'; +/** @public */ export const scaffolderApiRef = createApiRef({ id: 'plugin.scaffolder.service', }); diff --git a/plugins/scaffolder-react/src/next/components/Stepper/Stepper.test.tsx b/plugins/scaffolder-react/src/next/components/Stepper/Stepper.test.tsx index 2660eed47d..786f45b05d 100644 --- a/plugins/scaffolder-react/src/next/components/Stepper/Stepper.test.tsx +++ b/plugins/scaffolder-react/src/next/components/Stepper/Stepper.test.tsx @@ -20,7 +20,7 @@ import { renderInTestApp } from '@backstage/test-utils'; import { act, fireEvent } from '@testing-library/react'; import type { RJSFValidationError } from '@rjsf/utils'; import { JsonValue } from '@backstage/types'; -import { NextFieldExtensionComponentProps } from '../../../extensions/types'; +import { NextFieldExtensionComponentProps } from '../../extensions'; describe('Stepper', () => { it('should render the step titles for each step of the manifest', async () => { diff --git a/plugins/scaffolder/src/api.ts b/plugins/scaffolder/src/api.ts index 515496a363..15bd1925b3 100644 --- a/plugins/scaffolder/src/api.ts +++ b/plugins/scaffolder/src/api.ts @@ -140,12 +140,6 @@ export class ScaffolderClient implements ScaffolderApi { return schema; } - /** - * Executes the scaffolding of a component, given a template and its - * parameter values. - * - * @param options - The {@link ScaffolderScaffoldOptions} the scaffolding. - */ async scaffold( options: ScaffolderScaffoldOptions, ): Promise { From dc28726211315fe3f5a374b06ac151fe2fd204e0 Mon Sep 17 00:00:00 2001 From: blam Date: Fri, 30 Dec 2022 15:34:03 +0100 Subject: [PATCH 12/35] chore: fixing the deprecated export paths Signed-off-by: blam --- plugins/scaffolder/src/deprecated.ts | 195 +++++++++++++++++++++++++++ plugins/scaffolder/src/index.ts | 34 +---- 2 files changed, 196 insertions(+), 33 deletions(-) create mode 100644 plugins/scaffolder/src/deprecated.ts diff --git a/plugins/scaffolder/src/deprecated.ts b/plugins/scaffolder/src/deprecated.ts new file mode 100644 index 0000000000..64abbde7a4 --- /dev/null +++ b/plugins/scaffolder/src/deprecated.ts @@ -0,0 +1,195 @@ +/* + * Copyright 2022 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. + */ + +/* + * This file is here to re-export exports from the `@backage/plugin-scaffolder-react` package to keep backwards compatibility. + * But mark them as deprecated so that any import that is using these exports will be notified that they should use the `-react` package instead. + * It's a little awkward to get the deprecated notice to show up in the API report, which is why it's all been extracted out to this file. + */ + +import { + createScaffolderFieldExtension as createScaffolderFieldExtensionTemp, + ScaffolderFieldExtensions as ScaffolderFieldExtensionsTemp, + rootRouteRef as rootRouteRefTemp, + selectedTemplateRouteRef as selectedTemplateRouteRefTemp, + useTemplateSecrets as useTemplateSecretsTemp, + scaffolderApiRef as scaffolderApiRefTemp, + type ScaffolderApi as ScaffolderApiTemp, + type ScaffolderUseTemplateSecrets as ScaffolderUseTemplateSecretsTemp, + type TemplateParameterSchema as TemplateParameterSchemaTemp, + type CustomFieldExtensionSchema as CustomFieldExtensionSchemaTemp, + type CustomFieldValidator as CustomFieldValidatorTemp, + type FieldExtensionOptions as FieldExtensionOptionsTemp, + type FieldExtensionComponentProps as FieldExtensionComponentPropsTemp, + type FieldExtensionComponent as FieldExtensionComponentTemp, + type ListActionsResponse as ListActionsResponseTemp, + type LogEvent as LogEventTemp, + type ScaffolderDryRunOptions as ScaffolderDryRunOptionsTemp, + type ScaffolderDryRunResponse as ScaffolderDryRunResponseTemp, + type ScaffolderGetIntegrationsListOptions as ScaffolderGetIntegrationsListOptionsTemp, + type ScaffolderGetIntegrationsListResponse as ScaffolderGetIntegrationsListResponseTemp, + type ScaffolderOutputLink as ScaffolderOutputLinkTemp, + type ScaffolderScaffoldOptions as ScaffolderScaffoldOptionsTemp, + type ScaffolderScaffoldResponse as ScaffolderScaffoldResponseTemp, + type ScaffolderStreamLogsOptions as ScaffolderStreamLogsOptionsTemp, + type ScaffolderTask as ScaffolderTaskTemp, + type ScaffolderTaskOutput as ScaffolderTaskOutputTemp, + type ScaffolderTaskStatus as ScaffolderTaskStatusTemp, +} from '@backstage/plugin-scaffolder-react'; + +/** + * @public + * @deprecated use import from {@link @backstage/plugin-scaffolder-react#createScaffolderFieldExtension} instead as this has now been moved. + */ +export const createScaffolderFieldExtension = + createScaffolderFieldExtensionTemp; +/** + * @public + * @deprecated use import from {@link @backstage/plugin-scaffolder-react#ScaffolderFieldExtensions} instead as this has now been moved. + */ +export const ScaffolderFieldExtensions = ScaffolderFieldExtensionsTemp; +/** + * @public + * @deprecated use import from {@link @backstage/plugin-scaffolder-react#rootRouteRef} instead as this has now been moved. + */ +export const rootRouteRef = rootRouteRefTemp; +/** + * @public + * @deprecated use import from {@link @backstage/plugin-scaffolder-react#selectedTemplateRouteRef} instead as this has now been moved. + */ +export const selectedTemplateRouteRef = selectedTemplateRouteRefTemp; +/** + * @public + * @deprecated use import from {@link @backstage/plugin-scaffolder-react#useTemplateSecrets} instead as this has now been moved. + */ +export const useTemplateSecrets = useTemplateSecretsTemp; +/** + * @public + * @deprecated use import from {@link @backstage/plugin-scaffolder-react#scaffolderApiRef} instead as this has now been moved. + */ +export const scaffolderApiRef = scaffolderApiRefTemp; +/** + * @public + * @deprecated use import from {@link @backstage/plugin-scaffolder-react#ScaffolderApi} instead as this has now been moved. + */ +export type ScaffolderApi = ScaffolderApiTemp; +/** + * @public + * @deprecated use import from {@link @backstage/plugin-scaffolder-react#ScaffolderUseTemplateSecrets} instead as this has now been moved. + */ +export type ScaffolderUseTemplateSecrets = ScaffolderUseTemplateSecretsTemp; +/** + * @public + * @deprecated use import from {@link @backstage/plugin-scaffolder-react#TemplateParameterSchema} instead as this has now been moved. + */ +export type TemplateParameterSchema = TemplateParameterSchemaTemp; +/** + * @public + * @deprecated use import from {@link @backstage/plugin-scaffolder-react#CustomFieldExtensionSchema} instead as this has now been moved. + */ +export type CustomFieldExtensionSchema = CustomFieldExtensionSchemaTemp; +/** + * @public + * @deprecated use import from {@link @backstage/plugin-scaffolder-react#CustomFieldValidator} instead as this has now been moved. + */ +export type CustomFieldValidator = + CustomFieldValidatorTemp; +/** + * @public + * @deprecated use import from {@link @backstage/plugin-scaffolder-react#FieldExtensionOptions} instead as this has now been moved. + */ +export type FieldExtensionOptions = FieldExtensionOptionsTemp; +/** + * @public + * @deprecated use import from {@link @backstage/plugin-scaffolder-react#FieldExtensionComponentProps} instead as this has now been moved. + */ +export type FieldExtensionComponentProps< + TFieldReturnValue, + TUiOptions extends {} = {}, +> = FieldExtensionComponentPropsTemp; +/** + * @public + * @deprecated use import from {@link @backstage/plugin-scaffolder-react#FieldExtensionComponent} instead as this has now been moved. + */ +export type FieldExtensionComponent<_TReturnValue, _TInputProps> = + FieldExtensionComponentTemp<_TReturnValue, _TInputProps>; +/** + * @public + * @deprecated use import from {@link @backstage/plugin-scaffolder-react#ListActionsResponse} instead as this has now been moved. + */ +export type ListActionsResponse = ListActionsResponseTemp; +/** + * @public + * @deprecated use import from {@link @backstage/plugin-scaffolder-react#LogEvent} instead as this has now been moved. + */ +export type LogEvent = LogEventTemp; +/** + * @public + * @deprecated use import from {@link @backstage/plugin-scaffolder-react#ScaffolderDryRunOptions} instead as this has now been moved. + */ +export type ScaffolderDryRunOptions = ScaffolderDryRunOptionsTemp; +/** + * @public + * @deprecated use import from {@link @backstage/plugin-scaffolder-react#ScaffolderDryRunResponse} instead as this has now been moved. + */ +export type ScaffolderDryRunResponse = ScaffolderDryRunResponseTemp; +/** + * @public + * @deprecated use import from {@link @backstage/plugin-scaffolder-react#ScaffolderGetIntegrationsListOptions} instead as this has now been moved. + */ +export type ScaffolderGetIntegrationsListOptions = + ScaffolderGetIntegrationsListOptionsTemp; +/** + * @public + * @deprecated use import from {@link @backstage/plugin-scaffolder-react#ScaffolderGetIntegrationsListResponse} instead as this has now been moved. + */ +export type ScaffolderGetIntegrationsListResponse = + ScaffolderGetIntegrationsListResponseTemp; +/** + * @public + * @deprecated use import from {@link @backstage/plugin-scaffolder-react#ScaffolderOutputlink} instead as this has now been moved. + */ +export type ScaffolderOutputlink = ScaffolderOutputLinkTemp; +/** + * @public + * @deprecated use import from {@link @backstage/plugin-scaffolder-react#ScaffolderScaffoldOptions} instead as this has now been moved. + */ +export type ScaffolderScaffoldOptions = ScaffolderScaffoldOptionsTemp; +/** + * @public + * @deprecated use import from {@link @backstage/plugin-scaffolder-react#ScaffolderScaffoldResponse} instead as this has now been moved. + */ +export type ScaffolderScaffoldResponse = ScaffolderScaffoldResponseTemp; +/** + * @public + * @deprecated use import from {@link @backstage/plugin-scaffolder-react#ScaffolderStreamLogsOptions} instead as this has now been moved. + */ +export type ScaffolderStreamLogsOptions = ScaffolderStreamLogsOptionsTemp; +/** + * @public + * @deprecated use import from {@link @backstage/plugin-scaffolder-react#ScaffolderTask} instead as this has now been moved. + */ +export type ScaffolderTask = ScaffolderTaskTemp; +/** + * @public + * @deprecated use import from {@link @backstage/plugin-scaffolder-react#ScaffolderTaskOutput} instead as this has now been moved. + */ +export type ScaffolderTaskOutput = ScaffolderTaskOutputTemp; +/** + * @public + * @deprecated use import from {@link @backstage/plugin-scaffolder-react#ScaffolderTaskStatus} instead as this has now been moved. + */ +export type ScaffolderTaskStatus = ScaffolderTaskStatusTemp; diff --git a/plugins/scaffolder/src/index.ts b/plugins/scaffolder/src/index.ts index 85de61b667..c4abee4735 100644 --- a/plugins/scaffolder/src/index.ts +++ b/plugins/scaffolder/src/index.ts @@ -36,39 +36,7 @@ export { } from './plugin'; export * from './components'; -/** @deprecated - use imports from @backstage/plugin-scaffolder-react instead */ -export { - createScaffolderFieldExtension, - ScaffolderFieldExtensions, - rootRouteRef, - selectedTemplateRouteRef, - useTemplateSecrets, - scaffolderApiRef, - /** @deprecated - use imports from @backstage/plugin-scaffolder-react instead */ - type ScaffolderApi, - /** @deprecated */ - type ScaffolderUseTemplateSecrets, - /** @deprecated */ - type TemplateParameterSchema, - type CustomFieldExtensionSchema, - type CustomFieldValidator, - type FieldExtensionOptions, - type FieldExtensionComponentProps, - type FieldExtensionComponent, - type ListActionsResponse, - type LogEvent, - type ScaffolderDryRunOptions, - type ScaffolderDryRunResponse, - type ScaffolderGetIntegrationsListOptions, - type ScaffolderGetIntegrationsListResponse, - type ScaffolderOutputLink, - type ScaffolderScaffoldOptions, - type ScaffolderScaffoldResponse, - type ScaffolderStreamLogsOptions, - type ScaffolderTask, - type ScaffolderTaskOutput, - type ScaffolderTaskStatus, -} from '@backstage/plugin-scaffolder-react'; +export * from './deprecated'; export type { TaskPageProps } from './components/TaskPage'; From b4955ed7b937082f3922a3cbb0bfda1118fec04c Mon Sep 17 00:00:00 2001 From: blam Date: Fri, 30 Dec 2022 15:46:43 +0100 Subject: [PATCH 13/35] chore: added some changesets Signed-off-by: blam Signed-off-by: blam --- .changeset/kind-pianos-burn.md | 5 ++++ .changeset/wild-socks-breathe.md | 48 ++++++++++++++++++++++++++++++++ 2 files changed, 53 insertions(+) create mode 100644 .changeset/kind-pianos-burn.md create mode 100644 .changeset/wild-socks-breathe.md diff --git a/.changeset/kind-pianos-burn.md b/.changeset/kind-pianos-burn.md new file mode 100644 index 0000000000..078ab6846e --- /dev/null +++ b/.changeset/kind-pianos-burn.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-scaffolder-react': patch +--- + +Re-home some of the common types, components, hooks and `(route|api)Ref`'s for the `@backstage/plugin-scaffolder` to this package for easy re-use across things that want to interact with the `scaffolder`. diff --git a/.changeset/wild-socks-breathe.md b/.changeset/wild-socks-breathe.md new file mode 100644 index 0000000000..d96a5a33e3 --- /dev/null +++ b/.changeset/wild-socks-breathe.md @@ -0,0 +1,48 @@ +--- +'@backstage/plugin-scaffolder': minor +--- + +- **Deprecation** - Deprecated the following exports, please import them directly from `@backstage/plugin-scaffolder-react` instead + + ``` + createScaffolderFieldExtension + ScaffolderFieldExtensions + rootRouteRef + selectedTemplateRouteRef + useTemplateSecrets + scaffolderApiRef + ScaffolderApi + ScaffolderUseTemplateSecrets + TemplateParameterSchema + CustomFieldExtensionSchema + CustomFieldValidator + FieldExtensionOptions + FieldExtensionComponentProps + FieldExtensionComponent + ListActionsResponse + LogEvent + ScaffolderDryRunOptions + ScaffolderDryRunResponse + ScaffolderGetIntegrationsListOptions + ScaffolderGetIntegrationsListResponse + ScaffolderOutputlink + ScaffolderScaffoldOptions + ScaffolderScaffoldResponse + ScaffolderStreamLogsOptions + ScaffolderTask + ScaffolderTaskOutput + ScaffolderTaskStatus + ``` + +- The following `/alpha` types have removed from this package and moved to the `@backstage/plugin-scaffolder-react/alpha` package + + ``` + createNextScaffolderFieldExtension + FormProps + NextCustomFieldValidator + NextFieldExtensionComponentProps + NextFieldExtensionOptions + nextRouteRef + nextScaffolderTaskRouteRef + nextSelectedTemplateRouteRef + ``` From 56cda2cc4972e9cb8778e665a758ae977125f158 Mon Sep 17 00:00:00 2001 From: blam Date: Mon, 2 Jan 2023 14:54:09 +0100 Subject: [PATCH 14/35] chore: fixing dependency linting Signed-off-by: blam --- plugins/scaffolder/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/scaffolder/package.json b/plugins/scaffolder/package.json index 3431c46655..839779acf6 100644 --- a/plugins/scaffolder/package.json +++ b/plugins/scaffolder/package.json @@ -61,7 +61,6 @@ "@rjsf/material-ui-v5": "npm:@rjsf/material-ui@^5.0.0-beta.14", "@rjsf/utils": "^5.0.0-beta.14", "@rjsf/validator-ajv6": "^5.0.0-beta.14", - "@types/json-schema": "^7.0.9", "@uiw/react-codemirror": "^4.9.3", "classnames": "^2.2.6", "git-url-parse": "^13.0.0", @@ -95,6 +94,7 @@ "@testing-library/react-hooks": "^8.0.0", "@testing-library/user-event": "^14.0.0", "@types/humanize-duration": "^3.18.1", + "@types/json-schema": "^7.0.9", "@types/node": "^16.11.26", "cross-fetch": "^3.1.5", "event-source-polyfill": "1.0.25", From 3053e582fc4ae85f308d2680f0e5aa1953c0deba Mon Sep 17 00:00:00 2001 From: blam Date: Mon, 2 Jan 2023 16:15:13 +0100 Subject: [PATCH 15/35] fix: workaround the typing issue by duplicating the `FormProps` type as this is the only exported type from the `/alpha` imports Signed-off-by: blam --- plugins/scaffolder/src/index.ts | 7 ++-- plugins/scaffolder/src/next/Router/Router.tsx | 2 +- .../TemplateWizardPage/TemplateWizardPage.tsx | 4 +-- plugins/scaffolder/src/next/index.ts | 1 + plugins/scaffolder/src/next/types.ts | 34 +++++++++++++++++++ 5 files changed, 43 insertions(+), 5 deletions(-) create mode 100644 plugins/scaffolder/src/next/types.ts diff --git a/plugins/scaffolder/src/index.ts b/plugins/scaffolder/src/index.ts index c4abee4735..488ca7d670 100644 --- a/plugins/scaffolder/src/index.ts +++ b/plugins/scaffolder/src/index.ts @@ -42,5 +42,8 @@ export type { TaskPageProps } from './components/TaskPage'; /** next exports */ export { NextScaffolderPage } from './plugin'; -export type { NextRouterProps } from './next'; -export type { TemplateGroupFilter } from './next'; +export { + type TemplateGroupFilter, + type NextRouterProps, + type FormProps, +} from './next'; diff --git a/plugins/scaffolder/src/next/Router/Router.tsx b/plugins/scaffolder/src/next/Router/Router.tsx index 1c8e7ada6e..799dd10bca 100644 --- a/plugins/scaffolder/src/next/Router/Router.tsx +++ b/plugins/scaffolder/src/next/Router/Router.tsx @@ -24,13 +24,13 @@ import { FieldExtensionOptions, nextSelectedTemplateRouteRef, SecretsContextProvider, - type FormProps, } from '@backstage/plugin-scaffolder-react'; import { useElementFilter } from '@backstage/core-plugin-api'; import { TemplateEntityV1beta3 } from '@backstage/plugin-scaffolder-common'; import { TemplateGroupFilter } from '../TemplateListPage/TemplateGroups'; import { DEFAULT_SCAFFOLDER_FIELD_EXTENSIONS } from '../../extensions/default'; +import { FormProps } from '../types'; /** * The Props for the Scaffolder Router diff --git a/plugins/scaffolder/src/next/TemplateWizardPage/TemplateWizardPage.tsx b/plugins/scaffolder/src/next/TemplateWizardPage/TemplateWizardPage.tsx index d2ef72d4ae..e3717befdb 100644 --- a/plugins/scaffolder/src/next/TemplateWizardPage/TemplateWizardPage.tsx +++ b/plugins/scaffolder/src/next/TemplateWizardPage/TemplateWizardPage.tsx @@ -42,11 +42,11 @@ import { Stepper, NextFieldExtensionOptions, SecretsContext, - type FormProps, } from '@backstage/plugin-scaffolder-react'; import { JsonValue } from '@backstage/types'; +import { FormProps } from '../types'; -export type TemplateWizardPageProps = { +type TemplateWizardPageProps = { customFieldExtensions: NextFieldExtensionOptions[]; FormProps?: FormProps; }; diff --git a/plugins/scaffolder/src/next/index.ts b/plugins/scaffolder/src/next/index.ts index 089c268b0b..6cef3eaa03 100644 --- a/plugins/scaffolder/src/next/index.ts +++ b/plugins/scaffolder/src/next/index.ts @@ -16,3 +16,4 @@ export * from './Router'; export * from './TemplateListPage'; export * from './TemplateWizardPage'; +export * from './types'; diff --git a/plugins/scaffolder/src/next/types.ts b/plugins/scaffolder/src/next/types.ts new file mode 100644 index 0000000000..e9c77aa00e --- /dev/null +++ b/plugins/scaffolder/src/next/types.ts @@ -0,0 +1,34 @@ +/* + * Copyright 2022 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. + */ + +/** + * These types will be replaced eventually by the one in the scaffolder-react plugin. + * It is a temporary solution to avoid the `/alpha` types being re-exported and that not being supported right now. + * It exists already in the `scaffolder-react` plugin, so you may have to update both files. + */ + +import type { FormProps as SchemaFormProps } from '@rjsf/core-v5'; + +/** + * Any `@rjsf/core` form properties that are publicly exposed to the `NextScaffolderpage` + * + * @alpha + * @deprecated use the import from {@link @backstage/plugin-scaffolder-react/alpha#FormProps} instead + */ +export type FormProps = Pick< + SchemaFormProps, + 'transformErrors' | 'noHtml5Validate' +>; From 912bd110f23b28ba1eab9c6230decb7a88cc119b Mon Sep 17 00:00:00 2001 From: blam Date: Wed, 4 Jan 2023 23:20:28 +0100 Subject: [PATCH 16/35] chore: move the routeRefs back into the scaffolder plugin for now, maybe it makes sense to move them later. Signed-off-by: blam --- plugins/scaffolder-react/src/index.ts | 1 - .../src/next/components/Stepper/Stepper.tsx | 15 ++-- .../TemplateCard/TemplateCard.test.tsx | 7 -- .../components/TemplateCard/TemplateCard.tsx | 63 +++++---------- .../TemplateGroup/TemplateGroup.tsx | 27 ++++++- plugins/scaffolder-react/src/next/index.ts | 1 - .../ActionsPage/ActionsPage.test.tsx | 2 +- .../ListTasksPage/ListTaskPage.test.tsx | 2 +- .../ListTasksPage/ListTasksPage.tsx | 2 +- .../MultistepJsonForm/MultistepJsonForm.tsx | 6 +- plugins/scaffolder/src/components/Router.tsx | 14 ++-- .../ScaffolderPage/ScaffolderPage.tsx | 2 +- .../ScaffolderPageContextMenu.test.tsx | 2 +- .../ScaffolderPageContextMenu.tsx | 2 +- .../src/components/TaskPage/TaskPage.tsx | 8 +- .../components/TemplateCard/TemplateCard.tsx | 5 +- .../TemplatePage/TemplatePage.test.tsx | 2 +- .../components/TemplatePage/TemplatePage.tsx | 8 +- plugins/scaffolder/src/components/index.ts | 2 +- plugins/scaffolder/src/deprecated.ts | 12 --- plugins/scaffolder/src/index.ts | 18 +++-- plugins/scaffolder/src/next/Router/Router.tsx | 3 +- .../next/TemplateListPage/TemplateGroups.tsx | 76 +++++++++++++++---- .../TemplateListPage.test.tsx | 2 +- .../TemplateListPage/TemplateListPage.tsx | 2 +- .../TemplateWizardPage.test.tsx | 4 +- .../TemplateWizardPage/TemplateWizardPage.tsx | 5 +- plugins/scaffolder/src/next/index.ts | 1 + .../src/next/routes.ts | 0 plugins/scaffolder/src/plugin.tsx | 10 ++- .../src/routes.ts | 0 31 files changed, 169 insertions(+), 135 deletions(-) rename plugins/{scaffolder-react => scaffolder}/src/next/routes.ts (100%) rename plugins/{scaffolder-react => scaffolder}/src/routes.ts (100%) diff --git a/plugins/scaffolder-react/src/index.ts b/plugins/scaffolder-react/src/index.ts index 14bcb1e44f..a2336a5ca5 100644 --- a/plugins/scaffolder-react/src/index.ts +++ b/plugins/scaffolder-react/src/index.ts @@ -14,7 +14,6 @@ * limitations under the License. */ -export * from './routes'; export * from './extensions'; export * from './types'; export * from './secrets'; diff --git a/plugins/scaffolder-react/src/next/components/Stepper/Stepper.tsx b/plugins/scaffolder-react/src/next/components/Stepper/Stepper.tsx index 8ff4646d1c..05345c34b5 100644 --- a/plugins/scaffolder-react/src/next/components/Stepper/Stepper.tsx +++ b/plugins/scaffolder-react/src/next/components/Stepper/Stepper.tsx @@ -13,11 +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, @@ -35,7 +31,7 @@ import { createAsyncValidators } from './createAsyncValidators'; import { useTemplateSchema } from '../../hooks/useTemplateSchema'; import { ReviewState } from '../ReviewState'; import validator from '@rjsf/validator-ajv6'; -import { selectedTemplateRouteRef } from '../../../routes'; + import { useFormData } from '../../hooks/useFormData'; import { FormProps } from '../../types'; @@ -61,8 +57,10 @@ const useStyles = makeStyles(theme => ({ export type StepperProps = { manifest: TemplateParameterSchema; extensions: NextFieldExtensionOptions[]; - onComplete: (values: Record) => Promise; + templateName?: string; FormProps?: FormProps; + + onComplete: (values: Record) => Promise; }; // TODO(blam): We require here, as the types in this package depend on @rjsf/core explicitly @@ -75,7 +73,6 @@ const Form = withTheme(require('@rjsf/material-ui-v5').Theme); * @alpha */ export const Stepper = (props: StepperProps) => { - const { templateName } = useRouteRefParams(selectedTemplateRouteRef); const analytics = useAnalytics(); const { steps } = useTemplateSchema(props.manifest); const apiHolder = useApiHolder(); @@ -204,7 +201,7 @@ export const Stepper = (props: StepperProps) => { : undefined; analytics.captureEvent( 'create', - name || `new ${templateName}`, + name ?? props.templateName ?? 'unknown', ); }} > diff --git a/plugins/scaffolder-react/src/next/components/TemplateCard/TemplateCard.test.tsx b/plugins/scaffolder-react/src/next/components/TemplateCard/TemplateCard.test.tsx index 228d8af4e3..f2e2cae8c6 100644 --- a/plugins/scaffolder-react/src/next/components/TemplateCard/TemplateCard.test.tsx +++ b/plugins/scaffolder-react/src/next/components/TemplateCard/TemplateCard.test.tsx @@ -27,7 +27,6 @@ import { TemplateCard } from './TemplateCard'; import React from 'react'; import { TemplateEntityV1beta3 } from '@backstage/plugin-scaffolder-common'; import { RELATION_OWNED_BY } from '@backstage/catalog-model'; -import { nextRouteRef } from '../../routes'; describe('TemplateCard', () => { it('should render the card title', async () => { @@ -54,7 +53,6 @@ describe('TemplateCard', () => { > , - { mountedRoutes: { '/': nextRouteRef } }, ); expect(getByText('bob')).toBeInTheDocument(); @@ -84,7 +82,6 @@ describe('TemplateCard', () => { > , - { mountedRoutes: { '/': nextRouteRef } }, ); const description = getByText('hello'); @@ -115,7 +112,6 @@ describe('TemplateCard', () => { > , - { mountedRoutes: { '/': nextRouteRef } }, ); expect(getByText('No description')).toBeInTheDocument(); @@ -145,7 +141,6 @@ describe('TemplateCard', () => { > , - { mountedRoutes: { '/': nextRouteRef } }, ); for (const tag of mockTemplate.metadata.tags!) { @@ -185,7 +180,6 @@ describe('TemplateCard', () => { , { mountedRoutes: { - '/': nextRouteRef, '/catalog/:kind/:namespace/:name': entityRouteRef, }, }, @@ -224,7 +218,6 @@ describe('TemplateCard', () => { , { mountedRoutes: { - '/': nextRouteRef, '/catalog/:kind/:namespace/:name': entityRouteRef, }, }, diff --git a/plugins/scaffolder-react/src/next/components/TemplateCard/TemplateCard.tsx b/plugins/scaffolder-react/src/next/components/TemplateCard/TemplateCard.tsx index 1176b01e5d..6f89808405 100644 --- a/plugins/scaffolder-react/src/next/components/TemplateCard/TemplateCard.tsx +++ b/plugins/scaffolder-react/src/next/components/TemplateCard/TemplateCard.tsx @@ -13,14 +13,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { - DEFAULT_NAMESPACE, - parseEntityRef, - RELATION_OWNED_BY, - stringifyEntityRef, -} from '@backstage/catalog-model'; -import { Button, MarkdownContent, UserIcon } from '@backstage/core-components'; -import { IconComponent, useApp, useRouteRef } from '@backstage/core-plugin-api'; +import { RELATION_OWNED_BY } from '@backstage/catalog-model'; +import { MarkdownContent, UserIcon } from '@backstage/core-components'; +import { IconComponent, useApp } from '@backstage/core-plugin-api'; import { EntityRefLinks, getEntityRelations, @@ -34,13 +29,12 @@ import { CardContent, Chip, Divider, + Button, Grid, makeStyles, } from '@material-ui/core'; import LanguageIcon from '@material-ui/icons/Language'; import React from 'react'; -import { nextSelectedTemplateRouteRef } from '../../routes'; -import { viewTechDocRouteRef } from '../../../routes'; import { CardHeader } from './CardHeader'; import { CardLink } from './CardLink'; @@ -86,7 +80,13 @@ const useStyles = makeStyles(theme => ({ */ export interface TemplateCardProps { template: TemplateEntityV1beta3; - deprecated?: boolean; + additionalLinks?: { + icon: IconComponent; + text: string; + url: string; + }[]; + + onSelected?: (template: TemplateEntityV1beta3) => void; } /** @@ -97,32 +97,10 @@ export const TemplateCard = (props: TemplateCardProps) => { const { template } = props; const styles = useStyles(); const ownedByRelations = getEntityRelations(template, RELATION_OWNED_BY); - const templateRoute = useRouteRef(nextSelectedTemplateRouteRef); - const { name, namespace } = parseEntityRef( - stringifyEntityRef(props.template), - ); - const href = templateRoute({ - templateName: name, - namespace: namespace, - }); - const app = useApp(); const iconResolver = (key?: string): IconComponent => key ? app.getSystemIcon(key) ?? LanguageIcon : LanguageIcon; - // TechDocs Link - const viewTechDoc = useRouteRef(viewTechDocRouteRef); - const viewTechDocsAnnotation = - template.metadata.annotations?.['backstage.io/techdocs-ref']; - const viewTechDocsLink = - !!viewTechDocsAnnotation && - !!viewTechDoc && - viewTechDoc({ - namespace: template.metadata.namespace || DEFAULT_NAMESPACE, - kind: template.kind, - name: template.metadata.name, - }); - return ( @@ -157,22 +135,18 @@ export const TemplateCard = (props: TemplateCardProps) => { )} - {(!!viewTechDocsLink || template.metadata.links?.length) && ( + {(props.additionalLinks || template.metadata.links?.length) && ( <> - {viewTechDocsLink && ( + {props.additionalLinks?.map(({ icon, text, url }) => ( - + - )} + ))} {template.metadata.links?.map(({ url, icon, title }) => ( { )} - diff --git a/plugins/scaffolder-react/src/next/components/TemplateGroup/TemplateGroup.tsx b/plugins/scaffolder-react/src/next/components/TemplateGroup/TemplateGroup.tsx index 74d9242041..8134ea256d 100644 --- a/plugins/scaffolder-react/src/next/components/TemplateGroup/TemplateGroup.tsx +++ b/plugins/scaffolder-react/src/next/components/TemplateGroup/TemplateGroup.tsx @@ -24,13 +24,22 @@ import { import { Typography } from '@material-ui/core'; import { stringifyEntityRef } from '@backstage/catalog-model'; import { TemplateCardProps, TemplateCard } from '../TemplateCard'; +import { IconComponent } from '@backstage/core-plugin-api'; /** * The props for the {@link TemplateGroup} component. * @alpha */ export interface TemplateGroupProps { - templates: TemplateEntityV1beta3[]; + templates: { + template: TemplateEntityV1beta3; + additionalLinks?: { + icon: IconComponent; + text: string; + url: string; + }[]; + }[]; + onSelected: (template: TemplateEntityV1beta3) => void; title: React.ReactNode; components?: { CardComponent?: React.ComponentType; @@ -42,7 +51,12 @@ export interface TemplateGroupProps { * @alpha */ export const TemplateGroup = (props: TemplateGroupProps) => { - const { templates, title, components: { CardComponent } = {} } = props; + const { + templates, + title, + components: { CardComponent } = {}, + onSelected, + } = props; const titleComponent = typeof title === 'string' ? : title; @@ -67,8 +81,13 @@ export const TemplateGroup = (props: TemplateGroupProps) => { {titleComponent} - {templates.map(template => ( - + {templates.map(({ template, additionalLinks }) => ( + ))} diff --git a/plugins/scaffolder-react/src/next/index.ts b/plugins/scaffolder-react/src/next/index.ts index fe12e38ad9..a18649f506 100644 --- a/plugins/scaffolder-react/src/next/index.ts +++ b/plugins/scaffolder-react/src/next/index.ts @@ -18,4 +18,3 @@ export * from './extensions'; export * from './types'; export * from './lib'; export * from './hooks'; -export * from './routes'; diff --git a/plugins/scaffolder/src/components/ActionsPage/ActionsPage.test.tsx b/plugins/scaffolder/src/components/ActionsPage/ActionsPage.test.tsx index a049959ae4..552d0cea6a 100644 --- a/plugins/scaffolder/src/components/ActionsPage/ActionsPage.test.tsx +++ b/plugins/scaffolder/src/components/ActionsPage/ActionsPage.test.tsx @@ -16,12 +16,12 @@ import React from 'react'; import { ActionsPage } from './ActionsPage'; import { - rootRouteRef, scaffolderApiRef, ScaffolderApi, } from '@backstage/plugin-scaffolder-react'; import { renderInTestApp, TestApiRegistry } from '@backstage/test-utils'; import { ApiProvider } from '@backstage/core-app-api'; +import { rootRouteRef } from '../../routes'; const scaffolderApiMock: jest.Mocked = { scaffold: jest.fn(), diff --git a/plugins/scaffolder/src/components/ListTasksPage/ListTaskPage.test.tsx b/plugins/scaffolder/src/components/ListTasksPage/ListTaskPage.test.tsx index 4843d9bcc0..b9c5a84da3 100644 --- a/plugins/scaffolder/src/components/ListTasksPage/ListTaskPage.test.tsx +++ b/plugins/scaffolder/src/components/ListTasksPage/ListTaskPage.test.tsx @@ -25,11 +25,11 @@ import React from 'react'; import { identityApiRef } from '@backstage/core-plugin-api'; import { ListTasksPage } from './ListTasksPage'; import { - rootRouteRef, scaffolderApiRef, ScaffolderApi, } from '@backstage/plugin-scaffolder-react'; import { act, fireEvent } from '@testing-library/react'; +import { rootRouteRef } from '../../routes'; describe('', () => { const catalogApi: jest.Mocked = { diff --git a/plugins/scaffolder/src/components/ListTasksPage/ListTasksPage.tsx b/plugins/scaffolder/src/components/ListTasksPage/ListTasksPage.tsx index 68dcedc99f..1edac508d8 100644 --- a/plugins/scaffolder/src/components/ListTasksPage/ListTasksPage.tsx +++ b/plugins/scaffolder/src/components/ListTasksPage/ListTasksPage.tsx @@ -29,7 +29,6 @@ import { CatalogFilterLayout } from '@backstage/plugin-catalog-react'; import useAsync from 'react-use/lib/useAsync'; import React, { useState } from 'react'; import { - rootRouteRef, ScaffolderTask, scaffolderApiRef, } from '@backstage/plugin-scaffolder-react'; @@ -40,6 +39,7 @@ import { TaskStatusColumn, TemplateTitleColumn, } from './columns'; +import { rootRouteRef } from '../../routes'; export interface MyTaskPageProps { initiallySelectedFilter?: 'owned' | 'all'; diff --git a/plugins/scaffolder/src/components/MultistepJsonForm/MultistepJsonForm.tsx b/plugins/scaffolder/src/components/MultistepJsonForm/MultistepJsonForm.tsx index 65db4217be..ed8471ec1e 100644 --- a/plugins/scaffolder/src/components/MultistepJsonForm/MultistepJsonForm.tsx +++ b/plugins/scaffolder/src/components/MultistepJsonForm/MultistepJsonForm.tsx @@ -39,10 +39,8 @@ import * as fieldOverrides from './FieldOverrides'; import { LayoutOptions } from '../../layouts'; import { ReviewStepProps } from '../types'; import { ReviewStep } from './ReviewStep'; -import { - selectedTemplateRouteRef, - extractSchemaFromStep, -} from '@backstage/plugin-scaffolder-react'; +import { extractSchemaFromStep } from '@backstage/plugin-scaffolder-react'; +import { selectedTemplateRouteRef } from '../../routes'; const Form = withTheme(MuiTheme); diff --git a/plugins/scaffolder/src/components/Router.tsx b/plugins/scaffolder/src/components/Router.tsx index fefb550aa7..287342007b 100644 --- a/plugins/scaffolder/src/components/Router.tsx +++ b/plugins/scaffolder/src/components/Router.tsx @@ -30,12 +30,6 @@ import { useRouteRefParams, } from '@backstage/core-plugin-api'; import { - actionsRouteRef, - editRouteRef, - legacySelectedTemplateRouteRef, - scaffolderListTaskRouteRef, - scaffolderTaskRouteRef, - selectedTemplateRouteRef, FIELD_EXTENSION_KEY, FIELD_EXTENSION_WRAPPER_KEY, FieldExtensionOptions, @@ -44,6 +38,14 @@ import { import { ListTasksPage } from './ListTasksPage'; import { LayoutOptions, LAYOUTS_KEY, LAYOUTS_WRAPPER_KEY } from '../layouts'; import { ReviewStepProps } from './types'; +import { + actionsRouteRef, + editRouteRef, + legacySelectedTemplateRouteRef, + scaffolderListTaskRouteRef, + scaffolderTaskRouteRef, + selectedTemplateRouteRef, +} from '../routes'; /** * The props for the entrypoint `ScaffolderPage` component the plugin. diff --git a/plugins/scaffolder/src/components/ScaffolderPage/ScaffolderPage.tsx b/plugins/scaffolder/src/components/ScaffolderPage/ScaffolderPage.tsx index 7306ae8fd4..50221f3a83 100644 --- a/plugins/scaffolder/src/components/ScaffolderPage/ScaffolderPage.tsx +++ b/plugins/scaffolder/src/components/ScaffolderPage/ScaffolderPage.tsx @@ -34,12 +34,12 @@ import { UserListPicker, } from '@backstage/plugin-catalog-react'; import React, { ComponentType } from 'react'; -import { registerComponentRouteRef } from '@backstage/plugin-scaffolder-react'; import { TemplateList } from '../TemplateList'; import { TemplateTypePicker } from '../TemplateTypePicker'; import { catalogEntityCreatePermission } from '@backstage/plugin-catalog-common'; import { usePermission } from '@backstage/plugin-permission-react'; import { ScaffolderPageContextMenu } from './ScaffolderPageContextMenu'; +import { registerComponentRouteRef } from '../../routes'; export type ScaffolderPageProps = { TemplateCardComponent?: diff --git a/plugins/scaffolder/src/components/ScaffolderPage/ScaffolderPageContextMenu.test.tsx b/plugins/scaffolder/src/components/ScaffolderPage/ScaffolderPageContextMenu.test.tsx index d9993c16e7..66513591d0 100644 --- a/plugins/scaffolder/src/components/ScaffolderPage/ScaffolderPageContextMenu.test.tsx +++ b/plugins/scaffolder/src/components/ScaffolderPage/ScaffolderPageContextMenu.test.tsx @@ -18,8 +18,8 @@ import userEvent from '@testing-library/user-event'; import { renderInTestApp } from '@backstage/test-utils'; import { screen } from '@testing-library/react'; import React from 'react'; -import { rootRouteRef } from '@backstage/plugin-scaffolder-react'; import { ScaffolderPageContextMenu } from './ScaffolderPageContextMenu'; +import { rootRouteRef } from '../../routes'; describe('ScaffolderPageContextMenu', () => { it('does not render anything if fully disabled', async () => { diff --git a/plugins/scaffolder/src/components/ScaffolderPage/ScaffolderPageContextMenu.tsx b/plugins/scaffolder/src/components/ScaffolderPage/ScaffolderPageContextMenu.tsx index 3c62a34e29..9e69fae68d 100644 --- a/plugins/scaffolder/src/components/ScaffolderPage/ScaffolderPageContextMenu.tsx +++ b/plugins/scaffolder/src/components/ScaffolderPage/ScaffolderPageContextMenu.tsx @@ -32,7 +32,7 @@ import { actionsRouteRef, editRouteRef, scaffolderListTaskRouteRef, -} from '@backstage/plugin-scaffolder-react'; +} from '../../routes'; const useStyles = makeStyles({ button: { diff --git a/plugins/scaffolder/src/components/TaskPage/TaskPage.tsx b/plugins/scaffolder/src/components/TaskPage/TaskPage.tsx index 02f27bd0c0..393bd495bf 100644 --- a/plugins/scaffolder/src/components/TaskPage/TaskPage.tsx +++ b/plugins/scaffolder/src/components/TaskPage/TaskPage.tsx @@ -48,15 +48,17 @@ import React, { memo, useEffect, useMemo, useState } from 'react'; import { useNavigate } from 'react-router-dom'; import useInterval from 'react-use/lib/useInterval'; import { - rootRouteRef, - scaffolderTaskRouteRef, - selectedTemplateRouteRef, ScaffolderTaskStatus, ScaffolderTaskOutput, } from '@backstage/plugin-scaffolder-react'; import { useTaskEventStream } from '../hooks/useEventStream'; import { TaskErrors } from './TaskErrors'; import { TaskPageLinks } from './TaskPageLinks'; +import { + rootRouteRef, + scaffolderTaskRouteRef, + selectedTemplateRouteRef, +} from '../../routes'; // typings are wrong for this library, so fallback to not parsing types. const humanizeDuration = require('humanize-duration'); diff --git a/plugins/scaffolder/src/components/TemplateCard/TemplateCard.tsx b/plugins/scaffolder/src/components/TemplateCard/TemplateCard.tsx index bf9e022296..984e51f3b5 100644 --- a/plugins/scaffolder/src/components/TemplateCard/TemplateCard.tsx +++ b/plugins/scaffolder/src/components/TemplateCard/TemplateCard.tsx @@ -61,10 +61,7 @@ import { import LanguageIcon from '@material-ui/icons/Language'; import WarningIcon from '@material-ui/icons/Warning'; import React from 'react'; -import { - selectedTemplateRouteRef, - viewTechDocRouteRef, -} from '@backstage/plugin-scaffolder-react'; +import { selectedTemplateRouteRef, viewTechDocRouteRef } from '../../routes'; const useStyles = makeStyles(theme => ({ cardHeader: { diff --git a/plugins/scaffolder/src/components/TemplatePage/TemplatePage.test.tsx b/plugins/scaffolder/src/components/TemplatePage/TemplatePage.test.tsx index 5de29c42a5..5f43b54534 100644 --- a/plugins/scaffolder/src/components/TemplatePage/TemplatePage.test.tsx +++ b/plugins/scaffolder/src/components/TemplatePage/TemplatePage.test.tsx @@ -23,7 +23,6 @@ import { act, fireEvent, screen, within } from '@testing-library/react'; import React from 'react'; import { Route, Routes } from 'react-router-dom'; import { - rootRouteRef, scaffolderApiRef, ScaffolderApi, } from '@backstage/plugin-scaffolder-react'; @@ -35,6 +34,7 @@ import { } from '@backstage/core-plugin-api'; import { ApiProvider } from '@backstage/core-app-api'; import { errorApiRef } from '@backstage/core-plugin-api'; +import { rootRouteRef } from '../../routes'; jest.mock('react-router-dom', () => { return { diff --git a/plugins/scaffolder/src/components/TemplatePage/TemplatePage.tsx b/plugins/scaffolder/src/components/TemplatePage/TemplatePage.tsx index 08254491ce..c1814bf7e9 100644 --- a/plugins/scaffolder/src/components/TemplatePage/TemplatePage.tsx +++ b/plugins/scaffolder/src/components/TemplatePage/TemplatePage.tsx @@ -20,9 +20,6 @@ import React, { ComponentType, useCallback, useContext, useState } from 'react'; import { Navigate, useNavigate } from 'react-router-dom'; import useAsync from 'react-use/lib/useAsync'; import { - rootRouteRef, - scaffolderTaskRouteRef, - selectedTemplateRouteRef, FieldExtensionOptions, SecretsContext, scaffolderApiRef, @@ -42,6 +39,11 @@ import { import { stringifyEntityRef } from '@backstage/catalog-model'; import { LayoutOptions } from '../../layouts'; import { ReviewStepProps } from '../types'; +import { + rootRouteRef, + scaffolderTaskRouteRef, + selectedTemplateRouteRef, +} from '../../routes'; const useTemplateParameterSchema = (templateRef: string) => { const scaffolderApi = useApi(scaffolderApiRef); diff --git a/plugins/scaffolder/src/components/index.ts b/plugins/scaffolder/src/components/index.ts index 54d3a33d99..a5c17b8ab0 100644 --- a/plugins/scaffolder/src/components/index.ts +++ b/plugins/scaffolder/src/components/index.ts @@ -16,6 +16,6 @@ export * from './fields'; export type { RepoUrlPickerUiOptions } from './fields'; export { TemplateTypePicker } from './TemplateTypePicker'; -export { TaskPage } from './TaskPage'; +export { TaskPage, type TaskPageProps } from './TaskPage'; export type { RouterProps } from './Router'; export type { ReviewStepProps } from './types'; diff --git a/plugins/scaffolder/src/deprecated.ts b/plugins/scaffolder/src/deprecated.ts index 64abbde7a4..41d3568c0b 100644 --- a/plugins/scaffolder/src/deprecated.ts +++ b/plugins/scaffolder/src/deprecated.ts @@ -23,8 +23,6 @@ import { createScaffolderFieldExtension as createScaffolderFieldExtensionTemp, ScaffolderFieldExtensions as ScaffolderFieldExtensionsTemp, - rootRouteRef as rootRouteRefTemp, - selectedTemplateRouteRef as selectedTemplateRouteRefTemp, useTemplateSecrets as useTemplateSecretsTemp, scaffolderApiRef as scaffolderApiRefTemp, type ScaffolderApi as ScaffolderApiTemp, @@ -61,16 +59,6 @@ export const createScaffolderFieldExtension = * @deprecated use import from {@link @backstage/plugin-scaffolder-react#ScaffolderFieldExtensions} instead as this has now been moved. */ export const ScaffolderFieldExtensions = ScaffolderFieldExtensionsTemp; -/** - * @public - * @deprecated use import from {@link @backstage/plugin-scaffolder-react#rootRouteRef} instead as this has now been moved. - */ -export const rootRouteRef = rootRouteRefTemp; -/** - * @public - * @deprecated use import from {@link @backstage/plugin-scaffolder-react#selectedTemplateRouteRef} instead as this has now been moved. - */ -export const selectedTemplateRouteRef = selectedTemplateRouteRefTemp; /** * @public * @deprecated use import from {@link @backstage/plugin-scaffolder-react#useTemplateSecrets} instead as this has now been moved. diff --git a/plugins/scaffolder/src/index.ts b/plugins/scaffolder/src/index.ts index 488ca7d670..b5dd5e5d0d 100644 --- a/plugins/scaffolder/src/index.ts +++ b/plugins/scaffolder/src/index.ts @@ -22,8 +22,14 @@ export { ScaffolderClient } from './api'; -export { createScaffolderLayout, ScaffolderLayouts } from './layouts'; -export type { LayoutOptions, LayoutTemplate, LayoutComponent } from './layouts'; +export { + createScaffolderLayout, + ScaffolderLayouts, + type LayoutOptions, + type LayoutTemplate, + type LayoutComponent, +} from './layouts'; + export { EntityPickerFieldExtension, EntityNamePickerFieldExtension, @@ -34,15 +40,17 @@ export { ScaffolderPage, scaffolderPlugin, } from './plugin'; + export * from './components'; - +export * from './routes'; export * from './deprecated'; -export type { TaskPageProps } from './components/TaskPage'; - /** next exports */ export { NextScaffolderPage } from './plugin'; export { + nextRouteRef, + nextSelectedTemplateRouteRef, + nextScaffolderTaskRouteRef, type TemplateGroupFilter, type NextRouterProps, type FormProps, diff --git a/plugins/scaffolder/src/next/Router/Router.tsx b/plugins/scaffolder/src/next/Router/Router.tsx index 799dd10bca..a9785e6aa6 100644 --- a/plugins/scaffolder/src/next/Router/Router.tsx +++ b/plugins/scaffolder/src/next/Router/Router.tsx @@ -22,7 +22,6 @@ import { FIELD_EXTENSION_KEY, NextFieldExtensionOptions, FieldExtensionOptions, - nextSelectedTemplateRouteRef, SecretsContextProvider, } from '@backstage/plugin-scaffolder-react'; @@ -31,6 +30,7 @@ import { TemplateEntityV1beta3 } from '@backstage/plugin-scaffolder-common'; import { TemplateGroupFilter } from '../TemplateListPage/TemplateGroups'; import { DEFAULT_SCAFFOLDER_FIELD_EXTENSIONS } from '../../extensions/default'; import { FormProps } from '../types'; +import { nextSelectedTemplateRouteRef } from '../routes'; /** * The Props for the Scaffolder Router @@ -58,6 +58,7 @@ export const Router = (props: PropsWithChildren) => { const outlet = useOutlet() || props.children; + // todo(blam): move this out into a `useFieldExtensions` hook exported by -react const customFieldExtensions = useElementFilter(outlet, elements => elements .selectByComponentData({ diff --git a/plugins/scaffolder/src/next/TemplateListPage/TemplateGroups.tsx b/plugins/scaffolder/src/next/TemplateListPage/TemplateGroups.tsx index e502bfd9a7..485b0e40cd 100644 --- a/plugins/scaffolder/src/next/TemplateListPage/TemplateGroups.tsx +++ b/plugins/scaffolder/src/next/TemplateListPage/TemplateGroups.tsx @@ -13,15 +13,27 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import React from 'react'; +import React, { useCallback } from 'react'; -import { Entity } from '@backstage/catalog-model'; +import { + Entity, + parseEntityRef, + stringifyEntityRef, +} from '@backstage/catalog-model'; import { useEntityList } from '@backstage/plugin-catalog-react'; import { TemplateEntityV1beta3 } from '@backstage/plugin-scaffolder-common'; -import { Progress, Link } from '@backstage/core-components'; +import { Progress, Link, DocsIcon } from '@backstage/core-components'; import { Typography } from '@material-ui/core'; -import { errorApiRef, useApi } from '@backstage/core-plugin-api'; +import { + errorApiRef, + useApi, + useApp, + useRouteRef, +} from '@backstage/core-plugin-api'; import { TemplateGroup } from '@backstage/plugin-scaffolder-react'; +import { viewTechDocRouteRef } from '../../routes'; +import { nextSelectedTemplateRouteRef } from '../routes'; +import { useNavigate } from 'react-router-dom'; /** * @alpha @@ -42,6 +54,17 @@ export const TemplateGroups = (props: TemplateGroupsProps) => { const { loading, error, entities } = useEntityList(); const { groups, TemplateCardComponent } = props; const errorApi = useApi(errorApiRef); + const app = useApp(); + const viewTechDocsLink = useRouteRef(viewTechDocRouteRef); + const templateRoute = useRouteRef(nextSelectedTemplateRouteRef); + const navigate = useNavigate(); + const onSelected = useCallback( + (template: TemplateEntityV1beta3) => { + const { namespace, name } = parseEntityRef(stringifyEntityRef(template)); + navigate(templateRoute({ namespace, templateName: name })); + }, + [navigate, templateRoute], + ); if (loading) { return ; @@ -66,16 +89,41 @@ export const TemplateGroups = (props: TemplateGroupsProps) => { return ( <> - {groups.map(({ title, filter }, index) => ( - - filter(e), - )} - title={title} - components={{ CardComponent: TemplateCardComponent }} - /> - ))} + {groups.map(({ title, filter }, index) => { + const templates = entities + .filter((e): e is TemplateEntityV1beta3 => filter(e)) + .map(template => { + const { kind, namespace, name } = parseEntityRef( + stringifyEntityRef(template), + ); + const additionalLinks = + template.metadata.annotations?.['backstage.io/techdocs-ref'] && + viewTechDocsLink + ? [ + { + icon: app.getSystemIcon('docs') ?? DocsIcon, + text: 'View TechDocs', + url: viewTechDocsLink({ kind, namespace, name }), + }, + ] + : []; + + return { + template, + additionalLinks, + }; + }); + + return ( + + ); + })} ); }; diff --git a/plugins/scaffolder/src/next/TemplateListPage/TemplateListPage.test.tsx b/plugins/scaffolder/src/next/TemplateListPage/TemplateListPage.test.tsx index 16beeabd32..41e7897819 100644 --- a/plugins/scaffolder/src/next/TemplateListPage/TemplateListPage.test.tsx +++ b/plugins/scaffolder/src/next/TemplateListPage/TemplateListPage.test.tsx @@ -25,7 +25,7 @@ import { TestApiProvider, } from '@backstage/test-utils'; import React from 'react'; -import { nextRouteRef } from '@backstage/plugin-scaffolder-react'; +import { nextRouteRef } from '../routes'; import { TemplateListPage } from './TemplateListPage'; describe('TemplateListPage', () => { diff --git a/plugins/scaffolder/src/next/TemplateListPage/TemplateListPage.tsx b/plugins/scaffolder/src/next/TemplateListPage/TemplateListPage.tsx index bb77ed6479..4eae84b866 100644 --- a/plugins/scaffolder/src/next/TemplateListPage/TemplateListPage.tsx +++ b/plugins/scaffolder/src/next/TemplateListPage/TemplateListPage.tsx @@ -35,8 +35,8 @@ import { import { CategoryPicker } from './CategoryPicker'; import { RegisterExistingButton } from './RegisterExistingButton'; import { useRouteRef } from '@backstage/core-plugin-api'; -import { registerComponentRouteRef } from '@backstage/plugin-scaffolder-react'; import { TemplateGroupFilter, TemplateGroups } from './TemplateGroups'; +import { registerComponentRouteRef } from '../../routes'; export type TemplateListPageProps = { TemplateCardComponent?: React.ComponentType<{ diff --git a/plugins/scaffolder/src/next/TemplateWizardPage/TemplateWizardPage.test.tsx b/plugins/scaffolder/src/next/TemplateWizardPage/TemplateWizardPage.test.tsx index 52b6451862..469354e75f 100644 --- a/plugins/scaffolder/src/next/TemplateWizardPage/TemplateWizardPage.test.tsx +++ b/plugins/scaffolder/src/next/TemplateWizardPage/TemplateWizardPage.test.tsx @@ -23,12 +23,12 @@ import { import { act, fireEvent } from '@testing-library/react'; import React from 'react'; import { - nextRouteRef, - rootRouteRef, ScaffolderApi, scaffolderApiRef, } from '@backstage/plugin-scaffolder-react'; import { TemplateWizardPage } from './TemplateWizardPage'; +import { rootRouteRef } from '../../routes'; +import { nextRouteRef } from '../routes'; jest.mock('react-router-dom', () => { return { diff --git a/plugins/scaffolder/src/next/TemplateWizardPage/TemplateWizardPage.tsx b/plugins/scaffolder/src/next/TemplateWizardPage/TemplateWizardPage.tsx index e3717befdb..e446f781a2 100644 --- a/plugins/scaffolder/src/next/TemplateWizardPage/TemplateWizardPage.tsx +++ b/plugins/scaffolder/src/next/TemplateWizardPage/TemplateWizardPage.tsx @@ -36,15 +36,14 @@ import useAsync from 'react-use/lib/useAsync'; import { makeStyles } from '@material-ui/core'; import { BackstageTheme } from '@backstage/theme'; import { - nextRouteRef, - scaffolderTaskRouteRef, - selectedTemplateRouteRef, Stepper, NextFieldExtensionOptions, SecretsContext, } from '@backstage/plugin-scaffolder-react'; import { JsonValue } from '@backstage/types'; import { FormProps } from '../types'; +import { nextRouteRef } from '../routes'; +import { scaffolderTaskRouteRef, selectedTemplateRouteRef } from '../../routes'; type TemplateWizardPageProps = { customFieldExtensions: NextFieldExtensionOptions[]; diff --git a/plugins/scaffolder/src/next/index.ts b/plugins/scaffolder/src/next/index.ts index 6cef3eaa03..1ca9096459 100644 --- a/plugins/scaffolder/src/next/index.ts +++ b/plugins/scaffolder/src/next/index.ts @@ -17,3 +17,4 @@ export * from './Router'; export * from './TemplateListPage'; export * from './TemplateWizardPage'; export * from './types'; +export * from './routes'; diff --git a/plugins/scaffolder-react/src/next/routes.ts b/plugins/scaffolder/src/next/routes.ts similarity index 100% rename from plugins/scaffolder-react/src/next/routes.ts rename to plugins/scaffolder/src/next/routes.ts diff --git a/plugins/scaffolder/src/plugin.tsx b/plugins/scaffolder/src/plugin.tsx index 5bbe51dd2d..be9e14a92b 100644 --- a/plugins/scaffolder/src/plugin.tsx +++ b/plugins/scaffolder/src/plugin.tsx @@ -16,10 +16,6 @@ import { scmIntegrationsApiRef } from '@backstage/integration-react'; import { - nextRouteRef, - registerComponentRouteRef, - rootRouteRef, - viewTechDocRouteRef, createScaffolderFieldExtension, scaffolderApiRef, } from '@backstage/plugin-scaffolder-react'; @@ -58,6 +54,12 @@ import { EntityTagsPicker, EntityTagsPickerSchema, } from './components/fields/EntityTagsPicker/EntityTagsPicker'; +import { + registerComponentRouteRef, + rootRouteRef, + viewTechDocRouteRef, +} from './routes'; +import { nextRouteRef } from './next'; /** * The main plugin export for the scaffolder. diff --git a/plugins/scaffolder-react/src/routes.ts b/plugins/scaffolder/src/routes.ts similarity index 100% rename from plugins/scaffolder-react/src/routes.ts rename to plugins/scaffolder/src/routes.ts From 765888aa5e09c124ef3de6556c97426a3744b8d8 Mon Sep 17 00:00:00 2001 From: blam Date: Wed, 4 Jan 2023 23:27:51 +0100 Subject: [PATCH 17/35] chore: fixing onSelected tests Signed-off-by: blam --- .../TemplateGroup/TemplateGroup.test.tsx | 123 +++++++++++------- 1 file changed, 78 insertions(+), 45 deletions(-) diff --git a/plugins/scaffolder-react/src/next/components/TemplateGroup/TemplateGroup.test.tsx b/plugins/scaffolder-react/src/next/components/TemplateGroup/TemplateGroup.test.tsx index 63c06e778b..02756839c9 100644 --- a/plugins/scaffolder-react/src/next/components/TemplateGroup/TemplateGroup.test.tsx +++ b/plugins/scaffolder-react/src/next/components/TemplateGroup/TemplateGroup.test.tsx @@ -23,7 +23,9 @@ import { TemplateEntityV1beta3 } from '@backstage/plugin-scaffolder-common'; describe('TemplateGroup', () => { it('should return a message when no templates are passed in', async () => { - const { getByText } = render(); + const { getByText } = render( + , + ); expect( getByText(/No templates found that match your filter/), @@ -31,36 +33,47 @@ describe('TemplateGroup', () => { }); it('should render a card for each template with the template being passed as a prop', () => { - const mockTemplates: TemplateEntityV1beta3[] = [ + const mockOnSelected = jest.fn(); + const mockTemplates: { template: TemplateEntityV1beta3 }[] = [ { - apiVersion: 'scaffolder.backstage.io/v1beta3', - kind: 'Template', - metadata: { name: 'test' }, - spec: { - parameters: [], - steps: [], - type: 'website', + template: { + apiVersion: 'scaffolder.backstage.io/v1beta3', + kind: 'Template', + metadata: { name: 'test' }, + spec: { + parameters: [], + steps: [], + type: 'website', + }, }, }, { - apiVersion: 'scaffolder.backstage.io/v1beta3', - kind: 'Template', - metadata: { name: 'test2' }, - spec: { - parameters: [], - steps: [], - type: 'service', + template: { + apiVersion: 'scaffolder.backstage.io/v1beta3', + kind: 'Template', + metadata: { name: 'test2' }, + spec: { + parameters: [], + steps: [], + type: 'service', + }, }, }, ]; - render(); + render( + , + ); expect(TemplateCard).toHaveBeenCalledTimes(2); - for (const template of mockTemplates) { + for (const { template } of mockTemplates) { expect(TemplateCard).toHaveBeenCalledWith( - expect.objectContaining({ template }), + expect.objectContaining({ template, onSelected: mockOnSelected }), {}, ); } @@ -68,32 +81,37 @@ describe('TemplateGroup', () => { it('should use the passed in TemplateCard prop to render the template card', () => { const mockTemplateCardComponent = jest.fn(() => null); - - const mockTemplates: TemplateEntityV1beta3[] = [ + const mockOnSelected = jest.fn(); + const mockTemplates: { template: TemplateEntityV1beta3 }[] = [ { - apiVersion: 'scaffolder.backstage.io/v1beta3', - kind: 'Template', - metadata: { name: 'test' }, - spec: { - parameters: [], - steps: [], - type: 'website', + template: { + apiVersion: 'scaffolder.backstage.io/v1beta3', + kind: 'Template', + metadata: { name: 'test' }, + spec: { + parameters: [], + steps: [], + type: 'website', + }, }, }, { - apiVersion: 'scaffolder.backstage.io/v1beta3', - kind: 'Template', - metadata: { name: 'test2' }, - spec: { - parameters: [], - steps: [], - type: 'service', + template: { + apiVersion: 'scaffolder.backstage.io/v1beta3', + kind: 'Template', + metadata: { name: 'test2' }, + spec: { + parameters: [], + steps: [], + type: 'service', + }, }, }, ]; render( { expect(mockTemplateCardComponent).toHaveBeenCalledTimes(2); - for (const template of mockTemplates) { + for (const { template } of mockTemplates) { expect(mockTemplateCardComponent).toHaveBeenCalledWith( - expect.objectContaining({ template }), + expect.objectContaining({ + onSelected: mockOnSelected, + template, + }), {}, ); } }); it('should render the title when no templates passed', () => { - const { getByText } = render(); + const { getByText } = render( + , + ); expect(getByText('Test')).toBeInTheDocument(); }); it('should render the title when there are templates in the list', () => { - const mockTemplates: TemplateEntityV1beta3[] = [ + const mockTemplates: { template: TemplateEntityV1beta3 }[] = [ { - apiVersion: 'scaffolder.backstage.io/v1beta3', - kind: 'Template', - metadata: { name: 'test' }, - spec: { parameters: [], steps: [], type: 'website' }, + template: { + apiVersion: 'scaffolder.backstage.io/v1beta3', + kind: 'Template', + metadata: { name: 'test' }, + spec: { parameters: [], steps: [], type: 'website' }, + }, }, ]; const { getByText } = render( - , + , ); expect(getByText('Test')).toBeInTheDocument(); @@ -135,7 +164,11 @@ describe('TemplateGroup', () => { it('should allow for passing through a user given title component', () => { const TitleComponent =

Im a custom header

; const { getByText } = render( - , + , ); expect(getByText('Im a custom header')).toBeInTheDocument(); From 34a8a2c73b8a77920be4c2069520fea9979f1012 Mon Sep 17 00:00:00 2001 From: blam Date: Thu, 5 Jan 2023 09:39:25 +0100 Subject: [PATCH 18/35] chore: fixing package outline Signed-off-by: blam --- plugins/scaffolder-react/README.md | 2 -- plugins/scaffolder-react/package.json | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/plugins/scaffolder-react/README.md b/plugins/scaffolder-react/README.md index 8e93bff28a..1db37d5b23 100644 --- a/plugins/scaffolder-react/README.md +++ b/plugins/scaffolder-react/README.md @@ -1,7 +1,5 @@ # Scaffolder React -WORK IN PROGRESS - This is shared code of the frontend part of the default Scaffolder plugin. It will implement the core API for working with the Scaffolder, and diff --git a/plugins/scaffolder-react/package.json b/plugins/scaffolder-react/package.json index b115437e33..2a841a7e8b 100644 --- a/plugins/scaffolder-react/package.json +++ b/plugins/scaffolder-react/package.json @@ -1,7 +1,7 @@ { "name": "@backstage/plugin-scaffolder-react", "description": "A frontend library that helps other Backstage plugins interact with the Scaffolder", - "version": "1.0.0", + "version": "0.0.0", "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", From 7e7575409e76ecd5a03ececcbfe869255bf07f8c Mon Sep 17 00:00:00 2001 From: blam Date: Thu, 5 Jan 2023 09:52:40 +0100 Subject: [PATCH 19/35] chore: hook to get the field extensions Signed-off-by: blam --- .changeset/kind-pianos-burn.md | 4 +- plugins/scaffolder-react/src/api/ref.ts | 11 ++++-- .../scaffolder-react/src/extensions/index.tsx | 12 +----- .../scaffolder-react/src/extensions/keys.ts | 21 ++++++++++ plugins/scaffolder-react/src/hooks/index.ts | 17 +++++++++ .../src/hooks/useCustomFieldExtensions.ts | 38 +++++++++++++++++++ plugins/scaffolder-react/src/index.ts | 1 + plugins/scaffolder/src/components/Router.tsx | 16 ++------ plugins/scaffolder/src/next/Router/Router.tsx | 19 +--------- 9 files changed, 93 insertions(+), 46 deletions(-) create mode 100644 plugins/scaffolder-react/src/extensions/keys.ts create mode 100644 plugins/scaffolder-react/src/hooks/index.ts create mode 100644 plugins/scaffolder-react/src/hooks/useCustomFieldExtensions.ts diff --git a/.changeset/kind-pianos-burn.md b/.changeset/kind-pianos-burn.md index 078ab6846e..1fb09aeb83 100644 --- a/.changeset/kind-pianos-burn.md +++ b/.changeset/kind-pianos-burn.md @@ -1,5 +1,5 @@ --- -'@backstage/plugin-scaffolder-react': patch +'@backstage/plugin-scaffolder-react': major --- -Re-home some of the common types, components, hooks and `(route|api)Ref`'s for the `@backstage/plugin-scaffolder` to this package for easy re-use across things that want to interact with the `scaffolder`. +Re-home some of the common types, components, hooks and `scaffolderApiRef` for the `@backstage/plugin-scaffolder` to this package for easy re-use across things that want to interact with the `scaffolder`. diff --git a/plugins/scaffolder-react/src/api/ref.ts b/plugins/scaffolder-react/src/api/ref.ts index 3dee426b09..c4b7853556 100644 --- a/plugins/scaffolder-react/src/api/ref.ts +++ b/plugins/scaffolder-react/src/api/ref.ts @@ -16,8 +16,13 @@ import { createApiRef } from '@backstage/core-plugin-api'; import { ScaffolderApi } from './types'; +import { getOrCreateGlobalSingleton } from '@backstage/version-bridge'; /** @public */ -export const scaffolderApiRef = createApiRef({ - id: 'plugin.scaffolder.service', -}); +export const scaffolderApiRef = getOrCreateGlobalSingleton( + 'scaffolder:scaffolder-api-ref', + () => + createApiRef({ + id: 'plugin.scaffolder.service', + }), +); diff --git a/plugins/scaffolder-react/src/extensions/index.tsx b/plugins/scaffolder-react/src/extensions/index.tsx index 94bf8bad14..33442f6697 100644 --- a/plugins/scaffolder-react/src/extensions/index.tsx +++ b/plugins/scaffolder-react/src/extensions/index.tsx @@ -22,17 +22,7 @@ import { FieldExtensionComponentProps, } from './types'; import { Extension, attachComponentData } from '@backstage/core-plugin-api'; - -/** - * The key used to store the field extension data for the `` component - * @public - */ -export const FIELD_EXTENSION_WRAPPER_KEY = 'scaffolder.extensions.wrapper.v1'; -/** - * The key used to store the field extension data for any `` component - * @public - */ -export const FIELD_EXTENSION_KEY = 'scaffolder.extensions.field.v1'; +import { FIELD_EXTENSION_KEY, FIELD_EXTENSION_WRAPPER_KEY } from './keys'; /** * A type used to wrap up the FieldExtension to embed the ReturnValue and the InputProps diff --git a/plugins/scaffolder-react/src/extensions/keys.ts b/plugins/scaffolder-react/src/extensions/keys.ts new file mode 100644 index 0000000000..f035e9c1c2 --- /dev/null +++ b/plugins/scaffolder-react/src/extensions/keys.ts @@ -0,0 +1,21 @@ +/* + * 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 FIELD_EXTENSION_WRAPPER_KEY = 'scaffolder.extensions.wrapper.v1'; +/** + * The key used to store the field extension data for any `` component + */ +export const FIELD_EXTENSION_KEY = 'scaffolder.extensions.field.v1'; diff --git a/plugins/scaffolder-react/src/hooks/index.ts b/plugins/scaffolder-react/src/hooks/index.ts new file mode 100644 index 0000000000..022fe7c38c --- /dev/null +++ b/plugins/scaffolder-react/src/hooks/index.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 { useCustomFieldExtensions } from './useCustomFieldExtensions'; diff --git a/plugins/scaffolder-react/src/hooks/useCustomFieldExtensions.ts b/plugins/scaffolder-react/src/hooks/useCustomFieldExtensions.ts new file mode 100644 index 0000000000..15300956c6 --- /dev/null +++ b/plugins/scaffolder-react/src/hooks/useCustomFieldExtensions.ts @@ -0,0 +1,38 @@ +/* + * 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 { FieldExtensionOptions } from '../extensions'; +import { + FIELD_EXTENSION_KEY, + FIELD_EXTENSION_WRAPPER_KEY, +} from '../extensions/keys'; +import { NextFieldExtensionOptions } from '../next'; + +/** + * Hook that returns all custom field extensions from the current outlet. + * @public + */ +export const useCustomFieldExtensions = (outlet: React.ReactNode) => { + return useElementFilter(outlet, elements => + elements + .selectByComponentData({ + key: FIELD_EXTENSION_WRAPPER_KEY, + }) + .findComponentData({ + key: FIELD_EXTENSION_KEY, + }), + ); +}; diff --git a/plugins/scaffolder-react/src/index.ts b/plugins/scaffolder-react/src/index.ts index a2336a5ca5..0b053e6bf4 100644 --- a/plugins/scaffolder-react/src/index.ts +++ b/plugins/scaffolder-react/src/index.ts @@ -18,5 +18,6 @@ export * from './extensions'; export * from './types'; export * from './secrets'; export * from './api'; +export * from './hooks'; export * from './next'; diff --git a/plugins/scaffolder/src/components/Router.tsx b/plugins/scaffolder/src/components/Router.tsx index 287342007b..564e12bcae 100644 --- a/plugins/scaffolder/src/components/Router.tsx +++ b/plugins/scaffolder/src/components/Router.tsx @@ -30,10 +30,8 @@ import { useRouteRefParams, } from '@backstage/core-plugin-api'; import { - FIELD_EXTENSION_KEY, - FIELD_EXTENSION_WRAPPER_KEY, - FieldExtensionOptions, SecretsContextProvider, + useCustomFieldExtensions, } from '@backstage/plugin-scaffolder-react'; import { ListTasksPage } from './ListTasksPage'; import { LayoutOptions, LAYOUTS_KEY, LAYOUTS_WRAPPER_KEY } from '../layouts'; @@ -94,16 +92,7 @@ export const Router = (props: RouterProps) => { const outlet = useOutlet(); const TaskPageElement = TaskPageComponent ?? TaskPage; - const customFieldExtensions = useElementFilter(outlet, elements => - elements - .selectByComponentData({ - key: FIELD_EXTENSION_WRAPPER_KEY, - }) - .findComponentData({ - key: FIELD_EXTENSION_KEY, - }), - ); - + const customFieldExtensions = useCustomFieldExtensions(outlet); const fieldExtensions = [ ...customFieldExtensions, ...DEFAULT_SCAFFOLDER_FIELD_EXTENSIONS.filter( @@ -114,6 +103,7 @@ export const Router = (props: RouterProps) => { ), ]; + // todo(blam): this should also be moved to a hook in -react const customLayouts = useElementFilter(outlet, elements => elements .selectByComponentData({ diff --git a/plugins/scaffolder/src/next/Router/Router.tsx b/plugins/scaffolder/src/next/Router/Router.tsx index a9785e6aa6..33c2b40f01 100644 --- a/plugins/scaffolder/src/next/Router/Router.tsx +++ b/plugins/scaffolder/src/next/Router/Router.tsx @@ -18,14 +18,11 @@ import { Routes, Route, useOutlet } from 'react-router-dom'; import { TemplateListPage } from '../TemplateListPage'; import { TemplateWizardPage } from '../TemplateWizardPage'; import { - FIELD_EXTENSION_WRAPPER_KEY, - FIELD_EXTENSION_KEY, NextFieldExtensionOptions, - FieldExtensionOptions, SecretsContextProvider, + useCustomFieldExtensions, } from '@backstage/plugin-scaffolder-react'; -import { useElementFilter } from '@backstage/core-plugin-api'; import { TemplateEntityV1beta3 } from '@backstage/plugin-scaffolder-common'; import { TemplateGroupFilter } from '../TemplateListPage/TemplateGroups'; import { DEFAULT_SCAFFOLDER_FIELD_EXTENSIONS } from '../../extensions/default'; @@ -55,20 +52,8 @@ export type NextRouterProps = { */ export const Router = (props: PropsWithChildren) => { const { components: { TemplateCardComponent } = {} } = props; - const outlet = useOutlet() || props.children; - - // todo(blam): move this out into a `useFieldExtensions` hook exported by -react - const customFieldExtensions = useElementFilter(outlet, elements => - elements - .selectByComponentData({ - key: FIELD_EXTENSION_WRAPPER_KEY, - }) - .findComponentData({ - key: FIELD_EXTENSION_KEY, - }), - ); - + const customFieldExtensions = useCustomFieldExtensions(outlet); const fieldExtensions = [ ...customFieldExtensions, ...DEFAULT_SCAFFOLDER_FIELD_EXTENSIONS.filter( From 52d6ad7c0f9dec78386d6be939f1b85bd38f3eed Mon Sep 17 00:00:00 2001 From: blam Date: Thu, 5 Jan 2023 10:01:48 +0100 Subject: [PATCH 20/35] chore: moving some more re-usable logic to the `-react` package Signed-off-by: blam --- plugins/scaffolder-react/api-report.md | 91 ++++++------------- .../src/hooks/useCustomFieldExtensions.ts | 9 +- .../src/next/extensions/index.tsx | 3 +- plugins/scaffolder/src/components/Router.tsx | 3 +- plugins/scaffolder/src/next/Router/Router.tsx | 3 +- 5 files changed, 39 insertions(+), 70 deletions(-) diff --git a/plugins/scaffolder-react/api-report.md b/plugins/scaffolder-react/api-report.md index 79e461a2ec..1091f68d17 100644 --- a/plugins/scaffolder-react/api-report.md +++ b/plugins/scaffolder-react/api-report.md @@ -9,31 +9,25 @@ import { ApiHolder } from '@backstage/core-plugin-api'; import { ApiRef } from '@backstage/core-plugin-api'; import { Dispatch } from 'react'; import { Extension } from '@backstage/core-plugin-api'; -import { ExternalRouteRef } from '@backstage/core-plugin-api'; import { FieldProps } from '@rjsf/core'; import { FieldProps as FieldProps_2 } from '@rjsf/utils'; import { FieldValidation } from '@rjsf/core'; import { FieldValidation as FieldValidation_2 } from '@rjsf/utils'; import type { FormProps as FormProps_2 } from '@rjsf/core-v5'; +import { IconComponent } from '@backstage/core-plugin-api'; import { JsonObject } from '@backstage/types'; import { JSONSchema7 } from 'json-schema'; import { JsonValue } from '@backstage/types'; import { Observable } from '@backstage/types'; -import { PathParams } from '@backstage/core-plugin-api'; import { PropsWithChildren } from 'react'; import { default as React_2 } from 'react'; -import { RouteRef } from '@backstage/core-plugin-api'; import { SetStateAction } from 'react'; -import { SubRouteRef } from '@backstage/core-plugin-api'; import { TaskSpec } from '@backstage/plugin-scaffolder-common'; import { TaskStep } from '@backstage/plugin-scaffolder-common'; import { TemplateEntityV1beta3 } from '@backstage/plugin-scaffolder-common'; import { UIOptionsType } from '@rjsf/utils'; import { UiSchema } from '@rjsf/utils'; -// @public (undocumented) -export const actionsRouteRef: SubRouteRef; - // @alpha export const createFieldValidation: () => FieldValidation_2; @@ -68,21 +62,12 @@ export type CustomFieldValidator = ( }, ) => void | Promise; -// @public (undocumented) -export const editRouteRef: SubRouteRef; - // @alpha export const extractSchemaFromStep: (inputStep: JsonObject) => { uiSchema: UiSchema; schema: JsonObject; }; -// @public -export const FIELD_EXTENSION_KEY = 'scaffolder.extensions.field.v1'; - -// @public -export const FIELD_EXTENSION_WRAPPER_KEY = 'scaffolder.extensions.wrapper.v1'; - // @public export type FieldExtensionComponent<_TReturnValue, _TInputProps> = () => null; @@ -116,11 +101,6 @@ export type FormProps = Pick< 'transformErrors' | 'noHtml5Validate' >; -// @public @deprecated (undocumented) -export const legacySelectedTemplateRouteRef: SubRouteRef< - PathParams<'/templates/:templateName'> ->; - // @public export type ListActionsResponse = Array<{ id: string; @@ -178,19 +158,6 @@ export type NextFieldExtensionOptions< schema?: CustomFieldExtensionSchema; }; -// @alpha (undocumented) -export const nextRouteRef: RouteRef; - -// @alpha (undocumented) -export const nextScaffolderTaskRouteRef: SubRouteRef< - PathParams<'/tasks/:taskId'> ->; - -// @alpha (undocumented) -export const nextSelectedTemplateRouteRef: SubRouteRef< - PathParams<'/templates/:namespace/:templateName'> ->; - // @alpha export interface ParsedTemplateSchema { // (undocumented) @@ -205,9 +172,6 @@ export interface ParsedTemplateSchema { uiSchema: UiSchema; } -// @public (undocumented) -export const registerComponentRouteRef: ExternalRouteRef; - // @alpha export const ReviewState: (props: ReviewStateProps) => JSX.Element; @@ -217,9 +181,6 @@ export type ReviewStateProps = { formState: JsonObject; }; -// @public (undocumented) -export const rootRouteRef: RouteRef; - // @public export interface ScaffolderApi { // (undocumented) @@ -299,9 +260,6 @@ export interface ScaffolderGetIntegrationsListResponse { }[]; } -// @public (undocumented) -export const scaffolderListTaskRouteRef: SubRouteRef; - // @public (undocumented) export type ScaffolderOutputLink = { title?: string; @@ -350,9 +308,6 @@ export type ScaffolderTaskOutput = { [key: string]: unknown; }; -// @public (undocumented) -export const scaffolderTaskRouteRef: SubRouteRef>; - // @public export type ScaffolderTaskStatus = | 'open' @@ -383,11 +338,6 @@ export const SecretsContextProvider: ({ children, }: PropsWithChildren<{}>) => JSX.Element; -// @public (undocumented) -export const selectedTemplateRouteRef: SubRouteRef< - PathParams<'/templates/:namespace/:templateName'> ->; - // @alpha export const Stepper: (props: StepperProps) => JSX.Element; @@ -395,8 +345,9 @@ export const Stepper: (props: StepperProps) => JSX.Element; export type StepperProps = { manifest: TemplateParameterSchema; extensions: NextFieldExtensionOptions[]; - onComplete: (values: Record) => Promise; + templateName?: string; FormProps?: FormProps; + onComplete: (values: Record) => Promise; }; // @alpha @@ -405,7 +356,13 @@ export const TemplateCard: (props: TemplateCardProps) => JSX.Element; // @alpha export interface TemplateCardProps { // (undocumented) - deprecated?: boolean; + additionalLinks?: { + icon: IconComponent; + text: string; + url: string; + }[]; + // (undocumented) + onSelected?: (template: TemplateEntityV1beta3) => void; // (undocumented) template: TemplateEntityV1beta3; } @@ -420,7 +377,16 @@ export interface TemplateGroupProps { CardComponent?: React_2.ComponentType; }; // (undocumented) - templates: TemplateEntityV1beta3[]; + onSelected: (template: TemplateEntityV1beta3) => void; + // (undocumented) + templates: { + template: TemplateEntityV1beta3; + additionalLinks?: { + icon: IconComponent; + text: string; + url: string; + }[]; + }[]; // (undocumented) title: React_2.ReactNode; } @@ -436,6 +402,13 @@ export type TemplateParameterSchema = { }>; }; +// @public +export const useCustomFieldExtensions: < + TComponentDataType = FieldExtensionOptions, +>( + outlet: React.ReactNode, +) => TComponentDataType[]; + // @alpha export const useFormData: () => [ Record, @@ -450,15 +423,5 @@ export const useTemplateSchema: (manifest: TemplateParameterSchema) => { // @public export const useTemplateSecrets: () => ScaffolderUseTemplateSecrets; -// @public (undocumented) -export const viewTechDocRouteRef: ExternalRouteRef< - { - name: string; - kind: string; - namespace: string; - }, - true ->; - // (No @packageDocumentation comment for this package) ``` diff --git a/plugins/scaffolder-react/src/hooks/useCustomFieldExtensions.ts b/plugins/scaffolder-react/src/hooks/useCustomFieldExtensions.ts index 15300956c6..7e0aafd53f 100644 --- a/plugins/scaffolder-react/src/hooks/useCustomFieldExtensions.ts +++ b/plugins/scaffolder-react/src/hooks/useCustomFieldExtensions.ts @@ -19,19 +19,22 @@ import { FIELD_EXTENSION_KEY, FIELD_EXTENSION_WRAPPER_KEY, } from '../extensions/keys'; -import { NextFieldExtensionOptions } from '../next'; /** * Hook that returns all custom field extensions from the current outlet. * @public */ -export const useCustomFieldExtensions = (outlet: React.ReactNode) => { +export const useCustomFieldExtensions = < + TComponentDataType = FieldExtensionOptions, +>( + outlet: React.ReactNode, +) => { return useElementFilter(outlet, elements => elements .selectByComponentData({ key: FIELD_EXTENSION_WRAPPER_KEY, }) - .findComponentData({ + .findComponentData({ key: FIELD_EXTENSION_KEY, }), ); diff --git a/plugins/scaffolder-react/src/next/extensions/index.tsx b/plugins/scaffolder-react/src/next/extensions/index.tsx index d4161867e4..ee9b1cd326 100644 --- a/plugins/scaffolder-react/src/next/extensions/index.tsx +++ b/plugins/scaffolder-react/src/next/extensions/index.tsx @@ -21,7 +21,8 @@ import { } from './types'; import { Extension, attachComponentData } from '@backstage/core-plugin-api'; import { UIOptionsType } from '@rjsf/utils'; -import { FieldExtensionComponent, FIELD_EXTENSION_KEY } from '../../extensions'; +import { FieldExtensionComponent } from '../../extensions'; +import { FIELD_EXTENSION_KEY } from '../../extensions/keys'; /** * Method for creating field extensions that can be used in the scaffolder diff --git a/plugins/scaffolder/src/components/Router.tsx b/plugins/scaffolder/src/components/Router.tsx index 564e12bcae..6a2da406e0 100644 --- a/plugins/scaffolder/src/components/Router.tsx +++ b/plugins/scaffolder/src/components/Router.tsx @@ -30,6 +30,7 @@ import { useRouteRefParams, } from '@backstage/core-plugin-api'; import { + FieldExtensionOptions, SecretsContextProvider, useCustomFieldExtensions, } from '@backstage/plugin-scaffolder-react'; @@ -101,7 +102,7 @@ export const Router = (props: RouterProps) => { customFieldExtension => customFieldExtension.name === name, ), ), - ]; + ] as FieldExtensionOptions[]; // todo(blam): this should also be moved to a hook in -react const customLayouts = useElementFilter(outlet, elements => diff --git a/plugins/scaffolder/src/next/Router/Router.tsx b/plugins/scaffolder/src/next/Router/Router.tsx index 33c2b40f01..784e17dd55 100644 --- a/plugins/scaffolder/src/next/Router/Router.tsx +++ b/plugins/scaffolder/src/next/Router/Router.tsx @@ -53,7 +53,8 @@ export type NextRouterProps = { export const Router = (props: PropsWithChildren) => { const { components: { TemplateCardComponent } = {} } = props; const outlet = useOutlet() || props.children; - const customFieldExtensions = useCustomFieldExtensions(outlet); + const customFieldExtensions = + useCustomFieldExtensions(outlet); const fieldExtensions = [ ...customFieldExtensions, ...DEFAULT_SCAFFOLDER_FIELD_EXTENSIONS.filter( From fedc5074b1e53a961ca0d676577fcd5f3624f359 Mon Sep 17 00:00:00 2001 From: blam Date: Mon, 9 Jan 2023 14:08:45 +0100 Subject: [PATCH 21/35] chore: fixing the API reports Signed-off-by: blam --- plugins/scaffolder/api-report.md | 425 +++++++++++-------------------- 1 file changed, 145 insertions(+), 280 deletions(-) diff --git a/plugins/scaffolder/api-report.md b/plugins/scaffolder/api-report.md index bb45ad3b44..574184be15 100644 --- a/plugins/scaffolder/api-report.md +++ b/plugins/scaffolder/api-report.md @@ -9,79 +9,79 @@ import { ApiHolder } from '@backstage/core-plugin-api'; import { ApiRef } from '@backstage/core-plugin-api'; import { BackstagePlugin } from '@backstage/core-plugin-api'; import { ComponentType } from 'react'; +import { createScaffolderFieldExtension as createScaffolderFieldExtension_2 } from '@backstage/plugin-scaffolder-react'; +import { CustomFieldExtensionSchema as CustomFieldExtensionSchema_2 } from '@backstage/plugin-scaffolder-react'; +import { CustomFieldValidator as CustomFieldValidator_2 } from '@backstage/plugin-scaffolder-react'; import { DiscoveryApi } from '@backstage/core-plugin-api'; import { Entity } from '@backstage/catalog-model'; import { Extension } from '@backstage/core-plugin-api'; import { ExternalRouteRef } from '@backstage/core-plugin-api'; import { FetchApi } from '@backstage/core-plugin-api'; -import { FieldProps } from '@rjsf/core'; -import { FieldProps as FieldProps_2 } from '@rjsf/utils'; +import { FieldExtensionComponent as FieldExtensionComponent_2 } from '@backstage/plugin-scaffolder-react'; +import { FieldExtensionComponentProps as FieldExtensionComponentProps_2 } from '@backstage/plugin-scaffolder-react'; +import { FieldExtensionOptions as FieldExtensionOptions_2 } from '@backstage/plugin-scaffolder-react'; import { FieldValidation } from '@rjsf/core'; -import { FieldValidation as FieldValidation_2 } from '@rjsf/utils'; import type { FormProps as FormProps_2 } from '@rjsf/core'; import type { FormProps as FormProps_3 } from '@rjsf/core-v5'; import { IdentityApi } from '@backstage/core-plugin-api'; import { JsonObject } from '@backstage/types'; -import { JSONSchema7 } from 'json-schema'; -import { JsonValue } from '@backstage/types'; +import { ListActionsResponse as ListActionsResponse_2 } from '@backstage/plugin-scaffolder-react'; +import { LogEvent as LogEvent_2 } from '@backstage/plugin-scaffolder-react'; import { Observable } from '@backstage/types'; import { PathParams } from '@backstage/core-plugin-api'; import { PropsWithChildren } from 'react'; import { default as React_2 } from 'react'; +import { ReactNode } from 'react'; import { RouteRef } from '@backstage/core-plugin-api'; +import { ScaffolderApi as ScaffolderApi_2 } from '@backstage/plugin-scaffolder-react'; +import { ScaffolderDryRunOptions as ScaffolderDryRunOptions_2 } from '@backstage/plugin-scaffolder-react'; +import { ScaffolderDryRunResponse as ScaffolderDryRunResponse_2 } from '@backstage/plugin-scaffolder-react'; +import { ScaffolderGetIntegrationsListOptions as ScaffolderGetIntegrationsListOptions_2 } from '@backstage/plugin-scaffolder-react'; +import { ScaffolderGetIntegrationsListResponse as ScaffolderGetIntegrationsListResponse_2 } from '@backstage/plugin-scaffolder-react'; +import { ScaffolderOutputLink } from '@backstage/plugin-scaffolder-react'; +import { ScaffolderScaffoldOptions as ScaffolderScaffoldOptions_2 } from '@backstage/plugin-scaffolder-react'; +import { ScaffolderScaffoldResponse as ScaffolderScaffoldResponse_2 } from '@backstage/plugin-scaffolder-react'; +import { ScaffolderStreamLogsOptions as ScaffolderStreamLogsOptions_2 } from '@backstage/plugin-scaffolder-react'; +import { ScaffolderTask as ScaffolderTask_2 } from '@backstage/plugin-scaffolder-react'; +import { ScaffolderTaskOutput as ScaffolderTaskOutput_2 } from '@backstage/plugin-scaffolder-react'; +import { ScaffolderTaskStatus as ScaffolderTaskStatus_2 } from '@backstage/plugin-scaffolder-react'; +import { ScaffolderUseTemplateSecrets as ScaffolderUseTemplateSecrets_2 } from '@backstage/plugin-scaffolder-react'; import { ScmIntegrationRegistry } from '@backstage/integration'; import { SubRouteRef } from '@backstage/core-plugin-api'; -import { TaskSpec } from '@backstage/plugin-scaffolder-common'; -import { TaskStep } from '@backstage/plugin-scaffolder-common'; import { TemplateEntityV1beta3 } from '@backstage/plugin-scaffolder-common'; -import { UIOptionsType } from '@rjsf/utils'; +import { TemplateParameterSchema as TemplateParameterSchema_2 } from '@backstage/plugin-scaffolder-react'; import { UiSchema } from '@rjsf/utils'; import { z } from 'zod'; -// @alpha -export function createNextScaffolderFieldExtension< - TReturnValue = unknown, - TInputProps extends UIOptionsType = {}, ->( - options: NextFieldExtensionOptions, -): Extension>; +// @public (undocumented) +export const actionsRouteRef: SubRouteRef; -// @public -export function createScaffolderFieldExtension< - TReturnValue = unknown, - TInputProps = unknown, ->( - options: FieldExtensionOptions, -): Extension>; +// @public @deprecated (undocumented) +export const createScaffolderFieldExtension: typeof createScaffolderFieldExtension_2; // @public export function createScaffolderLayout( options: LayoutOptions, ): Extension>; -// @public -export type CustomFieldExtensionSchema = { - returnValue: JSONSchema7; - uiOptions?: JSONSchema7; -}; +// @public @deprecated (undocumented) +export type CustomFieldExtensionSchema = CustomFieldExtensionSchema_2; + +// @public @deprecated (undocumented) +export type CustomFieldValidator = + CustomFieldValidator_2; + +// @public (undocumented) +export const editRouteRef: SubRouteRef; // @public -export type CustomFieldValidator = ( - data: TFieldReturnValue, - field: FieldValidation, - context: { - apiHolder: ApiHolder; - }, -) => void | Promise; - -// @public -export const EntityNamePickerFieldExtension: FieldExtensionComponent< +export const EntityNamePickerFieldExtension: FieldExtensionComponent_2< string, {} >; // @public -export const EntityPickerFieldExtension: FieldExtensionComponent< +export const EntityPickerFieldExtension: FieldExtensionComponent_2< string, { defaultKind?: string | undefined; @@ -115,12 +115,12 @@ export type EntityPickerUiOptions = typeof EntityPickerFieldSchema.uiOptionsType; // @public -export const EntityTagsPickerFieldExtension: FieldExtensionComponent< +export const EntityTagsPickerFieldExtension: FieldExtensionComponent_2< string[], { - showCounts?: boolean | undefined; - kinds?: string[] | undefined; helperText?: string | undefined; + kinds?: string[] | undefined; + showCounts?: boolean | undefined; } >; @@ -128,9 +128,9 @@ export const EntityTagsPickerFieldExtension: FieldExtensionComponent< export const EntityTagsPickerFieldSchema: FieldSchema< string[], { - showCounts?: boolean | undefined; - kinds?: string[] | undefined; helperText?: string | undefined; + kinds?: string[] | undefined; + showCounts?: boolean | undefined; } >; @@ -138,44 +138,30 @@ export const EntityTagsPickerFieldSchema: FieldSchema< export type EntityTagsPickerUiOptions = typeof EntityTagsPickerFieldSchema.uiOptionsType; -// @public -export type FieldExtensionComponent<_TReturnValue, _TInputProps> = () => null; +// @public @deprecated (undocumented) +export type FieldExtensionComponent<_TReturnValue, _TInputProps> = + FieldExtensionComponent_2<_TReturnValue, _TInputProps>; -// @public -export interface FieldExtensionComponentProps< +// @public @deprecated (undocumented) +export type FieldExtensionComponentProps< TFieldReturnValue, TUiOptions extends {} = {}, -> extends FieldProps { - // (undocumented) - uiSchema: FieldProps['uiSchema'] & { - 'ui:options'?: TUiOptions; - }; -} +> = FieldExtensionComponentProps_2; -// @public -export type FieldExtensionOptions< - TFieldReturnValue = unknown, - TInputProps = unknown, -> = { - name: string; - component: ( - props: FieldExtensionComponentProps, - ) => JSX.Element | null; - validation?: CustomFieldValidator; - schema?: CustomFieldExtensionSchema; -}; +// @public @deprecated (undocumented) +export type FieldExtensionOptions = FieldExtensionOptions_2; // @public export interface FieldSchema { // (undocumented) - readonly schema: CustomFieldExtensionSchema; + readonly schema: CustomFieldExtensionSchema_2; // (undocumented) - readonly type: FieldExtensionComponentProps; + readonly type: FieldExtensionComponentProps_2; // (undocumented) readonly uiOptionsType: TUiOptions; } -// @alpha +// @alpha @deprecated export type FormProps = Pick< FormProps_3, 'transformErrors' | 'noHtml5Validate' @@ -195,28 +181,16 @@ export interface LayoutOptions

{ // @public export type LayoutTemplate = FormProps_2['ObjectFieldTemplate']; -// @public -export type ListActionsResponse = Array<{ - id: string; - description?: string; - schema?: { - input?: JSONSchema7; - output?: JSONSchema7; - }; -}>; +// @public @deprecated (undocumented) +export const legacySelectedTemplateRouteRef: SubRouteRef< + PathParams<'/templates/:templateName'> +>; -// @public -export type LogEvent = { - type: 'log' | 'completion'; - body: { - message: string; - stepId?: string; - status?: ScaffolderTaskStatus; - }; - createdAt: string; - id: string; - taskId: string; -}; +// @public @deprecated (undocumented) +export type ListActionsResponse = ListActionsResponse_2; + +// @public @deprecated (undocumented) +export type LogEvent = LogEvent_2; // @public export function makeFieldSchemaFromZod< @@ -232,40 +206,6 @@ export function makeFieldSchemaFromZod< : never >; -// @alpha -export type NextCustomFieldValidator = ( - data: TFieldReturnValue, - field: FieldValidation_2, - context: { - apiHolder: ApiHolder; - formData: JsonObject; - }, -) => void | Promise; - -// @alpha -export interface NextFieldExtensionComponentProps< - TFieldReturnValue, - TUiOptions = {}, -> extends PropsWithChildren> { - // (undocumented) - uiSchema?: UiSchema & { - 'ui:options'?: TUiOptions & UIOptionsType; - }; -} - -// @alpha -export type NextFieldExtensionOptions< - TFieldReturnValue = unknown, - TInputProps = unknown, -> = { - name: string; - component: ( - props: NextFieldExtensionComponentProps, - ) => JSX.Element | null; - validation?: NextCustomFieldValidator; - schema?: CustomFieldExtensionSchema; -}; - // @alpha (undocumented) export const nextRouteRef: RouteRef; @@ -286,13 +226,18 @@ export const NextScaffolderPage: ( props: PropsWithChildren, ) => JSX.Element; +// @alpha (undocumented) +export const nextScaffolderTaskRouteRef: SubRouteRef< + PathParams<'/tasks/:taskId'> +>; + // @alpha (undocumented) export const nextSelectedTemplateRouteRef: SubRouteRef< PathParams<'/templates/:namespace/:templateName'> >; // @public -export const OwnedEntityPickerFieldExtension: FieldExtensionComponent< +export const OwnedEntityPickerFieldExtension: FieldExtensionComponent_2< string, { defaultKind?: string | undefined; @@ -318,7 +263,7 @@ export type OwnedEntityPickerUiOptions = typeof OwnedEntityPickerFieldSchema.uiOptionsType; // @public -export const OwnerPickerFieldExtension: FieldExtensionComponent< +export const OwnerPickerFieldExtension: FieldExtensionComponent_2< string, { defaultNamespace?: string | false | undefined; @@ -348,6 +293,9 @@ export const OwnerPickerFieldSchema: FieldSchema< // @public export type OwnerPickerUiOptions = typeof OwnerPickerFieldSchema.uiOptionsType; +// @public (undocumented) +export const registerComponentRouteRef: ExternalRouteRef; + // @public export const repoPickerValidation: ( value: string, @@ -358,14 +306,14 @@ export const repoPickerValidation: ( ) => void; // @public -export const RepoUrlPickerFieldExtension: FieldExtensionComponent< +export const RepoUrlPickerFieldExtension: FieldExtensionComponent_2< string, { - allowedOwners?: string[] | undefined; + allowedHosts?: string[] | undefined; allowedOrganizations?: string[] | undefined; + allowedOwners?: string[] | undefined; allowedProjects?: string[] | undefined; allowedRepos?: string[] | undefined; - allowedHosts?: string[] | undefined; requestUserCredentials?: | { additionalScopes?: @@ -387,11 +335,11 @@ export const RepoUrlPickerFieldExtension: FieldExtensionComponent< export const RepoUrlPickerFieldSchema: FieldSchema< string, { - allowedOwners?: string[] | undefined; + allowedHosts?: string[] | undefined; allowedOrganizations?: string[] | undefined; + allowedOwners?: string[] | undefined; allowedProjects?: string[] | undefined; allowedRepos?: string[] | undefined; - allowedHosts?: string[] | undefined; requestUserCredentials?: | { additionalScopes?: @@ -457,37 +405,14 @@ export type RouterProps = { }; }; -// @public -export interface ScaffolderApi { - // (undocumented) - dryRun?(options: ScaffolderDryRunOptions): Promise; - // (undocumented) - getIntegrationsList( - options: ScaffolderGetIntegrationsListOptions, - ): Promise; - // (undocumented) - getTask(taskId: string): Promise; - // (undocumented) - getTemplateParameterSchema( - templateRef: string, - ): Promise; - listActions(): Promise; - // (undocumented) - listTasks?(options: { filterByOwnership: 'owned' | 'all' }): Promise<{ - tasks: ScaffolderTask[]; - }>; - scaffold( - options: ScaffolderScaffoldOptions, - ): Promise; - // (undocumented) - streamLogs(options: ScaffolderStreamLogsOptions): Observable; -} +// @public @deprecated (undocumented) +export type ScaffolderApi = ScaffolderApi_2; + +// @public @deprecated (undocumented) +export const scaffolderApiRef: ApiRef; // @public -export const scaffolderApiRef: ApiRef; - -// @public -export class ScaffolderClient implements ScaffolderApi { +export class ScaffolderClient implements ScaffolderApi_2 { constructor(options: { discoveryApi: DiscoveryApi; fetchApi: FetchApi; @@ -496,92 +421,60 @@ export class ScaffolderClient implements ScaffolderApi { useLongPollingLogs?: boolean; }); // (undocumented) - dryRun(options: ScaffolderDryRunOptions): Promise; + dryRun( + options: ScaffolderDryRunOptions_2, + ): Promise; // (undocumented) getIntegrationsList( - options: ScaffolderGetIntegrationsListOptions, - ): Promise; + options: ScaffolderGetIntegrationsListOptions_2, + ): Promise; // (undocumented) - getTask(taskId: string): Promise; + getTask(taskId: string): Promise; // (undocumented) getTemplateParameterSchema( templateRef: string, - ): Promise; + ): Promise; // (undocumented) - listActions(): Promise; + listActions(): Promise; // (undocumented) listTasks(options: { filterByOwnership: 'owned' | 'all' }): Promise<{ - tasks: ScaffolderTask[]; + tasks: ScaffolderTask_2[]; }>; + // (undocumented) scaffold( - options: ScaffolderScaffoldOptions, - ): Promise; + options: ScaffolderScaffoldOptions_2, + ): Promise; // (undocumented) - streamLogs(options: ScaffolderStreamLogsOptions): Observable; + streamLogs(options: ScaffolderStreamLogsOptions_2): Observable; } -// @public (undocumented) -export interface ScaffolderDryRunOptions { - // (undocumented) - directoryContents: { - path: string; - base64Content: string; - }[]; - // (undocumented) - secrets?: Record; - // (undocumented) - template: JsonValue; - // (undocumented) - values: JsonObject; -} +// @public @deprecated (undocumented) +export type ScaffolderDryRunOptions = ScaffolderDryRunOptions_2; -// @public (undocumented) -export interface ScaffolderDryRunResponse { - // (undocumented) - directoryContents: Array<{ - path: string; - base64Content: string; - executable: boolean; - }>; - // (undocumented) - log: Array>; - // (undocumented) - output: ScaffolderTaskOutput; - // (undocumented) - steps: TaskStep[]; -} +// @public @deprecated (undocumented) +export type ScaffolderDryRunResponse = ScaffolderDryRunResponse_2; -// @public -export const ScaffolderFieldExtensions: React_2.ComponentType< - React_2.PropsWithChildren<{}> ->; +// @public @deprecated (undocumented) +export const ScaffolderFieldExtensions: ComponentType<{ + children?: ReactNode; +}>; -// @public -export interface ScaffolderGetIntegrationsListOptions { - // (undocumented) - allowedHosts: string[]; -} +// @public @deprecated (undocumented) +export type ScaffolderGetIntegrationsListOptions = + ScaffolderGetIntegrationsListOptions_2; -// @public -export interface ScaffolderGetIntegrationsListResponse { - // (undocumented) - integrations: { - type: string; - title: string; - host: string; - }[]; -} +// @public @deprecated (undocumented) +export type ScaffolderGetIntegrationsListResponse = + ScaffolderGetIntegrationsListResponse_2; // @public export const ScaffolderLayouts: React.ComponentType; // @public (undocumented) -export type ScaffolderOutputLink = { - title?: string; - icon?: string; - url?: string; - entityRef?: string; -}; +export const scaffolderListTaskRouteRef: SubRouteRef; + +// @public @deprecated (undocumented) +export type ScaffolderOutputlink = ScaffolderOutputLink; // @public export const ScaffolderPage: (props: RouterProps) => JSX.Element; @@ -605,59 +498,29 @@ export const scaffolderPlugin: BackstagePlugin< {} >; -// @public -export interface ScaffolderScaffoldOptions { - // (undocumented) - secrets?: Record; - // (undocumented) - templateRef: string; - // (undocumented) - values: Record; -} +// @public @deprecated (undocumented) +export type ScaffolderScaffoldOptions = ScaffolderScaffoldOptions_2; -// @public -export interface ScaffolderScaffoldResponse { - // (undocumented) - taskId: string; -} +// @public @deprecated (undocumented) +export type ScaffolderScaffoldResponse = ScaffolderScaffoldResponse_2; -// @public -export interface ScaffolderStreamLogsOptions { - // (undocumented) - after?: number; - // (undocumented) - taskId: string; -} +// @public @deprecated (undocumented) +export type ScaffolderStreamLogsOptions = ScaffolderStreamLogsOptions_2; -// @public -export type ScaffolderTask = { - id: string; - spec: TaskSpec; - status: 'failed' | 'completed' | 'processing' | 'open' | 'cancelled'; - lastHeartbeatAt: string; - createdAt: string; -}; +// @public @deprecated (undocumented) +export type ScaffolderTask = ScaffolderTask_2; + +// @public @deprecated (undocumented) +export type ScaffolderTaskOutput = ScaffolderTaskOutput_2; // @public (undocumented) -export type ScaffolderTaskOutput = { - links?: ScaffolderOutputLink[]; -} & { - [key: string]: unknown; -}; +export const scaffolderTaskRouteRef: SubRouteRef>; -// @public -export type ScaffolderTaskStatus = - | 'open' - | 'processing' - | 'failed' - | 'completed' - | 'skipped'; +// @public @deprecated (undocumented) +export type ScaffolderTaskStatus = ScaffolderTaskStatus_2; -// @public -export interface ScaffolderUseTemplateSecrets { - // (undocumented) - setSecrets: (input: Record) => void; -} +// @public @deprecated (undocumented) +export type ScaffolderUseTemplateSecrets = ScaffolderUseTemplateSecrets_2; // @public (undocumented) export const selectedTemplateRouteRef: SubRouteRef< @@ -678,20 +541,22 @@ export type TemplateGroupFilter = { filter: (entity: Entity) => boolean; }; -// @public -export type TemplateParameterSchema = { - title: string; - description?: string; - steps: Array<{ - title: string; - description?: string; - schema: JsonObject; - }>; -}; +// @public @deprecated (undocumented) +export type TemplateParameterSchema = TemplateParameterSchema_2; // @public export const TemplateTypePicker: () => JSX.Element | null; -// @public -export const useTemplateSecrets: () => ScaffolderUseTemplateSecrets; +// @public @deprecated (undocumented) +export const useTemplateSecrets: () => ScaffolderUseTemplateSecrets_2; + +// @public (undocumented) +export const viewTechDocRouteRef: ExternalRouteRef< + { + name: string; + kind: string; + namespace: string; + }, + true +>; ``` From 3c72c0be914d867ccd6d0336865aa0fa554b2516 Mon Sep 17 00:00:00 2001 From: blam Date: Mon, 9 Jan 2023 14:55:05 +0100 Subject: [PATCH 22/35] chore: fix exporting the SecretsContext Signed-off-by: blam --- plugins/scaffolder-react/api-report.md | 11 ++++---- .../src/secrets/SecretsContext.test.tsx | 13 +++------- .../src/secrets/SecretsContext.tsx | 26 ++++++++++++------- plugins/scaffolder-react/src/secrets/index.ts | 1 - plugins/scaffolder/api-report.md | 8 +++--- .../components/TemplatePage/TemplatePage.tsx | 6 ++--- .../RepoUrlPicker/RepoUrlPicker.test.tsx | 10 ++++--- .../TemplateWizardPage/TemplateWizardPage.tsx | 10 ++++--- 8 files changed, 44 insertions(+), 41 deletions(-) diff --git a/plugins/scaffolder-react/api-report.md b/plugins/scaffolder-react/api-report.md index 1091f68d17..b124ad80f6 100644 --- a/plugins/scaffolder-react/api-report.md +++ b/plugins/scaffolder-react/api-report.md @@ -242,7 +242,9 @@ export interface ScaffolderDryRunResponse { } // @public -export const ScaffolderFieldExtensions: React_2.ComponentType; +export const ScaffolderFieldExtensions: React_2.ComponentType< + React_2.PropsWithChildren<{}> +>; // @public export interface ScaffolderGetIntegrationsListOptions { @@ -318,15 +320,12 @@ export type ScaffolderTaskStatus = // @public export interface ScaffolderUseTemplateSecrets { + // (undocumented) + secrets: Record; // (undocumented) setSecrets: (input: Record) => void; } -// @public -export const SecretsContext: React_2.Context< - SecretsContextContents | undefined ->; - // @public export type SecretsContextContents = { secrets: Record; diff --git a/plugins/scaffolder-react/src/secrets/SecretsContext.test.tsx b/plugins/scaffolder-react/src/secrets/SecretsContext.test.tsx index 3b84c074d7..593fbd908b 100644 --- a/plugins/scaffolder-react/src/secrets/SecretsContext.test.tsx +++ b/plugins/scaffolder-react/src/secrets/SecretsContext.test.tsx @@ -13,12 +13,8 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import React, { useContext } from 'react'; -import { - useTemplateSecrets, - SecretsContextProvider, - SecretsContext, -} from './SecretsContext'; +import React from 'react'; +import { useTemplateSecrets, SecretsContextProvider } from './SecretsContext'; import { renderHook, act } from '@testing-library/react-hooks'; describe('SecretsContext', () => { @@ -26,7 +22,6 @@ describe('SecretsContext', () => { const { result } = renderHook( () => ({ hook: useTemplateSecrets(), - context: useContext(SecretsContext), }), { wrapper: ({ children }) => ( @@ -34,10 +29,10 @@ describe('SecretsContext', () => { ), }, ); - expect(result.current.context?.secrets.foo).toEqual(undefined); + expect(result.current.hook?.secrets.foo).toEqual(undefined); act(() => result.current.hook.setSecrets({ foo: 'bar' })); - expect(result.current.context?.secrets.foo).toEqual('bar'); + expect(result.current.hook?.secrets.foo).toEqual('bar'); }); }); diff --git a/plugins/scaffolder-react/src/secrets/SecretsContext.tsx b/plugins/scaffolder-react/src/secrets/SecretsContext.tsx index 15548dfbc4..ca5ab1e671 100644 --- a/plugins/scaffolder-react/src/secrets/SecretsContext.tsx +++ b/plugins/scaffolder-react/src/secrets/SecretsContext.tsx @@ -13,16 +13,19 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +import { + createVersionedContext, + createVersionedValueMap, +} from '@backstage/version-bridge'; import React, { useState, useCallback, useContext, - createContext, PropsWithChildren, } from 'react'; /** - * The contents of the {@link SecretsContext}. + * The contents of the `SecretsContext` * @public */ export type SecretsContextContents = { @@ -32,11 +35,10 @@ export type SecretsContextContents = { /** * The context to hold the Secrets. - * @public */ -export const SecretsContext = createContext( - undefined, -); +const SecretsContext = createVersionedContext<{ + 1: SecretsContextContents; +}>('secrets-context'); /** * The Context Provider that holds the state for the secrets. @@ -46,7 +48,9 @@ export const SecretsContextProvider = ({ children }: PropsWithChildren<{}>) => { const [secrets, setSecrets] = useState>({}); return ( - + {children} ); @@ -58,6 +62,7 @@ export const SecretsContextProvider = ({ children }: PropsWithChildren<{}>) => { */ export interface ScaffolderUseTemplateSecrets { setSecrets: (input: Record) => void; + secrets: Record; } /** @@ -66,14 +71,15 @@ export interface ScaffolderUseTemplateSecrets { * @public */ export const useTemplateSecrets = (): ScaffolderUseTemplateSecrets => { - const value = useContext(SecretsContext); + const value = useContext(SecretsContext)?.atVersion(1); + if (!value) { throw new Error( 'useTemplateSecrets must be used within a SecretsContextProvider', ); } - const { setSecrets: updateSecrets } = value; + const { setSecrets: updateSecrets, secrets = {} } = value; const setSecrets = useCallback( (input: Record) => { @@ -82,5 +88,5 @@ export const useTemplateSecrets = (): ScaffolderUseTemplateSecrets => { [updateSecrets], ); - return { setSecrets }; + return { setSecrets, secrets }; }; diff --git a/plugins/scaffolder-react/src/secrets/index.ts b/plugins/scaffolder-react/src/secrets/index.ts index 90aa69158a..ca58455374 100644 --- a/plugins/scaffolder-react/src/secrets/index.ts +++ b/plugins/scaffolder-react/src/secrets/index.ts @@ -15,7 +15,6 @@ */ export { useTemplateSecrets, - SecretsContext, SecretsContextProvider, type ScaffolderUseTemplateSecrets, type SecretsContextContents, diff --git a/plugins/scaffolder/api-report.md b/plugins/scaffolder/api-report.md index 574184be15..cf26e41829 100644 --- a/plugins/scaffolder/api-report.md +++ b/plugins/scaffolder/api-report.md @@ -118,9 +118,9 @@ export type EntityPickerUiOptions = export const EntityTagsPickerFieldExtension: FieldExtensionComponent_2< string[], { - helperText?: string | undefined; - kinds?: string[] | undefined; showCounts?: boolean | undefined; + kinds?: string[] | undefined; + helperText?: string | undefined; } >; @@ -128,9 +128,9 @@ export const EntityTagsPickerFieldExtension: FieldExtensionComponent_2< export const EntityTagsPickerFieldSchema: FieldSchema< string[], { - helperText?: string | undefined; - kinds?: string[] | undefined; showCounts?: boolean | undefined; + kinds?: string[] | undefined; + helperText?: string | undefined; } >; diff --git a/plugins/scaffolder/src/components/TemplatePage/TemplatePage.tsx b/plugins/scaffolder/src/components/TemplatePage/TemplatePage.tsx index c1814bf7e9..0f484ff404 100644 --- a/plugins/scaffolder/src/components/TemplatePage/TemplatePage.tsx +++ b/plugins/scaffolder/src/components/TemplatePage/TemplatePage.tsx @@ -16,13 +16,13 @@ import { LinearProgress } from '@material-ui/core'; import { IChangeEvent } from '@rjsf/core'; import qs from 'qs'; -import React, { ComponentType, useCallback, useContext, useState } from 'react'; +import React, { ComponentType, useCallback, useState } from 'react'; import { Navigate, useNavigate } from 'react-router-dom'; import useAsync from 'react-use/lib/useAsync'; import { FieldExtensionOptions, - SecretsContext, scaffolderApiRef, + useTemplateSecrets, } from '@backstage/plugin-scaffolder-react'; import { MultistepJsonForm } from '../MultistepJsonForm'; import { createValidator } from './createValidator'; @@ -72,7 +72,7 @@ export const TemplatePage = ({ headerOptions, }: Props) => { const apiHolder = useApiHolder(); - const secretsContext = useContext(SecretsContext); + const secretsContext = useTemplateSecrets(); const errorApi = useApi(errorApiRef); const scaffolderApi = useApi(scaffolderApiRef); const { templateName, namespace } = useRouteRefParams( diff --git a/plugins/scaffolder/src/components/fields/RepoUrlPicker/RepoUrlPicker.test.tsx b/plugins/scaffolder/src/components/fields/RepoUrlPicker/RepoUrlPicker.test.tsx index 1cf8d91059..1edb4fb940 100644 --- a/plugins/scaffolder/src/components/fields/RepoUrlPicker/RepoUrlPicker.test.tsx +++ b/plugins/scaffolder/src/components/fields/RepoUrlPicker/RepoUrlPicker.test.tsx @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import React, { useContext } from 'react'; +import React from 'react'; import { RepoUrlPicker } from './RepoUrlPicker'; import Form from '@rjsf/core'; import { renderInTestApp, TestApiProvider } from '@backstage/test-utils'; @@ -26,9 +26,9 @@ import { import { SecretsContextProvider, - SecretsContext, scaffolderApiRef, ScaffolderApi, + useTemplateSecrets, } from '@backstage/plugin-scaffolder-react'; import { act, fireEvent } from '@testing-library/react'; @@ -119,8 +119,10 @@ describe('RepoUrlPicker', () => { describe('requestUserCredentials', () => { it('should call the scmAuthApi with the correct params', async () => { const SecretsComponent = () => { - const value = useContext(SecretsContext); - return

{JSON.stringify(value)}
; + const { secrets } = useTemplateSecrets(); + return ( +
{JSON.stringify({ secrets })}
+ ); }; const { getAllByRole, getByTestId } = await renderInTestApp( { const styles = useStyles(); const rootRef = useRouteRef(nextRouteRef); const taskRoute = useRouteRef(scaffolderTaskRouteRef); - const { secrets } = useContext(SecretsContext) ?? {}; + const { secrets } = useTemplateSecrets(); const scaffolderApi = useApi(scaffolderApiRef); const navigate = useNavigate(); const { templateName, namespace } = useRouteRefParams( From 50130d40918047edb8f24af791a2431377e49c63 Mon Sep 17 00:00:00 2001 From: blam Date: Mon, 9 Jan 2023 15:08:07 +0100 Subject: [PATCH 23/35] chore: renaming the hook for better understanding Signed-off-by: blam --- plugins/scaffolder-react/api-report.md | 2 +- .../scaffolder-react/src/next/components/Stepper/Stepper.tsx | 4 ++-- plugins/scaffolder-react/src/next/hooks/index.ts | 2 +- .../next/hooks/{useFormData.ts => useFormDataFromQuery.ts} | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) rename plugins/scaffolder-react/src/next/hooks/{useFormData.ts => useFormDataFromQuery.ts} (95%) diff --git a/plugins/scaffolder-react/api-report.md b/plugins/scaffolder-react/api-report.md index b124ad80f6..ddc2c91c41 100644 --- a/plugins/scaffolder-react/api-report.md +++ b/plugins/scaffolder-react/api-report.md @@ -409,7 +409,7 @@ export const useCustomFieldExtensions: < ) => TComponentDataType[]; // @alpha -export const useFormData: () => [ +export const useFormDataFromQuery: () => [ Record, Dispatch>>, ]; diff --git a/plugins/scaffolder-react/src/next/components/Stepper/Stepper.tsx b/plugins/scaffolder-react/src/next/components/Stepper/Stepper.tsx index 05345c34b5..37458fb402 100644 --- a/plugins/scaffolder-react/src/next/components/Stepper/Stepper.tsx +++ b/plugins/scaffolder-react/src/next/components/Stepper/Stepper.tsx @@ -32,7 +32,7 @@ import { useTemplateSchema } from '../../hooks/useTemplateSchema'; import { ReviewState } from '../ReviewState'; import validator from '@rjsf/validator-ajv6'; -import { useFormData } from '../../hooks/useFormData'; +import { useFormDataFromQuery } from '../../hooks'; import { FormProps } from '../../types'; const useStyles = makeStyles(theme => ({ @@ -77,7 +77,7 @@ export const Stepper = (props: StepperProps) => { const { steps } = useTemplateSchema(props.manifest); const apiHolder = useApiHolder(); const [activeStep, setActiveStep] = useState(0); - const [formState, setFormState] = useFormData(); + const [formState, setFormState] = useFormDataFromQuery(); const [errors, setErrors] = useState< undefined | Record diff --git a/plugins/scaffolder-react/src/next/hooks/index.ts b/plugins/scaffolder-react/src/next/hooks/index.ts index ba79bf0e9a..78a4d2a777 100644 --- a/plugins/scaffolder-react/src/next/hooks/index.ts +++ b/plugins/scaffolder-react/src/next/hooks/index.ts @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -export { useFormData } from './useFormData'; +export { useFormDataFromQuery } from './useFormDataFromQuery'; export { useTemplateSchema, type ParsedTemplateSchema, diff --git a/plugins/scaffolder-react/src/next/hooks/useFormData.ts b/plugins/scaffolder-react/src/next/hooks/useFormDataFromQuery.ts similarity index 95% rename from plugins/scaffolder-react/src/next/hooks/useFormData.ts rename to plugins/scaffolder-react/src/next/hooks/useFormDataFromQuery.ts index 0939630d1d..ad812480bd 100644 --- a/plugins/scaffolder-react/src/next/hooks/useFormData.ts +++ b/plugins/scaffolder-react/src/next/hooks/useFormDataFromQuery.ts @@ -21,7 +21,7 @@ import { useState } from 'react'; * This hook is used to get the formData from the query string. * @alpha */ -export const useFormData = () => { +export const useFormDataFromQuery = () => { return useState>(() => { const query = qs.parse(window.location.search, { ignoreQueryPrefix: true, From f59448367af45cd542c6c3e8ce43e9f7d39be3cb Mon Sep 17 00:00:00 2001 From: blam Date: Mon, 9 Jan 2023 16:17:08 +0100 Subject: [PATCH 24/35] chore: fix tests for the TemplateCard Signed-off-by: blam --- .../components/TemplateCard/TemplateCard.test.tsx | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/plugins/scaffolder-react/src/next/components/TemplateCard/TemplateCard.test.tsx b/plugins/scaffolder-react/src/next/components/TemplateCard/TemplateCard.test.tsx index f2e2cae8c6..2d5b203cfb 100644 --- a/plugins/scaffolder-react/src/next/components/TemplateCard/TemplateCard.test.tsx +++ b/plugins/scaffolder-react/src/next/components/TemplateCard/TemplateCard.test.tsx @@ -27,6 +27,7 @@ import { TemplateCard } from './TemplateCard'; import React from 'react'; import { TemplateEntityV1beta3 } from '@backstage/plugin-scaffolder-common'; import { RELATION_OWNED_BY } from '@backstage/catalog-model'; +import { fireEvent } from '@testing-library/react'; describe('TemplateCard', () => { it('should render the card title', async () => { @@ -192,7 +193,7 @@ describe('TemplateCard', () => { ); }); - it('should render the choose button to navigate to the selected template', async () => { + it('should call the onSelected handler when clicking the choose button', async () => { const mockTemplate: TemplateEntityV1beta3 = { apiVersion: 'scaffolder.backstage.io/v1beta3', kind: 'Template', @@ -202,6 +203,7 @@ describe('TemplateCard', () => { type: 'service', }, }; + const mockOnSelected = jest.fn(); const { getByRole } = await renderInTestApp( { ], ]} > - + , { mountedRoutes: { @@ -224,9 +226,9 @@ describe('TemplateCard', () => { ); expect(getByRole('button', { name: 'Choose' })).toBeInTheDocument(); - expect(getByRole('button', { name: 'Choose' })).toHaveAttribute( - 'href', - '/templates/default/bob', - ); + + fireEvent.click(getByRole('button', { name: 'Choose' })); + + expect(mockOnSelected).toHaveBeenCalledWith(mockTemplate); }); }); From 68aeea4ba5520f25d42bb3a4bba8e723e1ae66ff Mon Sep 17 00:00:00 2001 From: blam Date: Mon, 9 Jan 2023 16:45:43 +0100 Subject: [PATCH 25/35] chore: fixing the tests Signed-off-by: blam --- .../TemplatePage/TemplatePage.test.tsx | 30 ++++++++-- .../TemplateListPage/TemplateGroups.test.tsx | 58 +++++++++++++++---- .../TemplateWizardPage.test.tsx | 5 +- 3 files changed, 76 insertions(+), 17 deletions(-) diff --git a/plugins/scaffolder/src/components/TemplatePage/TemplatePage.test.tsx b/plugins/scaffolder/src/components/TemplatePage/TemplatePage.test.tsx index 5f43b54534..b4358146fd 100644 --- a/plugins/scaffolder/src/components/TemplatePage/TemplatePage.test.tsx +++ b/plugins/scaffolder/src/components/TemplatePage/TemplatePage.test.tsx @@ -25,6 +25,7 @@ import { Route, Routes } from 'react-router-dom'; import { scaffolderApiRef, ScaffolderApi, + SecretsContextProvider, } from '@backstage/plugin-scaffolder-react'; import { TemplatePage } from './TemplatePage'; import { @@ -127,7 +128,9 @@ describe('TemplatePage', () => { }); const rendered = await renderInTestApp( - + + + , { mountedRoutes: { @@ -148,7 +151,9 @@ describe('TemplatePage', () => { scaffolderApiMock.getTemplateParameterSchema.mockReturnValueOnce(promise); const rendered = await renderInTestApp( - + + + , { mountedRoutes: { @@ -189,7 +194,9 @@ describe('TemplatePage', () => { }); const { findByLabelText, findByText } = await renderInTestApp( - + + + , { mountedRoutes: { @@ -236,7 +243,14 @@ describe('TemplatePage', () => { const rendered = await renderInTestApp( - } /> + + + + } + /> This is root} /> , @@ -289,7 +303,9 @@ describe('TemplatePage', () => { const { findByText, findByLabelText, findAllByRole, findByRole } = await renderInTestApp( - + + + , { mountedRoutes: { @@ -333,7 +349,9 @@ describe('TemplatePage', () => { await renderInTestApp( - + + + , { mountedRoutes: { diff --git a/plugins/scaffolder/src/next/TemplateListPage/TemplateGroups.test.tsx b/plugins/scaffolder/src/next/TemplateListPage/TemplateGroups.test.tsx index 4abdd79463..f76c1a4ab6 100644 --- a/plugins/scaffolder/src/next/TemplateListPage/TemplateGroups.test.tsx +++ b/plugins/scaffolder/src/next/TemplateListPage/TemplateGroups.test.tsx @@ -23,21 +23,28 @@ jest.mock('@backstage/plugin-scaffolder-react', () => ({ })); import React from 'react'; -import { render } from '@testing-library/react'; import { useEntityList } from '@backstage/plugin-catalog-react'; import { TemplateGroups } from './TemplateGroups'; -import { TestApiProvider } from '@backstage/test-utils'; +import { renderInTestApp, TestApiProvider } from '@backstage/test-utils'; import { errorApiRef } from '@backstage/core-plugin-api'; import { TemplateGroup } from '@backstage/plugin-scaffolder-react'; +import { nextRouteRef } from '../routes'; describe('TemplateGroups', () => { + beforeEach(() => jest.clearAllMocks()); + it('should return progress if the hook is loading', async () => { (useEntityList as jest.Mock).mockReturnValue({ loading: true }); - const { findByTestId } = render( + const { findByTestId } = await renderInTestApp( , + { + mountedRoutes: { + '/next': nextRouteRef, + }, + }, ); expect(await findByTestId('progress')).toBeInTheDocument(); @@ -51,10 +58,15 @@ describe('TemplateGroups', () => { const errorApi = { post: jest.fn(), }; - render( + await renderInTestApp( , + { + mountedRoutes: { + '/next': nextRouteRef, + }, + }, ); expect(errorApi.post).toHaveBeenCalledWith(mockError); @@ -67,10 +79,15 @@ describe('TemplateGroups', () => { error: null, }); - const { findByText } = render( + const { findByText } = await renderInTestApp( , + { + mountedRoutes: { + '/next': nextRouteRef, + }, + }, ); expect(await findByText(/No templates found/)).toBeInTheDocument(); @@ -83,10 +100,15 @@ describe('TemplateGroups', () => { error: null, }); - const { findByText } = render( + const { findByText } = await renderInTestApp( , + { + mountedRoutes: { + '/next': nextRouteRef, + }, + }, ); expect(await findByText(/No templates found/)).toBeInTheDocument(); @@ -118,14 +140,23 @@ describe('TemplateGroups', () => { error: null, }); - render( + await renderInTestApp( true }]} /> , + { + mountedRoutes: { + '/next': nextRouteRef, + }, + }, ); expect(TemplateGroup).toHaveBeenCalledWith( - expect.objectContaining({ templates: mockEntities }), + expect.objectContaining({ + templates: mockEntities.map(template => + expect.objectContaining({ template }), + ), + }), {}, ); }); @@ -156,16 +187,23 @@ describe('TemplateGroups', () => { error: null, }); - render( + await renderInTestApp( e.metadata.name === 't1' }]} /> , + { + mountedRoutes: { + '/next': nextRouteRef, + }, + }, ); expect(TemplateGroup).toHaveBeenCalledWith( - expect.objectContaining({ templates: [mockEntities[0]] }), + expect.objectContaining({ + templates: [expect.objectContaining({ template: mockEntities[0] })], + }), {}, ); }); diff --git a/plugins/scaffolder/src/next/TemplateWizardPage/TemplateWizardPage.test.tsx b/plugins/scaffolder/src/next/TemplateWizardPage/TemplateWizardPage.test.tsx index 469354e75f..c4f9c75ceb 100644 --- a/plugins/scaffolder/src/next/TemplateWizardPage/TemplateWizardPage.test.tsx +++ b/plugins/scaffolder/src/next/TemplateWizardPage/TemplateWizardPage.test.tsx @@ -25,6 +25,7 @@ import React from 'react'; import { ScaffolderApi, scaffolderApiRef, + SecretsContextProvider, } from '@backstage/plugin-scaffolder-react'; import { TemplateWizardPage } from './TemplateWizardPage'; import { rootRouteRef } from '../../routes'; @@ -76,7 +77,9 @@ describe('TemplateWizardPage', () => { const { findByRole, getByRole } = await renderInTestApp( - , + + , + , { mountedRoutes: { From 0fbcdfd0d2567b5dda8f9925305da73a3572a424 Mon Sep 17 00:00:00 2001 From: blam Date: Mon, 9 Jan 2023 16:46:52 +0100 Subject: [PATCH 26/35] chore: fixing warning Signed-off-by: blam --- plugins/scaffolder/src/components/ActionsPage/ActionsPage.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/scaffolder/src/components/ActionsPage/ActionsPage.tsx b/plugins/scaffolder/src/components/ActionsPage/ActionsPage.tsx index 50ec86f2f5..c0957775c0 100644 --- a/plugins/scaffolder/src/components/ActionsPage/ActionsPage.tsx +++ b/plugins/scaffolder/src/components/ActionsPage/ActionsPage.tsx @@ -111,7 +111,7 @@ export const ActionsPage = () => { <> {[props.type].flat().map(type => ( - + ))} From 12b89a0c572568abed3f7bb56c72096aa71a10cb Mon Sep 17 00:00:00 2001 From: blam Date: Tue, 10 Jan 2023 11:01:42 +0100 Subject: [PATCH 27/35] chore: removing the routeRefs from the migration Signed-off-by: blam --- .changeset/wild-socks-breathe.md | 5 ----- 1 file changed, 5 deletions(-) diff --git a/.changeset/wild-socks-breathe.md b/.changeset/wild-socks-breathe.md index d96a5a33e3..c69af25749 100644 --- a/.changeset/wild-socks-breathe.md +++ b/.changeset/wild-socks-breathe.md @@ -7,8 +7,6 @@ ``` createScaffolderFieldExtension ScaffolderFieldExtensions - rootRouteRef - selectedTemplateRouteRef useTemplateSecrets scaffolderApiRef ScaffolderApi @@ -42,7 +40,4 @@ NextCustomFieldValidator NextFieldExtensionComponentProps NextFieldExtensionOptions - nextRouteRef - nextScaffolderTaskRouteRef - nextSelectedTemplateRouteRef ``` From 8b767113fef1eb1b367f219002193d7fb0b29128 Mon Sep 17 00:00:00 2001 From: blam Date: Tue, 10 Jan 2023 11:59:25 +0100 Subject: [PATCH 28/35] chore: deprecated routeRef exports Signed-off-by: blam --- plugins/scaffolder/api-report.md | 57 +++++----------------------- plugins/scaffolder/src/deprecated.ts | 7 ++++ plugins/scaffolder/src/index.ts | 5 +-- plugins/scaffolder/src/plugin.tsx | 14 ++++++- plugins/scaffolder/src/routes.ts | 11 ++---- 5 files changed, 33 insertions(+), 61 deletions(-) diff --git a/plugins/scaffolder/api-report.md b/plugins/scaffolder/api-report.md index cf26e41829..3706d869cd 100644 --- a/plugins/scaffolder/api-report.md +++ b/plugins/scaffolder/api-report.md @@ -53,9 +53,6 @@ import { TemplateParameterSchema as TemplateParameterSchema_2 } from '@backstage import { UiSchema } from '@rjsf/utils'; import { z } from 'zod'; -// @public (undocumented) -export const actionsRouteRef: SubRouteRef; - // @public @deprecated (undocumented) export const createScaffolderFieldExtension: typeof createScaffolderFieldExtension_2; @@ -71,9 +68,6 @@ export type CustomFieldExtensionSchema = CustomFieldExtensionSchema_2; export type CustomFieldValidator = CustomFieldValidator_2; -// @public (undocumented) -export const editRouteRef: SubRouteRef; - // @public export const EntityNamePickerFieldExtension: FieldExtensionComponent_2< string, @@ -181,11 +175,6 @@ export interface LayoutOptions

{ // @public export type LayoutTemplate = FormProps_2['ObjectFieldTemplate']; -// @public @deprecated (undocumented) -export const legacySelectedTemplateRouteRef: SubRouteRef< - PathParams<'/templates/:templateName'> ->; - // @public @deprecated (undocumented) export type ListActionsResponse = ListActionsResponse_2; @@ -206,9 +195,6 @@ export function makeFieldSchemaFromZod< : never >; -// @alpha (undocumented) -export const nextRouteRef: RouteRef; - // @alpha export type NextRouterProps = { components?: { @@ -226,16 +212,6 @@ export const NextScaffolderPage: ( props: PropsWithChildren, ) => JSX.Element; -// @alpha (undocumented) -export const nextScaffolderTaskRouteRef: SubRouteRef< - PathParams<'/tasks/:taskId'> ->; - -// @alpha (undocumented) -export const nextSelectedTemplateRouteRef: SubRouteRef< - PathParams<'/templates/:namespace/:templateName'> ->; - // @public export const OwnedEntityPickerFieldExtension: FieldExtensionComponent_2< string, @@ -293,9 +269,6 @@ export const OwnerPickerFieldSchema: FieldSchema< // @public export type OwnerPickerUiOptions = typeof OwnerPickerFieldSchema.uiOptionsType; -// @public (undocumented) -export const registerComponentRouteRef: ExternalRouteRef; - // @public export const repoPickerValidation: ( value: string, @@ -470,9 +443,6 @@ export type ScaffolderGetIntegrationsListResponse = // @public export const ScaffolderLayouts: React.ComponentType; -// @public (undocumented) -export const scaffolderListTaskRouteRef: SubRouteRef; - // @public @deprecated (undocumented) export type ScaffolderOutputlink = ScaffolderOutputLink; @@ -483,6 +453,15 @@ export const ScaffolderPage: (props: RouterProps) => JSX.Element; export const scaffolderPlugin: BackstagePlugin< { root: RouteRef; + selectedTemplate: SubRouteRef< + PathParams<'/templates/:namespace/:templateName'> + >; + ongoingTask: SubRouteRef>; + next: RouteRef; + nextSelectedTemplate: SubRouteRef< + PathParams<'/templates/:namespace/:templateName'> + >; + nextOngoingTask: SubRouteRef>; }, { registerComponent: ExternalRouteRef; @@ -513,20 +492,12 @@ export type ScaffolderTask = ScaffolderTask_2; // @public @deprecated (undocumented) export type ScaffolderTaskOutput = ScaffolderTaskOutput_2; -// @public (undocumented) -export const scaffolderTaskRouteRef: SubRouteRef>; - // @public @deprecated (undocumented) export type ScaffolderTaskStatus = ScaffolderTaskStatus_2; // @public @deprecated (undocumented) export type ScaffolderUseTemplateSecrets = ScaffolderUseTemplateSecrets_2; -// @public (undocumented) -export const selectedTemplateRouteRef: SubRouteRef< - PathParams<'/templates/:namespace/:templateName'> ->; - // @public export const TaskPage: ({ loadingText }: TaskPageProps) => JSX.Element; @@ -549,14 +520,4 @@ export const TemplateTypePicker: () => JSX.Element | null; // @public @deprecated (undocumented) export const useTemplateSecrets: () => ScaffolderUseTemplateSecrets_2; - -// @public (undocumented) -export const viewTechDocRouteRef: ExternalRouteRef< - { - name: string; - kind: string; - namespace: string; - }, - true ->; ``` diff --git a/plugins/scaffolder/src/deprecated.ts b/plugins/scaffolder/src/deprecated.ts index 41d3568c0b..72243641ed 100644 --- a/plugins/scaffolder/src/deprecated.ts +++ b/plugins/scaffolder/src/deprecated.ts @@ -48,6 +48,13 @@ import { type ScaffolderTaskStatus as ScaffolderTaskStatusTemp, } from '@backstage/plugin-scaffolder-react'; +import { rootRouteRef as rootRouteRefTemp } from './routes'; + +/** + * @public + * @deprecated use import from {@link @backstage/plugin-scaffolder#plugin.routes.root} instead. + */ +export const rootRouteRef = rootRouteRefTemp; /** * @public * @deprecated use import from {@link @backstage/plugin-scaffolder-react#createScaffolderFieldExtension} instead as this has now been moved. diff --git a/plugins/scaffolder/src/index.ts b/plugins/scaffolder/src/index.ts index b5dd5e5d0d..5f165111af 100644 --- a/plugins/scaffolder/src/index.ts +++ b/plugins/scaffolder/src/index.ts @@ -42,15 +42,12 @@ export { } from './plugin'; export * from './components'; -export * from './routes'; +export { rootRouteRef } from './routes'; export * from './deprecated'; /** next exports */ export { NextScaffolderPage } from './plugin'; export { - nextRouteRef, - nextSelectedTemplateRouteRef, - nextScaffolderTaskRouteRef, type TemplateGroupFilter, type NextRouterProps, type FormProps, diff --git a/plugins/scaffolder/src/plugin.tsx b/plugins/scaffolder/src/plugin.tsx index be9e14a92b..828bb6e25c 100644 --- a/plugins/scaffolder/src/plugin.tsx +++ b/plugins/scaffolder/src/plugin.tsx @@ -58,8 +58,14 @@ import { registerComponentRouteRef, rootRouteRef, viewTechDocRouteRef, + selectedTemplateRouteRef, + scaffolderTaskRouteRef, } from './routes'; -import { nextRouteRef } from './next'; +import { + nextRouteRef, + nextSelectedTemplateRouteRef, + nextScaffolderTaskRouteRef, +} from './next'; /** * The main plugin export for the scaffolder. @@ -87,6 +93,12 @@ export const scaffolderPlugin = createPlugin({ ], routes: { root: rootRouteRef, + selectedTemplate: selectedTemplateRouteRef, + ongoingTask: scaffolderTaskRouteRef, + /** next routes */ + next: nextRouteRef, + nextSelectedTemplate: nextSelectedTemplateRouteRef, + nextOngoingTask: nextScaffolderTaskRouteRef, }, externalRoutes: { registerComponent: registerComponentRouteRef, diff --git a/plugins/scaffolder/src/routes.ts b/plugins/scaffolder/src/routes.ts index 93c194360a..54b7605eb1 100644 --- a/plugins/scaffolder/src/routes.ts +++ b/plugins/scaffolder/src/routes.ts @@ -19,20 +19,20 @@ import { createSubRouteRef, } from '@backstage/core-plugin-api'; -/** @public */ export const registerComponentRouteRef = createExternalRouteRef({ id: 'register-component', optional: true, }); -/** @public */ export const viewTechDocRouteRef = createExternalRouteRef({ id: 'view-techdoc', optional: true, params: ['namespace', 'kind', 'name'], }); -/** @public */ +/** + * @public + */ export const rootRouteRef = createRouteRef({ id: 'scaffolder', }); @@ -47,35 +47,30 @@ export const legacySelectedTemplateRouteRef = createSubRouteRef({ path: '/templates/:templateName', }); -/** @public */ export const selectedTemplateRouteRef = createSubRouteRef({ id: 'scaffolder/selected-template', parent: rootRouteRef, path: '/templates/:namespace/:templateName', }); -/** @public */ export const scaffolderTaskRouteRef = createSubRouteRef({ id: 'scaffolder/task', parent: rootRouteRef, path: '/tasks/:taskId', }); -/** @public */ export const scaffolderListTaskRouteRef = createSubRouteRef({ id: 'scaffolder/list-tasks', parent: rootRouteRef, path: '/tasks', }); -/** @public */ export const actionsRouteRef = createSubRouteRef({ id: 'scaffolder/actions', parent: rootRouteRef, path: '/actions', }); -/** @public */ export const editRouteRef = createSubRouteRef({ id: 'scaffolder/edit', parent: rootRouteRef, From 1806e0c26e3e84209d189ff0b96e0cf61dbd8bcd Mon Sep 17 00:00:00 2001 From: blam Date: Tue, 10 Jan 2023 12:15:06 +0100 Subject: [PATCH 29/35] chore: deprecate the routeRef export and favour routes.root instead Signed-off-by: blam --- plugins/scaffolder/api-report.md | 2 +- plugins/scaffolder/src/deprecated.ts | 2 +- plugins/scaffolder/src/index.ts | 1 - plugins/scaffolder/src/plugin.tsx | 1 + 4 files changed, 3 insertions(+), 3 deletions(-) diff --git a/plugins/scaffolder/api-report.md b/plugins/scaffolder/api-report.md index 3706d869cd..dcfa78b4ee 100644 --- a/plugins/scaffolder/api-report.md +++ b/plugins/scaffolder/api-report.md @@ -348,7 +348,7 @@ export type ReviewStepProps = { }[]; }; -// @public (undocumented) +// @public @deprecated (undocumented) export const rootRouteRef: RouteRef; // @public diff --git a/plugins/scaffolder/src/deprecated.ts b/plugins/scaffolder/src/deprecated.ts index 72243641ed..201f7ac7d7 100644 --- a/plugins/scaffolder/src/deprecated.ts +++ b/plugins/scaffolder/src/deprecated.ts @@ -52,7 +52,7 @@ import { rootRouteRef as rootRouteRefTemp } from './routes'; /** * @public - * @deprecated use import from {@link @backstage/plugin-scaffolder#plugin.routes.root} instead. + * @deprecated use import from `{@link @backstage/plugin-scaffolder#scaffolderPlugin}.routes.root` instead. */ export const rootRouteRef = rootRouteRefTemp; /** diff --git a/plugins/scaffolder/src/index.ts b/plugins/scaffolder/src/index.ts index 5f165111af..b4e1bd99d4 100644 --- a/plugins/scaffolder/src/index.ts +++ b/plugins/scaffolder/src/index.ts @@ -42,7 +42,6 @@ export { } from './plugin'; export * from './components'; -export { rootRouteRef } from './routes'; export * from './deprecated'; /** next exports */ diff --git a/plugins/scaffolder/src/plugin.tsx b/plugins/scaffolder/src/plugin.tsx index 828bb6e25c..3d8ad5dd29 100644 --- a/plugins/scaffolder/src/plugin.tsx +++ b/plugins/scaffolder/src/plugin.tsx @@ -95,6 +95,7 @@ export const scaffolderPlugin = createPlugin({ root: rootRouteRef, selectedTemplate: selectedTemplateRouteRef, ongoingTask: scaffolderTaskRouteRef, + /** next routes */ next: nextRouteRef, nextSelectedTemplate: nextSelectedTemplateRouteRef, From fc73e5aee8f3d23514417fb85eb7dea288051442 Mon Sep 17 00:00:00 2001 From: blam Date: Tue, 10 Jan 2023 12:33:45 +0100 Subject: [PATCH 30/35] chore: removing some of the packages from this package now Signed-off-by: blam --- .changeset/wild-socks-breathe.md | 4 ++++ plugins/scaffolder/package.json | 3 --- yarn.lock | 3 --- 3 files changed, 4 insertions(+), 6 deletions(-) diff --git a/.changeset/wild-socks-breathe.md b/.changeset/wild-socks-breathe.md index c69af25749..78e570e118 100644 --- a/.changeset/wild-socks-breathe.md +++ b/.changeset/wild-socks-breathe.md @@ -32,6 +32,8 @@ ScaffolderTaskStatus ``` +- **Deprecation** - Deprecated the `rootRouteRef` export, this should now be used from `scaffolderPlugin.routes.root` + - The following `/alpha` types have removed from this package and moved to the `@backstage/plugin-scaffolder-react/alpha` package ``` @@ -41,3 +43,5 @@ NextFieldExtensionComponentProps NextFieldExtensionOptions ``` + +- The `/alpha` import for `nextSelectedTemplateRouteRef` has been moved to `scaffolderPlugin.routes.nextSelectedTemplate` diff --git a/plugins/scaffolder/package.json b/plugins/scaffolder/package.json index 839779acf6..8a93c8795f 100644 --- a/plugins/scaffolder/package.json +++ b/plugins/scaffolder/package.json @@ -58,9 +58,6 @@ "@rjsf/core": "^3.2.1", "@rjsf/core-v5": "npm:@rjsf/core@^5.0.0-beta.14", "@rjsf/material-ui": "^3.2.1", - "@rjsf/material-ui-v5": "npm:@rjsf/material-ui@^5.0.0-beta.14", - "@rjsf/utils": "^5.0.0-beta.14", - "@rjsf/validator-ajv6": "^5.0.0-beta.14", "@uiw/react-codemirror": "^4.9.3", "classnames": "^2.2.6", "git-url-parse": "^13.0.0", diff --git a/yarn.lock b/yarn.lock index 371902d90e..aa654f12a9 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7532,9 +7532,6 @@ __metadata: "@rjsf/core": ^3.2.1 "@rjsf/core-v5": "npm:@rjsf/core@^5.0.0-beta.14" "@rjsf/material-ui": ^3.2.1 - "@rjsf/material-ui-v5": "npm:@rjsf/material-ui@^5.0.0-beta.14" - "@rjsf/utils": ^5.0.0-beta.14 - "@rjsf/validator-ajv6": ^5.0.0-beta.14 "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 "@testing-library/react-hooks": ^8.0.0 From d1deceb410aed78283e3e760eae8838ffc87e9b5 Mon Sep 17 00:00:00 2001 From: blam Date: Tue, 10 Jan 2023 12:35:40 +0100 Subject: [PATCH 31/35] chore: setting initialstate Signed-off-by: blam --- .../src/next/components/Stepper/Stepper.tsx | 3 ++- .../src/next/hooks/useFormDataFromQuery.ts | 9 ++++++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/plugins/scaffolder-react/src/next/components/Stepper/Stepper.tsx b/plugins/scaffolder-react/src/next/components/Stepper/Stepper.tsx index 37458fb402..cde299da7e 100644 --- a/plugins/scaffolder-react/src/next/components/Stepper/Stepper.tsx +++ b/plugins/scaffolder-react/src/next/components/Stepper/Stepper.tsx @@ -59,6 +59,7 @@ export type StepperProps = { extensions: NextFieldExtensionOptions[]; templateName?: string; FormProps?: FormProps; + initialState?: Record; onComplete: (values: Record) => Promise; }; @@ -77,7 +78,7 @@ export const Stepper = (props: StepperProps) => { const { steps } = useTemplateSchema(props.manifest); const apiHolder = useApiHolder(); const [activeStep, setActiveStep] = useState(0); - const [formState, setFormState] = useFormDataFromQuery(); + const [formState, setFormState] = useFormDataFromQuery(props.initialState); const [errors, setErrors] = useState< undefined | Record diff --git a/plugins/scaffolder-react/src/next/hooks/useFormDataFromQuery.ts b/plugins/scaffolder-react/src/next/hooks/useFormDataFromQuery.ts index ad812480bd..966a8fe8f4 100644 --- a/plugins/scaffolder-react/src/next/hooks/useFormDataFromQuery.ts +++ b/plugins/scaffolder-react/src/next/hooks/useFormDataFromQuery.ts @@ -14,6 +14,7 @@ * limitations under the License. */ +import { JsonValue } from '@backstage/types'; import qs from 'qs'; import { useState } from 'react'; @@ -21,8 +22,14 @@ import { useState } from 'react'; * This hook is used to get the formData from the query string. * @alpha */ -export const useFormDataFromQuery = () => { +export const useFormDataFromQuery = ( + initialState?: Record, +) => { return useState>(() => { + if (initialState) { + return initialState; + } + const query = qs.parse(window.location.search, { ignoreQueryPrefix: true, }); From 3ea209aa12595611ae84013ce142301686057d03 Mon Sep 17 00:00:00 2001 From: blam Date: Tue, 10 Jan 2023 12:37:41 +0100 Subject: [PATCH 32/35] chore: fixing initialState in api-reports Signed-off-by: blam --- plugins/scaffolder-react/api-report.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/plugins/scaffolder-react/api-report.md b/plugins/scaffolder-react/api-report.md index ddc2c91c41..adffd29360 100644 --- a/plugins/scaffolder-react/api-report.md +++ b/plugins/scaffolder-react/api-report.md @@ -346,6 +346,7 @@ export type StepperProps = { extensions: NextFieldExtensionOptions[]; templateName?: string; FormProps?: FormProps; + initialState?: Record; onComplete: (values: Record) => Promise; }; @@ -409,10 +410,9 @@ export const useCustomFieldExtensions: < ) => TComponentDataType[]; // @alpha -export const useFormDataFromQuery: () => [ - Record, - Dispatch>>, -]; +export const useFormDataFromQuery: ( + initialState?: Record, +) => [Record, Dispatch>>]; // @alpha export const useTemplateSchema: (manifest: TemplateParameterSchema) => { From cacde27e15213d7c99551a6296ad57554b8a411a Mon Sep 17 00:00:00 2001 From: blam Date: Tue, 10 Jan 2023 13:28:04 +0100 Subject: [PATCH 33/35] chore: tidy up the api-reports with the `nextRouteRef` exports Signed-off-by: blam --- .changeset/wild-socks-breathe.md | 2 -- plugins/scaffolder/api-report.md | 18 +++++++++++++----- plugins/scaffolder/src/index.ts | 3 +++ plugins/scaffolder/src/plugin.tsx | 11 +---------- 4 files changed, 17 insertions(+), 17 deletions(-) diff --git a/.changeset/wild-socks-breathe.md b/.changeset/wild-socks-breathe.md index 78e570e118..7a4dff4c3b 100644 --- a/.changeset/wild-socks-breathe.md +++ b/.changeset/wild-socks-breathe.md @@ -43,5 +43,3 @@ NextFieldExtensionComponentProps NextFieldExtensionOptions ``` - -- The `/alpha` import for `nextSelectedTemplateRouteRef` has been moved to `scaffolderPlugin.routes.nextSelectedTemplate` diff --git a/plugins/scaffolder/api-report.md b/plugins/scaffolder/api-report.md index dcfa78b4ee..82a8dfd8d3 100644 --- a/plugins/scaffolder/api-report.md +++ b/plugins/scaffolder/api-report.md @@ -195,6 +195,9 @@ export function makeFieldSchemaFromZod< : never >; +// @alpha (undocumented) +export const nextRouteRef: RouteRef; + // @alpha export type NextRouterProps = { components?: { @@ -212,6 +215,16 @@ export const NextScaffolderPage: ( props: PropsWithChildren, ) => JSX.Element; +// @alpha (undocumented) +export const nextScaffolderTaskRouteRef: SubRouteRef< + PathParams<'/tasks/:taskId'> +>; + +// @alpha (undocumented) +export const nextSelectedTemplateRouteRef: SubRouteRef< + PathParams<'/templates/:namespace/:templateName'> +>; + // @public export const OwnedEntityPickerFieldExtension: FieldExtensionComponent_2< string, @@ -457,11 +470,6 @@ export const scaffolderPlugin: BackstagePlugin< PathParams<'/templates/:namespace/:templateName'> >; ongoingTask: SubRouteRef>; - next: RouteRef; - nextSelectedTemplate: SubRouteRef< - PathParams<'/templates/:namespace/:templateName'> - >; - nextOngoingTask: SubRouteRef>; }, { registerComponent: ExternalRouteRef; diff --git a/plugins/scaffolder/src/index.ts b/plugins/scaffolder/src/index.ts index b4e1bd99d4..7c99f8039b 100644 --- a/plugins/scaffolder/src/index.ts +++ b/plugins/scaffolder/src/index.ts @@ -47,6 +47,9 @@ export * from './deprecated'; /** next exports */ export { NextScaffolderPage } from './plugin'; export { + nextRouteRef, + nextScaffolderTaskRouteRef, + nextSelectedTemplateRouteRef, type TemplateGroupFilter, type NextRouterProps, type FormProps, diff --git a/plugins/scaffolder/src/plugin.tsx b/plugins/scaffolder/src/plugin.tsx index 3d8ad5dd29..f6801c6371 100644 --- a/plugins/scaffolder/src/plugin.tsx +++ b/plugins/scaffolder/src/plugin.tsx @@ -61,11 +61,7 @@ import { selectedTemplateRouteRef, scaffolderTaskRouteRef, } from './routes'; -import { - nextRouteRef, - nextSelectedTemplateRouteRef, - nextScaffolderTaskRouteRef, -} from './next'; +import { nextRouteRef } from './next'; /** * The main plugin export for the scaffolder. @@ -95,11 +91,6 @@ export const scaffolderPlugin = createPlugin({ root: rootRouteRef, selectedTemplate: selectedTemplateRouteRef, ongoingTask: scaffolderTaskRouteRef, - - /** next routes */ - next: nextRouteRef, - nextSelectedTemplate: nextSelectedTemplateRouteRef, - nextOngoingTask: nextScaffolderTaskRouteRef, }, externalRoutes: { registerComponent: registerComponentRouteRef, From 5d8250cbd3d97148979c1f5e1d32c6e73c27224d Mon Sep 17 00:00:00 2001 From: blam Date: Tue, 10 Jan 2023 13:45:02 +0100 Subject: [PATCH 34/35] chore: fix Signed-off-by: blam Signed-off-by: blam --- plugins/scaffolder/package.json | 1 + .../src/components/MultistepJsonForm/MultistepJsonForm.tsx | 7 +------ yarn.lock | 1 + 3 files changed, 3 insertions(+), 6 deletions(-) diff --git a/plugins/scaffolder/package.json b/plugins/scaffolder/package.json index 8a93c8795f..0a9f476f11 100644 --- a/plugins/scaffolder/package.json +++ b/plugins/scaffolder/package.json @@ -58,6 +58,7 @@ "@rjsf/core": "^3.2.1", "@rjsf/core-v5": "npm:@rjsf/core@^5.0.0-beta.14", "@rjsf/material-ui": "^3.2.1", + "@rjsf/utils": "^5.0.0-beta.14", "@uiw/react-codemirror": "^4.9.3", "classnames": "^2.2.6", "git-url-parse": "^13.0.0", diff --git a/plugins/scaffolder/src/components/MultistepJsonForm/MultistepJsonForm.tsx b/plugins/scaffolder/src/components/MultistepJsonForm/MultistepJsonForm.tsx index ed8471ec1e..3a1196bc0e 100644 --- a/plugins/scaffolder/src/components/MultistepJsonForm/MultistepJsonForm.tsx +++ b/plugins/scaffolder/src/components/MultistepJsonForm/MultistepJsonForm.tsx @@ -30,7 +30,6 @@ import { useApi, } from '@backstage/core-plugin-api'; import { FormProps, IChangeEvent, withTheme } from '@rjsf/core'; -import { UiSchema } from '@rjsf/utils'; import { Theme as MuiTheme } from '@rjsf/material-ui'; import React, { ComponentType, useState } from 'react'; import { transformSchemaToProps } from './schema'; @@ -68,11 +67,7 @@ export type MultistepJsonFormProps = { ReviewStepComponent?: ComponentType; }; -export function getSchemasFromSteps(steps: Step[]): { - uiSchema: UiSchema; - mergedSchema: JsonObject; - schema: JsonObject; -}[] { +export function getSchemasFromSteps(steps: Step[]) { return steps.map(({ schema }) => ({ mergedSchema: schema, ...extractSchemaFromStep(schema), diff --git a/yarn.lock b/yarn.lock index aa654f12a9..5e1c17cdba 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7532,6 +7532,7 @@ __metadata: "@rjsf/core": ^3.2.1 "@rjsf/core-v5": "npm:@rjsf/core@^5.0.0-beta.14" "@rjsf/material-ui": ^3.2.1 + "@rjsf/utils": ^5.0.0-beta.14 "@testing-library/jest-dom": ^5.10.1 "@testing-library/react": ^12.1.3 "@testing-library/react-hooks": ^8.0.0 From cc55b6ef6c729beb8b6e74407e4754d24ec1ea14 Mon Sep 17 00:00:00 2001 From: blam Date: Tue, 10 Jan 2023 14:25:31 +0100 Subject: [PATCH 35/35] chore: removing unused export from the api-surface Signed-off-by: blam --- plugins/scaffolder-react/api-report.md | 6 ------ plugins/scaffolder-react/src/secrets/SecretsContext.tsx | 3 +-- plugins/scaffolder-react/src/secrets/index.ts | 1 - 3 files changed, 1 insertion(+), 9 deletions(-) diff --git a/plugins/scaffolder-react/api-report.md b/plugins/scaffolder-react/api-report.md index d4dac82104..adc097775b 100644 --- a/plugins/scaffolder-react/api-report.md +++ b/plugins/scaffolder-react/api-report.md @@ -336,12 +336,6 @@ export interface ScaffolderUseTemplateSecrets { setSecrets: (input: Record) => void; } -// @public -export type SecretsContextContents = { - secrets: Record; - setSecrets: React_2.Dispatch>>; -}; - // @public export const SecretsContextProvider: ({ children, diff --git a/plugins/scaffolder-react/src/secrets/SecretsContext.tsx b/plugins/scaffolder-react/src/secrets/SecretsContext.tsx index ca5ab1e671..af5c2393cd 100644 --- a/plugins/scaffolder-react/src/secrets/SecretsContext.tsx +++ b/plugins/scaffolder-react/src/secrets/SecretsContext.tsx @@ -26,9 +26,8 @@ import React, { /** * The contents of the `SecretsContext` - * @public */ -export type SecretsContextContents = { +type SecretsContextContents = { secrets: Record; setSecrets: React.Dispatch>>; }; diff --git a/plugins/scaffolder-react/src/secrets/index.ts b/plugins/scaffolder-react/src/secrets/index.ts index ca58455374..0b8a09cd97 100644 --- a/plugins/scaffolder-react/src/secrets/index.ts +++ b/plugins/scaffolder-react/src/secrets/index.ts @@ -17,5 +17,4 @@ export { useTemplateSecrets, SecretsContextProvider, type ScaffolderUseTemplateSecrets, - type SecretsContextContents, } from './SecretsContext';