@kuadrant/kuadrant-backstage-plugin-frontend 0.2.0 → 0.3.0-aaa46b4

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 (198) hide show
  1. package/dist/api.esm.js +40 -2
  2. package/dist/api.esm.js.map +1 -1
  3. package/dist/components/ApiAccessCard/ApiAccessCard.esm.js +20 -85
  4. package/dist/components/ApiAccessCard/ApiAccessCard.esm.js.map +1 -1
  5. package/dist/components/ApiKeyApprovalPage/ApiKeyApprovalPageWithPermissions.esm.js +18 -0
  6. package/dist/components/ApiKeyApprovalPage/ApiKeyApprovalPageWithPermissions.esm.js.map +1 -0
  7. package/dist/components/ApiKeyApprovalPage/index.esm.js +1 -0
  8. package/dist/components/ApiKeyApprovalPage/index.esm.js.map +1 -1
  9. package/dist/components/ApiKeyDetailPage/ApiKeyDetailPage.esm.js +19 -60
  10. package/dist/components/ApiKeyDetailPage/ApiKeyDetailPage.esm.js.map +1 -1
  11. package/dist/components/ApiKeyManagementTab/ApiKeyManagementTab.esm.js +66 -113
  12. package/dist/components/ApiKeyManagementTab/ApiKeyManagementTab.esm.js.map +1 -1
  13. package/dist/components/ApiProductInfoCard/ApiProductInfoCard.esm.js +3 -2
  14. package/dist/components/ApiProductInfoCard/ApiProductInfoCard.esm.js.map +1 -1
  15. package/dist/components/ApprovalQueueTable/ApprovalQueueTable.esm.js +16 -15
  16. package/dist/components/ApprovalQueueTable/ApprovalQueueTable.esm.js.map +1 -1
  17. package/dist/components/CreateAPIProductDialog/CreateAPIProductDialog.esm.js +1 -7
  18. package/dist/components/CreateAPIProductDialog/CreateAPIProductDialog.esm.js.map +1 -1
  19. package/dist/components/EditAPIProductDialog/EditAPIProductDialog.esm.js +2 -3
  20. package/dist/components/EditAPIProductDialog/EditAPIProductDialog.esm.js.map +1 -1
  21. package/dist/components/KuadrantIcon/KuadrantIcon.esm.js +22 -0
  22. package/dist/components/KuadrantIcon/KuadrantIcon.esm.js.map +1 -0
  23. package/dist/components/KuadrantPage/ApiProductsPage.esm.js +5 -18
  24. package/dist/components/KuadrantPage/ApiProductsPage.esm.js.map +1 -1
  25. package/dist/components/MyApiKeysTable/MyApiKeysTable.esm.js +28 -138
  26. package/dist/components/MyApiKeysTable/MyApiKeysTable.esm.js.map +1 -1
  27. package/dist/components/PermissionGate/PermissionGate.esm.js +2 -2
  28. package/dist/components/PermissionGate/PermissionGate.esm.js.map +1 -1
  29. package/dist/components/RequestAccessDialog/RequestAccessDialog.esm.js +32 -18
  30. package/dist/components/RequestAccessDialog/RequestAccessDialog.esm.js.map +1 -1
  31. package/dist/components/SimpleRequestAccessDialog/SimpleRequestAccessDialog.esm.js +13 -2
  32. package/dist/components/SimpleRequestAccessDialog/SimpleRequestAccessDialog.esm.js.map +1 -1
  33. package/dist/components/icons.esm.js +11 -0
  34. package/dist/components/icons.esm.js.map +1 -0
  35. package/dist/index.d.ts +54 -6
  36. package/dist/index.esm.js +3 -1
  37. package/dist/index.esm.js.map +1 -1
  38. package/dist/plugin.esm.js +2 -10
  39. package/dist/plugin.esm.js.map +1 -1
  40. package/dist/utils/apikeys.esm.js +21 -0
  41. package/dist/utils/apikeys.esm.js.map +1 -0
  42. package/dist/utils/styles.esm.js +5 -2
  43. package/dist/utils/styles.esm.js.map +1 -1
  44. package/dist-scalprum/internal.plugin-kuadrant.7f1de85661b1b848af15.js +2 -0
  45. package/dist-scalprum/internal.plugin-kuadrant.7f1de85661b1b848af15.js.map +1 -0
  46. package/dist-scalprum/plugin-manifest.json +3 -3
  47. package/dist-scalprum/static/{1037.58dd29ad.chunk.js → 1037.25758556.chunk.js} +1 -1
  48. package/dist-scalprum/static/{1037.58dd29ad.chunk.js.map → 1037.25758556.chunk.js.map} +1 -1
  49. package/dist-scalprum/static/1340.7c4f4722.chunk.js +3 -0
  50. package/dist-scalprum/static/1340.7c4f4722.chunk.js.map +1 -0
  51. package/dist-scalprum/static/1719.52ca7daf.chunk.js +2 -0
  52. package/dist-scalprum/static/1719.52ca7daf.chunk.js.map +1 -0
  53. package/dist-scalprum/static/{1881.8221c002.chunk.js → 1931.f6a5edbb.chunk.js} +2 -2
  54. package/dist-scalprum/static/1931.f6a5edbb.chunk.js.map +1 -0
  55. package/dist-scalprum/static/20.b3a37d1d.chunk.js +3 -0
  56. package/dist-scalprum/static/20.b3a37d1d.chunk.js.map +1 -0
  57. package/dist-scalprum/static/2251.08f3db99.chunk.js +2 -0
  58. package/dist-scalprum/static/2251.08f3db99.chunk.js.map +1 -0
  59. package/dist-scalprum/static/2769.e09b0ab0.chunk.js +2 -0
  60. package/dist-scalprum/static/2769.e09b0ab0.chunk.js.map +1 -0
  61. package/dist-scalprum/static/2821.1ac360ec.chunk.js +2 -0
  62. package/dist-scalprum/static/2821.1ac360ec.chunk.js.map +1 -0
  63. package/dist-scalprum/static/2952.b54bd390.chunk.js +2 -0
  64. package/dist-scalprum/static/2952.b54bd390.chunk.js.map +1 -0
  65. package/dist-scalprum/static/2967.004a950e.chunk.js +2 -0
  66. package/dist-scalprum/static/2967.004a950e.chunk.js.map +1 -0
  67. package/dist-scalprum/static/3015.1fe097c2.chunk.js +3 -0
  68. package/dist-scalprum/static/3015.1fe097c2.chunk.js.LICENSE.txt +9 -0
  69. package/dist-scalprum/static/3015.1fe097c2.chunk.js.map +1 -0
  70. package/dist-scalprum/static/327.74ecd572.chunk.js +2 -0
  71. package/dist-scalprum/static/327.74ecd572.chunk.js.map +1 -0
  72. package/dist-scalprum/static/3657.882640ca.chunk.js +3 -0
  73. package/dist-scalprum/static/3657.882640ca.chunk.js.LICENSE.txt +8 -0
  74. package/dist-scalprum/static/3657.882640ca.chunk.js.map +1 -0
  75. package/dist-scalprum/static/3658.104704cc.chunk.js +2 -0
  76. package/dist-scalprum/static/3658.104704cc.chunk.js.map +1 -0
  77. package/dist-scalprum/static/{3897.ef4554b5.chunk.js → 3897.6e9c07c0.chunk.js} +1 -1
  78. package/dist-scalprum/static/{3897.ef4554b5.chunk.js.map → 3897.6e9c07c0.chunk.js.map} +1 -1
  79. package/dist-scalprum/static/3917.888fba36.chunk.js +2 -0
  80. package/dist-scalprum/static/3917.888fba36.chunk.js.map +1 -0
  81. package/dist-scalprum/static/3947.f5320e89.chunk.js +2 -0
  82. package/dist-scalprum/static/3947.f5320e89.chunk.js.map +1 -0
  83. package/dist-scalprum/static/{4083.488ff7a9.chunk.js → 4083.811c4e7a.chunk.js} +2 -2
  84. package/dist-scalprum/static/{4083.488ff7a9.chunk.js.map → 4083.811c4e7a.chunk.js.map} +1 -1
  85. package/dist-scalprum/static/438.4335b833.chunk.js +2 -0
  86. package/dist-scalprum/static/438.4335b833.chunk.js.map +1 -0
  87. package/dist-scalprum/static/4908.4f21d453.chunk.js +2 -0
  88. package/dist-scalprum/static/4908.4f21d453.chunk.js.map +1 -0
  89. package/dist-scalprum/static/{5010.6241b64f.chunk.js → 5010.4f67737b.chunk.js} +2 -2
  90. package/dist-scalprum/static/{5010.6241b64f.chunk.js.map → 5010.4f67737b.chunk.js.map} +1 -1
  91. package/dist-scalprum/static/5197.53535ff4.chunk.js +2 -0
  92. package/dist-scalprum/static/5197.53535ff4.chunk.js.map +1 -0
  93. package/dist-scalprum/static/5289.6c803140.chunk.js +2 -0
  94. package/dist-scalprum/static/5289.6c803140.chunk.js.map +1 -0
  95. package/dist-scalprum/static/5943.4e1dedc5.chunk.js +2 -0
  96. package/dist-scalprum/static/5943.4e1dedc5.chunk.js.map +1 -0
  97. package/dist-scalprum/static/6038.63d1f832.chunk.js +3 -0
  98. package/dist-scalprum/static/6038.63d1f832.chunk.js.LICENSE.txt +8 -0
  99. package/dist-scalprum/static/6038.63d1f832.chunk.js.map +1 -0
  100. package/dist-scalprum/static/{6272.b5645dc2.chunk.js → 6272.3ed14ea4.chunk.js} +1 -1
  101. package/dist-scalprum/static/{6272.b5645dc2.chunk.js.map → 6272.3ed14ea4.chunk.js.map} +1 -1
  102. package/dist-scalprum/static/6311.da1849d1.chunk.js +2 -0
  103. package/dist-scalprum/static/6311.da1849d1.chunk.js.map +1 -0
  104. package/dist-scalprum/static/635.f63679a5.chunk.js +3 -0
  105. package/dist-scalprum/static/635.f63679a5.chunk.js.map +1 -0
  106. package/dist-scalprum/static/6371.02375475.chunk.js +3 -0
  107. package/dist-scalprum/static/6371.02375475.chunk.js.LICENSE.txt +9 -0
  108. package/dist-scalprum/static/6371.02375475.chunk.js.map +1 -0
  109. package/dist-scalprum/static/{6386.2d20c412.chunk.js → 6386.5922f271.chunk.js} +3 -3
  110. package/dist-scalprum/static/{6386.2d20c412.chunk.js.map → 6386.5922f271.chunk.js.map} +1 -1
  111. package/dist-scalprum/static/6837.6252b97a.chunk.js +2 -0
  112. package/dist-scalprum/static/6837.6252b97a.chunk.js.map +1 -0
  113. package/dist-scalprum/static/{6972.e47ec97e.chunk.js → 6972.f22b9446.chunk.js} +1 -1
  114. package/dist-scalprum/static/{6972.e47ec97e.chunk.js.map → 6972.f22b9446.chunk.js.map} +1 -1
  115. package/dist-scalprum/static/7164.5dc4bc72.chunk.js +2 -0
  116. package/dist-scalprum/static/7164.5dc4bc72.chunk.js.map +1 -0
  117. package/dist-scalprum/static/{7266.e760b8c3.chunk.js → 7266.3c4174cc.chunk.js} +1 -1
  118. package/dist-scalprum/static/{7266.e760b8c3.chunk.js.map → 7266.3c4174cc.chunk.js.map} +1 -1
  119. package/dist-scalprum/static/7270.8ee9d452.chunk.js +2 -0
  120. package/dist-scalprum/static/7270.8ee9d452.chunk.js.map +1 -0
  121. package/dist-scalprum/static/{7791.8f84478d.chunk.js → 7791.ad31cf6d.chunk.js} +2 -2
  122. package/dist-scalprum/static/{7791.8f84478d.chunk.js.map → 7791.ad31cf6d.chunk.js.map} +1 -1
  123. package/dist-scalprum/static/{8563.46f1a3e1.chunk.js → 8563.6501eafb.chunk.js} +2 -2
  124. package/dist-scalprum/static/{8563.46f1a3e1.chunk.js.map → 8563.6501eafb.chunk.js.map} +1 -1
  125. package/dist-scalprum/static/980.744a4d36.chunk.js +2 -0
  126. package/dist-scalprum/static/980.744a4d36.chunk.js.map +1 -0
  127. package/dist-scalprum/static/exposed-KuadrantIcon.08abbb96.chunk.js +3 -0
  128. package/dist-scalprum/static/exposed-KuadrantIcon.08abbb96.chunk.js.LICENSE.txt +9 -0
  129. package/dist-scalprum/static/exposed-KuadrantIcon.08abbb96.chunk.js.map +1 -0
  130. package/dist-scalprum/static/exposed-KuadrantPage.f123b200.chunk.js +2 -0
  131. package/dist-scalprum/static/exposed-KuadrantPage.f123b200.chunk.js.map +1 -0
  132. package/dist-scalprum/static/exposed-PluginRoot.3a5f9157.chunk.js +2 -0
  133. package/dist-scalprum/static/exposed-PluginRoot.3a5f9157.chunk.js.map +1 -0
  134. package/package.json +6 -3
  135. package/dist/components/EntityApiApprovalTab/EntityApiApprovalTab.esm.js +0 -265
  136. package/dist/components/EntityApiApprovalTab/EntityApiApprovalTab.esm.js.map +0 -1
  137. package/dist/components/EntityApiApprovalTab/index.esm.js +0 -2
  138. package/dist/components/EntityApiApprovalTab/index.esm.js.map +0 -1
  139. package/dist-scalprum/internal.plugin-kuadrant.b3d35dc8b21ce867aa09.js +0 -2
  140. package/dist-scalprum/internal.plugin-kuadrant.b3d35dc8b21ce867aa09.js.map +0 -1
  141. package/dist-scalprum/static/1319.ac195ac2.chunk.js +0 -2
  142. package/dist-scalprum/static/1319.ac195ac2.chunk.js.map +0 -1
  143. package/dist-scalprum/static/1584.ae3779f0.chunk.js +0 -3
  144. package/dist-scalprum/static/1584.ae3779f0.chunk.js.map +0 -1
  145. package/dist-scalprum/static/1881.8221c002.chunk.js.map +0 -1
  146. package/dist-scalprum/static/2967.7c6a34cd.chunk.js +0 -2
  147. package/dist-scalprum/static/2967.7c6a34cd.chunk.js.map +0 -1
  148. package/dist-scalprum/static/3118.daee3324.chunk.js +0 -3
  149. package/dist-scalprum/static/3118.daee3324.chunk.js.map +0 -1
  150. package/dist-scalprum/static/3581.b5b97f08.chunk.js +0 -2
  151. package/dist-scalprum/static/3581.b5b97f08.chunk.js.map +0 -1
  152. package/dist-scalprum/static/369.2374941c.chunk.js +0 -2
  153. package/dist-scalprum/static/369.2374941c.chunk.js.map +0 -1
  154. package/dist-scalprum/static/3947.ad129ba4.chunk.js +0 -2
  155. package/dist-scalprum/static/3947.ad129ba4.chunk.js.map +0 -1
  156. package/dist-scalprum/static/3976.e0873210.chunk.js +0 -2
  157. package/dist-scalprum/static/3976.e0873210.chunk.js.map +0 -1
  158. package/dist-scalprum/static/4434.f92f6ba4.chunk.js +0 -2
  159. package/dist-scalprum/static/4434.f92f6ba4.chunk.js.map +0 -1
  160. package/dist-scalprum/static/483.d55d6ab2.chunk.js +0 -2
  161. package/dist-scalprum/static/483.d55d6ab2.chunk.js.map +0 -1
  162. package/dist-scalprum/static/512.f1c51799.chunk.js +0 -2
  163. package/dist-scalprum/static/512.f1c51799.chunk.js.map +0 -1
  164. package/dist-scalprum/static/5203.3df62d7e.chunk.js +0 -2
  165. package/dist-scalprum/static/5203.3df62d7e.chunk.js.map +0 -1
  166. package/dist-scalprum/static/5289.2e686027.chunk.js +0 -2
  167. package/dist-scalprum/static/5289.2e686027.chunk.js.map +0 -1
  168. package/dist-scalprum/static/5453.3c20d0a6.chunk.js +0 -2
  169. package/dist-scalprum/static/5453.3c20d0a6.chunk.js.map +0 -1
  170. package/dist-scalprum/static/6371.f183dddb.chunk.js +0 -3
  171. package/dist-scalprum/static/6371.f183dddb.chunk.js.map +0 -1
  172. package/dist-scalprum/static/6426.bf20c588.chunk.js +0 -2
  173. package/dist-scalprum/static/6426.bf20c588.chunk.js.map +0 -1
  174. package/dist-scalprum/static/6800.ddabed69.chunk.js +0 -2
  175. package/dist-scalprum/static/6800.ddabed69.chunk.js.map +0 -1
  176. package/dist-scalprum/static/7005.d548f8f1.chunk.js +0 -2
  177. package/dist-scalprum/static/7005.d548f8f1.chunk.js.map +0 -1
  178. package/dist-scalprum/static/7057.fcd688c7.chunk.js +0 -2
  179. package/dist-scalprum/static/7057.fcd688c7.chunk.js.map +0 -1
  180. package/dist-scalprum/static/7270.301a3c46.chunk.js +0 -2
  181. package/dist-scalprum/static/7270.301a3c46.chunk.js.map +0 -1
  182. package/dist-scalprum/static/9051.f095a8a1.chunk.js +0 -2
  183. package/dist-scalprum/static/9051.f095a8a1.chunk.js.map +0 -1
  184. package/dist-scalprum/static/9079.b6d5c19c.chunk.js +0 -2
  185. package/dist-scalprum/static/9079.b6d5c19c.chunk.js.map +0 -1
  186. package/dist-scalprum/static/9625.b0c6610a.chunk.js +0 -2
  187. package/dist-scalprum/static/9625.b0c6610a.chunk.js.map +0 -1
  188. package/dist-scalprum/static/9838.589f2156.chunk.js +0 -2
  189. package/dist-scalprum/static/9838.589f2156.chunk.js.map +0 -1
  190. package/dist-scalprum/static/exposed-PluginRoot.a8448fcc.chunk.js +0 -2
  191. package/dist-scalprum/static/exposed-PluginRoot.a8448fcc.chunk.js.map +0 -1
  192. /package/dist-scalprum/static/{1584.ae3779f0.chunk.js.LICENSE.txt → 1340.7c4f4722.chunk.js.LICENSE.txt} +0 -0
  193. /package/dist-scalprum/static/{3118.daee3324.chunk.js.LICENSE.txt → 20.b3a37d1d.chunk.js.LICENSE.txt} +0 -0
  194. /package/dist-scalprum/static/{4083.488ff7a9.chunk.js.LICENSE.txt → 4083.811c4e7a.chunk.js.LICENSE.txt} +0 -0
  195. /package/dist-scalprum/static/{5010.6241b64f.chunk.js.LICENSE.txt → 5010.4f67737b.chunk.js.LICENSE.txt} +0 -0
  196. /package/dist-scalprum/static/{6371.f183dddb.chunk.js.LICENSE.txt → 635.f63679a5.chunk.js.LICENSE.txt} +0 -0
  197. /package/dist-scalprum/static/{6386.2d20c412.chunk.js.LICENSE.txt → 6386.5922f271.chunk.js.LICENSE.txt} +0 -0
  198. /package/dist-scalprum/static/{8563.46f1a3e1.chunk.js.LICENSE.txt → 8563.6501eafb.chunk.js.LICENSE.txt} +0 -0
@@ -1 +0,0 @@
1
- {"version":3,"file":"static/6426.bf20c588.chunk.js","mappings":"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","sources":["webpack://internal.plugin-kuadrant/../../node_modules/@material-ui/lab/esm/Skeleton/Skeleton.js","webpack://internal.plugin-kuadrant/../../node_modules/react-use/lib/useAsyncFn.js","webpack://internal.plugin-kuadrant/../../node_modules/react-use/lib/useMountedState.js","webpack://internal.plugin-kuadrant/../../node_modules/@material-ui/icons/ExpandLess.js","webpack://internal.plugin-kuadrant/../../node_modules/@material-ui/icons/BrokenImage.js","webpack://internal.plugin-kuadrant/../../node_modules/@material-ui/icons/Visibility.js","webpack://internal.plugin-kuadrant/../../node_modules/@material-ui/icons/Delete.js","webpack://internal.plugin-kuadrant/./node_modules/@backstage/core-components/dist/hooks/useSupportConfig.esm.js","webpack://internal.plugin-kuadrant/./node_modules/@backstage/core-components/dist/icons/icons.esm.js","webpack://internal.plugin-kuadrant/./node_modules/@backstage/core-components/dist/components/SupportButton/SupportButton.esm.js","webpack://internal.plugin-kuadrant/../../node_modules/@material-ui/icons/VisibilityOff.js","webpack://internal.plugin-kuadrant/../../node_modules/@material-ui/icons/Warning.js","webpack://internal.plugin-kuadrant/../../node_modules/react-use/lib/useAsync.js"],"sourcesContent":["import _extends from \"@babel/runtime/helpers/esm/extends\";\nimport _objectWithoutProperties from \"@babel/runtime/helpers/esm/objectWithoutProperties\";\nimport * as React from 'react';\nimport clsx from 'clsx';\nimport PropTypes from 'prop-types';\nimport { alpha, withStyles } from '@material-ui/core/styles';\nexport var styles = function styles(theme) {\n return {\n /* Styles applied to the root element. */\n root: {\n display: 'block',\n // Create a \"on paper\" color with sufficient contrast retaining the color\n backgroundColor: alpha(theme.palette.text.primary, theme.palette.type === 'light' ? 0.11 : 0.13),\n height: '1.2em'\n },\n\n /* Styles applied to the root element if `variant=\"text\"`. */\n text: {\n marginTop: 0,\n marginBottom: 0,\n height: 'auto',\n transformOrigin: '0 60%',\n transform: 'scale(1, 0.60)',\n borderRadius: theme.shape.borderRadius,\n '&:empty:before': {\n content: '\"\\\\00a0\"'\n }\n },\n\n /* Styles applied to the root element if `variant=\"rect\"`. */\n rect: {},\n\n /* Styles applied to the root element if `variant=\"circle\"`. */\n circle: {\n borderRadius: '50%'\n },\n\n /* Styles applied to the root element if `animation=\"pulse\"`. */\n pulse: {\n animation: '$pulse 1.5s ease-in-out 0.5s infinite'\n },\n '@keyframes pulse': {\n '0%': {\n opacity: 1\n },\n '50%': {\n opacity: 0.4\n },\n '100%': {\n opacity: 1\n }\n },\n\n /* Styles applied to the root element if `animation=\"wave\"`. */\n wave: {\n position: 'relative',\n overflow: 'hidden',\n '&::after': {\n animation: '$wave 1.6s linear 0.5s infinite',\n background: \"linear-gradient(90deg, transparent, \".concat(theme.palette.action.hover, \", transparent)\"),\n content: '\"\"',\n position: 'absolute',\n transform: 'translateX(-100%)',\n // Avoid flash during server-side hydration\n bottom: 0,\n left: 0,\n right: 0,\n top: 0\n }\n },\n '@keyframes wave': {\n '0%': {\n transform: 'translateX(-100%)'\n },\n '60%': {\n // +0.5s of delay between each loop\n transform: 'translateX(100%)'\n },\n '100%': {\n transform: 'translateX(100%)'\n }\n },\n\n /* Styles applied when the component is passed children. */\n withChildren: {\n '& > *': {\n visibility: 'hidden'\n }\n },\n\n /* Styles applied when the component is passed children and no width. */\n fitContent: {\n maxWidth: 'fit-content'\n },\n\n /* Styles applied when the component is passed children and no height. */\n heightAuto: {\n height: 'auto'\n }\n };\n};\nvar Skeleton = /*#__PURE__*/React.forwardRef(function Skeleton(props, ref) {\n var _props$animation = props.animation,\n animation = _props$animation === void 0 ? 'pulse' : _props$animation,\n classes = props.classes,\n className = props.className,\n _props$component = props.component,\n Component = _props$component === void 0 ? 'span' : _props$component,\n height = props.height,\n _props$variant = props.variant,\n variant = _props$variant === void 0 ? 'text' : _props$variant,\n width = props.width,\n other = _objectWithoutProperties(props, [\"animation\", \"classes\", \"className\", \"component\", \"height\", \"variant\", \"width\"]);\n\n var hasChildren = Boolean(other.children);\n return /*#__PURE__*/React.createElement(Component, _extends({\n ref: ref,\n className: clsx(classes.root, classes[variant], className, hasChildren && [classes.withChildren, !width && classes.fitContent, !height && classes.heightAuto], animation !== false && classes[animation])\n }, other, {\n style: _extends({\n width: width,\n height: height\n }, other.style)\n }));\n});\nprocess.env.NODE_ENV !== \"production\" ? Skeleton.propTypes = {\n /**\n * The animation.\n * If `false` the animation effect is disabled.\n */\n animation: PropTypes.oneOf(['pulse', 'wave', false]),\n\n /**\n * Optional children to infer width and height from.\n */\n children: PropTypes.node,\n\n /**\n * Override or extend the styles applied to the component.\n * See [CSS API](#css) below for more details.\n */\n classes: PropTypes.object.isRequired,\n\n /**\n * @ignore\n */\n className: PropTypes.string,\n\n /**\n * The component used for the root node.\n * Either a string to use a HTML element or a component.\n */\n component: PropTypes\n /* @typescript-to-proptypes-ignore */\n .elementType,\n\n /**\n * Height of the skeleton.\n * Useful when you don't want to adapt the skeleton to a text element but for instance a card.\n */\n height: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),\n\n /**\n * The type of content that will be rendered.\n */\n variant: PropTypes.oneOf(['text', 'rect', 'circle']),\n\n /**\n * Width of the skeleton.\n * Useful when the skeleton is inside an inline element with no width of its own.\n */\n width: PropTypes.oneOfType([PropTypes.number, PropTypes.string])\n} : void 0;\nexport default withStyles(styles, {\n name: 'MuiSkeleton'\n})(Skeleton);","\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nvar tslib_1 = require(\"tslib\");\nvar react_1 = require(\"react\");\nvar useMountedState_1 = tslib_1.__importDefault(require(\"./useMountedState\"));\nfunction useAsyncFn(fn, deps, initialState) {\n if (deps === void 0) { deps = []; }\n if (initialState === void 0) { initialState = { loading: false }; }\n var lastCallId = react_1.useRef(0);\n var isMounted = useMountedState_1.default();\n var _a = react_1.useState(initialState), state = _a[0], set = _a[1];\n var callback = react_1.useCallback(function () {\n var args = [];\n for (var _i = 0; _i < arguments.length; _i++) {\n args[_i] = arguments[_i];\n }\n var callId = ++lastCallId.current;\n if (!state.loading) {\n set(function (prevState) { return (tslib_1.__assign(tslib_1.__assign({}, prevState), { loading: true })); });\n }\n return fn.apply(void 0, args).then(function (value) {\n isMounted() && callId === lastCallId.current && set({ value: value, loading: false });\n return value;\n }, function (error) {\n isMounted() && callId === lastCallId.current && set({ error: error, loading: false });\n return error;\n });\n }, deps);\n return [state, callback];\n}\nexports.default = useAsyncFn;\n","\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nvar react_1 = require(\"react\");\nfunction useMountedState() {\n var mountedRef = react_1.useRef(false);\n var get = react_1.useCallback(function () { return mountedRef.current; }, []);\n react_1.useEffect(function () {\n mountedRef.current = true;\n return function () {\n mountedRef.current = false;\n };\n }, []);\n return get;\n}\nexports.default = useMountedState;\n","\"use strict\";\n\nvar _interopRequireDefault = require(\"@babel/runtime/helpers/interopRequireDefault\");\n\nvar _interopRequireWildcard = require(\"@babel/runtime/helpers/interopRequireWildcard\");\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\nexports.default = void 0;\n\nvar React = _interopRequireWildcard(require(\"react\"));\n\nvar _createSvgIcon = _interopRequireDefault(require(\"./utils/createSvgIcon\"));\n\nvar _default = (0, _createSvgIcon.default)( /*#__PURE__*/React.createElement(\"path\", {\n d: \"M12 8l-6 6 1.41 1.41L12 10.83l4.59 4.58L18 14z\"\n}), 'ExpandLess');\n\nexports.default = _default;","\"use strict\";\n\nvar _interopRequireDefault = require(\"@babel/runtime/helpers/interopRequireDefault\");\n\nvar _interopRequireWildcard = require(\"@babel/runtime/helpers/interopRequireWildcard\");\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\nexports.default = void 0;\n\nvar React = _interopRequireWildcard(require(\"react\"));\n\nvar _createSvgIcon = _interopRequireDefault(require(\"./utils/createSvgIcon\"));\n\nvar _default = (0, _createSvgIcon.default)( /*#__PURE__*/React.createElement(\"path\", {\n d: \"M21 5v6.59l-3-3.01-4 4.01-4-4-4 4-3-3.01V5c0-1.1.9-2 2-2h14c1.1 0 2 .9 2 2zm-3 6.42l3 3.01V19c0 1.1-.9 2-2 2H5c-1.1 0-2-.9-2-2v-6.58l3 2.99 4-4 4 4 4-3.99z\"\n}), 'BrokenImage');\n\nexports.default = _default;","\"use strict\";\n\nvar _interopRequireDefault = require(\"@babel/runtime/helpers/interopRequireDefault\");\n\nvar _interopRequireWildcard = require(\"@babel/runtime/helpers/interopRequireWildcard\");\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\nexports.default = void 0;\n\nvar React = _interopRequireWildcard(require(\"react\"));\n\nvar _createSvgIcon = _interopRequireDefault(require(\"./utils/createSvgIcon\"));\n\nvar _default = (0, _createSvgIcon.default)( /*#__PURE__*/React.createElement(\"path\", {\n d: \"M12 4.5C7 4.5 2.73 7.61 1 12c1.73 4.39 6 7.5 11 7.5s9.27-3.11 11-7.5c-1.73-4.39-6-7.5-11-7.5zM12 17c-2.76 0-5-2.24-5-5s2.24-5 5-5 5 2.24 5 5-2.24 5-5 5zm0-8c-1.66 0-3 1.34-3 3s1.34 3 3 3 3-1.34 3-3-1.34-3-3-3z\"\n}), 'Visibility');\n\nexports.default = _default;","\"use strict\";\n\nvar _interopRequireDefault = require(\"@babel/runtime/helpers/interopRequireDefault\");\n\nvar _interopRequireWildcard = require(\"@babel/runtime/helpers/interopRequireWildcard\");\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\nexports.default = void 0;\n\nvar React = _interopRequireWildcard(require(\"react\"));\n\nvar _createSvgIcon = _interopRequireDefault(require(\"./utils/createSvgIcon\"));\n\nvar _default = (0, _createSvgIcon.default)( /*#__PURE__*/React.createElement(\"path\", {\n d: \"M6 19c0 1.1.9 2 2 2h8c1.1 0 2-.9 2-2V7H6v12zM19 4h-3.5l-1-1h-5l-1 1H5v2h14V4z\"\n}), 'Delete');\n\nexports.default = _default;","import { useApiHolder, configApiRef } from '@backstage/core-plugin-api';\nimport { coreComponentsTranslationRef } from '../translation.esm.js';\nimport { useTranslationRef } from '@backstage/core-plugin-api/alpha';\n\nconst useDefaultSupportConfig = () => {\n const { t } = useTranslationRef(coreComponentsTranslationRef);\n return {\n url: \"https://github.com/backstage/backstage/issues\",\n items: [\n {\n title: t(\"supportConfig.default.title\"),\n icon: \"warning\",\n links: [\n {\n // TODO: Update to dedicated support page on backstage.io/docs\n title: t(\"supportConfig.default.linkTitle\"),\n url: \"https://github.com/backstage/backstage/blob/master/app-config.yaml\"\n }\n ]\n }\n ]\n };\n};\nfunction useSupportConfig() {\n const apiHolder = useApiHolder();\n const config = apiHolder.get(configApiRef);\n const supportConfig = config?.getOptionalConfig(\"app.support\");\n const defaultSupportConfig = useDefaultSupportConfig();\n if (!supportConfig) {\n return defaultSupportConfig;\n }\n return {\n url: supportConfig.getString(\"url\"),\n items: supportConfig.getConfigArray(\"items\").flatMap((itemConf) => ({\n title: itemConf.getString(\"title\"),\n icon: itemConf.getOptionalString(\"icon\"),\n links: (itemConf.getOptionalConfigArray(\"links\") ?? []).flatMap(\n (linkConf) => ({\n url: linkConf.getString(\"url\"),\n title: linkConf.getOptionalString(\"title\") ?? \"\"\n })\n )\n }))\n };\n}\n\nexport { useSupportConfig };\n//# sourceMappingURL=useSupportConfig.esm.js.map\n","import { jsx } from 'react/jsx-runtime';\nimport { useApp } from '@backstage/core-plugin-api';\nimport MuiBrokenImageIcon from '@material-ui/icons/BrokenImage';\n\nfunction AppIcon(props) {\n const { id: key, Fallback = MuiBrokenImageIcon, ...rest } = props;\n const app = useApp();\n const Icon = app.getSystemIcon(key) ?? Fallback;\n return /* @__PURE__ */ jsx(Icon, { ...rest });\n}\nfunction BrokenImageIcon(props) {\n return /* @__PURE__ */ jsx(AppIcon, { id: \"brokenImage\", ...props });\n}\nfunction CatalogIcon(props) {\n return /* @__PURE__ */ jsx(AppIcon, { id: \"catalog\", ...props });\n}\nfunction ChatIcon(props) {\n return /* @__PURE__ */ jsx(AppIcon, { id: \"chat\", ...props });\n}\nfunction DashboardIcon(props) {\n return /* @__PURE__ */ jsx(AppIcon, { id: \"dashboard\", ...props });\n}\nfunction DocsIcon(props) {\n return /* @__PURE__ */ jsx(AppIcon, { id: \"docs\", ...props });\n}\nfunction EmailIcon(props) {\n return /* @__PURE__ */ jsx(AppIcon, { id: \"email\", ...props });\n}\nfunction GitHubIcon(props) {\n return /* @__PURE__ */ jsx(AppIcon, { id: \"github\", ...props });\n}\nfunction GroupIcon(props) {\n return /* @__PURE__ */ jsx(AppIcon, { id: \"group\", ...props });\n}\nfunction HelpIcon(props) {\n return /* @__PURE__ */ jsx(AppIcon, { id: \"help\", ...props });\n}\nfunction UserIcon(props) {\n return /* @__PURE__ */ jsx(AppIcon, { id: \"user\", ...props });\n}\nfunction WarningIcon(props) {\n return /* @__PURE__ */ jsx(AppIcon, { id: \"warning\", ...props });\n}\nfunction StarIcon(props) {\n return /* @__PURE__ */ jsx(AppIcon, { id: \"star\", ...props });\n}\nfunction UnstarredIcon(props) {\n return /* @__PURE__ */ jsx(AppIcon, { id: \"unstarred\", ...props });\n}\n\nexport { AppIcon, BrokenImageIcon, CatalogIcon, ChatIcon, DashboardIcon, DocsIcon, EmailIcon, GitHubIcon, GroupIcon, HelpIcon, StarIcon, UnstarredIcon, UserIcon, WarningIcon };\n//# sourceMappingURL=icons.esm.js.map\n","import { jsxs, Fragment, jsx } from 'react/jsx-runtime';\nimport { useApi, configApiRef, useApp } from '@backstage/core-plugin-api';\nimport Box from '@material-ui/core/Box';\nimport Button from '@material-ui/core/Button';\nimport DialogActions from '@material-ui/core/DialogActions';\nimport IconButton from '@material-ui/core/IconButton';\nimport ListItemIcon from '@material-ui/core/ListItemIcon';\nimport ListItemText from '@material-ui/core/ListItemText';\nimport MenuItem from '@material-ui/core/MenuItem';\nimport MenuList from '@material-ui/core/MenuList';\nimport Popover from '@material-ui/core/Popover';\nimport { makeStyles } from '@material-ui/core/styles';\nimport Typography from '@material-ui/core/Typography';\nimport useMediaQuery from '@material-ui/core/useMediaQuery';\nimport { useState, Children } from 'react';\nimport 'lodash';\nimport 'qs';\nimport 'react-router-dom';\nimport '@react-hookz/web';\nimport { useSupportConfig } from '../../hooks/useSupportConfig.esm.js';\nimport { HelpIcon } from '../../icons/icons.esm.js';\nimport { Link } from '../Link/Link.esm.js';\nimport { coreComponentsTranslationRef } from '../../translation.esm.js';\nimport { useTranslationRef } from '@backstage/core-plugin-api/alpha';\n\nconst useStyles = makeStyles(\n {\n popoverList: {\n minWidth: 260,\n maxWidth: 400\n },\n menuItem: {\n whiteSpace: \"normal\"\n }\n },\n { name: \"BackstageSupportButton\" }\n);\nconst SupportIcon = ({ icon }) => {\n const app = useApp();\n const Icon = icon ? app.getSystemIcon(icon) ?? HelpIcon : HelpIcon;\n return /* @__PURE__ */ jsx(Icon, {});\n};\nconst SupportLink = ({ link }) => /* @__PURE__ */ jsx(Link, { to: link.url, children: link.title ?? link.url });\nconst SupportListItem = ({ item }) => {\n return /* @__PURE__ */ jsxs(MenuItem, { button: false, children: [\n /* @__PURE__ */ jsx(ListItemIcon, { children: /* @__PURE__ */ jsx(SupportIcon, { icon: item.icon }) }),\n /* @__PURE__ */ jsx(\n ListItemText,\n {\n primary: item.title,\n secondary: item.links?.reduce(\n (prev, link, idx) => [\n ...prev,\n idx > 0 && /* @__PURE__ */ jsx(\"br\", {}, idx),\n /* @__PURE__ */ jsx(SupportLink, { link }, link.url)\n ],\n []\n )\n }\n )\n ] });\n};\nfunction SupportButton(props) {\n const { t } = useTranslationRef(coreComponentsTranslationRef);\n const { title, items, children } = props;\n const { items: configItems } = useSupportConfig();\n const [popoverOpen, setPopoverOpen] = useState(false);\n const [anchorEl, setAnchorEl] = useState(null);\n const classes = useStyles();\n const supportConfig = useApi(configApiRef).getOptionalConfig(\"app.support\");\n const isSmallScreen = useMediaQuery(\n (theme) => theme.breakpoints.down(\"sm\")\n );\n const onClickHandler = (event) => {\n setAnchorEl(event.currentTarget);\n setPopoverOpen(true);\n };\n const popoverCloseHandler = () => {\n setPopoverOpen(false);\n };\n if (!supportConfig) {\n return null;\n }\n return /* @__PURE__ */ jsxs(Fragment, { children: [\n /* @__PURE__ */ jsx(Box, { display: \"flex\", ml: 1, children: isSmallScreen ? /* @__PURE__ */ jsx(\n IconButton,\n {\n color: \"primary\",\n size: \"small\",\n onClick: onClickHandler,\n \"data-testid\": \"support-button\",\n \"aria-label\": \"Support\",\n children: /* @__PURE__ */ jsx(HelpIcon, {})\n }\n ) : /* @__PURE__ */ jsx(\n Button,\n {\n \"data-testid\": \"support-button\",\n \"aria-label\": \"Support\",\n color: \"primary\",\n onClick: onClickHandler,\n startIcon: /* @__PURE__ */ jsx(HelpIcon, {}),\n children: t(\"supportButton.title\")\n }\n ) }),\n /* @__PURE__ */ jsxs(\n Popover,\n {\n \"data-testid\": \"support-button-popover\",\n open: popoverOpen,\n anchorEl,\n anchorOrigin: {\n vertical: \"bottom\",\n horizontal: \"right\"\n },\n transformOrigin: {\n vertical: \"top\",\n horizontal: \"right\"\n },\n onClose: popoverCloseHandler,\n children: [\n /* @__PURE__ */ jsxs(\n MenuList,\n {\n className: classes.popoverList,\n autoFocusItem: Boolean(anchorEl),\n children: [\n title && /* @__PURE__ */ jsx(\n MenuItem,\n {\n button: false,\n alignItems: \"flex-start\",\n className: classes.menuItem,\n children: /* @__PURE__ */ jsx(Typography, { variant: \"subtitle1\", children: title })\n }\n ),\n Children.map(children, (child, i) => /* @__PURE__ */ jsx(\n MenuItem,\n {\n button: false,\n alignItems: \"flex-start\",\n className: classes.menuItem,\n children: child\n },\n `child-${i}`\n )),\n (items ?? configItems).map((item, i) => /* @__PURE__ */ jsx(SupportListItem, { item }, `item-${i}`))\n ]\n }\n ),\n /* @__PURE__ */ jsx(DialogActions, { children: /* @__PURE__ */ jsx(\n Button,\n {\n color: \"primary\",\n onClick: popoverCloseHandler,\n \"aria-label\": \"Close\",\n children: t(\"supportButton.close\")\n }\n ) })\n ]\n }\n )\n ] });\n}\n\nexport { SupportButton };\n//# sourceMappingURL=SupportButton.esm.js.map\n","\"use strict\";\n\nvar _interopRequireDefault = require(\"@babel/runtime/helpers/interopRequireDefault\");\n\nvar _interopRequireWildcard = require(\"@babel/runtime/helpers/interopRequireWildcard\");\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\nexports.default = void 0;\n\nvar React = _interopRequireWildcard(require(\"react\"));\n\nvar _createSvgIcon = _interopRequireDefault(require(\"./utils/createSvgIcon\"));\n\nvar _default = (0, _createSvgIcon.default)( /*#__PURE__*/React.createElement(\"path\", {\n d: \"M12 7c2.76 0 5 2.24 5 5 0 .65-.13 1.26-.36 1.83l2.92 2.92c1.51-1.26 2.7-2.89 3.43-4.75-1.73-4.39-6-7.5-11-7.5-1.4 0-2.74.25-3.98.7l2.16 2.16C10.74 7.13 11.35 7 12 7zM2 4.27l2.28 2.28.46.46C3.08 8.3 1.78 10.02 1 12c1.73 4.39 6 7.5 11 7.5 1.55 0 3.03-.3 4.38-.84l.42.42L19.73 22 21 20.73 3.27 3 2 4.27zM7.53 9.8l1.55 1.55c-.05.21-.08.43-.08.65 0 1.66 1.34 3 3 3 .22 0 .44-.03.65-.08l1.55 1.55c-.67.33-1.41.53-2.2.53-2.76 0-5-2.24-5-5 0-.79.2-1.53.53-2.2zm4.31-.78l3.15 3.15.02-.16c0-1.66-1.34-3-3-3l-.17.01z\"\n}), 'VisibilityOff');\n\nexports.default = _default;","\"use strict\";\n\nvar _interopRequireDefault = require(\"@babel/runtime/helpers/interopRequireDefault\");\n\nvar _interopRequireWildcard = require(\"@babel/runtime/helpers/interopRequireWildcard\");\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\nexports.default = void 0;\n\nvar React = _interopRequireWildcard(require(\"react\"));\n\nvar _createSvgIcon = _interopRequireDefault(require(\"./utils/createSvgIcon\"));\n\nvar _default = (0, _createSvgIcon.default)( /*#__PURE__*/React.createElement(\"path\", {\n d: \"M1 21h22L12 2 1 21zm12-3h-2v-2h2v2zm0-4h-2v-4h2v4z\"\n}), 'Warning');\n\nexports.default = _default;","\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nvar tslib_1 = require(\"tslib\");\nvar react_1 = require(\"react\");\nvar useAsyncFn_1 = tslib_1.__importDefault(require(\"./useAsyncFn\"));\nfunction useAsync(fn, deps) {\n if (deps === void 0) { deps = []; }\n var _a = useAsyncFn_1.default(fn, deps, {\n loading: true,\n }), state = _a[0], callback = _a[1];\n react_1.useEffect(function () {\n callback();\n }, [callback]);\n return state;\n}\nexports.default = useAsync;\n"],"names":["Skeleton","props","ref","_props$animation","animation","classes","className","_props$component","component","Component","height","_props$variant","variant","width","other","hasChildren","Boolean","children","root","withChildren","fitContent","heightAuto","style","withStyles","theme","display","backgroundColor","alpha","palette","text","primary","type","marginTop","marginBottom","transformOrigin","transform","borderRadius","shape","content","rect","circle","pulse","opacity","wave","position","overflow","background","concat","action","hover","bottom","left","right","top","visibility","maxWidth","name","Object","defineProperty","exports","value","tslib_1","react_1","useMountedState_1","__importDefault","fn","deps","initialState","loading","lastCallId","useRef","isMounted","default","_a","useState","state","set","callback","useCallback","args","_i","arguments","length","callId","current","prevState","__assign","apply","then","error","mountedRef","get","useEffect","_interopRequireDefault","_interopRequireWildcard","React","_default","createElement","d","useDefaultSupportConfig","url","items","title","t","icon","links","AppIcon","id","key","Fallback","rest","Icon","useApp","getSystemIcon","jsx","HelpIcon","useStyles","makeStyles","popoverList","minWidth","menuItem","whiteSpace","SupportIcon","app","SupportLink","link","to","SupportListItem","item","jsxs","MenuItem","button","ListItemIcon","ListItemText","secondary","reduce","prev","idx","SupportButton","configItems","config","useApiHolder","configApiRef","supportConfig","getOptionalConfig","defaultSupportConfig","getString","getConfigArray","flatMap","itemConf","getOptionalString","getOptionalConfigArray","linkConf","useSupportConfig","popoverOpen","setPopoverOpen","anchorEl","setAnchorEl","useApi","isSmallScreen","useMediaQuery","breakpoints","down","onClickHandler","event","currentTarget","popoverCloseHandler","Fragment","Box","ml","IconButton","color","size","onClick","Button","startIcon","Popover","open","anchorOrigin","vertical","horizontal","onClose","MenuList","autoFocusItem","alignItems","Typography","Children","map","child","i","DialogActions","useAsyncFn_1"],"sourceRoot":""}
@@ -1,2 +0,0 @@
1
- "use strict";(self.webpackChunkinternal_plugin_kuadrant=self.webpackChunkinternal_plugin_kuadrant||[]).push([[6800],{25467:(e,t,r)=>{r.d(t,{tN:()=>s}),r(31085),r(22097);var n=r(15427);function s(){const e=(0,n.useVersionedContext)("entity-context");if(!e)throw new Error("Entity context is not available");const t=e.atVersion(1);if(!t)throw new Error("EntityContext v1 not available");if(!t.entity)throw new Error("useEntity hook is being called outside of an EntityLayout where the entity has not been loaded. If this is intentional, please use useAsyncEntity instead.");return{entity:t.entity}}(0,n.createVersionedContext)("entity-context")},46800:(e,t,r)=>{r.r(t),r.d(t,{EntityApiApprovalTab:()=>z});var n=r(31085),s=r(95478),a=r(25467),i=r(22097),o=r(64047),l=r(35015),d=r(42367),c=r(25010),p=r(34955),u=r(46205),h=r(58837),v=r(10394),A=r(72501),x=r(76891),g=r(61477),y=r(46805),m=r(16249),j=r(93453),f=r(64947),b=r(78467),q=r(67720),C=r(71677),w=r(29365),k=r(4387),P=r(55429),R=r(92399),I=r(46299);const T=(0,h.A)(e=>({useCasePanel:{padding:e.spacing(2),backgroundColor:e.palette.background.default},useCaseLabel:{fontWeight:600,marginBottom:e.spacing(1),color:e.palette.text.secondary,textTransform:"uppercase",fontSize:"0.75rem"}})),E=({request:e})=>{const t=T();return(0,n.jsxs)(v.A,{className:t.useCasePanel,onClick:e=>e.stopPropagation(),children:[(0,n.jsx)(A.A,{className:t.useCaseLabel,children:"Use Case"}),(0,n.jsx)(A.A,{variant:"body2",children:e.spec.useCase||"No use case provided"})]})},S=({open:e,request:t,action:r,processing:a,onClose:i,onConfirm:o})=>{const[l,d]=(0,s.useState)(""),c=()=>{d(""),i()},p="reject"===r,u=(null==t?void 0:t.metadata.name)||"",h=l===u;return(0,n.jsxs)(x.A,{open:e,onClose:a?void 0:c,maxWidth:"sm",fullWidth:!0,children:[(0,n.jsx)(g.A,{children:p?"Reject API key":"Approve API key"}),(0,n.jsx)(y.A,{children:t&&(0,n.jsxs)(n.Fragment,{children:[(0,n.jsxs)(A.A,{variant:"body2",paragraph:!0,children:[(0,n.jsx)("strong",{children:"Requester:"})," ",t.spec.requestedBy.userId]}),(0,n.jsxs)(A.A,{variant:"body2",paragraph:!0,children:[(0,n.jsx)("strong",{children:"Tier:"})," ",t.spec.planTier]}),t.spec.useCase&&(0,n.jsxs)(A.A,{variant:"body2",paragraph:!0,children:[(0,n.jsx)("strong",{children:"Use Case:"})," ",t.spec.useCase]}),p&&(0,n.jsx)(v.A,{mt:2,p:2,bgcolor:"error.light",borderRadius:1,children:(0,n.jsx)(A.A,{variant:"body2",children:"This action will permanently deny access. The user will need to submit a new request."})}),(0,n.jsx)(v.A,{mt:2,children:(0,n.jsx)(m.A,{fullWidth:!0,label:`Type "${u}" to confirm`,value:l,onChange:e=>d(e.target.value),disabled:a,autoFocus:!0})})]})}),(0,n.jsxs)(j.A,{children:[(0,n.jsx)(f.A,{onClick:c,disabled:a,children:"Cancel"}),(0,n.jsx)(f.A,{onClick:()=>{o(l),d("")},color:p?"secondary":"primary",variant:"contained",disabled:!h||a,startIcon:a?(0,n.jsx)(b.A,{size:16,color:"inherit"}):void 0,children:a?p?"Rejecting...":"Approving...":p?"Reject":"Approve"})]})]})},z=()=>{var e,t;const{entity:r}=(0,a.tN)(),h=(0,i.useApi)(o.s),x=(0,i.useApi)(i.identityApiRef),g=(0,i.useApi)(i.alertApiRef),y=(null===(e=r.metadata.annotations)||void 0===e?void 0:e["kuadrant.io/apiproduct"])||r.metadata.name,m=(null===(t=r.metadata.annotations)||void 0===t?void 0:t["kuadrant.io/namespace"])||"default",[j,f]=(0,s.useState)(0),[b,T]=(0,s.useState)({open:!1,request:null,action:"approve",processing:!1}),{allowed:z,loading:B,error:N}=(0,u.l)(p.KV),{value:W,loading:_,error:L}=(0,l.A)(async()=>{const e=(await x.getBackstageIdentity()).userEntityRef;return{requests:((await h.getRequests()).items||[]).filter(e=>{var t;return(null===(t=e.spec.apiProductRef)||void 0===t?void 0:t.name)===y&&e.metadata.namespace===m}),reviewedBy:e}},[h,x,y,m,j]);if(_||B)return(0,n.jsx)(v.A,{p:2,children:[...Array(5)].map((e,t)=>(0,n.jsx)(v.A,{p:2,children:(0,n.jsx)(k.A,{variant:"text",width:"100%"})},t))});if(L)return(0,n.jsx)(d._,{error:L});if(N)return(0,n.jsx)(v.A,{p:2,children:(0,n.jsxs)(A.A,{color:"error",children:["Unable to check permissions: ",N.message]})});if(!z)return(0,n.jsx)(v.A,{p:3,textAlign:"center",children:(0,n.jsx)(A.A,{variant:"body1",color:"textSecondary",children:"You don't have permission to view the approval queue for this API."})});const U=(null==W?void 0:W.requests)||[],V=U.filter(e=>{var t;return!(null===(t=e.status)||void 0===t?void 0:t.phase)||"Pending"===e.status.phase}),$=U.filter(e=>{var t;return"Approved"===(null===(t=e.status)||void 0===t?void 0:t.phase)}),D=U.filter(e=>{var t;return"Rejected"===(null===(t=e.status)||void 0===t?void 0:t.phase)}),F=[{title:"Requester",field:"spec.requestedBy.userId",render:e=>(0,n.jsx)(A.A,{variant:"body2",children:e.spec.requestedBy.userId})},{title:"Status",field:"status.phase",render:e=>{var t;const r=(null===(t=e.status)||void 0===t?void 0:t.phase)||"Pending",s="Approved"===r?"Active":r;return(0,n.jsx)(q.A,{label:s,size:"small",style:(0,I.uU)(r)})}},{title:"Tier",field:"spec.planTier",render:e=>(0,n.jsx)(q.A,{label:e.spec.planTier,size:"small",variant:"outlined"})},{title:"Requested",field:"metadata.creationTimestamp",render:e=>e.metadata.creationTimestamp?(0,n.jsx)(A.A,{variant:"body2",children:new Date(e.metadata.creationTimestamp).toLocaleDateString()}):(0,n.jsx)(A.A,{variant:"body2",children:"-"})},{title:"Actions",filtering:!1,render:e=>{var t;return"Pending"!==((null===(t=e.status)||void 0===t?void 0:t.phase)||"Pending")?null:(0,n.jsxs)(v.A,{display:"flex",style:{gap:4},children:[(0,n.jsx)(C.Ay,{title:"Approve",children:(0,n.jsx)(w.A,{size:"small",onClick:()=>{T({open:!0,request:e,action:"approve",processing:!1})},children:(0,n.jsx)(P.A,{color:"primary"})})}),(0,n.jsx)(C.Ay,{title:"Reject",children:(0,n.jsx)(w.A,{size:"small",onClick:()=>{T({open:!0,request:e,action:"reject",processing:!1})},children:(0,n.jsx)(R.A,{color:"error"})})})]})}}],K=[{render:e=>{var t;const r=e.rowData;return(null==r||null===(t=r.metadata)||void 0===t?void 0:t.name)?(0,n.jsx)(E,{request:r}):(0,n.jsx)(v.A,{})}}];return(0,n.jsxs)(v.A,{p:2,children:[(0,n.jsx)(v.A,{mb:2,children:(0,n.jsxs)(A.A,{variant:"body2",color:"textSecondary",children:[V.length," pending, ",$.length," approved,"," ",D.length," rejected"]})}),0===U.length?(0,n.jsx)(v.A,{p:3,textAlign:"center",children:(0,n.jsx)(A.A,{variant:"body1",color:"textSecondary",children:"No API keys for this API."})}):(0,n.jsx)(c.X,{options:{paging:U.length>10,pageSize:20,search:!0,filtering:!1,debounceInterval:300,toolbar:!0,emptyRowsWhenPaging:!1},columns:F,data:U.map(e=>({...e,id:e.metadata.name})),detailPanel:K}),(0,n.jsx)(S,{open:b.open,request:b.request,action:b.action,processing:b.processing,onClose:()=>T({open:!1,request:null,action:"approve",processing:!1}),onConfirm:async()=>{if(!b.request||!W)return;T(e=>({...e,processing:!0}));const e="approve"===b.action,t=e?(e,t,r)=>h.approveRequest(e,t,r):(e,t,r)=>h.rejectRequest(e,t,r);try{await t(b.request.metadata.namespace,b.request.metadata.name,W.reviewedBy),T({open:!1,request:null,action:"approve",processing:!1}),f(e=>e+1),g.post({message:"API key "+(e?"approved":"rejected"),severity:"success",display:"transient"})}catch(e){console.error(`Error ${b.action}ing request:`,e),T(e=>({...e,processing:!1}));const t=e instanceof Error?e.message:"unknown error occurred";g.post({message:`Failed to ${b.action} APIKey. ${t}`,severity:"error",display:"transient"})}}})]})}}}]);
2
- //# sourceMappingURL=6800.ddabed69.chunk.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"static/6800.ddabed69.chunk.js","mappings":"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","sources":["webpack://internal.plugin-kuadrant/./node_modules/@backstage/plugin-catalog-react/dist/hooks/useEntity.esm.js","webpack://internal.plugin-kuadrant/./src/components/EntityApiApprovalTab/EntityApiApprovalTab.tsx"],"sourcesContent":["import { jsx } from 'react/jsx-runtime';\nimport { stringifyEntityRef } from '@backstage/catalog-model';\nimport { AnalyticsContext } from '@backstage/core-plugin-api';\nimport { createVersionedContext, useVersionedContext, createVersionedValueMap } from '@backstage/version-bridge';\n\nconst NewEntityContext = createVersionedContext(\n \"entity-context\"\n);\nconst AsyncEntityProvider = (props) => {\n const { children, entity, loading, error, refresh } = props;\n const value = { entity, loading, error, refresh };\n return /* @__PURE__ */ jsx(NewEntityContext.Provider, { value: createVersionedValueMap({ 1: value }), children: /* @__PURE__ */ jsx(\n AnalyticsContext,\n {\n attributes: {\n ...entity ? { entityRef: stringifyEntityRef(entity) } : void 0\n },\n children\n }\n ) });\n};\nconst EntityProvider = (props) => /* @__PURE__ */ jsx(\n AsyncEntityProvider,\n {\n entity: props.entity,\n loading: !Boolean(props.entity),\n error: void 0,\n refresh: void 0,\n children: props.children\n }\n);\nfunction useEntity() {\n const versionedHolder = useVersionedContext(\n \"entity-context\"\n );\n if (!versionedHolder) {\n throw new Error(\"Entity context is not available\");\n }\n const value = versionedHolder.atVersion(1);\n if (!value) {\n throw new Error(\"EntityContext v1 not available\");\n }\n if (!value.entity) {\n throw new Error(\n \"useEntity hook is being called outside of an EntityLayout where the entity has not been loaded. If this is intentional, please use useAsyncEntity instead.\"\n );\n }\n return { entity: value.entity };\n}\nfunction useAsyncEntity() {\n const versionedHolder = useVersionedContext(\n \"entity-context\"\n );\n if (!versionedHolder) {\n throw new Error(\"Entity context is not available\");\n }\n const value = versionedHolder.atVersion(1);\n if (!value) {\n throw new Error(\"EntityContext v1 not available\");\n }\n const { entity, loading, error, refresh } = value;\n return { entity, loading, error, refresh };\n}\n\nexport { AsyncEntityProvider, EntityProvider, useAsyncEntity, useEntity };\n//# sourceMappingURL=useEntity.esm.js.map\n","import React, { useState } from \"react\";\nimport { useEntity } from \"@backstage/plugin-catalog-react\";\nimport {\n useApi,\n identityApiRef,\n alertApiRef,\n} from \"@backstage/core-plugin-api\";\nimport { kuadrantApiRef } from '../../api';\nimport { useAsync } from \"react-use\";\nimport {\n Table,\n TableColumn,\n ResponseErrorPanel,\n} from \"@backstage/core-components\";\nimport { kuadrantApiKeyApprovePermission } from \"../../permissions\";\nimport { useKuadrantPermission } from \"../../utils/permissions\";\nimport {\n Box,\n Typography,\n Chip,\n IconButton,\n Tooltip,\n Button,\n Dialog,\n DialogTitle,\n DialogContent,\n DialogActions,\n TextField,\n CircularProgress,\n makeStyles,\n} from \"@material-ui/core\";\nimport { Skeleton } from \"@material-ui/lab\";\nimport CheckCircleIcon from \"@material-ui/icons/CheckCircle\";\nimport CancelIcon from \"@material-ui/icons/Cancel\";\nimport { APIKey } from \"../../types/api-management\";\nimport { getApprovalQueueStatusChipStyle } from \"../../utils/styles\";\n\nconst useStyles = makeStyles((theme) => ({\n useCasePanel: {\n padding: theme.spacing(2),\n backgroundColor: theme.palette.background.default,\n },\n useCaseLabel: {\n fontWeight: 600,\n marginBottom: theme.spacing(1),\n color: theme.palette.text.secondary,\n textTransform: \"uppercase\",\n fontSize: \"0.75rem\",\n },\n}));\n\ninterface ExpandedRowProps {\n request: APIKey;\n}\n\nconst ExpandedRowContent = ({ request }: ExpandedRowProps) => {\n const classes = useStyles();\n\n return (\n <Box className={classes.useCasePanel} onClick={(e) => e.stopPropagation()}>\n <Typography className={classes.useCaseLabel}>Use Case</Typography>\n <Typography variant=\"body2\">\n {request.spec.useCase || \"No use case provided\"}\n </Typography>\n </Box>\n );\n};\n\ninterface ApprovalDialogProps {\n open: boolean;\n request: APIKey | null;\n action: \"approve\" | \"reject\";\n processing: boolean;\n onClose: () => void;\n onConfirm: (confirmText: string) => void;\n}\n\nconst ApprovalDialog = ({\n open,\n request,\n action,\n processing,\n onClose,\n onConfirm,\n}: ApprovalDialogProps) => {\n const [confirmText, setConfirmText] = useState(\"\");\n\n const handleClose = () => {\n setConfirmText(\"\");\n onClose();\n };\n\n const handleConfirm = () => {\n onConfirm(confirmText);\n setConfirmText(\"\");\n };\n\n const isReject = action === \"reject\";\n const expectedText = request?.metadata.name || \"\";\n const isConfirmValid = confirmText === expectedText;\n\n return (\n <Dialog\n open={open}\n onClose={processing ? undefined : handleClose}\n maxWidth=\"sm\"\n fullWidth\n >\n <DialogTitle>\n {isReject ? \"Reject API key\" : \"Approve API key\"}\n </DialogTitle>\n <DialogContent>\n {request && (\n <>\n <Typography variant=\"body2\" paragraph>\n <strong>Requester:</strong> {request.spec.requestedBy.userId}\n </Typography>\n <Typography variant=\"body2\" paragraph>\n <strong>Tier:</strong> {request.spec.planTier}\n </Typography>\n {request.spec.useCase && (\n <Typography variant=\"body2\" paragraph>\n <strong>Use Case:</strong> {request.spec.useCase}\n </Typography>\n )}\n {isReject && (\n <Box mt={2} p={2} bgcolor=\"error.light\" borderRadius={1}>\n <Typography variant=\"body2\">\n This action will permanently deny access. The user will need\n to submit a new request.\n </Typography>\n </Box>\n )}\n <Box mt={2}>\n <TextField\n fullWidth\n label={`Type \"${expectedText}\" to confirm`}\n value={confirmText}\n onChange={(e) => setConfirmText(e.target.value)}\n disabled={processing}\n autoFocus\n />\n </Box>\n </>\n )}\n </DialogContent>\n <DialogActions>\n <Button onClick={handleClose} disabled={processing}>\n Cancel\n </Button>\n <Button\n onClick={handleConfirm}\n color={isReject ? \"secondary\" : \"primary\"}\n variant=\"contained\"\n disabled={!isConfirmValid || processing}\n startIcon={\n processing ? (\n <CircularProgress size={16} color=\"inherit\" />\n ) : undefined\n }\n >\n {processing\n ? isReject\n ? \"Rejecting...\"\n : \"Approving...\"\n : isReject\n ? \"Reject\"\n : \"Approve\"}\n </Button>\n </DialogActions>\n </Dialog>\n );\n};\n\nexport const EntityApiApprovalTab = () => {\n const { entity } = useEntity();\n const kuadrantApi = useApi(kuadrantApiRef);\n const identityApi = useApi(identityApiRef);\n const alertApi = useApi(alertApiRef);\n\n const apiProductName =\n entity.metadata.annotations?.[\"kuadrant.io/apiproduct\"] ||\n entity.metadata.name;\n const namespace =\n entity.metadata.annotations?.[\"kuadrant.io/namespace\"] || \"default\";\n\n const [refresh, setRefresh] = useState(0);\n const [dialogState, setDialogState] = useState<{\n open: boolean;\n request: APIKey | null;\n action: \"approve\" | \"reject\";\n processing: boolean;\n }>({\n open: false,\n request: null,\n action: \"approve\",\n processing: false,\n });\n\n const {\n allowed: canApprove,\n loading: permissionLoading,\n error: permissionError,\n } = useKuadrantPermission(kuadrantApiKeyApprovePermission);\n\n const { value, loading, error } = useAsync(async () => {\n const identity = await identityApi.getBackstageIdentity();\n const reviewedBy = identity.userEntityRef;\n\n const data = await kuadrantApi.getRequests();\n const allRequests: APIKey[] = data.items || [];\n\n // filter to this API product only\n const filtered = allRequests.filter(\n (r) =>\n r.spec.apiProductRef?.name === apiProductName &&\n r.metadata.namespace === namespace,\n );\n\n return { requests: filtered, reviewedBy };\n }, [kuadrantApi, identityApi, apiProductName, namespace, refresh]);\n\n const handleApprove = (request: APIKey) => {\n setDialogState({\n open: true,\n request,\n action: \"approve\",\n processing: false,\n });\n };\n\n const handleReject = (request: APIKey) => {\n setDialogState({\n open: true,\n request,\n action: \"reject\",\n processing: false,\n });\n };\n\n const handleConfirm = async () => {\n if (!dialogState.request || !value) return;\n\n setDialogState((prev) => ({ ...prev, processing: true }));\n\n const isApprove = dialogState.action === \"approve\"\n const requestFn = isApprove\n ? (ns: string, n: string, r: string) => kuadrantApi.approveRequest(ns, n, r)\n : (ns: string, n: string, r: string) => kuadrantApi.rejectRequest(ns, n, r)\n\n try {\n await requestFn(dialogState.request.metadata.namespace, dialogState.request.metadata.name, value.reviewedBy);\n\n setDialogState({\n open: false,\n request: null,\n action: \"approve\",\n processing: false,\n });\n setRefresh((r) => r + 1);\n alertApi.post({\n message: `API key ${isApprove ? \"approved\" : \"rejected\"}`,\n severity: \"success\",\n display: \"transient\",\n });\n } catch (err) {\n console.error(`Error ${dialogState.action}ing request:`, err);\n setDialogState((prev) => ({ ...prev, processing: false }));\n const errorMessage = err instanceof Error ? err.message : \"unknown error occurred\";\n alertApi.post({\n message: `Failed to ${dialogState.action} APIKey. ${errorMessage}`,\n severity: 'error',\n display: 'transient',\n });\n }\n };\n\n if (loading || permissionLoading) {\n return (\n <Box p={2}>\n {[...Array(5)].map((_, i) => (\n <Box key={i} p={2}>\n <Skeleton variant=\"text\" width=\"100%\" />\n </Box>\n ))}\n </Box>\n );\n }\n\n if (error) {\n return <ResponseErrorPanel error={error} />;\n }\n\n if (permissionError) {\n return (\n <Box p={2}>\n <Typography color=\"error\">\n Unable to check permissions: {permissionError.message}\n </Typography>\n </Box>\n );\n }\n\n if (!canApprove) {\n return (\n <Box p={3} textAlign=\"center\">\n <Typography variant=\"body1\" color=\"textSecondary\">\n You don't have permission to view the approval queue for this API.\n </Typography>\n </Box>\n );\n }\n\n const requests = value?.requests || [];\n const pendingRequests = requests.filter(\n (r) => !r.status?.phase || r.status.phase === \"Pending\",\n );\n const approvedRequests = requests.filter(\n (r) => r.status?.phase === \"Approved\",\n );\n const rejectedRequests = requests.filter(\n (r) => r.status?.phase === \"Rejected\",\n );\n\n const columns: TableColumn<APIKey>[] = [\n {\n title: \"Requester\",\n field: \"spec.requestedBy.userId\",\n render: (row) => (\n <Typography variant=\"body2\">{row.spec.requestedBy.userId}</Typography>\n ),\n },\n {\n title: \"Status\",\n field: \"status.phase\",\n render: (row) => {\n const phase = row.status?.phase || \"Pending\";\n const label = phase === \"Approved\" ? \"Active\" : phase;\n return (\n <Chip label={label} size=\"small\" style={getApprovalQueueStatusChipStyle(phase)} />\n );\n },\n },\n {\n title: \"Tier\",\n field: \"spec.planTier\",\n render: (row) => (\n <Chip label={row.spec.planTier} size=\"small\" variant=\"outlined\" />\n ),\n },\n {\n title: \"Requested\",\n field: \"metadata.creationTimestamp\",\n render: (row) => {\n if (!row.metadata.creationTimestamp)\n return <Typography variant=\"body2\">-</Typography>;\n return (\n <Typography variant=\"body2\">\n {new Date(row.metadata.creationTimestamp).toLocaleDateString()}\n </Typography>\n );\n },\n },\n {\n title: \"Actions\",\n filtering: false,\n render: (row) => {\n const phase = row.status?.phase || \"Pending\";\n if (phase !== \"Pending\") return null;\n return (\n <Box display=\"flex\" style={{ gap: 4 }}>\n <Tooltip title=\"Approve\">\n <IconButton size=\"small\" onClick={() => handleApprove(row)}>\n <CheckCircleIcon color=\"primary\" />\n </IconButton>\n </Tooltip>\n <Tooltip title=\"Reject\">\n <IconButton size=\"small\" onClick={() => handleReject(row)}>\n <CancelIcon color=\"error\" />\n </IconButton>\n </Tooltip>\n </Box>\n );\n },\n },\n ];\n\n const detailPanelConfig = [\n {\n render: (data: any) => {\n const request = data.rowData as APIKey;\n if (!request?.metadata?.name) return <Box />;\n return <ExpandedRowContent request={request} />;\n },\n },\n ];\n\n return (\n <Box p={2}>\n <Box mb={2}>\n <Typography variant=\"body2\" color=\"textSecondary\">\n {pendingRequests.length} pending, {approvedRequests.length} approved,{\" \"}\n {rejectedRequests.length} rejected\n </Typography>\n </Box>\n\n {requests.length === 0 ? (\n <Box p={3} textAlign=\"center\">\n <Typography variant=\"body1\" color=\"textSecondary\">\n No API keys for this API.\n </Typography>\n </Box>\n ) : (\n <Table\n options={{\n paging: requests.length > 10,\n pageSize: 20,\n search: true,\n filtering: false,\n debounceInterval: 300,\n toolbar: true,\n emptyRowsWhenPaging: false,\n }}\n columns={columns}\n data={requests.map((item) => ({ ...item, id: item.metadata.name }))}\n detailPanel={detailPanelConfig}\n />\n )}\n\n <ApprovalDialog\n open={dialogState.open}\n request={dialogState.request}\n action={dialogState.action}\n processing={dialogState.processing}\n onClose={() =>\n setDialogState({\n open: false,\n request: null,\n action: \"approve\",\n processing: false,\n })\n }\n onConfirm={handleConfirm}\n />\n </Box>\n );\n};\n"],"names":["useEntity","versionedHolder","useVersionedContext","Error","value","atVersion","entity","createVersionedContext","useStyles","makeStyles","theme","useCasePanel","padding","spacing","backgroundColor","palette","background","default","useCaseLabel","fontWeight","marginBottom","color","text","secondary","textTransform","fontSize","ExpandedRowContent","request","classes","Box","className","onClick","e","stopPropagation","Typography","variant","spec","useCase","ApprovalDialog","open","action","processing","onClose","onConfirm","confirmText","setConfirmText","useState","handleClose","isReject","expectedText","metadata","name","isConfirmValid","Dialog","undefined","maxWidth","fullWidth","DialogTitle","DialogContent","paragraph","strong","requestedBy","userId","planTier","mt","p","bgcolor","borderRadius","TextField","label","onChange","target","disabled","autoFocus","DialogActions","Button","startIcon","CircularProgress","size","EntityApiApprovalTab","kuadrantApi","useApi","kuadrantApiRef","identityApi","identityApiRef","alertApi","alertApiRef","apiProductName","annotations","namespace","refresh","setRefresh","dialogState","setDialogState","allowed","canApprove","loading","permissionLoading","error","permissionError","useKuadrantPermission","kuadrantApiKeyApprovePermission","useAsync","async","reviewedBy","getBackstageIdentity","userEntityRef","requests","getRequests","items","filter","r","apiProductRef","Array","map","_","i","Skeleton","width","ResponseErrorPanel","message","textAlign","pendingRequests","status","phase","approvedRequests","rejectedRequests","columns","title","field","render","row","Chip","style","getApprovalQueueStatusChipStyle","creationTimestamp","Date","toLocaleDateString","filtering","display","gap","Tooltip","IconButton","CheckCircleIcon","CancelIcon","detailPanelConfig","data","rowData","mb","length","Table","options","paging","pageSize","search","debounceInterval","toolbar","emptyRowsWhenPaging","item","id","detailPanel","prev","isApprove","requestFn","ns","n","approveRequest","rejectRequest","post","severity","err","console","errorMessage"],"sourceRoot":""}
@@ -1,2 +0,0 @@
1
- "use strict";(self.webpackChunkinternal_plugin_kuadrant=self.webpackChunkinternal_plugin_kuadrant||[]).push([[7005],{12229:(e,t,a)=>{a.d(t,{Z:()=>A});var s=a(31085),n=a(95478),l=a.n(n),i=a(10394),r=a(72501),o=a(64947),c=a(37197),d=a(69621),u=a(12981),p=a(86901),m=a(69076),h=a(58837),v=a(6924),g=a(23164);const x=(0,h.A)(e=>({root:{width:240,minWidth:240,padding:e.spacing(2),borderRight:`1px solid ${e.palette.divider}`,backgroundColor:e.palette.background.paper,height:"100%",overflowY:"auto"},sectionTitle:{fontWeight:600,fontSize:"0.75rem",textTransform:"uppercase",letterSpacing:"0.05em",color:e.palette.text.secondary,marginBottom:e.spacing(1),display:"flex",alignItems:"center",justifyContent:"space-between",cursor:"pointer",userSelect:"none"},filterSection:{marginBottom:e.spacing(2)},checkbox:{padding:e.spacing(.5)},checkboxLabel:{fontSize:"0.875rem"},clearButton:{marginTop:e.spacing(2)},count:{fontSize:"0.75rem",color:e.palette.text.secondary,marginLeft:e.spacing(1)}})),A=({sections:e,filters:t,onChange:a,onClear:n})=>{const h=x(),[A,y]=l().useState(new Set(e.filter(e=>e.collapsed).map(e=>e.id))),f=Object.values(t).some(e=>e.length>0);return(0,s.jsxs)(i.A,{className:h.root,children:[(0,s.jsxs)(i.A,{display:"flex",justifyContent:"space-between",alignItems:"center",mb:2,children:[(0,s.jsx)(r.A,{variant:"subtitle2",children:"Filters"}),f&&(0,s.jsx)(o.A,{size:"small",color:"primary",onClick:()=>{const t={};e.forEach(e=>{t[e.id]=[]}),a(t),null==n||n()},children:"Clear all"})]}),(0,s.jsx)(c.A,{}),e.map(e=>{const n=A.has(e.id),l=(t[e.id]||[]).length;return(0,s.jsxs)(i.A,{className:h.filterSection,mt:2,children:[(0,s.jsxs)(i.A,{className:h.sectionTitle,onClick:()=>{return t=e.id,void y(e=>{const a=new Set(e);return a.has(t)?a.delete(t):a.add(t),a});var t},children:[(0,s.jsxs)(i.A,{display:"flex",alignItems:"center",children:[(0,s.jsx)("span",{children:e.title}),l>0&&(0,s.jsxs)("span",{className:h.count,children:["(",l,")"]})]}),n?(0,s.jsx)(v.A,{fontSize:"small"}):(0,s.jsx)(g.A,{fontSize:"small"})]}),(0,s.jsx)(d.A,{in:!n,children:(0,s.jsx)(u.A,{children:e.options.map(n=>(0,s.jsx)(p.A,{control:(0,s.jsx)(m.A,{checked:(t[e.id]||[]).includes(n.value),onChange:()=>((e,s)=>{const n=t[e]||[],l=n.includes(s)?n.filter(e=>e!==s):[...n,s];a({...t,[e]:l})})(e.id,n.value),size:"small",className:h.checkbox,color:"primary"}),label:(0,s.jsxs)(i.A,{display:"flex",alignItems:"center",children:[(0,s.jsx)("span",{className:h.checkboxLabel,children:n.label}),void 0!==n.count&&(0,s.jsxs)("span",{className:h.count,children:["(",n.count,")"]})]})},n.value))})})]},e.id)})]})}},94251:(e,t,a)=>{a.r(t),a.d(t,{ApiProductsPage:()=>le});var s=a(31085),n=a(95478),l=a(58837),i=a(10394),r=a(67720),o=a(72501),c=a(64947),d=a(29365),u=a(78467),p=a(18466),m=a(39590),h=a(75625),v=a(21702),g=a(85142),x=a(12229),A=a(37725),y=a(289),f=a(15831),j=a(45210),b=a(46681),P=a(42367),S=a(25010),w=a(91638),C=a(22097),I=a(84692),k=a(64047),T=a(86687),N=a(46205);const R=({children:e,permission:t,fallback:a,errorMessage:n})=>{const{allowed:l,loading:r,error:c}=(0,N.l)(t);return r?(0,s.jsx)(T.k,{}):c?(0,s.jsxs)(i.A,{p:4,children:[(0,s.jsxs)(o.A,{color:"error",children:["Unable to check permissions: ",c.message]}),(0,s.jsx)(o.A,{variant:"body2",color:"textSecondary",children:"Please try again or contact your administrator"})]}):l?(0,s.jsx)(s.Fragment,{children:e}):a?(0,s.jsx)(s.Fragment,{children:a}):(0,s.jsxs)(i.A,{p:4,children:[(0,s.jsx)(o.A,{color:"textSecondary",children:n||"You don't have permission to view this page"}),(0,s.jsx)(i.A,{mt:1,children:(0,s.jsxs)(o.A,{variant:"caption",color:"textSecondary",children:["Required permission: ",t.name]})})]})};var z=a(76891),L=a(61477),D=a(46805),$=a(42899),H=a(16249),M=a(34839),W=a(71677),E=a(26343),K=a(95061),q=a(29635),B=a(86901),O=a(30285),F=a(93453),U=a(89031),_=a(48351),Y=a(86197),V=a(24170),Z=a(97859);const G=(0,l.A)(e=>({asterisk:{color:"#f44336"},sectionHeader:{display:"flex",alignItems:"center",gap:e.spacing(.5),marginTop:e.spacing(2),marginBottom:e.spacing(1)},infoIcon:{fontSize:18,color:e.palette.text.secondary},tagChip:{marginRight:e.spacing(.5),marginBottom:e.spacing(.5)}})),J=({open:e,onClose:t,onSuccess:a})=>{var l,m,h,v,g,x;const A=G(),y=(0,C.useApi)(k.s),[f,j]=(0,n.useState)(""),[b,P]=(0,n.useState)(""),[S,I]=(0,n.useState)(""),[T,N]=(0,n.useState)("v1"),[R,J]=(0,n.useState)("manual"),[X,Q]=(0,n.useState)("Published"),[ee,te]=(0,n.useState)("production"),[ae,se]=(0,n.useState)([]),[ne,le]=(0,n.useState)(""),[ie,re]=(0,n.useState)(""),[oe,ce]=(0,n.useState)(""),[de,ue]=(0,n.useState)(""),[pe,me]=(0,n.useState)(""),[he,ve]=(0,n.useState)(""),[ge,xe]=(0,n.useState)(""),[Ae,ye]=(0,n.useState)(!1),[fe,je]=(0,n.useState)(0),[be,Pe]=(0,n.useState)(null),[Se,we]=(0,n.useState)(null),[Ce,Ie]=(0,n.useState)(""),[ke,Te]=(0,n.useState)("name"),{value:Ne,loading:Re,error:ze}=(0,w.A)(async()=>(await y.getHttpRoutes()).items||[],[y,e,fe]),{value:Le,error:De}=(0,w.A)(async()=>await y.getPlanPolicies(),[y,e]),{value:$e,error:He}=(0,w.A)(async()=>await y.getAuthPolicies(),[y,e]),{value:Me,error:We}=(0,w.A)(async()=>await y.getRateLimitPolicies(),[y,e]),Ee=(e,t)=>(0,Z.d)(null==Le?void 0:Le.items,e,t),Ke=ie?ie.split("/"):null,qe=Ke?Ee(Ke[0],Ke[1]):null,Be=null==qe||null===(m=qe.status)||void 0===m||null===(l=m.conditions)||void 0===l?void 0:l.find(e=>"Accepted"===e.type),Oe=Ke?(Fe=Ke[0],Ue=Ke[1],(0,Z.d)(null==$e?void 0:$e.items,Fe,Ue)):null;var Fe,Ue;const _e=null==Oe||null===(v=Oe.status)||void 0===v||null===(h=v.conditions)||void 0===h?void 0:h.find(e=>"Accepted"===e.type),Ye=Ke?((e,t)=>(0,Z.d)(null==Me?void 0:Me.items,e,t))(Ke[0],Ke[1]):null,Ve=null==Ye||null===(x=Ye.status)||void 0===x||null===(g=x.conditions)||void 0===g?void 0:g.find(e=>"Accepted"===e.type),Ze={statusCondition:Be,discoveredPlans:null==qe?void 0:qe.spec.plans},Ge={namespacedName:{namespace:null==Oe?void 0:Oe.metadata.namespace,name:null==Oe?void 0:Oe.metadata.name},statusCondition:_e},Je={namespacedName:{namespace:null==Ye?void 0:Ye.metadata.namespace,name:null==Ye?void 0:Ye.metadata.name},statusCondition:Ve},Xe=(e,t)=>{const a=Ee(e,t);return a?`${a.metadata.name}${(e=>{var t;if(!(null==e||null===(t=e.spec)||void 0===t?void 0:t.plans))return"";const a=Object.entries(e.spec.plans).map(([e,t])=>{var a;const s=null==t||null===(a=t.limits)||void 0===a?void 0:a.requests;return s?`${e}: ${s.count}/${s.period}`:e}).join("; ");return a?` (${a})`:""})(a)}`:"N/A"};(0,n.useEffect)(()=>{e&&(Pe(null),we(null))},[e]);const Qe=()=>{ne.trim()&&!ae.includes(ne.trim())&&(se([...ae,ne.trim()]),le(""))},et=()=>{j(""),P(""),I(""),N("v1"),J("manual"),Q("Published"),te("production"),se([]),le(""),re(""),ce(""),ue(""),me(""),ve(""),xe(""),Pe(null),we(null),t()},tt=!!be||!!Se;return(0,s.jsxs)(z.A,{open:e,onClose:et,maxWidth:"md",fullWidth:!0,children:[(0,s.jsx)(L.A,{children:"Create API Product"}),(0,s.jsxs)(D.A,{children:[ge&&(0,s.jsx)(_.A,{severity:"error",style:{marginBottom:16},children:ge}),ze&&(0,s.jsxs)(_.A,{severity:"error",style:{marginBottom:16},children:[(0,s.jsx)("strong",{children:"Failed to load HTTPRoutes:"})," ",ze.message,(0,s.jsx)(i.A,{mt:1,children:(0,s.jsx)(c.A,{size:"small",variant:"outlined",onClick:()=>je(e=>e+1),children:"Retry"})})]}),De&&(0,s.jsxs)(_.A,{severity:"warning",style:{marginBottom:16},children:[(0,s.jsx)("strong",{children:"Failed to load PlanPolicies:"})," ",De.message,(0,s.jsx)(o.A,{variant:"body2",style:{marginTop:8},children:"You can still create the API Product, but plan information may be incomplete."})]}),He&&(0,s.jsxs)(_.A,{severity:"warning",style:{marginBottom:16},children:[(0,s.jsx)("strong",{children:"Failed to load AuthPolicies:"})," ",He.message]}),We&&(0,s.jsxs)(_.A,{severity:"warning",style:{marginBottom:16},children:[(0,s.jsx)("strong",{children:"Failed to load RateLimitPolicies:"})," ",We.message]}),(0,s.jsx)(i.A,{className:A.sectionHeader,children:(0,s.jsx)(o.A,{variant:"subtitle1",children:(0,s.jsx)("strong",{children:"API product info"})})}),(0,s.jsxs)($.A,{container:!0,spacing:2,children:[(0,s.jsx)($.A,{item:!0,xs:6,children:(0,s.jsx)(H.A,{fullWidth:!0,label:"API product name",value:b,onChange:e=>(e=>{if(P(e),!f||f.match(/-[a-f0-9]{6}$/)){const t=`${e.toLowerCase().replace(/[^a-z0-9-]/g,"-").replace(/-+/g,"-").replace(/^-|-$/g,"")}-${Math.floor(16777215*Math.random()).toString(16).padStart(6,"0")}`;j(t),Pe((0,V.o)(t))}})(e.target.value),placeholder:"My API",helperText:"Display name for your API product (shown to users)",margin:"normal",required:!0,disabled:Ae,InputLabelProps:{classes:{asterisk:A.asterisk}}})}),(0,s.jsx)($.A,{item:!0,xs:6,children:(0,s.jsx)(H.A,{fullWidth:!0,label:"Kubernetes resource name",value:f,onChange:e=>{return t=e.target.value,j(t),void Pe((0,V.o)(t));var t},placeholder:"my-api",helperText:be||"Auto-generated from product name. Only lowercase, numbers, and hyphens allowed.",error:!!be,margin:"normal",required:!0,disabled:Ae,InputLabelProps:{classes:{asterisk:A.asterisk}}})}),(0,s.jsx)($.A,{item:!0,xs:6,children:(0,s.jsx)(H.A,{fullWidth:!0,label:"Version",value:T,onChange:e=>N(e.target.value),placeholder:"v1",helperText:"Give a version to your API product",margin:"normal",required:!0,disabled:Ae,InputLabelProps:{classes:{asterisk:A.asterisk}}})}),(0,s.jsx)($.A,{item:!0,xs:6,children:(0,s.jsx)(H.A,{fullWidth:!0,label:"Tag",value:ne,onChange:e=>le(e.target.value),onKeyPress:e=>{"Enter"===e.key&&(e.preventDefault(),Qe())},placeholder:"Add tag",helperText:"Add a tag to your API product",margin:"normal",disabled:Ae,InputProps:{endAdornment:ne?(0,s.jsx)(M.A,{position:"end",children:(0,s.jsx)(d.A,{size:"small",onClick:Qe,disabled:Ae,children:(0,s.jsx)(p.A,{fontSize:"small"})})}):void 0}})}),ae.length>0&&(0,s.jsx)($.A,{item:!0,xs:12,children:(0,s.jsx)(i.A,{display:"flex",flexWrap:"wrap",children:ae.map(e=>(0,s.jsx)(r.A,{label:e,onDelete:Ae?void 0:()=>{return t=e,void se(ae.filter(e=>e!==t));var t},size:"small",className:A.tagChip,disabled:Ae},e))})}),(0,s.jsx)($.A,{item:!0,xs:12,children:(0,s.jsx)(H.A,{fullWidth:!0,label:"Description",value:S,onChange:e=>I(e.target.value),placeholder:"API description",margin:"normal",multiline:!0,rows:2,required:!0,disabled:Ae,InputLabelProps:{classes:{asterisk:A.asterisk}}})})]}),(0,s.jsxs)(i.A,{className:A.sectionHeader,children:[(0,s.jsx)(o.A,{variant:"subtitle1",children:(0,s.jsx)("strong",{children:"Add API and Associate route"})}),(0,s.jsx)(W.Ay,{title:"Register an existing API and associate HTTPRoute for your API product",children:(0,s.jsx)(U.A,{className:A.infoIcon})})]}),(0,s.jsxs)($.A,{container:!0,spacing:2,children:[(0,s.jsx)($.A,{item:!0,xs:12,children:(0,s.jsx)(H.A,{fullWidth:!0,label:"OpenAPI Spec URL",value:he,onChange:e=>{return t=e.target.value,ve(t),void we((0,V.q)(t));var t},placeholder:"https://api.example.com/openapi.json",helperText:Se||"Enter the full path to your API spec file",error:!!Se,margin:"normal",required:!0,disabled:Ae,InputLabelProps:{classes:{asterisk:A.asterisk}}})}),(0,s.jsx)($.A,{item:!0,xs:12,children:(0,s.jsx)(H.A,{fullWidth:!0,label:"Documentation URL",value:pe,onChange:e=>me(e.target.value),placeholder:"https://docs.example.com/api",helperText:"Link to external documentation for this API",margin:"normal",disabled:Ae})}),(0,s.jsx)($.A,{item:!0,xs:12,children:(0,s.jsxs)(H.A,{fullWidth:!0,select:!0,label:"HTTPRoute",value:ie,onChange:e=>re(e.target.value),margin:"normal",required:!0,helperText:ze?"Unable to load HTTPRoutes. Please retry.":"Select an HTTPRoute. APIProduct will be created in the same namespace.",error:!!ze,disabled:Re||Ae||!!ze,InputLabelProps:{classes:{asterisk:A.asterisk}},SelectProps:{"data-testid":"httproute-select",MenuProps:{PaperProps:{style:{maxHeight:400}},anchorOrigin:{vertical:"bottom",horizontal:"left"},transformOrigin:{vertical:"top",horizontal:"left"},getContentAnchorEl:null}},children:[(0,s.jsx)(i.A,{px:2,pt:1,pb:1,style:{position:"sticky",top:0,zIndex:1},children:(0,s.jsx)(H.A,{fullWidth:!0,size:"small",placeholder:"Search...",value:Ce,onChange:e=>Ie(e.target.value),onKeyDown:e=>e.stopPropagation(),onClick:e=>e.stopPropagation(),InputProps:{endAdornment:(0,s.jsx)(M.A,{position:"end",children:(0,s.jsxs)(H.A,{select:!0,size:"small",value:ke,onChange:e=>Te(e.target.value),onKeyDown:e=>e.stopPropagation(),onClick:e=>e.stopPropagation(),style:{minWidth:120},variant:"standard",children:[(0,s.jsx)(E.A,{value:"name",children:"Name"}),(0,s.jsx)(E.A,{value:"namespace",children:"Namespace"}),(0,s.jsx)(E.A,{value:"planpolicy",children:"PlanPolicy"})]})})}})}),Re&&(0,s.jsx)(E.A,{value:"",children:"Loading..."}),ze&&(0,s.jsx)(E.A,{value:"",children:"Error loading routes"}),!Re&&!ze&&Ne&&0===Ne.length&&(0,s.jsx)(E.A,{value:"",children:"No HTTPRoutes available"}),!Re&&!ze&&Ne&&Ne.filter(e=>{if(!Ce)return!0;const t=e.metadata.namespace,a=e.metadata.name,s=Xe(t,a),n=Ce.toLowerCase();switch(ke){case"name":return a.toLowerCase().includes(n);case"namespace":return t.toLowerCase().includes(n);case"planpolicy":return s.toLowerCase().includes(n);default:return!0}}).map(e=>{const t=e.metadata.namespace,a=e.metadata.name,n=Xe(t,a);return(0,s.jsx)(E.A,{value:`${t}/${a}`,children:(0,s.jsxs)(i.A,{children:[(0,s.jsx)(o.A,{variant:"body1",children:a}),(0,s.jsxs)(o.A,{variant:"caption",color:"textSecondary",children:["Associated PlanPolicy: ",n]})]})},`${t}/${a}`)})]})})]}),ie&&(0,s.jsxs)(s.Fragment,{children:[(0,s.jsxs)(i.A,{className:A.sectionHeader,children:[(0,s.jsx)(o.A,{variant:"subtitle1",children:(0,s.jsx)("strong",{children:"HTTPRoute policies"})}),(0,s.jsx)(W.Ay,{title:"Shows the associated policies and rate limit tiers for the selected HTTPRoute",children:(0,s.jsx)(U.A,{className:A.infoIcon})})]}),(0,s.jsx)(Y.K,{planPolicy:Ze,authPolicy:Ge,rateLimitPolicy:Je,includeTopMargin:!1})]}),(0,s.jsxs)(i.A,{className:A.sectionHeader,children:[(0,s.jsx)(o.A,{variant:"subtitle1",children:(0,s.jsx)("strong",{children:"Lifecycle and Visibility"})}),(0,s.jsx)(W.Ay,{title:"Control the lifecycle state and catalog visibility of this API product",children:(0,s.jsx)(U.A,{className:A.infoIcon})})]}),(0,s.jsxs)($.A,{container:!0,spacing:2,children:[(0,s.jsx)($.A,{item:!0,xs:6,children:(0,s.jsxs)(H.A,{fullWidth:!0,select:!0,label:"Lifecycle",value:ee,onChange:e=>te(e.target.value),margin:"normal",helperText:"API lifecycle state",disabled:Ae,children:[(0,s.jsx)(E.A,{value:"experimental",children:"Experimental"}),(0,s.jsx)(E.A,{value:"production",children:"Production"}),(0,s.jsx)(E.A,{value:"deprecated",children:"Deprecated"}),(0,s.jsx)(E.A,{value:"retired",children:"Retired"})]})}),(0,s.jsx)($.A,{item:!0,xs:6,children:(0,s.jsxs)(H.A,{fullWidth:!0,select:!0,label:"Publish Status",value:X,onChange:e=>Q(e.target.value),margin:"normal",helperText:"Controls catalog visibility (Draft = hidden from consumers)",disabled:Ae,children:[(0,s.jsx)(E.A,{value:"Draft",children:"Draft"}),(0,s.jsx)(E.A,{value:"Published",children:"Published"})]})})]}),(0,s.jsxs)(i.A,{className:A.sectionHeader,children:[(0,s.jsx)(o.A,{variant:"subtitle1",children:(0,s.jsx)("strong",{children:"API Key approval"})}),(0,s.jsx)(W.Ay,{title:"Choose how API key requests are handled for this product",children:(0,s.jsx)(U.A,{className:A.infoIcon})})]}),(0,s.jsx)(K.A,{component:"fieldset",disabled:Ae,children:(0,s.jsxs)(q.A,{row:!0,value:R,onChange:e=>J(e.target.value),children:[(0,s.jsx)(B.A,{value:"manual",control:(0,s.jsx)(O.A,{color:"primary"}),label:(0,s.jsxs)(i.A,{children:[(0,s.jsx)(o.A,{variant:"body2",children:"Need manual approval"}),(0,s.jsx)(o.A,{variant:"caption",color:"textSecondary",children:"Requires approval for requesting this API"})]})}),(0,s.jsx)(B.A,{value:"automatic",control:(0,s.jsx)(O.A,{color:"primary"}),label:(0,s.jsxs)(i.A,{children:[(0,s.jsx)(o.A,{variant:"body2",children:"Automatic"}),(0,s.jsx)(o.A,{variant:"caption",color:"textSecondary",children:"Keys are created without need to be approved"})]})})]})})]}),(0,s.jsxs)(F.A,{children:[(0,s.jsx)(c.A,{onClick:et,disabled:Ae,children:"Cancel"}),(0,s.jsx)(c.A,{onClick:async()=>{xe(""),ye(!0);try{if(!ie)throw new Error("Please select an HTTPRoute");const[e,t]=ie.split("/"),s=e,n={apiVersion:"devportal.kuadrant.io/v1alpha1",kind:"APIProduct",metadata:{name:f,namespace:s,labels:{lifecycle:ee}},spec:{displayName:b,description:S,version:T,approvalMode:R,publishStatus:X,tags:ae,targetRef:{group:"gateway.networking.k8s.io",kind:"HTTPRoute",name:t,namespace:e},...oe||de?{contact:{...oe&&{email:oe},...de&&{team:de}}}:{},...pe||he?{documentation:{...pe&&{docsURL:pe},...he&&{openAPISpecURL:he}}}:{}}};await y.createApiProduct(n),a({namespace:s,name:f,displayName:b}),et()}catch(e){xe(e instanceof Error?e.message:String(e))}finally{ye(!1)}},color:"primary",variant:"contained",disabled:Ae||!f||!b||!S||!ie||tt,startIcon:Ae?(0,s.jsx)(u.A,{size:16,color:"inherit"}):void 0,children:Ae?"Creating...":"Create"})]})]})};var X=a(34955),Q=a(26997),ee=a(63221),te=a(46299);const ae=a.p+"static/empty-state-illustration.7e3ad5a9..png",se=(0,l.A)(e=>({container:{display:"flex",height:"100%",minHeight:400},tableContainer:{flex:1,overflow:"auto",padding:10},emptyState:{display:"flex",alignItems:"center",justifyContent:"center",padding:e.spacing(6),minHeight:400},emptyStateContent:{display:"flex",alignItems:"center",gap:e.spacing(6),maxWidth:900},emptyStateText:{flex:1},emptyStateTitle:{marginBottom:e.spacing(2)},emptyStateDescription:{marginBottom:e.spacing(3),color:e.palette.text.secondary},emptyStateImage:{maxWidth:400,height:"auto"}})),ne=()=>{const e=se(),t=(0,C.useApi)(k.s),a=(0,C.useApi)(C.alertApiRef),l=(0,C.useApi)(C.identityApiRef),T=(0,C.useApi)(I.v),[R,z]=(0,n.useState)(""),[L,D]=(0,n.useState)(!1),[$,H]=(0,n.useState)(!1),[M,W]=(0,n.useState)(0),[E,K]=(0,n.useState)(!1),[q,B]=(0,n.useState)(null),[O,F]=(0,n.useState)(null),[U,_]=(0,n.useState)(!1),[Y,V]=(0,n.useState)(null),[Z,G]=(0,n.useState)({status:[],lifecycle:[],policy:[],route:[],namespace:[],tags:[],authentication:[]}),{allowed:ne,loading:le,error:ie}=(0,N.l)(X.FL),{allowed:re,loading:oe}=(0,N.l)(X.EM),{allowed:ce,loading:de,error:ue}=(0,N.l)(X.R_),{allowed:pe}=(0,N.l)(X.U3),{allowed:me}=(0,N.l)(X.v_),he=oe||de,{allowed:ve,loading:ge,error:xe}=(0,N.l)(X.J);(0,w.A)(async()=>{const e=await l.getBackstageIdentity();z(e.userEntityRef)},[l]);const{value:Ae,loading:ye,error:fe}=(0,w.A)(async()=>t.getApiProducts(),[t,M]),{value:je,loading:be,error:Pe}=(0,w.A)(async()=>ve?t.getPlanPolicies():{items:[]},[t,M,ve]),{value:Se}=(0,w.A)(async()=>(await T.getEntities({filter:{kind:"API","metadata.labels.kuadrant.io/synced":"true"},fields:["metadata.name","spec.lifecycle"]})).items,[T,M]),we=(0,n.useMemo)(()=>{const e=new Map;if(Se)for(const a of Se){var t;const s=null===(t=a.spec)||void 0===t?void 0:t.lifecycle;s&&e.set(a.metadata.name,s)}return e},[Se]),Ce=(0,n.useCallback)(e=>we.get(e.metadata.name),[we]),Ie=(0,n.useCallback)(e=>{var t;if(!(null==je?void 0:je.items))return null;const a=null===(t=e.spec)||void 0===t?void 0:t.targetRef;if(!a)return null;const s=je.items.find(t=>{const s=t.spec.targetRef;return"HTTPRoute"===(null==s?void 0:s.kind)&&(null==s?void 0:s.name)===a.name&&(!(null==s?void 0:s.namespace)||(null==s?void 0:s.namespace)===(a.namespace||e.metadata.namespace))});return(null==s?void 0:s.metadata.name)||null},[je]),ke=(0,n.useCallback)(e=>{var t,a;const s=(null===(a=e.status)||void 0===a||null===(t=a.discoveredAuthScheme)||void 0===t?void 0:t.authentication)||{},n=Object.values(s),l=[];return n.some(e=>e.hasOwnProperty("apiKey"))&&l.push("API Key"),n.some(e=>e.hasOwnProperty("jwt"))&&l.push("OIDC"),0===l.length&&l.push("Unknown"),l},[]),Te=ye||be||le||he||ge,Ne=fe||Pe,Re=ie||ue||xe,ze=(0,n.useMemo)(()=>{const e=(null==Ae?void 0:Ae.items)||[];return ne||pe||me?e:e.filter(e=>{var t;return"Published"===((null===(t=e.spec)||void 0===t?void 0:t.publishStatus)||"Draft")})},[Ae,ne,pe,me]),Le=(0,n.useMemo)(()=>{const e={Draft:0,Published:0},t=new Map,a=new Map,s=new Map,n=new Map,l=new Map,i=new Map;ze.forEach(r=>{var o,c,d,u;const p=(null===(o=r.spec)||void 0===o?void 0:o.publishStatus)||"Draft";e[p]++;const m=Ce(r);m&&t.set(m,(t.get(m)||0)+1);const h=Ie(r)||"N/A";a.set(h,(a.get(h)||0)+1);const v=(null===(d=r.spec)||void 0===d||null===(c=d.targetRef)||void 0===c?void 0:c.name)||"unknown";s.set(v,(s.get(v)||0)+1);const g=r.metadata.namespace;n.set(g,(n.get(g)||0)+1),((null===(u=r.spec)||void 0===u?void 0:u.tags)||[]).forEach(e=>{l.set(e,(l.get(e)||0)+1)}),ke(r).forEach(e=>{i.set(e,(i.get(e)||0)+1)})});const r=[{id:"status",title:"Publish Status",options:[{value:"Draft",label:"Draft",count:e.Draft},{value:"Published",label:"Published",count:e.Published}]},{id:"lifecycle",title:"Lifecycle",options:Array.from(t.entries()).map(([e,t])=>({value:e,label:e.charAt(0).toUpperCase()+e.slice(1),count:t}))},{id:"authentication",title:"Authentication",options:Array.from(i.entries()).map(([e,t])=>({value:e,label:e,count:t}))},{id:"route",title:"Route",options:Array.from(s.entries()).map(([e,t])=>({value:e,label:e,count:t})),collapsed:s.size>5},{id:"namespace",title:"Namespace",options:Array.from(n.entries()).map(([e,t])=>({value:e,label:e,count:t})),collapsed:n.size>5},{id:"tags",title:"Tags",options:Array.from(l.entries()).map(([e,t])=>({value:e,label:e,count:t})),collapsed:l.size>5}];return ve&&r.splice(2,0,{id:"policy",title:"Policy",options:Array.from(a.entries()).map(([e,t])=>({value:e,label:e,count:t})),collapsed:a.size>5}),r},[ze,Ie,ke,Ce,ve]),De=(0,n.useMemo)(()=>ze.filter(e=>{if(Z.status.length>0){var t;const a=(null===(t=e.spec)||void 0===t?void 0:t.publishStatus)||"Draft";if(!Z.status.includes(a))return!1}if(Z.lifecycle&&Z.lifecycle.length>0){const t=Ce(e);if(!t||!Z.lifecycle.includes(t))return!1}if(Z.authentication.length>0){const t=ke(e);if(!Z.authentication.some(e=>t.includes(e)))return!1}if(Z.policy.length>0){const t=Ie(e)||"N/A";if(!Z.policy.includes(t))return!1}if(Z.route.length>0){var a,s;const t=(null===(s=e.spec)||void 0===s||null===(a=s.targetRef)||void 0===a?void 0:a.name)||"unknown";if(!Z.route.includes(t))return!1}if(Z.namespace.length>0&&!Z.namespace.includes(e.metadata.namespace))return!1;if(Z.tags.length>0){var n;const t=(null===(n=e.spec)||void 0===n?void 0:n.tags)||[];if(!Z.tags.some(e=>t.includes(e)))return!1}return!0}),[ze,Z,Ie,ke,Ce]),$e=[{title:"Name",field:"spec.displayName",render:e=>{var t,a;const n=null!==(a=null===(t=e.spec)||void 0===t?void 0:t.displayName)&&void 0!==a?a:e.metadata.name;return(0,s.jsx)(A.N_,{to:`/kuadrant/api-products/${e.metadata.namespace}/${e.metadata.name}`,children:(0,s.jsx)("strong",{children:n})})},customFilterAndSearch:(e,t)=>{var a;return((null===(a=t.spec)||void 0===a?void 0:a.displayName)||t.metadata.name||"").toLowerCase().includes(e.toLowerCase())}},{title:"Version",field:"spec.version",render:e=>{var t;return(null===(t=e.spec)||void 0===t?void 0:t.version)||"-"}},{title:"Route",field:"spec.targetRef.name",render:e=>{var t,a;return(null===(a=e.spec)||void 0===a||null===(t=a.targetRef)||void 0===t?void 0:t.name)||"-"}},...ve?[{title:"Policy",field:"policy",render:e=>Ie(e)||"N/A"}]:[],{title:"Tags",field:"spec.tags",render:e=>{var t;const a=(null===(t=e.spec)||void 0===t?void 0:t.tags)||[];return 0===a.length?"-":(0,s.jsx)(i.A,{display:"flex",style:{gap:4,flexWrap:"wrap"},children:a.map(e=>(0,s.jsx)(r.A,{label:e,size:"small",variant:"outlined"},e))})}},{title:"Status",field:"spec.publishStatus",render:e=>{var t;const a=(null===(t=e.spec)||void 0===t?void 0:t.publishStatus)||"Draft";return(0,s.jsx)(r.A,{label:a,size:"small",color:"Published"===a?"primary":"default"})}},{title:"Lifecycle",render:e=>{const t=Ce(e);return t?(0,s.jsx)(r.A,{label:t.charAt(0).toUpperCase()+t.slice(1),size:"small",style:(0,te.ee)(t)}):"-"}},{title:"Authentication",field:"status.discoveredAuthScheme",render:e=>{var t,a;const n=(null===(a=e.status)||void 0===a||null===(t=a.discoveredAuthScheme)||void 0===t?void 0:t.authentication)||{},l=Object.values(n),c=l.some(e=>e.hasOwnProperty("apiKey")),d=l.some(e=>e.hasOwnProperty("jwt"));return c||d?(0,s.jsxs)(i.A,{display:"flex",style:{gap:4},children:[c&&(0,s.jsx)(r.A,{icon:(0,s.jsx)(v.A,{}),label:"API Key",size:"small",color:"primary"}),d&&(0,s.jsx)(r.A,{icon:(0,s.jsx)(g.A,{}),label:"OIDC",size:"small",color:"secondary"})]}):(0,s.jsx)(o.A,{variant:"body2",style:{fontStyle:"italic"},children:"unknown"})}},{title:"Namespace",field:"metadata.namespace"},{title:"Actions",field:"actions",filtering:!1,render:e=>{var n,l,r;const o=(null===(l=e.metadata)||void 0===l||null===(n=l.annotations)||void 0===n?void 0:n["backstage.io/owner"])===R,u=me||pe&&o,p=ce||re&&o,v="Published"===(null===(r=e.spec)||void 0===r?void 0:r.publishStatus);return(0,s.jsxs)(i.A,{display:"flex",alignItems:"center",style:{gap:4},children:[u&&(0,s.jsx)(c.A,{size:"small",color:"primary",onClick:()=>(async e=>{var s,n;const l=e.metadata.namespace,i=e.metadata.name,r=(null===(s=e.spec)||void 0===s?void 0:s.displayName)||i,o="Published"===((null===(n=e.spec)||void 0===n?void 0:n.publishStatus)||"Draft")?"Draft":"Published";if("Published"===o&&"retired"===Ce(e))return void a.post({message:"Cannot publish a retired API product. Please change the lifecycle status first.",severity:"error",display:"transient"});const c={spec:{publishStatus:o}};try{await t.updateApiProduct(l,i,c),W(e=>e+1),a.post({message:`"${r}" ${"Published"===o?"published":"unpublished"} successfully`,severity:"success",display:"transient"})}catch(e){const t=e instanceof Error?e.message:"unknown error occurred";a.post({message:`Failed to update publish status: ${t}`,severity:"error",display:"transient"})}})(e),style:{marginRight:4,textTransform:"none"},children:v?"Unpublish":"Publish"}),u&&(0,s.jsx)(d.A,{size:"small",onClick:()=>{return t=e.metadata.namespace,a=e.metadata.name,F({namespace:t,name:a}),void H(!0);var t,a},title:"Edit API Product",children:(0,s.jsx)(h.A,{fontSize:"small"})}),p&&(0,s.jsx)(d.A,{size:"small",onClick:()=>(async(e,s)=>{B({namespace:e,name:s}),V(null);try{const a=((await t.getRequestsByNamespace(e)).items||[]).filter(t=>t.spec.apiName===s&&t.spec.apiNamespace===e),n=a.filter(e=>{var t;return"Approved"===(null===(t=e.status)||void 0===t?void 0:t.phase)}).length;V({requests:a.length,secrets:n})}catch(e){const t=e instanceof Error?e.message:"unknown error occurred";a.post({message:`Failed to delete access request: ${t}`,severity:"error",display:"transient"})}finally{K(!0)}})(e.metadata.namespace,e.metadata.name),title:"Delete API Product",children:(0,s.jsx)(m.A,{fontSize:"small"})})]})}}];return(0,s.jsxs)(y.Y,{themeId:"tool",children:[(0,s.jsx)(f.Y,{title:"API Products",subtitle:"Manage API products for Kubernetes",children:(0,s.jsx)(j.Y,{children:"Manage API products and plan policies"})}),(0,s.jsxs)(b.U,{children:[Te&&(0,s.jsxs)(i.A,{display:"flex",flexDirection:"column",alignItems:"center",justifyContent:"center",minHeight:300,children:[(0,s.jsx)(u.A,{}),(0,s.jsx)(o.A,{variant:"h6",style:{marginTop:16},children:"Loading data..."}),(0,s.jsx)(o.A,{variant:"body2",color:"textSecondary",children:"Preparing your data... This should only take a moment."})]}),Ne&&(0,s.jsx)(P._,{error:Ne}),Re&&(0,s.jsxs)(i.A,{p:2,children:[(0,s.jsxs)(o.A,{color:"error",children:["unable to check permissions: ",Re.message]}),(0,s.jsxs)(o.A,{variant:"body2",color:"textSecondary",children:["permission:"," ",ie?"kuadrant.apiproduct.create":ue?"kuadrant.apiproduct.delete":xe?"kuadrant.planpolicy.list":"unknown"]}),(0,s.jsx)(o.A,{variant:"body2",color:"textSecondary",children:"please try again or contact your administrator"})]}),!Te&&!Ne&&!Re&&0===ze.length&&(0,s.jsx)(i.A,{className:e.emptyState,children:(0,s.jsxs)(i.A,{className:e.emptyStateContent,children:[(0,s.jsxs)(i.A,{className:e.emptyStateText,children:[(0,s.jsx)(o.A,{variant:"h4",className:e.emptyStateTitle,children:"API Product"}),(0,s.jsx)(o.A,{variant:"body1",className:e.emptyStateDescription,children:"Create API product by registering existing API, associate route and policy"}),ne&&(0,s.jsx)(c.A,{variant:"contained",color:"primary",startIcon:(0,s.jsx)(p.A,{}),onClick:()=>D(!0),children:"Create API Product"})]}),(0,s.jsx)("img",{src:ae,alt:"API Product illustration",className:e.emptyStateImage})]})}),!Te&&!Ne&&!Re&&ze.length>0&&(0,s.jsxs)(i.A,{className:e.container,children:[(0,s.jsx)(x.Z,{sections:Le,filters:Z,onChange:G}),(0,s.jsxs)(i.A,{className:e.tableContainer,children:[(0,s.jsx)(i.A,{display:"flex",justifyContent:"flex-end",mb:2,children:ne&&(0,s.jsx)(c.A,{variant:"contained",color:"primary",size:"small",startIcon:(0,s.jsx)(p.A,{}),onClick:()=>D(!0),children:"Create API Product"})}),0===De.length?(0,s.jsx)(i.A,{p:4,textAlign:"center",children:(0,s.jsx)(o.A,{variant:"body1",color:"textSecondary",children:"No API products match the selected filters."})}):(0,s.jsx)(S.X,{options:{paging:De.length>10,pageSize:20,search:!0,filtering:!1,debounceInterval:300,toolbar:!0,emptyRowsWhenPaging:!1},columns:$e,data:De})]})]}),(0,s.jsx)(J,{open:L,onClose:()=>D(!1),onSuccess:e=>{W(e=>e+1),a.post({message:`"${e.displayName}" created successfully`,severity:"success",display:"transient"})}}),(0,s.jsx)(Q.C,{open:$,onClose:()=>H(!1),onSuccess:()=>{W(e=>e+1);const e=(null==O?void 0:O.name)||"API Product";a.post({message:`"${e}" updated successfully`,severity:"success",display:"transient"})},namespace:(null==O?void 0:O.namespace)||"",name:(null==O?void 0:O.name)||""}),(0,s.jsx)(ee.K,{open:E,title:"Delete API Product",description:Y?`Deleting "${null==q?void 0:q.name}" will also remove:\n\n• ${Y.requests} API Key(s)\n• ${Y.secrets} API Key Secret(s)\n\nThis action cannot be undone.`:`Deleting "${null==q?void 0:q.name}" will also remove all associated API Keys and Secrets.\nThis action cannot be undone.`,confirmText:null==q?void 0:q.name,severity:"high",deleting:U,onConfirm:async()=>{if(q){_(!0);try{await t.deleteApiProduct(q.namespace,q.name);const e=(null==q?void 0:q.name)||"API Product";W(e=>e+1),a.post({message:`"${e}" deleted successfully`,severity:"success",display:"transient"})}catch(e){const t=e instanceof Error?e.message:"unknown error occurred";a.post({message:`Failed to delete API Product: ${t}`,severity:"error",display:"transient"})}finally{_(!1),K(!1),B(null)}}},onCancel:()=>{K(!1),B(null)}})]})]})},le=()=>(0,s.jsx)(R,{permission:X.vs,errorMessage:"you don't have permission to view the Kuadrant page",children:(0,s.jsx)(ne,{})})}}]);
2
- //# sourceMappingURL=7005.d548f8f1.chunk.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"static/7005.d548f8f1.chunk.js","mappings":"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","sources":["webpack://internal.plugin-kuadrant/./src/components/FilterPanel/FilterPanel.tsx","webpack://internal.plugin-kuadrant/./src/components/PermissionGate/PermissionGate.tsx","webpack://internal.plugin-kuadrant/./src/components/CreateAPIProductDialog/CreateAPIProductDialog.tsx","webpack://internal.plugin-kuadrant/./src/components/KuadrantPage/ApiProductsPage.tsx"],"sourcesContent":["import React from 'react';\nimport {\n Box,\n Typography,\n Checkbox,\n FormControlLabel,\n FormGroup,\n Divider,\n Button,\n Collapse,\n makeStyles,\n} from '@material-ui/core';\nimport ExpandMoreIcon from '@material-ui/icons/ExpandMore';\nimport ExpandLessIcon from '@material-ui/icons/ExpandLess';\n\nconst useStyles = makeStyles(theme => ({\n root: {\n width: 240,\n minWidth: 240,\n padding: theme.spacing(2),\n borderRight: `1px solid ${theme.palette.divider}`,\n backgroundColor: theme.palette.background.paper,\n height: '100%',\n overflowY: 'auto',\n },\n sectionTitle: {\n fontWeight: 600,\n fontSize: '0.75rem',\n textTransform: 'uppercase',\n letterSpacing: '0.05em',\n color: theme.palette.text.secondary,\n marginBottom: theme.spacing(1),\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'space-between',\n cursor: 'pointer',\n userSelect: 'none',\n },\n filterSection: {\n marginBottom: theme.spacing(2),\n },\n checkbox: {\n padding: theme.spacing(0.5),\n },\n checkboxLabel: {\n fontSize: '0.875rem',\n },\n clearButton: {\n marginTop: theme.spacing(2),\n },\n count: {\n fontSize: '0.75rem',\n color: theme.palette.text.secondary,\n marginLeft: theme.spacing(1),\n },\n}));\n\nexport interface FilterOption {\n value: string;\n label: string;\n count?: number;\n}\n\nexport interface FilterSection {\n id: string;\n title: string;\n options: FilterOption[];\n collapsed?: boolean;\n}\n\nexport interface FilterState {\n [sectionId: string]: string[];\n}\n\ninterface FilterPanelProps {\n sections: FilterSection[];\n filters: FilterState;\n onChange: (filters: FilterState) => void;\n onClear?: () => void;\n}\n\nexport const FilterPanel = ({\n sections,\n filters,\n onChange,\n onClear,\n}: FilterPanelProps) => {\n const classes = useStyles();\n const [collapsedSections, setCollapsedSections] = React.useState<Set<string>>(\n new Set(sections.filter(s => s.collapsed).map(s => s.id)),\n );\n\n const toggleSection = (sectionId: string) => {\n setCollapsedSections(prev => {\n const next = new Set(prev);\n if (next.has(sectionId)) {\n next.delete(sectionId);\n } else {\n next.add(sectionId);\n }\n return next;\n });\n };\n\n const handleCheckboxChange = (sectionId: string, value: string) => {\n const currentValues = filters[sectionId] || [];\n const newValues = currentValues.includes(value)\n ? currentValues.filter(v => v !== value)\n : [...currentValues, value];\n\n onChange({\n ...filters,\n [sectionId]: newValues,\n });\n };\n\n const hasActiveFilters = Object.values(filters).some(\n values => values.length > 0,\n );\n\n const handleClear = () => {\n const clearedFilters: FilterState = {};\n sections.forEach(section => {\n clearedFilters[section.id] = [];\n });\n onChange(clearedFilters);\n onClear?.();\n };\n\n return (\n <Box className={classes.root}>\n <Box display=\"flex\" justifyContent=\"space-between\" alignItems=\"center\" mb={2}>\n <Typography variant=\"subtitle2\">Filters</Typography>\n {hasActiveFilters && (\n <Button\n size=\"small\"\n color=\"primary\"\n onClick={handleClear}\n >\n Clear all\n </Button>\n )}\n </Box>\n\n <Divider />\n\n {sections.map(section => {\n const isCollapsed = collapsedSections.has(section.id);\n const selectedCount = (filters[section.id] || []).length;\n\n return (\n <Box key={section.id} className={classes.filterSection} mt={2}>\n <Box\n className={classes.sectionTitle}\n onClick={() => toggleSection(section.id)}\n >\n <Box display=\"flex\" alignItems=\"center\">\n <span>{section.title}</span>\n {selectedCount > 0 && (\n <span className={classes.count}>({selectedCount})</span>\n )}\n </Box>\n {isCollapsed ? (\n <ExpandMoreIcon fontSize=\"small\" />\n ) : (\n <ExpandLessIcon fontSize=\"small\" />\n )}\n </Box>\n\n <Collapse in={!isCollapsed}>\n <FormGroup>\n {section.options.map(option => (\n <FormControlLabel\n key={option.value}\n control={\n <Checkbox\n checked={(filters[section.id] || []).includes(option.value)}\n onChange={() =>\n handleCheckboxChange(section.id, option.value)\n }\n size=\"small\"\n className={classes.checkbox}\n color=\"primary\"\n />\n }\n label={\n <Box display=\"flex\" alignItems=\"center\">\n <span className={classes.checkboxLabel}>\n {option.label}\n </span>\n {option.count !== undefined && (\n <span className={classes.count}>({option.count})</span>\n )}\n </Box>\n }\n />\n ))}\n </FormGroup>\n </Collapse>\n </Box>\n );\n })}\n </Box>\n );\n};\n","import React from 'react';\nimport { Typography, Box } from '@material-ui/core';\nimport { Progress } from '@backstage/core-components';\nimport { Permission } from '@backstage/plugin-permission-common';\nimport { useKuadrantPermission } from '../../utils/permissions';\n\ninterface PermissionGateProps {\n children: React.ReactNode;\n permission: Permission;\n fallback?: React.ReactNode;\n errorMessage?: string;\n}\n\nexport const PermissionGate = ({ children, permission, fallback, errorMessage }: PermissionGateProps) => {\n const { allowed, loading, error } = useKuadrantPermission(permission);\n\n if (loading) {\n return <Progress />;\n }\n\n if (error) {\n return (\n <Box p={4}>\n <Typography color=\"error\">\n Unable to check permissions: {error.message}\n </Typography>\n <Typography variant=\"body2\" color=\"textSecondary\">\n Please try again or contact your administrator\n </Typography>\n </Box>\n );\n }\n\n if (!allowed) {\n if (fallback) {\n return <>{fallback}</>;\n }\n return (\n <Box p={4}>\n <Typography color=\"textSecondary\">\n {errorMessage || 'You don\\'t have permission to view this page'}\n </Typography>\n <Box mt={1}>\n <Typography variant=\"caption\" color=\"textSecondary\">\n Required permission: {permission.name}\n </Typography>\n </Box>\n </Box>\n );\n }\n\n return <>{children}</>;\n};\n","import React, { useEffect, useState } from 'react';\nimport {\n Dialog,\n DialogTitle,\n DialogContent,\n DialogActions,\n Button,\n TextField,\n Box,\n Typography,\n Chip,\n Grid,\n MenuItem,\n CircularProgress,\n makeStyles,\n FormControl,\n RadioGroup,\n FormControlLabel,\n Radio,\n Tooltip,\n IconButton,\n InputAdornment,\n} from '@material-ui/core';\nimport InfoOutlinedIcon from '@material-ui/icons/InfoOutlined';\nimport AddIcon from '@material-ui/icons/Add';\nimport { useApi } from '@backstage/core-plugin-api';\nimport { kuadrantApiRef } from '../../api';\nimport { Alert } from '@material-ui/lab';\nimport useAsync from 'react-use/lib/useAsync';\nimport { ApiProductPolicies } from '../ApiProductPolicies';\nimport { validateKubernetesName, validateURL } from '../../utils/validation';\nimport { APIProduct } from \"../../types/api-management.ts\";\nimport { Lifecycle } from '../../types/api-management';\nimport { getPolicyForRoute } from '../../utils/policies';\n\nconst useStyles = makeStyles((theme) => ({\n asterisk: {\n color: '#f44336',\n },\n sectionHeader: {\n display: 'flex',\n alignItems: 'center',\n gap: theme.spacing(0.5),\n marginTop: theme.spacing(2),\n marginBottom: theme.spacing(1),\n },\n infoIcon: {\n fontSize: 18,\n color: theme.palette.text.secondary,\n },\n tagChip: {\n marginRight: theme.spacing(0.5),\n marginBottom: theme.spacing(0.5),\n },\n}));\n\ninterface CreateAPIProductDialogProps {\n open: boolean;\n onClose: () => void;\n onSuccess: (productInfo: { namespace: string; name: string; displayName: string }) => void;\n}\n\nexport const CreateAPIProductDialog = ({ open, onClose, onSuccess }: CreateAPIProductDialogProps) => {\n const classes = useStyles();\n const kuadrantApi = useApi(kuadrantApiRef);\n\n const [name, setName] = useState('');\n const [displayName, setDisplayName] = useState('');\n const [description, setDescription] = useState('');\n const [version, setVersion] = useState('v1');\n const [approvalMode, setApprovalMode] = useState<'automatic' | 'manual'>('manual');\n const [publishStatus, setPublishStatus] = useState<'Draft' | 'Published'>('Published');\n const [lifecycle, setLifecycle] = useState<Lifecycle>('production');\n const [tags, setTags] = useState<string[]>([]);\n const [tagInput, setTagInput] = useState('');\n const [selectedHTTPRoute, setSelectedHTTPRoute] = useState('');\n const [contactEmail, setContactEmail] = useState('');\n const [contactTeam, setContactTeam] = useState('');\n const [docsURL, setDocsURL] = useState('');\n const [openAPISpec, setOpenAPISpec] = useState('');\n const [error, setError] = useState('');\n const [creating, setCreating] = useState(false);\n const [httpRoutesRetry, setHttpRoutesRetry] = useState(0);\n const [nameError, setNameError] = useState<string | null>(null);\n const [openAPISpecError, setOpenAPISpecError] = useState<string | null>(null);\n const [routeSearchTerm, setRouteSearchTerm] = useState('');\n const [routeSearchField, setRouteSearchField] = useState<'name' | 'namespace' | 'planpolicy'>('name');\n const {\n value: httpRoutes,\n loading: httpRoutesLoading,\n error: httpRoutesError\n } = useAsync(async () => {\n const data = await kuadrantApi.getHttpRoutes();\n return data.items || [];\n }, [kuadrantApi, open, httpRoutesRetry]);\n\n // load planpolicies with full details to show associated plans\n const {\n value: planPolicies,\n error: planPoliciesError\n } = useAsync(async () => {\n return await kuadrantApi.getPlanPolicies();\n }, [kuadrantApi, open]);\n\n // load authpolicies\n const {\n value: authPolicies,\n error: authPoliciesError\n } = useAsync(async () => {\n return await kuadrantApi.getAuthPolicies();\n }, [kuadrantApi, open]);\n\n // load ratelimitpolicies\n const {\n value: rateLimitPolicies,\n error: rateLimitPoliciesError\n } = useAsync(async () => {\n return await kuadrantApi.getRateLimitPolicies();\n }, [kuadrantApi, open]);\n\n // find planpolicy associated with selected httproute\n const getPlanPolicyForRoute = (routeNamespace: string, routeName: string) => {\n return getPolicyForRoute(planPolicies?.items, routeNamespace, routeName);\n };\n\n // find authpolicy associated with selected httproute\n const getAuthPolicyForRoute = (routeNamespace: string, routeName: string) => {\n return getPolicyForRoute(authPolicies?.items, routeNamespace, routeName);\n };\n\n // find ratelimitpolicy associated with selected httproute\n const getRateLimitPolicyForRoute = (routeNamespace: string, routeName: string) => {\n return getPolicyForRoute(rateLimitPolicies?.items, routeNamespace, routeName);\n };\n\n const selectedRouteInfo = selectedHTTPRoute ? selectedHTTPRoute.split('/') : null;\n const selectedPlanPolicy = selectedRouteInfo\n ? getPlanPolicyForRoute(selectedRouteInfo[0], selectedRouteInfo[1])\n : null;\n const planPolicyAcceptedCondition = selectedPlanPolicy?.status?.conditions?.find(\n (c: any) => c.type === \"Accepted\"\n );\n const selectedAuthPolicy = selectedRouteInfo\n ? getAuthPolicyForRoute(selectedRouteInfo[0], selectedRouteInfo[1])\n : null;\n const authPolicyAcceptedCondition = selectedAuthPolicy?.status?.conditions?.find(\n (c: any) => c.type === \"Accepted\"\n );\n const selectedRateLimitPolicy = selectedRouteInfo\n ? getRateLimitPolicyForRoute(selectedRouteInfo[0], selectedRouteInfo[1])\n : null;\n const rateLimitPolicyAcceptedCondition = selectedRateLimitPolicy?.status?.conditions?.find(\n (c: any) => c.type === \"Accepted\"\n );\n const planPolicyProps = {\n statusCondition: planPolicyAcceptedCondition,\n discoveredPlans: selectedPlanPolicy?.spec.plans,\n }\n const authPolicyProps = {\n namespacedName: {\n namespace: selectedAuthPolicy?.metadata.namespace,\n name: selectedAuthPolicy?.metadata.name,\n },\n statusCondition: authPolicyAcceptedCondition,\n }\n const rateLimitPolicyProps = {\n namespacedName: {\n namespace: selectedRateLimitPolicy?.metadata.namespace,\n name: selectedRateLimitPolicy?.metadata.name,\n },\n statusCondition: rateLimitPolicyAcceptedCondition,\n }\n\n // format tier info for dropdown display\n const formatTierInfo = (policy: any): string => {\n if (!policy?.spec?.plans) return '';\n const tiers = Object.entries(policy.spec.plans)\n .map(([name, plan]: [string, any]) => {\n const limit = plan?.limits?.requests;\n if (!limit) return name;\n return `${name}: ${limit.count}/${limit.period}`;\n })\n .join('; ');\n return tiers ? ` (${tiers})` : '';\n };\n\n // get policy info for a route (for dropdown display)\n const getPolicyInfoForRoute = (routeNamespace: string, routeName: string): string => {\n const policy = getPlanPolicyForRoute(routeNamespace, routeName);\n if (!policy) return 'N/A';\n return `${policy.metadata.name}${formatTierInfo(policy)}`;\n };\n\n useEffect(() => {\n if (open) {\n setNameError(null);\n setOpenAPISpecError(null);\n }\n }, [open]);\n\n // validate handlers\n const handleNameChange = (value: string) => {\n setName(value);\n setNameError(validateKubernetesName(value));\n };\n\n const handleDisplayNameChange = (value: string) => {\n setDisplayName(value);\n // Auto-generate Kubernetes resource name from display name with random hex suffix\n if (!name || name.match(/-[a-f0-9]{6}$/)) {\n const baseName = value.toLowerCase().replace(/[^a-z0-9-]/g, '-').replace(/-+/g, '-').replace(/^-|-$/g, '');\n const randomHex = Math.floor(Math.random() * 16777215).toString(16).padStart(6, '0');\n const autoName = `${baseName}-${randomHex}`;\n setName(autoName);\n setNameError(validateKubernetesName(autoName));\n }\n };\n\n const handleOpenAPISpecChange = (value: string) => {\n setOpenAPISpec(value);\n setOpenAPISpecError(validateURL(value));\n };\n\n const handleAddTag = () => {\n if (tagInput.trim() && !tags.includes(tagInput.trim())) {\n setTags([...tags, tagInput.trim()]);\n setTagInput('');\n }\n };\n\n const handleDeleteTag = (tagToDelete: string) => {\n setTags(tags.filter(tag => tag !== tagToDelete));\n };\n\n const handleClose = () => {\n setName('');\n setDisplayName('');\n setDescription('');\n setVersion('v1');\n setApprovalMode('manual');\n setPublishStatus('Published');\n setLifecycle('production');\n setTags([]);\n setTagInput('');\n setSelectedHTTPRoute('');\n setContactEmail('');\n setContactTeam('');\n setDocsURL('');\n setOpenAPISpec('');\n setError('');\n setNameError(null);\n setOpenAPISpecError(null);\n onClose();\n };\n\n const handleCreate = async () => {\n setError('');\n setCreating(true);\n\n try {\n if (!selectedHTTPRoute) {\n throw new Error('Please select an HTTPRoute');\n }\n\n const [selectedRouteNamespace, selectedRouteName] = selectedHTTPRoute.split('/');\n\n // derive namespace from selected httproute\n const namespace = selectedRouteNamespace;\n\n const apiProduct: APIProduct = {\n apiVersion: 'devportal.kuadrant.io/v1alpha1',\n kind: 'APIProduct',\n metadata: {\n name,\n namespace,\n labels: {\n lifecycle,\n },\n },\n spec: {\n displayName,\n description,\n version,\n approvalMode,\n publishStatus,\n tags,\n targetRef: {\n group: 'gateway.networking.k8s.io',\n kind: 'HTTPRoute',\n name: selectedRouteName,\n namespace: selectedRouteNamespace,\n },\n ...(contactEmail || contactTeam ? {\n contact: {\n ...(contactEmail && { email: contactEmail }),\n ...(contactTeam && { team: contactTeam }),\n },\n } : {}),\n ...(docsURL || openAPISpec ? {\n documentation: {\n ...(docsURL && { docsURL }),\n ...(openAPISpec && { openAPISpecURL: openAPISpec }),\n },\n } : {}),\n },\n };\n\n await kuadrantApi.createApiProduct(apiProduct);\n onSuccess({ namespace, name, displayName });\n handleClose();\n } catch (err) {\n setError(err instanceof Error ? err.message : String(err));\n } finally {\n setCreating(false);\n }\n };\n\n const hasValidationErrors = !!nameError || !!openAPISpecError;\n\n return (\n <Dialog open={open} onClose={handleClose} maxWidth=\"md\" fullWidth>\n <DialogTitle>Create API Product</DialogTitle>\n <DialogContent>\n {error && (\n <Alert severity=\"error\" style={{ marginBottom: 16 }}>\n {error}\n </Alert>\n )}\n {httpRoutesError && (\n <Alert severity=\"error\" style={{ marginBottom: 16 }}>\n <strong>Failed to load HTTPRoutes:</strong> {httpRoutesError.message}\n <Box mt={1}>\n <Button\n size=\"small\"\n variant=\"outlined\"\n onClick={() => setHttpRoutesRetry(prev => prev + 1)}\n >\n Retry\n </Button>\n </Box>\n </Alert>\n )}\n\n {planPoliciesError && (\n <Alert severity=\"warning\" style={{ marginBottom: 16 }}>\n <strong>Failed to load PlanPolicies:</strong> {planPoliciesError.message}\n <Typography variant=\"body2\" style={{ marginTop: 8 }}>\n You can still create the API Product, but plan information may be incomplete.\n </Typography>\n </Alert>\n )}\n {authPoliciesError && (\n <Alert severity=\"warning\" style={{ marginBottom: 16 }}>\n <strong>Failed to load AuthPolicies:</strong> {authPoliciesError.message}\n </Alert>\n )}\n {rateLimitPoliciesError && (\n <Alert severity=\"warning\" style={{ marginBottom: 16 }}>\n <strong>Failed to load RateLimitPolicies:</strong> {rateLimitPoliciesError.message}\n </Alert>\n )}\n {/* API product info section */}\n <Box className={classes.sectionHeader}>\n <Typography variant=\"subtitle1\"><strong>API product info</strong></Typography>\n </Box>\n <Grid container spacing={2}>\n <Grid item xs={6}>\n <TextField\n fullWidth\n label=\"API product name\"\n value={displayName}\n onChange={e => handleDisplayNameChange(e.target.value)}\n placeholder=\"My API\"\n helperText=\"Display name for your API product (shown to users)\"\n margin=\"normal\"\n required\n disabled={creating}\n InputLabelProps={{\n classes: {\n asterisk: classes.asterisk,\n },\n }}\n />\n </Grid>\n <Grid item xs={6}>\n <TextField\n fullWidth\n label=\"Kubernetes resource name\"\n value={name}\n onChange={e => handleNameChange(e.target.value)}\n placeholder=\"my-api\"\n helperText={nameError || \"Auto-generated from product name. Only lowercase, numbers, and hyphens allowed.\"}\n error={!!nameError}\n margin=\"normal\"\n required\n disabled={creating}\n InputLabelProps={{\n classes: {\n asterisk: classes.asterisk,\n },\n }}\n />\n </Grid>\n <Grid item xs={6}>\n <TextField\n fullWidth\n label=\"Version\"\n value={version}\n onChange={e => setVersion(e.target.value)}\n placeholder=\"v1\"\n helperText=\"Give a version to your API product\"\n margin=\"normal\"\n required\n disabled={creating}\n InputLabelProps={{\n classes: {\n asterisk: classes.asterisk,\n },\n }}\n />\n </Grid>\n <Grid item xs={6}>\n <TextField\n fullWidth\n label=\"Tag\"\n value={tagInput}\n onChange={e => setTagInput(e.target.value)}\n onKeyPress={e => {\n if (e.key === 'Enter') {\n e.preventDefault();\n handleAddTag();\n }\n }}\n placeholder=\"Add tag\"\n helperText=\"Add a tag to your API product\"\n margin=\"normal\"\n disabled={creating}\n InputProps={{\n endAdornment: tagInput ? (\n <InputAdornment position=\"end\">\n <IconButton size=\"small\" onClick={handleAddTag} disabled={creating}>\n <AddIcon fontSize=\"small\" />\n </IconButton>\n </InputAdornment>\n ) : undefined,\n }}\n />\n </Grid>\n {tags.length > 0 && (\n <Grid item xs={12}>\n <Box display=\"flex\" flexWrap=\"wrap\">\n {tags.map(tag => (\n <Chip\n key={tag}\n label={tag}\n onDelete={creating ? undefined : () => handleDeleteTag(tag)}\n size=\"small\"\n className={classes.tagChip}\n disabled={creating}\n />\n ))}\n </Box>\n </Grid>\n )}\n <Grid item xs={12}>\n <TextField\n fullWidth\n label=\"Description\"\n value={description}\n onChange={e => setDescription(e.target.value)}\n placeholder=\"API description\"\n margin=\"normal\"\n multiline\n rows={2}\n required\n disabled={creating}\n InputLabelProps={{\n classes: {\n asterisk: classes.asterisk,\n },\n }}\n />\n </Grid>\n </Grid>\n\n {/* Add API and Associate route section */}\n <Box className={classes.sectionHeader}>\n <Typography variant=\"subtitle1\"><strong>Add API and Associate route</strong></Typography>\n <Tooltip title=\"Register an existing API and associate HTTPRoute for your API product\">\n <InfoOutlinedIcon className={classes.infoIcon} />\n </Tooltip>\n </Box>\n <Grid container spacing={2}>\n <Grid item xs={12}>\n <TextField\n fullWidth\n label=\"OpenAPI Spec URL\"\n value={openAPISpec}\n onChange={e => handleOpenAPISpecChange(e.target.value)}\n placeholder=\"https://api.example.com/openapi.json\"\n helperText={openAPISpecError || \"Enter the full path to your API spec file\"}\n error={!!openAPISpecError}\n margin=\"normal\"\n required\n disabled={creating}\n InputLabelProps={{\n classes: {\n asterisk: classes.asterisk,\n },\n }}\n />\n </Grid>\n <Grid item xs={12}>\n <TextField\n fullWidth\n label=\"Documentation URL\"\n value={docsURL}\n onChange={e => setDocsURL(e.target.value)}\n placeholder=\"https://docs.example.com/api\"\n helperText=\"Link to external documentation for this API\"\n margin=\"normal\"\n disabled={creating}\n />\n </Grid>\n <Grid item xs={12}>\n <TextField\n fullWidth\n select\n label=\"HTTPRoute\"\n value={selectedHTTPRoute}\n onChange={e => setSelectedHTTPRoute(e.target.value)}\n margin=\"normal\"\n required\n helperText={\n httpRoutesError\n ? \"Unable to load HTTPRoutes. Please retry.\"\n : \"Select an HTTPRoute. APIProduct will be created in the same namespace.\"\n }\n error={!!httpRoutesError}\n disabled={httpRoutesLoading || creating || !!httpRoutesError}\n InputLabelProps={{\n classes: {\n asterisk: classes.asterisk,\n },\n }}\n SelectProps={{\n 'data-testid': 'httproute-select',\n MenuProps: {\n PaperProps: {\n style: { maxHeight: 400 },\n },\n anchorOrigin: {\n vertical: 'bottom',\n horizontal: 'left',\n },\n transformOrigin: {\n vertical: 'top',\n horizontal: 'left',\n },\n getContentAnchorEl: null,\n },\n } as any}\n >\n {/* Search bar inside dropdown */}\n <Box px={2} pt={1} pb={1} style={{ position: 'sticky', top: 0, zIndex: 1 }}>\n <TextField\n fullWidth\n size=\"small\"\n placeholder=\"Search...\"\n value={routeSearchTerm}\n onChange={e => setRouteSearchTerm(e.target.value)}\n onKeyDown={e => e.stopPropagation()}\n onClick={e => e.stopPropagation()}\n InputProps={{\n endAdornment: (\n <InputAdornment position=\"end\">\n <TextField\n select\n size=\"small\"\n value={routeSearchField}\n onChange={e => setRouteSearchField(e.target.value as 'name' | 'namespace' | 'planpolicy')}\n onKeyDown={e => e.stopPropagation()}\n onClick={e => e.stopPropagation()}\n style={{ minWidth: 120 }}\n variant=\"standard\"\n >\n <MenuItem value=\"name\">Name</MenuItem>\n <MenuItem value=\"namespace\">Namespace</MenuItem>\n <MenuItem value=\"planpolicy\">PlanPolicy</MenuItem>\n </TextField>\n </InputAdornment>\n ),\n }}\n />\n </Box>\n {httpRoutesLoading && (\n <MenuItem value=\"\">Loading...</MenuItem>\n )}\n {httpRoutesError && (\n <MenuItem value=\"\">Error loading routes</MenuItem>\n )}\n {!httpRoutesLoading && !httpRoutesError && httpRoutes && httpRoutes.length === 0 && (\n <MenuItem value=\"\">No HTTPRoutes available</MenuItem>\n )}\n {!httpRoutesLoading && !httpRoutesError && httpRoutes && httpRoutes\n .filter((route: any) => {\n if (!routeSearchTerm) return true;\n const routeNs = route.metadata.namespace;\n const routeName = route.metadata.name;\n const policyInfo = getPolicyInfoForRoute(routeNs, routeName);\n const searchLower = routeSearchTerm.toLowerCase();\n\n switch (routeSearchField) {\n case 'name':\n return routeName.toLowerCase().includes(searchLower);\n case 'namespace':\n return routeNs.toLowerCase().includes(searchLower);\n case 'planpolicy':\n return policyInfo.toLowerCase().includes(searchLower);\n default:\n return true;\n }\n })\n .map((route: any) => {\n const routeNs = route.metadata.namespace;\n const routeName = route.metadata.name;\n const policyInfo = getPolicyInfoForRoute(routeNs, routeName);\n return (\n <MenuItem\n key={`${routeNs}/${routeName}`}\n value={`${routeNs}/${routeName}`}\n >\n <Box>\n <Typography variant=\"body1\">{routeName}</Typography>\n <Typography variant=\"caption\" color=\"textSecondary\">\n Associated PlanPolicy: {policyInfo}\n </Typography>\n </Box>\n </MenuItem>\n );\n })}\n </TextField>\n </Grid>\n </Grid>\n\n {/* HTTPRoute policies section */}\n {selectedHTTPRoute && (\n <>\n <Box className={classes.sectionHeader}>\n <Typography variant=\"subtitle1\"><strong>HTTPRoute policies</strong></Typography>\n <Tooltip title=\"Shows the associated policies and rate limit tiers for the selected HTTPRoute\">\n <InfoOutlinedIcon className={classes.infoIcon} />\n </Tooltip>\n </Box>\n <ApiProductPolicies\n planPolicy={planPolicyProps}\n authPolicy={authPolicyProps}\n rateLimitPolicy={rateLimitPolicyProps}\n includeTopMargin={false}\n />\n </>\n )}\n\n <Box className={classes.sectionHeader}>\n <Typography variant=\"subtitle1\"><strong>Lifecycle and Visibility</strong></Typography>\n <Tooltip title=\"Control the lifecycle state and catalog visibility of this API product\">\n <InfoOutlinedIcon className={classes.infoIcon} />\n </Tooltip>\n </Box>\n <Grid container spacing={2}>\n <Grid item xs={6}>\n <TextField\n fullWidth\n select\n label=\"Lifecycle\"\n value={lifecycle}\n onChange={e => setLifecycle(e.target.value as Lifecycle)}\n margin=\"normal\"\n helperText=\"API lifecycle state\"\n disabled={creating}\n >\n <MenuItem value=\"experimental\">Experimental</MenuItem>\n <MenuItem value=\"production\">Production</MenuItem>\n <MenuItem value=\"deprecated\">Deprecated</MenuItem>\n <MenuItem value=\"retired\">Retired</MenuItem>\n </TextField>\n </Grid>\n <Grid item xs={6}>\n <TextField\n fullWidth\n select\n label=\"Publish Status\"\n value={publishStatus}\n onChange={e => setPublishStatus(e.target.value as 'Draft' | 'Published')}\n margin=\"normal\"\n helperText=\"Controls catalog visibility (Draft = hidden from consumers)\"\n disabled={creating}\n >\n <MenuItem value=\"Draft\">Draft</MenuItem>\n <MenuItem value=\"Published\">Published</MenuItem>\n </TextField>\n </Grid>\n </Grid>\n\n {/* API Key approval section */}\n <Box className={classes.sectionHeader}>\n <Typography variant=\"subtitle1\"><strong>API Key approval</strong></Typography>\n <Tooltip title=\"Choose how API key requests are handled for this product\">\n <InfoOutlinedIcon className={classes.infoIcon} />\n </Tooltip>\n </Box>\n <FormControl component=\"fieldset\" disabled={creating}>\n <RadioGroup\n row\n value={approvalMode}\n onChange={e => setApprovalMode(e.target.value as 'automatic' | 'manual')}\n >\n <FormControlLabel\n value=\"manual\"\n control={<Radio color=\"primary\" />}\n label={\n <Box>\n <Typography variant=\"body2\">Need manual approval</Typography>\n <Typography variant=\"caption\" color=\"textSecondary\">\n Requires approval for requesting this API\n </Typography>\n </Box>\n }\n />\n <FormControlLabel\n value=\"automatic\"\n control={<Radio color=\"primary\" />}\n label={\n <Box>\n <Typography variant=\"body2\">Automatic</Typography>\n <Typography variant=\"caption\" color=\"textSecondary\">\n Keys are created without need to be approved\n </Typography>\n </Box>\n }\n />\n </RadioGroup>\n </FormControl>\n </DialogContent>\n <DialogActions>\n <Button onClick={handleClose} disabled={creating}>Cancel</Button>\n <Button\n onClick={handleCreate}\n color=\"primary\"\n variant=\"contained\"\n disabled={creating || !name || !displayName || !description || !selectedHTTPRoute || hasValidationErrors}\n startIcon={creating ? <CircularProgress size={16} color=\"inherit\" /> : undefined}\n >\n {creating ? 'Creating...' : 'Create'}\n </Button>\n </DialogActions>\n </Dialog>\n );\n};\n","import React, { useState, useMemo, useCallback } from \"react\";\nimport {\n Typography,\n Box,\n Chip,\n Button,\n IconButton,\n CircularProgress,\n makeStyles,\n} from \"@material-ui/core\";\nimport AddIcon from \"@material-ui/icons/Add\";\nimport DeleteIcon from \"@material-ui/icons/Delete\";\nimport EditIcon from \"@material-ui/icons/Edit\";\nimport VpnKeyIcon from \"@material-ui/icons/VpnKey\";\nimport LockIcon from \"@material-ui/icons/Lock\";\nimport { FilterPanel, FilterSection, FilterState } from \"../FilterPanel\";\nimport {\n Header,\n Page,\n Content,\n SupportButton,\n ResponseErrorPanel,\n Link,\n Table,\n TableColumn,\n} from \"@backstage/core-components\";\nimport useAsync from \"react-use/lib/useAsync\";\nimport {\n useApi,\n alertApiRef,\n identityApiRef,\n} from \"@backstage/core-plugin-api\";\nimport { catalogApiRef } from \"@backstage/plugin-catalog-react\";\nimport {kuadrantApiRef, KuadrantList} from \"../../api\";\nimport { PermissionGate } from \"../PermissionGate\";\nimport { CreateAPIProductDialog } from \"../CreateAPIProductDialog\";\nimport {\n kuadrantApiProductCreatePermission,\n kuadrantApiProductDeleteOwnPermission,\n kuadrantApiProductDeleteAllPermission,\n kuadrantApiProductUpdateOwnPermission,\n kuadrantApiProductUpdateAllPermission,\n kuadrantApiProductListPermission,\n kuadrantPlanPolicyListPermission,\n} from \"../../permissions\";\nimport { useKuadrantPermission } from \"../../utils/permissions\";\nimport { EditAPIProductDialog } from \"../EditAPIProductDialog\";\nimport { ConfirmDeleteDialog } from \"../ConfirmDeleteDialog\";\nimport { getLifecycleChipStyle } from \"../../utils/styles\";\nimport emptyStateIllustration from \"../../assets/empty-state-illustration.png\";\nimport {APIProduct, PlanPolicy} from \"../../types/api-management.ts\";\n\nconst useStyles = makeStyles((theme) => ({\n container: {\n display: \"flex\",\n height: \"100%\",\n minHeight: 400,\n },\n tableContainer: {\n flex: 1,\n overflow: \"auto\",\n padding: 10,\n },\n emptyState: {\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n padding: theme.spacing(6),\n minHeight: 400,\n },\n emptyStateContent: {\n display: \"flex\",\n alignItems: \"center\",\n gap: theme.spacing(6),\n maxWidth: 900,\n },\n emptyStateText: {\n flex: 1,\n },\n emptyStateTitle: {\n marginBottom: theme.spacing(2),\n },\n emptyStateDescription: {\n marginBottom: theme.spacing(3),\n color: theme.palette.text.secondary,\n },\n emptyStateImage: {\n maxWidth: 400,\n height: \"auto\",\n },\n}));\n\nconst ResourceList = () => {\n const classes = useStyles();\n const kuadrantApi = useApi(kuadrantApiRef);\n const alertApi = useApi(alertApiRef);\n const identityApi = useApi(identityApiRef);\n const catalogApi = useApi(catalogApiRef);\n const [userEntityRef, setUserEntityRef] = useState<string>(\"\");\n const [createDialogOpen, setCreateDialogOpen] = useState(false);\n const [editDialogOpen, setEditDialogOpen] = useState(false);\n const [refreshTrigger, setRefreshTrigger] = useState(0);\n const [deleteDialogOpen, setDeleteDialogOpen] = useState(false);\n const [apiProductToDelete, setApiProductToDelete] = useState<{\n namespace: string;\n name: string;\n } | null>(null);\n const [apiProductToEdit, setApiProductToEdit] = useState<{\n namespace: string;\n name: string;\n } | null>(null);\n const [deleting, setDeleting] = useState(false);\n const [deleteStats, setDeleteStats] = useState<{\n requests: number;\n secrets: number;\n } | null>(null);\n const [filters, setFilters] = useState<FilterState>({\n status: [],\n lifecycle: [],\n policy: [],\n route: [],\n namespace: [],\n tags: [],\n authentication: [],\n });\n\n const {\n allowed: canCreateApiProduct,\n loading: createPermissionLoading,\n error: createPermissionError,\n } = useKuadrantPermission(kuadrantApiProductCreatePermission);\n\n const {\n allowed: canDeleteOwnApiProduct,\n loading: deleteOwnPermissionLoading,\n } = useKuadrantPermission(kuadrantApiProductDeleteOwnPermission);\n\n const {\n allowed: canDeleteAllApiProducts,\n loading: deleteAllPermissionLoading,\n error: deletePermissionError,\n } = useKuadrantPermission(kuadrantApiProductDeleteAllPermission);\n\n const { allowed: canUpdateOwnApiProduct } = useKuadrantPermission(\n kuadrantApiProductUpdateOwnPermission,\n );\n\n const { allowed: canUpdateAllApiProducts } = useKuadrantPermission(\n kuadrantApiProductUpdateAllPermission,\n );\n\n const deletePermissionLoading =\n deleteOwnPermissionLoading || deleteAllPermissionLoading;\n\n const {\n allowed: canListPlanPolicies,\n loading: planPolicyPermissionLoading,\n error: planPolicyPermissionError,\n } = useKuadrantPermission(kuadrantPlanPolicyListPermission);\n\n useAsync(async () => {\n const identity = await identityApi.getBackstageIdentity();\n setUserEntityRef(identity.userEntityRef);\n }, [identityApi]);\n\n const {\n value: apiProducts,\n loading: apiProductsLoading,\n error: apiProductsError,\n } = useAsync(async (): Promise<KuadrantList<APIProduct>> => {\n return kuadrantApi.getApiProducts();\n }, [kuadrantApi, refreshTrigger]);\n\n const {\n value: planPolicies,\n loading: planPoliciesLoading,\n error: planPoliciesError,\n } = useAsync(async (): Promise<KuadrantList<PlanPolicy>> => {\n // skip fetch if user doesn't have permission\n if (!canListPlanPolicies) {\n return { items: [] };\n }\n return kuadrantApi.getPlanPolicies();\n }, [kuadrantApi, refreshTrigger, canListPlanPolicies]);\n\n // fetch catalog entities synced from apiproducts to get lifecycle\n const { value: catalogEntities } = useAsync(async () => {\n const response = await catalogApi.getEntities({\n filter: {\n kind: 'API',\n 'metadata.labels.kuadrant.io/synced': 'true',\n },\n fields: ['metadata.name', 'spec.lifecycle'],\n });\n return response.items;\n }, [catalogApi, refreshTrigger]);\n\n // build name -> lifecycle lookup from catalog entities\n const lifecycleByName = useMemo(() => {\n const map = new Map<string, string>();\n if (catalogEntities) {\n for (const entity of catalogEntities) {\n const lifecycle = (entity.spec as any)?.lifecycle;\n if (lifecycle) {\n map.set(entity.metadata.name, lifecycle);\n }\n }\n }\n return map;\n }, [catalogEntities]);\n\n const getLifecycle = useCallback((product: APIProduct): string | undefined => {\n return lifecycleByName.get(product.metadata.name);\n }, [lifecycleByName]);\n\n // helper to find policy for a given route\n const getPolicyForProduct = useCallback((product: APIProduct): string | null => {\n if (!planPolicies?.items) return null;\n const targetRef = product.spec?.targetRef;\n if (!targetRef) return null;\n\n const policy = planPolicies.items.find((pp: PlanPolicy) => {\n const ref = (pp as any).spec.targetRef;\n return (\n ref?.kind === \"HTTPRoute\" &&\n ref?.name === targetRef.name &&\n (!ref?.namespace || ref?.namespace === (targetRef.namespace || product.metadata.namespace))\n );\n });\n return policy?.metadata.name || null;\n }, [planPolicies]);\n\n // helper to get auth schemes for a product\n const getAuthSchemes = useCallback((product: APIProduct): string[] => {\n const authSchemes = product.status?.discoveredAuthScheme?.authentication || {};\n const schemeObjects = Object.values(authSchemes);\n const schemes: string[] = [];\n\n if (schemeObjects.some((scheme: any) => scheme.hasOwnProperty(\"apiKey\"))) {\n schemes.push(\"API Key\");\n }\n if (schemeObjects.some((scheme: any) => scheme.hasOwnProperty(\"jwt\"))) {\n schemes.push(\"OIDC\");\n }\n if (schemes.length === 0) {\n schemes.push(\"Unknown\");\n }\n return schemes;\n }, []);\n\n const loading =\n apiProductsLoading ||\n planPoliciesLoading ||\n createPermissionLoading ||\n deletePermissionLoading ||\n planPolicyPermissionLoading;\n const error = apiProductsError || planPoliciesError;\n const permissionError =\n createPermissionError || deletePermissionError || planPolicyPermissionError;\n\n const allProducts = useMemo(() => {\n const products = apiProducts?.items || [];\n\n // API consumers (users without create/update permissions) should only see Published products\n // API owners can see all products (Draft and Published)\n if (!canCreateApiProduct && !canUpdateOwnApiProduct && !canUpdateAllApiProducts) {\n return products.filter((p: APIProduct) => {\n const publishStatus = p.spec?.publishStatus || 'Draft';\n return publishStatus === 'Published';\n });\n }\n\n return products;\n }, [apiProducts, canCreateApiProduct, canUpdateOwnApiProduct, canUpdateAllApiProducts]);\n\n const filterSections: FilterSection[] = useMemo(() => {\n const statusCounts = { Draft: 0, Published: 0 };\n const lifecycleCounts = new Map<string, number>();\n const policyCounts = new Map<string, number>();\n const routeCounts = new Map<string, number>();\n const namespaceCounts = new Map<string, number>();\n const tagCounts = new Map<string, number>();\n const authCounts = new Map<string, number>();\n\n allProducts.forEach((p: APIProduct) => {\n const status = p.spec?.publishStatus || \"Draft\";\n statusCounts[status as keyof typeof statusCounts]++;\n\n const lifecycle = getLifecycle(p);\n if (lifecycle) {\n lifecycleCounts.set(lifecycle, (lifecycleCounts.get(lifecycle) || 0) + 1);\n }\n\n const policy = getPolicyForProduct(p) || \"N/A\";\n policyCounts.set(policy, (policyCounts.get(policy) || 0) + 1);\n\n const route = p.spec?.targetRef?.name || \"unknown\";\n routeCounts.set(route, (routeCounts.get(route) || 0) + 1);\n\n const ns = p.metadata.namespace;\n namespaceCounts.set(ns, (namespaceCounts.get(ns) || 0) + 1);\n\n const tags = p.spec?.tags || [];\n tags.forEach((tag: string) => {\n tagCounts.set(tag, (tagCounts.get(tag) || 0) + 1);\n });\n\n const authSchemes = getAuthSchemes(p);\n authSchemes.forEach((scheme: string) => {\n authCounts.set(scheme, (authCounts.get(scheme) || 0) + 1);\n });\n });\n\n const sections: FilterSection[] = [\n {\n id: \"status\",\n title: \"Publish Status\",\n options: [\n { value: \"Draft\", label: \"Draft\", count: statusCounts.Draft },\n { value: \"Published\", label: \"Published\", count: statusCounts.Published },\n ],\n },\n {\n id: \"lifecycle\",\n title: \"Lifecycle\",\n options: Array.from(lifecycleCounts.entries()).map(([state, count]) => ({\n value: state,\n label: state.charAt(0).toUpperCase() + state.slice(1),\n count,\n })),\n },\n {\n id: \"authentication\",\n title: \"Authentication\",\n options: Array.from(authCounts.entries()).map(([scheme, count]) => ({\n value: scheme,\n label: scheme,\n count,\n })),\n },\n {\n id: \"route\",\n title: \"Route\",\n options: Array.from(routeCounts.entries()).map(([name, count]) => ({\n value: name,\n label: name,\n count,\n })),\n collapsed: routeCounts.size > 5,\n },\n {\n id: \"namespace\",\n title: \"Namespace\",\n options: Array.from(namespaceCounts.entries()).map(([ns, count]) => ({\n value: ns,\n label: ns,\n count,\n })),\n collapsed: namespaceCounts.size > 5,\n },\n {\n id: \"tags\",\n title: \"Tags\",\n options: Array.from(tagCounts.entries()).map(([tag, count]) => ({\n value: tag,\n label: tag,\n count,\n })),\n collapsed: tagCounts.size > 5,\n },\n ];\n\n // only show policy filter if user can list planpolicies\n if (canListPlanPolicies) {\n sections.splice(2, 0, {\n id: \"policy\",\n title: \"Policy\",\n options: Array.from(policyCounts.entries()).map(([name, count]) => ({\n value: name,\n label: name,\n count,\n })),\n collapsed: policyCounts.size > 5,\n });\n }\n\n return sections;\n }, [allProducts, getPolicyForProduct, getAuthSchemes, getLifecycle, canListPlanPolicies]);\n\n const filteredProducts = useMemo(() => {\n return allProducts.filter((p: APIProduct) => {\n if (filters.status.length > 0) {\n const status = p.spec?.publishStatus || \"Draft\";\n if (!filters.status.includes(status)) return false;\n }\n\n if (filters.lifecycle && filters.lifecycle.length > 0) {\n const lifecycle = getLifecycle(p);\n if (!lifecycle || !filters.lifecycle.includes(lifecycle)) return false;\n }\n\n if (filters.authentication.length > 0) {\n const authSchemes = getAuthSchemes(p);\n if (!filters.authentication.some((a: string) => authSchemes.includes(a))) return false;\n }\n\n if (filters.policy.length > 0) {\n const policy = getPolicyForProduct(p) || \"N/A\";\n if (!filters.policy.includes(policy)) return false;\n }\n\n if (filters.route.length > 0) {\n const route = p.spec?.targetRef?.name || \"unknown\";\n if (!filters.route.includes(route)) return false;\n }\n\n if (filters.namespace.length > 0) {\n if (!filters.namespace.includes(p.metadata.namespace)) return false;\n }\n\n if (filters.tags.length > 0) {\n const tags = p.spec?.tags || [];\n if (!filters.tags.some((t: string) => tags.includes(t))) return false;\n }\n\n return true;\n });\n }, [allProducts, filters, getPolicyForProduct, getAuthSchemes, getLifecycle]);\n\n const handleCreateSuccess = (productInfo: { namespace: string; name: string; displayName: string }) => {\n setRefreshTrigger((prev) => prev + 1);\n alertApi.post({\n message: `\"${productInfo.displayName}\" created successfully`,\n severity: \"success\",\n display: \"transient\",\n });\n };\n\n const handleEditClick = (namespace: string, name: string) => {\n setApiProductToEdit({ namespace, name });\n setEditDialogOpen(true);\n };\n\n const handleEditSuccess = () => {\n setRefreshTrigger((prev) => prev + 1);\n const productName = apiProductToEdit?.name || \"API Product\";\n alertApi.post({\n message: `\"${productName}\" updated successfully`,\n severity: \"success\",\n display: \"transient\",\n });\n };\n\n const handleDeleteClick = async (namespace: string, name: string) => {\n setApiProductToDelete({ namespace, name });\n setDeleteStats(null);\n\n try {\n const data = await kuadrantApi.getRequestsByNamespace(namespace);\n const related = (data.items || []).filter(\n (r: any) =>\n r.spec.apiName === name && r.spec.apiNamespace === namespace,\n );\n const approved = related.filter(\n (r: any) => r.status?.phase === \"Approved\",\n ).length;\n setDeleteStats({ requests: related.length, secrets: approved });\n } catch (err) {\n const errorMessage =\n err instanceof Error ? err.message : \"unknown error occurred\";\n alertApi.post({\n message: `Failed to delete access request: ${errorMessage}`,\n severity: \"error\",\n display: \"transient\",\n });\n } finally {\n setDeleteDialogOpen(true);\n }\n\n };\n\n const handleDeleteConfirm = async () => {\n if (!apiProductToDelete) return;\n\n setDeleting(true);\n try {\n await kuadrantApi.deleteApiProduct(\n apiProductToDelete.namespace,\n apiProductToDelete.name,\n );\n\n const deletedName = apiProductToDelete?.name || \"API Product\";\n setRefreshTrigger((prev) => prev + 1);\n alertApi.post({\n message: `\"${deletedName}\" deleted successfully`,\n severity: \"success\",\n display: \"transient\",\n });\n } catch (err) {\n const errorMessage =\n err instanceof Error ? err.message : \"unknown error occurred\";\n alertApi.post({\n message: `Failed to delete API Product: ${errorMessage}`,\n severity: \"error\",\n display: \"transient\",\n });\n } finally {\n setDeleting(false);\n setDeleteDialogOpen(false);\n setApiProductToDelete(null);\n }\n };\n\n const handleDeleteCancel = () => {\n setDeleteDialogOpen(false);\n setApiProductToDelete(null);\n };\n\n const handlePublishToggle = async (row: any) => {\n const namespace = row.metadata.namespace;\n const name = row.metadata.name;\n const displayName = row.spec?.displayName || name;\n const currentStatus = row.spec?.publishStatus || \"Draft\";\n const newStatus = currentStatus === \"Published\" ? \"Draft\" : \"Published\";\n // prevent publishing retired APIs\n if (newStatus === \"Published\" && getLifecycle(row) === \"retired\") {\n alertApi.post({\n message: `Cannot publish a retired API product. Please change the lifecycle status first.`,\n severity: \"error\",\n display: \"transient\",\n });\n return;\n }\n\n const productPatch: Partial<APIProduct> = {\n // @ts-ignore partial obj\n spec: {\n publishStatus: newStatus\n },\n }\n\n try {\n await kuadrantApi.updateApiProduct(namespace, name, productPatch);\n\n setRefreshTrigger((prev) => prev + 1);\n alertApi.post({\n message: `\"${displayName}\" ${newStatus === \"Published\" ? \"published\" : \"unpublished\"} successfully`,\n severity: \"success\",\n display: \"transient\",\n });\n } catch (err) {\n const errorMessage =\n err instanceof Error ? err.message : \"unknown error occurred\";\n alertApi.post({\n message: `Failed to update publish status: ${errorMessage}`,\n severity: \"error\",\n display: \"transient\",\n });\n }\n };\n\n const columns: TableColumn[] = [\n {\n title: \"Name\",\n field: \"spec.displayName\",\n render: (row: any) => {\n const displayName = row.spec?.displayName ?? row.metadata.name;\n return (\n <Link to={`/kuadrant/api-products/${row.metadata.namespace}/${row.metadata.name}`}>\n <strong>{displayName}</strong>\n </Link>\n );\n },\n customFilterAndSearch: (term, row: any) => {\n const displayName = row.spec?.displayName || row.metadata.name || \"\";\n return displayName.toLowerCase().includes(term.toLowerCase());\n },\n },\n {\n title: \"Version\",\n field: \"spec.version\",\n render: (row: any) => row.spec?.version || \"-\",\n },\n {\n title: \"Route\",\n field: \"spec.targetRef.name\",\n render: (row: any) => row.spec?.targetRef?.name || \"-\",\n },\n // only show policy column if user can list planpolicies\n ...(canListPlanPolicies\n ? [\n {\n title: \"Policy\",\n field: \"policy\",\n render: (row: any) => getPolicyForProduct(row) || \"N/A\",\n },\n ]\n : []),\n {\n title: \"Tags\",\n field: \"spec.tags\",\n render: (row: any) => {\n const tags = row.spec?.tags || [];\n if (tags.length === 0) return \"-\";\n return (\n <Box display=\"flex\" style={{ gap: 4, flexWrap: \"wrap\" }}>\n {tags.map((tag: string) => (\n <Chip key={tag} label={tag} size=\"small\" variant=\"outlined\" />\n ))}\n </Box>\n );\n },\n },\n {\n title: \"Status\",\n field: \"spec.publishStatus\",\n render: (row: any) => {\n const status = row.spec?.publishStatus || \"Draft\";\n return (\n <Chip\n label={status}\n size=\"small\"\n color={status === \"Published\" ? \"primary\" : \"default\"}\n />\n );\n },\n },\n {\n title: \"Lifecycle\",\n render: (row: any) => {\n const lifecycle = getLifecycle(row);\n if (!lifecycle) return \"-\";\n return (\n <Chip\n label={lifecycle.charAt(0).toUpperCase() + lifecycle.slice(1)}\n size=\"small\"\n style={getLifecycleChipStyle(lifecycle)}\n />\n );\n },\n },\n {\n title: \"Authentication\",\n field: \"status.discoveredAuthScheme\",\n render: (row: any) => {\n const authSchemes =\n row.status?.discoveredAuthScheme?.authentication || {};\n const schemeObjects = Object.values(authSchemes);\n\n const hasApiKey = schemeObjects.some((scheme: any) =>\n scheme.hasOwnProperty(\"apiKey\"),\n );\n const hasJwt = schemeObjects.some((scheme: any) =>\n scheme.hasOwnProperty(\"jwt\"),\n );\n\n if (!hasApiKey && !hasJwt) {\n return (\n <Typography variant=\"body2\" style={{ fontStyle: \"italic\" }}>\n unknown\n </Typography>\n );\n }\n\n return (\n <Box display=\"flex\" style={{ gap: 4 }}>\n {hasApiKey && (\n <Chip\n icon={<VpnKeyIcon />}\n label=\"API Key\"\n size=\"small\"\n color=\"primary\"\n />\n )}\n {hasJwt && (\n <Chip\n icon={<LockIcon />}\n label=\"OIDC\"\n size=\"small\"\n color=\"secondary\"\n />\n )}\n </Box>\n );\n },\n },\n {\n title: \"Namespace\",\n field: \"metadata.namespace\",\n },\n {\n title: \"Actions\",\n field: \"actions\",\n filtering: false,\n render: (row: any) => {\n const owner = row.metadata?.annotations?.[\"backstage.io/owner\"];\n const isOwner = owner === userEntityRef;\n const canEdit =\n canUpdateAllApiProducts || (canUpdateOwnApiProduct && isOwner);\n const canDelete =\n canDeleteAllApiProducts || (canDeleteOwnApiProduct && isOwner);\n const isPublished = row.spec?.publishStatus === \"Published\";\n\n return (\n <Box display=\"flex\" alignItems=\"center\" style={{ gap: 4 }}>\n {canEdit && (\n <Button\n size=\"small\"\n color=\"primary\"\n onClick={() => handlePublishToggle(row)}\n style={{ marginRight: 4, textTransform: \"none\" }}\n >\n {isPublished ? \"Unpublish\" : \"Publish\"}\n </Button>\n )}\n {canEdit && (\n <IconButton\n size=\"small\"\n onClick={() =>\n handleEditClick(row.metadata.namespace, row.metadata.name)\n }\n title=\"Edit API Product\"\n >\n <EditIcon fontSize=\"small\" />\n </IconButton>\n )}\n {canDelete && (\n <IconButton\n size=\"small\"\n onClick={() =>\n handleDeleteClick(row.metadata.namespace, row.metadata.name)\n }\n title=\"Delete API Product\"\n >\n <DeleteIcon fontSize=\"small\" />\n </IconButton>\n )}\n </Box>\n );\n },\n },\n ];\n\n return (\n <Page themeId=\"tool\">\n <Header\n title=\"API Products\"\n subtitle=\"Manage API products for Kubernetes\"\n >\n <SupportButton>Manage API products and plan policies</SupportButton>\n </Header>\n <Content>\n {loading && (\n <Box\n display=\"flex\"\n flexDirection=\"column\"\n alignItems=\"center\"\n justifyContent=\"center\"\n minHeight={300}\n >\n <CircularProgress />\n <Typography variant=\"h6\" style={{ marginTop: 16 }}>\n Loading data...\n </Typography>\n <Typography variant=\"body2\" color=\"textSecondary\">\n Preparing your data... This should only take a moment.\n </Typography>\n </Box>\n )}\n {error && <ResponseErrorPanel error={error} />}\n {permissionError && (\n <Box p={2}>\n <Typography color=\"error\">\n unable to check permissions: {permissionError.message}\n </Typography>\n <Typography variant=\"body2\" color=\"textSecondary\">\n permission:{\" \"}\n {createPermissionError\n ? \"kuadrant.apiproduct.create\"\n : deletePermissionError\n ? \"kuadrant.apiproduct.delete\"\n : planPolicyPermissionError\n ? \"kuadrant.planpolicy.list\"\n : \"unknown\"}\n </Typography>\n <Typography variant=\"body2\" color=\"textSecondary\">\n please try again or contact your administrator\n </Typography>\n </Box>\n )}\n {!loading && !error && !permissionError && allProducts.length === 0 && (\n <Box className={classes.emptyState}>\n <Box className={classes.emptyStateContent}>\n <Box className={classes.emptyStateText}>\n <Typography variant=\"h4\" className={classes.emptyStateTitle}>\n API Product\n </Typography>\n <Typography\n variant=\"body1\"\n className={classes.emptyStateDescription}\n >\n Create API product by registering existing API, associate\n route and policy\n </Typography>\n {canCreateApiProduct && (\n <Button\n variant=\"contained\"\n color=\"primary\"\n startIcon={<AddIcon />}\n onClick={() => setCreateDialogOpen(true)}\n >\n Create API Product\n </Button>\n )}\n </Box>\n <img\n src={emptyStateIllustration}\n alt=\"API Product illustration\"\n className={classes.emptyStateImage}\n />\n </Box>\n </Box>\n )}\n {!loading && !error && !permissionError && allProducts.length > 0 && (\n <Box className={classes.container}>\n <FilterPanel\n sections={filterSections}\n filters={filters}\n onChange={setFilters}\n />\n <Box className={classes.tableContainer}>\n <Box display=\"flex\" justifyContent=\"flex-end\" mb={2}>\n {canCreateApiProduct && (\n <Button\n variant=\"contained\"\n color=\"primary\"\n size=\"small\"\n startIcon={<AddIcon />}\n onClick={() => setCreateDialogOpen(true)}\n >\n Create API Product\n </Button>\n )}\n </Box>\n {filteredProducts.length === 0 ? (\n <Box p={4} textAlign=\"center\">\n <Typography variant=\"body1\" color=\"textSecondary\">\n No API products match the selected filters.\n </Typography>\n </Box>\n ) : (\n <Table\n options={{\n paging: filteredProducts.length > 10,\n pageSize: 20,\n search: true,\n filtering: false,\n debounceInterval: 300,\n toolbar: true,\n emptyRowsWhenPaging: false,\n }}\n columns={columns}\n data={filteredProducts}\n />\n )}\n </Box>\n </Box>\n )}\n <CreateAPIProductDialog\n open={createDialogOpen}\n onClose={() => setCreateDialogOpen(false)}\n onSuccess={handleCreateSuccess}\n />\n <EditAPIProductDialog\n open={editDialogOpen}\n onClose={() => setEditDialogOpen(false)}\n onSuccess={handleEditSuccess}\n namespace={apiProductToEdit?.namespace || \"\"}\n name={apiProductToEdit?.name || \"\"}\n />\n <ConfirmDeleteDialog\n open={deleteDialogOpen}\n title=\"Delete API Product\"\n description={\n deleteStats\n ? `Deleting \"${apiProductToDelete?.name}\" will also remove:\n\n• ${deleteStats.requests} API Key(s)\n• ${deleteStats.secrets} API Key Secret(s)\n\nThis action cannot be undone.`\n : `Deleting \"${apiProductToDelete?.name}\" will also remove all associated API Keys and Secrets.\nThis action cannot be undone.`\n }\n confirmText={apiProductToDelete?.name}\n severity=\"high\"\n deleting={deleting}\n onConfirm={handleDeleteConfirm}\n onCancel={handleDeleteCancel}\n />\n </Content>\n </Page>\n );\n};\n\nexport const ApiProductsPage = () => {\n return (\n <PermissionGate\n permission={kuadrantApiProductListPermission}\n errorMessage=\"you don't have permission to view the Kuadrant page\"\n >\n <ResourceList />\n </PermissionGate>\n );\n};\n"],"names":["useStyles","makeStyles","theme","root","width","minWidth","padding","spacing","borderRight","palette","divider","backgroundColor","background","paper","height","overflowY","sectionTitle","fontWeight","fontSize","textTransform","letterSpacing","color","text","secondary","marginBottom","display","alignItems","justifyContent","cursor","userSelect","filterSection","checkbox","checkboxLabel","clearButton","marginTop","count","marginLeft","FilterPanel","sections","filters","onChange","onClear","classes","collapsedSections","setCollapsedSections","React","Set","filter","s","collapsed","map","id","hasActiveFilters","Object","values","some","length","Box","className","mb","Typography","variant","Button","size","onClick","clearedFilters","forEach","section","Divider","isCollapsed","has","selectedCount","mt","toggleSection","sectionId","prev","next","delete","add","span","title","ExpandMoreIcon","ExpandLessIcon","Collapse","in","FormGroup","options","option","FormControlLabel","control","Checkbox","checked","includes","value","currentValues","newValues","v","handleCheckboxChange","label","undefined","PermissionGate","children","permission","fallback","errorMessage","allowed","loading","error","useKuadrantPermission","Progress","p","message","name","asterisk","sectionHeader","gap","infoIcon","tagChip","marginRight","CreateAPIProductDialog","open","onClose","onSuccess","selectedPlanPolicy","selectedAuthPolicy","selectedRateLimitPolicy","kuadrantApi","useApi","kuadrantApiRef","setName","useState","displayName","setDisplayName","description","setDescription","version","setVersion","approvalMode","setApprovalMode","publishStatus","setPublishStatus","lifecycle","setLifecycle","tags","setTags","tagInput","setTagInput","selectedHTTPRoute","setSelectedHTTPRoute","contactEmail","setContactEmail","contactTeam","setContactTeam","docsURL","setDocsURL","openAPISpec","setOpenAPISpec","setError","creating","setCreating","httpRoutesRetry","setHttpRoutesRetry","nameError","setNameError","openAPISpecError","setOpenAPISpecError","routeSearchTerm","setRouteSearchTerm","routeSearchField","setRouteSearchField","httpRoutes","httpRoutesLoading","httpRoutesError","useAsync","async","getHttpRoutes","items","planPolicies","planPoliciesError","getPlanPolicies","authPolicies","authPoliciesError","getAuthPolicies","rateLimitPolicies","rateLimitPoliciesError","getRateLimitPolicies","getPlanPolicyForRoute","routeNamespace","routeName","getPolicyForRoute","selectedRouteInfo","split","planPolicyAcceptedCondition","status","conditions","find","c","type","authPolicyAcceptedCondition","getRateLimitPolicyForRoute","rateLimitPolicyAcceptedCondition","planPolicyProps","statusCondition","discoveredPlans","spec","plans","authPolicyProps","namespacedName","namespace","metadata","rateLimitPolicyProps","getPolicyInfoForRoute","policy","tiers","entries","plan","limit","limits","requests","period","join","formatTierInfo","useEffect","handleAddTag","trim","handleClose","hasValidationErrors","Dialog","maxWidth","fullWidth","DialogTitle","DialogContent","Alert","severity","style","strong","Grid","container","item","xs","TextField","e","match","autoName","toLowerCase","replace","Math","floor","random","toString","padStart","validateKubernetesName","handleDisplayNameChange","target","placeholder","helperText","margin","required","disabled","InputLabelProps","handleNameChange","onKeyPress","key","preventDefault","InputProps","endAdornment","InputAdornment","position","IconButton","AddIcon","flexWrap","tag","Chip","onDelete","handleDeleteTag","tagToDelete","multiline","rows","Tooltip","InfoOutlinedIcon","handleOpenAPISpecChange","validateURL","select","SelectProps","MenuProps","PaperProps","maxHeight","anchorOrigin","vertical","horizontal","transformOrigin","getContentAnchorEl","px","pt","pb","top","zIndex","onKeyDown","stopPropagation","MenuItem","route","routeNs","policyInfo","searchLower","ApiProductPolicies","planPolicy","authPolicy","rateLimitPolicy","includeTopMargin","FormControl","component","RadioGroup","row","Radio","DialogActions","Error","selectedRouteNamespace","selectedRouteName","apiProduct","apiVersion","kind","labels","targetRef","group","contact","email","team","documentation","openAPISpecURL","createApiProduct","err","String","startIcon","CircularProgress","minHeight","tableContainer","flex","overflow","emptyState","emptyStateContent","emptyStateText","emptyStateTitle","emptyStateDescription","emptyStateImage","ResourceList","alertApi","alertApiRef","identityApi","identityApiRef","catalogApi","catalogApiRef","userEntityRef","setUserEntityRef","createDialogOpen","setCreateDialogOpen","editDialogOpen","setEditDialogOpen","refreshTrigger","setRefreshTrigger","deleteDialogOpen","setDeleteDialogOpen","apiProductToDelete","setApiProductToDelete","apiProductToEdit","setApiProductToEdit","deleting","setDeleting","deleteStats","setDeleteStats","setFilters","authentication","canCreateApiProduct","createPermissionLoading","createPermissionError","kuadrantApiProductCreatePermission","canDeleteOwnApiProduct","deleteOwnPermissionLoading","kuadrantApiProductDeleteOwnPermission","canDeleteAllApiProducts","deleteAllPermissionLoading","deletePermissionError","kuadrantApiProductDeleteAllPermission","canUpdateOwnApiProduct","kuadrantApiProductUpdateOwnPermission","canUpdateAllApiProducts","kuadrantApiProductUpdateAllPermission","deletePermissionLoading","canListPlanPolicies","planPolicyPermissionLoading","planPolicyPermissionError","kuadrantPlanPolicyListPermission","identity","getBackstageIdentity","apiProducts","apiProductsLoading","apiProductsError","getApiProducts","planPoliciesLoading","catalogEntities","getEntities","fields","lifecycleByName","useMemo","Map","entity","set","getLifecycle","useCallback","product","get","getPolicyForProduct","pp","ref","getAuthSchemes","authSchemes","discoveredAuthScheme","schemeObjects","schemes","scheme","hasOwnProperty","push","permissionError","allProducts","products","filterSections","statusCounts","Draft","Published","lifecycleCounts","policyCounts","routeCounts","namespaceCounts","tagCounts","authCounts","ns","Array","from","state","charAt","toUpperCase","slice","splice","filteredProducts","a","t","columns","field","render","Link","to","customFilterAndSearch","term","getLifecycleChipStyle","hasApiKey","hasJwt","icon","VpnKeyIcon","LockIcon","fontStyle","filtering","isOwner","annotations","canEdit","canDelete","isPublished","newStatus","post","productPatch","updateApiProduct","handlePublishToggle","handleEditClick","EditIcon","related","getRequestsByNamespace","r","apiName","apiNamespace","approved","phase","secrets","handleDeleteClick","DeleteIcon","Page","themeId","Header","subtitle","SupportButton","Content","flexDirection","ResponseErrorPanel","img","src","emptyStateIllustration","alt","textAlign","Table","paging","pageSize","search","debounceInterval","toolbar","emptyRowsWhenPaging","data","productInfo","EditAPIProductDialog","productName","ConfirmDeleteDialog","confirmText","onConfirm","deleteApiProduct","deletedName","onCancel","ApiProductsPage","kuadrantApiProductListPermission"],"sourceRoot":""}
@@ -1,2 +0,0 @@
1
- "use strict";(self.webpackChunkinternal_plugin_kuadrant=self.webpackChunkinternal_plugin_kuadrant||[]).push([[7057],{137:(e,a,n)=>{n.d(a,{A:()=>p});var t=n(89575),o=n(90689),r=n(39850),i=n(95478),l=n(36274),c=n(45065),d=n(41682),s=n(7031),u=n(29365),m=i.forwardRef(function(e,a){var n=e.autoFocus,s=e.checked,m=e.checkedIcon,p=e.classes,f=e.className,h=e.defaultChecked,v=e.disabled,b=e.icon,A=e.id,g=e.inputProps,k=e.inputRef,y=e.name,C=e.onBlur,E=e.onChange,x=e.onFocus,w=e.readOnly,R=e.required,S=e.tabIndex,P=e.type,N=e.value,I=(0,r.A)(e,["autoFocus","checked","checkedIcon","classes","className","defaultChecked","disabled","icon","id","inputProps","inputRef","name","onBlur","onChange","onFocus","readOnly","required","tabIndex","type","value"]),B=(0,c.A)({controlled:s,default:Boolean(h),name:"SwitchBase",state:"checked"}),z=(0,o.A)(B,2),L=z[0],F=z[1],$=(0,d.A)(),M=v;$&&void 0===M&&(M=$.disabled);var D="checkbox"===P||"radio"===P;return i.createElement(u.A,(0,t.A)({component:"span",className:(0,l.A)(p.root,f,L&&p.checked,M&&p.disabled),disabled:M,tabIndex:null,role:void 0,onFocus:function(e){x&&x(e),$&&$.onFocus&&$.onFocus(e)},onBlur:function(e){C&&C(e),$&&$.onBlur&&$.onBlur(e)},ref:a},I),i.createElement("input",(0,t.A)({autoFocus:n,checked:s,defaultChecked:h,className:p.input,disabled:M,id:D&&A,name:y,onChange:function(e){var a=e.target.checked;F(a),E&&E(e,a)},readOnly:w,ref:k,required:R,tabIndex:S,type:P,value:N},g)),L?m:b)});const p=(0,s.A)({root:{padding:9},checked:{},disabled:{},input:{cursor:"inherit",position:"absolute",opacity:0,width:"100%",height:"100%",top:0,left:0,margin:0,padding:0,zIndex:1}},{name:"PrivateSwitchBase"})(m)},12981:(e,a,n)=>{n.d(a,{A:()=>d});var t=n(89575),o=n(39850),r=n(95478),i=n(36274),l=n(7031),c=r.forwardRef(function(e,a){var n=e.classes,l=e.className,c=e.row,d=void 0!==c&&c,s=(0,o.A)(e,["classes","className","row"]);return r.createElement("div",(0,t.A)({className:(0,i.A)(n.root,l,d&&n.row),ref:a},s))});const d=(0,l.A)({root:{display:"flex",flexDirection:"column",flexWrap:"wrap"},row:{flexDirection:"row"}},{name:"MuiFormGroup"})(c)},29635:(e,a,n)=>{n.d(a,{A:()=>m});var t=n(89575),o=n(90689),r=n(39850),i=n(95478),l=n(12981),c=n(19878),d=n(45065),s=n(70108),u=n(18955);const m=i.forwardRef(function(e,a){var n=e.actions,m=e.children,p=e.name,f=e.value,h=e.onChange,v=(0,r.A)(e,["actions","children","name","value","onChange"]),b=i.useRef(null),A=(0,d.A)({controlled:f,default:e.defaultValue,name:"RadioGroup"}),g=(0,o.A)(A,2),k=g[0],y=g[1];i.useImperativeHandle(n,function(){return{focus:function(){var e=b.current.querySelector("input:not(:disabled):checked");e||(e=b.current.querySelector("input:not(:disabled)")),e&&e.focus()}}},[]);var C=(0,c.A)(a,b),E=(0,u.A)(p);return i.createElement(s.A.Provider,{value:{name:E,onChange:function(e){y(e.target.value),h&&h(e,e.target.value)},value:k}},i.createElement(l.A,(0,t.A)({role:"radiogroup",ref:C},v),m))})},30285:(e,a,n)=>{n.d(a,{A:()=>k});var t=n(89575),o=n(39850),r=n(95478),i=n(36274),l=n(137),c=n(38483);const d=(0,c.A)(r.createElement("path",{d:"M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.42 0-8-3.58-8-8s3.58-8 8-8 8 3.58 8 8-3.58 8-8 8z"}),"RadioButtonUnchecked"),s=(0,c.A)(r.createElement("path",{d:"M8.465 8.465C9.37 7.56 10.62 7 12 7C14.76 7 17 9.24 17 12C17 13.38 16.44 14.63 15.535 15.535C14.63 16.44 13.38 17 12 17C9.24 17 7 14.76 7 12C7 10.62 7.56 9.37 8.465 8.465Z"}),"RadioButtonChecked");var u=n(7031);const m=(0,u.A)(function(e){return{root:{position:"relative",display:"flex","&$checked $layer":{transform:"scale(1)",transition:e.transitions.create("transform",{easing:e.transitions.easing.easeOut,duration:e.transitions.duration.shortest})}},layer:{left:0,position:"absolute",transform:"scale(0)",transition:e.transitions.create("transform",{easing:e.transitions.easing.easeIn,duration:e.transitions.duration.shortest})},checked:{}}},{name:"PrivateRadioButtonIcon"})(function(e){var a=e.checked,n=e.classes,t=e.fontSize;return r.createElement("div",{className:(0,i.A)(n.root,a&&n.checked)},r.createElement(d,{fontSize:t}),r.createElement(s,{fontSize:t,className:n.layer}))});var p=n(268),f=n(11192),h=n(37260),v=n(66912),b=r.createElement(m,{checked:!0}),A=r.createElement(m,null),g=r.forwardRef(function(e,a){var n=e.checked,c=e.classes,d=e.color,s=void 0===d?"secondary":d,u=e.name,m=e.onChange,p=e.size,g=void 0===p?"medium":p,k=(0,o.A)(e,["checked","classes","color","name","onChange","size"]),y=(0,v.A)(),C=n,E=(0,h.A)(m,y&&y.onChange),x=u;return y&&(void 0===C&&(C=y.value===e.value),void 0===x&&(x=y.name)),r.createElement(l.A,(0,t.A)({color:s,type:"radio",icon:r.cloneElement(A,{fontSize:"small"===g?"small":"medium"}),checkedIcon:r.cloneElement(b,{fontSize:"small"===g?"small":"medium"}),classes:{root:(0,i.A)(c.root,c["color".concat((0,f.A)(s))]),checked:c.checked,disabled:c.disabled},name:x,checked:C,onChange:E,ref:a},k))});const k=(0,u.A)(function(e){return{root:{color:e.palette.text.secondary},checked:{},disabled:{},colorPrimary:{"&$checked":{color:e.palette.primary.main,"&:hover":{backgroundColor:(0,p.X4)(e.palette.primary.main,e.palette.action.hoverOpacity),"@media (hover: none)":{backgroundColor:"transparent"}}},"&$disabled":{color:e.palette.action.disabled}},colorSecondary:{"&$checked":{color:e.palette.secondary.main,"&:hover":{backgroundColor:(0,p.X4)(e.palette.secondary.main,e.palette.action.hoverOpacity),"@media (hover: none)":{backgroundColor:"transparent"}}},"&$disabled":{color:e.palette.action.disabled}}}},{name:"MuiRadio"})(g)},34839:(e,a,n)=>{n.d(a,{A:()=>u});var t=n(89575),o=n(39850),r=n(95478),i=n(36274),l=n(72501),c=n(7031),d=n(42062),s=r.forwardRef(function(e,a){var n=e.children,c=e.classes,s=e.className,u=e.component,m=void 0===u?"div":u,p=e.disablePointerEvents,f=void 0!==p&&p,h=e.disableTypography,v=void 0!==h&&h,b=e.position,A=e.variant,g=(0,o.A)(e,["children","classes","className","component","disablePointerEvents","disableTypography","position","variant"]),k=(0,d.t)()||{},y=A;return A&&k.variant,k&&!y&&(y=k.variant),r.createElement(d.A.Provider,{value:null},r.createElement(m,(0,t.A)({className:(0,i.A)(c.root,s,"end"===b?c.positionEnd:c.positionStart,f&&c.disablePointerEvents,k.hiddenLabel&&c.hiddenLabel,"filled"===y&&c.filled,"dense"===k.margin&&c.marginDense),ref:a},g),"string"!=typeof n||v?n:r.createElement(l.A,{color:"textSecondary"},n)))});const u=(0,c.A)({root:{display:"flex",height:"0.01em",maxHeight:"2em",alignItems:"center",whiteSpace:"nowrap"},filled:{"&$positionStart:not($hiddenLabel)":{marginTop:16}},positionStart:{marginRight:8},positionEnd:{marginLeft:8},disablePointerEvents:{pointerEvents:"none"},hiddenLabel:{},marginDense:{}},{name:"MuiInputAdornment"})(s)},59461:(e,a,n)=>{n.d(a,{A:()=>c});var t=n(89575),o=n(95478),r=n(7031),i=n(72501),l=o.forwardRef(function(e,a){return o.createElement(i.A,(0,t.A)({component:"p",variant:"body1",color:"textSecondary",ref:a},e))});const c=(0,r.A)({root:{marginBottom:12}},{name:"MuiDialogContentText"})(l)},66912:(e,a,n)=>{n.d(a,{A:()=>r});var t=n(95478),o=n(70108);function r(){return t.useContext(o.A)}},70108:(e,a,n)=>{n.d(a,{A:()=>t});const t=n(95478).createContext()},75625:(e,a,n)=>{var t=n(4293),o=n(78920);a.A=void 0;var r=o(n(95478)),i=(0,t(n(74044)).default)(r.createElement("path",{d:"M3 17.25V21h3.75L17.81 9.94l-3.75-3.75L3 17.25zM20.71 7.04c.39-.39.39-1.02 0-1.41l-2.34-2.34a.9959.9959 0 00-1.41 0l-1.83 1.83 3.75 3.75 1.83-1.83z"}),"Edit");a.A=i},86901:(e,a,n)=>{n.d(a,{A:()=>m});var t=n(89575),o=n(39850),r=n(95478),i=n(36274),l=n(41682),c=n(7031),d=n(72501),s=n(11192),u=r.forwardRef(function(e,a){e.checked;var n=e.classes,c=e.className,u=e.control,m=e.disabled,p=(e.inputRef,e.label),f=e.labelPlacement,h=void 0===f?"end":f,v=(e.name,e.onChange,e.value,(0,o.A)(e,["checked","classes","className","control","disabled","inputRef","label","labelPlacement","name","onChange","value"])),b=(0,l.A)(),A=m;void 0===A&&void 0!==u.props.disabled&&(A=u.props.disabled),void 0===A&&b&&(A=b.disabled);var g={disabled:A};return["checked","name","onChange","value","inputRef"].forEach(function(a){void 0===u.props[a]&&void 0!==e[a]&&(g[a]=e[a])}),r.createElement("label",(0,t.A)({className:(0,i.A)(n.root,c,"end"!==h&&n["labelPlacement".concat((0,s.A)(h))],A&&n.disabled),ref:a},v),r.cloneElement(u,g),r.createElement(d.A,{component:"span",className:(0,i.A)(n.label,A&&n.disabled)},p))});const m=(0,c.A)(function(e){return{root:{display:"inline-flex",alignItems:"center",cursor:"pointer",verticalAlign:"middle",WebkitTapHighlightColor:"transparent",marginLeft:-11,marginRight:16,"&$disabled":{cursor:"default"}},labelPlacementStart:{flexDirection:"row-reverse",marginLeft:16,marginRight:-11},labelPlacementTop:{flexDirection:"column-reverse",marginLeft:16},labelPlacementBottom:{flexDirection:"column",marginLeft:16},disabled:{},label:{"&$disabled":{color:e.palette.text.disabled}}}},{name:"MuiFormControlLabel"})(u)}}]);
2
- //# sourceMappingURL=7057.fcd688c7.chunk.js.map