@backstage/plugin-scaffolder 0.11.16 → 0.12.0
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 +114 -0
- package/dist/esm/{Router-a8e778fd.esm.js → Router-5ca674eb.esm.js} +5 -3
- package/dist/esm/Router-5ca674eb.esm.js.map +1 -0
- package/dist/esm/{index-f378943f.esm.js → index-8b5d21c1.esm.js} +270 -222
- package/dist/esm/index-8b5d21c1.esm.js.map +1 -0
- package/dist/index.d.ts +60 -17
- package/dist/index.esm.js +4 -3
- package/dist/index.esm.js.map +1 -1
- package/package.json +17 -17
- package/dist/esm/Router-a8e778fd.esm.js.map +0 -1
- package/dist/esm/index-f378943f.esm.js.map +0 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { createApiRef, useApi, attachComponentData, createExternalRouteRef, createRouteRef, createPlugin, createApiFactory, discoveryApiRef,
|
|
1
|
+
import { createApiRef, useApi, attachComponentData, createExternalRouteRef, createRouteRef, createPlugin, createApiFactory, discoveryApiRef, fetchApiRef, createRoutableExtension, useRouteRef, alertApiRef } from '@backstage/core-plugin-api';
|
|
2
2
|
import { ResponseError } from '@backstage/errors';
|
|
3
3
|
import qs from 'qs';
|
|
4
4
|
import ObservableImpl from 'zen-observable';
|
|
@@ -6,15 +6,16 @@ import { catalogApiRef, formatEntityRefTitle, useOwnedEntities, useStarredEntity
|
|
|
6
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, useState } from 'react';
|
|
10
|
-
import
|
|
9
|
+
import React, { useCallback, useEffect, useState, useMemo } from 'react';
|
|
10
|
+
import useAsync from 'react-use/lib/useAsync';
|
|
11
11
|
import { KubernetesValidatorFunctions, makeValidator, RELATION_OWNED_BY, stringifyEntityRef } from '@backstage/catalog-model';
|
|
12
|
+
import useEffectOnce from 'react-use/lib/useEffectOnce';
|
|
12
13
|
import { Autocomplete as Autocomplete$1 } from '@material-ui/lab';
|
|
13
|
-
import { Progress, Select, ItemCardHeader, Button, ContentHeader, WarningPanel, Link as Link$1, Content, ItemCardGrid } from '@backstage/core-components';
|
|
14
14
|
import { scmIntegrationsApiRef, ScmIntegrationIcon } from '@backstage/integration-react';
|
|
15
15
|
import FormHelperText from '@material-ui/core/FormHelperText';
|
|
16
16
|
import Input from '@material-ui/core/Input';
|
|
17
17
|
import InputLabel from '@material-ui/core/InputLabel';
|
|
18
|
+
import { Select, Progress, ItemCardHeader, Button, ContentHeader, WarningPanel, Link as Link$1, Content, ItemCardGrid } from '@backstage/core-components';
|
|
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';
|
|
@@ -29,11 +30,11 @@ const scaffolderApiRef = createApiRef({
|
|
|
29
30
|
});
|
|
30
31
|
class ScaffolderClient {
|
|
31
32
|
constructor(options) {
|
|
32
|
-
var _a;
|
|
33
|
+
var _a, _b;
|
|
33
34
|
this.discoveryApi = options.discoveryApi;
|
|
34
|
-
this.
|
|
35
|
+
this.fetchApi = (_a = options.fetchApi) != null ? _a : { fetch };
|
|
35
36
|
this.scmIntegrationsApi = options.scmIntegrationsApi;
|
|
36
|
-
this.useLongPollingLogs = (
|
|
37
|
+
this.useLongPollingLogs = (_b = options.useLongPollingLogs) != null ? _b : false;
|
|
37
38
|
}
|
|
38
39
|
async getIntegrationsList(options) {
|
|
39
40
|
return [
|
|
@@ -45,31 +46,28 @@ class ScaffolderClient {
|
|
|
45
46
|
}
|
|
46
47
|
async getTemplateParameterSchema(templateName) {
|
|
47
48
|
const { namespace, kind, name } = templateName;
|
|
48
|
-
const token = await this.identityApi.getIdToken();
|
|
49
49
|
const baseUrl = await this.discoveryApi.getBaseUrl("scaffolder");
|
|
50
50
|
const templatePath = [namespace, kind, name].map((s) => encodeURIComponent(s)).join("/");
|
|
51
51
|
const url = `${baseUrl}/v2/templates/${templatePath}/parameter-schema`;
|
|
52
|
-
const response = await fetch(url
|
|
53
|
-
headers: {
|
|
54
|
-
...token && { Authorization: `Bearer ${token}` }
|
|
55
|
-
}
|
|
56
|
-
});
|
|
52
|
+
const response = await this.fetchApi.fetch(url);
|
|
57
53
|
if (!response.ok) {
|
|
58
54
|
throw await ResponseError.fromResponse(response);
|
|
59
55
|
}
|
|
60
56
|
const schema = await response.json();
|
|
61
57
|
return schema;
|
|
62
58
|
}
|
|
63
|
-
async scaffold(templateName, values) {
|
|
64
|
-
const token = await this.identityApi.getIdToken();
|
|
59
|
+
async scaffold(templateName, values, secrets = {}) {
|
|
65
60
|
const url = `${await this.discoveryApi.getBaseUrl("scaffolder")}/v2/tasks`;
|
|
66
|
-
const response = await fetch(url, {
|
|
61
|
+
const response = await this.fetchApi.fetch(url, {
|
|
67
62
|
method: "POST",
|
|
68
63
|
headers: {
|
|
69
|
-
"Content-Type": "application/json"
|
|
70
|
-
...token && { Authorization: `Bearer ${token}` }
|
|
64
|
+
"Content-Type": "application/json"
|
|
71
65
|
},
|
|
72
|
-
body: JSON.stringify({
|
|
66
|
+
body: JSON.stringify({
|
|
67
|
+
templateName,
|
|
68
|
+
values: { ...values },
|
|
69
|
+
secrets
|
|
70
|
+
})
|
|
73
71
|
});
|
|
74
72
|
if (response.status !== 201) {
|
|
75
73
|
const status = `${response.status} ${response.statusText}`;
|
|
@@ -80,22 +78,19 @@ class ScaffolderClient {
|
|
|
80
78
|
return id;
|
|
81
79
|
}
|
|
82
80
|
async getTask(taskId) {
|
|
83
|
-
const token = await this.identityApi.getIdToken();
|
|
84
81
|
const baseUrl = await this.discoveryApi.getBaseUrl("scaffolder");
|
|
85
82
|
const url = `${baseUrl}/v2/tasks/${encodeURIComponent(taskId)}`;
|
|
86
|
-
const response = await fetch(url
|
|
87
|
-
headers: token ? { Authorization: `Bearer ${token}` } : {}
|
|
88
|
-
});
|
|
83
|
+
const response = await this.fetchApi.fetch(url);
|
|
89
84
|
if (!response.ok) {
|
|
90
85
|
throw await ResponseError.fromResponse(response);
|
|
91
86
|
}
|
|
92
87
|
return await response.json();
|
|
93
88
|
}
|
|
94
|
-
streamLogs(
|
|
89
|
+
streamLogs(options) {
|
|
95
90
|
if (this.useLongPollingLogs) {
|
|
96
|
-
return this.streamLogsPolling(
|
|
91
|
+
return this.streamLogsPolling(options);
|
|
97
92
|
}
|
|
98
|
-
return this.streamLogsEventStream(
|
|
93
|
+
return this.streamLogsEventStream(options);
|
|
99
94
|
}
|
|
100
95
|
streamLogsEventStream({
|
|
101
96
|
taskId,
|
|
@@ -146,7 +141,7 @@ class ScaffolderClient {
|
|
|
146
141
|
this.discoveryApi.getBaseUrl("scaffolder").then(async (baseUrl) => {
|
|
147
142
|
while (!subscriber.closed) {
|
|
148
143
|
const url = `${baseUrl}/v2/tasks/${encodeURIComponent(taskId)}/events?${qs.stringify({ after })}`;
|
|
149
|
-
const response = await fetch(url);
|
|
144
|
+
const response = await this.fetchApi.fetch(url);
|
|
150
145
|
if (!response.ok) {
|
|
151
146
|
await new Promise((resolve) => setTimeout(resolve, 1e3));
|
|
152
147
|
continue;
|
|
@@ -166,10 +161,7 @@ class ScaffolderClient {
|
|
|
166
161
|
}
|
|
167
162
|
async listActions() {
|
|
168
163
|
const baseUrl = await this.discoveryApi.getBaseUrl("scaffolder");
|
|
169
|
-
const
|
|
170
|
-
const response = await fetch(`${baseUrl}/v2/actions`, {
|
|
171
|
-
headers: token ? { Authorization: `Bearer ${token}` } : {}
|
|
172
|
-
});
|
|
164
|
+
const response = await this.fetchApi.fetch(`${baseUrl}/v2/actions`);
|
|
173
165
|
if (!response.ok) {
|
|
174
166
|
throw await ResponseError.fromResponse(response);
|
|
175
167
|
}
|
|
@@ -350,221 +342,273 @@ const OwnerPicker = ({
|
|
|
350
342
|
});
|
|
351
343
|
};
|
|
352
344
|
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
let organization = void 0;
|
|
358
|
-
let workspace = void 0;
|
|
359
|
-
let project = void 0;
|
|
360
|
-
try {
|
|
361
|
-
if (url) {
|
|
362
|
-
const parsed = new URL(`https://${url}`);
|
|
363
|
-
host = parsed.host;
|
|
364
|
-
owner = parsed.searchParams.get("owner") || (allowedOwners == null ? void 0 : allowedOwners[0]);
|
|
365
|
-
repo = parsed.searchParams.get("repo") || void 0;
|
|
366
|
-
organization = parsed.searchParams.get("organization") || void 0;
|
|
367
|
-
workspace = parsed.searchParams.get("workspace") || void 0;
|
|
368
|
-
project = parsed.searchParams.get("project") || void 0;
|
|
369
|
-
}
|
|
370
|
-
} catch {
|
|
371
|
-
}
|
|
372
|
-
return { host, owner, repo, organization, workspace, project };
|
|
373
|
-
}
|
|
374
|
-
function serializeFormData(data) {
|
|
375
|
-
if (!data.host) {
|
|
376
|
-
return void 0;
|
|
377
|
-
}
|
|
378
|
-
const params = new URLSearchParams();
|
|
379
|
-
if (data.owner) {
|
|
380
|
-
params.set("owner", data.owner);
|
|
381
|
-
}
|
|
382
|
-
if (data.repo) {
|
|
383
|
-
params.set("repo", data.repo);
|
|
384
|
-
}
|
|
385
|
-
if (data.organization) {
|
|
386
|
-
params.set("organization", data.organization);
|
|
387
|
-
}
|
|
388
|
-
if (data.workspace) {
|
|
389
|
-
params.set("workspace", data.workspace);
|
|
390
|
-
}
|
|
391
|
-
if (data.project) {
|
|
392
|
-
params.set("project", data.project);
|
|
393
|
-
}
|
|
394
|
-
return `${data.host}?${params.toString()}`;
|
|
395
|
-
}
|
|
396
|
-
const RepoUrlPicker = ({
|
|
397
|
-
onChange,
|
|
398
|
-
uiSchema,
|
|
399
|
-
rawErrors,
|
|
400
|
-
formData
|
|
401
|
-
}) => {
|
|
402
|
-
var _a, _b, _c, _d, _e;
|
|
403
|
-
const scaffolderApi = useApi(scaffolderApiRef);
|
|
404
|
-
const integrationApi = useApi(scmIntegrationsApiRef);
|
|
405
|
-
const allowedHosts = (_a = uiSchema["ui:options"]) == null ? void 0 : _a.allowedHosts;
|
|
406
|
-
const allowedOwners = (_b = uiSchema["ui:options"]) == null ? void 0 : _b.allowedOwners;
|
|
407
|
-
const { value: integrations, loading } = useAsync(async () => {
|
|
408
|
-
return await scaffolderApi.getIntegrationsList({ allowedHosts });
|
|
409
|
-
});
|
|
410
|
-
const { host, owner, repo, organization, workspace, project } = splitFormData(formData, allowedOwners);
|
|
411
|
-
const updateHost = useCallback((value) => {
|
|
412
|
-
onChange(serializeFormData({
|
|
413
|
-
host: value,
|
|
414
|
-
owner,
|
|
415
|
-
repo,
|
|
416
|
-
organization,
|
|
417
|
-
workspace,
|
|
418
|
-
project
|
|
419
|
-
}));
|
|
420
|
-
}, [onChange, owner, repo, organization, workspace, project]);
|
|
421
|
-
const updateOwnerSelect = useCallback((value) => onChange(serializeFormData({
|
|
422
|
-
host,
|
|
423
|
-
owner: value,
|
|
424
|
-
repo,
|
|
425
|
-
organization,
|
|
426
|
-
workspace,
|
|
427
|
-
project
|
|
428
|
-
})), [onChange, host, repo, organization, workspace, project]);
|
|
429
|
-
const updateOwner = useCallback((evt) => onChange(serializeFormData({
|
|
430
|
-
host,
|
|
431
|
-
owner: evt.target.value,
|
|
432
|
-
repo,
|
|
433
|
-
organization,
|
|
434
|
-
workspace,
|
|
435
|
-
project
|
|
436
|
-
})), [onChange, host, repo, organization, workspace, project]);
|
|
437
|
-
const updateRepo = useCallback((evt) => onChange(serializeFormData({
|
|
438
|
-
host,
|
|
439
|
-
owner,
|
|
440
|
-
repo: evt.target.value,
|
|
441
|
-
organization,
|
|
442
|
-
workspace,
|
|
443
|
-
project
|
|
444
|
-
})), [onChange, host, owner, organization, workspace, project]);
|
|
445
|
-
const updateOrganization = useCallback((evt) => onChange(serializeFormData({
|
|
446
|
-
host,
|
|
447
|
-
owner,
|
|
448
|
-
repo,
|
|
449
|
-
organization: evt.target.value,
|
|
450
|
-
workspace,
|
|
451
|
-
project
|
|
452
|
-
})), [onChange, host, owner, repo, workspace, project]);
|
|
453
|
-
const updateWorkspace = useCallback((evt) => onChange(serializeFormData({
|
|
454
|
-
host,
|
|
455
|
-
owner,
|
|
456
|
-
repo,
|
|
457
|
-
organization,
|
|
458
|
-
workspace: evt.target.value,
|
|
459
|
-
project
|
|
460
|
-
})), [onChange, host, owner, repo, organization, project]);
|
|
461
|
-
const updateProject = useCallback((evt) => onChange(serializeFormData({
|
|
462
|
-
host,
|
|
463
|
-
owner,
|
|
464
|
-
repo,
|
|
465
|
-
organization,
|
|
466
|
-
workspace,
|
|
467
|
-
project: evt.target.value
|
|
468
|
-
})), [onChange, host, owner, repo, organization, workspace]);
|
|
469
|
-
useEffect(() => {
|
|
470
|
-
if (host === void 0 && (integrations == null ? void 0 : integrations.length)) {
|
|
471
|
-
onChange(serializeFormData({
|
|
472
|
-
host: integrations[0].host,
|
|
473
|
-
owner,
|
|
474
|
-
repo,
|
|
475
|
-
organization,
|
|
476
|
-
workspace,
|
|
477
|
-
project
|
|
478
|
-
}));
|
|
479
|
-
}
|
|
480
|
-
}, [
|
|
481
|
-
onChange,
|
|
482
|
-
integrations,
|
|
483
|
-
host,
|
|
484
|
-
owner,
|
|
485
|
-
repo,
|
|
486
|
-
organization,
|
|
487
|
-
workspace,
|
|
488
|
-
project
|
|
489
|
-
]);
|
|
490
|
-
if (loading) {
|
|
491
|
-
return /* @__PURE__ */ React.createElement(Progress, null);
|
|
492
|
-
}
|
|
493
|
-
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" }];
|
|
494
|
-
const ownersOptions = allowedOwners ? allowedOwners.map((i) => ({ label: i, value: i })) : [{ label: "Loading...", value: "loading" }];
|
|
345
|
+
const GithubRepoPicker = (props) => {
|
|
346
|
+
const { allowedOwners = [], rawErrors, state, onChange } = props;
|
|
347
|
+
const ownerItems = allowedOwners ? allowedOwners.map((i) => ({ label: i, value: i })) : [{ label: "Loading...", value: "loading" }];
|
|
348
|
+
const { owner, repoName } = state;
|
|
495
349
|
return /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(FormControl, {
|
|
496
350
|
margin: "normal",
|
|
497
351
|
required: true,
|
|
498
|
-
error: (rawErrors == null ? void 0 : rawErrors.length) > 0 && !
|
|
499
|
-
}, /* @__PURE__ */ React.createElement(Select, {
|
|
352
|
+
error: (rawErrors == null ? void 0 : rawErrors.length) > 0 && !owner
|
|
353
|
+
}, (allowedOwners == null ? void 0 : allowedOwners.length) ? /* @__PURE__ */ React.createElement(Select, {
|
|
500
354
|
native: true,
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
selected:
|
|
505
|
-
items:
|
|
506
|
-
})
|
|
355
|
+
label: "Owner Available",
|
|
356
|
+
onChange: (s) => onChange({ owner: String(Array.isArray(s) ? s[0] : s) }),
|
|
357
|
+
disabled: allowedOwners.length === 1,
|
|
358
|
+
selected: owner,
|
|
359
|
+
items: ownerItems
|
|
360
|
+
}) : /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(InputLabel, {
|
|
361
|
+
htmlFor: "ownerInput"
|
|
362
|
+
}, "Owner"), /* @__PURE__ */ React.createElement(Input, {
|
|
363
|
+
id: "ownerInput",
|
|
364
|
+
onChange: (e) => onChange({ owner: e.target.value }),
|
|
365
|
+
value: owner
|
|
366
|
+
})), /* @__PURE__ */ React.createElement(FormHelperText, null, "The organization, user or project that this repo will belong to")), /* @__PURE__ */ React.createElement(FormControl, {
|
|
367
|
+
margin: "normal",
|
|
368
|
+
required: true,
|
|
369
|
+
error: (rawErrors == null ? void 0 : rawErrors.length) > 0 && !repoName
|
|
370
|
+
}, /* @__PURE__ */ React.createElement(InputLabel, {
|
|
371
|
+
htmlFor: "repoNameInput"
|
|
372
|
+
}, "Repository"), /* @__PURE__ */ React.createElement(Input, {
|
|
373
|
+
id: "repoNameInput",
|
|
374
|
+
onChange: (e) => onChange({ repoName: e.target.value }),
|
|
375
|
+
value: repoName
|
|
376
|
+
}), /* @__PURE__ */ React.createElement(FormHelperText, null, "The name of the repository")));
|
|
377
|
+
};
|
|
378
|
+
|
|
379
|
+
const GitlabRepoPicker = (props) => {
|
|
380
|
+
const { allowedOwners = [], rawErrors, state, onChange } = props;
|
|
381
|
+
const ownerItems = allowedOwners ? allowedOwners.map((i) => ({ label: i, value: i })) : [{ label: "Loading...", value: "loading" }];
|
|
382
|
+
const { owner, repoName } = state;
|
|
383
|
+
return /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(FormControl, {
|
|
384
|
+
margin: "normal",
|
|
385
|
+
required: true,
|
|
386
|
+
error: (rawErrors == null ? void 0 : rawErrors.length) > 0 && !owner
|
|
387
|
+
}, (allowedOwners == null ? void 0 : allowedOwners.length) ? /* @__PURE__ */ React.createElement(Select, {
|
|
388
|
+
native: true,
|
|
389
|
+
label: "Owner Available",
|
|
390
|
+
onChange: (selected) => onChange({
|
|
391
|
+
owner: String(Array.isArray(selected) ? selected[0] : selected)
|
|
392
|
+
}),
|
|
393
|
+
disabled: allowedOwners.length === 1,
|
|
394
|
+
selected: owner,
|
|
395
|
+
items: ownerItems
|
|
396
|
+
}) : /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(InputLabel, {
|
|
397
|
+
htmlFor: "ownerInput"
|
|
398
|
+
}, "Owner"), /* @__PURE__ */ React.createElement(Input, {
|
|
399
|
+
id: "ownerInput",
|
|
400
|
+
onChange: (e) => onChange({ owner: e.target.value }),
|
|
401
|
+
value: owner
|
|
402
|
+
})), /* @__PURE__ */ React.createElement(FormHelperText, null, "The organization, user or project that this repo will belong to")), /* @__PURE__ */ React.createElement(FormControl, {
|
|
403
|
+
margin: "normal",
|
|
404
|
+
required: true,
|
|
405
|
+
error: (rawErrors == null ? void 0 : rawErrors.length) > 0 && !repoName
|
|
406
|
+
}, /* @__PURE__ */ React.createElement(InputLabel, {
|
|
407
|
+
htmlFor: "repoNameInput"
|
|
408
|
+
}, "Repository"), /* @__PURE__ */ React.createElement(Input, {
|
|
409
|
+
id: "repoNameInput",
|
|
410
|
+
onChange: (e) => onChange({ repoName: e.target.value }),
|
|
411
|
+
value: repoName
|
|
412
|
+
}), /* @__PURE__ */ React.createElement(FormHelperText, null, "The name of the repository")));
|
|
413
|
+
};
|
|
414
|
+
|
|
415
|
+
const AzureRepoPicker = (props) => {
|
|
416
|
+
const { rawErrors, state, onChange } = props;
|
|
417
|
+
const { organization, repoName, owner } = state;
|
|
418
|
+
return /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(FormControl, {
|
|
507
419
|
margin: "normal",
|
|
508
420
|
required: true,
|
|
509
421
|
error: (rawErrors == null ? void 0 : rawErrors.length) > 0 && !organization
|
|
510
422
|
}, /* @__PURE__ */ React.createElement(InputLabel, {
|
|
511
|
-
htmlFor: "
|
|
423
|
+
htmlFor: "orgInput"
|
|
512
424
|
}, "Organization"), /* @__PURE__ */ React.createElement(Input, {
|
|
513
|
-
id: "
|
|
514
|
-
onChange:
|
|
425
|
+
id: "orgInput",
|
|
426
|
+
onChange: (e) => onChange({ organization: e.target.value }),
|
|
515
427
|
value: organization
|
|
516
|
-
}), /* @__PURE__ */ React.createElement(FormHelperText, null, "The
|
|
428
|
+
}), /* @__PURE__ */ React.createElement(FormHelperText, null, "The organization that this repo will belong to")), /* @__PURE__ */ React.createElement(FormControl, {
|
|
429
|
+
margin: "normal",
|
|
430
|
+
required: true,
|
|
431
|
+
error: (rawErrors == null ? void 0 : rawErrors.length) > 0 && !owner
|
|
432
|
+
}, /* @__PURE__ */ React.createElement(InputLabel, {
|
|
433
|
+
htmlFor: "ownerInput"
|
|
434
|
+
}, "Owner"), /* @__PURE__ */ React.createElement(Input, {
|
|
435
|
+
id: "ownerInput",
|
|
436
|
+
onChange: (e) => onChange({ owner: e.target.value }),
|
|
437
|
+
value: owner
|
|
438
|
+
}), /* @__PURE__ */ React.createElement(FormHelperText, null, "The Owner that this repo will belong to")), /* @__PURE__ */ React.createElement(FormControl, {
|
|
439
|
+
margin: "normal",
|
|
440
|
+
required: true,
|
|
441
|
+
error: (rawErrors == null ? void 0 : rawErrors.length) > 0 && !repoName
|
|
442
|
+
}, /* @__PURE__ */ React.createElement(InputLabel, {
|
|
443
|
+
htmlFor: "repoNameInput"
|
|
444
|
+
}, "Repository"), /* @__PURE__ */ React.createElement(Input, {
|
|
445
|
+
id: "repoNameInput",
|
|
446
|
+
onChange: (e) => onChange({ repoName: e.target.value }),
|
|
447
|
+
value: repoName
|
|
448
|
+
}), /* @__PURE__ */ React.createElement(FormHelperText, null, "The name of the repository")));
|
|
449
|
+
};
|
|
450
|
+
|
|
451
|
+
const BitbucketRepoPicker = (props) => {
|
|
452
|
+
const { onChange, rawErrors, state } = props;
|
|
453
|
+
const { host, workspace, project, repoName } = state;
|
|
454
|
+
return /* @__PURE__ */ React.createElement(React.Fragment, null, host === "bitbucket.org" && /* @__PURE__ */ React.createElement(FormControl, {
|
|
517
455
|
margin: "normal",
|
|
518
456
|
required: true,
|
|
519
457
|
error: (rawErrors == null ? void 0 : rawErrors.length) > 0 && !workspace
|
|
520
458
|
}, /* @__PURE__ */ React.createElement(InputLabel, {
|
|
521
|
-
htmlFor: "
|
|
459
|
+
htmlFor: "workspaceInput"
|
|
522
460
|
}, "Workspace"), /* @__PURE__ */ React.createElement(Input, {
|
|
523
|
-
id: "
|
|
524
|
-
onChange:
|
|
461
|
+
id: "workspaceInput",
|
|
462
|
+
onChange: (e) => onChange({ workspace: e.target.value }),
|
|
525
463
|
value: workspace
|
|
526
|
-
}), /* @__PURE__ */ React.createElement(FormHelperText, null, "The
|
|
464
|
+
}), /* @__PURE__ */ React.createElement(FormHelperText, null, "The Organization that this repo will belong to")), /* @__PURE__ */ React.createElement(FormControl, {
|
|
527
465
|
margin: "normal",
|
|
528
466
|
required: true,
|
|
529
467
|
error: (rawErrors == null ? void 0 : rawErrors.length) > 0 && !project
|
|
530
468
|
}, /* @__PURE__ */ React.createElement(InputLabel, {
|
|
531
|
-
htmlFor: "
|
|
469
|
+
htmlFor: "projectInput"
|
|
532
470
|
}, "Project"), /* @__PURE__ */ React.createElement(Input, {
|
|
533
|
-
id: "
|
|
534
|
-
onChange:
|
|
471
|
+
id: "projectInput",
|
|
472
|
+
onChange: (e) => onChange({ project: e.target.value }),
|
|
535
473
|
value: project
|
|
536
|
-
}), /* @__PURE__ */ React.createElement(FormHelperText, null, "The
|
|
474
|
+
}), /* @__PURE__ */ React.createElement(FormHelperText, null, "The Project that this repo will belong to")), /* @__PURE__ */ React.createElement(FormControl, {
|
|
537
475
|
margin: "normal",
|
|
538
476
|
required: true,
|
|
539
|
-
error: (rawErrors == null ? void 0 : rawErrors.length) > 0 && !
|
|
477
|
+
error: (rawErrors == null ? void 0 : rawErrors.length) > 0 && !repoName
|
|
540
478
|
}, /* @__PURE__ */ React.createElement(InputLabel, {
|
|
541
|
-
htmlFor: "
|
|
542
|
-
}, "
|
|
543
|
-
id: "
|
|
544
|
-
onChange:
|
|
545
|
-
value:
|
|
546
|
-
}), /* @__PURE__ */ React.createElement(FormHelperText, null, "The
|
|
479
|
+
htmlFor: "repoNameInput"
|
|
480
|
+
}, "Repository"), /* @__PURE__ */ React.createElement(Input, {
|
|
481
|
+
id: "repoNameInput",
|
|
482
|
+
onChange: (e) => onChange({ repoName: e.target.value }),
|
|
483
|
+
value: repoName
|
|
484
|
+
}), /* @__PURE__ */ React.createElement(FormHelperText, null, "The name of the repository")));
|
|
485
|
+
};
|
|
486
|
+
|
|
487
|
+
const RepoUrlPickerHost = (props) => {
|
|
488
|
+
const { host, hosts, onChange, rawErrors } = props;
|
|
489
|
+
const scaffolderApi = useApi(scaffolderApiRef);
|
|
490
|
+
const { value: integrations, loading } = useAsync(async () => {
|
|
491
|
+
return await scaffolderApi.getIntegrationsList({
|
|
492
|
+
allowedHosts: hosts != null ? hosts : []
|
|
493
|
+
});
|
|
494
|
+
});
|
|
495
|
+
useEffect(() => {
|
|
496
|
+
if (hosts && !host) {
|
|
497
|
+
onChange(hosts[0]);
|
|
498
|
+
}
|
|
499
|
+
}, [hosts, host, onChange]);
|
|
500
|
+
const hostsOptions = integrations ? integrations.filter((i) => hosts == null ? void 0 : hosts.includes(i.host)).map((i) => ({ label: i.title, value: i.host })) : [{ label: "Loading...", value: "loading" }];
|
|
501
|
+
if (loading) {
|
|
502
|
+
return /* @__PURE__ */ React.createElement(Progress, null);
|
|
503
|
+
}
|
|
504
|
+
return /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(FormControl, {
|
|
547
505
|
margin: "normal",
|
|
548
506
|
required: true,
|
|
549
|
-
error: (rawErrors == null ? void 0 : rawErrors.length) > 0 && !
|
|
507
|
+
error: (rawErrors == null ? void 0 : rawErrors.length) > 0 && !host
|
|
550
508
|
}, /* @__PURE__ */ React.createElement(Select, {
|
|
551
509
|
native: true,
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
selected:
|
|
556
|
-
items:
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
510
|
+
disabled: (hosts == null ? void 0 : hosts.length) === 1,
|
|
511
|
+
label: "Host",
|
|
512
|
+
onChange: (s) => onChange(String(Array.isArray(s) ? s[0] : s)),
|
|
513
|
+
selected: host,
|
|
514
|
+
items: hostsOptions,
|
|
515
|
+
"data-testid": "host-select"
|
|
516
|
+
}), /* @__PURE__ */ React.createElement(FormHelperText, null, "The host where the repository will be created")));
|
|
517
|
+
};
|
|
518
|
+
|
|
519
|
+
function serializeRepoPickerUrl(data) {
|
|
520
|
+
if (!data.host) {
|
|
521
|
+
return void 0;
|
|
522
|
+
}
|
|
523
|
+
const params = new URLSearchParams();
|
|
524
|
+
if (data.owner) {
|
|
525
|
+
params.set("owner", data.owner);
|
|
526
|
+
}
|
|
527
|
+
if (data.repoName) {
|
|
528
|
+
params.set("repo", data.repoName);
|
|
529
|
+
}
|
|
530
|
+
if (data.organization) {
|
|
531
|
+
params.set("organization", data.organization);
|
|
532
|
+
}
|
|
533
|
+
if (data.workspace) {
|
|
534
|
+
params.set("workspace", data.workspace);
|
|
535
|
+
}
|
|
536
|
+
if (data.project) {
|
|
537
|
+
params.set("project", data.project);
|
|
538
|
+
}
|
|
539
|
+
return `${data.host}?${params.toString()}`;
|
|
540
|
+
}
|
|
541
|
+
function parseRepoPickerUrl(url) {
|
|
542
|
+
let host = void 0;
|
|
543
|
+
let owner = void 0;
|
|
544
|
+
let repoName = void 0;
|
|
545
|
+
let organization = void 0;
|
|
546
|
+
let workspace = void 0;
|
|
547
|
+
let project = void 0;
|
|
548
|
+
try {
|
|
549
|
+
if (url) {
|
|
550
|
+
const parsed = new URL(`https://${url}`);
|
|
551
|
+
host = parsed.host;
|
|
552
|
+
owner = parsed.searchParams.get("owner") || void 0;
|
|
553
|
+
repoName = parsed.searchParams.get("repo") || void 0;
|
|
554
|
+
organization = parsed.searchParams.get("organization") || void 0;
|
|
555
|
+
workspace = parsed.searchParams.get("workspace") || void 0;
|
|
556
|
+
project = parsed.searchParams.get("project") || void 0;
|
|
557
|
+
}
|
|
558
|
+
} catch {
|
|
559
|
+
}
|
|
560
|
+
return { host, owner, repoName, organization, workspace, project };
|
|
561
|
+
}
|
|
562
|
+
|
|
563
|
+
const RepoUrlPicker = (props) => {
|
|
564
|
+
var _a, _b;
|
|
565
|
+
const { uiSchema, onChange, rawErrors, formData } = props;
|
|
566
|
+
const [state, setState] = useState(parseRepoPickerUrl(formData));
|
|
567
|
+
const integrationApi = useApi(scmIntegrationsApiRef);
|
|
568
|
+
const allowedHosts = useMemo(() => {
|
|
569
|
+
var _a2, _b2;
|
|
570
|
+
return (_b2 = (_a2 = uiSchema == null ? void 0 : uiSchema["ui:options"]) == null ? void 0 : _a2.allowedHosts) != null ? _b2 : [];
|
|
571
|
+
}, [uiSchema]);
|
|
572
|
+
const allowedOwners = useMemo(() => {
|
|
573
|
+
var _a2, _b2;
|
|
574
|
+
return (_b2 = (_a2 = uiSchema == null ? void 0 : uiSchema["ui:options"]) == null ? void 0 : _a2.allowedOwners) != null ? _b2 : [];
|
|
575
|
+
}, [uiSchema]);
|
|
576
|
+
useEffect(() => {
|
|
577
|
+
onChange(serializeRepoPickerUrl(state));
|
|
578
|
+
}, [state, onChange]);
|
|
579
|
+
useEffect(() => {
|
|
580
|
+
if (allowedOwners.length === 1) {
|
|
581
|
+
setState((prevState) => ({ ...prevState, owner: allowedOwners[0] }));
|
|
582
|
+
}
|
|
583
|
+
}, [setState, allowedOwners]);
|
|
584
|
+
const updateLocalState = useCallback((newState) => {
|
|
585
|
+
setState((prevState) => ({ ...prevState, ...newState }));
|
|
586
|
+
}, [setState]);
|
|
587
|
+
const hostType = (_b = state.host && ((_a = integrationApi.byHost(state.host)) == null ? void 0 : _a.type)) != null ? _b : null;
|
|
588
|
+
return /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(RepoUrlPickerHost, {
|
|
589
|
+
host: state.host,
|
|
590
|
+
hosts: allowedHosts,
|
|
591
|
+
onChange: (host) => setState((prevState) => ({ ...prevState, host })),
|
|
592
|
+
rawErrors
|
|
593
|
+
}), hostType === "github" && /* @__PURE__ */ React.createElement(GithubRepoPicker, {
|
|
594
|
+
allowedOwners,
|
|
595
|
+
rawErrors,
|
|
596
|
+
state,
|
|
597
|
+
onChange: updateLocalState
|
|
598
|
+
}), hostType === "gitlab" && /* @__PURE__ */ React.createElement(GitlabRepoPicker, {
|
|
599
|
+
allowedOwners,
|
|
600
|
+
rawErrors,
|
|
601
|
+
state,
|
|
602
|
+
onChange: updateLocalState
|
|
603
|
+
}), hostType === "bitbucket" && /* @__PURE__ */ React.createElement(BitbucketRepoPicker, {
|
|
604
|
+
rawErrors,
|
|
605
|
+
state,
|
|
606
|
+
onChange: updateLocalState
|
|
607
|
+
}), hostType === "azure" && /* @__PURE__ */ React.createElement(AzureRepoPicker, {
|
|
608
|
+
rawErrors,
|
|
609
|
+
state,
|
|
610
|
+
onChange: updateLocalState
|
|
611
|
+
}));
|
|
568
612
|
};
|
|
569
613
|
|
|
570
614
|
const repoPickerValidation = (value, validation, context) => {
|
|
@@ -666,10 +710,14 @@ const scaffolderPlugin = createPlugin({
|
|
|
666
710
|
api: scaffolderApiRef,
|
|
667
711
|
deps: {
|
|
668
712
|
discoveryApi: discoveryApiRef,
|
|
669
|
-
|
|
670
|
-
|
|
713
|
+
scmIntegrationsApi: scmIntegrationsApiRef,
|
|
714
|
+
fetchApi: fetchApiRef
|
|
671
715
|
},
|
|
672
|
-
factory: ({ discoveryApi,
|
|
716
|
+
factory: ({ discoveryApi, scmIntegrationsApi, fetchApi }) => new ScaffolderClient({
|
|
717
|
+
discoveryApi,
|
|
718
|
+
scmIntegrationsApi,
|
|
719
|
+
fetchApi
|
|
720
|
+
})
|
|
673
721
|
})
|
|
674
722
|
],
|
|
675
723
|
routes: {
|
|
@@ -699,7 +747,7 @@ const OwnerPickerFieldExtension = scaffolderPlugin.provide(createScaffolderField
|
|
|
699
747
|
}));
|
|
700
748
|
const ScaffolderPage = scaffolderPlugin.provide(createRoutableExtension({
|
|
701
749
|
name: "ScaffolderPage",
|
|
702
|
-
component: () => import('./Router-
|
|
750
|
+
component: () => import('./Router-5ca674eb.esm.js').then((m) => m.Router),
|
|
703
751
|
mountPoint: rootRouteRef
|
|
704
752
|
}));
|
|
705
753
|
const OwnedEntityPickerFieldExtension = scaffolderPlugin.provide(createScaffolderFieldExtension({
|
|
@@ -942,4 +990,4 @@ const TemplateTypePicker = () => {
|
|
|
942
990
|
};
|
|
943
991
|
|
|
944
992
|
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 };
|
|
945
|
-
//# sourceMappingURL=index-
|
|
993
|
+
//# sourceMappingURL=index-8b5d21c1.esm.js.map
|