@backstage/plugin-scaffolder 1.28.0-next.1 → 1.28.0-next.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +23 -0
- package/dist/components/Router/Router.esm.js +4 -8
- package/dist/components/Router/Router.esm.js.map +1 -1
- package/dist/components/fields/RepoBranchPicker/GitHubRepoBranchPicker.esm.js +62 -0
- package/dist/components/fields/RepoBranchPicker/GitHubRepoBranchPicker.esm.js.map +1 -0
- package/dist/components/fields/RepoBranchPicker/RepoBranchPicker.esm.js +14 -1
- package/dist/components/fields/RepoBranchPicker/RepoBranchPicker.esm.js.map +1 -1
- package/dist/components/fields/RepoUrlPicker/GithubRepoPicker.esm.js +65 -11
- package/dist/components/fields/RepoUrlPicker/GithubRepoPicker.esm.js.map +1 -1
- package/dist/components/fields/RepoUrlPicker/RepoUrlPicker.esm.js +3 -3
- package/dist/components/fields/RepoUrlPicker/RepoUrlPicker.esm.js.map +1 -1
- package/dist/components/fields/RepoUrlPicker/utils.esm.js +1 -6
- package/dist/components/fields/RepoUrlPicker/utils.esm.js.map +1 -1
- package/package.json +13 -10
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,28 @@
|
|
|
1
1
|
# @backstage/plugin-scaffolder
|
|
2
2
|
|
|
3
|
+
## 1.28.0-next.2
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- eb3d91a: Use the custom error page if provided for displaying errors instead of the default error page
|
|
8
|
+
- fe44946: Fixed bug of passing wrong value to `onChange` handler when using `GitLab` autocomplete
|
|
9
|
+
- Updated dependencies
|
|
10
|
+
- @backstage/plugin-scaffolder-react@1.14.5-next.2
|
|
11
|
+
- @backstage/core-components@0.16.4-next.1
|
|
12
|
+
- @backstage/plugin-catalog-react@1.15.2-next.2
|
|
13
|
+
- @backstage/catalog-client@1.9.1
|
|
14
|
+
- @backstage/catalog-model@1.7.3
|
|
15
|
+
- @backstage/core-compat-api@0.3.6-next.2
|
|
16
|
+
- @backstage/core-plugin-api@1.10.4-next.0
|
|
17
|
+
- @backstage/errors@1.2.7
|
|
18
|
+
- @backstage/frontend-plugin-api@0.9.5-next.2
|
|
19
|
+
- @backstage/integration@1.16.1
|
|
20
|
+
- @backstage/integration-react@1.2.4-next.0
|
|
21
|
+
- @backstage/types@1.2.1
|
|
22
|
+
- @backstage/plugin-catalog-common@1.1.3
|
|
23
|
+
- @backstage/plugin-permission-react@0.4.31-next.0
|
|
24
|
+
- @backstage/plugin-scaffolder-common@1.5.9
|
|
25
|
+
|
|
3
26
|
## 1.28.0-next.1
|
|
4
27
|
|
|
5
28
|
### Minor Changes
|
|
@@ -3,7 +3,6 @@ import { useOutlet, Routes, Route } from 'react-router-dom';
|
|
|
3
3
|
import { useCustomFieldExtensions, useCustomLayouts, SecretsContextProvider } from '@backstage/plugin-scaffolder-react';
|
|
4
4
|
import { DEFAULT_SCAFFOLDER_FIELD_EXTENSIONS } from '../../extensions/default.esm.js';
|
|
5
5
|
import { selectedTemplateRouteRef, scaffolderTaskRouteRef, editRouteRef, customFieldsRouteRef, templateFormRouteRef, actionsRouteRef, scaffolderListTaskRouteRef, editorRouteRef } from '../../routes.esm.js';
|
|
6
|
-
import { ErrorPage } from '@backstage/core-components';
|
|
7
6
|
import { ActionsPage } from '../ActionsPage/ActionsPage.esm.js';
|
|
8
7
|
import { ListTasksPage } from '../ListTasksPage/ListTasksPage.esm.js';
|
|
9
8
|
import { TemplateListPage } from '../../alpha/components/TemplateListPage/TemplateListPage.esm.js';
|
|
@@ -15,6 +14,7 @@ import { TemplateIntroPage } from '../../alpha/components/TemplateEditorPage/Tem
|
|
|
15
14
|
import { CustomFieldsPage } from '../../alpha/components/TemplateEditorPage/CustomFieldsPage.esm.js';
|
|
16
15
|
import { RequirePermission } from '@backstage/plugin-permission-react';
|
|
17
16
|
import { taskReadPermission, templateManagementPermission } from '@backstage/plugin-scaffolder-common/alpha';
|
|
17
|
+
import { useApp } from '@backstage/core-plugin-api';
|
|
18
18
|
|
|
19
19
|
const Router = (props) => {
|
|
20
20
|
const {
|
|
@@ -29,6 +29,8 @@ const Router = (props) => {
|
|
|
29
29
|
} = props;
|
|
30
30
|
const outlet = useOutlet() || props.children;
|
|
31
31
|
const customFieldExtensions = useCustomFieldExtensions(outlet);
|
|
32
|
+
const app = useApp();
|
|
33
|
+
const { NotFoundErrorPage } = app.getComponents();
|
|
32
34
|
const fieldExtensions = [
|
|
33
35
|
...customFieldExtensions,
|
|
34
36
|
...DEFAULT_SCAFFOLDER_FIELD_EXTENSIONS.filter(
|
|
@@ -129,13 +131,7 @@ const Router = (props) => {
|
|
|
129
131
|
}
|
|
130
132
|
)))
|
|
131
133
|
}
|
|
132
|
-
), /* @__PURE__ */ React.createElement(
|
|
133
|
-
Route,
|
|
134
|
-
{
|
|
135
|
-
path: "*",
|
|
136
|
-
element: /* @__PURE__ */ React.createElement(ErrorPage, { status: "404", statusMessage: "Page not found" })
|
|
137
|
-
}
|
|
138
|
-
));
|
|
134
|
+
), /* @__PURE__ */ React.createElement(Route, { path: "*", element: /* @__PURE__ */ React.createElement(NotFoundErrorPage, null) }));
|
|
139
135
|
};
|
|
140
136
|
|
|
141
137
|
export { Router };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Router.esm.js","sources":["../../../src/components/Router/Router.tsx"],"sourcesContent":["/*\n * Copyright 2022 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport React, { PropsWithChildren } from 'react';\nimport { Routes, Route, useOutlet } from 'react-router-dom';\n\nimport {\n FieldExtensionOptions,\n FormProps,\n ReviewStepProps,\n TemplateGroupFilter,\n} from '@backstage/plugin-scaffolder-react';\nimport {\n ScaffolderTaskOutput,\n SecretsContextProvider,\n useCustomFieldExtensions,\n useCustomLayouts,\n} from '@backstage/plugin-scaffolder-react';\n\nimport { TemplateEntityV1beta3 } from '@backstage/plugin-scaffolder-common';\nimport { DEFAULT_SCAFFOLDER_FIELD_EXTENSIONS } from '../../extensions/default';\n\nimport {\n actionsRouteRef,\n editorRouteRef,\n customFieldsRouteRef,\n editRouteRef,\n scaffolderListTaskRouteRef,\n scaffolderTaskRouteRef,\n selectedTemplateRouteRef,\n templateFormRouteRef,\n} from '../../routes';\nimport { ErrorPage } from '@backstage/core-components';\n\nimport { ActionsPage } from '../../components/ActionsPage';\nimport { ListTasksPage } from '../../components/ListTasksPage';\n\nimport {\n TemplateListPageProps,\n TemplateWizardPageProps,\n} from '@backstage/plugin-scaffolder/alpha';\nimport { TemplateListPage, TemplateWizardPage } from '../../alpha/components';\nimport { OngoingTask } from '../OngoingTask';\nimport {\n TemplateFormPage,\n TemplateIntroPage,\n TemplateEditorPage,\n CustomFieldsPage,\n} from '../../alpha/components/TemplateEditorPage';\nimport { RequirePermission } from '@backstage/plugin-permission-react';\nimport {\n taskReadPermission,\n templateManagementPermission,\n} from '@backstage/plugin-scaffolder-common/alpha';\n\n/**\n * The Props for the Scaffolder Router\n *\n * @public\n */\nexport type RouterProps = {\n components?: {\n ReviewStepComponent?: React.ComponentType<ReviewStepProps>;\n TemplateCardComponent?: React.ComponentType<{\n template: TemplateEntityV1beta3;\n }>;\n TaskPageComponent?: React.ComponentType<PropsWithChildren<{}>>;\n EXPERIMENTAL_TemplateOutputsComponent?: React.ComponentType<{\n output?: ScaffolderTaskOutput;\n }>;\n EXPERIMENTAL_TemplateListPageComponent?: React.ComponentType<TemplateListPageProps>;\n EXPERIMENTAL_TemplateWizardPageComponent?: React.ComponentType<TemplateWizardPageProps>;\n };\n groups?: TemplateGroupFilter[];\n templateFilter?: (entity: TemplateEntityV1beta3) => boolean;\n headerOptions?: {\n pageTitleOverride?: string;\n title?: string;\n subtitle?: string;\n };\n defaultPreviewTemplate?: string;\n formProps?: FormProps;\n contextMenu?: {\n /** Whether to show a link to the template editor */\n editor?: boolean;\n /** Whether to show a link to the actions documentation */\n actions?: boolean;\n /** Whether to show a link to the tasks page */\n tasks?: boolean;\n /** Whether to show a link to the create page (on /create subroutes) */\n create?: boolean;\n };\n};\n\n/**\n * The Scaffolder Router\n *\n * @public\n */\nexport const Router = (props: PropsWithChildren<RouterProps>) => {\n const {\n components: {\n TemplateCardComponent,\n TaskPageComponent = OngoingTask,\n ReviewStepComponent,\n EXPERIMENTAL_TemplateOutputsComponent: TemplateOutputsComponent,\n EXPERIMENTAL_TemplateListPageComponent:\n TemplateListPageComponent = TemplateListPage,\n EXPERIMENTAL_TemplateWizardPageComponent:\n TemplateWizardPageComponent = TemplateWizardPage,\n } = {},\n } = props;\n const outlet = useOutlet() || props.children;\n const customFieldExtensions =\n useCustomFieldExtensions<FieldExtensionOptions>(outlet);\n\n const fieldExtensions = [\n ...customFieldExtensions,\n ...DEFAULT_SCAFFOLDER_FIELD_EXTENSIONS.filter(\n ({ name }) =>\n !customFieldExtensions.some(\n customFieldExtension => customFieldExtension.name === name,\n ),\n ),\n ] as FieldExtensionOptions[];\n\n const customLayouts = useCustomLayouts(outlet);\n\n return (\n <Routes>\n <Route\n path=\"/\"\n element={\n <TemplateListPageComponent\n TemplateCardComponent={TemplateCardComponent}\n contextMenu={props.contextMenu}\n groups={props.groups}\n templateFilter={props.templateFilter}\n headerOptions={props.headerOptions}\n />\n }\n />\n <Route\n path={selectedTemplateRouteRef.path}\n element={\n <SecretsContextProvider>\n <TemplateWizardPageComponent\n headerOptions={props.headerOptions}\n customFieldExtensions={fieldExtensions}\n layouts={customLayouts}\n components={{ ReviewStepComponent }}\n formProps={props.formProps}\n />\n </SecretsContextProvider>\n }\n />\n <Route\n path={scaffolderTaskRouteRef.path}\n element={\n <RequirePermission permission={taskReadPermission}>\n <TaskPageComponent\n TemplateOutputsComponent={TemplateOutputsComponent}\n />\n </RequirePermission>\n }\n />\n <Route\n path={editRouteRef.path}\n element={\n <RequirePermission permission={templateManagementPermission}>\n <SecretsContextProvider>\n <TemplateIntroPage />\n </SecretsContextProvider>\n </RequirePermission>\n }\n />\n <Route\n path={customFieldsRouteRef.path}\n element={\n <RequirePermission permission={templateManagementPermission}>\n <SecretsContextProvider>\n <CustomFieldsPage fieldExtensions={fieldExtensions} />\n </SecretsContextProvider>\n </RequirePermission>\n }\n />\n <Route\n path={templateFormRouteRef.path}\n element={\n <RequirePermission permission={templateManagementPermission}>\n <SecretsContextProvider>\n <TemplateFormPage\n layouts={customLayouts}\n formProps={props.formProps}\n fieldExtensions={fieldExtensions}\n />\n </SecretsContextProvider>\n </RequirePermission>\n }\n />\n\n <Route\n path={actionsRouteRef.path}\n element={<ActionsPage contextMenu={props.contextMenu} />}\n />\n <Route\n path={scaffolderListTaskRouteRef.path}\n element={\n <RequirePermission permission={taskReadPermission}>\n <ListTasksPage contextMenu={props.contextMenu} />\n </RequirePermission>\n }\n />\n <Route\n path={editorRouteRef.path}\n element={\n <RequirePermission permission={templateManagementPermission}>\n <SecretsContextProvider>\n <TemplateEditorPage\n layouts={customLayouts}\n formProps={props.formProps}\n fieldExtensions={fieldExtensions}\n />\n </SecretsContextProvider>\n </RequirePermission>\n }\n />\n <Route\n path=\"*\"\n element={<ErrorPage status=\"404\" statusMessage=\"Page not found\" />}\n />\n </Routes>\n );\n};\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"Router.esm.js","sources":["../../../src/components/Router/Router.tsx"],"sourcesContent":["/*\n * Copyright 2022 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport React, { PropsWithChildren } from 'react';\nimport { Routes, Route, useOutlet } from 'react-router-dom';\n\nimport {\n FieldExtensionOptions,\n FormProps,\n ReviewStepProps,\n TemplateGroupFilter,\n} from '@backstage/plugin-scaffolder-react';\nimport {\n ScaffolderTaskOutput,\n SecretsContextProvider,\n useCustomFieldExtensions,\n useCustomLayouts,\n} from '@backstage/plugin-scaffolder-react';\n\nimport { TemplateEntityV1beta3 } from '@backstage/plugin-scaffolder-common';\nimport { DEFAULT_SCAFFOLDER_FIELD_EXTENSIONS } from '../../extensions/default';\n\nimport {\n actionsRouteRef,\n editorRouteRef,\n customFieldsRouteRef,\n editRouteRef,\n scaffolderListTaskRouteRef,\n scaffolderTaskRouteRef,\n selectedTemplateRouteRef,\n templateFormRouteRef,\n} from '../../routes';\n\nimport { ActionsPage } from '../../components/ActionsPage';\nimport { ListTasksPage } from '../../components/ListTasksPage';\n\nimport {\n TemplateListPageProps,\n TemplateWizardPageProps,\n} from '@backstage/plugin-scaffolder/alpha';\nimport { TemplateListPage, TemplateWizardPage } from '../../alpha/components';\nimport { OngoingTask } from '../OngoingTask';\nimport {\n TemplateFormPage,\n TemplateIntroPage,\n TemplateEditorPage,\n CustomFieldsPage,\n} from '../../alpha/components/TemplateEditorPage';\nimport { RequirePermission } from '@backstage/plugin-permission-react';\nimport {\n taskReadPermission,\n templateManagementPermission,\n} from '@backstage/plugin-scaffolder-common/alpha';\nimport { useApp } from '@backstage/core-plugin-api';\n\n/**\n * The Props for the Scaffolder Router\n *\n * @public\n */\nexport type RouterProps = {\n components?: {\n ReviewStepComponent?: React.ComponentType<ReviewStepProps>;\n TemplateCardComponent?: React.ComponentType<{\n template: TemplateEntityV1beta3;\n }>;\n TaskPageComponent?: React.ComponentType<PropsWithChildren<{}>>;\n EXPERIMENTAL_TemplateOutputsComponent?: React.ComponentType<{\n output?: ScaffolderTaskOutput;\n }>;\n EXPERIMENTAL_TemplateListPageComponent?: React.ComponentType<TemplateListPageProps>;\n EXPERIMENTAL_TemplateWizardPageComponent?: React.ComponentType<TemplateWizardPageProps>;\n };\n groups?: TemplateGroupFilter[];\n templateFilter?: (entity: TemplateEntityV1beta3) => boolean;\n headerOptions?: {\n pageTitleOverride?: string;\n title?: string;\n subtitle?: string;\n };\n defaultPreviewTemplate?: string;\n formProps?: FormProps;\n contextMenu?: {\n /** Whether to show a link to the template editor */\n editor?: boolean;\n /** Whether to show a link to the actions documentation */\n actions?: boolean;\n /** Whether to show a link to the tasks page */\n tasks?: boolean;\n /** Whether to show a link to the create page (on /create subroutes) */\n create?: boolean;\n };\n};\n\n/**\n * The Scaffolder Router\n *\n * @public\n */\nexport const Router = (props: PropsWithChildren<RouterProps>) => {\n const {\n components: {\n TemplateCardComponent,\n TaskPageComponent = OngoingTask,\n ReviewStepComponent,\n EXPERIMENTAL_TemplateOutputsComponent: TemplateOutputsComponent,\n EXPERIMENTAL_TemplateListPageComponent:\n TemplateListPageComponent = TemplateListPage,\n EXPERIMENTAL_TemplateWizardPageComponent:\n TemplateWizardPageComponent = TemplateWizardPage,\n } = {},\n } = props;\n const outlet = useOutlet() || props.children;\n const customFieldExtensions =\n useCustomFieldExtensions<FieldExtensionOptions>(outlet);\n const app = useApp();\n const { NotFoundErrorPage } = app.getComponents();\n\n const fieldExtensions = [\n ...customFieldExtensions,\n ...DEFAULT_SCAFFOLDER_FIELD_EXTENSIONS.filter(\n ({ name }) =>\n !customFieldExtensions.some(\n customFieldExtension => customFieldExtension.name === name,\n ),\n ),\n ] as FieldExtensionOptions[];\n\n const customLayouts = useCustomLayouts(outlet);\n\n return (\n <Routes>\n <Route\n path=\"/\"\n element={\n <TemplateListPageComponent\n TemplateCardComponent={TemplateCardComponent}\n contextMenu={props.contextMenu}\n groups={props.groups}\n templateFilter={props.templateFilter}\n headerOptions={props.headerOptions}\n />\n }\n />\n <Route\n path={selectedTemplateRouteRef.path}\n element={\n <SecretsContextProvider>\n <TemplateWizardPageComponent\n headerOptions={props.headerOptions}\n customFieldExtensions={fieldExtensions}\n layouts={customLayouts}\n components={{ ReviewStepComponent }}\n formProps={props.formProps}\n />\n </SecretsContextProvider>\n }\n />\n <Route\n path={scaffolderTaskRouteRef.path}\n element={\n <RequirePermission permission={taskReadPermission}>\n <TaskPageComponent\n TemplateOutputsComponent={TemplateOutputsComponent}\n />\n </RequirePermission>\n }\n />\n <Route\n path={editRouteRef.path}\n element={\n <RequirePermission permission={templateManagementPermission}>\n <SecretsContextProvider>\n <TemplateIntroPage />\n </SecretsContextProvider>\n </RequirePermission>\n }\n />\n <Route\n path={customFieldsRouteRef.path}\n element={\n <RequirePermission permission={templateManagementPermission}>\n <SecretsContextProvider>\n <CustomFieldsPage fieldExtensions={fieldExtensions} />\n </SecretsContextProvider>\n </RequirePermission>\n }\n />\n <Route\n path={templateFormRouteRef.path}\n element={\n <RequirePermission permission={templateManagementPermission}>\n <SecretsContextProvider>\n <TemplateFormPage\n layouts={customLayouts}\n formProps={props.formProps}\n fieldExtensions={fieldExtensions}\n />\n </SecretsContextProvider>\n </RequirePermission>\n }\n />\n\n <Route\n path={actionsRouteRef.path}\n element={<ActionsPage contextMenu={props.contextMenu} />}\n />\n <Route\n path={scaffolderListTaskRouteRef.path}\n element={\n <RequirePermission permission={taskReadPermission}>\n <ListTasksPage contextMenu={props.contextMenu} />\n </RequirePermission>\n }\n />\n <Route\n path={editorRouteRef.path}\n element={\n <RequirePermission permission={templateManagementPermission}>\n <SecretsContextProvider>\n <TemplateEditorPage\n layouts={customLayouts}\n formProps={props.formProps}\n fieldExtensions={fieldExtensions}\n />\n </SecretsContextProvider>\n </RequirePermission>\n }\n />\n <Route path=\"*\" element={<NotFoundErrorPage />} />\n </Routes>\n );\n};\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;AA+Ga,MAAA,MAAA,GAAS,CAAC,KAA0C,KAAA;AAC/D,EAAM,MAAA;AAAA,IACJ,UAAY,EAAA;AAAA,MACV,qBAAA;AAAA,MACA,iBAAoB,GAAA,WAAA;AAAA,MACpB,mBAAA;AAAA,MACA,qCAAuC,EAAA,wBAAA;AAAA,MACvC,wCACE,yBAA4B,GAAA,gBAAA;AAAA,MAC9B,0CACE,2BAA8B,GAAA;AAAA,QAC9B;AAAC,GACH,GAAA,KAAA;AACJ,EAAM,MAAA,MAAA,GAAS,SAAU,EAAA,IAAK,KAAM,CAAA,QAAA;AACpC,EAAM,MAAA,qBAAA,GACJ,yBAAgD,MAAM,CAAA;AACxD,EAAA,MAAM,MAAM,MAAO,EAAA;AACnB,EAAA,MAAM,EAAE,iBAAA,EAAsB,GAAA,GAAA,CAAI,aAAc,EAAA;AAEhD,EAAA,MAAM,eAAkB,GAAA;AAAA,IACtB,GAAG,qBAAA;AAAA,IACH,GAAG,mCAAoC,CAAA,MAAA;AAAA,MACrC,CAAC,EAAE,IAAK,EAAA,KACN,CAAC,qBAAsB,CAAA,IAAA;AAAA,QACrB,CAAA,oBAAA,KAAwB,qBAAqB,IAAS,KAAA;AAAA;AACxD;AACJ,GACF;AAEA,EAAM,MAAA,aAAA,GAAgB,iBAAiB,MAAM,CAAA;AAE7C,EAAA,2CACG,MACC,EAAA,IAAA,kBAAA,KAAA,CAAA,aAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MACC,IAAK,EAAA,GAAA;AAAA,MACL,OACE,kBAAA,KAAA,CAAA,aAAA;AAAA,QAAC,yBAAA;AAAA,QAAA;AAAA,UACC,qBAAA;AAAA,UACA,aAAa,KAAM,CAAA,WAAA;AAAA,UACnB,QAAQ,KAAM,CAAA,MAAA;AAAA,UACd,gBAAgB,KAAM,CAAA,cAAA;AAAA,UACtB,eAAe,KAAM,CAAA;AAAA;AAAA;AACvB;AAAA,GAGJ,kBAAA,KAAA,CAAA,aAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MACC,MAAM,wBAAyB,CAAA,IAAA;AAAA,MAC/B,OAAA,sCACG,sBACC,EAAA,IAAA,kBAAA,KAAA,CAAA,aAAA;AAAA,QAAC,2BAAA;AAAA,QAAA;AAAA,UACC,eAAe,KAAM,CAAA,aAAA;AAAA,UACrB,qBAAuB,EAAA,eAAA;AAAA,UACvB,OAAS,EAAA,aAAA;AAAA,UACT,UAAA,EAAY,EAAE,mBAAoB,EAAA;AAAA,UAClC,WAAW,KAAM,CAAA;AAAA;AAAA,OAErB;AAAA;AAAA,GAGJ,kBAAA,KAAA,CAAA,aAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MACC,MAAM,sBAAuB,CAAA,IAAA;AAAA,MAC7B,OACE,kBAAA,KAAA,CAAA,aAAA,CAAC,iBAAkB,EAAA,EAAA,UAAA,EAAY,kBAC7B,EAAA,kBAAA,KAAA,CAAA,aAAA;AAAA,QAAC,iBAAA;AAAA,QAAA;AAAA,UACC;AAAA;AAAA,OAEJ;AAAA;AAAA,GAGJ,kBAAA,KAAA,CAAA,aAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MACC,MAAM,YAAa,CAAA,IAAA;AAAA,MACnB,OAAA,kBACG,KAAA,CAAA,aAAA,CAAA,iBAAA,EAAA,EAAkB,UAAY,EAAA,4BAAA,EAAA,sCAC5B,sBACC,EAAA,IAAA,kBAAA,KAAA,CAAA,aAAA,CAAC,iBAAkB,EAAA,IAAA,CACrB,CACF;AAAA;AAAA,GAGJ,kBAAA,KAAA,CAAA,aAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MACC,MAAM,oBAAqB,CAAA,IAAA;AAAA,MAC3B,OAAA,kBACG,KAAA,CAAA,aAAA,CAAA,iBAAA,EAAA,EAAkB,UAAY,EAAA,4BAAA,EAAA,kBAC5B,KAAA,CAAA,aAAA,CAAA,sBAAA,EAAA,IAAA,kBACE,KAAA,CAAA,aAAA,CAAA,gBAAA,EAAA,EAAiB,eAAkC,EAAA,CACtD,CACF;AAAA;AAAA,GAGJ,kBAAA,KAAA,CAAA,aAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MACC,MAAM,oBAAqB,CAAA,IAAA;AAAA,MAC3B,yBACG,KAAA,CAAA,aAAA,CAAA,iBAAA,EAAA,EAAkB,UAAY,EAAA,4BAAA,EAAA,sCAC5B,sBACC,EAAA,IAAA,kBAAA,KAAA,CAAA,aAAA;AAAA,QAAC,gBAAA;AAAA,QAAA;AAAA,UACC,OAAS,EAAA,aAAA;AAAA,UACT,WAAW,KAAM,CAAA,SAAA;AAAA,UACjB;AAAA;AAAA,OAEJ,CACF;AAAA;AAAA,GAIJ,kBAAA,KAAA,CAAA,aAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MACC,MAAM,eAAgB,CAAA,IAAA;AAAA,MACtB,OAAS,kBAAA,KAAA,CAAA,aAAA,CAAC,WAAY,EAAA,EAAA,WAAA,EAAa,MAAM,WAAa,EAAA;AAAA;AAAA,GAExD,kBAAA,KAAA,CAAA,aAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MACC,MAAM,0BAA2B,CAAA,IAAA;AAAA,MACjC,OAAA,kBACG,KAAA,CAAA,aAAA,CAAA,iBAAA,EAAA,EAAkB,UAAY,EAAA,kBAAA,EAAA,sCAC5B,aAAc,EAAA,EAAA,WAAA,EAAa,KAAM,CAAA,WAAA,EAAa,CACjD;AAAA;AAAA,GAGJ,kBAAA,KAAA,CAAA,aAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MACC,MAAM,cAAe,CAAA,IAAA;AAAA,MACrB,yBACG,KAAA,CAAA,aAAA,CAAA,iBAAA,EAAA,EAAkB,UAAY,EAAA,4BAAA,EAAA,sCAC5B,sBACC,EAAA,IAAA,kBAAA,KAAA,CAAA,aAAA;AAAA,QAAC,kBAAA;AAAA,QAAA;AAAA,UACC,OAAS,EAAA,aAAA;AAAA,UACT,WAAW,KAAM,CAAA,SAAA;AAAA,UACjB;AAAA;AAAA,OAEJ,CACF;AAAA;AAAA,GAEJ,sCACC,KAAM,EAAA,EAAA,IAAA,EAAK,KAAI,OAAS,kBAAA,KAAA,CAAA,aAAA,CAAC,iBAAkB,EAAA,IAAA,CAAA,EAAI,CAClD,CAAA;AAEJ;;;;"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { useApi } from '@backstage/core-plugin-api';
|
|
2
|
+
import { scaffolderApiRef } from '@backstage/plugin-scaffolder-react';
|
|
3
|
+
import FormControl from '@material-ui/core/FormControl';
|
|
4
|
+
import FormHelperText from '@material-ui/core/FormHelperText';
|
|
5
|
+
import TextField from '@material-ui/core/TextField';
|
|
6
|
+
import Autocomplete from '@material-ui/lab/Autocomplete';
|
|
7
|
+
import React, { useState, useCallback } from 'react';
|
|
8
|
+
import useDebounce from 'react-use/esm/useDebounce';
|
|
9
|
+
|
|
10
|
+
const GitHubRepoBranchPicker = ({
|
|
11
|
+
onChange,
|
|
12
|
+
state,
|
|
13
|
+
rawErrors,
|
|
14
|
+
accessToken,
|
|
15
|
+
required
|
|
16
|
+
}) => {
|
|
17
|
+
const { host, owner, repository, branch } = state;
|
|
18
|
+
const [availableBranches, setAvailableBranches] = useState([]);
|
|
19
|
+
const scaffolderApi = useApi(scaffolderApiRef);
|
|
20
|
+
const updateAvailableBranches = useCallback(() => {
|
|
21
|
+
if (!scaffolderApi.autocomplete || !owner || !repository || !accessToken || !host) {
|
|
22
|
+
setAvailableBranches([]);
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
scaffolderApi.autocomplete({
|
|
26
|
+
token: accessToken,
|
|
27
|
+
resource: "branches",
|
|
28
|
+
context: { host, owner, repository },
|
|
29
|
+
provider: "github"
|
|
30
|
+
}).then(({ results }) => {
|
|
31
|
+
setAvailableBranches(results.map((r) => r.id));
|
|
32
|
+
}).catch(() => {
|
|
33
|
+
setAvailableBranches([]);
|
|
34
|
+
});
|
|
35
|
+
}, [host, owner, repository, accessToken, scaffolderApi]);
|
|
36
|
+
useDebounce(updateAvailableBranches, 500, [updateAvailableBranches]);
|
|
37
|
+
return /* @__PURE__ */ React.createElement(
|
|
38
|
+
FormControl,
|
|
39
|
+
{
|
|
40
|
+
margin: "normal",
|
|
41
|
+
required,
|
|
42
|
+
error: rawErrors?.length > 0 && !branch
|
|
43
|
+
},
|
|
44
|
+
/* @__PURE__ */ React.createElement(
|
|
45
|
+
Autocomplete,
|
|
46
|
+
{
|
|
47
|
+
value: branch,
|
|
48
|
+
onChange: (_, newValue) => {
|
|
49
|
+
onChange({ branch: newValue || "" });
|
|
50
|
+
},
|
|
51
|
+
options: availableBranches,
|
|
52
|
+
renderInput: (params) => /* @__PURE__ */ React.createElement(TextField, { ...params, label: "Branch", required }),
|
|
53
|
+
freeSolo: true,
|
|
54
|
+
autoSelect: true
|
|
55
|
+
}
|
|
56
|
+
),
|
|
57
|
+
/* @__PURE__ */ React.createElement(FormHelperText, null, "The branch of the repository")
|
|
58
|
+
);
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
export { GitHubRepoBranchPicker };
|
|
62
|
+
//# sourceMappingURL=GitHubRepoBranchPicker.esm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"GitHubRepoBranchPicker.esm.js","sources":["../../../../src/components/fields/RepoBranchPicker/GitHubRepoBranchPicker.tsx"],"sourcesContent":["/*\n * Copyright 2025 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { useApi } from '@backstage/core-plugin-api';\nimport { scaffolderApiRef } from '@backstage/plugin-scaffolder-react';\nimport FormControl from '@material-ui/core/FormControl';\nimport FormHelperText from '@material-ui/core/FormHelperText';\nimport TextField from '@material-ui/core/TextField';\nimport Autocomplete from '@material-ui/lab/Autocomplete';\nimport React, { useCallback, useState } from 'react';\nimport useDebounce from 'react-use/esm/useDebounce';\nimport { BaseRepoBranchPickerProps } from './types';\n\n/**\n * The underlying component that is rendered in the form for the `GitHubRepoBranchPicker`\n * field extension.\n *\n * @public\n *\n */\nexport const GitHubRepoBranchPicker = ({\n onChange,\n state,\n rawErrors,\n accessToken,\n required,\n}: BaseRepoBranchPickerProps<{\n accessToken?: string;\n}>) => {\n const { host, owner, repository, branch } = state;\n\n const [availableBranches, setAvailableBranches] = useState<string[]>([]);\n\n const scaffolderApi = useApi(scaffolderApiRef);\n\n const updateAvailableBranches = useCallback(() => {\n if (\n !scaffolderApi.autocomplete ||\n !owner ||\n !repository ||\n !accessToken ||\n !host\n ) {\n setAvailableBranches([]);\n return;\n }\n\n scaffolderApi\n .autocomplete({\n token: accessToken,\n resource: 'branches',\n context: { host, owner, repository },\n provider: 'github',\n })\n .then(({ results }) => {\n setAvailableBranches(results.map(r => r.id));\n })\n .catch(() => {\n setAvailableBranches([]);\n });\n }, [host, owner, repository, accessToken, scaffolderApi]);\n\n useDebounce(updateAvailableBranches, 500, [updateAvailableBranches]);\n\n return (\n <FormControl\n margin=\"normal\"\n required={required}\n error={rawErrors?.length > 0 && !branch}\n >\n <Autocomplete\n value={branch}\n onChange={(_, newValue) => {\n onChange({ branch: newValue || '' });\n }}\n options={availableBranches}\n renderInput={params => (\n <TextField {...params} label=\"Branch\" required={required} />\n )}\n freeSolo\n autoSelect\n />\n <FormHelperText>The branch of the repository</FormHelperText>\n </FormControl>\n );\n};\n"],"names":[],"mappings":";;;;;;;;;AAiCO,MAAM,yBAAyB,CAAC;AAAA,EACrC,QAAA;AAAA,EACA,KAAA;AAAA,EACA,SAAA;AAAA,EACA,WAAA;AAAA,EACA;AACF,CAEO,KAAA;AACL,EAAA,MAAM,EAAE,IAAA,EAAM,KAAO,EAAA,UAAA,EAAY,QAAW,GAAA,KAAA;AAE5C,EAAA,MAAM,CAAC,iBAAmB,EAAA,oBAAoB,CAAI,GAAA,QAAA,CAAmB,EAAE,CAAA;AAEvE,EAAM,MAAA,aAAA,GAAgB,OAAO,gBAAgB,CAAA;AAE7C,EAAM,MAAA,uBAAA,GAA0B,YAAY,MAAM;AAChD,IACE,IAAA,CAAC,aAAc,CAAA,YAAA,IACf,CAAC,KAAA,IACD,CAAC,UACD,IAAA,CAAC,WACD,IAAA,CAAC,IACD,EAAA;AACA,MAAA,oBAAA,CAAqB,EAAE,CAAA;AACvB,MAAA;AAAA;AAGF,IAAA,aAAA,CACG,YAAa,CAAA;AAAA,MACZ,KAAO,EAAA,WAAA;AAAA,MACP,QAAU,EAAA,UAAA;AAAA,MACV,OAAS,EAAA,EAAE,IAAM,EAAA,KAAA,EAAO,UAAW,EAAA;AAAA,MACnC,QAAU,EAAA;AAAA,KACX,CACA,CAAA,IAAA,CAAK,CAAC,EAAE,SAAc,KAAA;AACrB,MAAA,oBAAA,CAAqB,OAAQ,CAAA,GAAA,CAAI,CAAK,CAAA,KAAA,CAAA,CAAE,EAAE,CAAC,CAAA;AAAA,KAC5C,CACA,CAAA,KAAA,CAAM,MAAM;AACX,MAAA,oBAAA,CAAqB,EAAE,CAAA;AAAA,KACxB,CAAA;AAAA,KACF,CAAC,IAAA,EAAM,OAAO,UAAY,EAAA,WAAA,EAAa,aAAa,CAAC,CAAA;AAExD,EAAA,WAAA,CAAY,uBAAyB,EAAA,GAAA,EAAK,CAAC,uBAAuB,CAAC,CAAA;AAEnE,EACE,uBAAA,KAAA,CAAA,aAAA;AAAA,IAAC,WAAA;AAAA,IAAA;AAAA,MACC,MAAO,EAAA,QAAA;AAAA,MACP,QAAA;AAAA,MACA,KAAO,EAAA,SAAA,EAAW,MAAS,GAAA,CAAA,IAAK,CAAC;AAAA,KAAA;AAAA,oBAEjC,KAAA,CAAA,aAAA;AAAA,MAAC,YAAA;AAAA,MAAA;AAAA,QACC,KAAO,EAAA,MAAA;AAAA,QACP,QAAA,EAAU,CAAC,CAAA,EAAG,QAAa,KAAA;AACzB,UAAA,QAAA,CAAS,EAAE,MAAA,EAAQ,QAAY,IAAA,EAAA,EAAI,CAAA;AAAA,SACrC;AAAA,QACA,OAAS,EAAA,iBAAA;AAAA,QACT,WAAA,EAAa,4BACV,KAAA,CAAA,aAAA,CAAA,SAAA,EAAA,EAAW,GAAG,MAAQ,EAAA,KAAA,EAAM,UAAS,QAAoB,EAAA,CAAA;AAAA,QAE5D,QAAQ,EAAA,IAAA;AAAA,QACR,UAAU,EAAA;AAAA;AAAA,KACZ;AAAA,oBACA,KAAA,CAAA,aAAA,CAAC,sBAAe,8BAA4B;AAAA,GAC9C;AAEJ;;;;"}
|
|
@@ -8,6 +8,7 @@ import Divider from '@material-ui/core/Divider';
|
|
|
8
8
|
import Typography from '@material-ui/core/Typography';
|
|
9
9
|
import { BitbucketRepoBranchPicker } from './BitbucketRepoBranchPicker.esm.js';
|
|
10
10
|
import { DefaultRepoBranchPicker } from './DefaultRepoBranchPicker.esm.js';
|
|
11
|
+
import { GitHubRepoBranchPicker } from './GitHubRepoBranchPicker.esm.js';
|
|
11
12
|
|
|
12
13
|
const RepoBranchPicker = (props) => {
|
|
13
14
|
const {
|
|
@@ -57,7 +58,8 @@ const RepoBranchPicker = (props) => {
|
|
|
57
58
|
...prevState,
|
|
58
59
|
host: url.host,
|
|
59
60
|
workspace: url.searchParams.get("workspace") || "",
|
|
60
|
-
repository: url.searchParams.get("repo") || ""
|
|
61
|
+
repository: url.searchParams.get("repo") || "",
|
|
62
|
+
owner: url.searchParams.get("owner") || ""
|
|
61
63
|
}));
|
|
62
64
|
}
|
|
63
65
|
}, [repoUrl]);
|
|
@@ -84,6 +86,17 @@ const RepoBranchPicker = (props) => {
|
|
|
84
86
|
required
|
|
85
87
|
}
|
|
86
88
|
);
|
|
89
|
+
case "github":
|
|
90
|
+
return /* @__PURE__ */ React.createElement(
|
|
91
|
+
GitHubRepoBranchPicker,
|
|
92
|
+
{
|
|
93
|
+
onChange: updateLocalState,
|
|
94
|
+
state,
|
|
95
|
+
rawErrors,
|
|
96
|
+
accessToken: uiSchema?.["ui:options"]?.requestUserCredentials?.secretsKey && secrets[uiSchema["ui:options"].requestUserCredentials.secretsKey],
|
|
97
|
+
required
|
|
98
|
+
}
|
|
99
|
+
);
|
|
87
100
|
default:
|
|
88
101
|
return /* @__PURE__ */ React.createElement(
|
|
89
102
|
DefaultRepoBranchPicker,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RepoBranchPicker.esm.js","sources":["../../../../src/components/fields/RepoBranchPicker/RepoBranchPicker.tsx"],"sourcesContent":["/*\n * Copyright 2024 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { useApi } from '@backstage/core-plugin-api';\nimport {\n scmIntegrationsApiRef,\n scmAuthApiRef,\n} from '@backstage/integration-react';\nimport React, { useEffect, useState, useCallback } from 'react';\nimport useDebounce from 'react-use/esm/useDebounce';\nimport { useTemplateSecrets } from '@backstage/plugin-scaffolder-react';\nimport Box from '@material-ui/core/Box';\nimport Divider from '@material-ui/core/Divider';\nimport Typography from '@material-ui/core/Typography';\n\nimport { RepoBranchPickerProps } from './schema';\nimport { RepoBranchPickerState } from './types';\nimport { BitbucketRepoBranchPicker } from './BitbucketRepoBranchPicker';\nimport { DefaultRepoBranchPicker } from './DefaultRepoBranchPicker';\n\n/**\n * The underlying component that is rendered in the form for the `RepoBranchPicker`\n * field extension.\n *\n * @public\n */\nexport const RepoBranchPicker = (props: RepoBranchPickerProps) => {\n const {\n uiSchema,\n onChange,\n rawErrors,\n formData,\n schema,\n formContext,\n required,\n } = props;\n const {\n formData: { repoUrl },\n } = formContext;\n\n const [state, setState] = useState<RepoBranchPickerState>({\n branch: formData || '',\n });\n const { host, branch } = state;\n\n const integrationApi = useApi(scmIntegrationsApiRef);\n const scmAuthApi = useApi(scmAuthApiRef);\n\n const { secrets, setSecrets } = useTemplateSecrets();\n\n useDebounce(\n async () => {\n const { requestUserCredentials } = uiSchema?.['ui:options'] ?? {};\n\n if (!requestUserCredentials || !host) {\n return;\n }\n\n // don't show login prompt if secret value is already in state\n if (secrets[requestUserCredentials.secretsKey]) {\n return;\n }\n\n // user has requested that we use the users credentials\n // so lets grab them using the scmAuthApi and pass through\n // any additional scopes from the ui:options\n const { token } = await scmAuthApi.getCredentials({\n url: `https://${host}`,\n additionalScope: {\n repoWrite: true,\n customScopes: requestUserCredentials.additionalScopes,\n },\n });\n\n // set the secret using the key provided in the ui:options for use\n // in the templating the manifest with ${{ secrets[secretsKey] }}\n setSecrets({ [requestUserCredentials.secretsKey]: token });\n },\n 500,\n [host, uiSchema],\n );\n\n useEffect(() => {\n if (repoUrl) {\n const url = new URL(`https://${repoUrl}`);\n\n setState(prevState => ({\n ...prevState,\n host: url.host,\n workspace: url.searchParams.get('workspace') || '',\n repository: url.searchParams.get('repo') || '',\n }));\n }\n }, [repoUrl]);\n\n useEffect(() => {\n onChange(branch);\n }, [branch, onChange]);\n\n const updateLocalState = useCallback(\n (newState: RepoBranchPickerState) => {\n setState(prevState => ({ ...prevState, ...newState }));\n },\n [setState],\n );\n\n const hostType = (host && integrationApi.byHost(host)?.type) ?? null;\n\n const renderRepoBranchPicker = () => {\n switch (hostType) {\n case 'bitbucket':\n return (\n <BitbucketRepoBranchPicker\n onChange={updateLocalState}\n state={state}\n rawErrors={rawErrors}\n accessToken={\n uiSchema?.['ui:options']?.requestUserCredentials?.secretsKey &&\n secrets[uiSchema['ui:options'].requestUserCredentials.secretsKey]\n }\n required={required}\n />\n );\n default:\n return (\n <DefaultRepoBranchPicker\n onChange={updateLocalState}\n state={state}\n rawErrors={rawErrors}\n required={required}\n />\n );\n }\n };\n\n return (\n <>\n {schema.title && (\n <Box my={1}>\n <Typography variant=\"h5\">{schema.title}</Typography>\n <Divider />\n </Box>\n )}\n {schema.description && (\n <Typography variant=\"body1\">{schema.description}</Typography>\n )}\n {renderRepoBranchPicker()}\n </>\n );\n};\n"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"RepoBranchPicker.esm.js","sources":["../../../../src/components/fields/RepoBranchPicker/RepoBranchPicker.tsx"],"sourcesContent":["/*\n * Copyright 2024 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { useApi } from '@backstage/core-plugin-api';\nimport {\n scmIntegrationsApiRef,\n scmAuthApiRef,\n} from '@backstage/integration-react';\nimport React, { useEffect, useState, useCallback } from 'react';\nimport useDebounce from 'react-use/esm/useDebounce';\nimport { useTemplateSecrets } from '@backstage/plugin-scaffolder-react';\nimport Box from '@material-ui/core/Box';\nimport Divider from '@material-ui/core/Divider';\nimport Typography from '@material-ui/core/Typography';\n\nimport { RepoBranchPickerProps } from './schema';\nimport { RepoBranchPickerState } from './types';\nimport { BitbucketRepoBranchPicker } from './BitbucketRepoBranchPicker';\nimport { DefaultRepoBranchPicker } from './DefaultRepoBranchPicker';\nimport { GitHubRepoBranchPicker } from './GitHubRepoBranchPicker';\n\n/**\n * The underlying component that is rendered in the form for the `RepoBranchPicker`\n * field extension.\n *\n * @public\n */\nexport const RepoBranchPicker = (props: RepoBranchPickerProps) => {\n const {\n uiSchema,\n onChange,\n rawErrors,\n formData,\n schema,\n formContext,\n required,\n } = props;\n const {\n formData: { repoUrl },\n } = formContext;\n\n const [state, setState] = useState<RepoBranchPickerState>({\n branch: formData || '',\n });\n const { host, branch } = state;\n\n const integrationApi = useApi(scmIntegrationsApiRef);\n const scmAuthApi = useApi(scmAuthApiRef);\n\n const { secrets, setSecrets } = useTemplateSecrets();\n\n useDebounce(\n async () => {\n const { requestUserCredentials } = uiSchema?.['ui:options'] ?? {};\n\n if (!requestUserCredentials || !host) {\n return;\n }\n\n // don't show login prompt if secret value is already in state\n if (secrets[requestUserCredentials.secretsKey]) {\n return;\n }\n\n // user has requested that we use the users credentials\n // so lets grab them using the scmAuthApi and pass through\n // any additional scopes from the ui:options\n const { token } = await scmAuthApi.getCredentials({\n url: `https://${host}`,\n additionalScope: {\n repoWrite: true,\n customScopes: requestUserCredentials.additionalScopes,\n },\n });\n\n // set the secret using the key provided in the ui:options for use\n // in the templating the manifest with ${{ secrets[secretsKey] }}\n setSecrets({ [requestUserCredentials.secretsKey]: token });\n },\n 500,\n [host, uiSchema],\n );\n\n useEffect(() => {\n if (repoUrl) {\n const url = new URL(`https://${repoUrl}`);\n\n setState(prevState => ({\n ...prevState,\n host: url.host,\n workspace: url.searchParams.get('workspace') || '',\n repository: url.searchParams.get('repo') || '',\n owner: url.searchParams.get('owner') || '',\n }));\n }\n }, [repoUrl]);\n\n useEffect(() => {\n onChange(branch);\n }, [branch, onChange]);\n\n const updateLocalState = useCallback(\n (newState: RepoBranchPickerState) => {\n setState(prevState => ({ ...prevState, ...newState }));\n },\n [setState],\n );\n\n const hostType = (host && integrationApi.byHost(host)?.type) ?? null;\n\n const renderRepoBranchPicker = () => {\n switch (hostType) {\n case 'bitbucket':\n return (\n <BitbucketRepoBranchPicker\n onChange={updateLocalState}\n state={state}\n rawErrors={rawErrors}\n accessToken={\n uiSchema?.['ui:options']?.requestUserCredentials?.secretsKey &&\n secrets[uiSchema['ui:options'].requestUserCredentials.secretsKey]\n }\n required={required}\n />\n );\n case 'github':\n return (\n <GitHubRepoBranchPicker\n onChange={updateLocalState}\n state={state}\n rawErrors={rawErrors}\n accessToken={\n uiSchema?.['ui:options']?.requestUserCredentials?.secretsKey &&\n secrets[uiSchema['ui:options'].requestUserCredentials.secretsKey]\n }\n required={required}\n />\n );\n default:\n return (\n <DefaultRepoBranchPicker\n onChange={updateLocalState}\n state={state}\n rawErrors={rawErrors}\n required={required}\n />\n );\n }\n };\n\n return (\n <>\n {schema.title && (\n <Box my={1}>\n <Typography variant=\"h5\">{schema.title}</Typography>\n <Divider />\n </Box>\n )}\n {schema.description && (\n <Typography variant=\"body1\">{schema.description}</Typography>\n )}\n {renderRepoBranchPicker()}\n </>\n );\n};\n"],"names":[],"mappings":"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"}
|
|
@@ -1,16 +1,59 @@
|
|
|
1
|
-
import React from 'react';
|
|
1
|
+
import React, { useState, useCallback, useMemo } from 'react';
|
|
2
2
|
import FormControl from '@material-ui/core/FormControl';
|
|
3
3
|
import FormHelperText from '@material-ui/core/FormHelperText';
|
|
4
4
|
import TextField from '@material-ui/core/TextField';
|
|
5
5
|
import { Select } from '@backstage/core-components';
|
|
6
6
|
import { useTranslationRef } from '@backstage/core-plugin-api/alpha';
|
|
7
7
|
import { scaffolderTranslationRef } from '../../../translation.esm.js';
|
|
8
|
+
import { useApi } from '@backstage/core-plugin-api';
|
|
9
|
+
import { scaffolderApiRef } from '@backstage/plugin-scaffolder-react';
|
|
10
|
+
import useDebounce from 'react-use/esm/useDebounce';
|
|
11
|
+
import Autocomplete from '@material-ui/lab/Autocomplete';
|
|
12
|
+
import uniq from 'lodash/uniq';
|
|
13
|
+
import map from 'lodash/map';
|
|
8
14
|
|
|
9
15
|
const GithubRepoPicker = (props) => {
|
|
10
|
-
const { allowedOwners = [], rawErrors, state, onChange } = props;
|
|
16
|
+
const { allowedOwners = [], rawErrors, state, onChange, accessToken } = props;
|
|
11
17
|
const { t } = useTranslationRef(scaffolderTranslationRef);
|
|
12
18
|
const ownerItems = allowedOwners ? allowedOwners.map((i) => ({ label: i, value: i })) : [{ label: "Loading...", value: "loading" }];
|
|
13
|
-
const { owner } = state;
|
|
19
|
+
const { host, owner } = state;
|
|
20
|
+
const scaffolderApi = useApi(scaffolderApiRef);
|
|
21
|
+
const [availableRepositoriesWithOwner, setAvailableRepositoriesWithOwner] = useState([]);
|
|
22
|
+
const updateAvailableRepositoriesWithOwner = useCallback(() => {
|
|
23
|
+
if (!scaffolderApi.autocomplete || !accessToken || !host) {
|
|
24
|
+
setAvailableRepositoriesWithOwner([]);
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
scaffolderApi.autocomplete({
|
|
28
|
+
token: accessToken,
|
|
29
|
+
resource: "repositoriesWithOwner",
|
|
30
|
+
provider: "github",
|
|
31
|
+
context: { host }
|
|
32
|
+
}).then(({ results }) => {
|
|
33
|
+
setAvailableRepositoriesWithOwner(
|
|
34
|
+
results.map((r) => {
|
|
35
|
+
const [rOwner, rName] = r.id.split("/");
|
|
36
|
+
return { owner: rOwner, name: rName };
|
|
37
|
+
})
|
|
38
|
+
);
|
|
39
|
+
}).catch(() => {
|
|
40
|
+
setAvailableRepositoriesWithOwner([]);
|
|
41
|
+
});
|
|
42
|
+
}, [scaffolderApi, accessToken, host]);
|
|
43
|
+
useDebounce(updateAvailableRepositoriesWithOwner, 500, [
|
|
44
|
+
updateAvailableRepositoriesWithOwner
|
|
45
|
+
]);
|
|
46
|
+
const availableOwners = useMemo(
|
|
47
|
+
() => uniq(map(availableRepositoriesWithOwner, "owner")),
|
|
48
|
+
[availableRepositoriesWithOwner]
|
|
49
|
+
);
|
|
50
|
+
const updateAvailableRepositories = useCallback(() => {
|
|
51
|
+
const availableRepos = availableRepositoriesWithOwner.flatMap(
|
|
52
|
+
(r) => r.owner === owner ? [{ name: r.name }] : []
|
|
53
|
+
);
|
|
54
|
+
onChange({ availableRepos });
|
|
55
|
+
}, [availableRepositoriesWithOwner, owner, onChange]);
|
|
56
|
+
useDebounce(updateAvailableRepositories, 500, [updateAvailableRepositories]);
|
|
14
57
|
return /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(
|
|
15
58
|
FormControl,
|
|
16
59
|
{
|
|
@@ -28,16 +71,27 @@ const GithubRepoPicker = (props) => {
|
|
|
28
71
|
selected: owner,
|
|
29
72
|
items: ownerItems
|
|
30
73
|
}
|
|
31
|
-
)
|
|
32
|
-
|
|
74
|
+
)) : /* @__PURE__ */ React.createElement(
|
|
75
|
+
Autocomplete,
|
|
33
76
|
{
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
77
|
+
value: owner,
|
|
78
|
+
onChange: (_, newValue) => {
|
|
79
|
+
onChange({ owner: newValue || "" });
|
|
80
|
+
},
|
|
81
|
+
options: availableOwners,
|
|
82
|
+
renderInput: (params) => /* @__PURE__ */ React.createElement(
|
|
83
|
+
TextField,
|
|
84
|
+
{
|
|
85
|
+
...params,
|
|
86
|
+
label: t("fields.githubRepoPicker.owner.inputTitle"),
|
|
87
|
+
required: true
|
|
88
|
+
}
|
|
89
|
+
),
|
|
90
|
+
freeSolo: true,
|
|
91
|
+
autoSelect: true
|
|
39
92
|
}
|
|
40
|
-
)
|
|
93
|
+
),
|
|
94
|
+
/* @__PURE__ */ React.createElement(FormHelperText, null, t("fields.githubRepoPicker.owner.description"))
|
|
41
95
|
));
|
|
42
96
|
};
|
|
43
97
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"GithubRepoPicker.esm.js","sources":["../../../../src/components/fields/RepoUrlPicker/GithubRepoPicker.tsx"],"sourcesContent":["/*\n * Copyright 2021 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport React from 'react';\nimport FormControl from '@material-ui/core/FormControl';\nimport FormHelperText from '@material-ui/core/FormHelperText';\nimport TextField from '@material-ui/core/TextField';\nimport { Select, SelectItem } from '@backstage/core-components';\nimport { BaseRepoUrlPickerProps } from './types';\nimport { useTranslationRef } from '@backstage/core-plugin-api/alpha';\nimport { scaffolderTranslationRef } from '../../../translation';\n\nexport const GithubRepoPicker = (\n props: BaseRepoUrlPickerProps<{\n allowedOwners?: string[];\n }>,\n) => {\n const { allowedOwners = [], rawErrors, state, onChange } = props;\n const { t } = useTranslationRef(scaffolderTranslationRef);\n const ownerItems: SelectItem[] = allowedOwners\n ? allowedOwners.map(i => ({ label: i, value: i }))\n : [{ label: 'Loading...', value: 'loading' }];\n\n const { owner } = state;\n\n return (\n <>\n <FormControl\n margin=\"normal\"\n required\n error={rawErrors?.length > 0 && !owner}\n >\n {allowedOwners?.length ? (\n <>\n <Select\n native\n label={t('fields.githubRepoPicker.owner.title')}\n onChange={s =>\n onChange({ owner: String(Array.isArray(s) ? s[0] : s) })\n }\n disabled={allowedOwners.length === 1}\n selected={owner}\n items={ownerItems}\n />\n
|
|
1
|
+
{"version":3,"file":"GithubRepoPicker.esm.js","sources":["../../../../src/components/fields/RepoUrlPicker/GithubRepoPicker.tsx"],"sourcesContent":["/*\n * Copyright 2021 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport React, { useCallback, useMemo, useState } from 'react';\nimport FormControl from '@material-ui/core/FormControl';\nimport FormHelperText from '@material-ui/core/FormHelperText';\nimport TextField from '@material-ui/core/TextField';\nimport { Select, SelectItem } from '@backstage/core-components';\nimport { BaseRepoUrlPickerProps } from './types';\nimport { useTranslationRef } from '@backstage/core-plugin-api/alpha';\nimport { scaffolderTranslationRef } from '../../../translation';\nimport { useApi } from '@backstage/core-plugin-api';\nimport { scaffolderApiRef } from '@backstage/plugin-scaffolder-react';\nimport useDebounce from 'react-use/esm/useDebounce';\nimport Autocomplete from '@material-ui/lab/Autocomplete';\nimport uniq from 'lodash/uniq';\nimport map from 'lodash/map';\n\nexport const GithubRepoPicker = (\n props: BaseRepoUrlPickerProps<{\n allowedOwners?: string[];\n accessToken?: string;\n }>,\n) => {\n const { allowedOwners = [], rawErrors, state, onChange, accessToken } = props;\n const { t } = useTranslationRef(scaffolderTranslationRef);\n const ownerItems: SelectItem[] = allowedOwners\n ? allowedOwners.map(i => ({ label: i, value: i }))\n : [{ label: 'Loading...', value: 'loading' }];\n\n const { host, owner } = state;\n\n const scaffolderApi = useApi(scaffolderApiRef);\n\n const [availableRepositoriesWithOwner, setAvailableRepositoriesWithOwner] =\n useState<{ owner: string; name: string }[]>([]);\n\n // Update available repositories with owner when client is available\n const updateAvailableRepositoriesWithOwner = useCallback(() => {\n if (!scaffolderApi.autocomplete || !accessToken || !host) {\n setAvailableRepositoriesWithOwner([]);\n return;\n }\n\n scaffolderApi\n .autocomplete({\n token: accessToken,\n resource: 'repositoriesWithOwner',\n provider: 'github',\n context: { host },\n })\n .then(({ results }) => {\n setAvailableRepositoriesWithOwner(\n results.map(r => {\n const [rOwner, rName] = r.id.split('/');\n return { owner: rOwner, name: rName };\n }),\n );\n })\n .catch(() => {\n setAvailableRepositoriesWithOwner([]);\n });\n }, [scaffolderApi, accessToken, host]);\n\n useDebounce(updateAvailableRepositoriesWithOwner, 500, [\n updateAvailableRepositoriesWithOwner,\n ]);\n\n // Update available owners when available repositories with owner change\n const availableOwners = useMemo<string[]>(\n () => uniq(map(availableRepositoriesWithOwner, 'owner')),\n [availableRepositoriesWithOwner],\n );\n\n // Update available repositories when available repositories with owner change or when owner changes\n const updateAvailableRepositories = useCallback(() => {\n const availableRepos = availableRepositoriesWithOwner.flatMap(r =>\n r.owner === owner ? [{ name: r.name }] : [],\n );\n\n onChange({ availableRepos });\n }, [availableRepositoriesWithOwner, owner, onChange]);\n\n useDebounce(updateAvailableRepositories, 500, [updateAvailableRepositories]);\n\n return (\n <>\n <FormControl\n margin=\"normal\"\n required\n error={rawErrors?.length > 0 && !owner}\n >\n {allowedOwners?.length ? (\n <>\n <Select\n native\n label={t('fields.githubRepoPicker.owner.title')}\n onChange={s =>\n onChange({ owner: String(Array.isArray(s) ? s[0] : s) })\n }\n disabled={allowedOwners.length === 1}\n selected={owner}\n items={ownerItems}\n />\n </>\n ) : (\n <Autocomplete\n value={owner}\n onChange={(_, newValue) => {\n onChange({ owner: newValue || '' });\n }}\n options={availableOwners}\n renderInput={params => (\n <TextField\n {...params}\n label={t('fields.githubRepoPicker.owner.inputTitle')}\n required\n />\n )}\n freeSolo\n autoSelect\n />\n )}\n <FormHelperText>\n {t('fields.githubRepoPicker.owner.description')}\n </FormHelperText>\n </FormControl>\n </>\n );\n};\n"],"names":[],"mappings":";;;;;;;;;;;;;;AA8Ba,MAAA,gBAAA,GAAmB,CAC9B,KAIG,KAAA;AACH,EAAM,MAAA,EAAE,gBAAgB,EAAC,EAAG,WAAW,KAAO,EAAA,QAAA,EAAU,aAAgB,GAAA,KAAA;AACxE,EAAA,MAAM,EAAE,CAAA,EAAM,GAAA,iBAAA,CAAkB,wBAAwB,CAAA;AACxD,EAAA,MAAM,aAA2B,aAC7B,GAAA,aAAA,CAAc,IAAI,CAAM,CAAA,MAAA,EAAE,OAAO,CAAG,EAAA,KAAA,EAAO,CAAE,EAAA,CAAE,IAC/C,CAAC,EAAE,OAAO,YAAc,EAAA,KAAA,EAAO,WAAW,CAAA;AAE9C,EAAM,MAAA,EAAE,IAAM,EAAA,KAAA,EAAU,GAAA,KAAA;AAExB,EAAM,MAAA,aAAA,GAAgB,OAAO,gBAAgB,CAAA;AAE7C,EAAA,MAAM,CAAC,8BAAgC,EAAA,iCAAiC,CACtE,GAAA,QAAA,CAA4C,EAAE,CAAA;AAGhD,EAAM,MAAA,oCAAA,GAAuC,YAAY,MAAM;AAC7D,IAAA,IAAI,CAAC,aAAc,CAAA,YAAA,IAAgB,CAAC,WAAA,IAAe,CAAC,IAAM,EAAA;AACxD,MAAA,iCAAA,CAAkC,EAAE,CAAA;AACpC,MAAA;AAAA;AAGF,IAAA,aAAA,CACG,YAAa,CAAA;AAAA,MACZ,KAAO,EAAA,WAAA;AAAA,MACP,QAAU,EAAA,uBAAA;AAAA,MACV,QAAU,EAAA,QAAA;AAAA,MACV,OAAA,EAAS,EAAE,IAAK;AAAA,KACjB,CACA,CAAA,IAAA,CAAK,CAAC,EAAE,SAAc,KAAA;AACrB,MAAA,iCAAA;AAAA,QACE,OAAA,CAAQ,IAAI,CAAK,CAAA,KAAA;AACf,UAAA,MAAM,CAAC,MAAQ,EAAA,KAAK,IAAI,CAAE,CAAA,EAAA,CAAG,MAAM,GAAG,CAAA;AACtC,UAAA,OAAO,EAAE,KAAA,EAAO,MAAQ,EAAA,IAAA,EAAM,KAAM,EAAA;AAAA,SACrC;AAAA,OACH;AAAA,KACD,CACA,CAAA,KAAA,CAAM,MAAM;AACX,MAAA,iCAAA,CAAkC,EAAE,CAAA;AAAA,KACrC,CAAA;AAAA,GACF,EAAA,CAAC,aAAe,EAAA,WAAA,EAAa,IAAI,CAAC,CAAA;AAErC,EAAA,WAAA,CAAY,sCAAsC,GAAK,EAAA;AAAA,IACrD;AAAA,GACD,CAAA;AAGD,EAAA,MAAM,eAAkB,GAAA,OAAA;AAAA,IACtB,MAAM,IAAA,CAAK,GAAI,CAAA,8BAAA,EAAgC,OAAO,CAAC,CAAA;AAAA,IACvD,CAAC,8BAA8B;AAAA,GACjC;AAGA,EAAM,MAAA,2BAAA,GAA8B,YAAY,MAAM;AACpD,IAAA,MAAM,iBAAiB,8BAA+B,CAAA,OAAA;AAAA,MAAQ,CAAA,CAAA,KAC5D,CAAE,CAAA,KAAA,KAAU,KAAQ,GAAA,CAAC,EAAE,IAAA,EAAM,CAAE,CAAA,IAAA,EAAM,CAAA,GAAI;AAAC,KAC5C;AAEA,IAAS,QAAA,CAAA,EAAE,gBAAgB,CAAA;AAAA,GAC1B,EAAA,CAAC,8BAAgC,EAAA,KAAA,EAAO,QAAQ,CAAC,CAAA;AAEpD,EAAA,WAAA,CAAY,2BAA6B,EAAA,GAAA,EAAK,CAAC,2BAA2B,CAAC,CAAA;AAE3E,EAAA,uBAEI,KAAA,CAAA,aAAA,CAAA,KAAA,CAAA,QAAA,EAAA,IAAA,kBAAA,KAAA,CAAA,aAAA;AAAA,IAAC,WAAA;AAAA,IAAA;AAAA,MACC,MAAO,EAAA,QAAA;AAAA,MACP,QAAQ,EAAA,IAAA;AAAA,MACR,KAAO,EAAA,SAAA,EAAW,MAAS,GAAA,CAAA,IAAK,CAAC;AAAA,KAAA;AAAA,IAEhC,aAAA,EAAe,yBAEZ,KAAA,CAAA,aAAA,CAAA,KAAA,CAAA,QAAA,EAAA,IAAA,kBAAA,KAAA,CAAA,aAAA;AAAA,MAAC,MAAA;AAAA,MAAA;AAAA,QACC,MAAM,EAAA,IAAA;AAAA,QACN,KAAA,EAAO,EAAE,qCAAqC,CAAA;AAAA,QAC9C,QAAU,EAAA,CAAA,CAAA,KACR,QAAS,CAAA,EAAE,OAAO,MAAO,CAAA,KAAA,CAAM,OAAQ,CAAA,CAAC,IAAI,CAAE,CAAA,CAAC,CAAI,GAAA,CAAC,GAAG,CAAA;AAAA,QAEzD,QAAA,EAAU,cAAc,MAAW,KAAA,CAAA;AAAA,QACnC,QAAU,EAAA,KAAA;AAAA,QACV,KAAO,EAAA;AAAA;AAAA,KAEX,CAEA,mBAAA,KAAA,CAAA,aAAA;AAAA,MAAC,YAAA;AAAA,MAAA;AAAA,QACC,KAAO,EAAA,KAAA;AAAA,QACP,QAAA,EAAU,CAAC,CAAA,EAAG,QAAa,KAAA;AACzB,UAAA,QAAA,CAAS,EAAE,KAAA,EAAO,QAAY,IAAA,EAAA,EAAI,CAAA;AAAA,SACpC;AAAA,QACA,OAAS,EAAA,eAAA;AAAA,QACT,aAAa,CACX,MAAA,qBAAA,KAAA,CAAA,aAAA;AAAA,UAAC,SAAA;AAAA,UAAA;AAAA,YACE,GAAG,MAAA;AAAA,YACJ,KAAA,EAAO,EAAE,0CAA0C,CAAA;AAAA,YACnD,QAAQ,EAAA;AAAA;AAAA,SACV;AAAA,QAEF,QAAQ,EAAA,IAAA;AAAA,QACR,UAAU,EAAA;AAAA;AAAA,KACZ;AAAA,oBAED,KAAA,CAAA,aAAA,CAAA,cAAA,EAAA,IAAA,EACE,CAAE,CAAA,2CAA2C,CAChD;AAAA,GAEJ,CAAA;AAEJ;;;;"}
|
|
@@ -124,7 +124,8 @@ const RepoUrlPicker = (props) => {
|
|
|
124
124
|
allowedOwners,
|
|
125
125
|
onChange: updateLocalState,
|
|
126
126
|
rawErrors,
|
|
127
|
-
state
|
|
127
|
+
state,
|
|
128
|
+
accessToken: uiSchema?.["ui:options"]?.requestUserCredentials?.secretsKey && secrets[uiSchema["ui:options"].requestUserCredentials.secretsKey]
|
|
128
129
|
}
|
|
129
130
|
), hostType === "gitea" && /* @__PURE__ */ React.createElement(
|
|
130
131
|
GiteaRepoPicker,
|
|
@@ -177,8 +178,7 @@ const RepoUrlPicker = (props) => {
|
|
|
177
178
|
allowedRepos,
|
|
178
179
|
onChange: (repo) => setState((prevState) => ({
|
|
179
180
|
...prevState,
|
|
180
|
-
repoName: repo.name
|
|
181
|
-
id: repo.id || ""
|
|
181
|
+
repoName: repo.id || repo.name
|
|
182
182
|
})),
|
|
183
183
|
rawErrors,
|
|
184
184
|
availableRepos: state.availableRepos
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RepoUrlPicker.esm.js","sources":["../../../../src/components/fields/RepoUrlPicker/RepoUrlPicker.tsx"],"sourcesContent":["/*\n * Copyright 2021 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { useApi } from '@backstage/core-plugin-api';\nimport {\n scmAuthApiRef,\n scmIntegrationsApiRef,\n} from '@backstage/integration-react';\nimport { useTemplateSecrets } from '@backstage/plugin-scaffolder-react';\nimport Box from '@material-ui/core/Box';\nimport Divider from '@material-ui/core/Divider';\nimport Typography from '@material-ui/core/Typography';\nimport React, { useCallback, useEffect, useMemo, useState } from 'react';\nimport useDebounce from 'react-use/esm/useDebounce';\nimport { AzureRepoPicker } from './AzureRepoPicker';\nimport { BitbucketRepoPicker } from './BitbucketRepoPicker';\nimport { GerritRepoPicker } from './GerritRepoPicker';\nimport { GiteaRepoPicker } from './GiteaRepoPicker';\nimport { GithubRepoPicker } from './GithubRepoPicker';\nimport { GitlabRepoPicker } from './GitlabRepoPicker';\nimport { RepoUrlPickerHost } from './RepoUrlPickerHost';\nimport { RepoUrlPickerRepoName } from './RepoUrlPickerRepoName';\nimport { RepoUrlPickerFieldSchema } from './schema';\nimport { RepoUrlPickerState } from './types';\nimport { parseRepoPickerUrl, serializeRepoPickerUrl } from './utils';\n\nexport { RepoUrlPickerSchema } from './schema';\n\n/**\n * The underlying component that is rendered in the form for the `RepoUrlPicker`\n * field extension.\n *\n * @public\n */\nexport const RepoUrlPicker = (\n props: typeof RepoUrlPickerFieldSchema.TProps,\n) => {\n const { uiSchema, onChange, rawErrors, formData, schema } = props;\n const [state, setState] = useState<RepoUrlPickerState>(\n parseRepoPickerUrl(formData),\n );\n const [credentialsHost, setCredentialsHost] = useState<string | undefined>(\n undefined,\n );\n const integrationApi = useApi(scmIntegrationsApiRef);\n const scmAuthApi = useApi(scmAuthApiRef);\n const { secrets, setSecrets } = useTemplateSecrets();\n const allowedHosts = useMemo(\n () => uiSchema?.['ui:options']?.allowedHosts ?? [],\n [uiSchema],\n );\n const allowedOrganizations = useMemo(\n () => uiSchema?.['ui:options']?.allowedOrganizations ?? [],\n [uiSchema],\n );\n const allowedOwners = useMemo(\n () => uiSchema?.['ui:options']?.allowedOwners ?? [],\n [uiSchema],\n );\n const allowedProjects = useMemo(\n () => uiSchema?.['ui:options']?.allowedProjects ?? [],\n [uiSchema],\n );\n const allowedRepos = useMemo(\n () => uiSchema?.['ui:options']?.allowedRepos ?? [],\n [uiSchema],\n );\n\n const { owner, organization, project, repoName } = state;\n\n useEffect(() => {\n onChange(serializeRepoPickerUrl(state));\n }, [state, onChange]);\n\n /* we deal with calling the repo setting here instead of in each components for ease */\n useEffect(() => {\n if (allowedOrganizations.length > 0 && !organization) {\n setState(prevState => ({\n ...prevState,\n organization: allowedOrganizations[0],\n }));\n }\n }, [setState, allowedOrganizations, organization]);\n\n useEffect(() => {\n if (allowedOwners.length > 0 && !owner) {\n setState(prevState => ({\n ...prevState,\n owner: allowedOwners[0],\n }));\n }\n }, [setState, allowedOwners, owner]);\n\n useEffect(() => {\n if (allowedProjects.length > 0 && !project) {\n setState(prevState => ({\n ...prevState,\n project: allowedProjects[0],\n }));\n }\n }, [setState, allowedProjects, project]);\n\n useEffect(() => {\n if (allowedRepos.length > 0 && !repoName) {\n setState(prevState => ({ ...prevState, repoName: allowedRepos[0] }));\n }\n }, [setState, allowedRepos, repoName]);\n\n const updateLocalState = useCallback(\n (newState: RepoUrlPickerState) => {\n setState(prevState => ({ ...prevState, ...newState }));\n },\n [setState],\n );\n\n useDebounce(\n async () => {\n const { requestUserCredentials } = uiSchema?.['ui:options'] ?? {};\n\n if (!requestUserCredentials || !state.host) {\n return;\n }\n\n // don't show login prompt if secret value is already in state for selected host\n if (\n secrets[requestUserCredentials.secretsKey] &&\n credentialsHost === state.host\n ) {\n return;\n }\n\n // user has requested that we use the users credentials\n // so lets grab them using the scmAuthApi and pass through\n // any additional scopes from the ui:options\n const { token } = await scmAuthApi.getCredentials({\n url: `https://${state.host}`,\n additionalScope: {\n repoWrite: true,\n customScopes: requestUserCredentials.additionalScopes,\n },\n });\n\n // set the secret using the key provided in the ui:options for use\n // in the templating the manifest with ${{ secrets[secretsKey] }}\n setSecrets({ [requestUserCredentials.secretsKey]: token });\n setCredentialsHost(state.host);\n },\n 500,\n [state, uiSchema],\n );\n\n const hostType =\n (state.host && integrationApi.byHost(state.host)?.type) ?? null;\n return (\n <>\n {schema.title && (\n <Box my={1}>\n <Typography variant=\"h5\">{schema.title}</Typography>\n <Divider />\n </Box>\n )}\n {schema.description && (\n <Typography variant=\"body1\">{schema.description}</Typography>\n )}\n <RepoUrlPickerHost\n host={state.host}\n hosts={allowedHosts}\n onChange={host => setState(prevState => ({ ...prevState, host }))}\n rawErrors={rawErrors}\n />\n {hostType === 'github' && (\n <GithubRepoPicker\n allowedOwners={allowedOwners}\n onChange={updateLocalState}\n rawErrors={rawErrors}\n state={state}\n />\n )}\n {hostType === 'gitea' && (\n <GiteaRepoPicker\n allowedOwners={allowedOwners}\n allowedRepos={allowedRepos}\n rawErrors={rawErrors}\n state={state}\n onChange={updateLocalState}\n />\n )}\n {hostType === 'gitlab' && (\n <GitlabRepoPicker\n allowedOwners={allowedOwners}\n rawErrors={rawErrors}\n state={state}\n onChange={updateLocalState}\n accessToken={\n uiSchema?.['ui:options']?.requestUserCredentials?.secretsKey &&\n secrets[uiSchema['ui:options'].requestUserCredentials.secretsKey]\n }\n />\n )}\n {hostType === 'bitbucket' && (\n <BitbucketRepoPicker\n allowedOwners={allowedOwners}\n allowedProjects={allowedProjects}\n rawErrors={rawErrors}\n state={state}\n onChange={updateLocalState}\n accessToken={\n uiSchema?.['ui:options']?.requestUserCredentials?.secretsKey &&\n secrets[uiSchema['ui:options'].requestUserCredentials.secretsKey]\n }\n />\n )}\n {hostType === 'azure' && (\n <AzureRepoPicker\n allowedOrganizations={allowedOrganizations}\n allowedProject={allowedProjects}\n rawErrors={rawErrors}\n state={state}\n onChange={updateLocalState}\n />\n )}\n {hostType === 'gerrit' && (\n <GerritRepoPicker\n rawErrors={rawErrors}\n state={state}\n onChange={updateLocalState}\n />\n )}\n <RepoUrlPickerRepoName\n repoName={state.repoName}\n allowedRepos={allowedRepos}\n onChange={repo =>\n setState(prevState => ({\n ...prevState,\n repoName: repo.name,\n id: repo.id || '',\n }))\n }\n rawErrors={rawErrors}\n availableRepos={state.availableRepos}\n />\n </>\n );\n};\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"RepoUrlPicker.esm.js","sources":["../../../../src/components/fields/RepoUrlPicker/RepoUrlPicker.tsx"],"sourcesContent":["/*\n * Copyright 2021 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { useApi } from '@backstage/core-plugin-api';\nimport {\n scmAuthApiRef,\n scmIntegrationsApiRef,\n} from '@backstage/integration-react';\nimport { useTemplateSecrets } from '@backstage/plugin-scaffolder-react';\nimport Box from '@material-ui/core/Box';\nimport Divider from '@material-ui/core/Divider';\nimport Typography from '@material-ui/core/Typography';\nimport React, { useCallback, useEffect, useMemo, useState } from 'react';\nimport useDebounce from 'react-use/esm/useDebounce';\nimport { AzureRepoPicker } from './AzureRepoPicker';\nimport { BitbucketRepoPicker } from './BitbucketRepoPicker';\nimport { GerritRepoPicker } from './GerritRepoPicker';\nimport { GiteaRepoPicker } from './GiteaRepoPicker';\nimport { GithubRepoPicker } from './GithubRepoPicker';\nimport { GitlabRepoPicker } from './GitlabRepoPicker';\nimport { RepoUrlPickerHost } from './RepoUrlPickerHost';\nimport { RepoUrlPickerRepoName } from './RepoUrlPickerRepoName';\nimport { RepoUrlPickerFieldSchema } from './schema';\nimport { RepoUrlPickerState } from './types';\nimport { parseRepoPickerUrl, serializeRepoPickerUrl } from './utils';\n\nexport { RepoUrlPickerSchema } from './schema';\n\n/**\n * The underlying component that is rendered in the form for the `RepoUrlPicker`\n * field extension.\n *\n * @public\n */\nexport const RepoUrlPicker = (\n props: typeof RepoUrlPickerFieldSchema.TProps,\n) => {\n const { uiSchema, onChange, rawErrors, formData, schema } = props;\n const [state, setState] = useState<RepoUrlPickerState>(\n parseRepoPickerUrl(formData),\n );\n const [credentialsHost, setCredentialsHost] = useState<string | undefined>(\n undefined,\n );\n const integrationApi = useApi(scmIntegrationsApiRef);\n const scmAuthApi = useApi(scmAuthApiRef);\n const { secrets, setSecrets } = useTemplateSecrets();\n const allowedHosts = useMemo(\n () => uiSchema?.['ui:options']?.allowedHosts ?? [],\n [uiSchema],\n );\n const allowedOrganizations = useMemo(\n () => uiSchema?.['ui:options']?.allowedOrganizations ?? [],\n [uiSchema],\n );\n const allowedOwners = useMemo(\n () => uiSchema?.['ui:options']?.allowedOwners ?? [],\n [uiSchema],\n );\n const allowedProjects = useMemo(\n () => uiSchema?.['ui:options']?.allowedProjects ?? [],\n [uiSchema],\n );\n const allowedRepos = useMemo(\n () => uiSchema?.['ui:options']?.allowedRepos ?? [],\n [uiSchema],\n );\n\n const { owner, organization, project, repoName } = state;\n\n useEffect(() => {\n onChange(serializeRepoPickerUrl(state));\n }, [state, onChange]);\n\n /* we deal with calling the repo setting here instead of in each components for ease */\n useEffect(() => {\n if (allowedOrganizations.length > 0 && !organization) {\n setState(prevState => ({\n ...prevState,\n organization: allowedOrganizations[0],\n }));\n }\n }, [setState, allowedOrganizations, organization]);\n\n useEffect(() => {\n if (allowedOwners.length > 0 && !owner) {\n setState(prevState => ({\n ...prevState,\n owner: allowedOwners[0],\n }));\n }\n }, [setState, allowedOwners, owner]);\n\n useEffect(() => {\n if (allowedProjects.length > 0 && !project) {\n setState(prevState => ({\n ...prevState,\n project: allowedProjects[0],\n }));\n }\n }, [setState, allowedProjects, project]);\n\n useEffect(() => {\n if (allowedRepos.length > 0 && !repoName) {\n setState(prevState => ({ ...prevState, repoName: allowedRepos[0] }));\n }\n }, [setState, allowedRepos, repoName]);\n\n const updateLocalState = useCallback(\n (newState: RepoUrlPickerState) => {\n setState(prevState => ({ ...prevState, ...newState }));\n },\n [setState],\n );\n\n useDebounce(\n async () => {\n const { requestUserCredentials } = uiSchema?.['ui:options'] ?? {};\n\n if (!requestUserCredentials || !state.host) {\n return;\n }\n\n // don't show login prompt if secret value is already in state for selected host\n if (\n secrets[requestUserCredentials.secretsKey] &&\n credentialsHost === state.host\n ) {\n return;\n }\n\n // user has requested that we use the users credentials\n // so lets grab them using the scmAuthApi and pass through\n // any additional scopes from the ui:options\n const { token } = await scmAuthApi.getCredentials({\n url: `https://${state.host}`,\n additionalScope: {\n repoWrite: true,\n customScopes: requestUserCredentials.additionalScopes,\n },\n });\n\n // set the secret using the key provided in the ui:options for use\n // in the templating the manifest with ${{ secrets[secretsKey] }}\n setSecrets({ [requestUserCredentials.secretsKey]: token });\n setCredentialsHost(state.host);\n },\n 500,\n [state, uiSchema],\n );\n\n const hostType =\n (state.host && integrationApi.byHost(state.host)?.type) ?? null;\n return (\n <>\n {schema.title && (\n <Box my={1}>\n <Typography variant=\"h5\">{schema.title}</Typography>\n <Divider />\n </Box>\n )}\n {schema.description && (\n <Typography variant=\"body1\">{schema.description}</Typography>\n )}\n <RepoUrlPickerHost\n host={state.host}\n hosts={allowedHosts}\n onChange={host => setState(prevState => ({ ...prevState, host }))}\n rawErrors={rawErrors}\n />\n {hostType === 'github' && (\n <GithubRepoPicker\n allowedOwners={allowedOwners}\n onChange={updateLocalState}\n rawErrors={rawErrors}\n state={state}\n accessToken={\n uiSchema?.['ui:options']?.requestUserCredentials?.secretsKey &&\n secrets[uiSchema['ui:options'].requestUserCredentials.secretsKey]\n }\n />\n )}\n {hostType === 'gitea' && (\n <GiteaRepoPicker\n allowedOwners={allowedOwners}\n allowedRepos={allowedRepos}\n rawErrors={rawErrors}\n state={state}\n onChange={updateLocalState}\n />\n )}\n {hostType === 'gitlab' && (\n <GitlabRepoPicker\n allowedOwners={allowedOwners}\n rawErrors={rawErrors}\n state={state}\n onChange={updateLocalState}\n accessToken={\n uiSchema?.['ui:options']?.requestUserCredentials?.secretsKey &&\n secrets[uiSchema['ui:options'].requestUserCredentials.secretsKey]\n }\n />\n )}\n {hostType === 'bitbucket' && (\n <BitbucketRepoPicker\n allowedOwners={allowedOwners}\n allowedProjects={allowedProjects}\n rawErrors={rawErrors}\n state={state}\n onChange={updateLocalState}\n accessToken={\n uiSchema?.['ui:options']?.requestUserCredentials?.secretsKey &&\n secrets[uiSchema['ui:options'].requestUserCredentials.secretsKey]\n }\n />\n )}\n {hostType === 'azure' && (\n <AzureRepoPicker\n allowedOrganizations={allowedOrganizations}\n allowedProject={allowedProjects}\n rawErrors={rawErrors}\n state={state}\n onChange={updateLocalState}\n />\n )}\n {hostType === 'gerrit' && (\n <GerritRepoPicker\n rawErrors={rawErrors}\n state={state}\n onChange={updateLocalState}\n />\n )}\n <RepoUrlPickerRepoName\n repoName={state.repoName}\n allowedRepos={allowedRepos}\n onChange={repo =>\n setState(prevState => ({\n ...prevState,\n repoName: repo.id || repo.name,\n }))\n }\n rawErrors={rawErrors}\n availableRepos={state.availableRepos}\n />\n </>\n );\n};\n"],"names":[],"mappings":"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"}
|
|
@@ -18,9 +18,6 @@ function serializeRepoPickerUrl(data) {
|
|
|
18
18
|
if (data.project) {
|
|
19
19
|
params.set("project", data.project);
|
|
20
20
|
}
|
|
21
|
-
if (data.id) {
|
|
22
|
-
params.set("id", data.id);
|
|
23
|
-
}
|
|
24
21
|
return `${data.host}?${params.toString()}`;
|
|
25
22
|
}
|
|
26
23
|
function parseRepoPickerUrl(url) {
|
|
@@ -30,7 +27,6 @@ function parseRepoPickerUrl(url) {
|
|
|
30
27
|
let organization = "";
|
|
31
28
|
let workspace = "";
|
|
32
29
|
let project = "";
|
|
33
|
-
let id = "";
|
|
34
30
|
try {
|
|
35
31
|
if (url) {
|
|
36
32
|
const parsed = new URL(`https://${url}`);
|
|
@@ -40,11 +36,10 @@ function parseRepoPickerUrl(url) {
|
|
|
40
36
|
organization = parsed.searchParams.get("organization") || "";
|
|
41
37
|
workspace = parsed.searchParams.get("workspace") || "";
|
|
42
38
|
project = parsed.searchParams.get("project") || "";
|
|
43
|
-
id = parsed.searchParams.get("id") || "";
|
|
44
39
|
}
|
|
45
40
|
} catch {
|
|
46
41
|
}
|
|
47
|
-
return { host, owner, repoName, organization, workspace, project
|
|
42
|
+
return { host, owner, repoName, organization, workspace, project };
|
|
48
43
|
}
|
|
49
44
|
|
|
50
45
|
export { parseRepoPickerUrl, serializeRepoPickerUrl };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.esm.js","sources":["../../../../src/components/fields/RepoUrlPicker/utils.ts"],"sourcesContent":["/*\n * Copyright 2021 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { RepoUrlPickerState } from './types';\n\nexport function serializeRepoPickerUrl(data: RepoUrlPickerState) {\n if (!data.host) {\n return undefined;\n }\n\n const params = new URLSearchParams();\n if (data.owner) {\n params.set('owner', data.owner);\n }\n if (data.repoName) {\n params.set('repo', data.repoName);\n }\n if (data.organization) {\n params.set('organization', data.organization);\n }\n if (data.workspace) {\n params.set('workspace', data.workspace);\n }\n if (data.project) {\n params.set('project', data.project);\n }\n
|
|
1
|
+
{"version":3,"file":"utils.esm.js","sources":["../../../../src/components/fields/RepoUrlPicker/utils.ts"],"sourcesContent":["/*\n * Copyright 2021 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { RepoUrlPickerState } from './types';\n\nexport function serializeRepoPickerUrl(data: RepoUrlPickerState) {\n if (!data.host) {\n return undefined;\n }\n\n const params = new URLSearchParams();\n if (data.owner) {\n params.set('owner', data.owner);\n }\n if (data.repoName) {\n params.set('repo', data.repoName);\n }\n if (data.organization) {\n params.set('organization', data.organization);\n }\n if (data.workspace) {\n params.set('workspace', data.workspace);\n }\n if (data.project) {\n params.set('project', data.project);\n }\n\n return `${data.host}?${params.toString()}`;\n}\n\nexport function parseRepoPickerUrl(\n url: string | undefined,\n): RepoUrlPickerState {\n let host = '';\n let owner = '';\n let repoName = '';\n let organization = '';\n let workspace = '';\n let project = '';\n\n try {\n if (url) {\n const parsed = new URL(`https://${url}`);\n host = parsed.host;\n owner = parsed.searchParams.get('owner') || '';\n repoName = parsed.searchParams.get('repo') || '';\n organization = parsed.searchParams.get('organization') || '';\n workspace = parsed.searchParams.get('workspace') || '';\n project = parsed.searchParams.get('project') || '';\n }\n } catch {\n /* ok */\n }\n return { host, owner, repoName, organization, workspace, project };\n}\n"],"names":[],"mappings":"AAkBO,SAAS,uBAAuB,IAA0B,EAAA;AAC/D,EAAI,IAAA,CAAC,KAAK,IAAM,EAAA;AACd,IAAO,OAAA,KAAA,CAAA;AAAA;AAGT,EAAM,MAAA,MAAA,GAAS,IAAI,eAAgB,EAAA;AACnC,EAAA,IAAI,KAAK,KAAO,EAAA;AACd,IAAO,MAAA,CAAA,GAAA,CAAI,OAAS,EAAA,IAAA,CAAK,KAAK,CAAA;AAAA;AAEhC,EAAA,IAAI,KAAK,QAAU,EAAA;AACjB,IAAO,MAAA,CAAA,GAAA,CAAI,MAAQ,EAAA,IAAA,CAAK,QAAQ,CAAA;AAAA;AAElC,EAAA,IAAI,KAAK,YAAc,EAAA;AACrB,IAAO,MAAA,CAAA,GAAA,CAAI,cAAgB,EAAA,IAAA,CAAK,YAAY,CAAA;AAAA;AAE9C,EAAA,IAAI,KAAK,SAAW,EAAA;AAClB,IAAO,MAAA,CAAA,GAAA,CAAI,WAAa,EAAA,IAAA,CAAK,SAAS,CAAA;AAAA;AAExC,EAAA,IAAI,KAAK,OAAS,EAAA;AAChB,IAAO,MAAA,CAAA,GAAA,CAAI,SAAW,EAAA,IAAA,CAAK,OAAO,CAAA;AAAA;AAGpC,EAAA,OAAO,GAAG,IAAK,CAAA,IAAI,CAAI,CAAA,EAAA,MAAA,CAAO,UAAU,CAAA,CAAA;AAC1C;AAEO,SAAS,mBACd,GACoB,EAAA;AACpB,EAAA,IAAI,IAAO,GAAA,EAAA;AACX,EAAA,IAAI,KAAQ,GAAA,EAAA;AACZ,EAAA,IAAI,QAAW,GAAA,EAAA;AACf,EAAA,IAAI,YAAe,GAAA,EAAA;AACnB,EAAA,IAAI,SAAY,GAAA,EAAA;AAChB,EAAA,IAAI,OAAU,GAAA,EAAA;AAEd,EAAI,IAAA;AACF,IAAA,IAAI,GAAK,EAAA;AACP,MAAA,MAAM,MAAS,GAAA,IAAI,GAAI,CAAA,CAAA,QAAA,EAAW,GAAG,CAAE,CAAA,CAAA;AACvC,MAAA,IAAA,GAAO,MAAO,CAAA,IAAA;AACd,MAAA,KAAA,GAAQ,MAAO,CAAA,YAAA,CAAa,GAAI,CAAA,OAAO,CAAK,IAAA,EAAA;AAC5C,MAAA,QAAA,GAAW,MAAO,CAAA,YAAA,CAAa,GAAI,CAAA,MAAM,CAAK,IAAA,EAAA;AAC9C,MAAA,YAAA,GAAe,MAAO,CAAA,YAAA,CAAa,GAAI,CAAA,cAAc,CAAK,IAAA,EAAA;AAC1D,MAAA,SAAA,GAAY,MAAO,CAAA,YAAA,CAAa,GAAI,CAAA,WAAW,CAAK,IAAA,EAAA;AACpD,MAAA,OAAA,GAAU,MAAO,CAAA,YAAA,CAAa,GAAI,CAAA,SAAS,CAAK,IAAA,EAAA;AAAA;AAClD,GACM,CAAA,MAAA;AAAA;AAGR,EAAA,OAAO,EAAE,IAAM,EAAA,KAAA,EAAO,QAAU,EAAA,YAAA,EAAc,WAAW,OAAQ,EAAA;AACnE;;;;"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@backstage/plugin-scaffolder",
|
|
3
|
-
"version": "1.28.0-next.
|
|
3
|
+
"version": "1.28.0-next.2",
|
|
4
4
|
"description": "The Backstage plugin that helps you create new things",
|
|
5
5
|
"backstage": {
|
|
6
6
|
"role": "frontend-plugin",
|
|
@@ -12,7 +12,10 @@
|
|
|
12
12
|
"@backstage/plugin-scaffolder-node",
|
|
13
13
|
"@backstage/plugin-scaffolder-node-test-utils",
|
|
14
14
|
"@backstage/plugin-scaffolder-react"
|
|
15
|
-
]
|
|
15
|
+
],
|
|
16
|
+
"features": {
|
|
17
|
+
"./alpha": "@backstage/FrontendPlugin"
|
|
18
|
+
}
|
|
16
19
|
},
|
|
17
20
|
"publishConfig": {
|
|
18
21
|
"access": "public"
|
|
@@ -69,18 +72,18 @@
|
|
|
69
72
|
"dependencies": {
|
|
70
73
|
"@backstage/catalog-client": "1.9.1",
|
|
71
74
|
"@backstage/catalog-model": "1.7.3",
|
|
72
|
-
"@backstage/core-compat-api": "0.3.6-next.
|
|
73
|
-
"@backstage/core-components": "0.16.4-next.
|
|
75
|
+
"@backstage/core-compat-api": "0.3.6-next.2",
|
|
76
|
+
"@backstage/core-components": "0.16.4-next.1",
|
|
74
77
|
"@backstage/core-plugin-api": "1.10.4-next.0",
|
|
75
78
|
"@backstage/errors": "1.2.7",
|
|
76
|
-
"@backstage/frontend-plugin-api": "0.9.5-next.
|
|
79
|
+
"@backstage/frontend-plugin-api": "0.9.5-next.2",
|
|
77
80
|
"@backstage/integration": "1.16.1",
|
|
78
81
|
"@backstage/integration-react": "1.2.4-next.0",
|
|
79
82
|
"@backstage/plugin-catalog-common": "1.1.3",
|
|
80
|
-
"@backstage/plugin-catalog-react": "1.15.2-next.
|
|
83
|
+
"@backstage/plugin-catalog-react": "1.15.2-next.2",
|
|
81
84
|
"@backstage/plugin-permission-react": "0.4.31-next.0",
|
|
82
85
|
"@backstage/plugin-scaffolder-common": "1.5.9",
|
|
83
|
-
"@backstage/plugin-scaffolder-react": "1.14.
|
|
86
|
+
"@backstage/plugin-scaffolder-react": "1.14.5-next.2",
|
|
84
87
|
"@backstage/types": "1.2.1",
|
|
85
88
|
"@codemirror/language": "^6.0.0",
|
|
86
89
|
"@codemirror/legacy-modes": "^6.1.0",
|
|
@@ -114,10 +117,10 @@
|
|
|
114
117
|
"zod-to-json-schema": "^3.20.4"
|
|
115
118
|
},
|
|
116
119
|
"devDependencies": {
|
|
117
|
-
"@backstage/cli": "0.30.0-next.
|
|
120
|
+
"@backstage/cli": "0.30.0-next.2",
|
|
118
121
|
"@backstage/core-app-api": "1.15.5-next.0",
|
|
119
|
-
"@backstage/dev-utils": "1.1.7-next.
|
|
120
|
-
"@backstage/plugin-catalog": "1.
|
|
122
|
+
"@backstage/dev-utils": "1.1.7-next.2",
|
|
123
|
+
"@backstage/plugin-catalog": "1.27.0-next.2",
|
|
121
124
|
"@backstage/plugin-permission-common": "0.8.4",
|
|
122
125
|
"@backstage/test-utils": "1.7.5-next.0",
|
|
123
126
|
"@testing-library/dom": "^10.0.0",
|