@backstage-community/plugin-tekton 3.16.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 (151) hide show
  1. package/CHANGELOG.md +801 -0
  2. package/README.md +369 -0
  3. package/app-config.dynamic.yaml +12 -0
  4. package/dist/components/Charts/PipelineBars.esm.js +49 -0
  5. package/dist/components/Charts/PipelineBars.esm.js.map +1 -0
  6. package/dist/components/Icons/CriticalRiskIcon.esm.js +22 -0
  7. package/dist/components/Icons/CriticalRiskIcon.esm.js.map +1 -0
  8. package/dist/components/Icons/EqualsIcon.esm.js +22 -0
  9. package/dist/components/Icons/EqualsIcon.esm.js.map +1 -0
  10. package/dist/components/Icons/LinkToSbomIcon.esm.js +37 -0
  11. package/dist/components/Icons/LinkToSbomIcon.esm.js.map +1 -0
  12. package/dist/components/Icons/OutputIcon.esm.js +36 -0
  13. package/dist/components/Icons/OutputIcon.esm.js.map +1 -0
  14. package/dist/components/Icons/SignedBadge.esm.js +16 -0
  15. package/dist/components/Icons/SignedBadge.esm.js.map +1 -0
  16. package/dist/components/Icons/ViewLogsIcon.esm.js +35 -0
  17. package/dist/components/Icons/ViewLogsIcon.esm.js.map +1 -0
  18. package/dist/components/PipelineRunList/PipelineRunColumnHeader.esm.js +43 -0
  19. package/dist/components/PipelineRunList/PipelineRunColumnHeader.esm.js.map +1 -0
  20. package/dist/components/PipelineRunList/PipelineRunList.esm.js +185 -0
  21. package/dist/components/PipelineRunList/PipelineRunList.esm.js.map +1 -0
  22. package/dist/components/PipelineRunList/PipelineRunListSearchBar.esm.js +42 -0
  23. package/dist/components/PipelineRunList/PipelineRunListSearchBar.esm.js.map +1 -0
  24. package/dist/components/PipelineRunList/PipelineRunOutput.esm.js +70 -0
  25. package/dist/components/PipelineRunList/PipelineRunOutput.esm.js.map +1 -0
  26. package/dist/components/PipelineRunList/PipelineRunRow.css.esm.js +7 -0
  27. package/dist/components/PipelineRunList/PipelineRunRow.css.esm.js.map +1 -0
  28. package/dist/components/PipelineRunList/PipelineRunRow.esm.js +110 -0
  29. package/dist/components/PipelineRunList/PipelineRunRow.esm.js.map +1 -0
  30. package/dist/components/PipelineRunList/PipelineRunRowActions.esm.js +137 -0
  31. package/dist/components/PipelineRunList/PipelineRunRowActions.esm.js.map +1 -0
  32. package/dist/components/PipelineRunList/PipelineRunSBOMLink.esm.js +25 -0
  33. package/dist/components/PipelineRunList/PipelineRunSBOMLink.esm.js.map +1 -0
  34. package/dist/components/PipelineRunList/PipelineRunTableBody.esm.js +32 -0
  35. package/dist/components/PipelineRunList/PipelineRunTableBody.esm.js.map +1 -0
  36. package/dist/components/PipelineRunList/PipelineRunTaskStatus.esm.js +11 -0
  37. package/dist/components/PipelineRunList/PipelineRunTaskStatus.esm.js.map +1 -0
  38. package/dist/components/PipelineRunList/PipelineRunVulnerabilities.esm.js +81 -0
  39. package/dist/components/PipelineRunList/PipelineRunVulnerabilities.esm.js.map +1 -0
  40. package/dist/components/PipelineRunList/PipelineTableHeader.esm.js +53 -0
  41. package/dist/components/PipelineRunList/PipelineTableHeader.esm.js.map +1 -0
  42. package/dist/components/PipelineRunList/PlrStatus.css.esm.js +7 -0
  43. package/dist/components/PipelineRunList/PlrStatus.css.esm.js.map +1 -0
  44. package/dist/components/PipelineRunList/PlrStatus.esm.js +11 -0
  45. package/dist/components/PipelineRunList/PlrStatus.esm.js.map +1 -0
  46. package/dist/components/PipelineRunList/ResourceBadge.css.esm.js +7 -0
  47. package/dist/components/PipelineRunList/ResourceBadge.css.esm.js.map +1 -0
  48. package/dist/components/PipelineRunList/ResourceBadge.esm.js +15 -0
  49. package/dist/components/PipelineRunList/ResourceBadge.esm.js.map +1 -0
  50. package/dist/components/PipelineRunLogs/PipelineRunLogDialog.esm.js +82 -0
  51. package/dist/components/PipelineRunLogs/PipelineRunLogDialog.esm.js.map +1 -0
  52. package/dist/components/PipelineRunLogs/PipelineRunLogDownloader.esm.js +47 -0
  53. package/dist/components/PipelineRunLogs/PipelineRunLogDownloader.esm.js.map +1 -0
  54. package/dist/components/PipelineRunLogs/PipelineRunLogViewer.esm.js +53 -0
  55. package/dist/components/PipelineRunLogs/PipelineRunLogViewer.esm.js.map +1 -0
  56. package/dist/components/PipelineRunLogs/PipelineRunLogs.esm.js +69 -0
  57. package/dist/components/PipelineRunLogs/PipelineRunLogs.esm.js.map +1 -0
  58. package/dist/components/PipelineRunLogs/PodLogsDownloadLink.esm.js +69 -0
  59. package/dist/components/PipelineRunLogs/PodLogsDownloadLink.esm.js.map +1 -0
  60. package/dist/components/PipelineRunLogs/TaskStatusStepper.esm.js +128 -0
  61. package/dist/components/PipelineRunLogs/TaskStatusStepper.esm.js.map +1 -0
  62. package/dist/components/PipelineRunOutput/PipelineRunOutputDialog.esm.js +62 -0
  63. package/dist/components/PipelineRunOutput/PipelineRunOutputDialog.esm.js.map +1 -0
  64. package/dist/components/Router.esm.js +16 -0
  65. package/dist/components/Router.esm.js.map +1 -0
  66. package/dist/components/Tekton/TektonCIComponent.esm.js +53 -0
  67. package/dist/components/Tekton/TektonCIComponent.esm.js.map +1 -0
  68. package/dist/components/common/ClusterSelector.css.esm.js +7 -0
  69. package/dist/components/common/ClusterSelector.css.esm.js.map +1 -0
  70. package/dist/components/common/ClusterSelector.esm.js +46 -0
  71. package/dist/components/common/ClusterSelector.esm.js.map +1 -0
  72. package/dist/components/common/ErrorPanel.esm.js +33 -0
  73. package/dist/components/common/ErrorPanel.esm.js.map +1 -0
  74. package/dist/components/common/PermissionAlert.esm.js +9 -0
  75. package/dist/components/common/PermissionAlert.esm.js.map +1 -0
  76. package/dist/components/common/ResourceStatus.css.esm.js +7 -0
  77. package/dist/components/common/ResourceStatus.css.esm.js.map +1 -0
  78. package/dist/components/common/StatusSelector.css.esm.js +7 -0
  79. package/dist/components/common/StatusSelector.css.esm.js.map +1 -0
  80. package/dist/components/common/StatusSelector.esm.js +48 -0
  81. package/dist/components/common/StatusSelector.esm.js.map +1 -0
  82. package/dist/components/common/TableExpandCollapse.esm.js +44 -0
  83. package/dist/components/common/TableExpandCollapse.esm.js.map +1 -0
  84. package/dist/components/pipeline-topology/PipelineLayout.esm.js +126 -0
  85. package/dist/components/pipeline-topology/PipelineLayout.esm.js.map +1 -0
  86. package/dist/components/pipeline-topology/PipelineRunVisualization.esm.js +13 -0
  87. package/dist/components/pipeline-topology/PipelineRunVisualization.esm.js.map +1 -0
  88. package/dist/components/pipeline-topology/PipelineTaskNode.css.esm.js +7 -0
  89. package/dist/components/pipeline-topology/PipelineTaskNode.css.esm.js.map +1 -0
  90. package/dist/components/pipeline-topology/PipelineTaskNode.esm.js +132 -0
  91. package/dist/components/pipeline-topology/PipelineTaskNode.esm.js.map +1 -0
  92. package/dist/components/pipeline-topology/PipelineVisualization.css.esm.js +7 -0
  93. package/dist/components/pipeline-topology/PipelineVisualization.css.esm.js.map +1 -0
  94. package/dist/components/pipeline-topology/PipelineVisualization.esm.js +24 -0
  95. package/dist/components/pipeline-topology/PipelineVisualization.esm.js.map +1 -0
  96. package/dist/components/pipeline-topology/PipelineVisualizationStepList.css.esm.js +7 -0
  97. package/dist/components/pipeline-topology/PipelineVisualizationStepList.css.esm.js.map +1 -0
  98. package/dist/components/pipeline-topology/PipelineVisualizationStepList.esm.js +39 -0
  99. package/dist/components/pipeline-topology/PipelineVisualizationStepList.esm.js.map +1 -0
  100. package/dist/components/pipeline-topology/PipelineVisualizationView.esm.js +41 -0
  101. package/dist/components/pipeline-topology/PipelineVisualizationView.esm.js.map +1 -0
  102. package/dist/components/pipeline-topology/TaskGroupEdge.esm.js +16 -0
  103. package/dist/components/pipeline-topology/TaskGroupEdge.esm.js.map +1 -0
  104. package/dist/components/pipeline-topology/dag.esm.js +119 -0
  105. package/dist/components/pipeline-topology/dag.esm.js.map +1 -0
  106. package/dist/components/pipeline-topology/pipelineComponentFactory.esm.js +60 -0
  107. package/dist/components/pipeline-topology/pipelineComponentFactory.esm.js.map +1 -0
  108. package/dist/consts/pipeline-topology-const.esm.js +66 -0
  109. package/dist/consts/pipeline-topology-const.esm.js.map +1 -0
  110. package/dist/consts/tekton-const.esm.js +7 -0
  111. package/dist/consts/tekton-const.esm.js.map +1 -0
  112. package/dist/hooks/TektonResourcesContext.esm.js +16 -0
  113. package/dist/hooks/TektonResourcesContext.esm.js.map +1 -0
  114. package/dist/hooks/useAllWatchResources.esm.js +35 -0
  115. package/dist/hooks/useAllWatchResources.esm.js.map +1 -0
  116. package/dist/hooks/useDarkTheme.esm.js +21 -0
  117. package/dist/hooks/useDarkTheme.esm.js.map +1 -0
  118. package/dist/hooks/usePipelineRunScanResults.esm.js +35 -0
  119. package/dist/hooks/usePipelineRunScanResults.esm.js.map +1 -0
  120. package/dist/hooks/usePodLogsOfPipelineRun.esm.js +67 -0
  121. package/dist/hooks/usePodLogsOfPipelineRun.esm.js.map +1 -0
  122. package/dist/hooks/useResourcesClusters.esm.js +24 -0
  123. package/dist/hooks/useResourcesClusters.esm.js.map +1 -0
  124. package/dist/hooks/useTektonObjectsResponse.esm.js +78 -0
  125. package/dist/hooks/useTektonObjectsResponse.esm.js.map +1 -0
  126. package/dist/hooks/useTektonViewPermission.esm.js +12 -0
  127. package/dist/hooks/useTektonViewPermission.esm.js.map +1 -0
  128. package/dist/index.d.ts +32 -0
  129. package/dist/index.esm.js +3 -0
  130. package/dist/index.esm.js.map +1 -0
  131. package/dist/models.esm.js +21 -0
  132. package/dist/models.esm.js.map +1 -0
  133. package/dist/plugin.esm.js +72 -0
  134. package/dist/plugin.esm.js.map +1 -0
  135. package/dist/types/types.esm.js +15 -0
  136. package/dist/types/types.esm.js.map +1 -0
  137. package/dist/utils/isTektonCIAvailable.esm.js +7 -0
  138. package/dist/utils/isTektonCIAvailable.esm.js.map +1 -0
  139. package/dist/utils/log-downloader-utils.esm.js +33 -0
  140. package/dist/utils/log-downloader-utils.esm.js.map +1 -0
  141. package/dist/utils/pipeline-step-utils.esm.js +53 -0
  142. package/dist/utils/pipeline-step-utils.esm.js.map +1 -0
  143. package/dist/utils/pipeline-topology-utils.esm.js +250 -0
  144. package/dist/utils/pipeline-topology-utils.esm.js.map +1 -0
  145. package/dist/utils/pipelineRun-utils.esm.js +128 -0
  146. package/dist/utils/pipelineRun-utils.esm.js.map +1 -0
  147. package/dist/utils/taskRun-utils.esm.js +50 -0
  148. package/dist/utils/taskRun-utils.esm.js.map +1 -0
  149. package/dist/utils/tekton-utils.esm.js +191 -0
  150. package/dist/utils/tekton-utils.esm.js.map +1 -0
  151. package/package.json +114 -0
@@ -0,0 +1,46 @@
1
+ import React__default from 'react';
2
+ import { Select } from '@backstage/core-components';
3
+ import { makeStyles, Typography } from '@material-ui/core';
4
+ import { TektonResourcesContext } from '../../hooks/TektonResourcesContext.esm.js';
5
+ import './ClusterSelector.css.esm.js';
6
+
7
+ const useStyles = makeStyles((theme) => ({
8
+ label: {
9
+ color: theme.palette.text.primary,
10
+ fontSize: "1rem",
11
+ paddingRight: "10px",
12
+ fontWeight: "bold"
13
+ }
14
+ }));
15
+ const ClusterSelector = () => {
16
+ const classes = useStyles();
17
+ const {
18
+ clusters: k8sClusters,
19
+ selectedCluster,
20
+ setSelectedCluster: setClusterContext
21
+ } = React__default.useContext(TektonResourcesContext);
22
+ const clusterOptions = k8sClusters.map((cluster) => ({
23
+ value: cluster,
24
+ label: cluster
25
+ }));
26
+ const curCluster = selectedCluster && k8sClusters?.length > 0 ? k8sClusters[selectedCluster] : k8sClusters?.[0];
27
+ const [clusterSelected, setClusterSelected] = React__default.useState(curCluster);
28
+ const onClusterChange = (arg) => {
29
+ const index = k8sClusters.findIndex((cluster) => cluster === arg);
30
+ setClusterContext(index);
31
+ setClusterSelected(arg);
32
+ };
33
+ return /* @__PURE__ */ React__default.createElement("div", { className: "bs-tkn-cluster-selector" }, /* @__PURE__ */ React__default.createElement(Typography, { className: classes.label }, "Cluster"), /* @__PURE__ */ React__default.createElement(
34
+ Select,
35
+ {
36
+ onChange: onClusterChange,
37
+ label: "",
38
+ items: clusterOptions,
39
+ selected: clusterSelected,
40
+ margin: "dense"
41
+ }
42
+ ));
43
+ };
44
+
45
+ export { ClusterSelector };
46
+ //# sourceMappingURL=ClusterSelector.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ClusterSelector.esm.js","sources":["../../../src/components/common/ClusterSelector.tsx"],"sourcesContent":["/*\n * Copyright 2024 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport React from 'react';\n\nimport { Select, SelectedItems } from '@backstage/core-components';\nimport { BackstageTheme } from '@backstage/theme';\n\nimport { makeStyles, Typography } from '@material-ui/core';\n\nimport { TektonResourcesContext } from '../../hooks/TektonResourcesContext';\n\nimport './ClusterSelector.css';\n\nconst useStyles = makeStyles<BackstageTheme>(theme => ({\n label: {\n color: theme.palette.text.primary,\n fontSize: '1rem',\n paddingRight: '10px',\n fontWeight: 'bold',\n },\n}));\n\nexport const ClusterSelector = () => {\n const classes = useStyles();\n const {\n clusters: k8sClusters,\n selectedCluster,\n setSelectedCluster: setClusterContext,\n } = React.useContext(TektonResourcesContext);\n const clusterOptions = k8sClusters.map(cluster => ({\n value: cluster,\n label: cluster,\n }));\n\n const curCluster =\n selectedCluster && k8sClusters?.length > 0\n ? k8sClusters[selectedCluster]\n : k8sClusters?.[0];\n\n const [clusterSelected, setClusterSelected] =\n React.useState<SelectedItems>(curCluster);\n\n const onClusterChange = (arg: SelectedItems) => {\n const index = k8sClusters.findIndex(cluster => cluster === arg);\n setClusterContext(index);\n setClusterSelected(arg);\n };\n return (\n <div className=\"bs-tkn-cluster-selector\">\n <Typography className={classes.label}>Cluster</Typography>\n <Select\n onChange={onClusterChange}\n label=\"\"\n items={clusterOptions}\n selected={clusterSelected}\n margin=\"dense\"\n />\n </div>\n );\n};\n"],"names":["React"],"mappings":";;;;;;AA0BA,MAAM,SAAA,GAAY,WAA2B,CAAU,KAAA,MAAA;AAAA,EACrD,KAAO,EAAA;AAAA,IACL,KAAA,EAAO,KAAM,CAAA,OAAA,CAAQ,IAAK,CAAA,OAAA;AAAA,IAC1B,QAAU,EAAA,MAAA;AAAA,IACV,YAAc,EAAA,MAAA;AAAA,IACd,UAAY,EAAA;AAAA;AAEhB,CAAE,CAAA,CAAA;AAEK,MAAM,kBAAkB,MAAM;AACnC,EAAA,MAAM,UAAU,SAAU,EAAA;AAC1B,EAAM,MAAA;AAAA,IACJ,QAAU,EAAA,WAAA;AAAA,IACV,eAAA;AAAA,IACA,kBAAoB,EAAA;AAAA,GACtB,GAAIA,cAAM,CAAA,UAAA,CAAW,sBAAsB,CAAA;AAC3C,EAAM,MAAA,cAAA,GAAiB,WAAY,CAAA,GAAA,CAAI,CAAY,OAAA,MAAA;AAAA,IACjD,KAAO,EAAA,OAAA;AAAA,IACP,KAAO,EAAA;AAAA,GACP,CAAA,CAAA;AAEF,EAAM,MAAA,UAAA,GACJ,mBAAmB,WAAa,EAAA,MAAA,GAAS,IACrC,WAAY,CAAA,eAAe,CAC3B,GAAA,WAAA,GAAc,CAAC,CAAA;AAErB,EAAA,MAAM,CAAC,eAAiB,EAAA,kBAAkB,CACxC,GAAAA,cAAA,CAAM,SAAwB,UAAU,CAAA;AAE1C,EAAM,MAAA,eAAA,GAAkB,CAAC,GAAuB,KAAA;AAC9C,IAAA,MAAM,KAAQ,GAAA,WAAA,CAAY,SAAU,CAAA,CAAA,OAAA,KAAW,YAAY,GAAG,CAAA;AAC9D,IAAA,iBAAA,CAAkB,KAAK,CAAA;AACvB,IAAA,kBAAA,CAAmB,GAAG,CAAA;AAAA,GACxB;AACA,EACE,uBAAAA,cAAA,CAAA,aAAA,CAAC,KAAI,EAAA,EAAA,SAAA,EAAU,yBACb,EAAA,kBAAAA,cAAA,CAAA,aAAA,CAAC,cAAW,SAAW,EAAA,OAAA,CAAQ,KAAO,EAAA,EAAA,SAAO,CAC7C,kBAAAA,cAAA,CAAA,aAAA;AAAA,IAAC,MAAA;AAAA,IAAA;AAAA,MACC,QAAU,EAAA,eAAA;AAAA,MACV,KAAM,EAAA,EAAA;AAAA,MACN,KAAO,EAAA,cAAA;AAAA,MACP,QAAU,EAAA,eAAA;AAAA,MACV,MAAO,EAAA;AAAA;AAAA,GAEX,CAAA;AAEJ;;;;"}
@@ -0,0 +1,33 @@
1
+ import React__default from 'react';
2
+ import { WarningPanel } from '@backstage/core-components';
3
+ import { useEntity } from '@backstage/plugin-catalog-react';
4
+ import { Typography } from '@material-ui/core';
5
+
6
+ const ErrorPanel = ({ allErrors }) => {
7
+ const {
8
+ entity: {
9
+ metadata: { name: entityName }
10
+ }
11
+ } = useEntity();
12
+ return /* @__PURE__ */ React__default.createElement("div", { className: "warning-panel", style: { marginBottom: "16px" } }, /* @__PURE__ */ React__default.createElement(
13
+ WarningPanel,
14
+ {
15
+ title: "There was a problem retrieving Kubernetes objects",
16
+ message: `There was a problem retrieving some Kubernetes resources for the entity: ${entityName}. This could mean that the Error Reporting card is not completely accurate.`
17
+ },
18
+ /* @__PURE__ */ React__default.createElement("div", null, "Errors:", allErrors.map((err, _index) => {
19
+ const errMessage = err.message ? `${err.message}` : `Error fetching Kubernetes resource: '${err.resourcePath}', error: ${err.errorType}, status code: ${err.statusCode}`;
20
+ return /* @__PURE__ */ React__default.createElement(
21
+ Typography,
22
+ {
23
+ variant: "body2",
24
+ key: `${err.resourcePath}-${err.statusCode}`
25
+ },
26
+ err.errorType === "FETCH_ERROR" ? `Error communicating with Kubernetes: ${err.errorType}, message: ${err.message}` : errMessage
27
+ );
28
+ }))
29
+ ));
30
+ };
31
+
32
+ export { ErrorPanel };
33
+ //# sourceMappingURL=ErrorPanel.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ErrorPanel.esm.js","sources":["../../../src/components/common/ErrorPanel.tsx"],"sourcesContent":["/*\n * Copyright 2024 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport React from 'react';\n\nimport { WarningPanel } from '@backstage/core-components';\nimport { useEntity } from '@backstage/plugin-catalog-react';\n\nimport { Typography } from '@material-ui/core';\n\nimport { ClusterError, ClusterErrors } from '../../types/types';\n\ntype ErrorPanelProps = { allErrors: ClusterErrors };\n\nexport const ErrorPanel = ({ allErrors }: ErrorPanelProps) => {\n const {\n entity: {\n metadata: { name: entityName },\n },\n } = useEntity();\n return (\n <div className=\"warning-panel\" style={{ marginBottom: '16px' }}>\n <WarningPanel\n title=\"There was a problem retrieving Kubernetes objects\"\n message={`There was a problem retrieving some Kubernetes resources for the entity: ${entityName}. This could mean that the Error Reporting card is not completely accurate.`}\n >\n <div>\n Errors:\n {allErrors.map((err: ClusterError, _index) => {\n const errMessage = err.message\n ? `${err.message}`\n : `Error fetching Kubernetes resource: '${err.resourcePath}', error: ${err.errorType}, status code: ${err.statusCode}`;\n return (\n <Typography\n variant=\"body2\"\n key={`${err.resourcePath}-${err.statusCode}`}\n >\n {err.errorType === 'FETCH_ERROR'\n ? `Error communicating with Kubernetes: ${err.errorType}, message: ${err.message}`\n : errMessage}\n </Typography>\n );\n })}\n </div>\n </WarningPanel>\n </div>\n );\n};\n"],"names":["React"],"mappings":";;;;;AA0BO,MAAM,UAAa,GAAA,CAAC,EAAE,SAAA,EAAiC,KAAA;AAC5D,EAAM,MAAA;AAAA,IACJ,MAAQ,EAAA;AAAA,MACN,QAAA,EAAU,EAAE,IAAA,EAAM,UAAW;AAAA;AAC/B,MACE,SAAU,EAAA;AACd,EACE,uBAAAA,cAAA,CAAA,aAAA,CAAC,SAAI,SAAU,EAAA,eAAA,EAAgB,OAAO,EAAE,YAAA,EAAc,QACpD,EAAA,kBAAAA,cAAA,CAAA,aAAA;AAAA,IAAC,YAAA;AAAA,IAAA;AAAA,MACC,KAAM,EAAA,mDAAA;AAAA,MACN,OAAA,EAAS,4EAA4E,UAAU,CAAA,2EAAA;AAAA,KAAA;AAAA,iDAE9F,KAAI,EAAA,IAAA,EAAA,SAAA,EAEF,UAAU,GAAI,CAAA,CAAC,KAAmB,MAAW,KAAA;AAC5C,MAAA,MAAM,UAAa,GAAA,GAAA,CAAI,OACnB,GAAA,CAAA,EAAG,IAAI,OAAO,CAAA,CAAA,GACd,CAAwC,qCAAA,EAAA,GAAA,CAAI,YAAY,CAAa,UAAA,EAAA,GAAA,CAAI,SAAS,CAAA,eAAA,EAAkB,IAAI,UAAU,CAAA,CAAA;AACtH,MACE,uBAAAA,cAAA,CAAA,aAAA;AAAA,QAAC,UAAA;AAAA,QAAA;AAAA,UACC,OAAQ,EAAA,OAAA;AAAA,UACR,KAAK,CAAG,EAAA,GAAA,CAAI,YAAY,CAAA,CAAA,EAAI,IAAI,UAAU,CAAA;AAAA,SAAA;AAAA,QAEzC,GAAA,CAAI,cAAc,aACf,GAAA,CAAA,qCAAA,EAAwC,IAAI,SAAS,CAAA,WAAA,EAAc,GAAI,CAAA,OAAO,CAC9E,CAAA,GAAA;AAAA,OACN;AAAA,KAEH,CACH;AAAA,GAEJ,CAAA;AAEJ;;;;"}
@@ -0,0 +1,9 @@
1
+ import React__default from 'react';
2
+ import { Alert, AlertTitle } from '@material-ui/lab';
3
+
4
+ const PermissionAlert = () => {
5
+ return /* @__PURE__ */ React__default.createElement(Alert, { severity: "warning", "data-testid": "no-permission-alert" }, /* @__PURE__ */ React__default.createElement(AlertTitle, null, "Permission required"), "To view Tekton Pipeline Runs, contact your administrator to give you the tekton.view.read permission.");
6
+ };
7
+
8
+ export { PermissionAlert as default };
9
+ //# sourceMappingURL=PermissionAlert.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PermissionAlert.esm.js","sources":["../../../src/components/common/PermissionAlert.tsx"],"sourcesContent":["/*\n * Copyright 2024 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport React from 'react';\n\nimport { Alert, AlertTitle } from '@material-ui/lab';\n\nconst PermissionAlert = () => {\n return (\n <Alert severity=\"warning\" data-testid=\"no-permission-alert\">\n <AlertTitle>Permission required</AlertTitle>\n To view Tekton Pipeline Runs, contact your administrator to give you the\n tekton.view.read permission.\n </Alert>\n );\n};\nexport default PermissionAlert;\n"],"names":["React"],"mappings":";;;AAmBA,MAAM,kBAAkB,MAAM;AAC5B,EACE,uBAAAA,cAAA,CAAA,aAAA,CAAC,KAAM,EAAA,EAAA,QAAA,EAAS,SAAU,EAAA,aAAA,EAAY,yCACnCA,cAAA,CAAA,aAAA,CAAA,UAAA,EAAA,IAAA,EAAW,qBAAmB,CAAA,EAAa,uGAG9C,CAAA;AAEJ;;;;"}
@@ -0,0 +1,7 @@
1
+ import styleInject from '../../node_modules/style-inject/dist/style-inject.es.esm.js';
2
+
3
+ var css_248z = ".bs-tkn-resource-status {\n padding-left: var(--pf-v5-global--spacer--sm);\n white-space: nowrap;\n}\n\n.bs-tkn-resource-status__badge {\n vertical-align: middle;\n}\n\n.bs-tkn-resource-status__badge--alt {\n vertical-align: baseline;\n}\n";
4
+ styleInject(css_248z);
5
+
6
+ export { css_248z as default };
7
+ //# sourceMappingURL=ResourceStatus.css.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ResourceStatus.css.esm.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;"}
@@ -0,0 +1,7 @@
1
+ import styleInject from '../../node_modules/style-inject/dist/style-inject.es.esm.js';
2
+
3
+ var css_248z = ".bs-tkn-status-selector {\n display: flex;\n align-items: center;\n}\n\n.bs-tkn-status-selector > div > div > div {\n margin-top: 0;\n}\n";
4
+ styleInject(css_248z);
5
+
6
+ export { css_248z as default };
7
+ //# sourceMappingURL=StatusSelector.css.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"StatusSelector.css.esm.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;"}
@@ -0,0 +1,48 @@
1
+ import React__default from 'react';
2
+ import { Select } from '@backstage/core-components';
3
+ import { makeStyles, Typography } from '@material-ui/core';
4
+ import './StatusSelector.css.esm.js';
5
+ import { ComputedStatus } from '@janus-idp/shared-react';
6
+ import { TektonResourcesContext } from '../../hooks/TektonResourcesContext.esm.js';
7
+
8
+ const useStyles = makeStyles((theme) => ({
9
+ label: {
10
+ color: theme.palette.text.primary,
11
+ fontSize: "1rem",
12
+ paddingRight: "10px",
13
+ fontWeight: "bold"
14
+ }
15
+ }));
16
+ const statusOptions = Object.entries(ComputedStatus).sort(([keyA], [keyB]) => {
17
+ if (keyA === keyB) {
18
+ return 0;
19
+ } else if (keyA < keyB) {
20
+ return -1;
21
+ }
22
+ return 1;
23
+ }).map(([key, value]) => ({
24
+ value: key,
25
+ label: value
26
+ }));
27
+ const StatusSelector = () => {
28
+ const classes = useStyles();
29
+ const { selectedStatus, setSelectedStatus } = React__default.useContext(
30
+ TektonResourcesContext
31
+ );
32
+ const onStatusChange = (status) => {
33
+ setSelectedStatus(status);
34
+ };
35
+ return /* @__PURE__ */ React__default.createElement("div", { className: "bs-tkn-status-selector" }, /* @__PURE__ */ React__default.createElement(Typography, { className: classes.label }, "Status"), /* @__PURE__ */ React__default.createElement(
36
+ Select,
37
+ {
38
+ onChange: onStatusChange,
39
+ label: "",
40
+ items: statusOptions,
41
+ selected: selectedStatus,
42
+ margin: "dense"
43
+ }
44
+ ));
45
+ };
46
+
47
+ export { StatusSelector, statusOptions };
48
+ //# sourceMappingURL=StatusSelector.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"StatusSelector.esm.js","sources":["../../../src/components/common/StatusSelector.tsx"],"sourcesContent":["/*\n * Copyright 2024 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport React from 'react';\n\nimport { Select, SelectedItems } from '@backstage/core-components';\n\nimport { makeStyles, Theme, Typography } from '@material-ui/core';\n\nimport './StatusSelector.css';\n\nimport { ComputedStatus } from '@janus-idp/shared-react';\n\nimport { TektonResourcesContext } from '../../hooks/TektonResourcesContext';\n\nconst useStyles = makeStyles<Theme>(theme => ({\n label: {\n color: theme.palette.text.primary,\n fontSize: '1rem',\n paddingRight: '10px',\n fontWeight: 'bold',\n },\n}));\n\nexport const statusOptions = Object.entries(ComputedStatus)\n .sort(([keyA], [keyB]) => {\n if (keyA === keyB) {\n return 0;\n } else if (keyA < keyB) {\n return -1;\n }\n return 1;\n })\n .map(([key, value]) => ({\n value: key,\n label: value,\n }));\n\nexport const StatusSelector = () => {\n const classes = useStyles();\n const { selectedStatus, setSelectedStatus } = React.useContext(\n TektonResourcesContext,\n );\n\n const onStatusChange = (status: SelectedItems) => {\n setSelectedStatus(status as ComputedStatus);\n };\n\n return (\n <div className=\"bs-tkn-status-selector\">\n <Typography className={classes.label}>Status</Typography>\n <Select\n onChange={onStatusChange}\n label=\"\"\n items={statusOptions}\n selected={selectedStatus}\n margin=\"dense\"\n />\n </div>\n );\n};\n"],"names":["React"],"mappings":";;;;;;;AA2BA,MAAM,SAAA,GAAY,WAAkB,CAAU,KAAA,MAAA;AAAA,EAC5C,KAAO,EAAA;AAAA,IACL,KAAA,EAAO,KAAM,CAAA,OAAA,CAAQ,IAAK,CAAA,OAAA;AAAA,IAC1B,QAAU,EAAA,MAAA;AAAA,IACV,YAAc,EAAA,MAAA;AAAA,IACd,UAAY,EAAA;AAAA;AAEhB,CAAE,CAAA,CAAA;AAEK,MAAM,aAAgB,GAAA,MAAA,CAAO,OAAQ,CAAA,cAAc,CACvD,CAAA,IAAA,CAAK,CAAC,CAAC,IAAI,CAAA,EAAG,CAAC,IAAI,CAAM,KAAA;AACxB,EAAA,IAAI,SAAS,IAAM,EAAA;AACjB,IAAO,OAAA,CAAA;AAAA,GACT,MAAA,IAAW,OAAO,IAAM,EAAA;AACtB,IAAO,OAAA,CAAA,CAAA;AAAA;AAET,EAAO,OAAA,CAAA;AACT,CAAC,EACA,GAAI,CAAA,CAAC,CAAC,GAAA,EAAK,KAAK,CAAO,MAAA;AAAA,EACtB,KAAO,EAAA,GAAA;AAAA,EACP,KAAO,EAAA;AACT,CAAE,CAAA;AAEG,MAAM,iBAAiB,MAAM;AAClC,EAAA,MAAM,UAAU,SAAU,EAAA;AAC1B,EAAA,MAAM,EAAE,cAAA,EAAgB,iBAAkB,EAAA,GAAIA,cAAM,CAAA,UAAA;AAAA,IAClD;AAAA,GACF;AAEA,EAAM,MAAA,cAAA,GAAiB,CAAC,MAA0B,KAAA;AAChD,IAAA,iBAAA,CAAkB,MAAwB,CAAA;AAAA,GAC5C;AAEA,EACE,uBAAAA,cAAA,CAAA,aAAA,CAAC,KAAI,EAAA,EAAA,SAAA,EAAU,wBACb,EAAA,kBAAAA,cAAA,CAAA,aAAA,CAAC,cAAW,SAAW,EAAA,OAAA,CAAQ,KAAO,EAAA,EAAA,QAAM,CAC5C,kBAAAA,cAAA,CAAA,aAAA;AAAA,IAAC,MAAA;AAAA,IAAA;AAAA,MACC,QAAU,EAAA,cAAA;AAAA,MACV,KAAM,EAAA,EAAA;AAAA,MACN,KAAO,EAAA,aAAA;AAAA,MACP,QAAU,EAAA,cAAA;AAAA,MACV,MAAO,EAAA;AAAA;AAAA,GAEX,CAAA;AAEJ;;;;"}
@@ -0,0 +1,44 @@
1
+ import React__default from 'react';
2
+ import { makeStyles, Tooltip, IconButton } from '@material-ui/core';
3
+ import Collapse from '@material-ui/icons/UnfoldLess';
4
+ import Expand from '@material-ui/icons/UnfoldMore';
5
+ import { TektonResourcesContext } from '../../hooks/TektonResourcesContext.esm.js';
6
+
7
+ const useStyles = makeStyles({
8
+ expandCollapse: {
9
+ flexGrow: 1,
10
+ textAlign: "end"
11
+ },
12
+ iconButton: {
13
+ padding: "2px"
14
+ }
15
+ });
16
+ const TableExpandCollapse = () => {
17
+ const classes = useStyles();
18
+ const { isExpanded, setIsExpanded } = React__default.useContext(
19
+ TektonResourcesContext
20
+ );
21
+ const handleExpandCollaspse = () => {
22
+ setIsExpanded(!isExpanded);
23
+ };
24
+ return /* @__PURE__ */ React__default.createElement("div", { className: classes.expandCollapse }, /* @__PURE__ */ React__default.createElement(Tooltip, { title: "Collapse all", placement: "top" }, /* @__PURE__ */ React__default.createElement("span", null, /* @__PURE__ */ React__default.createElement(
25
+ IconButton,
26
+ {
27
+ onClick: () => handleExpandCollaspse(),
28
+ disabled: !isExpanded,
29
+ className: classes.iconButton
30
+ },
31
+ /* @__PURE__ */ React__default.createElement(Collapse, null)
32
+ ))), /* @__PURE__ */ React__default.createElement(Tooltip, { title: "Expand all", placement: "top" }, /* @__PURE__ */ React__default.createElement("span", null, /* @__PURE__ */ React__default.createElement(
33
+ IconButton,
34
+ {
35
+ onClick: () => handleExpandCollaspse(),
36
+ disabled: isExpanded,
37
+ className: classes.iconButton
38
+ },
39
+ /* @__PURE__ */ React__default.createElement(Expand, null)
40
+ ))));
41
+ };
42
+
43
+ export { TableExpandCollapse };
44
+ //# sourceMappingURL=TableExpandCollapse.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TableExpandCollapse.esm.js","sources":["../../../src/components/common/TableExpandCollapse.tsx"],"sourcesContent":["/*\n * Copyright 2024 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport React from 'react';\n\nimport { IconButton, makeStyles, Tooltip } from '@material-ui/core';\nimport Collapse from '@material-ui/icons/UnfoldLess';\nimport Expand from '@material-ui/icons/UnfoldMore';\n\nimport { TektonResourcesContext } from '../../hooks/TektonResourcesContext';\n\nconst useStyles = makeStyles({\n expandCollapse: {\n flexGrow: 1,\n textAlign: 'end',\n },\n iconButton: {\n padding: '2px',\n },\n});\n\nexport const TableExpandCollapse = () => {\n const classes = useStyles();\n const { isExpanded, setIsExpanded } = React.useContext(\n TektonResourcesContext,\n );\n\n const handleExpandCollaspse = () => {\n setIsExpanded(!isExpanded);\n };\n return (\n <div className={classes.expandCollapse}>\n <Tooltip title=\"Collapse all\" placement=\"top\">\n <span>\n <IconButton\n onClick={() => handleExpandCollaspse()}\n disabled={!isExpanded}\n className={classes.iconButton}\n >\n <Collapse />\n </IconButton>\n </span>\n </Tooltip>\n <Tooltip title=\"Expand all\" placement=\"top\">\n <span>\n <IconButton\n onClick={() => handleExpandCollaspse()}\n disabled={isExpanded}\n className={classes.iconButton}\n >\n <Expand />\n </IconButton>\n </span>\n </Tooltip>\n </div>\n );\n};\n"],"names":["React"],"mappings":";;;;;;AAuBA,MAAM,YAAY,UAAW,CAAA;AAAA,EAC3B,cAAgB,EAAA;AAAA,IACd,QAAU,EAAA,CAAA;AAAA,IACV,SAAW,EAAA;AAAA,GACb;AAAA,EACA,UAAY,EAAA;AAAA,IACV,OAAS,EAAA;AAAA;AAEb,CAAC,CAAA;AAEM,MAAM,sBAAsB,MAAM;AACvC,EAAA,MAAM,UAAU,SAAU,EAAA;AAC1B,EAAA,MAAM,EAAE,UAAA,EAAY,aAAc,EAAA,GAAIA,cAAM,CAAA,UAAA;AAAA,IAC1C;AAAA,GACF;AAEA,EAAA,MAAM,wBAAwB,MAAM;AAClC,IAAA,aAAA,CAAc,CAAC,UAAU,CAAA;AAAA,GAC3B;AACA,EAAA,uBACGA,cAAA,CAAA,aAAA,CAAA,KAAA,EAAA,EAAI,SAAW,EAAA,OAAA,CAAQ,cACtB,EAAA,kBAAAA,cAAA,CAAA,aAAA,CAAC,OAAQ,EAAA,EAAA,KAAA,EAAM,cAAe,EAAA,SAAA,EAAU,KACtC,EAAA,kBAAAA,cAAA,CAAA,aAAA,CAAC,MACC,EAAA,IAAA,kBAAAA,cAAA,CAAA,aAAA;AAAA,IAAC,UAAA;AAAA,IAAA;AAAA,MACC,OAAA,EAAS,MAAM,qBAAsB,EAAA;AAAA,MACrC,UAAU,CAAC,UAAA;AAAA,MACX,WAAW,OAAQ,CAAA;AAAA,KAAA;AAAA,iDAElB,QAAS,EAAA,IAAA;AAAA,GAEd,CACF,CAAA,kBACCA,cAAA,CAAA,aAAA,CAAA,OAAA,EAAA,EAAQ,OAAM,YAAa,EAAA,SAAA,EAAU,KACpC,EAAA,kBAAAA,cAAA,CAAA,aAAA,CAAC,MACC,EAAA,IAAA,kBAAAA,cAAA,CAAA,aAAA;AAAA,IAAC,UAAA;AAAA,IAAA;AAAA,MACC,OAAA,EAAS,MAAM,qBAAsB,EAAA;AAAA,MACrC,QAAU,EAAA,UAAA;AAAA,MACV,WAAW,OAAQ,CAAA;AAAA,KAAA;AAAA,iDAElB,MAAO,EAAA,IAAA;AAAA,GAEZ,CACF,CACF,CAAA;AAEJ;;;;"}
@@ -0,0 +1,126 @@
1
+ import React__default from 'react';
2
+ import { Visualization, GRAPH_POSITION_CHANGE_EVENT, GRAPH_LAYOUT_END_EVENT, VisualizationProvider, TopologyView, VisualizationSurface, TopologyControlBar, createTopologyControlButtons, defaultControlButtonsOptions, action } from '@patternfly/react-topology';
3
+ import { DROP_SHADOW_SPACING, TOOLBAR_HEIGHT, GRAPH_MIN_WIDTH, NODE_HEIGHT } from '../../consts/pipeline-topology-const.esm.js';
4
+ import { getLayoutData } from '../../utils/pipeline-topology-utils.esm.js';
5
+ import pipelineComponentFactory, { layoutFactory } from './pipelineComponentFactory.esm.js';
6
+
7
+ const PipelineLayout = ({ model }) => {
8
+ const [vis, setVis] = React__default.useState(null);
9
+ const [maxSize, setMaxSize] = React__default.useState({ height: 0, width: 0 });
10
+ const storedGraphModel = React__default.useRef(null);
11
+ const layout = model.graph.layout;
12
+ const onLayoutUpdate = React__default.useCallback(
13
+ (nodes) => {
14
+ const nodeBounds = nodes.map(
15
+ (node) => node.getBounds()
16
+ );
17
+ const maxWidth = Math.floor(
18
+ nodeBounds.map((bounds) => bounds.width).reduce((w1, w2) => Math.max(w1, w2), 0)
19
+ );
20
+ const maxHeight = Math.floor(
21
+ nodeBounds.map((bounds) => bounds.height).reduce((h1, h2) => Math.max(h1, h2), 0)
22
+ );
23
+ const maxObject = nodeBounds.find((nb) => nb.height === maxHeight) ?? { y: 0 };
24
+ const maxX = Math.floor(
25
+ nodeBounds.map((bounds) => bounds.x).reduce((x1, x2) => Math.max(x1, x2), 0)
26
+ );
27
+ const maxY = Math.floor(
28
+ nodeBounds.map((bounds) => bounds.y).reduce((y1, y2) => Math.max(y1, y2), 0)
29
+ );
30
+ let horizontalMargin = 0;
31
+ let verticalMargin = 0;
32
+ if (layout) {
33
+ horizontalMargin = getLayoutData(layout)?.marginx || 0;
34
+ verticalMargin = getLayoutData(layout)?.marginy || 0;
35
+ }
36
+ const finallyTaskHeight = maxObject.y + maxHeight + DROP_SHADOW_SPACING + verticalMargin * 2;
37
+ const regularTaskHeight = maxY + NODE_HEIGHT + DROP_SHADOW_SPACING + verticalMargin * 2;
38
+ setMaxSize({
39
+ height: Math.max(finallyTaskHeight, regularTaskHeight) + TOOLBAR_HEIGHT,
40
+ width: Math.max(
41
+ maxX + maxWidth + DROP_SHADOW_SPACING + horizontalMargin * 2,
42
+ GRAPH_MIN_WIDTH
43
+ )
44
+ });
45
+ },
46
+ [setMaxSize, layout]
47
+ );
48
+ React__default.useEffect(() => {
49
+ if (model.graph.id !== storedGraphModel?.current?.id) {
50
+ storedGraphModel.current = null;
51
+ setVis(null);
52
+ }
53
+ }, [vis, model]);
54
+ React__default.useEffect(() => {
55
+ let mounted = true;
56
+ if (vis === null) {
57
+ const controller = new Visualization();
58
+ controller.registerLayoutFactory(layoutFactory);
59
+ controller.registerComponentFactory(pipelineComponentFactory);
60
+ controller.fromModel(model);
61
+ controller.addEventListener(GRAPH_POSITION_CHANGE_EVENT, () => {
62
+ storedGraphModel.current = controller.getGraph().toModel();
63
+ });
64
+ controller.addEventListener(GRAPH_LAYOUT_END_EVENT, () => {
65
+ onLayoutUpdate(controller.getGraph().getNodes());
66
+ });
67
+ if (mounted) {
68
+ setVis(controller);
69
+ }
70
+ } else {
71
+ const graph = storedGraphModel.current;
72
+ if (graph) {
73
+ model.graph = graph;
74
+ }
75
+ vis.fromModel(model);
76
+ vis.getGraph().layout();
77
+ }
78
+ return () => {
79
+ mounted = false;
80
+ };
81
+ }, [vis, model, onLayoutUpdate]);
82
+ React__default.useEffect(() => {
83
+ if (model && vis) {
84
+ const graph = storedGraphModel.current;
85
+ if (graph) {
86
+ model.graph = graph;
87
+ }
88
+ vis.fromModel(model);
89
+ }
90
+ }, [model, vis]);
91
+ if (!vis) return null;
92
+ const controlBar = (controller) => /* @__PURE__ */ React__default.createElement(
93
+ TopologyControlBar,
94
+ {
95
+ controlButtons: createTopologyControlButtons({
96
+ ...defaultControlButtonsOptions,
97
+ zoomInCallback: action(() => {
98
+ controller.getGraph().scaleBy(4 / 3);
99
+ }),
100
+ zoomOutCallback: action(() => {
101
+ controller.getGraph().scaleBy(0.75);
102
+ }),
103
+ fitToScreenCallback: action(() => {
104
+ controller.getGraph().fit(80);
105
+ }),
106
+ resetViewCallback: action(() => {
107
+ controller.getGraph().reset();
108
+ controller.getGraph().layout();
109
+ }),
110
+ legend: false
111
+ })
112
+ }
113
+ );
114
+ return /* @__PURE__ */ React__default.createElement(
115
+ "div",
116
+ {
117
+ style: {
118
+ height: Math.min(window.innerHeight, maxSize?.height)
119
+ }
120
+ },
121
+ /* @__PURE__ */ React__default.createElement(VisualizationProvider, { controller: vis }, /* @__PURE__ */ React__default.createElement(TopologyView, { controlBar: controlBar(vis) }, /* @__PURE__ */ React__default.createElement(VisualizationSurface, null)))
122
+ );
123
+ };
124
+
125
+ export { PipelineLayout };
126
+ //# sourceMappingURL=PipelineLayout.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PipelineLayout.esm.js","sources":["../../../src/components/pipeline-topology/PipelineLayout.tsx"],"sourcesContent":["/*\n * Copyright 2024 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport React from 'react';\n\nimport {\n action,\n Controller,\n createTopologyControlButtons,\n defaultControlButtonsOptions,\n EdgeModel,\n GRAPH_LAYOUT_END_EVENT,\n GRAPH_POSITION_CHANGE_EVENT,\n GraphModel,\n Node,\n NodeModel,\n Rect,\n TopologyControlBar,\n TopologyView,\n Visualization,\n VisualizationProvider,\n VisualizationSurface,\n} from '@patternfly/react-topology';\n\nimport {\n DROP_SHADOW_SPACING,\n GRAPH_MIN_WIDTH,\n NODE_HEIGHT,\n PipelineLayout as PipelineLayoutTypes,\n TOOLBAR_HEIGHT,\n} from '../../consts/pipeline-topology-const';\nimport { PipelineMixedNodeModel } from '../../types/pipeline-topology-types';\nimport { getLayoutData } from '../../utils/pipeline-topology-utils';\nimport pipelineComponentFactory, {\n layoutFactory,\n} from './pipelineComponentFactory';\n\ntype PipelineLayoutProps = {\n model: {\n graph: GraphModel;\n nodes: PipelineMixedNodeModel[];\n edges: EdgeModel[];\n };\n};\n\nexport const PipelineLayout = ({ model }: PipelineLayoutProps) => {\n const [vis, setVis] = React.useState<Controller | null>(null);\n const [maxSize, setMaxSize] = React.useState<{\n height: number;\n width: number;\n }>({ height: 0, width: 0 });\n const storedGraphModel = React.useRef<GraphModel | null>(null);\n\n const layout: PipelineLayoutTypes = model.graph.layout as PipelineLayoutTypes;\n\n const onLayoutUpdate = React.useCallback(\n (nodes: Node[]) => {\n const nodeBounds = nodes.map((node: Node<NodeModel, any>) =>\n node.getBounds(),\n );\n const maxWidth = Math.floor(\n nodeBounds\n .map((bounds: Rect) => bounds.width)\n .reduce((w1: number, w2: number) => Math.max(w1, w2), 0),\n );\n const maxHeight = Math.floor(\n nodeBounds\n .map((bounds: Rect) => bounds.height)\n .reduce((h1: number, h2: number) => Math.max(h1, h2), 0),\n );\n const maxObject =\n nodeBounds.find((nb: Rect) => nb.height === maxHeight) ??\n ({ y: 0 } as Rect);\n\n const maxX = Math.floor(\n nodeBounds\n .map((bounds: Rect) => bounds.x)\n .reduce((x1: number, x2: number) => Math.max(x1, x2), 0),\n );\n const maxY = Math.floor(\n nodeBounds\n .map((bounds: Rect) => bounds.y)\n .reduce((y1: number, y2: number) => Math.max(y1, y2), 0),\n );\n\n let horizontalMargin = 0;\n let verticalMargin = 0;\n if (layout) {\n horizontalMargin = getLayoutData(layout)?.marginx || 0;\n verticalMargin = getLayoutData(layout)?.marginy || 0;\n }\n const finallyTaskHeight =\n maxObject.y + maxHeight + DROP_SHADOW_SPACING + verticalMargin * 2;\n const regularTaskHeight =\n maxY + NODE_HEIGHT + DROP_SHADOW_SPACING + verticalMargin * 2;\n\n setMaxSize({\n height: Math.max(finallyTaskHeight, regularTaskHeight) + TOOLBAR_HEIGHT,\n width: Math.max(\n maxX + maxWidth + DROP_SHADOW_SPACING + horizontalMargin * 2,\n GRAPH_MIN_WIDTH,\n ),\n });\n },\n [setMaxSize, layout],\n );\n\n React.useEffect(() => {\n if (model.graph.id !== storedGraphModel?.current?.id) {\n storedGraphModel.current = null;\n setVis(null);\n }\n }, [vis, model]);\n\n React.useEffect(() => {\n let mounted = true;\n if (vis === null) {\n const controller = new Visualization();\n controller.registerLayoutFactory(layoutFactory);\n controller.registerComponentFactory(pipelineComponentFactory);\n controller.fromModel(model);\n controller.addEventListener(GRAPH_POSITION_CHANGE_EVENT, () => {\n storedGraphModel.current = controller.getGraph().toModel();\n });\n controller.addEventListener(GRAPH_LAYOUT_END_EVENT, () => {\n onLayoutUpdate(controller.getGraph().getNodes());\n });\n if (mounted) {\n setVis(controller);\n }\n } else {\n const graph = storedGraphModel.current;\n if (graph) {\n model.graph = graph;\n }\n vis.fromModel(model);\n vis.getGraph().layout();\n }\n return () => {\n mounted = false;\n };\n }, [vis, model, onLayoutUpdate]);\n\n React.useEffect(() => {\n if (model && vis) {\n const graph = storedGraphModel.current;\n if (graph) {\n model.graph = graph;\n }\n vis.fromModel(model);\n }\n }, [model, vis]);\n\n if (!vis) return null;\n\n const controlBar = (controller: Controller) => (\n <TopologyControlBar\n controlButtons={createTopologyControlButtons({\n ...defaultControlButtonsOptions,\n zoomInCallback: action(() => {\n controller.getGraph().scaleBy(4 / 3);\n }),\n zoomOutCallback: action(() => {\n controller.getGraph().scaleBy(0.75);\n }),\n fitToScreenCallback: action(() => {\n controller.getGraph().fit(80);\n }),\n resetViewCallback: action(() => {\n controller.getGraph().reset();\n controller.getGraph().layout();\n }),\n legend: false,\n })}\n />\n );\n\n return (\n <div\n style={{\n height: Math.min(window.innerHeight, maxSize?.height),\n }}\n >\n <VisualizationProvider controller={vis}>\n <TopologyView controlBar={controlBar(vis)}>\n <VisualizationSurface />\n </TopologyView>\n </VisualizationProvider>\n </div>\n );\n};\n"],"names":["React"],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ import React__default from 'react';
2
+ import { useDarkTheme } from '../../hooks/useDarkTheme.esm.js';
3
+ import { PipelineVisualizationView } from './PipelineVisualizationView.esm.js';
4
+
5
+ const PipelineRunVisualization = ({
6
+ pipelineRunName
7
+ }) => {
8
+ useDarkTheme();
9
+ return /* @__PURE__ */ React__default.createElement(React__default.Fragment, null, pipelineRunName && /* @__PURE__ */ React__default.createElement(PipelineVisualizationView, { pipelineRun: pipelineRunName }));
10
+ };
11
+
12
+ export { PipelineRunVisualization };
13
+ //# sourceMappingURL=PipelineRunVisualization.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PipelineRunVisualization.esm.js","sources":["../../../src/components/pipeline-topology/PipelineRunVisualization.tsx"],"sourcesContent":["/*\n * Copyright 2024 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport React from 'react';\n\nimport { useDarkTheme } from '../../hooks/useDarkTheme';\nimport { PipelineVisualizationView } from './PipelineVisualizationView';\n\ntype PipelineRunVisualizationProps = {\n pipelineRunName?: string;\n};\n\nexport const PipelineRunVisualization = ({\n pipelineRunName,\n}: PipelineRunVisualizationProps) => {\n useDarkTheme();\n\n return (\n <>\n {pipelineRunName && (\n <PipelineVisualizationView pipelineRun={pipelineRunName} />\n )}\n </>\n );\n};\n"],"names":["React"],"mappings":";;;;AAwBO,MAAM,2BAA2B,CAAC;AAAA,EACvC;AACF,CAAqC,KAAA;AACnC,EAAa,YAAA,EAAA;AAEb,EAAA,mFAEK,eACC,oBAAAA,cAAA,CAAA,aAAA,CAAC,yBAA0B,EAAA,EAAA,WAAA,EAAa,iBAAiB,CAE7D,CAAA;AAEJ;;;;"}
@@ -0,0 +1,7 @@
1
+ import styleInject from '../../node_modules/style-inject/dist/style-inject.es.esm.js';
2
+
3
+ var css_248z = ".bs-tkn-pipeline-task-node:focus {\n outline: -webkit-focus-ring-color auto 5px;\n}\n";
4
+ styleInject(css_248z);
5
+
6
+ export { css_248z as default };
7
+ //# sourceMappingURL=PipelineTaskNode.css.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PipelineTaskNode.css.esm.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;"}
@@ -0,0 +1,132 @@
1
+ import React__default from 'react';
2
+ import { Tooltip } from '@patternfly/react-core';
3
+ import { useHover, useDetailsLevel, RunStatus, WhenDecorator, DEFAULT_WHEN_OFFSET, TaskNode, ScaleDetailsLevel, Layer, TOP_LAYER, DEFAULT_LAYER } from '@patternfly/react-topology';
4
+ import { observer } from 'mobx-react';
5
+ import { NodeType } from '../../consts/pipeline-topology-const.esm.js';
6
+ import { TEKTON_PIPELINE_RUN, TEKTON_PIPELINE_TASK } from '../../consts/tekton-const.esm.js';
7
+ import { TektonResourcesContext } from '../../hooks/TektonResourcesContext.esm.js';
8
+ import { createStepStatus } from '../../utils/pipeline-step-utils.esm.js';
9
+ import { getTaskStatus } from '../../utils/pipelineRun-utils.esm.js';
10
+ import PipelineRunLogDialog from '../PipelineRunLogs/PipelineRunLogDialog.esm.js';
11
+ import { PipelineVisualizationStepList } from './PipelineVisualizationStepList.esm.js';
12
+ import './PipelineTaskNode.css.esm.js';
13
+
14
+ const PipelineTaskNode = ({
15
+ element,
16
+ onContextMenu,
17
+ contextMenuOpen,
18
+ ...rest
19
+ }) => {
20
+ const [open, setOpen] = React__default.useState(false);
21
+ const { watchResourcesData } = React__default.useContext(
22
+ TektonResourcesContext
23
+ );
24
+ const data = element.getData();
25
+ const triggerRef = React__default.useRef(null);
26
+ const pipelineRun = data.pipelineRun;
27
+ const [hover, hoverRef] = useHover();
28
+ const detailsLevel = useDetailsLevel();
29
+ const isFinallyTask = element.getType() === NodeType.FINALLY_NODE;
30
+ const pods = watchResourcesData?.pods?.data || [];
31
+ const taskRuns = watchResourcesData?.taskruns?.data || [];
32
+ const openDialog = () => {
33
+ setOpen(true);
34
+ };
35
+ const closeDialog = () => {
36
+ setOpen(false);
37
+ };
38
+ const computedTask = data.task;
39
+ const stepList = computedTask?.status?.steps || computedTask?.taskSpec?.steps || [];
40
+ const taskStatus = getTaskStatus(data.pipelineRun, data.task);
41
+ const stepStatusList = stepList.map(
42
+ (step) => createStepStatus(step, taskStatus)
43
+ );
44
+ const succeededStepsCount = stepStatusList.filter(
45
+ ({ status }) => status === RunStatus.Succeeded
46
+ ).length;
47
+ const badge = stepStatusList.length > 0 && data.status ? `${succeededStepsCount}/${stepStatusList.length}` : null;
48
+ const passedData = React__default.useMemo(() => {
49
+ const newData = { ...data };
50
+ Object.keys(newData).forEach((key) => {
51
+ if (newData[key] === void 0) {
52
+ delete newData[key];
53
+ }
54
+ });
55
+ return newData;
56
+ }, [data]);
57
+ const hasTaskIcon = !!(data.taskIconClass || data.taskIcon);
58
+ const whenDecorator = data.whenStatus ? /* @__PURE__ */ React__default.createElement(
59
+ WhenDecorator,
60
+ {
61
+ element,
62
+ status: data.whenStatus,
63
+ leftOffset: hasTaskIcon ? DEFAULT_WHEN_OFFSET + (element.getBounds().height - 4) * 0.75 : DEFAULT_WHEN_OFFSET
64
+ }
65
+ ) : null;
66
+ const activeTaskId = taskRuns.find(
67
+ (tr) => tr?.metadata?.labels?.[TEKTON_PIPELINE_RUN] === pipelineRun?.metadata?.name && tr?.metadata?.labels?.[TEKTON_PIPELINE_TASK] === data.task?.name
68
+ )?.metadata?.name;
69
+ const taskNode = /* @__PURE__ */ React__default.createElement(React__default.Fragment, null, /* @__PURE__ */ React__default.createElement(
70
+ PipelineRunLogDialog,
71
+ {
72
+ pipelineRun,
73
+ open,
74
+ closeDialog,
75
+ pods,
76
+ taskRuns,
77
+ activeTask: activeTaskId
78
+ }
79
+ ), /* @__PURE__ */ React__default.createElement(
80
+ TaskNode,
81
+ {
82
+ className: "bs-tkn-pipeline-task-node",
83
+ element,
84
+ onContextMenu: data.showContextMenu ? onContextMenu : void 0,
85
+ contextMenuOpen,
86
+ scaleNode: (hover || contextMenuOpen) && detailsLevel !== ScaleDetailsLevel.high,
87
+ hideDetailsAtMedium: true,
88
+ ...passedData,
89
+ ...rest,
90
+ badge,
91
+ truncateLength: element.getData()?.label?.length,
92
+ onSelect: activeTaskId && openDialog
93
+ },
94
+ whenDecorator
95
+ ));
96
+ return /* @__PURE__ */ React__default.createElement(
97
+ Layer,
98
+ {
99
+ id: detailsLevel !== ScaleDetailsLevel.high && (hover || contextMenuOpen) ? TOP_LAYER : DEFAULT_LAYER
100
+ },
101
+ /* @__PURE__ */ React__default.createElement(
102
+ "g",
103
+ {
104
+ "data-test": `task ${element.getLabel()}`,
105
+ className: "bs-tkn-pipeline-task-node",
106
+ ref: hoverRef
107
+ },
108
+ /* @__PURE__ */ React__default.createElement(
109
+ Tooltip,
110
+ {
111
+ position: "bottom",
112
+ enableFlip: false,
113
+ content: /* @__PURE__ */ React__default.createElement(
114
+ PipelineVisualizationStepList,
115
+ {
116
+ isSpecOverview: !data.status,
117
+ taskName: element.getLabel(),
118
+ steps: stepStatusList,
119
+ isFinallyTask
120
+ }
121
+ ),
122
+ triggerRef
123
+ },
124
+ /* @__PURE__ */ React__default.createElement("g", { ref: triggerRef }, taskNode)
125
+ )
126
+ )
127
+ );
128
+ };
129
+ var PipelineTaskNode$1 = React__default.memo(observer(PipelineTaskNode));
130
+
131
+ export { PipelineTaskNode$1 as default };
132
+ //# sourceMappingURL=PipelineTaskNode.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PipelineTaskNode.esm.js","sources":["../../../src/components/pipeline-topology/PipelineTaskNode.tsx"],"sourcesContent":["/*\n * Copyright 2024 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport React from 'react';\n\nimport { Tooltip } from '@patternfly/react-core';\nimport {\n DEFAULT_LAYER,\n DEFAULT_WHEN_OFFSET,\n GraphElement,\n Layer,\n Node,\n RunStatus,\n ScaleDetailsLevel,\n TaskNode,\n TOP_LAYER,\n useDetailsLevel,\n useHover,\n WhenDecorator,\n WithContextMenuProps,\n WithSelectionProps,\n} from '@patternfly/react-topology';\n// eslint-disable-next-line @backstage/no-undeclared-imports\nimport { observer } from 'mobx-react';\n\nimport { PipelineTaskWithStatus, TaskRunKind } from '@janus-idp/shared-react';\n\nimport { NodeType } from '../../consts/pipeline-topology-const';\nimport {\n TEKTON_PIPELINE_RUN,\n TEKTON_PIPELINE_TASK,\n} from '../../consts/tekton-const';\nimport { TektonResourcesContext } from '../../hooks/TektonResourcesContext';\nimport { StepStatus } from '../../types/taskRun';\nimport { TektonResourcesContextData } from '../../types/types';\nimport { createStepStatus } from '../../utils/pipeline-step-utils';\nimport { getTaskStatus } from '../../utils/pipelineRun-utils';\nimport PipelineRunLogDialog from '../PipelineRunLogs/PipelineRunLogDialog';\nimport { PipelineVisualizationStepList } from './PipelineVisualizationStepList';\n\nimport './PipelineTaskNode.css';\n\ntype PipelineTaskNodeProps = {\n element: Node;\n} & WithContextMenuProps &\n WithSelectionProps &\n GraphElement;\n\nconst PipelineTaskNode = ({\n element,\n onContextMenu,\n contextMenuOpen,\n ...rest\n}: PipelineTaskNodeProps) => {\n const [open, setOpen] = React.useState<boolean>(false);\n const { watchResourcesData } = React.useContext<TektonResourcesContextData>(\n TektonResourcesContext,\n );\n const data = element.getData();\n const triggerRef = React.useRef<SVGGElement | null>(null);\n\n const pipelineRun = data.pipelineRun;\n const [hover, hoverRef] = useHover();\n const detailsLevel = useDetailsLevel();\n const isFinallyTask = element.getType() === NodeType.FINALLY_NODE;\n\n const pods = watchResourcesData?.pods?.data || [];\n const taskRuns = watchResourcesData?.taskruns?.data || [];\n const openDialog = () => {\n setOpen(true);\n };\n\n const closeDialog = () => {\n setOpen(false);\n };\n\n const computedTask: PipelineTaskWithStatus = data.task;\n const stepList =\n computedTask?.status?.steps || computedTask?.taskSpec?.steps || [];\n\n const taskStatus = getTaskStatus(data.pipelineRun, data.task);\n\n const stepStatusList: StepStatus[] = stepList.map((step: { name: string }) =>\n createStepStatus(step, taskStatus),\n );\n const succeededStepsCount = stepStatusList.filter(\n ({ status }) => status === RunStatus.Succeeded,\n ).length;\n\n const badge =\n stepStatusList.length > 0 && data.status\n ? `${succeededStepsCount}/${stepStatusList.length}`\n : null;\n\n const passedData = React.useMemo(() => {\n const newData = { ...data };\n Object.keys(newData).forEach(key => {\n if (newData[key] === undefined) {\n delete newData[key];\n }\n });\n return newData;\n }, [data]);\n\n const hasTaskIcon = !!(data.taskIconClass || data.taskIcon);\n const whenDecorator = data.whenStatus ? (\n <WhenDecorator\n element={element}\n status={data.whenStatus}\n leftOffset={\n hasTaskIcon\n ? DEFAULT_WHEN_OFFSET + (element.getBounds().height - 4) * 0.75\n : DEFAULT_WHEN_OFFSET\n }\n />\n ) : null;\n const activeTaskId = taskRuns.find(\n (tr: TaskRunKind) =>\n tr?.metadata?.labels?.[TEKTON_PIPELINE_RUN] ===\n pipelineRun?.metadata?.name &&\n tr?.metadata?.labels?.[TEKTON_PIPELINE_TASK] === data.task?.name,\n )?.metadata?.name;\n\n const taskNode = (\n <>\n <PipelineRunLogDialog\n pipelineRun={pipelineRun}\n open={open}\n closeDialog={closeDialog}\n pods={pods}\n taskRuns={taskRuns}\n activeTask={activeTaskId}\n />\n <TaskNode\n className=\"bs-tkn-pipeline-task-node\"\n element={element}\n onContextMenu={data.showContextMenu ? onContextMenu : undefined}\n contextMenuOpen={contextMenuOpen}\n scaleNode={\n (hover || contextMenuOpen) && detailsLevel !== ScaleDetailsLevel.high\n }\n hideDetailsAtMedium\n {...passedData}\n {...rest}\n badge={badge}\n truncateLength={element.getData()?.label?.length}\n onSelect={activeTaskId && openDialog}\n >\n {whenDecorator}\n </TaskNode>\n </>\n );\n\n return (\n <Layer\n id={\n detailsLevel !== ScaleDetailsLevel.high && (hover || contextMenuOpen)\n ? TOP_LAYER\n : DEFAULT_LAYER\n }\n >\n <g\n data-test={`task ${element.getLabel()}`}\n className=\"bs-tkn-pipeline-task-node\"\n ref={hoverRef as React.LegacyRef<SVGGElement>}\n >\n <Tooltip\n position=\"bottom\"\n enableFlip={false}\n content={\n <PipelineVisualizationStepList\n isSpecOverview={!data.status}\n taskName={element.getLabel()}\n steps={stepStatusList}\n isFinallyTask={isFinallyTask}\n />\n }\n triggerRef={triggerRef}\n >\n <g ref={triggerRef}>{taskNode}</g>\n </Tooltip>\n </g>\n </Layer>\n );\n};\n\nexport default React.memo(observer(PipelineTaskNode));\n"],"names":["React"],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ import styleInject from '../../node_modules/style-inject/dist/style-inject.es.esm.js';
2
+
3
+ var css_248z = ".bs-tkn-pipeline-visualization__label {\n align-items: baseline;\n padding-bottom: var(--pf-v5-global--spacer--xs);\n}\n\n.bs-tkn-pipeline-visualization__label .badge {\n font-size: 17px;\n line-height: 20px;\n margin-right: 4px;\n min-width: 24px;\n padding: 0 7px;\n border-radius: 20px;\n color: var(--pf-v5-global--palette--white);\n display: inline-block;\n text-align: center;\n white-space: nowrap;\n width: 100%;\n}\n\n.bs-tkn-pipeline-visualization__layout .pf-topology-content {\n border-radius: 20px;\n}\n\n.bs-tkn-pipeline-visualization__layout .pf-topology-visualization-surface {\n font-size: 1rem;\n border-radius: 1rem;\n}\n";
4
+ styleInject(css_248z);
5
+
6
+ export { css_248z as default };
7
+ //# sourceMappingURL=PipelineVisualization.css.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PipelineVisualization.css.esm.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;"}
@@ -0,0 +1,24 @@
1
+ import React__default from 'react';
2
+ import { useDarkTheme } from '../../hooks/useDarkTheme.esm.js';
3
+ import { getGraphDataModel } from '../../utils/pipeline-topology-utils.esm.js';
4
+ import { PipelineLayout } from './PipelineLayout.esm.js';
5
+ import './PipelineVisualization.css.esm.js';
6
+
7
+ const PipelineVisualization = ({
8
+ pipelineRun,
9
+ taskRuns
10
+ }) => {
11
+ useDarkTheme();
12
+ const model = getGraphDataModel(pipelineRun ?? void 0, taskRuns ?? []);
13
+ return /* @__PURE__ */ React__default.createElement(React__default.Fragment, null, !model || model.nodes.length === 0 && model.edges.length === 0 ? /* @__PURE__ */ React__default.createElement("div", { "data-testid": "pipeline-no-tasks" }, "This Pipeline Run has no tasks to visualize") : /* @__PURE__ */ React__default.createElement(
14
+ "div",
15
+ {
16
+ "data-testid": "pipelineRun-visualization",
17
+ className: "bs-tkn-pipeline-visualization__layout"
18
+ },
19
+ /* @__PURE__ */ React__default.createElement(PipelineLayout, { model })
20
+ ));
21
+ };
22
+
23
+ export { PipelineVisualization };
24
+ //# sourceMappingURL=PipelineVisualization.esm.js.map