@backstage/plugin-scaffolder 1.19.4-next.2 → 1.20.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.
Files changed (84) hide show
  1. package/CHANGELOG.md +50 -0
  2. package/README.md +1 -2
  3. package/alpha/package.json +1 -1
  4. package/dist/api.esm.js +9 -17
  5. package/dist/api.esm.js.map +1 -1
  6. package/dist/components/ActionsPage/ActionsPage.esm.js +10 -13
  7. package/dist/components/ActionsPage/ActionsPage.esm.js.map +1 -1
  8. package/dist/components/FileBrowser/FileBrowser.esm.js +1 -1
  9. package/dist/components/FileBrowser/FileBrowser.esm.js.map +1 -1
  10. package/dist/components/ListTasksPage/ListTasksPage.esm.js +9 -17
  11. package/dist/components/ListTasksPage/ListTasksPage.esm.js.map +1 -1
  12. package/dist/components/ListTasksPage/columns/OwnerEntityColumn.esm.js +1 -2
  13. package/dist/components/ListTasksPage/columns/OwnerEntityColumn.esm.js.map +1 -1
  14. package/dist/components/ListTasksPage/columns/TemplateTitleColumn.esm.js +1 -1
  15. package/dist/components/ListTasksPage/columns/TemplateTitleColumn.esm.js.map +1 -1
  16. package/dist/components/OngoingTask/ContextMenu.esm.js +1 -1
  17. package/dist/components/OngoingTask/ContextMenu.esm.js.map +1 -1
  18. package/dist/components/OngoingTask/OngoingTask.esm.js +10 -18
  19. package/dist/components/OngoingTask/OngoingTask.esm.js.map +1 -1
  20. package/dist/components/fields/EntityNamePicker/EntityNamePicker.esm.js +3 -3
  21. package/dist/components/fields/EntityNamePicker/EntityNamePicker.esm.js.map +1 -1
  22. package/dist/components/fields/EntityPicker/EntityPicker.esm.js +11 -13
  23. package/dist/components/fields/EntityPicker/EntityPicker.esm.js.map +1 -1
  24. package/dist/components/fields/EntityTagsPicker/EntityTagsPicker.esm.js +6 -7
  25. package/dist/components/fields/EntityTagsPicker/EntityTagsPicker.esm.js.map +1 -1
  26. package/dist/components/fields/MultiEntityPicker/MultiEntityPicker.esm.js +29 -41
  27. package/dist/components/fields/MultiEntityPicker/MultiEntityPicker.esm.js.map +1 -1
  28. package/dist/components/fields/MyGroupsPicker/MyGroupsPicker.esm.js +7 -11
  29. package/dist/components/fields/MyGroupsPicker/MyGroupsPicker.esm.js.map +1 -1
  30. package/dist/components/fields/OwnedEntityPicker/OwnedEntityPicker.esm.js +1 -1
  31. package/dist/components/fields/OwnedEntityPicker/OwnedEntityPicker.esm.js.map +1 -1
  32. package/dist/components/fields/OwnerPicker/OwnerPicker.esm.js +4 -5
  33. package/dist/components/fields/OwnerPicker/OwnerPicker.esm.js.map +1 -1
  34. package/dist/components/fields/RepoUrlPicker/AzureRepoPicker.esm.js +16 -16
  35. package/dist/components/fields/RepoUrlPicker/AzureRepoPicker.esm.js.map +1 -1
  36. package/dist/components/fields/RepoUrlPicker/BitbucketRepoPicker.esm.js +6 -6
  37. package/dist/components/fields/RepoUrlPicker/BitbucketRepoPicker.esm.js.map +1 -1
  38. package/dist/components/fields/RepoUrlPicker/GerritRepoPicker.esm.js +2 -2
  39. package/dist/components/fields/RepoUrlPicker/GerritRepoPicker.esm.js.map +1 -1
  40. package/dist/components/fields/RepoUrlPicker/GiteaRepoPicker.esm.js +2 -2
  41. package/dist/components/fields/RepoUrlPicker/GiteaRepoPicker.esm.js.map +1 -1
  42. package/dist/components/fields/RepoUrlPicker/GithubRepoPicker.esm.js +2 -2
  43. package/dist/components/fields/RepoUrlPicker/GithubRepoPicker.esm.js.map +1 -1
  44. package/dist/components/fields/RepoUrlPicker/GitlabRepoPicker.esm.js +2 -2
  45. package/dist/components/fields/RepoUrlPicker/GitlabRepoPicker.esm.js.map +1 -1
  46. package/dist/components/fields/RepoUrlPicker/RepoUrlPicker.esm.js +8 -25
  47. package/dist/components/fields/RepoUrlPicker/RepoUrlPicker.esm.js.map +1 -1
  48. package/dist/components/fields/RepoUrlPicker/RepoUrlPickerHost.esm.js +6 -6
  49. package/dist/components/fields/RepoUrlPicker/RepoUrlPickerHost.esm.js.map +1 -1
  50. package/dist/components/fields/RepoUrlPicker/RepoUrlPickerRepoName.esm.js +3 -3
  51. package/dist/components/fields/RepoUrlPicker/RepoUrlPickerRepoName.esm.js.map +1 -1
  52. package/dist/components/fields/RepoUrlPicker/validation.esm.js +2 -3
  53. package/dist/components/fields/RepoUrlPicker/validation.esm.js.map +1 -1
  54. package/dist/components/fields/SecretInput/SecretInput.esm.js +3 -5
  55. package/dist/components/fields/SecretInput/SecretInput.esm.js.map +1 -1
  56. package/dist/next/TemplateEditorPage/CustomFieldExplorer.esm.js +14 -18
  57. package/dist/next/TemplateEditorPage/CustomFieldExplorer.esm.js.map +1 -1
  58. package/dist/next/TemplateEditorPage/DirectoryEditorContext.esm.js +55 -91
  59. package/dist/next/TemplateEditorPage/DirectoryEditorContext.esm.js.map +1 -1
  60. package/dist/next/TemplateEditorPage/DryRunContext.esm.js +5 -9
  61. package/dist/next/TemplateEditorPage/DryRunContext.esm.js.map +1 -1
  62. package/dist/next/TemplateEditorPage/DryRunResults/DryRunResultsList.esm.js +1 -2
  63. package/dist/next/TemplateEditorPage/DryRunResults/DryRunResultsList.esm.js.map +1 -1
  64. package/dist/next/TemplateEditorPage/DryRunResults/DryRunResultsView.esm.js +8 -12
  65. package/dist/next/TemplateEditorPage/DryRunResults/DryRunResultsView.esm.js.map +1 -1
  66. package/dist/next/TemplateEditorPage/DryRunResults/TaskPageLinks.esm.js +2 -5
  67. package/dist/next/TemplateEditorPage/DryRunResults/TaskPageLinks.esm.js.map +1 -1
  68. package/dist/next/TemplateEditorPage/TemplateEditorBrowser.esm.js +1 -2
  69. package/dist/next/TemplateEditorPage/TemplateEditorBrowser.esm.js.map +1 -1
  70. package/dist/next/TemplateEditorPage/TemplateEditorForm.esm.js +4 -13
  71. package/dist/next/TemplateEditorPage/TemplateEditorForm.esm.js.map +1 -1
  72. package/dist/next/TemplateEditorPage/TemplateEditorIntro.esm.js +3 -12
  73. package/dist/next/TemplateEditorPage/TemplateEditorIntro.esm.js.map +1 -1
  74. package/dist/next/TemplateEditorPage/TemplateEditorPage.esm.js +3 -3
  75. package/dist/next/TemplateEditorPage/TemplateEditorPage.esm.js.map +1 -1
  76. package/dist/next/TemplateEditorPage/TemplateEditorTextArea.esm.js +5 -15
  77. package/dist/next/TemplateEditorPage/TemplateEditorTextArea.esm.js.map +1 -1
  78. package/dist/next/TemplateEditorPage/TemplateFormPreviewer.esm.js +4 -7
  79. package/dist/next/TemplateEditorPage/TemplateFormPreviewer.esm.js.map +1 -1
  80. package/dist/next/TemplateListPage/TemplateListPage.esm.js +5 -7
  81. package/dist/next/TemplateListPage/TemplateListPage.esm.js.map +1 -1
  82. package/dist/next/TemplateWizardPage/TemplateWizardPage.esm.js +1 -2
  83. package/dist/next/TemplateWizardPage/TemplateWizardPage.esm.js.map +1 -1
  84. package/package.json +17 -17
@@ -2,157 +2,121 @@ import { ErrorPanel, Progress } from '@backstage/core-components';
2
2
  import { useAsync, useRerender } from '@react-hookz/web';
3
3
  import React, { createContext, useEffect, useContext } from 'react';
4
4
 
5
- var __defProp = Object.defineProperty;
6
- var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
7
- var __publicField = (obj, key, value) => {
8
- __defNormalProp(obj, key + "" , value);
9
- return value;
10
- };
11
- var __accessCheck = (obj, member, msg) => {
12
- if (!member.has(obj))
13
- throw TypeError("Cannot " + msg);
14
- };
15
- var __privateGet = (obj, member, getter) => {
16
- __accessCheck(obj, member, "read from private field");
17
- return member.get(obj);
18
- };
19
- var __privateAdd = (obj, member, value) => {
20
- if (member.has(obj))
21
- throw TypeError("Cannot add the same private member more than once");
22
- member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
23
- };
24
- var __privateSet = (obj, member, value, setter) => {
25
- __accessCheck(obj, member, "write to private field");
26
- member.set(obj, value);
27
- return value;
28
- };
29
- var _access, _signalUpdate, _content, _savedContent, _access2, _listeners, _files, _selectedFile, _signalUpdate2;
30
5
  const MAX_SIZE = 1024 * 1024;
31
6
  const MAX_SIZE_MESSAGE = "This file is too large to be displayed";
32
7
  class DirectoryEditorFileManager {
8
+ #access;
9
+ #signalUpdate;
10
+ #content;
11
+ #savedContent;
33
12
  constructor(access, signalUpdate) {
34
- __privateAdd(this, _access, void 0);
35
- __privateAdd(this, _signalUpdate, void 0);
36
- __privateAdd(this, _content, void 0);
37
- __privateAdd(this, _savedContent, void 0);
38
- __privateSet(this, _access, access);
39
- __privateSet(this, _signalUpdate, signalUpdate);
13
+ this.#access = access;
14
+ this.#signalUpdate = signalUpdate;
40
15
  }
41
16
  get path() {
42
- return __privateGet(this, _access).path;
17
+ return this.#access.path;
43
18
  }
44
19
  get content() {
45
- var _a;
46
- return (_a = __privateGet(this, _content)) != null ? _a : MAX_SIZE_MESSAGE;
20
+ return this.#content ?? MAX_SIZE_MESSAGE;
47
21
  }
48
22
  updateContent(content) {
49
- if (__privateGet(this, _content) === void 0) {
23
+ if (this.#content === void 0) {
50
24
  return;
51
25
  }
52
- __privateSet(this, _content, content);
53
- __privateGet(this, _signalUpdate).call(this);
26
+ this.#content = content;
27
+ this.#signalUpdate();
54
28
  }
55
29
  get dirty() {
56
- return __privateGet(this, _content) !== __privateGet(this, _savedContent);
30
+ return this.#content !== this.#savedContent;
57
31
  }
58
32
  async save() {
59
- if (__privateGet(this, _content) !== void 0) {
60
- await __privateGet(this, _access).save(__privateGet(this, _content));
61
- __privateSet(this, _savedContent, __privateGet(this, _content));
62
- __privateGet(this, _signalUpdate).call(this);
33
+ if (this.#content !== void 0) {
34
+ await this.#access.save(this.#content);
35
+ this.#savedContent = this.#content;
36
+ this.#signalUpdate();
63
37
  }
64
38
  }
65
39
  async reload() {
66
- const file = await __privateGet(this, _access).file();
40
+ const file = await this.#access.file();
67
41
  if (file.size > MAX_SIZE) {
68
- if (__privateGet(this, _content) !== void 0) {
69
- __privateSet(this, _content, void 0);
70
- __privateSet(this, _savedContent, void 0);
71
- __privateGet(this, _signalUpdate).call(this);
42
+ if (this.#content !== void 0) {
43
+ this.#content = void 0;
44
+ this.#savedContent = void 0;
45
+ this.#signalUpdate();
72
46
  }
73
47
  return;
74
48
  }
75
49
  const content = await file.text();
76
- if (__privateGet(this, _content) !== content) {
77
- __privateSet(this, _content, content);
78
- __privateSet(this, _savedContent, content);
79
- __privateGet(this, _signalUpdate).call(this);
50
+ if (this.#content !== content) {
51
+ this.#content = content;
52
+ this.#savedContent = content;
53
+ this.#signalUpdate();
80
54
  }
81
55
  }
82
56
  }
83
- _access = new WeakMap();
84
- _signalUpdate = new WeakMap();
85
- _content = new WeakMap();
86
- _savedContent = new WeakMap();
87
57
  class DirectoryEditorManager {
58
+ #access;
59
+ #listeners = /* @__PURE__ */ new Set();
60
+ #files = [];
61
+ #selectedFile;
88
62
  constructor(access) {
89
- __privateAdd(this, _access2, void 0);
90
- __privateAdd(this, _listeners, /* @__PURE__ */ new Set());
91
- __privateAdd(this, _files, []);
92
- __privateAdd(this, _selectedFile, void 0);
93
- __publicField(this, "setSelectedFile", (path) => {
94
- const prev = __privateGet(this, _selectedFile);
95
- const next = __privateGet(this, _files).find((file) => file.path === path);
96
- if (prev !== next) {
97
- __privateSet(this, _selectedFile, next);
98
- __privateGet(this, _signalUpdate2).call(this);
99
- }
100
- });
101
- __privateAdd(this, _signalUpdate2, () => {
102
- __privateGet(this, _listeners).forEach((listener) => listener());
103
- });
104
- __privateSet(this, _access2, access);
63
+ this.#access = access;
105
64
  }
106
65
  get files() {
107
- return __privateGet(this, _files);
66
+ return this.#files;
108
67
  }
109
68
  get selectedFile() {
110
- return __privateGet(this, _selectedFile);
111
- }
69
+ return this.#selectedFile;
70
+ }
71
+ setSelectedFile = (path) => {
72
+ const prev = this.#selectedFile;
73
+ const next = this.#files.find((file) => file.path === path);
74
+ if (prev !== next) {
75
+ this.#selectedFile = next;
76
+ this.#signalUpdate();
77
+ }
78
+ };
112
79
  get dirty() {
113
- return __privateGet(this, _files).some((file) => file.dirty);
80
+ return this.#files.some((file) => file.dirty);
114
81
  }
115
82
  async save() {
116
- await Promise.all(__privateGet(this, _files).map((file) => file.save()));
83
+ await Promise.all(this.#files.map((file) => file.save()));
117
84
  }
118
85
  async reload() {
119
- var _a;
120
- const selectedPath = (_a = __privateGet(this, _selectedFile)) == null ? void 0 : _a.path;
121
- const files = await __privateGet(this, _access2).listFiles();
86
+ const selectedPath = this.#selectedFile?.path;
87
+ const files = await this.#access.listFiles();
122
88
  const fileManagers = await Promise.all(
123
89
  files.map(async (file) => {
124
90
  const manager = new DirectoryEditorFileManager(
125
91
  file,
126
- __privateGet(this, _signalUpdate2)
92
+ this.#signalUpdate
127
93
  );
128
94
  await manager.reload();
129
95
  return manager;
130
96
  })
131
97
  );
132
- __privateGet(this, _files).length = 0;
133
- __privateGet(this, _files).push(...fileManagers);
98
+ this.#files.length = 0;
99
+ this.#files.push(...fileManagers);
134
100
  this.setSelectedFile(selectedPath);
135
- __privateGet(this, _signalUpdate2).call(this);
101
+ this.#signalUpdate();
136
102
  }
137
103
  subscribe(listener) {
138
- __privateGet(this, _listeners).add(listener);
104
+ this.#listeners.add(listener);
139
105
  return () => {
140
- __privateGet(this, _listeners).delete(listener);
106
+ this.#listeners.delete(listener);
141
107
  };
142
108
  }
109
+ #signalUpdate = () => {
110
+ this.#listeners.forEach((listener) => listener());
111
+ };
143
112
  }
144
- _access2 = new WeakMap();
145
- _listeners = new WeakMap();
146
- _files = new WeakMap();
147
- _selectedFile = new WeakMap();
148
- _signalUpdate2 = new WeakMap();
149
113
  const DirectoryEditorContext = createContext(
150
114
  void 0
151
115
  );
152
116
  function useDirectoryEditor() {
153
117
  const value = useContext(DirectoryEditorContext);
154
118
  const rerender = useRerender();
155
- useEffect(() => value == null ? void 0 : value.subscribe(rerender), [value, rerender]);
119
+ useEffect(() => value?.subscribe(rerender), [value, rerender]);
156
120
  if (!value) {
157
121
  throw new Error("must be used within a DirectoryEditorProvider");
158
122
  }
@@ -1 +1 @@
1
- {"version":3,"file":"DirectoryEditorContext.esm.js","sources":["../../../src/next/TemplateEditorPage/DirectoryEditorContext.tsx"],"sourcesContent":["/*\n * Copyright 2022 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { ErrorPanel, Progress } from '@backstage/core-components';\nimport { useAsync, useRerender } from '@react-hookz/web';\nimport React, { createContext, ReactNode, useContext, useEffect } from 'react';\nimport {\n TemplateDirectoryAccess,\n TemplateFileAccess,\n} from '../../lib/filesystem';\n\nconst MAX_SIZE = 1024 * 1024;\nconst MAX_SIZE_MESSAGE = 'This file is too large to be displayed';\n\ninterface DirectoryEditorFile {\n /** The path of the file relative to the root directory */\n path: string;\n /** The staged content of the file */\n content: string;\n /** Whether the staged content matches what is on disk */\n dirty: boolean;\n\n /** Update the staged content of the file without saving */\n updateContent(content: string): void;\n /** Save the staged content of the file to disk */\n save(): Promise<void>;\n /** Reload the staged content of the file from disk */\n reload(): Promise<void>;\n}\n\ninterface DirectoryEditor {\n /** A list of all files in the edited directory */\n files: Array<DirectoryEditorFile>;\n\n /** The currently selected file */\n selectedFile: DirectoryEditorFile | undefined;\n /** Switch the selected file */\n setSelectedFile(path: string | undefined): void;\n\n /** Save all files to disk */\n save(): Promise<void>;\n /** Reload all files from disk */\n reload(): Promise<void>;\n\n subscribe(listener: () => void): () => void;\n}\n\nclass DirectoryEditorFileManager implements DirectoryEditorFile {\n readonly #access: TemplateFileAccess;\n readonly #signalUpdate: () => void;\n\n #content?: string;\n #savedContent?: string;\n\n constructor(access: TemplateFileAccess, signalUpdate: () => void) {\n this.#access = access;\n this.#signalUpdate = signalUpdate;\n }\n\n get path() {\n return this.#access.path;\n }\n\n get content() {\n return this.#content ?? MAX_SIZE_MESSAGE;\n }\n\n updateContent(content: string): void {\n if (this.#content === undefined) {\n return;\n }\n this.#content = content;\n this.#signalUpdate();\n }\n\n get dirty() {\n return this.#content !== this.#savedContent;\n }\n\n async save(): Promise<void> {\n if (this.#content !== undefined) {\n await this.#access.save(this.#content);\n this.#savedContent = this.#content;\n this.#signalUpdate();\n }\n }\n\n async reload(): Promise<void> {\n const file = await this.#access.file();\n if (file.size > MAX_SIZE) {\n if (this.#content !== undefined) {\n this.#content = undefined;\n this.#savedContent = undefined;\n this.#signalUpdate();\n }\n return;\n }\n\n const content = await file.text();\n if (this.#content !== content) {\n this.#content = content;\n this.#savedContent = content;\n this.#signalUpdate();\n }\n }\n}\n\nclass DirectoryEditorManager implements DirectoryEditor {\n readonly #access: TemplateDirectoryAccess;\n readonly #listeners = new Set<() => void>();\n\n #files: DirectoryEditorFile[] = [];\n #selectedFile: DirectoryEditorFile | undefined;\n\n constructor(access: TemplateDirectoryAccess) {\n this.#access = access;\n }\n\n get files() {\n return this.#files;\n }\n\n get selectedFile() {\n return this.#selectedFile;\n }\n\n setSelectedFile = (path: string | undefined): void => {\n const prev = this.#selectedFile;\n const next = this.#files.find(file => file.path === path);\n if (prev !== next) {\n this.#selectedFile = next;\n this.#signalUpdate();\n }\n };\n\n get dirty() {\n return this.#files.some(file => file.dirty);\n }\n\n async save(): Promise<void> {\n await Promise.all(this.#files.map(file => file.save()));\n }\n\n async reload(): Promise<void> {\n const selectedPath = this.#selectedFile?.path;\n\n const files = await this.#access.listFiles();\n const fileManagers = await Promise.all(\n files.map(async file => {\n const manager = new DirectoryEditorFileManager(\n file,\n this.#signalUpdate,\n );\n await manager.reload();\n return manager;\n }),\n );\n this.#files.length = 0;\n this.#files.push(...fileManagers);\n\n this.setSelectedFile(selectedPath);\n this.#signalUpdate();\n }\n\n subscribe(listener: () => void): () => void {\n this.#listeners.add(listener);\n return () => {\n this.#listeners.delete(listener);\n };\n }\n\n #signalUpdate = () => {\n this.#listeners.forEach(listener => listener());\n };\n}\n\nconst DirectoryEditorContext = createContext<DirectoryEditor | undefined>(\n undefined,\n);\n\nexport function useDirectoryEditor(): DirectoryEditor {\n const value = useContext(DirectoryEditorContext);\n const rerender = useRerender();\n\n useEffect(() => value?.subscribe(rerender), [value, rerender]);\n\n if (!value) {\n throw new Error('must be used within a DirectoryEditorProvider');\n }\n return value;\n}\n\ninterface DirectoryEditorProviderProps {\n directory: TemplateDirectoryAccess;\n children?: ReactNode;\n}\n\nexport function DirectoryEditorProvider(props: DirectoryEditorProviderProps) {\n const { directory } = props;\n\n const [{ result, error }, { execute }] = useAsync(\n async (dir: TemplateDirectoryAccess) => {\n const manager = new DirectoryEditorManager(dir);\n await manager.reload();\n\n const firstYaml = manager.files.find(file => file.path.match(/\\.ya?ml$/));\n if (firstYaml) {\n manager.setSelectedFile(firstYaml.path);\n }\n\n return manager;\n },\n );\n\n useEffect(() => {\n execute(directory);\n }, [execute, directory]);\n\n if (error) {\n return <ErrorPanel error={error} />;\n } else if (!result) {\n return <Progress />;\n }\n\n return (\n <DirectoryEditorContext.Provider value={result}>\n {props.children}\n </DirectoryEditorContext.Provider>\n );\n}\n"],"names":["_access","_signalUpdate"],"mappings":"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"}
1
+ {"version":3,"file":"DirectoryEditorContext.esm.js","sources":["../../../src/next/TemplateEditorPage/DirectoryEditorContext.tsx"],"sourcesContent":["/*\n * Copyright 2022 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { ErrorPanel, Progress } from '@backstage/core-components';\nimport { useAsync, useRerender } from '@react-hookz/web';\nimport React, { createContext, ReactNode, useContext, useEffect } from 'react';\nimport {\n TemplateDirectoryAccess,\n TemplateFileAccess,\n} from '../../lib/filesystem';\n\nconst MAX_SIZE = 1024 * 1024;\nconst MAX_SIZE_MESSAGE = 'This file is too large to be displayed';\n\ninterface DirectoryEditorFile {\n /** The path of the file relative to the root directory */\n path: string;\n /** The staged content of the file */\n content: string;\n /** Whether the staged content matches what is on disk */\n dirty: boolean;\n\n /** Update the staged content of the file without saving */\n updateContent(content: string): void;\n /** Save the staged content of the file to disk */\n save(): Promise<void>;\n /** Reload the staged content of the file from disk */\n reload(): Promise<void>;\n}\n\ninterface DirectoryEditor {\n /** A list of all files in the edited directory */\n files: Array<DirectoryEditorFile>;\n\n /** The currently selected file */\n selectedFile: DirectoryEditorFile | undefined;\n /** Switch the selected file */\n setSelectedFile(path: string | undefined): void;\n\n /** Save all files to disk */\n save(): Promise<void>;\n /** Reload all files from disk */\n reload(): Promise<void>;\n\n subscribe(listener: () => void): () => void;\n}\n\nclass DirectoryEditorFileManager implements DirectoryEditorFile {\n readonly #access: TemplateFileAccess;\n readonly #signalUpdate: () => void;\n\n #content?: string;\n #savedContent?: string;\n\n constructor(access: TemplateFileAccess, signalUpdate: () => void) {\n this.#access = access;\n this.#signalUpdate = signalUpdate;\n }\n\n get path() {\n return this.#access.path;\n }\n\n get content() {\n return this.#content ?? MAX_SIZE_MESSAGE;\n }\n\n updateContent(content: string): void {\n if (this.#content === undefined) {\n return;\n }\n this.#content = content;\n this.#signalUpdate();\n }\n\n get dirty() {\n return this.#content !== this.#savedContent;\n }\n\n async save(): Promise<void> {\n if (this.#content !== undefined) {\n await this.#access.save(this.#content);\n this.#savedContent = this.#content;\n this.#signalUpdate();\n }\n }\n\n async reload(): Promise<void> {\n const file = await this.#access.file();\n if (file.size > MAX_SIZE) {\n if (this.#content !== undefined) {\n this.#content = undefined;\n this.#savedContent = undefined;\n this.#signalUpdate();\n }\n return;\n }\n\n const content = await file.text();\n if (this.#content !== content) {\n this.#content = content;\n this.#savedContent = content;\n this.#signalUpdate();\n }\n }\n}\n\nclass DirectoryEditorManager implements DirectoryEditor {\n readonly #access: TemplateDirectoryAccess;\n readonly #listeners = new Set<() => void>();\n\n #files: DirectoryEditorFile[] = [];\n #selectedFile: DirectoryEditorFile | undefined;\n\n constructor(access: TemplateDirectoryAccess) {\n this.#access = access;\n }\n\n get files() {\n return this.#files;\n }\n\n get selectedFile() {\n return this.#selectedFile;\n }\n\n setSelectedFile = (path: string | undefined): void => {\n const prev = this.#selectedFile;\n const next = this.#files.find(file => file.path === path);\n if (prev !== next) {\n this.#selectedFile = next;\n this.#signalUpdate();\n }\n };\n\n get dirty() {\n return this.#files.some(file => file.dirty);\n }\n\n async save(): Promise<void> {\n await Promise.all(this.#files.map(file => file.save()));\n }\n\n async reload(): Promise<void> {\n const selectedPath = this.#selectedFile?.path;\n\n const files = await this.#access.listFiles();\n const fileManagers = await Promise.all(\n files.map(async file => {\n const manager = new DirectoryEditorFileManager(\n file,\n this.#signalUpdate,\n );\n await manager.reload();\n return manager;\n }),\n );\n this.#files.length = 0;\n this.#files.push(...fileManagers);\n\n this.setSelectedFile(selectedPath);\n this.#signalUpdate();\n }\n\n subscribe(listener: () => void): () => void {\n this.#listeners.add(listener);\n return () => {\n this.#listeners.delete(listener);\n };\n }\n\n #signalUpdate = () => {\n this.#listeners.forEach(listener => listener());\n };\n}\n\nconst DirectoryEditorContext = createContext<DirectoryEditor | undefined>(\n undefined,\n);\n\nexport function useDirectoryEditor(): DirectoryEditor {\n const value = useContext(DirectoryEditorContext);\n const rerender = useRerender();\n\n useEffect(() => value?.subscribe(rerender), [value, rerender]);\n\n if (!value) {\n throw new Error('must be used within a DirectoryEditorProvider');\n }\n return value;\n}\n\ninterface DirectoryEditorProviderProps {\n directory: TemplateDirectoryAccess;\n children?: ReactNode;\n}\n\nexport function DirectoryEditorProvider(props: DirectoryEditorProviderProps) {\n const { directory } = props;\n\n const [{ result, error }, { execute }] = useAsync(\n async (dir: TemplateDirectoryAccess) => {\n const manager = new DirectoryEditorManager(dir);\n await manager.reload();\n\n const firstYaml = manager.files.find(file => file.path.match(/\\.ya?ml$/));\n if (firstYaml) {\n manager.setSelectedFile(firstYaml.path);\n }\n\n return manager;\n },\n );\n\n useEffect(() => {\n execute(directory);\n }, [execute, directory]);\n\n if (error) {\n return <ErrorPanel error={error} />;\n } else if (!result) {\n return <Progress />;\n }\n\n return (\n <DirectoryEditorContext.Provider value={result}>\n {props.children}\n </DirectoryEditorContext.Provider>\n );\n}\n"],"names":[],"mappings":"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"}
@@ -45,7 +45,6 @@ function DryRunProvider(props) {
45
45
  }, []);
46
46
  const deleteResult = useCallback((id) => {
47
47
  setState((prevState) => {
48
- var _a;
49
48
  const index = prevState.results.findIndex((r) => r.id === id);
50
49
  if (index === -1) {
51
50
  return prevState;
@@ -54,7 +53,7 @@ function DryRunProvider(props) {
54
53
  const [deleted] = newResults.splice(index, 1);
55
54
  return {
56
55
  results: newResults,
57
- selectedResult: ((_a = prevState.selectedResult) == null ? void 0 : _a.id) === deleted.id ? newResults[0] : prevState.selectedResult
56
+ selectedResult: prevState.selectedResult?.id === deleted.id ? newResults[0] : prevState.selectedResult
58
57
  };
59
58
  });
60
59
  }, []);
@@ -77,13 +76,10 @@ function DryRunProvider(props) {
77
76
  ...response,
78
77
  id: idRef.current++
79
78
  };
80
- setState((prevState) => {
81
- var _a;
82
- return {
83
- results: [...prevState.results, result],
84
- selectedResult: (_a = prevState.selectedResult) != null ? _a : result
85
- };
86
- });
79
+ setState((prevState) => ({
80
+ results: [...prevState.results, result],
81
+ selectedResult: prevState.selectedResult ?? result
82
+ }));
87
83
  },
88
84
  [scaffolderApi]
89
85
  );
@@ -1 +1 @@
1
- {"version":3,"file":"DryRunContext.esm.js","sources":["../../../src/next/TemplateEditorPage/DryRunContext.tsx"],"sourcesContent":["/*\n * Copyright 2022 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport yaml from 'yaml';\nimport { useApi } from '@backstage/core-plugin-api';\nimport { JsonObject } from '@backstage/types';\nimport React, {\n createContext,\n ReactNode,\n useCallback,\n useContext,\n useMemo,\n useRef,\n useState,\n} from 'react';\nimport {\n scaffolderApiRef,\n ScaffolderDryRunResponse,\n} from '@backstage/plugin-scaffolder-react';\n\nconst MAX_CONTENT_SIZE = 64 * 1024;\nconst CHUNK_SIZE = 32 * 1024;\n\ninterface DryRunOptions {\n templateContent: string;\n values: JsonObject;\n files: Array<{ path: string; content: string }>;\n}\n\nexport interface DryRunResult extends ScaffolderDryRunResponse {\n id: number;\n}\n\ninterface DryRun {\n results: DryRunResult[];\n selectedResult: DryRunResult | undefined;\n\n selectResult(id: number): void;\n deleteResult(id: number): void;\n execute(options: DryRunOptions): Promise<void>;\n}\n\nconst DryRunContext = createContext<DryRun | undefined>(undefined);\n\ninterface DryRunProviderProps {\n children: ReactNode;\n}\n\nexport function base64EncodeContent(content: string): string {\n if (content.length > MAX_CONTENT_SIZE) {\n return window.btoa('<file too large>');\n }\n\n try {\n return window.btoa(content);\n } catch {\n const decoder = new TextEncoder();\n const buffer = decoder.encode(content);\n\n const chunks = new Array<string>();\n for (let offset = 0; offset < buffer.length; offset += CHUNK_SIZE) {\n chunks.push(\n String.fromCharCode(...buffer.slice(offset, offset + CHUNK_SIZE)),\n );\n }\n return window.btoa(chunks.join(''));\n }\n}\n\nexport function DryRunProvider(props: DryRunProviderProps) {\n const scaffolderApi = useApi(scaffolderApiRef);\n\n const [state, setState] = useState<\n Pick<DryRun, 'results' | 'selectedResult'>\n >({\n results: [],\n selectedResult: undefined,\n });\n const idRef = useRef(1);\n\n const selectResult = useCallback((id: number) => {\n setState(prevState => {\n const result = prevState.results.find(r => r.id === id);\n if (result === prevState.selectedResult) {\n return prevState;\n }\n return {\n results: prevState.results,\n selectedResult: result,\n };\n });\n }, []);\n\n const deleteResult = useCallback((id: number) => {\n setState(prevState => {\n const index = prevState.results.findIndex(r => r.id === id);\n if (index === -1) {\n return prevState;\n }\n const newResults = prevState.results.slice();\n const [deleted] = newResults.splice(index, 1);\n return {\n results: newResults,\n selectedResult:\n prevState.selectedResult?.id === deleted.id\n ? newResults[0]\n : prevState.selectedResult,\n };\n });\n }, []);\n\n const execute = useCallback(\n async (options: DryRunOptions) => {\n if (!scaffolderApi.dryRun) {\n throw new Error('Scaffolder API does not support dry-run');\n }\n\n const parsed = yaml.parse(options.templateContent);\n\n const response = await scaffolderApi.dryRun({\n template: parsed,\n values: options.values,\n secrets: {},\n directoryContents: options.files.map(file => ({\n path: file.path,\n base64Content: base64EncodeContent(file.content),\n })),\n });\n\n const result = {\n ...response,\n id: idRef.current++,\n };\n\n setState(prevState => ({\n results: [...prevState.results, result],\n selectedResult: prevState.selectedResult ?? result,\n }));\n },\n [scaffolderApi],\n );\n\n const dryRun = useMemo(\n () => ({\n ...state,\n selectResult,\n deleteResult,\n execute,\n }),\n [state, selectResult, deleteResult, execute],\n );\n\n return (\n <DryRunContext.Provider value={dryRun}>\n {props.children}\n </DryRunContext.Provider>\n );\n}\n\nexport function useDryRun(): DryRun {\n const value = useContext(DryRunContext);\n if (!value) {\n throw new Error('must be used within a DryRunProvider');\n }\n return value;\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"DryRunContext.esm.js","sources":["../../../src/next/TemplateEditorPage/DryRunContext.tsx"],"sourcesContent":["/*\n * Copyright 2022 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport yaml from 'yaml';\nimport { useApi } from '@backstage/core-plugin-api';\nimport { JsonObject } from '@backstage/types';\nimport React, {\n createContext,\n ReactNode,\n useCallback,\n useContext,\n useMemo,\n useRef,\n useState,\n} from 'react';\nimport {\n scaffolderApiRef,\n ScaffolderDryRunResponse,\n} from '@backstage/plugin-scaffolder-react';\n\nconst MAX_CONTENT_SIZE = 64 * 1024;\nconst CHUNK_SIZE = 32 * 1024;\n\ninterface DryRunOptions {\n templateContent: string;\n values: JsonObject;\n files: Array<{ path: string; content: string }>;\n}\n\nexport interface DryRunResult extends ScaffolderDryRunResponse {\n id: number;\n}\n\ninterface DryRun {\n results: DryRunResult[];\n selectedResult: DryRunResult | undefined;\n\n selectResult(id: number): void;\n deleteResult(id: number): void;\n execute(options: DryRunOptions): Promise<void>;\n}\n\nconst DryRunContext = createContext<DryRun | undefined>(undefined);\n\ninterface DryRunProviderProps {\n children: ReactNode;\n}\n\nexport function base64EncodeContent(content: string): string {\n if (content.length > MAX_CONTENT_SIZE) {\n return window.btoa('<file too large>');\n }\n\n try {\n return window.btoa(content);\n } catch {\n const decoder = new TextEncoder();\n const buffer = decoder.encode(content);\n\n const chunks = new Array<string>();\n for (let offset = 0; offset < buffer.length; offset += CHUNK_SIZE) {\n chunks.push(\n String.fromCharCode(...buffer.slice(offset, offset + CHUNK_SIZE)),\n );\n }\n return window.btoa(chunks.join(''));\n }\n}\n\nexport function DryRunProvider(props: DryRunProviderProps) {\n const scaffolderApi = useApi(scaffolderApiRef);\n\n const [state, setState] = useState<\n Pick<DryRun, 'results' | 'selectedResult'>\n >({\n results: [],\n selectedResult: undefined,\n });\n const idRef = useRef(1);\n\n const selectResult = useCallback((id: number) => {\n setState(prevState => {\n const result = prevState.results.find(r => r.id === id);\n if (result === prevState.selectedResult) {\n return prevState;\n }\n return {\n results: prevState.results,\n selectedResult: result,\n };\n });\n }, []);\n\n const deleteResult = useCallback((id: number) => {\n setState(prevState => {\n const index = prevState.results.findIndex(r => r.id === id);\n if (index === -1) {\n return prevState;\n }\n const newResults = prevState.results.slice();\n const [deleted] = newResults.splice(index, 1);\n return {\n results: newResults,\n selectedResult:\n prevState.selectedResult?.id === deleted.id\n ? newResults[0]\n : prevState.selectedResult,\n };\n });\n }, []);\n\n const execute = useCallback(\n async (options: DryRunOptions) => {\n if (!scaffolderApi.dryRun) {\n throw new Error('Scaffolder API does not support dry-run');\n }\n\n const parsed = yaml.parse(options.templateContent);\n\n const response = await scaffolderApi.dryRun({\n template: parsed,\n values: options.values,\n secrets: {},\n directoryContents: options.files.map(file => ({\n path: file.path,\n base64Content: base64EncodeContent(file.content),\n })),\n });\n\n const result = {\n ...response,\n id: idRef.current++,\n };\n\n setState(prevState => ({\n results: [...prevState.results, result],\n selectedResult: prevState.selectedResult ?? result,\n }));\n },\n [scaffolderApi],\n );\n\n const dryRun = useMemo(\n () => ({\n ...state,\n selectResult,\n deleteResult,\n execute,\n }),\n [state, selectResult, deleteResult, execute],\n );\n\n return (\n <DryRunContext.Provider value={dryRun}>\n {props.children}\n </DryRunContext.Provider>\n );\n}\n\nexport function useDryRun(): DryRun {\n const value = useContext(DryRunContext);\n if (!value) {\n throw new Error('must be used within a DryRunProvider');\n }\n return value;\n}\n"],"names":[],"mappings":"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"}
@@ -33,7 +33,6 @@ function DryRunResultsList() {
33
33
  const classes = useStyles();
34
34
  const dryRun = useDryRun();
35
35
  return /* @__PURE__ */ React.createElement(List, { className: classes.root, dense: true }, dryRun.results.map((result) => {
36
- var _a;
37
36
  const failed = result.log.some((l) => l.body.status === "failed");
38
37
  let isLoading = false;
39
38
  async function downloadResult() {
@@ -49,7 +48,7 @@ function DryRunResultsList() {
49
48
  {
50
49
  button: true,
51
50
  key: result.id,
52
- selected: ((_a = dryRun.selectedResult) == null ? void 0 : _a.id) === result.id,
51
+ selected: dryRun.selectedResult?.id === result.id,
53
52
  onClick: () => dryRun.selectResult(result.id)
54
53
  },
55
54
  /* @__PURE__ */ React.createElement(
@@ -1 +1 @@
1
- {"version":3,"file":"DryRunResultsList.esm.js","sources":["../../../../src/next/TemplateEditorPage/DryRunResults/DryRunResultsList.tsx"],"sourcesContent":["/*\n * Copyright 2022 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport IconButton from '@material-ui/core/IconButton';\nimport List from '@material-ui/core/List';\nimport ListItem from '@material-ui/core/ListItem';\nimport ListItemIcon from '@material-ui/core/ListItemIcon';\nimport ListItemSecondaryAction from '@material-ui/core/ListItemSecondaryAction';\nimport ListItemText from '@material-ui/core/ListItemText';\nimport { makeStyles } from '@material-ui/core/styles';\nimport CancelIcon from '@material-ui/icons/Cancel';\nimport CheckIcon from '@material-ui/icons/Check';\nimport DeleteIcon from '@material-ui/icons/Delete';\nimport DownloadIcon from '@material-ui/icons/GetApp';\nimport React from 'react';\nimport { useDryRun } from '../DryRunContext';\nimport { downloadBlob } from '../../../lib/download';\n\nconst useStyles = makeStyles(theme => ({\n root: {\n overflowY: 'auto',\n background: theme.palette.background.default,\n },\n iconSuccess: {\n minWidth: 0,\n marginRight: theme.spacing(1),\n color: theme.palette.status.ok,\n },\n iconFailure: {\n minWidth: 0,\n marginRight: theme.spacing(1),\n color: theme.palette.status.error,\n },\n}));\n\nexport function DryRunResultsList() {\n const classes = useStyles();\n const dryRun = useDryRun();\n\n return (\n <List className={classes.root} dense>\n {dryRun.results.map(result => {\n const failed = result.log.some(l => l.body.status === 'failed');\n let isLoading = false;\n\n async function downloadResult() {\n isLoading = true;\n await downloadDirectoryContents(\n result.directoryContents,\n `dry-run-result-${result.id}.zip`,\n );\n isLoading = false;\n }\n\n return (\n <ListItem\n button\n key={result.id}\n selected={dryRun.selectedResult?.id === result.id}\n onClick={() => dryRun.selectResult(result.id)}\n >\n <ListItemIcon\n className={failed ? classes.iconFailure : classes.iconSuccess}\n >\n {failed ? <CancelIcon /> : <CheckIcon />}\n </ListItemIcon>\n <ListItemText primary={`Result ${result.id}`} />\n <ListItemSecondaryAction>\n <IconButton\n edge=\"end\"\n aria-label=\"download\"\n title=\"Download as .zip\"\n disabled={isLoading}\n onClick={() => downloadResult()}\n >\n <DownloadIcon />\n </IconButton>\n <IconButton\n edge=\"end\"\n aria-label=\"delete\"\n title=\"Delete result\"\n onClick={() => dryRun.deleteResult(result.id)}\n >\n <DeleteIcon />\n </IconButton>\n </ListItemSecondaryAction>\n </ListItem>\n );\n })}\n </List>\n );\n}\n\nasync function downloadDirectoryContents(\n directoryContents: {\n path: string;\n base64Content: string;\n executable: boolean;\n }[],\n name: string,\n) {\n const { default: JSZip } = await import('jszip');\n const zip = new JSZip();\n\n for (const d of directoryContents) {\n // Decode text content from base64 to ascii\n const converted = atob(d.base64Content);\n\n // add folder/file to zip\n await zip.file(d.path, converted);\n }\n\n const blob = await zip.generateAsync({ type: 'blob' });\n downloadBlob(blob, name);\n}\n"],"names":["CancelIcon"],"mappings":"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"}
1
+ {"version":3,"file":"DryRunResultsList.esm.js","sources":["../../../../src/next/TemplateEditorPage/DryRunResults/DryRunResultsList.tsx"],"sourcesContent":["/*\n * Copyright 2022 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport IconButton from '@material-ui/core/IconButton';\nimport List from '@material-ui/core/List';\nimport ListItem from '@material-ui/core/ListItem';\nimport ListItemIcon from '@material-ui/core/ListItemIcon';\nimport ListItemSecondaryAction from '@material-ui/core/ListItemSecondaryAction';\nimport ListItemText from '@material-ui/core/ListItemText';\nimport { makeStyles } from '@material-ui/core/styles';\nimport CancelIcon from '@material-ui/icons/Cancel';\nimport CheckIcon from '@material-ui/icons/Check';\nimport DeleteIcon from '@material-ui/icons/Delete';\nimport DownloadIcon from '@material-ui/icons/GetApp';\nimport React from 'react';\nimport { useDryRun } from '../DryRunContext';\nimport { downloadBlob } from '../../../lib/download';\n\nconst useStyles = makeStyles(theme => ({\n root: {\n overflowY: 'auto',\n background: theme.palette.background.default,\n },\n iconSuccess: {\n minWidth: 0,\n marginRight: theme.spacing(1),\n color: theme.palette.status.ok,\n },\n iconFailure: {\n minWidth: 0,\n marginRight: theme.spacing(1),\n color: theme.palette.status.error,\n },\n}));\n\nexport function DryRunResultsList() {\n const classes = useStyles();\n const dryRun = useDryRun();\n\n return (\n <List className={classes.root} dense>\n {dryRun.results.map(result => {\n const failed = result.log.some(l => l.body.status === 'failed');\n let isLoading = false;\n\n async function downloadResult() {\n isLoading = true;\n await downloadDirectoryContents(\n result.directoryContents,\n `dry-run-result-${result.id}.zip`,\n );\n isLoading = false;\n }\n\n return (\n <ListItem\n button\n key={result.id}\n selected={dryRun.selectedResult?.id === result.id}\n onClick={() => dryRun.selectResult(result.id)}\n >\n <ListItemIcon\n className={failed ? classes.iconFailure : classes.iconSuccess}\n >\n {failed ? <CancelIcon /> : <CheckIcon />}\n </ListItemIcon>\n <ListItemText primary={`Result ${result.id}`} />\n <ListItemSecondaryAction>\n <IconButton\n edge=\"end\"\n aria-label=\"download\"\n title=\"Download as .zip\"\n disabled={isLoading}\n onClick={() => downloadResult()}\n >\n <DownloadIcon />\n </IconButton>\n <IconButton\n edge=\"end\"\n aria-label=\"delete\"\n title=\"Delete result\"\n onClick={() => dryRun.deleteResult(result.id)}\n >\n <DeleteIcon />\n </IconButton>\n </ListItemSecondaryAction>\n </ListItem>\n );\n })}\n </List>\n );\n}\n\nasync function downloadDirectoryContents(\n directoryContents: {\n path: string;\n base64Content: string;\n executable: boolean;\n }[],\n name: string,\n) {\n const { default: JSZip } = await import('jszip');\n const zip = new JSZip();\n\n for (const d of directoryContents) {\n // Decode text content from base64 to ascii\n const converted = atob(d.base64Content);\n\n // add folder/file to zip\n await zip.file(d.path, converted);\n }\n\n const blob = await zip.generateAsync({ type: 'blob' });\n downloadBlob(blob, name);\n}\n"],"names":["CancelIcon"],"mappings":"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"}
@@ -43,7 +43,7 @@ function FilesContent() {
43
43
  const classes = useStyles();
44
44
  const { selectedResult } = useDryRun();
45
45
  const [selectedPath, setSelectedPath] = useState("");
46
- const selectedFile = selectedResult == null ? void 0 : selectedResult.directoryContents.find(
46
+ const selectedFile = selectedResult?.directoryContents.find(
47
47
  (f) => f.path === selectedPath
48
48
  );
49
49
  useEffect(() => {
@@ -75,21 +75,18 @@ function FilesContent() {
75
75
  height: "100%",
76
76
  extensions: [StreamLanguage.define(yaml)],
77
77
  readOnly: true,
78
- value: (selectedFile == null ? void 0 : selectedFile.base64Content) ? atob(selectedFile.base64Content) : ""
78
+ value: selectedFile?.base64Content ? atob(selectedFile.base64Content) : ""
79
79
  }
80
80
  ));
81
81
  }
82
82
  function LogContent() {
83
- var _a, _b;
84
83
  const { selectedResult } = useDryRun();
85
84
  const [currentStepId, setUserSelectedStepId] = useState();
86
85
  const steps = useMemo(() => {
87
- var _a2;
88
86
  if (!selectedResult) {
89
87
  return [];
90
88
  }
91
- return (_a2 = selectedResult.steps.map((step) => {
92
- var _a3, _b2;
89
+ return selectedResult.steps.map((step) => {
93
90
  const stepLog = selectedResult.log.filter(
94
91
  (l) => l.body.stepId === step.id
95
92
  );
@@ -97,14 +94,14 @@ function LogContent() {
97
94
  id: step.id,
98
95
  name: step.name,
99
96
  logString: stepLog.map((l) => l.body.message).join("\n"),
100
- status: (_b2 = (_a3 = stepLog[stepLog.length - 1]) == null ? void 0 : _a3.body.status) != null ? _b2 : "completed"
97
+ status: stepLog[stepLog.length - 1]?.body.status ?? "completed"
101
98
  };
102
- })) != null ? _a2 : [];
99
+ }) ?? [];
103
100
  }, [selectedResult]);
104
101
  if (!selectedResult) {
105
102
  return null;
106
103
  }
107
- const selectedStep = (_a = steps.find((s) => s.id === currentStepId)) != null ? _a : steps[0];
104
+ const selectedStep = steps.find((s) => s.id === currentStepId) ?? steps[0];
108
105
  return /* @__PURE__ */ React.createElement(DryRunResultsSplitView, null, /* @__PURE__ */ React.createElement(
109
106
  TaskStatusStepper,
110
107
  {
@@ -112,16 +109,15 @@ function LogContent() {
112
109
  currentStepId: selectedStep.id,
113
110
  onUserStepChange: setUserSelectedStepId
114
111
  }
115
- ), /* @__PURE__ */ React.createElement(LogViewer, { text: (_b = selectedStep == null ? void 0 : selectedStep.logString) != null ? _b : "" }));
112
+ ), /* @__PURE__ */ React.createElement(LogViewer, { text: selectedStep?.logString ?? "" }));
116
113
  }
117
114
  function OutputContent() {
118
- var _a, _b;
119
115
  const classes = useStyles();
120
116
  const { selectedResult } = useDryRun();
121
117
  if (!selectedResult) {
122
118
  return null;
123
119
  }
124
- return /* @__PURE__ */ React.createElement(DryRunResultsSplitView, null, /* @__PURE__ */ React.createElement(Box, { pt: 2 }, ((_b = (_a = selectedResult.output) == null ? void 0 : _a.links) == null ? void 0 : _b.length) && /* @__PURE__ */ React.createElement(TaskPageLinks, { output: selectedResult.output })), /* @__PURE__ */ React.createElement(
120
+ return /* @__PURE__ */ React.createElement(DryRunResultsSplitView, null, /* @__PURE__ */ React.createElement(Box, { pt: 2 }, selectedResult.output?.links?.length && /* @__PURE__ */ React.createElement(TaskPageLinks, { output: selectedResult.output })), /* @__PURE__ */ React.createElement(
125
121
  CodeMirror,
126
122
  {
127
123
  className: classes.codeMirror,
@@ -1 +1 @@
1
- {"version":3,"file":"DryRunResultsView.esm.js","sources":["../../../../src/next/TemplateEditorPage/DryRunResults/DryRunResultsView.tsx"],"sourcesContent":["/*\n * Copyright 2022 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { LogViewer } from '@backstage/core-components';\nimport { StreamLanguage } from '@codemirror/language';\nimport { yaml as yamlSupport } from '@codemirror/legacy-modes/mode/yaml';\nimport Box from '@material-ui/core/Box';\nimport Divider from '@material-ui/core/Divider';\nimport { makeStyles } from '@material-ui/core/styles';\nimport Tab from '@material-ui/core/Tab';\nimport Tabs from '@material-ui/core/Tabs';\nimport CodeMirror from '@uiw/react-codemirror';\nimport React, { useEffect, useMemo, useState } from 'react';\nimport { useDryRun } from '../DryRunContext';\nimport { DryRunResultsSplitView } from './DryRunResultsSplitView';\nimport { FileBrowser } from '../../../components/FileBrowser';\nimport { TaskPageLinks } from './TaskPageLinks';\nimport { TaskStatusStepper } from './TaskStatusStepper';\n\nconst useStyles = makeStyles({\n root: {\n display: 'flex',\n flexFlow: 'column nowrap',\n },\n contentWrapper: {\n flex: 1,\n position: 'relative',\n },\n content: {\n position: 'absolute',\n top: 0,\n left: 0,\n right: 0,\n bottom: 0,\n\n display: 'flex',\n '& > *': {\n flex: 1,\n },\n },\n codeMirror: {\n height: '100%',\n overflowY: 'auto',\n },\n});\n\nfunction FilesContent() {\n const classes = useStyles();\n const { selectedResult } = useDryRun();\n const [selectedPath, setSelectedPath] = useState<string>('');\n const selectedFile = selectedResult?.directoryContents.find(\n f => f.path === selectedPath,\n );\n\n useEffect(() => {\n if (selectedResult) {\n const [firstFile] = selectedResult.directoryContents;\n if (firstFile) {\n setSelectedPath(firstFile.path);\n } else {\n setSelectedPath('');\n }\n }\n return undefined;\n }, [selectedResult]);\n\n if (!selectedResult) {\n return null;\n }\n return (\n <DryRunResultsSplitView>\n <FileBrowser\n selected={selectedPath}\n onSelect={setSelectedPath}\n filePaths={selectedResult.directoryContents.map(file => file.path)}\n />\n <CodeMirror\n className={classes.codeMirror}\n theme=\"dark\"\n height=\"100%\"\n extensions={[StreamLanguage.define(yamlSupport)]}\n readOnly\n value={\n selectedFile?.base64Content ? atob(selectedFile.base64Content) : ''\n }\n />\n </DryRunResultsSplitView>\n );\n}\nfunction LogContent() {\n const { selectedResult } = useDryRun();\n const [currentStepId, setUserSelectedStepId] = useState<string>();\n\n const steps = useMemo(() => {\n if (!selectedResult) {\n return [];\n }\n return (\n selectedResult.steps.map(step => {\n const stepLog = selectedResult.log.filter(\n l => l.body.stepId === step.id,\n );\n return {\n id: step.id,\n name: step.name,\n logString: stepLog.map(l => l.body.message).join('\\n'),\n status: stepLog[stepLog.length - 1]?.body.status ?? 'completed',\n };\n }) ?? []\n );\n }, [selectedResult]);\n\n if (!selectedResult) {\n return null;\n }\n\n const selectedStep = steps.find(s => s.id === currentStepId) ?? steps[0];\n\n return (\n <DryRunResultsSplitView>\n <TaskStatusStepper\n steps={steps}\n currentStepId={selectedStep.id}\n onUserStepChange={setUserSelectedStepId}\n />\n <LogViewer text={selectedStep?.logString ?? ''} />\n </DryRunResultsSplitView>\n );\n}\n\nfunction OutputContent() {\n const classes = useStyles();\n const { selectedResult } = useDryRun();\n\n if (!selectedResult) {\n return null;\n }\n\n return (\n <DryRunResultsSplitView>\n <Box pt={2}>\n {selectedResult.output?.links?.length && (\n <TaskPageLinks output={selectedResult.output} />\n )}\n </Box>\n <CodeMirror\n className={classes.codeMirror}\n theme=\"dark\"\n height=\"100%\"\n extensions={[StreamLanguage.define(yamlSupport)]}\n readOnly\n value={JSON.stringify(selectedResult.output, null, 2)}\n />\n </DryRunResultsSplitView>\n );\n}\n\nexport function DryRunResultsView() {\n const classes = useStyles();\n const [selectedTab, setSelectedTab] = useState<'files' | 'log' | 'output'>(\n 'files',\n );\n\n return (\n <div className={classes.root}>\n <Tabs value={selectedTab} onChange={(_, v) => setSelectedTab(v)}>\n <Tab value=\"files\" label=\"Files\" />\n <Tab value=\"log\" label=\"Log\" />\n <Tab value=\"output\" label=\"Output\" />\n </Tabs>\n <Divider />\n\n <div className={classes.contentWrapper}>\n <div className={classes.content}>\n {selectedTab === 'files' && <FilesContent />}\n {selectedTab === 'log' && <LogContent />}\n {selectedTab === 'output' && <OutputContent />}\n </div>\n </div>\n </div>\n );\n}\n"],"names":["yamlSupport","_a","_b"],"mappings":"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"}
1
+ {"version":3,"file":"DryRunResultsView.esm.js","sources":["../../../../src/next/TemplateEditorPage/DryRunResults/DryRunResultsView.tsx"],"sourcesContent":["/*\n * Copyright 2022 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { LogViewer } from '@backstage/core-components';\nimport { StreamLanguage } from '@codemirror/language';\nimport { yaml as yamlSupport } from '@codemirror/legacy-modes/mode/yaml';\nimport Box from '@material-ui/core/Box';\nimport Divider from '@material-ui/core/Divider';\nimport { makeStyles } from '@material-ui/core/styles';\nimport Tab from '@material-ui/core/Tab';\nimport Tabs from '@material-ui/core/Tabs';\nimport CodeMirror from '@uiw/react-codemirror';\nimport React, { useEffect, useMemo, useState } from 'react';\nimport { useDryRun } from '../DryRunContext';\nimport { DryRunResultsSplitView } from './DryRunResultsSplitView';\nimport { FileBrowser } from '../../../components/FileBrowser';\nimport { TaskPageLinks } from './TaskPageLinks';\nimport { TaskStatusStepper } from './TaskStatusStepper';\n\nconst useStyles = makeStyles({\n root: {\n display: 'flex',\n flexFlow: 'column nowrap',\n },\n contentWrapper: {\n flex: 1,\n position: 'relative',\n },\n content: {\n position: 'absolute',\n top: 0,\n left: 0,\n right: 0,\n bottom: 0,\n\n display: 'flex',\n '& > *': {\n flex: 1,\n },\n },\n codeMirror: {\n height: '100%',\n overflowY: 'auto',\n },\n});\n\nfunction FilesContent() {\n const classes = useStyles();\n const { selectedResult } = useDryRun();\n const [selectedPath, setSelectedPath] = useState<string>('');\n const selectedFile = selectedResult?.directoryContents.find(\n f => f.path === selectedPath,\n );\n\n useEffect(() => {\n if (selectedResult) {\n const [firstFile] = selectedResult.directoryContents;\n if (firstFile) {\n setSelectedPath(firstFile.path);\n } else {\n setSelectedPath('');\n }\n }\n return undefined;\n }, [selectedResult]);\n\n if (!selectedResult) {\n return null;\n }\n return (\n <DryRunResultsSplitView>\n <FileBrowser\n selected={selectedPath}\n onSelect={setSelectedPath}\n filePaths={selectedResult.directoryContents.map(file => file.path)}\n />\n <CodeMirror\n className={classes.codeMirror}\n theme=\"dark\"\n height=\"100%\"\n extensions={[StreamLanguage.define(yamlSupport)]}\n readOnly\n value={\n selectedFile?.base64Content ? atob(selectedFile.base64Content) : ''\n }\n />\n </DryRunResultsSplitView>\n );\n}\nfunction LogContent() {\n const { selectedResult } = useDryRun();\n const [currentStepId, setUserSelectedStepId] = useState<string>();\n\n const steps = useMemo(() => {\n if (!selectedResult) {\n return [];\n }\n return (\n selectedResult.steps.map(step => {\n const stepLog = selectedResult.log.filter(\n l => l.body.stepId === step.id,\n );\n return {\n id: step.id,\n name: step.name,\n logString: stepLog.map(l => l.body.message).join('\\n'),\n status: stepLog[stepLog.length - 1]?.body.status ?? 'completed',\n };\n }) ?? []\n );\n }, [selectedResult]);\n\n if (!selectedResult) {\n return null;\n }\n\n const selectedStep = steps.find(s => s.id === currentStepId) ?? steps[0];\n\n return (\n <DryRunResultsSplitView>\n <TaskStatusStepper\n steps={steps}\n currentStepId={selectedStep.id}\n onUserStepChange={setUserSelectedStepId}\n />\n <LogViewer text={selectedStep?.logString ?? ''} />\n </DryRunResultsSplitView>\n );\n}\n\nfunction OutputContent() {\n const classes = useStyles();\n const { selectedResult } = useDryRun();\n\n if (!selectedResult) {\n return null;\n }\n\n return (\n <DryRunResultsSplitView>\n <Box pt={2}>\n {selectedResult.output?.links?.length && (\n <TaskPageLinks output={selectedResult.output} />\n )}\n </Box>\n <CodeMirror\n className={classes.codeMirror}\n theme=\"dark\"\n height=\"100%\"\n extensions={[StreamLanguage.define(yamlSupport)]}\n readOnly\n value={JSON.stringify(selectedResult.output, null, 2)}\n />\n </DryRunResultsSplitView>\n );\n}\n\nexport function DryRunResultsView() {\n const classes = useStyles();\n const [selectedTab, setSelectedTab] = useState<'files' | 'log' | 'output'>(\n 'files',\n );\n\n return (\n <div className={classes.root}>\n <Tabs value={selectedTab} onChange={(_, v) => setSelectedTab(v)}>\n <Tab value=\"files\" label=\"Files\" />\n <Tab value=\"log\" label=\"Log\" />\n <Tab value=\"output\" label=\"Output\" />\n </Tabs>\n <Divider />\n\n <div className={classes.contentWrapper}>\n <div className={classes.content}>\n {selectedTab === 'files' && <FilesContent />}\n {selectedTab === 'log' && <LogContent />}\n {selectedTab === 'output' && <OutputContent />}\n </div>\n </div>\n </div>\n );\n}\n"],"names":["yamlSupport"],"mappings":"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"}
@@ -10,10 +10,7 @@ const TaskPageLinks = ({ output }) => {
10
10
  const { links = [] } = output;
11
11
  const app = useApp();
12
12
  const entityRoute = useRouteRef(entityRouteRef);
13
- const iconResolver = (key) => {
14
- var _a;
15
- return key ? (_a = app.getSystemIcon(key)) != null ? _a : LanguageIcon : LanguageIcon;
16
- };
13
+ const iconResolver = (key) => key ? app.getSystemIcon(key) ?? LanguageIcon : LanguageIcon;
17
14
  return /* @__PURE__ */ React.createElement(Box, { px: 3, pb: 3 }, links.filter(({ url, entityRef }) => url || entityRef).map(({ url, entityRef, title, icon }) => {
18
15
  if (entityRef) {
19
16
  const entityName = parseEntityRef(entityRef, {
@@ -29,7 +26,7 @@ const TaskPageLinks = ({ output }) => {
29
26
  {
30
27
  key: `output-link-${i}`,
31
28
  href: url,
32
- text: title != null ? title : url,
29
+ text: title ?? url,
33
30
  Icon: iconResolver(icon),
34
31
  target: "_blank"
35
32
  }
@@ -1 +1 @@
1
- {"version":3,"file":"TaskPageLinks.esm.js","sources":["../../../../src/next/TemplateEditorPage/DryRunResults/TaskPageLinks.tsx"],"sourcesContent":["/*\n * Copyright 2021 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { parseEntityRef } from '@backstage/catalog-model';\nimport { entityRouteRef } from '@backstage/plugin-catalog-react';\nimport Box from '@material-ui/core/Box';\nimport LanguageIcon from '@material-ui/icons/Language';\nimport React from 'react';\nimport { ScaffolderTaskOutput } from '@backstage/plugin-scaffolder-react';\nimport { IconLink } from './IconLink';\nimport { IconComponent, useApp, useRouteRef } from '@backstage/core-plugin-api';\n\ntype TaskPageLinksProps = {\n output: ScaffolderTaskOutput;\n};\n\nexport const TaskPageLinks = ({ output }: TaskPageLinksProps) => {\n const { links = [] } = output;\n const app = useApp();\n const entityRoute = useRouteRef(entityRouteRef);\n\n const iconResolver = (key?: string): IconComponent =>\n key ? app.getSystemIcon(key) ?? LanguageIcon : LanguageIcon;\n\n return (\n <Box px={3} pb={3}>\n {links\n .filter(({ url, entityRef }) => url || entityRef)\n .map(({ url, entityRef, title, icon }) => {\n if (entityRef) {\n const entityName = parseEntityRef(entityRef, {\n defaultKind: '<unknown>',\n defaultNamespace: '<unknown>',\n });\n const target = entityRoute(entityName);\n return { title, icon, url: target };\n }\n return { title, icon, url: url! };\n })\n .map(({ url, title, icon }, i) => (\n <IconLink\n key={`output-link-${i}`}\n href={url}\n text={title ?? url}\n Icon={iconResolver(icon)}\n target=\"_blank\"\n />\n ))}\n </Box>\n );\n};\n"],"names":[],"mappings":";;;;;;;;AA6BO,MAAM,aAAgB,GAAA,CAAC,EAAE,MAAA,EAAiC,KAAA;AAC/D,EAAA,MAAM,EAAE,KAAA,GAAQ,EAAC,EAAM,GAAA,MAAA,CAAA;AACvB,EAAA,MAAM,MAAM,MAAO,EAAA,CAAA;AACnB,EAAM,MAAA,WAAA,GAAc,YAAY,cAAc,CAAA,CAAA;AAE9C,EAAM,MAAA,YAAA,GAAe,CAAC,GAA6B,KAAA;AAlCrD,IAAA,IAAA,EAAA,CAAA;AAmCI,IAAA,OAAA,GAAA,GAAA,CAAM,EAAI,GAAA,GAAA,CAAA,aAAA,CAAc,GAAG,CAAA,KAArB,YAA0B,YAAe,GAAA,YAAA,CAAA;AAAA,GAAA,CAAA;AAEjD,EACE,uBAAA,KAAA,CAAA,aAAA,CAAC,OAAI,EAAI,EAAA,CAAA,EAAG,IAAI,CACb,EAAA,EAAA,KAAA,CACE,MAAO,CAAA,CAAC,EAAE,GAAA,EAAK,WAAgB,KAAA,GAAA,IAAO,SAAS,CAAA,CAC/C,GAAI,CAAA,CAAC,EAAE,GAAK,EAAA,SAAA,EAAW,KAAO,EAAA,IAAA,EAAW,KAAA;AACxC,IAAA,IAAI,SAAW,EAAA;AACb,MAAM,MAAA,UAAA,GAAa,eAAe,SAAW,EAAA;AAAA,QAC3C,WAAa,EAAA,WAAA;AAAA,QACb,gBAAkB,EAAA,WAAA;AAAA,OACnB,CAAA,CAAA;AACD,MAAM,MAAA,MAAA,GAAS,YAAY,UAAU,CAAA,CAAA;AACrC,MAAA,OAAO,EAAE,KAAA,EAAO,IAAM,EAAA,GAAA,EAAK,MAAO,EAAA,CAAA;AAAA,KACpC;AACA,IAAO,OAAA,EAAE,KAAO,EAAA,IAAA,EAAM,GAAU,EAAA,CAAA;AAAA,GACjC,EACA,GAAI,CAAA,CAAC,EAAE,GAAK,EAAA,KAAA,EAAO,IAAK,EAAA,EAAG,CAC1B,qBAAA,KAAA,CAAA,aAAA;AAAA,IAAC,QAAA;AAAA,IAAA;AAAA,MACC,GAAA,EAAK,eAAe,CAAC,CAAA,CAAA;AAAA,MACrB,IAAM,EAAA,GAAA;AAAA,MACN,MAAM,KAAS,IAAA,IAAA,GAAA,KAAA,GAAA,GAAA;AAAA,MACf,IAAA,EAAM,aAAa,IAAI,CAAA;AAAA,MACvB,MAAO,EAAA,QAAA;AAAA,KAAA;AAAA,GAEV,CACL,CAAA,CAAA;AAEJ;;;;"}
1
+ {"version":3,"file":"TaskPageLinks.esm.js","sources":["../../../../src/next/TemplateEditorPage/DryRunResults/TaskPageLinks.tsx"],"sourcesContent":["/*\n * Copyright 2021 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { parseEntityRef } from '@backstage/catalog-model';\nimport { entityRouteRef } from '@backstage/plugin-catalog-react';\nimport Box from '@material-ui/core/Box';\nimport LanguageIcon from '@material-ui/icons/Language';\nimport React from 'react';\nimport { ScaffolderTaskOutput } from '@backstage/plugin-scaffolder-react';\nimport { IconLink } from './IconLink';\nimport { IconComponent, useApp, useRouteRef } from '@backstage/core-plugin-api';\n\ntype TaskPageLinksProps = {\n output: ScaffolderTaskOutput;\n};\n\nexport const TaskPageLinks = ({ output }: TaskPageLinksProps) => {\n const { links = [] } = output;\n const app = useApp();\n const entityRoute = useRouteRef(entityRouteRef);\n\n const iconResolver = (key?: string): IconComponent =>\n key ? app.getSystemIcon(key) ?? LanguageIcon : LanguageIcon;\n\n return (\n <Box px={3} pb={3}>\n {links\n .filter(({ url, entityRef }) => url || entityRef)\n .map(({ url, entityRef, title, icon }) => {\n if (entityRef) {\n const entityName = parseEntityRef(entityRef, {\n defaultKind: '<unknown>',\n defaultNamespace: '<unknown>',\n });\n const target = entityRoute(entityName);\n return { title, icon, url: target };\n }\n return { title, icon, url: url! };\n })\n .map(({ url, title, icon }, i) => (\n <IconLink\n key={`output-link-${i}`}\n href={url}\n text={title ?? url}\n Icon={iconResolver(icon)}\n target=\"_blank\"\n />\n ))}\n </Box>\n );\n};\n"],"names":[],"mappings":";;;;;;;;AA6BO,MAAM,aAAgB,GAAA,CAAC,EAAE,MAAA,EAAiC,KAAA;AAC/D,EAAA,MAAM,EAAE,KAAA,GAAQ,EAAC,EAAM,GAAA,MAAA,CAAA;AACvB,EAAA,MAAM,MAAM,MAAO,EAAA,CAAA;AACnB,EAAM,MAAA,WAAA,GAAc,YAAY,cAAc,CAAA,CAAA;AAE9C,EAAM,MAAA,YAAA,GAAe,CAAC,GACpB,KAAA,GAAA,GAAM,IAAI,aAAc,CAAA,GAAG,KAAK,YAAe,GAAA,YAAA,CAAA;AAEjD,EACE,uBAAA,KAAA,CAAA,aAAA,CAAC,OAAI,EAAI,EAAA,CAAA,EAAG,IAAI,CACb,EAAA,EAAA,KAAA,CACE,MAAO,CAAA,CAAC,EAAE,GAAA,EAAK,WAAgB,KAAA,GAAA,IAAO,SAAS,CAAA,CAC/C,GAAI,CAAA,CAAC,EAAE,GAAK,EAAA,SAAA,EAAW,KAAO,EAAA,IAAA,EAAW,KAAA;AACxC,IAAA,IAAI,SAAW,EAAA;AACb,MAAM,MAAA,UAAA,GAAa,eAAe,SAAW,EAAA;AAAA,QAC3C,WAAa,EAAA,WAAA;AAAA,QACb,gBAAkB,EAAA,WAAA;AAAA,OACnB,CAAA,CAAA;AACD,MAAM,MAAA,MAAA,GAAS,YAAY,UAAU,CAAA,CAAA;AACrC,MAAA,OAAO,EAAE,KAAA,EAAO,IAAM,EAAA,GAAA,EAAK,MAAO,EAAA,CAAA;AAAA,KACpC;AACA,IAAO,OAAA,EAAE,KAAO,EAAA,IAAA,EAAM,GAAU,EAAA,CAAA;AAAA,GACjC,EACA,GAAI,CAAA,CAAC,EAAE,GAAK,EAAA,KAAA,EAAO,IAAK,EAAA,EAAG,CAC1B,qBAAA,KAAA,CAAA,aAAA;AAAA,IAAC,QAAA;AAAA,IAAA;AAAA,MACC,GAAA,EAAK,eAAe,CAAC,CAAA,CAAA;AAAA,MACrB,IAAM,EAAA,GAAA;AAAA,MACN,MAAM,KAAS,IAAA,GAAA;AAAA,MACf,IAAA,EAAM,aAAa,IAAI,CAAA;AAAA,MACvB,MAAO,EAAA,QAAA;AAAA,KAAA;AAAA,GAEV,CACL,CAAA,CAAA;AAEJ;;;;"}
@@ -27,7 +27,6 @@ const useStyles = makeStyles((theme) => ({
27
27
  }
28
28
  }));
29
29
  function TemplateEditorBrowser(props) {
30
- var _a, _b;
31
30
  const classes = useStyles();
32
31
  const directoryEditor = useDirectoryEditor();
33
32
  const changedFiles = directoryEditor.files.filter((file) => file.dirty);
@@ -63,7 +62,7 @@ function TemplateEditorBrowser(props) {
63
62
  )), /* @__PURE__ */ React.createElement("div", { className: classes.buttonsGap }), /* @__PURE__ */ React.createElement(Tooltip, { title: "Close directory" }, /* @__PURE__ */ React.createElement(IconButton, { className: classes.button, onClick: handleClose }, /* @__PURE__ */ React.createElement(CloseIcon, null)))), /* @__PURE__ */ React.createElement(Divider, { className: classes.buttonsDivider }), /* @__PURE__ */ React.createElement(
64
63
  FileBrowser,
65
64
  {
66
- selected: (_b = (_a = directoryEditor.selectedFile) == null ? void 0 : _a.path) != null ? _b : "",
65
+ selected: directoryEditor.selectedFile?.path ?? "",
67
66
  onSelect: directoryEditor.setSelectedFile,
68
67
  filePaths: directoryEditor.files.map((file) => file.path)
69
68
  }