@backstage/plugin-scaffolder 0.11.14 → 0.11.18

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.
@@ -2,19 +2,20 @@ import { createApiRef, useApi, attachComponentData, createExternalRouteRef, crea
2
2
  import { ResponseError } from '@backstage/errors';
3
3
  import qs from 'qs';
4
4
  import ObservableImpl from 'zen-observable';
5
- import { catalogApiRef, formatEntityRefTitle, useStarredEntity, getEntityRelations, getEntitySourceLocation, EntityRefLinks, useEntityListProvider, useEntityTypeFilter } from '@backstage/plugin-catalog-react';
6
- import { TextField, withStyles, makeStyles, IconButton, Tooltip, useTheme, Card, CardMedia, CardContent, Box, Typography, Chip, CardActions, Link, FormControlLabel, Checkbox } from '@material-ui/core';
5
+ import { catalogApiRef, formatEntityRefTitle, useOwnedEntities, useStarredEntity, getEntityRelations, getEntitySourceLocation, EntityRefLinks, useEntityListProvider, useEntityTypeFilter } from '@backstage/plugin-catalog-react';
6
+ import { TextField, FormControl as FormControl$1, withStyles, makeStyles, IconButton, Tooltip, useTheme, Card, CardMedia, CardContent, Box, Typography, Chip, CardActions, Link, FormControlLabel, Checkbox } from '@material-ui/core';
7
7
  import FormControl from '@material-ui/core/FormControl';
8
8
  import Autocomplete from '@material-ui/lab/Autocomplete';
9
- import React, { useCallback, useEffect } from 'react';
10
- import { useAsync } from 'react-use';
11
- import { KubernetesValidatorFunctions, RELATION_OWNED_BY, stringifyEntityRef } from '@backstage/catalog-model';
9
+ import React, { useCallback, useEffect, useState } from 'react';
10
+ import useAsync from 'react-use/lib/useAsync';
11
+ import { KubernetesValidatorFunctions, makeValidator, RELATION_OWNED_BY, stringifyEntityRef } from '@backstage/catalog-model';
12
+ import { useAsync as useAsync$1, useEffectOnce } from 'react-use';
13
+ import { Autocomplete as Autocomplete$1 } from '@material-ui/lab';
14
+ import { Progress, Select, ItemCardHeader, Button, ContentHeader, WarningPanel, Link as Link$1, Content, ItemCardGrid } from '@backstage/core-components';
12
15
  import { scmIntegrationsApiRef, ScmIntegrationIcon } from '@backstage/integration-react';
13
- import Select from '@material-ui/core/Select';
14
- import InputLabel from '@material-ui/core/InputLabel';
15
- import Input from '@material-ui/core/Input';
16
16
  import FormHelperText from '@material-ui/core/FormHelperText';
17
- import { Progress, ItemCardHeader, Button, ContentHeader, WarningPanel, Content, ItemCardGrid } from '@backstage/core-components';
17
+ import Input from '@material-ui/core/Input';
18
+ import InputLabel from '@material-ui/core/InputLabel';
18
19
  import Star from '@material-ui/icons/Star';
19
20
  import StarBorder from '@material-ui/icons/StarBorder';
20
21
  import WarningIcon from '@material-ui/icons/Warning';
@@ -23,11 +24,9 @@ import capitalize from 'lodash/capitalize';
23
24
  import CheckBoxIcon from '@material-ui/icons/CheckBox';
24
25
  import CheckBoxOutlineBlankIcon from '@material-ui/icons/CheckBoxOutlineBlank';
25
26
  import ExpandMoreIcon from '@material-ui/icons/ExpandMore';
26
- import { Autocomplete as Autocomplete$1 } from '@material-ui/lab';
27
27
 
28
28
  const scaffolderApiRef = createApiRef({
29
- id: "plugin.scaffolder.service",
30
- description: "Used to make requests towards the scaffolder backend"
29
+ id: "plugin.scaffolder.service"
31
30
  });
32
31
  class ScaffolderClient {
33
32
  constructor(options) {
@@ -179,6 +178,10 @@ class ScaffolderClient {
179
178
  }
180
179
  }
181
180
 
181
+ const allowArbitraryValues = (uiSchema) => {
182
+ var _a, _b;
183
+ return (_b = (_a = uiSchema["ui:options"]) == null ? void 0 : _a.allowArbitraryValues) != null ? _b : true;
184
+ };
182
185
  const EntityPicker = ({
183
186
  onChange,
184
187
  schema: { title = "Entity", description = "An entity from the catalog" },
@@ -194,21 +197,27 @@ const EntityPicker = ({
194
197
  const catalogApi = useApi(catalogApiRef);
195
198
  const { value: entities, loading } = useAsync(() => catalogApi.getEntities(allowedKinds ? { filter: { kind: allowedKinds } } : void 0));
196
199
  const entityRefs = entities == null ? void 0 : entities.items.map((e) => formatEntityRefTitle(e, { defaultKind }));
197
- const onSelect = (_, value) => {
200
+ const onSelect = useCallback((_, value) => {
198
201
  onChange(value || "");
199
- };
202
+ }, [onChange]);
203
+ useEffect(() => {
204
+ if ((entityRefs == null ? void 0 : entityRefs.length) === 1) {
205
+ onChange(entityRefs[0]);
206
+ }
207
+ }, [entityRefs, onChange]);
200
208
  return /* @__PURE__ */ React.createElement(FormControl, {
201
209
  margin: "normal",
202
210
  required,
203
211
  error: (rawErrors == null ? void 0 : rawErrors.length) > 0 && !formData
204
212
  }, /* @__PURE__ */ React.createElement(Autocomplete, {
213
+ disabled: (entityRefs == null ? void 0 : entityRefs.length) === 1,
205
214
  id: idSchema == null ? void 0 : idSchema.$id,
206
215
  value: formData || "",
207
216
  loading,
208
217
  onChange: onSelect,
209
218
  options: entityRefs || [],
210
219
  autoSelect: true,
211
- freeSolo: true,
220
+ freeSolo: allowArbitraryValues(uiSchema),
212
221
  renderInput: (params) => /* @__PURE__ */ React.createElement(TextField, {
213
222
  ...params,
214
223
  label: title,
@@ -257,6 +266,68 @@ const entityNamePickerValidation = (value, validation) => {
257
266
  }
258
267
  };
259
268
 
269
+ const EntityTagsPicker = ({
270
+ formData,
271
+ onChange,
272
+ uiSchema
273
+ }) => {
274
+ var _a;
275
+ const catalogApi = useApi(catalogApiRef);
276
+ const [inputValue, setInputValue] = useState("");
277
+ const [inputError, setInputError] = useState(false);
278
+ const tagValidator = makeValidator().isValidTag;
279
+ const kinds = (_a = uiSchema["ui:options"]) == null ? void 0 : _a.kinds;
280
+ const { loading, value: existingTags } = useAsync$1(async () => {
281
+ const tagsRequest = { fields: ["metadata.tags"] };
282
+ if (kinds) {
283
+ tagsRequest.filter = { kind: kinds };
284
+ }
285
+ const entities = await catalogApi.getEntities(tagsRequest);
286
+ return [
287
+ ...new Set(entities.items.flatMap((e) => {
288
+ var _a2;
289
+ return (_a2 = e.metadata) == null ? void 0 : _a2.tags;
290
+ }).filter(Boolean))
291
+ ].sort();
292
+ });
293
+ const setTags = (_, values) => {
294
+ let hasError = false;
295
+ let addDuplicate = false;
296
+ const currentTags = formData || [];
297
+ if ((values == null ? void 0 : values.length) && currentTags.length < values.length) {
298
+ const newTag = values[values.length - 1] = values[values.length - 1].toLocaleLowerCase("en-US").trim();
299
+ hasError = !tagValidator(newTag);
300
+ addDuplicate = currentTags.indexOf(newTag) !== -1;
301
+ }
302
+ setInputError(hasError);
303
+ setInputValue(!hasError ? "" : inputValue);
304
+ if (!hasError && !addDuplicate) {
305
+ onChange(values || []);
306
+ }
307
+ };
308
+ useEffectOnce(() => onChange(formData || []));
309
+ return /* @__PURE__ */ React.createElement(FormControl$1, {
310
+ margin: "normal"
311
+ }, /* @__PURE__ */ React.createElement(Autocomplete$1, {
312
+ multiple: true,
313
+ freeSolo: true,
314
+ filterSelectedOptions: true,
315
+ onChange: setTags,
316
+ value: formData || [],
317
+ inputValue,
318
+ loading,
319
+ options: existingTags || [],
320
+ ChipProps: { size: "small" },
321
+ renderInput: (params) => /* @__PURE__ */ React.createElement(TextField, {
322
+ ...params,
323
+ label: "Tags",
324
+ onChange: (e) => setInputValue(e.target.value),
325
+ error: inputError,
326
+ helperText: "Add any relevant tags, hit 'Enter' to add new tags. Valid format: [a-z0-9+#] separated by [-], at most 63 characters"
327
+ })
328
+ }));
329
+ };
330
+
260
331
  const OwnerPicker = ({
261
332
  schema: { title = "Owner", description = "The owner of the component" },
262
333
  uiSchema,
@@ -338,9 +409,9 @@ const RepoUrlPicker = ({
338
409
  return await scaffolderApi.getIntegrationsList({ allowedHosts });
339
410
  });
340
411
  const { host, owner, repo, organization, workspace, project } = splitFormData(formData, allowedOwners);
341
- const updateHost = useCallback((evt) => {
412
+ const updateHost = useCallback((value) => {
342
413
  onChange(serializeFormData({
343
- host: evt.target.value,
414
+ host: value,
344
415
  owner,
345
416
  repo,
346
417
  organization,
@@ -348,6 +419,14 @@ const RepoUrlPicker = ({
348
419
  project
349
420
  }));
350
421
  }, [onChange, owner, repo, organization, workspace, project]);
422
+ const updateOwnerSelect = useCallback((value) => onChange(serializeFormData({
423
+ host,
424
+ owner: value,
425
+ repo,
426
+ organization,
427
+ workspace,
428
+ project
429
+ })), [onChange, host, repo, organization, workspace, project]);
351
430
  const updateOwner = useCallback((evt) => onChange(serializeFormData({
352
431
  host,
353
432
  owner: evt.target.value,
@@ -412,21 +491,20 @@ const RepoUrlPicker = ({
412
491
  if (loading) {
413
492
  return /* @__PURE__ */ React.createElement(Progress, null);
414
493
  }
494
+ const hostsOptions = integrations ? integrations.filter((i) => allowedHosts == null ? void 0 : allowedHosts.includes(i.host)).map((i) => ({ label: i.title, value: i.host })) : [{ label: "Loading...", value: "loading" }];
495
+ const ownersOptions = allowedOwners ? allowedOwners.map((i) => ({ label: i, value: i })) : [{ label: "Loading...", value: "loading" }];
415
496
  return /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(FormControl, {
416
497
  margin: "normal",
417
498
  required: true,
418
499
  error: (rawErrors == null ? void 0 : rawErrors.length) > 0 && !host
419
- }, /* @__PURE__ */ React.createElement(InputLabel, {
420
- htmlFor: "hostInput"
421
- }, "Host"), /* @__PURE__ */ React.createElement(Select, {
500
+ }, /* @__PURE__ */ React.createElement(Select, {
422
501
  native: true,
423
- id: "hostInput",
502
+ disabled: hostsOptions.length === 1,
503
+ label: "Host",
424
504
  onChange: updateHost,
425
- value: host
426
- }, integrations ? integrations.filter((i) => allowedHosts == null ? void 0 : allowedHosts.includes(i.host)).map((i) => /* @__PURE__ */ React.createElement("option", {
427
- key: i.host,
428
- value: i.host
429
- }, i.title)) : /* @__PURE__ */ React.createElement("p", null, "loading")), /* @__PURE__ */ React.createElement(FormHelperText, null, "The host where the repository will be created")), host === "dev.azure.com" && /* @__PURE__ */ React.createElement(FormControl, {
505
+ selected: host,
506
+ items: hostsOptions
507
+ }), /* @__PURE__ */ React.createElement(FormHelperText, null, "The host where the repository will be created")), host === "dev.azure.com" && /* @__PURE__ */ React.createElement(FormControl, {
430
508
  margin: "normal",
431
509
  required: true,
432
510
  error: (rawErrors == null ? void 0 : rawErrors.length) > 0 && !organization
@@ -470,17 +548,14 @@ const RepoUrlPicker = ({
470
548
  margin: "normal",
471
549
  required: true,
472
550
  error: (rawErrors == null ? void 0 : rawErrors.length) > 0 && !owner
473
- }, /* @__PURE__ */ React.createElement(InputLabel, {
474
- htmlFor: "ownerInput"
475
- }, "Owner Available"), /* @__PURE__ */ React.createElement(Select, {
551
+ }, /* @__PURE__ */ React.createElement(Select, {
476
552
  native: true,
477
- id: "ownerInput",
478
- onChange: updateOwner,
479
- value: owner
480
- }, allowedOwners ? allowedOwners.map((i) => /* @__PURE__ */ React.createElement("option", {
481
- key: i,
482
- value: i
483
- }, i)) : /* @__PURE__ */ React.createElement("p", null, "loading"), ";"), /* @__PURE__ */ React.createElement(FormHelperText, null, "The organization, user or project that this repo will belong to"))), /* @__PURE__ */ React.createElement(FormControl, {
553
+ label: "Owner Available",
554
+ onChange: updateOwnerSelect,
555
+ disabled: ownersOptions.length === 1,
556
+ selected: owner,
557
+ items: ownersOptions
558
+ }), /* @__PURE__ */ React.createElement(FormHelperText, null, "The organization, user or project that this repo will belong to"))), /* @__PURE__ */ React.createElement(FormControl, {
484
559
  margin: "normal",
485
560
  required: true,
486
561
  error: (rawErrors == null ? void 0 : rawErrors.length) > 0 && !repo
@@ -522,6 +597,47 @@ const repoPickerValidation = (value, validation, context) => {
522
597
  }
523
598
  };
524
599
 
600
+ const OwnedEntityPicker = ({
601
+ onChange,
602
+ schema: { title = "Entity", description = "An entity from the catalog" },
603
+ required,
604
+ uiSchema,
605
+ rawErrors,
606
+ formData,
607
+ idSchema
608
+ }) => {
609
+ var _a, _b;
610
+ const allowedKinds = (_a = uiSchema["ui:options"]) == null ? void 0 : _a.allowedKinds;
611
+ const defaultKind = (_b = uiSchema["ui:options"]) == null ? void 0 : _b.defaultKind;
612
+ const { ownedEntities, loading } = useOwnedEntities(allowedKinds);
613
+ const entityRefs = ownedEntities == null ? void 0 : ownedEntities.items.map((e) => formatEntityRefTitle(e, { defaultKind })).filter((n) => n);
614
+ const onSelect = (_, value) => {
615
+ onChange(value || "");
616
+ };
617
+ return /* @__PURE__ */ React.createElement(FormControl, {
618
+ margin: "normal",
619
+ required,
620
+ error: (rawErrors == null ? void 0 : rawErrors.length) > 0 && !formData
621
+ }, /* @__PURE__ */ React.createElement(Autocomplete, {
622
+ id: idSchema == null ? void 0 : idSchema.$id,
623
+ value: formData || "",
624
+ loading,
625
+ onChange: onSelect,
626
+ options: entityRefs || [],
627
+ autoSelect: true,
628
+ freeSolo: true,
629
+ renderInput: (params) => /* @__PURE__ */ React.createElement(TextField, {
630
+ ...params,
631
+ label: title,
632
+ margin: "normal",
633
+ helperText: description,
634
+ variant: "outlined",
635
+ required,
636
+ InputProps: params.InputProps
637
+ })
638
+ }));
639
+ };
640
+
525
641
  const FIELD_EXTENSION_WRAPPER_KEY = "scaffolder.extensions.wrapper.v1";
526
642
  const FIELD_EXTENSION_KEY = "scaffolder.extensions.field.v1";
527
643
  function createScaffolderFieldExtension(options) {
@@ -584,9 +700,17 @@ const OwnerPickerFieldExtension = scaffolderPlugin.provide(createScaffolderField
584
700
  }));
585
701
  const ScaffolderPage = scaffolderPlugin.provide(createRoutableExtension({
586
702
  name: "ScaffolderPage",
587
- component: () => import('./Router-0282e15a.esm.js').then((m) => m.Router),
703
+ component: () => import('./Router-552fb2ce.esm.js').then((m) => m.Router),
588
704
  mountPoint: rootRouteRef
589
705
  }));
706
+ const OwnedEntityPickerFieldExtension = scaffolderPlugin.provide(createScaffolderFieldExtension({
707
+ component: OwnedEntityPicker,
708
+ name: "OwnedEntityPicker"
709
+ }));
710
+ const EntityTagsPickerFieldExtension = scaffolderPlugin.provide(createScaffolderFieldExtension({
711
+ component: EntityTagsPicker,
712
+ name: "EntityTagsPicker"
713
+ }));
590
714
 
591
715
  const YellowStar = withStyles({
592
716
  root: {
@@ -760,8 +884,8 @@ const TemplateList = ({
760
884
  title: "Oops! Something went wrong loading the templates"
761
885
  }, error.message), !error && !loading && !entities.length && /* @__PURE__ */ React.createElement(Typography, {
762
886
  variant: "body2"
763
- }, "No templates found that match your filter. Learn more about", " ", /* @__PURE__ */ React.createElement(Link, {
764
- href: "https://backstage.io/docs/features/software-templates/adding-templates"
887
+ }, "No templates found that match your filter. Learn more about", " ", /* @__PURE__ */ React.createElement(Link$1, {
888
+ to: "https://backstage.io/docs/features/software-templates/adding-templates"
765
889
  }, "adding templates"), "."), /* @__PURE__ */ React.createElement(Content, null, title, /* @__PURE__ */ React.createElement(ItemCardGrid, null, maybeFilteredEntities && (maybeFilteredEntities == null ? void 0 : maybeFilteredEntities.length) > 0 && maybeFilteredEntities.map((template) => /* @__PURE__ */ React.createElement(Card, {
766
890
  key: stringifyEntityRef(template),
767
891
  template
@@ -818,5 +942,5 @@ const TemplateTypePicker = () => {
818
942
  }));
819
943
  };
820
944
 
821
- export { EntityPicker as E, FIELD_EXTENSION_WRAPPER_KEY as F, OwnerPicker as O, RepoUrlPicker as R, ScaffolderClient as S, TemplateTypePicker as T, EntityNamePicker as a, registerComponentRouteRef as b, TemplateList as c, rootRouteRef as d, entityNamePickerValidation as e, FIELD_EXTENSION_KEY as f, createScaffolderFieldExtension as g, ScaffolderFieldExtensions as h, EntityPickerFieldExtension as i, EntityNamePickerFieldExtension as j, OwnerPickerFieldExtension as k, RepoUrlPickerFieldExtension as l, ScaffolderPage as m, scaffolderPlugin as n, TextValuePicker as o, FavouriteTemplate as p, repoPickerValidation as r, scaffolderApiRef as s };
822
- //# sourceMappingURL=index-306a8b5a.esm.js.map
945
+ export { EntityPicker as E, FIELD_EXTENSION_WRAPPER_KEY as F, OwnerPicker as O, RepoUrlPicker as R, ScaffolderClient as S, TemplateTypePicker as T, EntityNamePicker as a, EntityTagsPicker as b, OwnedEntityPicker as c, registerComponentRouteRef as d, entityNamePickerValidation as e, TemplateList as f, rootRouteRef as g, FIELD_EXTENSION_KEY as h, createScaffolderFieldExtension as i, ScaffolderFieldExtensions as j, EntityPickerFieldExtension as k, EntityNamePickerFieldExtension as l, EntityTagsPickerFieldExtension as m, OwnerPickerFieldExtension as n, OwnedEntityPickerFieldExtension as o, RepoUrlPickerFieldExtension as p, ScaffolderPage as q, repoPickerValidation as r, scaffolderApiRef as s, scaffolderPlugin as t, TextValuePicker as u, FavouriteTemplate as v };
946
+ //# sourceMappingURL=index-768702c3.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index-768702c3.esm.js","sources":["../../src/api.ts","../../src/components/fields/EntityPicker/EntityPicker.tsx","../../src/components/fields/TextValuePicker/TextValuePicker.tsx","../../src/components/fields/EntityNamePicker/EntityNamePicker.tsx","../../src/components/fields/EntityNamePicker/validation.ts","../../src/components/fields/EntityTagsPicker/EntityTagsPicker.tsx","../../src/components/fields/OwnerPicker/OwnerPicker.tsx","../../src/components/fields/RepoUrlPicker/RepoUrlPicker.tsx","../../src/components/fields/RepoUrlPicker/validation.ts","../../src/components/fields/OwnedEntityPicker/OwnedEntityPicker.tsx","../../src/extensions/index.tsx","../../src/routes.ts","../../src/plugin.ts","../../src/components/FavouriteTemplate/FavouriteTemplate.tsx","../../src/components/TemplateCard/TemplateCard.tsx","../../src/components/TemplateList/TemplateList.tsx","../../src/components/TemplateTypePicker/TemplateTypePicker.tsx"],"sourcesContent":["/*\n * Copyright 2020 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 { EntityName } from '@backstage/catalog-model';\nimport {\n createApiRef,\n DiscoveryApi,\n IdentityApi,\n} from '@backstage/core-plugin-api';\nimport { ResponseError } from '@backstage/errors';\nimport { ScmIntegrationRegistry } from '@backstage/integration';\nimport { JsonObject, JsonValue, Observable } from '@backstage/types';\nimport { Field, FieldValidation } from '@rjsf/core';\nimport qs from 'qs';\nimport ObservableImpl from 'zen-observable';\nimport { ListActionsResponse, ScaffolderTask, Status } from './types';\n\nexport const scaffolderApiRef = createApiRef<ScaffolderApi>({\n id: 'plugin.scaffolder.service',\n});\n\ntype TemplateParameterSchema = {\n title: string;\n steps: Array<{\n title: string;\n schema: JsonObject;\n }>;\n};\n\nexport type LogEvent = {\n type: 'log' | 'completion';\n body: {\n message: string;\n stepId?: string;\n status?: Status;\n };\n createdAt: string;\n id: string;\n taskId: string;\n};\n\nexport type CustomField = {\n name: string;\n component: Field;\n validation: (data: JsonValue, field: FieldValidation) => void;\n};\n\nexport interface ScaffolderApi {\n getTemplateParameterSchema(\n templateName: EntityName,\n ): Promise<TemplateParameterSchema>;\n\n /**\n * Executes the scaffolding of a component, given a template and its\n * parameter values.\n *\n * @param templateName - Name of the Template entity for the scaffolder to use. New project is going to be created out of this template.\n * @param values - Parameters for the template, e.g. name, description\n */\n scaffold(templateName: string, values: Record<string, any>): Promise<string>;\n\n getTask(taskId: string): Promise<ScaffolderTask>;\n\n getIntegrationsList(options: {\n allowedHosts: string[];\n }): Promise<{ type: string; title: string; host: string }[]>;\n\n // Returns a list of all installed actions.\n listActions(): Promise<ListActionsResponse>;\n\n streamLogs({\n taskId,\n after,\n }: {\n taskId: string;\n after?: number;\n }): Observable<LogEvent>;\n}\n\nexport class ScaffolderClient implements ScaffolderApi {\n private readonly discoveryApi: DiscoveryApi;\n private readonly identityApi: IdentityApi;\n private readonly scmIntegrationsApi: ScmIntegrationRegistry;\n private readonly useLongPollingLogs: boolean;\n\n constructor(options: {\n discoveryApi: DiscoveryApi;\n identityApi: IdentityApi;\n scmIntegrationsApi: ScmIntegrationRegistry;\n useLongPollingLogs?: boolean;\n }) {\n this.discoveryApi = options.discoveryApi;\n this.identityApi = options.identityApi;\n this.scmIntegrationsApi = options.scmIntegrationsApi;\n this.useLongPollingLogs = options.useLongPollingLogs ?? false;\n }\n\n async getIntegrationsList(options: { allowedHosts: string[] }) {\n return [\n ...this.scmIntegrationsApi.azure.list(),\n ...this.scmIntegrationsApi.bitbucket.list(),\n ...this.scmIntegrationsApi.github.list(),\n ...this.scmIntegrationsApi.gitlab.list(),\n ]\n .map(c => ({ type: c.type, title: c.title, host: c.config.host }))\n .filter(c => options.allowedHosts.includes(c.host));\n }\n\n async getTemplateParameterSchema(\n templateName: EntityName,\n ): Promise<TemplateParameterSchema> {\n const { namespace, kind, name } = templateName;\n\n const token = await this.identityApi.getIdToken();\n const baseUrl = await this.discoveryApi.getBaseUrl('scaffolder');\n const templatePath = [namespace, kind, name]\n .map(s => encodeURIComponent(s))\n .join('/');\n const url = `${baseUrl}/v2/templates/${templatePath}/parameter-schema`;\n\n const response = await fetch(url, {\n headers: {\n ...(token && { Authorization: `Bearer ${token}` }),\n },\n });\n\n if (!response.ok) {\n throw await ResponseError.fromResponse(response);\n }\n\n const schema: TemplateParameterSchema = await response.json();\n return schema;\n }\n\n /**\n * Executes the scaffolding of a component, given a template and its\n * parameter values.\n *\n * @param templateName - Template name for the scaffolder to use. New project is going to be created out of this template.\n * @param values - Parameters for the template, e.g. name, description\n */\n async scaffold(\n templateName: string,\n values: Record<string, any>,\n ): Promise<string> {\n const token = await this.identityApi.getIdToken();\n const url = `${await this.discoveryApi.getBaseUrl('scaffolder')}/v2/tasks`;\n const response = await fetch(url, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n ...(token && { Authorization: `Bearer ${token}` }),\n },\n body: JSON.stringify({ templateName, values: { ...values } }),\n });\n\n if (response.status !== 201) {\n const status = `${response.status} ${response.statusText}`;\n const body = await response.text();\n throw new Error(`Backend request failed, ${status} ${body.trim()}`);\n }\n\n const { id } = (await response.json()) as { id: string };\n return id;\n }\n\n async getTask(taskId: string) {\n const token = await this.identityApi.getIdToken();\n const baseUrl = await this.discoveryApi.getBaseUrl('scaffolder');\n const url = `${baseUrl}/v2/tasks/${encodeURIComponent(taskId)}`;\n const response = await fetch(url, {\n headers: token ? { Authorization: `Bearer ${token}` } : {},\n });\n\n if (!response.ok) {\n throw await ResponseError.fromResponse(response);\n }\n\n return await response.json();\n }\n\n streamLogs(opts: { taskId: string; after?: number }): Observable<LogEvent> {\n if (this.useLongPollingLogs) {\n return this.streamLogsPolling(opts);\n }\n\n return this.streamLogsEventStream(opts);\n }\n\n private streamLogsEventStream({\n taskId,\n after,\n }: {\n taskId: string;\n after?: number;\n }): Observable<LogEvent> {\n return new ObservableImpl(subscriber => {\n const params = new URLSearchParams();\n if (after !== undefined) {\n params.set('after', String(Number(after)));\n }\n\n this.discoveryApi.getBaseUrl('scaffolder').then(\n baseUrl => {\n const url = `${baseUrl}/v2/tasks/${encodeURIComponent(\n taskId,\n )}/eventstream`;\n const eventSource = new EventSource(url, { withCredentials: true });\n eventSource.addEventListener('log', (event: any) => {\n if (event.data) {\n try {\n subscriber.next(JSON.parse(event.data));\n } catch (ex) {\n subscriber.error(ex);\n }\n }\n });\n eventSource.addEventListener('completion', (event: any) => {\n if (event.data) {\n try {\n subscriber.next(JSON.parse(event.data));\n } catch (ex) {\n subscriber.error(ex);\n }\n }\n eventSource.close();\n subscriber.complete();\n });\n eventSource.addEventListener('error', event => {\n subscriber.error(event);\n });\n },\n error => {\n subscriber.error(error);\n },\n );\n });\n }\n\n private streamLogsPolling({\n taskId,\n after: inputAfter,\n }: {\n taskId: string;\n after?: number;\n }): Observable<LogEvent> {\n let after = inputAfter;\n\n return new ObservableImpl(subscriber => {\n this.discoveryApi.getBaseUrl('scaffolder').then(async baseUrl => {\n while (!subscriber.closed) {\n const url = `${baseUrl}/v2/tasks/${encodeURIComponent(\n taskId,\n )}/events?${qs.stringify({ after })}`;\n const response = await fetch(url);\n\n if (!response.ok) {\n // wait for one second to not run into an\n await new Promise(resolve => setTimeout(resolve, 1000));\n continue;\n }\n\n const logs = (await response.json()) as LogEvent[];\n\n for (const event of logs) {\n after = Number(event.id);\n\n subscriber.next(event);\n\n if (event.type === 'completion') {\n subscriber.complete();\n return;\n }\n }\n }\n });\n });\n }\n\n /**\n * @returns ListActionsResponse containing all registered actions.\n */\n async listActions(): Promise<ListActionsResponse> {\n const baseUrl = await this.discoveryApi.getBaseUrl('scaffolder');\n const token = await this.identityApi.getIdToken();\n const response = await fetch(`${baseUrl}/v2/actions`, {\n headers: token ? { Authorization: `Bearer ${token}` } : {},\n });\n\n if (!response.ok) {\n throw await ResponseError.fromResponse(response);\n }\n\n return await response.json();\n }\n}\n","/*\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 catalogApiRef,\n formatEntityRefTitle,\n} from '@backstage/plugin-catalog-react';\nimport { TextField } from '@material-ui/core';\nimport FormControl from '@material-ui/core/FormControl';\nimport Autocomplete from '@material-ui/lab/Autocomplete';\nimport { FieldProps, UiSchema } from '@rjsf/core';\nimport React, { useCallback, useEffect } from 'react';\nimport useAsync from 'react-use/lib/useAsync';\n\nexport const allowArbitraryValues = (uiSchema: UiSchema): boolean =>\n (uiSchema['ui:options']?.allowArbitraryValues as boolean) ?? true;\n\nexport const EntityPicker = ({\n onChange,\n schema: { title = 'Entity', description = 'An entity from the catalog' },\n required,\n uiSchema,\n rawErrors,\n formData,\n idSchema,\n}: FieldProps<string>) => {\n const allowedKinds = uiSchema['ui:options']?.allowedKinds as string[];\n const defaultKind = uiSchema['ui:options']?.defaultKind as string | undefined;\n const catalogApi = useApi(catalogApiRef);\n\n const { value: entities, loading } = useAsync(() =>\n catalogApi.getEntities(\n allowedKinds ? { filter: { kind: allowedKinds } } : undefined,\n ),\n );\n\n const entityRefs = entities?.items.map(e =>\n formatEntityRefTitle(e, { defaultKind }),\n );\n\n const onSelect = useCallback(\n (_: any, value: string | null) => {\n onChange(value || '');\n },\n [onChange],\n );\n\n useEffect(() => {\n if (entityRefs?.length === 1) {\n onChange(entityRefs[0]);\n }\n }, [entityRefs, onChange]);\n\n return (\n <FormControl\n margin=\"normal\"\n required={required}\n error={rawErrors?.length > 0 && !formData}\n >\n <Autocomplete\n disabled={entityRefs?.length === 1}\n id={idSchema?.$id}\n value={(formData as string) || ''}\n loading={loading}\n onChange={onSelect}\n options={entityRefs || []}\n autoSelect\n freeSolo={allowArbitraryValues(uiSchema)}\n renderInput={params => (\n <TextField\n {...params}\n label={title}\n margin=\"normal\"\n helperText={description}\n variant=\"outlined\"\n required={required}\n InputProps={params.InputProps}\n />\n )}\n />\n </FormControl>\n );\n};\n","/*\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 { TextField } from '@material-ui/core';\nimport { FieldProps } from '@rjsf/core';\nimport React from 'react';\n\nexport const TextValuePicker = ({\n onChange,\n required,\n schema: { title, description },\n rawErrors,\n formData,\n uiSchema: { 'ui:autofocus': autoFocus },\n idSchema,\n placeholder,\n}: FieldProps<string>) => (\n <TextField\n id={idSchema?.$id}\n label={title}\n placeholder={placeholder}\n helperText={description}\n required={required}\n value={formData ?? ''}\n onChange={({ target: { value } }) => onChange(value)}\n margin=\"normal\"\n error={rawErrors?.length > 0 && !formData}\n inputProps={{ autoFocus }}\n />\n);\n","/*\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 { FieldProps } from '@rjsf/core';\nimport { TextValuePicker } from '../TextValuePicker';\n\nexport const EntityNamePicker = ({\n schema: { title = 'Name', description = 'Unique name of the component' },\n ...props\n}: FieldProps<string>) => (\n <TextValuePicker schema={{ title, description }} {...props} />\n);\n","/*\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 { FieldValidation } from '@rjsf/core';\nimport { KubernetesValidatorFunctions } from '@backstage/catalog-model';\n\nexport const entityNamePickerValidation = (\n value: string,\n validation: FieldValidation,\n) => {\n if (!KubernetesValidatorFunctions.isValidObjectName(value)) {\n validation.addError(\n 'must start and end with an alphanumeric character, and contain only alphanumeric characters, hyphens, underscores, and periods. Maximum length is 63 characters.',\n );\n }\n};\n","/*\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, { useState } from 'react';\nimport { useAsync, useEffectOnce } from 'react-use';\nimport { CatalogEntitiesRequest } from '@backstage/catalog-client';\nimport { Entity, makeValidator } from '@backstage/catalog-model';\nimport { useApi } from '@backstage/core-plugin-api';\nimport { catalogApiRef } from '@backstage/plugin-catalog-react';\nimport { FormControl, TextField } from '@material-ui/core';\nimport { Autocomplete } from '@material-ui/lab';\nimport { FieldProps } from '@rjsf/core';\n\n/**\n * EntityTagsPicker\n * @public\n */\nexport const EntityTagsPicker = ({\n formData,\n onChange,\n uiSchema,\n}: FieldProps<string[]>) => {\n const catalogApi = useApi(catalogApiRef);\n const [inputValue, setInputValue] = useState('');\n const [inputError, setInputError] = useState(false);\n const tagValidator = makeValidator().isValidTag;\n const kinds = uiSchema['ui:options']?.kinds as string[];\n\n const { loading, value: existingTags } = useAsync(async () => {\n const tagsRequest: CatalogEntitiesRequest = { fields: ['metadata.tags'] };\n if (kinds) {\n tagsRequest.filter = { kind: kinds };\n }\n\n const entities = await catalogApi.getEntities(tagsRequest);\n\n return [\n ...new Set(\n entities.items\n .flatMap((e: Entity) => e.metadata?.tags)\n .filter(Boolean) as string[],\n ),\n ].sort();\n });\n\n const setTags = (_: React.ChangeEvent<{}>, values: string[] | null) => {\n // Reset error state in case all tags were removed\n let hasError = false;\n let addDuplicate = false;\n const currentTags = formData || [];\n\n // If adding a new tag\n if (values?.length && currentTags.length < values.length) {\n const newTag = (values[values.length - 1] = values[values.length - 1]\n .toLocaleLowerCase('en-US')\n .trim());\n hasError = !tagValidator(newTag);\n addDuplicate = currentTags.indexOf(newTag) !== -1;\n }\n\n setInputError(hasError);\n setInputValue(!hasError ? '' : inputValue);\n if (!hasError && !addDuplicate) {\n onChange(values || []);\n }\n };\n\n // Initialize field to always return an array\n useEffectOnce(() => onChange(formData || []));\n\n return (\n <FormControl margin=\"normal\">\n <Autocomplete\n multiple\n freeSolo\n filterSelectedOptions\n onChange={setTags}\n value={formData || []}\n inputValue={inputValue}\n loading={loading}\n options={existingTags || []}\n ChipProps={{ size: 'small' }}\n renderInput={params => (\n <TextField\n {...params}\n label=\"Tags\"\n onChange={e => setInputValue(e.target.value)}\n error={inputError}\n helperText=\"Add any relevant tags, hit 'Enter' to add new tags. Valid format: [a-z0-9+#] separated by [-], at most 63 characters\"\n />\n )}\n />\n </FormControl>\n );\n};\n","/*\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 { FieldProps } from '@rjsf/core';\nimport React from 'react';\nimport { EntityPicker } from '../EntityPicker';\n\nexport const OwnerPicker = ({\n schema: { title = 'Owner', description = 'The owner of the component' },\n uiSchema,\n ...props\n}: FieldProps<string>) => {\n const ownerUiSchema = {\n ...uiSchema,\n 'ui:options': {\n allowedKinds: (uiSchema['ui:options']?.allowedKinds || [\n 'Group',\n 'User',\n ]) as string[],\n defaultKind: 'Group',\n },\n };\n\n return (\n <EntityPicker\n {...props}\n schema={{ title, description }}\n uiSchema={ownerUiSchema}\n />\n );\n};\n","/*\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 {\n Progress,\n Select,\n SelectedItems,\n SelectItem,\n} from '@backstage/core-components';\nimport { useApi } from '@backstage/core-plugin-api';\nimport { scmIntegrationsApiRef } from '@backstage/integration-react';\nimport FormControl from '@material-ui/core/FormControl';\nimport FormHelperText from '@material-ui/core/FormHelperText';\nimport Input from '@material-ui/core/Input';\nimport InputLabel from '@material-ui/core/InputLabel';\nimport { FieldProps } from '@rjsf/core';\nimport React, { useCallback, useEffect } from 'react';\nimport useAsync from 'react-use/lib/useAsync';\nimport { scaffolderApiRef } from '../../../api';\n\nfunction splitFormData(url: string | undefined, allowedOwners?: string[]) {\n let host = undefined;\n let owner = undefined;\n let repo = undefined;\n let organization = undefined;\n let workspace = undefined;\n let project = undefined;\n\n try {\n if (url) {\n const parsed = new URL(`https://${url}`);\n host = parsed.host;\n owner = parsed.searchParams.get('owner') || allowedOwners?.[0];\n repo = parsed.searchParams.get('repo') || undefined;\n // This is azure dev ops specific. not used for any other provider.\n organization = parsed.searchParams.get('organization') || undefined;\n // These are bitbucket specific, not used for any other provider.\n workspace = parsed.searchParams.get('workspace') || undefined;\n project = parsed.searchParams.get('project') || undefined;\n }\n } catch {\n /* ok */\n }\n\n return { host, owner, repo, organization, workspace, project };\n}\n\nfunction serializeFormData(data: {\n host?: string;\n owner?: string;\n repo?: string;\n organization?: string;\n workspace?: string;\n project?: string;\n}) {\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.repo) {\n params.set('repo', data.repo);\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 const RepoUrlPicker = ({\n onChange,\n uiSchema,\n rawErrors,\n formData,\n}: FieldProps<string>) => {\n const scaffolderApi = useApi(scaffolderApiRef);\n const integrationApi = useApi(scmIntegrationsApiRef);\n const allowedHosts = uiSchema['ui:options']?.allowedHosts as string[];\n const allowedOwners = uiSchema['ui:options']?.allowedOwners as string[];\n\n const { value: integrations, loading } = useAsync(async () => {\n return await scaffolderApi.getIntegrationsList({ allowedHosts });\n });\n\n const { host, owner, repo, organization, workspace, project } = splitFormData(\n formData,\n allowedOwners,\n );\n const updateHost = useCallback(\n (value: SelectedItems) => {\n onChange(\n serializeFormData({\n host: value as string,\n owner,\n repo,\n organization,\n workspace,\n project,\n }),\n );\n },\n [onChange, owner, repo, organization, workspace, project],\n );\n\n const updateOwnerSelect = useCallback(\n (value: SelectedItems) =>\n onChange(\n serializeFormData({\n host,\n owner: value as string,\n repo,\n organization,\n workspace,\n project,\n }),\n ),\n [onChange, host, repo, organization, workspace, project],\n );\n\n const updateOwner = useCallback(\n (evt: React.ChangeEvent<{ name?: string; value: unknown }>) =>\n onChange(\n serializeFormData({\n host,\n owner: evt.target.value as string,\n repo,\n organization,\n workspace,\n project,\n }),\n ),\n [onChange, host, repo, organization, workspace, project],\n );\n\n const updateRepo = useCallback(\n (evt: React.ChangeEvent<{ name?: string; value: unknown }>) =>\n onChange(\n serializeFormData({\n host,\n owner,\n repo: evt.target.value as string,\n organization,\n workspace,\n project,\n }),\n ),\n [onChange, host, owner, organization, workspace, project],\n );\n\n const updateOrganization = useCallback(\n (evt: React.ChangeEvent<{ name?: string; value: unknown }>) =>\n onChange(\n serializeFormData({\n host,\n owner,\n repo,\n organization: evt.target.value as string,\n workspace,\n project,\n }),\n ),\n [onChange, host, owner, repo, workspace, project],\n );\n\n const updateWorkspace = useCallback(\n (evt: React.ChangeEvent<{ name?: string; value: unknown }>) =>\n onChange(\n serializeFormData({\n host,\n owner,\n repo,\n organization,\n workspace: evt.target.value as string,\n project,\n }),\n ),\n [onChange, host, owner, repo, organization, project],\n );\n\n const updateProject = useCallback(\n (evt: React.ChangeEvent<{ name?: string; value: unknown }>) =>\n onChange(\n serializeFormData({\n host,\n owner,\n repo,\n organization,\n workspace,\n project: evt.target.value as string,\n }),\n ),\n [onChange, host, owner, repo, organization, workspace],\n );\n\n useEffect(() => {\n if (host === undefined && integrations?.length) {\n onChange(\n serializeFormData({\n host: integrations[0].host,\n owner,\n repo,\n organization,\n workspace,\n project,\n }),\n );\n }\n }, [\n onChange,\n integrations,\n host,\n owner,\n repo,\n organization,\n workspace,\n project,\n ]);\n\n if (loading) {\n return <Progress />;\n }\n\n const hostsOptions: SelectItem[] = integrations\n ? integrations\n .filter(i => allowedHosts?.includes(i.host))\n .map(i => ({ label: i.title, value: i.host }))\n : [{ label: 'Loading...', value: 'loading' }];\n\n const ownersOptions: SelectItem[] = allowedOwners\n ? allowedOwners.map(i => ({ label: i, value: i }))\n : [{ label: 'Loading...', value: 'loading' }];\n\n return (\n <>\n <FormControl\n margin=\"normal\"\n required\n error={rawErrors?.length > 0 && !host}\n >\n <Select\n native\n disabled={hostsOptions.length === 1}\n label=\"Host\"\n onChange={updateHost}\n selected={host}\n items={hostsOptions}\n />\n\n <FormHelperText>\n The host where the repository will be created\n </FormHelperText>\n </FormControl>\n {/* Show this for dev.azure.com only */}\n {host === 'dev.azure.com' && (\n <FormControl\n margin=\"normal\"\n required\n error={rawErrors?.length > 0 && !organization}\n >\n <InputLabel htmlFor=\"repoInput\">Organization</InputLabel>\n <Input\n id=\"repoInput\"\n onChange={updateOrganization}\n value={organization}\n />\n <FormHelperText>The name of the organization</FormHelperText>\n </FormControl>\n )}\n {host && integrationApi.byHost(host)?.type === 'bitbucket' && (\n <>\n {/* Show this for bitbucket.org only */}\n {host === 'bitbucket.org' && (\n <FormControl\n margin=\"normal\"\n required\n error={rawErrors?.length > 0 && !workspace}\n >\n <InputLabel htmlFor=\"wokrspaceInput\">Workspace</InputLabel>\n <Input\n id=\"wokrspaceInput\"\n onChange={updateWorkspace}\n value={workspace}\n />\n <FormHelperText>\n The workspace where the repository will be created\n </FormHelperText>\n </FormControl>\n )}\n <FormControl\n margin=\"normal\"\n required\n error={rawErrors?.length > 0 && !project}\n >\n <InputLabel htmlFor=\"wokrspaceInput\">Project</InputLabel>\n <Input\n id=\"wokrspaceInput\"\n onChange={updateProject}\n value={project}\n />\n <FormHelperText>\n The project where the repository will be created\n </FormHelperText>\n </FormControl>\n </>\n )}\n {/* Show this for all hosts except bitbucket */}\n {host &&\n integrationApi.byHost(host)?.type !== 'bitbucket' &&\n !allowedOwners && (\n <>\n <FormControl\n margin=\"normal\"\n required\n error={rawErrors?.length > 0 && !owner}\n >\n <InputLabel htmlFor=\"ownerInput\">Owner</InputLabel>\n <Input id=\"ownerInput\" onChange={updateOwner} value={owner} />\n <FormHelperText>\n The organization, user or project that this repo will belong to\n </FormHelperText>\n </FormControl>\n </>\n )}\n {/* Show this for all hosts except bitbucket where allowed owner is set */}\n {host &&\n integrationApi.byHost(host)?.type !== 'bitbucket' &&\n allowedOwners && (\n <>\n <FormControl\n margin=\"normal\"\n required\n error={rawErrors?.length > 0 && !owner}\n >\n <Select\n native\n label=\"Owner Available\"\n onChange={updateOwnerSelect}\n disabled={ownersOptions.length === 1}\n selected={owner}\n items={ownersOptions}\n />\n\n <FormHelperText>\n The organization, user or project that this repo will belong to\n </FormHelperText>\n </FormControl>\n </>\n )}\n {/* Show this for all hosts */}\n <FormControl\n margin=\"normal\"\n required\n error={rawErrors?.length > 0 && !repo}\n >\n <InputLabel htmlFor=\"repoInput\">Repository</InputLabel>\n <Input id=\"repoInput\" onChange={updateRepo} value={repo} />\n <FormHelperText>The name of the repository</FormHelperText>\n </FormControl>\n </>\n );\n};\n","/*\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 { FieldValidation } from '@rjsf/core';\nimport { ApiHolder } from '@backstage/core-plugin-api';\nimport { scmIntegrationsApiRef } from '@backstage/integration-react';\n\nexport const repoPickerValidation = (\n value: string,\n validation: FieldValidation,\n context: { apiHolder: ApiHolder },\n) => {\n try {\n const { host, searchParams } = new URL(`https://${value}`);\n\n const integrationApi = context.apiHolder.get(scmIntegrationsApiRef);\n\n if (!host) {\n validation.addError(\n 'Incomplete repository location provided, host not provided',\n );\n } else {\n if (integrationApi?.byHost(host)?.type === 'bitbucket') {\n // workspace is only applicable for bitbucket cloud\n if (host === 'bitbucket.org' && !searchParams.get('workspace')) {\n validation.addError(\n 'Incomplete repository location provided, workspace not provided',\n );\n }\n\n if (!searchParams.get('project')) {\n validation.addError(\n 'Incomplete repository location provided, project not provided',\n );\n }\n }\n // For anything other than bitbucket\n else {\n if (!searchParams.get('owner')) {\n validation.addError(\n 'Incomplete repository location provided, owner not provided',\n );\n }\n }\n\n // Do this for all hosts\n if (!searchParams.get('repo')) {\n validation.addError(\n 'Incomplete repository location provided, repo not provided',\n );\n }\n }\n } catch {\n validation.addError('Unable to parse the Repository URL');\n }\n};\n","/*\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 {\n formatEntityRefTitle,\n useOwnedEntities,\n} from '@backstage/plugin-catalog-react';\nimport { TextField } from '@material-ui/core';\nimport FormControl from '@material-ui/core/FormControl';\nimport Autocomplete from '@material-ui/lab/Autocomplete';\nimport { FieldProps } from '@rjsf/core';\nimport React from 'react';\n\nexport const OwnedEntityPicker = ({\n onChange,\n schema: { title = 'Entity', description = 'An entity from the catalog' },\n required,\n uiSchema,\n rawErrors,\n formData,\n idSchema,\n}: FieldProps<string>) => {\n const allowedKinds = uiSchema['ui:options']?.allowedKinds as string[];\n const defaultKind = uiSchema['ui:options']?.defaultKind as string | undefined;\n const { ownedEntities, loading } = useOwnedEntities(allowedKinds);\n\n const entityRefs = ownedEntities?.items\n .map(e => formatEntityRefTitle(e, { defaultKind }))\n .filter(n => n);\n\n const onSelect = (_: any, value: string | null) => {\n onChange(value || '');\n };\n\n return (\n <FormControl\n margin=\"normal\"\n required={required}\n error={rawErrors?.length > 0 && !formData}\n >\n <Autocomplete\n id={idSchema?.$id}\n value={(formData as string) || ''}\n loading={loading}\n onChange={onSelect}\n options={entityRefs || []}\n autoSelect\n freeSolo\n renderInput={params => (\n <TextField\n {...params}\n label={title}\n margin=\"normal\"\n helperText={description}\n variant=\"outlined\"\n required={required}\n InputProps={params.InputProps}\n />\n )}\n />\n </FormControl>\n );\n};\n","/*\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 React from 'react';\nimport { CustomFieldValidator, FieldExtensionOptions } from './types';\nimport { Extension, attachComponentData } from '@backstage/core-plugin-api';\n\nexport const FIELD_EXTENSION_WRAPPER_KEY = 'scaffolder.extensions.wrapper.v1';\nexport const FIELD_EXTENSION_KEY = 'scaffolder.extensions.field.v1';\n\nexport function createScaffolderFieldExtension<T = any>(\n options: FieldExtensionOptions<T>,\n): Extension<() => null> {\n return {\n expose() {\n const FieldExtensionDataHolder: any = () => null;\n\n attachComponentData(\n FieldExtensionDataHolder,\n FIELD_EXTENSION_KEY,\n options,\n );\n\n return FieldExtensionDataHolder;\n },\n };\n}\n\nexport const ScaffolderFieldExtensions: React.ComponentType = () => null;\nattachComponentData(\n ScaffolderFieldExtensions,\n FIELD_EXTENSION_WRAPPER_KEY,\n true,\n);\n\nexport type { CustomFieldValidator, FieldExtensionOptions };\n\nexport { DEFAULT_SCAFFOLDER_FIELD_EXTENSIONS } from './default';\n","/*\n * Copyright 2020 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 {\n createExternalRouteRef,\n createRouteRef,\n} from '@backstage/core-plugin-api';\n\nexport const registerComponentRouteRef = createExternalRouteRef({\n id: 'register-component',\n optional: true,\n});\n\nexport const rootRouteRef = createRouteRef({\n id: 'scaffolder',\n});\n","/*\n * Copyright 2020 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 { scmIntegrationsApiRef } from '@backstage/integration-react';\nimport { scaffolderApiRef, ScaffolderClient } from './api';\nimport { EntityPicker } from './components/fields/EntityPicker';\nimport {\n entityNamePickerValidation,\n EntityNamePicker,\n} from './components/fields/EntityNamePicker';\nimport { OwnerPicker } from './components/fields/OwnerPicker';\nimport {\n repoPickerValidation,\n RepoUrlPicker,\n} from './components/fields/RepoUrlPicker';\nimport { createScaffolderFieldExtension } from './extensions';\nimport { registerComponentRouteRef, rootRouteRef } from './routes';\nimport {\n createApiFactory,\n createPlugin,\n createRoutableExtension,\n discoveryApiRef,\n identityApiRef,\n} from '@backstage/core-plugin-api';\nimport { OwnedEntityPicker } from './components/fields/OwnedEntityPicker';\nimport { EntityTagsPicker } from './components/fields/EntityTagsPicker';\n\nexport const scaffolderPlugin = createPlugin({\n id: 'scaffolder',\n apis: [\n createApiFactory({\n api: scaffolderApiRef,\n deps: {\n discoveryApi: discoveryApiRef,\n identityApi: identityApiRef,\n scmIntegrationsApi: scmIntegrationsApiRef,\n },\n factory: ({ discoveryApi, identityApi, scmIntegrationsApi }) =>\n new ScaffolderClient({ discoveryApi, identityApi, scmIntegrationsApi }),\n }),\n ],\n routes: {\n root: rootRouteRef,\n },\n externalRoutes: {\n registerComponent: registerComponentRouteRef,\n },\n});\n\nexport const EntityPickerFieldExtension = scaffolderPlugin.provide(\n createScaffolderFieldExtension({\n component: EntityPicker,\n name: 'EntityPicker',\n }),\n);\n\nexport const EntityNamePickerFieldExtension = scaffolderPlugin.provide(\n createScaffolderFieldExtension({\n component: EntityNamePicker,\n name: 'EntityNamePicker',\n validation: entityNamePickerValidation,\n }),\n);\n\nexport const RepoUrlPickerFieldExtension = scaffolderPlugin.provide(\n createScaffolderFieldExtension({\n component: RepoUrlPicker,\n name: 'RepoUrlPicker',\n validation: repoPickerValidation,\n }),\n);\n\nexport const OwnerPickerFieldExtension = scaffolderPlugin.provide(\n createScaffolderFieldExtension({\n component: OwnerPicker,\n name: 'OwnerPicker',\n }),\n);\n\nexport const ScaffolderPage = scaffolderPlugin.provide(\n createRoutableExtension({\n name: 'ScaffolderPage',\n component: () => import('./components/Router').then(m => m.Router),\n mountPoint: rootRouteRef,\n }),\n);\n\nexport const OwnedEntityPickerFieldExtension = scaffolderPlugin.provide(\n createScaffolderFieldExtension({\n component: OwnedEntityPicker,\n name: 'OwnedEntityPicker',\n }),\n);\n\n/**\n * EntityTagsPickerFieldExtension\n * @public\n */\nexport const EntityTagsPickerFieldExtension = scaffolderPlugin.provide(\n createScaffolderFieldExtension({\n component: EntityTagsPicker,\n name: 'EntityTagsPicker',\n }),\n);\n","/*\n * Copyright 2020 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 { Entity } from '@backstage/catalog-model';\nimport { useStarredEntity } from '@backstage/plugin-catalog-react';\nimport { IconButton, makeStyles, Tooltip, withStyles } from '@material-ui/core';\nimport Star from '@material-ui/icons/Star';\nimport StarBorder from '@material-ui/icons/StarBorder';\nimport React, { ComponentProps } from 'react';\n\ntype Props = ComponentProps<typeof IconButton> & { entity: Entity };\n\nconst YellowStar = withStyles({\n root: {\n color: '#f3ba37',\n },\n})(Star);\n\nconst WhiteBorderStar = withStyles({\n root: {\n color: '#ffffff',\n },\n})(StarBorder);\n\nconst useStyles = makeStyles(theme => ({\n starButton: {\n position: 'absolute',\n top: theme.spacing(0.5),\n right: theme.spacing(0.5),\n padding: '0.25rem',\n },\n}));\n\nexport const favouriteTemplateTooltip = (isStarred: boolean) =>\n isStarred ? 'Remove from favorites' : 'Add to favorites';\n\nexport const favouriteTemplateIcon = (isStarred: boolean) =>\n isStarred ? <YellowStar /> : <WhiteBorderStar />;\n\n/**\n * IconButton for showing if a current entity is starred and adding/removing it from the favourite entities\n * @param props - MaterialUI IconButton props extended by required `entity` prop\n */\nexport const FavouriteTemplate = (props: Props) => {\n const classes = useStyles();\n const { toggleStarredEntity, isStarredEntity } = useStarredEntity(\n props.entity,\n );\n return (\n <IconButton\n color=\"inherit\"\n className={classes.starButton}\n {...props}\n onClick={() => toggleStarredEntity()}\n >\n <Tooltip title={favouriteTemplateTooltip(isStarredEntity)}>\n {favouriteTemplateIcon(isStarredEntity)}\n </Tooltip>\n </IconButton>\n );\n};\n","/*\n * Copyright 2020 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 {\n Entity,\n RELATION_OWNED_BY,\n TemplateEntityV1beta2,\n} from '@backstage/catalog-model';\nimport {\n ScmIntegrationIcon,\n scmIntegrationsApiRef,\n} from '@backstage/integration-react';\nimport {\n EntityRefLinks,\n getEntityRelations,\n getEntitySourceLocation,\n} from '@backstage/plugin-catalog-react';\nimport { BackstageTheme } from '@backstage/theme';\nimport {\n Box,\n Card,\n CardActions,\n CardContent,\n CardMedia,\n Chip,\n IconButton,\n Link,\n makeStyles,\n Tooltip,\n Typography,\n useTheme,\n} from '@material-ui/core';\nimport WarningIcon from '@material-ui/icons/Warning';\nimport React from 'react';\nimport { generatePath } from 'react-router';\nimport { rootRouteRef } from '../../routes';\nimport { FavouriteTemplate } from '../FavouriteTemplate/FavouriteTemplate';\n\nimport { Button, ItemCardHeader } from '@backstage/core-components';\nimport { useApi, useRouteRef } from '@backstage/core-plugin-api';\n\nconst useStyles = makeStyles(theme => ({\n cardHeader: {\n position: 'relative',\n },\n title: {\n backgroundImage: ({ backgroundImage }: any) => backgroundImage,\n },\n box: {\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n display: '-webkit-box',\n '-webkit-line-clamp': 10,\n '-webkit-box-orient': 'vertical',\n paddingBottom: '0.8em',\n },\n label: {\n color: theme.palette.text.secondary,\n textTransform: 'uppercase',\n fontSize: '0.65rem',\n fontWeight: 'bold',\n letterSpacing: 0.5,\n lineHeight: 1,\n paddingBottom: '0.2rem',\n },\n leftButton: {\n marginRight: 'auto',\n },\n}));\n\nconst useDeprecationStyles = makeStyles(theme => ({\n deprecationIcon: {\n position: 'absolute',\n top: theme.spacing(0.5),\n right: theme.spacing(3.5),\n padding: '0.25rem',\n },\n link: {\n color: theme.palette.warning.light,\n },\n}));\n\nexport type TemplateCardProps = {\n template: TemplateEntityV1beta2;\n deprecated?: boolean;\n};\n\ntype TemplateProps = {\n description: string;\n tags: string[];\n title: string;\n type: string;\n name: string;\n};\n\nconst getTemplateCardProps = (\n template: TemplateEntityV1beta2,\n): TemplateProps & { key: string } => {\n return {\n key: template.metadata.uid!,\n name: template.metadata.name,\n title: `${(template.metadata.title || template.metadata.name) ?? ''}`,\n type: template.spec.type ?? '',\n description: template.metadata.description ?? '-',\n tags: (template.metadata?.tags as string[]) ?? [],\n };\n};\n\nconst DeprecationWarning = () => {\n const styles = useDeprecationStyles();\n\n const Title = (\n <Typography style={{ padding: 10, maxWidth: 300 }}>\n This template syntax is deprecated. Click for more info.\n </Typography>\n );\n\n return (\n <div className={styles.deprecationIcon}>\n <Tooltip title={Title}>\n <Link\n href=\"https://backstage.io/docs/features/software-templates/migrating-from-v1alpha1-to-v1beta2\"\n className={styles.link}\n >\n <WarningIcon />\n </Link>\n </Tooltip>\n </div>\n );\n};\n\nexport const TemplateCard = ({ template, deprecated }: TemplateCardProps) => {\n const backstageTheme = useTheme<BackstageTheme>();\n const rootLink = useRouteRef(rootRouteRef);\n const templateProps = getTemplateCardProps(template);\n const ownedByRelations = getEntityRelations(\n template as Entity,\n RELATION_OWNED_BY,\n );\n const themeId = backstageTheme.getPageTheme({ themeId: templateProps.type })\n ? templateProps.type\n : 'other';\n const theme = backstageTheme.getPageTheme({ themeId });\n const classes = useStyles({ backgroundImage: theme.backgroundImage });\n const href = generatePath(`${rootLink()}/templates/:templateName`, {\n templateName: templateProps.name,\n });\n\n const scmIntegrationsApi = useApi(scmIntegrationsApiRef);\n const sourceLocation = getEntitySourceLocation(template, scmIntegrationsApi);\n\n return (\n <Card>\n <CardMedia className={classes.cardHeader}>\n <FavouriteTemplate entity={template} />\n {deprecated && <DeprecationWarning />}\n <ItemCardHeader\n title={templateProps.title}\n subtitle={templateProps.type}\n classes={{ root: classes.title }}\n />\n </CardMedia>\n <CardContent style={{ display: 'grid' }}>\n <Box className={classes.box}>\n <Typography variant=\"body2\" className={classes.label}>\n Description\n </Typography>\n {templateProps.description}\n </Box>\n <Box className={classes.box}>\n <Typography variant=\"body2\" className={classes.label}>\n Owner\n </Typography>\n <EntityRefLinks entityRefs={ownedByRelations} defaultKind=\"Group\" />\n </Box>\n <Box>\n <Typography variant=\"body2\" className={classes.label}>\n Tags\n </Typography>\n {templateProps.tags?.map(tag => (\n <Chip size=\"small\" label={tag} key={tag} />\n ))}\n </Box>\n </CardContent>\n <CardActions>\n {sourceLocation && (\n <IconButton\n className={classes.leftButton}\n href={sourceLocation.locationTargetUrl}\n >\n <ScmIntegrationIcon type={sourceLocation.integrationType} />\n </IconButton>\n )}\n <Button\n color=\"primary\"\n to={href}\n aria-label={`Choose ${templateProps.title}`}\n >\n Choose\n </Button>\n </CardActions>\n </Card>\n );\n};\n","/*\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 React, { ComponentType } from 'react';\nimport {\n Entity,\n stringifyEntityRef,\n TemplateEntityV1beta2,\n} from '@backstage/catalog-model';\nimport {\n Content,\n ContentHeader,\n ItemCardGrid,\n Link,\n Progress,\n WarningPanel,\n} from '@backstage/core-components';\nimport { useEntityListProvider } from '@backstage/plugin-catalog-react';\nimport { Typography } from '@material-ui/core';\nimport { TemplateCard } from '../TemplateCard';\n\nexport type TemplateListProps = {\n TemplateCardComponent?:\n | ComponentType<{ template: TemplateEntityV1beta2 }>\n | undefined;\n group?: {\n title?: string;\n titleComponent?: React.ReactNode;\n filter: (entity: Entity) => boolean;\n };\n};\n\nexport const TemplateList = ({\n TemplateCardComponent,\n group,\n}: TemplateListProps) => {\n const { loading, error, entities } = useEntityListProvider();\n const Card = TemplateCardComponent || TemplateCard;\n const maybeFilteredEntities = group\n ? entities.filter(e => group.filter(e))\n : entities;\n const title = group ? (\n group.titleComponent || <ContentHeader title={group.title} />\n ) : (\n <ContentHeader title=\"Other Templates\" />\n );\n\n if (group && maybeFilteredEntities.length === 0) {\n return null;\n }\n return (\n <>\n {loading && <Progress />}\n\n {error && (\n <WarningPanel title=\"Oops! Something went wrong loading the templates\">\n {error.message}\n </WarningPanel>\n )}\n\n {!error && !loading && !entities.length && (\n <Typography variant=\"body2\">\n No templates found that match your filter. Learn more about{' '}\n <Link to=\"https://backstage.io/docs/features/software-templates/adding-templates\">\n adding templates\n </Link>\n .\n </Typography>\n )}\n\n <Content>\n {title}\n <ItemCardGrid>\n {maybeFilteredEntities &&\n maybeFilteredEntities?.length > 0 &&\n maybeFilteredEntities.map((template: Entity) => (\n <Card\n key={stringifyEntityRef(template)}\n template={template as TemplateEntityV1beta2}\n />\n ))}\n </ItemCardGrid>\n </Content>\n </>\n );\n};\n","/*\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 React from 'react';\nimport capitalize from 'lodash/capitalize';\nimport { Progress } from '@backstage/core-components';\nimport {\n Box,\n Checkbox,\n FormControlLabel,\n TextField,\n Typography,\n} from '@material-ui/core';\nimport CheckBoxIcon from '@material-ui/icons/CheckBox';\nimport CheckBoxOutlineBlankIcon from '@material-ui/icons/CheckBoxOutlineBlank';\nimport ExpandMoreIcon from '@material-ui/icons/ExpandMore';\nimport { Autocomplete } from '@material-ui/lab';\nimport { useEntityTypeFilter } from '@backstage/plugin-catalog-react';\nimport { alertApiRef, useApi } from '@backstage/core-plugin-api';\n\nconst icon = <CheckBoxOutlineBlankIcon fontSize=\"small\" />;\nconst checkedIcon = <CheckBoxIcon fontSize=\"small\" />;\n\nexport const TemplateTypePicker = () => {\n const alertApi = useApi(alertApiRef);\n const { error, loading, availableTypes, selectedTypes, setSelectedTypes } =\n useEntityTypeFilter();\n\n if (loading) return <Progress />;\n\n if (!availableTypes) return null;\n\n if (error) {\n alertApi.post({\n message: `Failed to load entity types`,\n severity: 'error',\n });\n return null;\n }\n\n return (\n <Box pb={1} pt={1}>\n <Typography variant=\"button\">Categories</Typography>\n <Autocomplete\n multiple\n aria-label=\"Categories\"\n options={availableTypes}\n value={selectedTypes}\n onChange={(_: object, value: string[]) => setSelectedTypes(value)}\n renderOption={(option, { selected }) => (\n <FormControlLabel\n control={\n <Checkbox\n icon={icon}\n checkedIcon={checkedIcon}\n checked={selected}\n />\n }\n label={capitalize(option)}\n />\n )}\n size=\"small\"\n popupIcon={<ExpandMoreIcon data-testid=\"categories-picker-expand\" />}\n renderInput={params => <TextField {...params} variant=\"outlined\" />}\n />\n </Box>\n );\n};\n"],"names":["useAsync","FormControl","Autocomplete","useStyles","Link"],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -4,26 +4,17 @@ import { DiscoveryApi, IdentityApi, ApiHolder, Extension } from '@backstage/core
4
4
  import * as _backstage_catalog_model from '@backstage/catalog-model';
5
5
  import { JSONSchema, EntityName, Entity, TemplateEntityV1beta2 } from '@backstage/catalog-model';
6
6
  import { ScmIntegrationRegistry } from '@backstage/integration';
7
- import { JsonValue, Observable, JsonObject } from '@backstage/types';
7
+ import { Observable, JsonObject } from '@backstage/types';
8
+ import { TaskSpec } from '@backstage/plugin-scaffolder-common';
8
9
  import * as react from 'react';
9
10
  import react__default, { ComponentProps, ComponentType } from 'react';
10
11
  import { FieldValidation, FieldProps } from '@rjsf/core';
11
12
  import { IconButton } from '@material-ui/core';
12
13
 
13
14
  declare type Status = 'open' | 'processing' | 'failed' | 'completed' | 'skipped';
14
- declare type ScaffolderStep = {
15
- id: string;
16
- name: string;
17
- action: string;
18
- parameters?: {
19
- [name: string]: JsonValue;
20
- };
21
- };
22
15
  declare type ScaffolderTask = {
23
16
  id: string;
24
- spec: {
25
- steps: ScaffolderStep[];
26
- };
17
+ spec: TaskSpec;
27
18
  status: 'failed' | 'completed' | 'processing' | 'open' | 'cancelled';
28
19
  lastHeartbeatAt: string;
29
20
  createdAt: string;
@@ -62,8 +53,8 @@ interface ScaffolderApi {
62
53
  * Executes the scaffolding of a component, given a template and its
63
54
  * parameter values.
64
55
  *
65
- * @param templateName Name of the Template entity for the scaffolder to use. New project is going to be created out of this template.
66
- * @param values Parameters for the template, e.g. name, description
56
+ * @param templateName - Name of the Template entity for the scaffolder to use. New project is going to be created out of this template.
57
+ * @param values - Parameters for the template, e.g. name, description
67
58
  */
68
59
  scaffold(templateName: string, values: Record<string, any>): Promise<string>;
69
60
  getTask(taskId: string): Promise<ScaffolderTask>;
@@ -103,8 +94,8 @@ declare class ScaffolderClient implements ScaffolderApi {
103
94
  * Executes the scaffolding of a component, given a template and its
104
95
  * parameter values.
105
96
  *
106
- * @param templateName Template name for the scaffolder to use. New project is going to be created out of this template.
107
- * @param values Parameters for the template, e.g. name, description
97
+ * @param templateName - Template name for the scaffolder to use. New project is going to be created out of this template.
98
+ * @param values - Parameters for the template, e.g. name, description
108
99
  */
109
100
  scaffold(templateName: string, values: Record<string, any>): Promise<string>;
110
101
  getTask(taskId: string): Promise<any>;
@@ -151,6 +142,12 @@ declare const ScaffolderPage: ({ TemplateCardComponent, groups }: {
151
142
  filter: (entity: _backstage_catalog_model.Entity) => boolean;
152
143
  }[] | undefined;
153
144
  }) => JSX.Element;
145
+ declare const OwnedEntityPickerFieldExtension: () => null;
146
+ /**
147
+ * EntityTagsPickerFieldExtension
148
+ * @public
149
+ */
150
+ declare const EntityTagsPickerFieldExtension: () => null;
154
151
 
155
152
  declare const EntityNamePicker: ({ schema: { title, description }, ...props }: FieldProps<string>) => JSX.Element;
156
153
 
@@ -162,12 +159,20 @@ declare const RepoUrlPicker: ({ onChange, uiSchema, rawErrors, formData, }: Fiel
162
159
 
163
160
  declare const TextValuePicker: ({ onChange, required, schema: { title, description }, rawErrors, formData, uiSchema: { "ui:autofocus": autoFocus }, idSchema, placeholder, }: FieldProps<string>) => JSX.Element;
164
161
 
162
+ declare const OwnedEntityPicker: ({ onChange, schema: { title, description }, required, uiSchema, rawErrors, formData, idSchema, }: FieldProps<string>) => JSX.Element;
163
+
164
+ /**
165
+ * EntityTagsPicker
166
+ * @public
167
+ */
168
+ declare const EntityTagsPicker: ({ formData, onChange, uiSchema, }: FieldProps<string[]>) => JSX.Element;
169
+
165
170
  declare type Props = ComponentProps<typeof IconButton> & {
166
171
  entity: Entity;
167
172
  };
168
173
  /**
169
174
  * IconButton for showing if a current entity is starred and adding/removing it from the favourite entities
170
- * @param props MaterialUI IconButton props extended by required `entity` prop
175
+ * @param props - MaterialUI IconButton props extended by required `entity` prop
171
176
  */
172
177
  declare const FavouriteTemplate: (props: Props) => JSX.Element;
173
178
 
@@ -185,4 +190,4 @@ declare const TemplateList: ({ TemplateCardComponent, group, }: TemplateListProp
185
190
 
186
191
  declare const TemplateTypePicker: () => JSX.Element | null;
187
192
 
188
- export { CustomFieldValidator, EntityNamePicker, EntityNamePickerFieldExtension, EntityPicker, EntityPickerFieldExtension, FavouriteTemplate, FieldExtensionOptions, OwnerPicker, OwnerPickerFieldExtension, RepoUrlPicker, RepoUrlPickerFieldExtension, ScaffolderApi, ScaffolderClient, ScaffolderFieldExtensions, ScaffolderPage, TemplateList, TemplateListProps, TemplateTypePicker, TextValuePicker, createScaffolderFieldExtension, scaffolderPlugin as plugin, scaffolderApiRef, scaffolderPlugin };
193
+ export { CustomFieldValidator, EntityNamePicker, EntityNamePickerFieldExtension, EntityPicker, EntityPickerFieldExtension, EntityTagsPicker, EntityTagsPickerFieldExtension, FavouriteTemplate, FieldExtensionOptions, OwnedEntityPicker, OwnedEntityPickerFieldExtension, OwnerPicker, OwnerPickerFieldExtension, RepoUrlPicker, RepoUrlPickerFieldExtension, ScaffolderApi, ScaffolderClient, ScaffolderFieldExtensions, ScaffolderPage, TemplateList, TemplateListProps, TemplateTypePicker, TextValuePicker, createScaffolderFieldExtension, scaffolderPlugin as plugin, scaffolderApiRef, scaffolderPlugin };
package/dist/index.esm.js CHANGED
@@ -1,4 +1,4 @@
1
- export { a as EntityNamePicker, j as EntityNamePickerFieldExtension, E as EntityPicker, i as EntityPickerFieldExtension, p as FavouriteTemplate, O as OwnerPicker, k as OwnerPickerFieldExtension, R as RepoUrlPicker, l as RepoUrlPickerFieldExtension, S as ScaffolderClient, h as ScaffolderFieldExtensions, m as ScaffolderPage, c as TemplateList, T as TemplateTypePicker, o as TextValuePicker, g as createScaffolderFieldExtension, n as plugin, s as scaffolderApiRef, n as scaffolderPlugin } from './esm/index-306a8b5a.esm.js';
1
+ export { a as EntityNamePicker, l as EntityNamePickerFieldExtension, E as EntityPicker, k as EntityPickerFieldExtension, b as EntityTagsPicker, m as EntityTagsPickerFieldExtension, v as FavouriteTemplate, c as OwnedEntityPicker, o as OwnedEntityPickerFieldExtension, O as OwnerPicker, n as OwnerPickerFieldExtension, R as RepoUrlPicker, p as RepoUrlPickerFieldExtension, S as ScaffolderClient, j as ScaffolderFieldExtensions, q as ScaffolderPage, f as TemplateList, T as TemplateTypePicker, u as TextValuePicker, i as createScaffolderFieldExtension, t as plugin, s as scaffolderApiRef, t as scaffolderPlugin } from './esm/index-768702c3.esm.js';
2
2
  import '@backstage/catalog-model';
3
3
  import '@backstage/integration-react';
4
4
  import '@backstage/core-plugin-api';
@@ -10,12 +10,13 @@ import '@material-ui/core';
10
10
  import '@material-ui/core/FormControl';
11
11
  import '@material-ui/lab/Autocomplete';
12
12
  import 'react';
13
+ import 'react-use/lib/useAsync';
13
14
  import 'react-use';
14
- import '@material-ui/core/Select';
15
- import '@material-ui/core/InputLabel';
16
- import '@material-ui/core/Input';
17
- import '@material-ui/core/FormHelperText';
15
+ import '@material-ui/lab';
18
16
  import '@backstage/core-components';
17
+ import '@material-ui/core/FormHelperText';
18
+ import '@material-ui/core/Input';
19
+ import '@material-ui/core/InputLabel';
19
20
  import '@material-ui/icons/Star';
20
21
  import '@material-ui/icons/StarBorder';
21
22
  import '@material-ui/icons/Warning';
@@ -24,5 +25,4 @@ import 'lodash/capitalize';
24
25
  import '@material-ui/icons/CheckBox';
25
26
  import '@material-ui/icons/CheckBoxOutlineBlank';
26
27
  import '@material-ui/icons/ExpandMore';
27
- import '@material-ui/lab';
28
28
  //# sourceMappingURL=index.esm.js.map