@backstage/plugin-scaffolder 0.11.17 → 0.12.1-next.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-552fb2ce.esm.js → Router-9da81048.esm.js} +5 -4
- package/dist/esm/Router-9da81048.esm.js.map +1 -0
- package/dist/esm/{index-768702c3.esm.js → index-837d4328.esm.js} +270 -223
- package/dist/esm/index-837d4328.esm.js.map +1 -0
- package/dist/index.d.ts +60 -17
- package/dist/index.esm.js +3 -3
- package/package.json +17 -17
- package/dist/esm/Router-552fb2ce.esm.js.map +0 -1
- package/dist/esm/index-768702c3.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,16 +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';
|
|
9
|
+
import React, { useCallback, useEffect, useState, useMemo } from 'react';
|
|
10
10
|
import useAsync from 'react-use/lib/useAsync';
|
|
11
11
|
import { KubernetesValidatorFunctions, makeValidator, RELATION_OWNED_BY, stringifyEntityRef } from '@backstage/catalog-model';
|
|
12
|
-
import
|
|
12
|
+
import useEffectOnce from 'react-use/lib/useEffectOnce';
|
|
13
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';
|
|
15
14
|
import { scmIntegrationsApiRef, ScmIntegrationIcon } from '@backstage/integration-react';
|
|
16
15
|
import FormHelperText from '@material-ui/core/FormHelperText';
|
|
17
16
|
import Input from '@material-ui/core/Input';
|
|
18
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';
|
|
19
19
|
import Star from '@material-ui/icons/Star';
|
|
20
20
|
import StarBorder from '@material-ui/icons/StarBorder';
|
|
21
21
|
import WarningIcon from '@material-ui/icons/Warning';
|
|
@@ -30,11 +30,11 @@ const scaffolderApiRef = createApiRef({
|
|
|
30
30
|
});
|
|
31
31
|
class ScaffolderClient {
|
|
32
32
|
constructor(options) {
|
|
33
|
-
var _a;
|
|
33
|
+
var _a, _b;
|
|
34
34
|
this.discoveryApi = options.discoveryApi;
|
|
35
|
-
this.
|
|
35
|
+
this.fetchApi = (_a = options.fetchApi) != null ? _a : { fetch };
|
|
36
36
|
this.scmIntegrationsApi = options.scmIntegrationsApi;
|
|
37
|
-
this.useLongPollingLogs = (
|
|
37
|
+
this.useLongPollingLogs = (_b = options.useLongPollingLogs) != null ? _b : false;
|
|
38
38
|
}
|
|
39
39
|
async getIntegrationsList(options) {
|
|
40
40
|
return [
|
|
@@ -46,31 +46,28 @@ class ScaffolderClient {
|
|
|
46
46
|
}
|
|
47
47
|
async getTemplateParameterSchema(templateName) {
|
|
48
48
|
const { namespace, kind, name } = templateName;
|
|
49
|
-
const token = await this.identityApi.getIdToken();
|
|
50
49
|
const baseUrl = await this.discoveryApi.getBaseUrl("scaffolder");
|
|
51
50
|
const templatePath = [namespace, kind, name].map((s) => encodeURIComponent(s)).join("/");
|
|
52
51
|
const url = `${baseUrl}/v2/templates/${templatePath}/parameter-schema`;
|
|
53
|
-
const response = await fetch(url
|
|
54
|
-
headers: {
|
|
55
|
-
...token && { Authorization: `Bearer ${token}` }
|
|
56
|
-
}
|
|
57
|
-
});
|
|
52
|
+
const response = await this.fetchApi.fetch(url);
|
|
58
53
|
if (!response.ok) {
|
|
59
54
|
throw await ResponseError.fromResponse(response);
|
|
60
55
|
}
|
|
61
56
|
const schema = await response.json();
|
|
62
57
|
return schema;
|
|
63
58
|
}
|
|
64
|
-
async scaffold(templateName, values) {
|
|
65
|
-
const token = await this.identityApi.getIdToken();
|
|
59
|
+
async scaffold(templateName, values, secrets = {}) {
|
|
66
60
|
const url = `${await this.discoveryApi.getBaseUrl("scaffolder")}/v2/tasks`;
|
|
67
|
-
const response = await fetch(url, {
|
|
61
|
+
const response = await this.fetchApi.fetch(url, {
|
|
68
62
|
method: "POST",
|
|
69
63
|
headers: {
|
|
70
|
-
"Content-Type": "application/json"
|
|
71
|
-
...token && { Authorization: `Bearer ${token}` }
|
|
64
|
+
"Content-Type": "application/json"
|
|
72
65
|
},
|
|
73
|
-
body: JSON.stringify({
|
|
66
|
+
body: JSON.stringify({
|
|
67
|
+
templateName,
|
|
68
|
+
values: { ...values },
|
|
69
|
+
secrets
|
|
70
|
+
})
|
|
74
71
|
});
|
|
75
72
|
if (response.status !== 201) {
|
|
76
73
|
const status = `${response.status} ${response.statusText}`;
|
|
@@ -81,22 +78,19 @@ class ScaffolderClient {
|
|
|
81
78
|
return id;
|
|
82
79
|
}
|
|
83
80
|
async getTask(taskId) {
|
|
84
|
-
const token = await this.identityApi.getIdToken();
|
|
85
81
|
const baseUrl = await this.discoveryApi.getBaseUrl("scaffolder");
|
|
86
82
|
const url = `${baseUrl}/v2/tasks/${encodeURIComponent(taskId)}`;
|
|
87
|
-
const response = await fetch(url
|
|
88
|
-
headers: token ? { Authorization: `Bearer ${token}` } : {}
|
|
89
|
-
});
|
|
83
|
+
const response = await this.fetchApi.fetch(url);
|
|
90
84
|
if (!response.ok) {
|
|
91
85
|
throw await ResponseError.fromResponse(response);
|
|
92
86
|
}
|
|
93
87
|
return await response.json();
|
|
94
88
|
}
|
|
95
|
-
streamLogs(
|
|
89
|
+
streamLogs(options) {
|
|
96
90
|
if (this.useLongPollingLogs) {
|
|
97
|
-
return this.streamLogsPolling(
|
|
91
|
+
return this.streamLogsPolling(options);
|
|
98
92
|
}
|
|
99
|
-
return this.streamLogsEventStream(
|
|
93
|
+
return this.streamLogsEventStream(options);
|
|
100
94
|
}
|
|
101
95
|
streamLogsEventStream({
|
|
102
96
|
taskId,
|
|
@@ -147,7 +141,7 @@ class ScaffolderClient {
|
|
|
147
141
|
this.discoveryApi.getBaseUrl("scaffolder").then(async (baseUrl) => {
|
|
148
142
|
while (!subscriber.closed) {
|
|
149
143
|
const url = `${baseUrl}/v2/tasks/${encodeURIComponent(taskId)}/events?${qs.stringify({ after })}`;
|
|
150
|
-
const response = await fetch(url);
|
|
144
|
+
const response = await this.fetchApi.fetch(url);
|
|
151
145
|
if (!response.ok) {
|
|
152
146
|
await new Promise((resolve) => setTimeout(resolve, 1e3));
|
|
153
147
|
continue;
|
|
@@ -167,10 +161,7 @@ class ScaffolderClient {
|
|
|
167
161
|
}
|
|
168
162
|
async listActions() {
|
|
169
163
|
const baseUrl = await this.discoveryApi.getBaseUrl("scaffolder");
|
|
170
|
-
const
|
|
171
|
-
const response = await fetch(`${baseUrl}/v2/actions`, {
|
|
172
|
-
headers: token ? { Authorization: `Bearer ${token}` } : {}
|
|
173
|
-
});
|
|
164
|
+
const response = await this.fetchApi.fetch(`${baseUrl}/v2/actions`);
|
|
174
165
|
if (!response.ok) {
|
|
175
166
|
throw await ResponseError.fromResponse(response);
|
|
176
167
|
}
|
|
@@ -277,7 +268,7 @@ const EntityTagsPicker = ({
|
|
|
277
268
|
const [inputError, setInputError] = useState(false);
|
|
278
269
|
const tagValidator = makeValidator().isValidTag;
|
|
279
270
|
const kinds = (_a = uiSchema["ui:options"]) == null ? void 0 : _a.kinds;
|
|
280
|
-
const { loading, value: existingTags } = useAsync
|
|
271
|
+
const { loading, value: existingTags } = useAsync(async () => {
|
|
281
272
|
const tagsRequest = { fields: ["metadata.tags"] };
|
|
282
273
|
if (kinds) {
|
|
283
274
|
tagsRequest.filter = { kind: kinds };
|
|
@@ -351,221 +342,273 @@ const OwnerPicker = ({
|
|
|
351
342
|
});
|
|
352
343
|
};
|
|
353
344
|
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
let organization = void 0;
|
|
359
|
-
let workspace = void 0;
|
|
360
|
-
let project = void 0;
|
|
361
|
-
try {
|
|
362
|
-
if (url) {
|
|
363
|
-
const parsed = new URL(`https://${url}`);
|
|
364
|
-
host = parsed.host;
|
|
365
|
-
owner = parsed.searchParams.get("owner") || (allowedOwners == null ? void 0 : allowedOwners[0]);
|
|
366
|
-
repo = parsed.searchParams.get("repo") || void 0;
|
|
367
|
-
organization = parsed.searchParams.get("organization") || void 0;
|
|
368
|
-
workspace = parsed.searchParams.get("workspace") || void 0;
|
|
369
|
-
project = parsed.searchParams.get("project") || void 0;
|
|
370
|
-
}
|
|
371
|
-
} catch {
|
|
372
|
-
}
|
|
373
|
-
return { host, owner, repo, organization, workspace, project };
|
|
374
|
-
}
|
|
375
|
-
function serializeFormData(data) {
|
|
376
|
-
if (!data.host) {
|
|
377
|
-
return void 0;
|
|
378
|
-
}
|
|
379
|
-
const params = new URLSearchParams();
|
|
380
|
-
if (data.owner) {
|
|
381
|
-
params.set("owner", data.owner);
|
|
382
|
-
}
|
|
383
|
-
if (data.repo) {
|
|
384
|
-
params.set("repo", data.repo);
|
|
385
|
-
}
|
|
386
|
-
if (data.organization) {
|
|
387
|
-
params.set("organization", data.organization);
|
|
388
|
-
}
|
|
389
|
-
if (data.workspace) {
|
|
390
|
-
params.set("workspace", data.workspace);
|
|
391
|
-
}
|
|
392
|
-
if (data.project) {
|
|
393
|
-
params.set("project", data.project);
|
|
394
|
-
}
|
|
395
|
-
return `${data.host}?${params.toString()}`;
|
|
396
|
-
}
|
|
397
|
-
const RepoUrlPicker = ({
|
|
398
|
-
onChange,
|
|
399
|
-
uiSchema,
|
|
400
|
-
rawErrors,
|
|
401
|
-
formData
|
|
402
|
-
}) => {
|
|
403
|
-
var _a, _b, _c, _d, _e;
|
|
404
|
-
const scaffolderApi = useApi(scaffolderApiRef);
|
|
405
|
-
const integrationApi = useApi(scmIntegrationsApiRef);
|
|
406
|
-
const allowedHosts = (_a = uiSchema["ui:options"]) == null ? void 0 : _a.allowedHosts;
|
|
407
|
-
const allowedOwners = (_b = uiSchema["ui:options"]) == null ? void 0 : _b.allowedOwners;
|
|
408
|
-
const { value: integrations, loading } = useAsync(async () => {
|
|
409
|
-
return await scaffolderApi.getIntegrationsList({ allowedHosts });
|
|
410
|
-
});
|
|
411
|
-
const { host, owner, repo, organization, workspace, project } = splitFormData(formData, allowedOwners);
|
|
412
|
-
const updateHost = useCallback((value) => {
|
|
413
|
-
onChange(serializeFormData({
|
|
414
|
-
host: value,
|
|
415
|
-
owner,
|
|
416
|
-
repo,
|
|
417
|
-
organization,
|
|
418
|
-
workspace,
|
|
419
|
-
project
|
|
420
|
-
}));
|
|
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]);
|
|
430
|
-
const updateOwner = useCallback((evt) => onChange(serializeFormData({
|
|
431
|
-
host,
|
|
432
|
-
owner: evt.target.value,
|
|
433
|
-
repo,
|
|
434
|
-
organization,
|
|
435
|
-
workspace,
|
|
436
|
-
project
|
|
437
|
-
})), [onChange, host, repo, organization, workspace, project]);
|
|
438
|
-
const updateRepo = useCallback((evt) => onChange(serializeFormData({
|
|
439
|
-
host,
|
|
440
|
-
owner,
|
|
441
|
-
repo: evt.target.value,
|
|
442
|
-
organization,
|
|
443
|
-
workspace,
|
|
444
|
-
project
|
|
445
|
-
})), [onChange, host, owner, organization, workspace, project]);
|
|
446
|
-
const updateOrganization = useCallback((evt) => onChange(serializeFormData({
|
|
447
|
-
host,
|
|
448
|
-
owner,
|
|
449
|
-
repo,
|
|
450
|
-
organization: evt.target.value,
|
|
451
|
-
workspace,
|
|
452
|
-
project
|
|
453
|
-
})), [onChange, host, owner, repo, workspace, project]);
|
|
454
|
-
const updateWorkspace = useCallback((evt) => onChange(serializeFormData({
|
|
455
|
-
host,
|
|
456
|
-
owner,
|
|
457
|
-
repo,
|
|
458
|
-
organization,
|
|
459
|
-
workspace: evt.target.value,
|
|
460
|
-
project
|
|
461
|
-
})), [onChange, host, owner, repo, organization, project]);
|
|
462
|
-
const updateProject = useCallback((evt) => onChange(serializeFormData({
|
|
463
|
-
host,
|
|
464
|
-
owner,
|
|
465
|
-
repo,
|
|
466
|
-
organization,
|
|
467
|
-
workspace,
|
|
468
|
-
project: evt.target.value
|
|
469
|
-
})), [onChange, host, owner, repo, organization, workspace]);
|
|
470
|
-
useEffect(() => {
|
|
471
|
-
if (host === void 0 && (integrations == null ? void 0 : integrations.length)) {
|
|
472
|
-
onChange(serializeFormData({
|
|
473
|
-
host: integrations[0].host,
|
|
474
|
-
owner,
|
|
475
|
-
repo,
|
|
476
|
-
organization,
|
|
477
|
-
workspace,
|
|
478
|
-
project
|
|
479
|
-
}));
|
|
480
|
-
}
|
|
481
|
-
}, [
|
|
482
|
-
onChange,
|
|
483
|
-
integrations,
|
|
484
|
-
host,
|
|
485
|
-
owner,
|
|
486
|
-
repo,
|
|
487
|
-
organization,
|
|
488
|
-
workspace,
|
|
489
|
-
project
|
|
490
|
-
]);
|
|
491
|
-
if (loading) {
|
|
492
|
-
return /* @__PURE__ */ React.createElement(Progress, null);
|
|
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" }];
|
|
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;
|
|
496
349
|
return /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(FormControl, {
|
|
497
350
|
margin: "normal",
|
|
498
351
|
required: true,
|
|
499
|
-
error: (rawErrors == null ? void 0 : rawErrors.length) > 0 && !
|
|
500
|
-
}, /* @__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, {
|
|
501
354
|
native: true,
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
selected:
|
|
506
|
-
items:
|
|
507
|
-
})
|
|
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, {
|
|
508
419
|
margin: "normal",
|
|
509
420
|
required: true,
|
|
510
421
|
error: (rawErrors == null ? void 0 : rawErrors.length) > 0 && !organization
|
|
511
422
|
}, /* @__PURE__ */ React.createElement(InputLabel, {
|
|
512
|
-
htmlFor: "
|
|
423
|
+
htmlFor: "orgInput"
|
|
513
424
|
}, "Organization"), /* @__PURE__ */ React.createElement(Input, {
|
|
514
|
-
id: "
|
|
515
|
-
onChange:
|
|
425
|
+
id: "orgInput",
|
|
426
|
+
onChange: (e) => onChange({ organization: e.target.value }),
|
|
516
427
|
value: organization
|
|
517
|
-
}), /* @__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, {
|
|
518
455
|
margin: "normal",
|
|
519
456
|
required: true,
|
|
520
457
|
error: (rawErrors == null ? void 0 : rawErrors.length) > 0 && !workspace
|
|
521
458
|
}, /* @__PURE__ */ React.createElement(InputLabel, {
|
|
522
|
-
htmlFor: "
|
|
459
|
+
htmlFor: "workspaceInput"
|
|
523
460
|
}, "Workspace"), /* @__PURE__ */ React.createElement(Input, {
|
|
524
|
-
id: "
|
|
525
|
-
onChange:
|
|
461
|
+
id: "workspaceInput",
|
|
462
|
+
onChange: (e) => onChange({ workspace: e.target.value }),
|
|
526
463
|
value: workspace
|
|
527
|
-
}), /* @__PURE__ */ React.createElement(FormHelperText, null, "The
|
|
464
|
+
}), /* @__PURE__ */ React.createElement(FormHelperText, null, "The Organization that this repo will belong to")), /* @__PURE__ */ React.createElement(FormControl, {
|
|
528
465
|
margin: "normal",
|
|
529
466
|
required: true,
|
|
530
467
|
error: (rawErrors == null ? void 0 : rawErrors.length) > 0 && !project
|
|
531
468
|
}, /* @__PURE__ */ React.createElement(InputLabel, {
|
|
532
|
-
htmlFor: "
|
|
469
|
+
htmlFor: "projectInput"
|
|
533
470
|
}, "Project"), /* @__PURE__ */ React.createElement(Input, {
|
|
534
|
-
id: "
|
|
535
|
-
onChange:
|
|
471
|
+
id: "projectInput",
|
|
472
|
+
onChange: (e) => onChange({ project: e.target.value }),
|
|
536
473
|
value: project
|
|
537
|
-
}), /* @__PURE__ */ React.createElement(FormHelperText, null, "The
|
|
474
|
+
}), /* @__PURE__ */ React.createElement(FormHelperText, null, "The Project that this repo will belong to")), /* @__PURE__ */ React.createElement(FormControl, {
|
|
538
475
|
margin: "normal",
|
|
539
476
|
required: true,
|
|
540
|
-
error: (rawErrors == null ? void 0 : rawErrors.length) > 0 && !
|
|
477
|
+
error: (rawErrors == null ? void 0 : rawErrors.length) > 0 && !repoName
|
|
541
478
|
}, /* @__PURE__ */ React.createElement(InputLabel, {
|
|
542
|
-
htmlFor: "
|
|
543
|
-
}, "
|
|
544
|
-
id: "
|
|
545
|
-
onChange:
|
|
546
|
-
value:
|
|
547
|
-
}), /* @__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, {
|
|
548
505
|
margin: "normal",
|
|
549
506
|
required: true,
|
|
550
|
-
error: (rawErrors == null ? void 0 : rawErrors.length) > 0 && !
|
|
507
|
+
error: (rawErrors == null ? void 0 : rawErrors.length) > 0 && !host
|
|
551
508
|
}, /* @__PURE__ */ React.createElement(Select, {
|
|
552
509
|
native: true,
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
selected:
|
|
557
|
-
items:
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
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
|
+
}));
|
|
569
612
|
};
|
|
570
613
|
|
|
571
614
|
const repoPickerValidation = (value, validation, context) => {
|
|
@@ -667,10 +710,14 @@ const scaffolderPlugin = createPlugin({
|
|
|
667
710
|
api: scaffolderApiRef,
|
|
668
711
|
deps: {
|
|
669
712
|
discoveryApi: discoveryApiRef,
|
|
670
|
-
|
|
671
|
-
|
|
713
|
+
scmIntegrationsApi: scmIntegrationsApiRef,
|
|
714
|
+
fetchApi: fetchApiRef
|
|
672
715
|
},
|
|
673
|
-
factory: ({ discoveryApi,
|
|
716
|
+
factory: ({ discoveryApi, scmIntegrationsApi, fetchApi }) => new ScaffolderClient({
|
|
717
|
+
discoveryApi,
|
|
718
|
+
scmIntegrationsApi,
|
|
719
|
+
fetchApi
|
|
720
|
+
})
|
|
674
721
|
})
|
|
675
722
|
],
|
|
676
723
|
routes: {
|
|
@@ -700,7 +747,7 @@ const OwnerPickerFieldExtension = scaffolderPlugin.provide(createScaffolderField
|
|
|
700
747
|
}));
|
|
701
748
|
const ScaffolderPage = scaffolderPlugin.provide(createRoutableExtension({
|
|
702
749
|
name: "ScaffolderPage",
|
|
703
|
-
component: () => import('./Router-
|
|
750
|
+
component: () => import('./Router-9da81048.esm.js').then((m) => m.Router),
|
|
704
751
|
mountPoint: rootRouteRef
|
|
705
752
|
}));
|
|
706
753
|
const OwnedEntityPickerFieldExtension = scaffolderPlugin.provide(createScaffolderFieldExtension({
|
|
@@ -943,4 +990,4 @@ const TemplateTypePicker = () => {
|
|
|
943
990
|
};
|
|
944
991
|
|
|
945
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 };
|
|
946
|
-
//# sourceMappingURL=index-
|
|
993
|
+
//# sourceMappingURL=index-837d4328.esm.js.map
|