@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
@@ -3,8 +3,9 @@ import { useNavigate } from 'react-router-dom';
3
3
  import { ResponseErrorPanel, Table, Link } from '@backstage/core-components';
4
4
  import { useApi, alertApiRef } from '@backstage/core-plugin-api';
5
5
  import { kuadrantApiRef } from '../../api.esm.js';
6
+ import { getAPIKeyPhase } from '../../utils/apikeys.esm.js';
6
7
  import useAsync from 'react-use/lib/useAsync';
7
- import { makeStyles, Box, Button, Typography, Menu, MenuItem, Dialog, DialogTitle, DialogContent, DialogActions, Chip, Tooltip, IconButton, CircularProgress } from '@material-ui/core';
8
+ import { makeStyles, Box, Button, Typography, Dialog, DialogTitle, DialogContent, DialogActions, Chip, Tooltip, IconButton, CircularProgress } from '@material-ui/core';
8
9
  import { Skeleton } from '@material-ui/lab';
9
10
  import { SimpleRequestAccessDialog } from '../SimpleRequestAccessDialog/SimpleRequestAccessDialog.esm.js';
10
11
  import VisibilityIcon from '@material-ui/icons/Visibility';
@@ -12,7 +13,6 @@ import VisibilityOffIcon from '@material-ui/icons/VisibilityOff';
12
13
  import FileCopyIcon from '@material-ui/icons/FileCopy';
13
14
  import WarningIcon from '@material-ui/icons/Warning';
14
15
  import DeleteIcon from '@material-ui/icons/Delete';
15
- import { EditAPIKeyDialog } from '../EditAPIKeyDialog/EditAPIKeyDialog.esm.js';
16
16
  import { ConfirmDeleteDialog } from '../ConfirmDeleteDialog/ConfirmDeleteDialog.esm.js';
17
17
  import { FilterPanel } from '../FilterPanel/FilterPanel.esm.js';
18
18
  import { getMyApiKeysStatusChipStyle } from '../../utils/styles.esm.js';
@@ -52,9 +52,9 @@ const useStyles = makeStyles((theme) => ({
52
52
  }));
53
53
  const ExpandedRowContent = ({ request }) => {
54
54
  const classes = useStyles();
55
- const isRejected = request.status?.phase === "Rejected";
55
+ const isRejected = getAPIKeyPhase(request.status?.conditions) === "Denied";
56
56
  const apiProductName = request.spec.apiProductRef?.name || "unknown";
57
- return /* @__PURE__ */ React.createElement(Box, { className: classes.useCasePanel, onClick: (e) => e.stopPropagation() }, isRejected && /* @__PURE__ */ React.createElement(Box, { className: classes.rejectedBanner }, /* @__PURE__ */ React.createElement(WarningIcon, { color: "error", fontSize: "small" }), /* @__PURE__ */ React.createElement(Typography, { variant: "body2" }, "This API key was rejected.", " ", /* @__PURE__ */ React.createElement(Link, { to: `/catalog/default/api/${apiProductName}/api-keys` }, "Request a new API key"))), /* @__PURE__ */ React.createElement(Typography, { className: classes.useCaseLabel }, "Use Case"), /* @__PURE__ */ React.createElement(Typography, { variant: "body2" }, request.spec.useCase || "No use case provided"));
57
+ return /* @__PURE__ */ React.createElement(Box, { className: classes.useCasePanel, onClick: (e) => e.stopPropagation() }, isRejected && /* @__PURE__ */ React.createElement(Box, { className: classes.rejectedBanner }, /* @__PURE__ */ React.createElement(WarningIcon, { color: "error", fontSize: "small" }), /* @__PURE__ */ React.createElement(Typography, { variant: "body2" }, "This API key was denied.", " ", /* @__PURE__ */ React.createElement(Link, { to: `/catalog/default/api/${apiProductName}/api-keys` }, "Request a new API key"))), /* @__PURE__ */ React.createElement(Typography, { className: classes.useCaseLabel }, "Use Case"), /* @__PURE__ */ React.createElement(Typography, { variant: "body2" }, request.spec.useCase || "No use case provided"));
58
58
  };
59
59
  const MyApiKeysTable = () => {
60
60
  const classes = useStyles();
@@ -63,9 +63,6 @@ const MyApiKeysTable = () => {
63
63
  const alertApi = useApi(alertApiRef);
64
64
  const [requestDialogOpen, setRequestDialogOpen] = useState(false);
65
65
  const [visibleKeys, setVisibleKeys] = useState(/* @__PURE__ */ new Set());
66
- const [menuAnchor, setMenuAnchor] = useState(null);
67
- const [menuRequest, setMenuRequest] = useState(null);
68
- const [editDialogState, setEditDialogState] = useState({ open: false, request: null, plans: [] });
69
66
  const [refresh, setRefresh] = useState(0);
70
67
  const [deleting, setDeleting] = useState(null);
71
68
  const [deleteDialogState, setDeleteDialogState] = useState({ open: false, request: null });
@@ -73,9 +70,6 @@ const MyApiKeysTable = () => {
73
70
  /* @__PURE__ */ new Map()
74
71
  );
75
72
  const [apiKeyLoading, setApiKeyLoading] = useState(/* @__PURE__ */ new Set());
76
- const [alreadyReadKeys, setAlreadyReadKeys] = useState(
77
- /* @__PURE__ */ new Set()
78
- );
79
73
  const [showOnceWarningOpen, setShowOnceWarningOpen] = useState(false);
80
74
  const [pendingKeyReveal, setPendingKeyReveal] = useState(null);
81
75
  const [optimisticallyDeleted, setOptimisticallyDeleted] = useState(/* @__PURE__ */ new Set());
@@ -109,12 +103,13 @@ const MyApiKeysTable = () => {
109
103
  (r) => !optimisticallyDeleted.has(r.metadata.name)
110
104
  );
111
105
  }, [data?.requests, optimisticallyDeleted]);
106
+ const toUiStatus = (phase) => phase;
112
107
  const filterSections = useMemo(() => {
113
- const statusCounts = { Approved: 0, Pending: 0, Rejected: 0 };
108
+ const statusCounts = { Approved: 0, Pending: 0, Denied: 0, Failed: 0 };
114
109
  const apiProductCounts = /* @__PURE__ */ new Map();
115
110
  const tierCounts = /* @__PURE__ */ new Map();
116
111
  allRequests.forEach((r) => {
117
- const status = r.status?.phase || "Pending";
112
+ const status = toUiStatus(getAPIKeyPhase(r.status?.conditions));
118
113
  statusCounts[status]++;
119
114
  const apiProduct = r.spec.apiProductRef?.name || "unknown";
120
115
  apiProductCounts.set(
@@ -132,10 +127,11 @@ const MyApiKeysTable = () => {
132
127
  { value: "Approved", label: "Active", count: statusCounts.Approved },
133
128
  { value: "Pending", label: "Pending", count: statusCounts.Pending },
134
129
  {
135
- value: "Rejected",
136
- label: "Rejected",
137
- count: statusCounts.Rejected
138
- }
130
+ value: "Denied",
131
+ label: "Denied",
132
+ count: statusCounts.Denied
133
+ },
134
+ { value: "Failed", label: "Failed", count: statusCounts.Failed }
139
135
  ]
140
136
  },
141
137
  {
@@ -164,7 +160,7 @@ const MyApiKeysTable = () => {
164
160
  const filteredRequests = useMemo(() => {
165
161
  return allRequests.filter((r) => {
166
162
  if (filters.status.length > 0) {
167
- const status = r.status?.phase || "Pending";
163
+ const status = toUiStatus(getAPIKeyPhase(r.status?.conditions));
168
164
  if (!filters.status.includes(status)) return false;
169
165
  }
170
166
  if (filters.apiProduct.length > 0) {
@@ -196,23 +192,13 @@ const MyApiKeysTable = () => {
196
192
  try {
197
193
  const result = await kuadrantApi.getApiKeySecret(requestNamespace, requestName);
198
194
  setApiKeyValues((prev) => new Map(prev).set(key, result.apiKey));
199
- setAlreadyReadKeys((prev) => new Set(prev).add(key));
200
195
  } catch (err) {
201
196
  const errorMessage = err instanceof Error ? err.message : "unknown error occurred";
202
- if (errorMessage.includes("403") || errorMessage.includes("already been viewed")) {
203
- setAlreadyReadKeys((prev) => new Set(prev).add(key));
204
- alertApi.post({
205
- message: "This API key has already been viewed and cannot be retrieved again.",
206
- severity: "warning",
207
- display: "transient"
208
- });
209
- } else {
210
- alertApi.post({
211
- message: `Failed to fetch api key: ${errorMessage}`,
212
- severity: "error",
213
- display: "transient"
214
- });
215
- }
197
+ alertApi.post({
198
+ message: `Failed to fetch api key: ${errorMessage}`,
199
+ severity: "error",
200
+ display: "transient"
201
+ });
216
202
  } finally {
217
203
  setApiKeyLoading((prev) => {
218
204
  const next = new Set(prev);
@@ -229,37 +215,6 @@ const MyApiKeysTable = () => {
229
215
  return next;
230
216
  });
231
217
  };
232
- const handleMenuClose = () => {
233
- setMenuAnchor(null);
234
- setMenuRequest(null);
235
- };
236
- const handleEdit = async () => {
237
- if (!menuRequest) return;
238
- const request = menuRequest;
239
- handleMenuClose();
240
- try {
241
- const apiProductName = request.spec.apiProductRef?.name;
242
- const apiProductNamespace = request.metadata.namespace;
243
- const apiProduct = await kuadrantApi.getApiProduct(apiProductNamespace, apiProductName);
244
- const plans = apiProduct.status?.discoveredPlans || [];
245
- setEditDialogState({ open: true, request, plans });
246
- } catch (err) {
247
- console.error("Error fetching plans:", err);
248
- setEditDialogState({ open: true, request: menuRequest, plans: [] });
249
- const errorMessage = err instanceof Error ? err.message : "unknown error occurred";
250
- alertApi.post({
251
- message: `Failed to fetch Plans. ${errorMessage}`,
252
- severity: "error",
253
- display: "transient"
254
- });
255
- }
256
- };
257
- const handleDeleteClick = () => {
258
- if (!menuRequest) return;
259
- const request = menuRequest;
260
- handleMenuClose();
261
- setDeleteDialogState({ open: true, request });
262
- };
263
218
  const handleDeleteConfirm = async () => {
264
219
  if (!deleteDialogState.request) return;
265
220
  const request = deleteDialogState.request;
@@ -316,10 +271,11 @@ const MyApiKeysTable = () => {
316
271
  },
317
272
  {
318
273
  title: "Status",
319
- field: "status.phase",
274
+ field: "status.conditions",
320
275
  render: (row) => {
321
- const phase = row.status?.phase || "Pending";
322
- const label = phase === "Approved" ? "Active" : phase;
276
+ const phase = getAPIKeyPhase(row.status?.conditions);
277
+ const displayPhase = toUiStatus(phase);
278
+ const label = displayPhase === "Approved" ? "Active" : displayPhase;
323
279
  return /* @__PURE__ */ React.createElement(Chip, { label, size: "small", style: getMyApiKeysStatusChipStyle(phase) });
324
280
  }
325
281
  },
@@ -333,35 +289,18 @@ const MyApiKeysTable = () => {
333
289
  field: "status.secretRef",
334
290
  filtering: false,
335
291
  render: (row) => {
336
- if (row.status?.phase !== "Approved") {
292
+ if (getAPIKeyPhase(row.status?.conditions) !== "Approved") {
337
293
  return /* @__PURE__ */ React.createElement(Typography, { variant: "body2", color: "textSecondary" }, "-");
338
294
  }
339
295
  const key = `${row.metadata.namespace}/${row.metadata.name}`;
340
- const hasSecretRef = row.status?.secretRef?.name;
341
296
  const isVisible = visibleKeys.has(row.metadata.name);
342
297
  const isLoading = apiKeyLoading.has(key);
343
298
  const apiKeyValue = apiKeyValues.get(key);
344
- const canReadSecret = row.status?.canReadSecret !== false;
345
- const isAlreadyRead = alreadyReadKeys.has(key) || !canReadSecret;
346
- if (!hasSecretRef) {
347
- return /* @__PURE__ */ React.createElement(Typography, { variant: "body2", color: "textSecondary" }, "Awaiting secret...");
348
- }
349
- if (isAlreadyRead && !apiKeyValue) {
350
- return /* @__PURE__ */ React.createElement(Tooltip, { title: "This API key has already been viewed and cannot be retrieved again" }, /* @__PURE__ */ React.createElement(Box, { display: "flex", alignItems: "center" }, /* @__PURE__ */ React.createElement(
351
- Typography,
352
- {
353
- variant: "body2",
354
- color: "textSecondary",
355
- style: { fontFamily: "monospace", marginRight: 8 }
356
- },
357
- "Already viewed"
358
- ), /* @__PURE__ */ React.createElement(VisibilityOffIcon, { fontSize: "small", color: "disabled" })));
359
- }
360
299
  const handleRevealClick = () => {
361
300
  if (isVisible) {
362
301
  clearApiKeyValue(row.metadata.namespace, row.metadata.name);
363
302
  toggleKeyVisibility(row.metadata.name);
364
- } else if (!isAlreadyRead) {
303
+ } else {
365
304
  setPendingKeyReveal({
366
305
  namespace: row.metadata.namespace,
367
306
  name: row.metadata.name
@@ -379,17 +318,17 @@ const MyApiKeysTable = () => {
379
318
  });
380
319
  }
381
320
  };
382
- return /* @__PURE__ */ React.createElement(Box, { display: "flex", alignItems: "center", style: { gap: 8 } }, /* @__PURE__ */ React.createElement(Box, { fontFamily: "monospace", fontSize: "0.875rem" }, isLoading ? "Loading..." : isVisible && apiKeyValue ? apiKeyValue : "\u2022".repeat(20) + "..."), isVisible && apiKeyValue && /* @__PURE__ */ React.createElement(Tooltip, { title: "Copy to clipboard" }, /* @__PURE__ */ React.createElement(IconButton, { size: "small", onClick: handleCopy }, /* @__PURE__ */ React.createElement(FileCopyIcon, { fontSize: "small" }))), /* @__PURE__ */ React.createElement(
321
+ return /* @__PURE__ */ React.createElement(Box, { display: "flex", alignItems: "center", style: { gap: 8 } }, /* @__PURE__ */ React.createElement(Box, { fontFamily: "monospace", fontSize: "0.875rem" }, isLoading ? "Loading..." : isVisible && apiKeyValue ? apiKeyValue : "\u2022".repeat(20)), isVisible && apiKeyValue && /* @__PURE__ */ React.createElement(Tooltip, { title: "Copy to clipboard" }, /* @__PURE__ */ React.createElement(IconButton, { size: "small", onClick: handleCopy }, /* @__PURE__ */ React.createElement(FileCopyIcon, { fontSize: "small" }))), /* @__PURE__ */ React.createElement(
383
322
  Tooltip,
384
323
  {
385
- title: isVisible ? "Hide API key" : "Reveal API key (one-time only)"
324
+ title: isVisible ? "Hide API key" : "Reveal API key"
386
325
  },
387
326
  /* @__PURE__ */ React.createElement("span", null, /* @__PURE__ */ React.createElement(
388
327
  IconButton,
389
328
  {
390
329
  size: "small",
391
330
  onClick: handleRevealClick,
392
- disabled: isLoading || isAlreadyRead && !apiKeyValue
331
+ disabled: isLoading
393
332
  },
394
333
  isVisible ? /* @__PURE__ */ React.createElement(VisibilityOffIcon, { fontSize: "small" }) : /* @__PURE__ */ React.createElement(VisibilityIcon, { fontSize: "small" })
395
334
  ))
@@ -462,7 +401,6 @@ const MyApiKeysTable = () => {
462
401
  if (error) {
463
402
  return /* @__PURE__ */ React.createElement(ResponseErrorPanel, { error });
464
403
  }
465
- const isPending = (row) => !row.status || row.status.phase === "Pending";
466
404
  return /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(Box, { display: "flex", justifyContent: "flex-end", mb: 2, px: 2 }, /* @__PURE__ */ React.createElement(
467
405
  Button,
468
406
  {
@@ -499,54 +437,6 @@ const MyApiKeysTable = () => {
499
437
  detailPanel: detailPanelConfig
500
438
  }
501
439
  ))), /* @__PURE__ */ React.createElement(
502
- Menu,
503
- {
504
- id: "myapikeys-menu",
505
- open: Boolean(menuAnchor),
506
- onClose: handleMenuClose,
507
- anchorReference: "anchorPosition",
508
- anchorPosition: menuAnchor || { top: 0, left: 0 }
509
- },
510
- menuRequest && (() => {
511
- const items = [];
512
- items.push(
513
- /* @__PURE__ */ React.createElement(
514
- MenuItem,
515
- {
516
- key: "view",
517
- onClick: () => {
518
- navigate(
519
- `/kuadrant/api-keys/${menuRequest.metadata.namespace}/${menuRequest.metadata.name}`
520
- );
521
- handleMenuClose();
522
- }
523
- },
524
- "View Details"
525
- )
526
- );
527
- if (isPending(menuRequest)) {
528
- items.push(
529
- /* @__PURE__ */ React.createElement(MenuItem, { key: "edit", onClick: handleEdit }, "Edit")
530
- );
531
- }
532
- items.push(
533
- /* @__PURE__ */ React.createElement(MenuItem, { key: "delete", onClick: handleDeleteClick }, "Delete")
534
- );
535
- return items;
536
- })()
537
- ), editDialogState.request && /* @__PURE__ */ React.createElement(
538
- EditAPIKeyDialog,
539
- {
540
- open: editDialogState.open,
541
- request: editDialogState.request,
542
- availablePlans: editDialogState.plans,
543
- onClose: () => setEditDialogState({ open: false, request: null, plans: [] }),
544
- onSuccess: () => {
545
- setEditDialogState({ open: false, request: null, plans: [] });
546
- setRefresh((r) => r + 1);
547
- }
548
- }
549
- ), /* @__PURE__ */ React.createElement(
550
440
  ConfirmDeleteDialog,
551
441
  {
552
442
  open: deleteDialogState.open,
@@ -567,7 +457,7 @@ const MyApiKeysTable = () => {
567
457
  maxWidth: "sm"
568
458
  },
569
459
  /* @__PURE__ */ React.createElement(DialogTitle, null, /* @__PURE__ */ React.createElement(Box, { display: "flex", alignItems: "center" }, /* @__PURE__ */ React.createElement(WarningIcon, { color: "primary", style: { marginRight: 8 } }), "View API Key")),
570
- /* @__PURE__ */ React.createElement(DialogContent, null, /* @__PURE__ */ React.createElement(Typography, { variant: "body1", paragraph: true }, "This API key can only be viewed ", /* @__PURE__ */ React.createElement("strong", null, "once"), ". After you reveal it, you will not be able to retrieve it again."), /* @__PURE__ */ React.createElement(Typography, { variant: "body2", color: "textSecondary" }, "Make sure to copy and store it securely before closing this view.")),
460
+ /* @__PURE__ */ React.createElement(DialogContent, null, /* @__PURE__ */ React.createElement(Typography, { variant: "body1", paragraph: true }, "You are about to reveal the API key. Make sure to copy and store it securely."), /* @__PURE__ */ React.createElement(Typography, { variant: "body2", color: "textSecondary" }, "The key will remain accessible for future viewing if needed.")),
571
461
  /* @__PURE__ */ React.createElement(DialogActions, null, /* @__PURE__ */ React.createElement(
572
462
  Button,
573
463
  {
@@ -1 +1 @@
1
- {"version":3,"file":"MyApiKeysTable.esm.js","sources":["../../../src/components/MyApiKeysTable/MyApiKeysTable.tsx"],"sourcesContent":["import React, { useState, useMemo } from \"react\";\nimport { useNavigate } from \"react-router-dom\";\nimport {\n Table,\n TableColumn,\n Link,\n ResponseErrorPanel,\n} from \"@backstage/core-components\";\nimport {\n useApi,\n alertApiRef,\n} from \"@backstage/core-plugin-api\";\nimport { kuadrantApiRef } from '../../api';\nimport useAsync from \"react-use/lib/useAsync\";\nimport {\n Box,\n Chip,\n Typography,\n IconButton,\n Tooltip,\n Menu,\n MenuItem,\n CircularProgress,\n Dialog,\n DialogTitle,\n DialogContent,\n DialogActions,\n Button,\n makeStyles,\n} from \"@material-ui/core\";\nimport { Skeleton } from \"@material-ui/lab\";\nimport { SimpleRequestAccessDialog } from \"../SimpleRequestAccessDialog\";\nimport VisibilityIcon from \"@material-ui/icons/Visibility\";\nimport VisibilityOffIcon from \"@material-ui/icons/VisibilityOff\";\nimport FileCopyIcon from \"@material-ui/icons/FileCopy\";\nimport WarningIcon from \"@material-ui/icons/Warning\";\nimport DeleteIcon from \"@material-ui/icons/Delete\";\nimport { EditAPIKeyDialog } from \"../EditAPIKeyDialog\";\nimport { ConfirmDeleteDialog } from \"../ConfirmDeleteDialog\";\nimport { FilterPanel, FilterSection, FilterState } from \"../FilterPanel\";\nimport { APIKey, APIProduct } from \"../../types/api-management\";\nimport { getMyApiKeysStatusChipStyle } from \"../../utils/styles\";\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 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 rejectedBanner: {\n backgroundColor: theme.palette.error.light,\n border: `1px solid ${theme.palette.error.main}`,\n borderRadius: theme.shape.borderRadius,\n padding: theme.spacing(1.5, 2),\n marginBottom: theme.spacing(2),\n display: \"flex\",\n alignItems: \"center\",\n gap: theme.spacing(1),\n },\n}));\n\ninterface ExpandedRowProps {\n request: APIKey;\n}\n\nconst ExpandedRowContent = ({ request }: ExpandedRowProps) => {\n const classes = useStyles();\n const isRejected = request.status?.phase === \"Rejected\";\n const apiProductName = request.spec.apiProductRef?.name || \"unknown\";\n\n return (\n <Box className={classes.useCasePanel} onClick={(e) => e.stopPropagation()}>\n {isRejected && (\n <Box className={classes.rejectedBanner}>\n <WarningIcon color=\"error\" fontSize=\"small\" />\n <Typography variant=\"body2\">\n This API key was rejected.{\" \"}\n <Link to={`/catalog/default/api/${apiProductName}/api-keys`}>\n Request a new API key\n </Link>\n </Typography>\n </Box>\n )}\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\nexport const MyApiKeysTable = () => {\n const classes = useStyles();\n const navigate = useNavigate();\n const kuadrantApi = useApi(kuadrantApiRef);\n const alertApi = useApi(alertApiRef);\n\n const [requestDialogOpen, setRequestDialogOpen] = useState(false);\n const [visibleKeys, setVisibleKeys] = useState<Set<string>>(new Set());\n const [menuAnchor, setMenuAnchor] = useState<{\n top: number;\n left: number;\n } | null>(null);\n const [menuRequest, setMenuRequest] = useState<APIKey | null>(null);\n const [editDialogState, setEditDialogState] = useState<{\n open: boolean;\n request: APIKey | null;\n plans: any[];\n }>({ open: false, request: null, plans: [] });\n const [refresh, setRefresh] = useState(0);\n const [deleting, setDeleting] = useState<string | null>(null);\n const [deleteDialogState, setDeleteDialogState] = useState<{\n open: boolean;\n request: APIKey | null;\n }>({ open: false, request: null });\n const [apiKeyValues, setApiKeyValues] = useState<Map<string, string>>(\n new Map(),\n );\n const [apiKeyLoading, setApiKeyLoading] = useState<Set<string>>(new Set());\n const [alreadyReadKeys, setAlreadyReadKeys] = useState<Set<string>>(\n new Set(),\n );\n const [showOnceWarningOpen, setShowOnceWarningOpen] = useState(false);\n const [pendingKeyReveal, setPendingKeyReveal] = useState<{\n namespace: string;\n name: string;\n } | null>(null);\n const [optimisticallyDeleted, setOptimisticallyDeleted] = useState<\n Set<string>\n >(new Set());\n\n const [filters, setFilters] = useState<FilterState>({\n status: [],\n apiProduct: [],\n tier: [],\n });\n\n const {\n value: data,\n loading,\n error,\n } = useAsync(async () => {\n const [requestsData, productsData] = await Promise.all([\n kuadrantApi.getRequests(),\n kuadrantApi.getApiProducts(),\n ]);\n\n const requests: APIKey[] = requestsData.items || [];\n const products: APIProduct[] = productsData.items || [];\n\n // build owner map from products\n const ownerMap = new Map<string, string>();\n products.forEach((p) => {\n const key = `${p.metadata.namespace}/${p.metadata.name}`;\n const owner = p.metadata.annotations?.[\"backstage.io/owner\"] || \"unknown\";\n ownerMap.set(key, owner);\n });\n\n return { requests, products, ownerMap };\n }, [kuadrantApi, refresh]);\n\n const allRequests = useMemo(() => {\n if (!data?.requests) return [];\n return data.requests.filter(\n (r: APIKey) => !optimisticallyDeleted.has(r.metadata.name),\n );\n }, [data?.requests, optimisticallyDeleted]);\n\n // filter options from data\n const filterSections: FilterSection[] = useMemo(() => {\n const statusCounts = { Approved: 0, Pending: 0, Rejected: 0 };\n const apiProductCounts = new Map<string, number>();\n const tierCounts = new Map<string, number>();\n\n allRequests.forEach((r: APIKey) => {\n const status = r.status?.phase || \"Pending\";\n statusCounts[status as keyof typeof statusCounts]++;\n\n const apiProduct = r.spec.apiProductRef?.name || \"unknown\";\n apiProductCounts.set(\n apiProduct,\n (apiProductCounts.get(apiProduct) || 0) + 1,\n );\n\n const tier = r.spec.planTier || \"unknown\";\n tierCounts.set(tier, (tierCounts.get(tier) || 0) + 1);\n });\n\n return [\n {\n id: \"status\",\n title: \"Status\",\n options: [\n { value: \"Approved\", label: \"Active\", count: statusCounts.Approved },\n { value: \"Pending\", label: \"Pending\", count: statusCounts.Pending },\n {\n value: \"Rejected\",\n label: \"Rejected\",\n count: statusCounts.Rejected,\n },\n ],\n },\n {\n id: \"apiProduct\",\n title: \"API Product\",\n options: Array.from(apiProductCounts.entries()).map(\n ([name, count]) => ({\n value: name,\n label: name,\n count,\n }),\n ),\n collapsed: apiProductCounts.size > 5,\n },\n {\n id: \"tier\",\n title: \"Tier\",\n options: Array.from(tierCounts.entries()).map(([tier, count]) => ({\n value: tier,\n label: tier.charAt(0).toUpperCase() + tier.slice(1),\n count,\n })),\n },\n ];\n }, [allRequests]);\n\n // filtered requests\n const filteredRequests = useMemo(() => {\n return allRequests.filter((r: APIKey) => {\n // status filter\n if (filters.status.length > 0) {\n const status = r.status?.phase || \"Pending\";\n if (!filters.status.includes(status)) return false;\n }\n\n // api product filter\n if (filters.apiProduct.length > 0) {\n const apiProduct = r.spec.apiProductRef?.name || \"unknown\";\n if (!filters.apiProduct.includes(apiProduct)) return false;\n }\n\n // tier filter\n if (filters.tier.length > 0) {\n const tier = r.spec.planTier || \"unknown\";\n if (!filters.tier.includes(tier)) return false;\n }\n\n return true;\n });\n }, [allRequests, filters]);\n\n const toggleKeyVisibility = (keyName: string) => {\n setVisibleKeys((prev) => {\n const newSet = new Set(prev);\n if (newSet.has(keyName)) {\n newSet.delete(keyName);\n } else {\n newSet.add(keyName);\n }\n return newSet;\n });\n };\n\n const fetchApiKeyFromSecret = async (\n requestNamespace: string,\n requestName: string,\n ) => {\n const key = `${requestNamespace}/${requestName}`;\n if (apiKeyLoading.has(key)) return;\n\n setApiKeyLoading((prev) => new Set(prev).add(key));\n try {\n const result = await kuadrantApi.getApiKeySecret(requestNamespace, requestName);\n setApiKeyValues((prev) => new Map(prev).set(key, result.apiKey));\n setAlreadyReadKeys((prev) => new Set(prev).add(key));\n } catch (err) {\n const errorMessage =\n err instanceof Error ? err.message : \"unknown error occurred\";\n if (errorMessage.includes(\"403\") || errorMessage.includes(\"already been viewed\")) {\n setAlreadyReadKeys((prev) => new Set(prev).add(key));\n alertApi.post({\n message:\n \"This API key has already been viewed and cannot be retrieved again.\",\n severity: \"warning\",\n display: \"transient\",\n });\n } else {\n alertApi.post({\n message: `Failed to fetch api key: ${errorMessage}`,\n severity: \"error\",\n display: \"transient\",\n });\n }\n } finally {\n setApiKeyLoading((prev) => {\n const next = new Set(prev);\n next.delete(key);\n return next;\n });\n }\n };\n\n const clearApiKeyValue = (requestNamespace: string, requestName: string) => {\n const key = `${requestNamespace}/${requestName}`;\n setApiKeyValues((prev) => {\n const next = new Map(prev);\n next.delete(key);\n return next;\n });\n };\n\n const handleMenuClose = () => {\n setMenuAnchor(null);\n setMenuRequest(null);\n };\n\n const handleEdit = async () => {\n if (!menuRequest) return;\n\n const request = menuRequest;\n handleMenuClose();\n\n try {\n const apiProductName = request.spec.apiProductRef?.name;\n const apiProductNamespace = request.metadata.namespace;\n const apiProduct = await kuadrantApi.getApiProduct(apiProductNamespace, apiProductName);\n const plans = apiProduct.status?.discoveredPlans || [];\n setEditDialogState({ open: true, request, plans });\n } catch (err) {\n console.error(\"Error fetching plans:\", err);\n setEditDialogState({ open: true, request: menuRequest, plans: [] });\n const errorMessage = err instanceof Error ? err.message : \"unknown error occurred\";\n alertApi.post({\n message: `Failed to fetch Plans. ${errorMessage}`,\n severity: 'error',\n display: 'transient',\n });\n }\n };\n\n const handleDeleteClick = () => {\n if (!menuRequest) return;\n const request = menuRequest;\n handleMenuClose();\n setDeleteDialogState({ open: true, request });\n };\n\n const handleDeleteConfirm = async () => {\n if (!deleteDialogState.request) return;\n\n const request = deleteDialogState.request;\n const requestName = request.metadata.name;\n\n setOptimisticallyDeleted((prev) => new Set(prev).add(requestName));\n setDeleting(requestName);\n\n try {\n await kuadrantApi.deleteRequest(request.metadata.namespace, request.metadata.name);\n setRefresh((r) => r + 1);\n alertApi.post({\n message: \"API key deleted\",\n severity: \"success\",\n display: \"transient\",\n });\n setDeleteDialogState({ open: false, request: null });\n } catch (err) {\n console.error(\"Error deleting request:\", err);\n setOptimisticallyDeleted((prev) => {\n const next = new Set(prev);\n next.delete(requestName);\n return next;\n });\n const errorMessage = err instanceof Error ? err.message : \"unknown error occurred\";\n alertApi.post({\n message: `Failed to delete APIKey. ${errorMessage}`,\n severity: 'error',\n display: 'transient',\n });\n } finally {\n setDeleting(null);\n }\n };\n\n const handleDeleteCancel = () => {\n setDeleteDialogState({ open: false, request: null });\n };\n\n const columns: TableColumn<APIKey>[] = [\n {\n title: \"API Product\",\n field: \"spec.apiProductRef.name\",\n render: (row: APIKey) => {\n const apiProductName = row.spec.apiProductRef?.name || \"unknown\";\n return (\n <Link to={`/catalog/default/api/${apiProductName}/api-keys`}>\n <strong>{apiProductName}</strong>\n </Link>\n );\n },\n },\n {\n title: \"Owner\",\n field: \"owner\",\n render: (row: APIKey) => {\n const key = `${row.metadata.namespace}/${row.spec.apiProductRef?.name}`;\n const owner = data?.ownerMap?.get(key) || \"unknown\";\n // strip 'user:default/' prefix if present\n const displayOwner = owner.replace(/^user:default\\//, \"\");\n return <Typography variant=\"body2\">{displayOwner}</Typography>;\n },\n },\n {\n title: \"Status\",\n field: \"status.phase\",\n render: (row: APIKey) => {\n const phase = row.status?.phase || \"Pending\";\n const label = phase === \"Approved\" ? \"Active\" : phase;\n return (\n <Chip label={label} size=\"small\" style={getMyApiKeysStatusChipStyle(phase)} />\n );\n },\n },\n {\n title: \"Tier\",\n field: \"spec.planTier\",\n render: (row: APIKey) => (\n <Chip label={row.spec.planTier} size=\"small\" variant=\"outlined\" />\n ),\n },\n {\n title: \"API Key\",\n field: \"status.secretRef\",\n filtering: false,\n render: (row: APIKey) => {\n if (row.status?.phase !== \"Approved\") {\n return (\n <Typography variant=\"body2\" color=\"textSecondary\">\n -\n </Typography>\n );\n }\n\n const key = `${row.metadata.namespace}/${row.metadata.name}`;\n const hasSecretRef = row.status?.secretRef?.name;\n const isVisible = visibleKeys.has(row.metadata.name);\n const isLoading = apiKeyLoading.has(key);\n const apiKeyValue = apiKeyValues.get(key);\n const canReadSecret = row.status?.canReadSecret !== false;\n const isAlreadyRead = alreadyReadKeys.has(key) || !canReadSecret;\n\n if (!hasSecretRef) {\n return (\n <Typography variant=\"body2\" color=\"textSecondary\">\n Awaiting secret...\n </Typography>\n );\n }\n\n if (isAlreadyRead && !apiKeyValue) {\n return (\n <Tooltip title=\"This API key has already been viewed and cannot be retrieved again\">\n <Box display=\"flex\" alignItems=\"center\">\n <Typography\n variant=\"body2\"\n color=\"textSecondary\"\n style={{ fontFamily: \"monospace\", marginRight: 8 }}\n >\n Already viewed\n </Typography>\n <VisibilityOffIcon fontSize=\"small\" color=\"disabled\" />\n </Box>\n </Tooltip>\n );\n }\n\n const handleRevealClick = () => {\n if (isVisible) {\n clearApiKeyValue(row.metadata.namespace, row.metadata.name);\n toggleKeyVisibility(row.metadata.name);\n } else if (!isAlreadyRead) {\n setPendingKeyReveal({\n namespace: row.metadata.namespace,\n name: row.metadata.name,\n });\n setShowOnceWarningOpen(true);\n }\n };\n\n const handleCopy = async () => {\n if (apiKeyValue) {\n await navigator.clipboard.writeText(apiKeyValue);\n alertApi.post({\n message: \"API key copied to clipboard\",\n severity: \"success\",\n display: \"transient\",\n });\n }\n };\n\n return (\n <Box display=\"flex\" alignItems=\"center\" style={{ gap: 8 }}>\n <Box fontFamily=\"monospace\" fontSize=\"0.875rem\">\n {isLoading\n ? \"Loading...\"\n : isVisible && apiKeyValue\n ? apiKeyValue\n : \"•\".repeat(20) + \"...\"}\n </Box>\n {isVisible && apiKeyValue && (\n <Tooltip title=\"Copy to clipboard\">\n <IconButton size=\"small\" onClick={handleCopy}>\n <FileCopyIcon fontSize=\"small\" />\n </IconButton>\n </Tooltip>\n )}\n <Tooltip\n title={\n isVisible ? \"Hide API key\" : \"Reveal API key (one-time only)\"\n }\n >\n <span>\n <IconButton\n size=\"small\"\n onClick={handleRevealClick}\n disabled={isLoading || (isAlreadyRead && !apiKeyValue)}\n >\n {isVisible ? (\n <VisibilityOffIcon fontSize=\"small\" />\n ) : (\n <VisibilityIcon fontSize=\"small\" />\n )}\n </IconButton>\n </span>\n </Tooltip>\n </Box>\n );\n },\n },\n {\n title: \"Requested\",\n field: \"metadata.creationTimestamp\",\n render: (row: APIKey) => {\n if (!row.metadata.creationTimestamp) {\n return <Typography variant=\"body2\">-</Typography>;\n }\n const date = new Date(row.metadata.creationTimestamp);\n return (\n <Typography variant=\"body2\">{date.toLocaleDateString()}</Typography>\n );\n },\n },\n {\n title: \"Actions\",\n filtering: false,\n width: \"100px\",\n render: (row: APIKey) => {\n const isDeleting = deleting === row.metadata.name;\n if (isDeleting) {\n return <CircularProgress size={20} />;\n }\n return (\n <Box display=\"flex\" style={{ gap: 4 }}>\n <Tooltip title=\"View details\">\n <IconButton\n size=\"small\"\n onClick={(e) => {\n e.stopPropagation();\n navigate(\n `/kuadrant/api-keys/${row.metadata.namespace}/${row.metadata.name}`,\n );\n }}\n >\n <VisibilityIcon fontSize=\"small\" />\n </IconButton>\n </Tooltip>\n <Tooltip title=\"Delete\">\n <IconButton\n size=\"small\"\n onClick={(e) => {\n e.stopPropagation();\n setDeleteDialogState({ open: true, request: row });\n }}\n >\n <DeleteIcon fontSize=\"small\" />\n </IconButton>\n </Tooltip>\n </Box>\n );\n },\n },\n ];\n\n const detailPanelConfig = useMemo(\n () => [\n {\n render: (data: any) => {\n const request = data.rowData as APIKey;\n if (!request?.metadata?.name) {\n return <Box />;\n }\n return <ExpandedRowContent request={request} />;\n },\n },\n ],\n [],\n );\n\n if (loading) {\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 const isPending = (row: APIKey) =>\n !row.status || row.status.phase === \"Pending\";\n\n return (\n <>\n <Box display=\"flex\" justifyContent=\"flex-end\" mb={2} px={2}>\n <Button\n variant=\"contained\"\n color=\"primary\"\n onClick={() => setRequestDialogOpen(true)}\n data-testid=\"request-access-button\"\n >\n Request Access\n </Button>\n </Box>\n <Box className={classes.container}>\n <FilterPanel\n sections={filterSections}\n filters={filters}\n onChange={setFilters}\n />\n <Box className={classes.tableContainer}>\n {allRequests.length === 0 ? (\n <Box p={4} textAlign=\"center\">\n <Typography variant=\"body1\" color=\"textSecondary\" gutterBottom>\n No API keys found. Request access to an API to get started.\n </Typography>\n </Box>\n ) : filteredRequests.length === 0 ? (\n <Box p={4} textAlign=\"center\">\n <Typography variant=\"body1\" color=\"textSecondary\">\n No API keys match the selected filters.\n </Typography>\n </Box>\n ) : (\n <Table\n options={{\n paging: filteredRequests.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={filteredRequests.map((item: APIKey) => ({\n ...item,\n id: item.metadata.name,\n }))}\n detailPanel={detailPanelConfig}\n />\n )}\n </Box>\n </Box>\n\n <Menu\n id=\"myapikeys-menu\"\n open={Boolean(menuAnchor)}\n onClose={handleMenuClose}\n anchorReference=\"anchorPosition\"\n anchorPosition={menuAnchor || { top: 0, left: 0 }}\n >\n {menuRequest &&\n (() => {\n const items = [];\n items.push(\n <MenuItem\n key=\"view\"\n onClick={() => {\n navigate(\n `/kuadrant/api-keys/${menuRequest.metadata.namespace}/${menuRequest.metadata.name}`,\n );\n handleMenuClose();\n }}\n >\n View Details\n </MenuItem>,\n );\n if (isPending(menuRequest)) {\n items.push(\n <MenuItem key=\"edit\" onClick={handleEdit}>\n Edit\n </MenuItem>,\n );\n }\n items.push(\n <MenuItem key=\"delete\" onClick={handleDeleteClick}>\n Delete\n </MenuItem>,\n );\n return items;\n })()}\n </Menu>\n\n {editDialogState.request && (\n <EditAPIKeyDialog\n open={editDialogState.open}\n request={editDialogState.request}\n availablePlans={editDialogState.plans}\n onClose={() =>\n setEditDialogState({ open: false, request: null, plans: [] })\n }\n onSuccess={() => {\n setEditDialogState({ open: false, request: null, plans: [] });\n setRefresh((r) => r + 1);\n }}\n />\n )}\n\n <ConfirmDeleteDialog\n open={deleteDialogState.open}\n title=\"Delete API Key\"\n description={`Are you sure you want to delete this API key for ${deleteDialogState.request?.spec.apiProductRef?.name || \"this API\"}?`}\n deleting={deleting !== null}\n onConfirm={handleDeleteConfirm}\n onCancel={handleDeleteCancel}\n />\n\n <Dialog\n open={showOnceWarningOpen}\n onClose={() => {\n setShowOnceWarningOpen(false);\n setPendingKeyReveal(null);\n }}\n maxWidth=\"sm\"\n >\n <DialogTitle>\n <Box display=\"flex\" alignItems=\"center\">\n <WarningIcon color=\"primary\" style={{ marginRight: 8 }} />\n View API Key\n </Box>\n </DialogTitle>\n <DialogContent>\n <Typography variant=\"body1\" paragraph>\n This API key can only be viewed <strong>once</strong>. After you\n reveal it, you will not be able to retrieve it again.\n </Typography>\n <Typography variant=\"body2\" color=\"textSecondary\">\n Make sure to copy and store it securely before closing this view.\n </Typography>\n </DialogContent>\n <DialogActions>\n <Button\n onClick={() => {\n setShowOnceWarningOpen(false);\n setPendingKeyReveal(null);\n }}\n >\n Cancel\n </Button>\n <Button\n variant=\"contained\"\n color=\"primary\"\n onClick={() => {\n if (pendingKeyReveal) {\n fetchApiKeyFromSecret(\n pendingKeyReveal.namespace,\n pendingKeyReveal.name,\n );\n toggleKeyVisibility(pendingKeyReveal.name);\n }\n setShowOnceWarningOpen(false);\n setPendingKeyReveal(null);\n }}\n >\n Reveal API Key\n </Button>\n </DialogActions>\n </Dialog>\n\n <SimpleRequestAccessDialog\n open={requestDialogOpen}\n onClose={() => setRequestDialogOpen(false)}\n onSuccess={() => {\n setRequestDialogOpen(false);\n setRefresh((prev) => prev + 1);\n }}\n />\n </>\n );\n};\n"],"names":["data"],"mappings":"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"}
1
+ {"version":3,"file":"MyApiKeysTable.esm.js","sources":["../../../src/components/MyApiKeysTable/MyApiKeysTable.tsx"],"sourcesContent":["import React, { useState, useMemo } from \"react\";\nimport { useNavigate } from \"react-router-dom\";\nimport {\n Table,\n TableColumn,\n Link,\n ResponseErrorPanel,\n} from \"@backstage/core-components\";\nimport {\n useApi,\n alertApiRef,\n} from \"@backstage/core-plugin-api\";\nimport { kuadrantApiRef } from '../../api';\nimport { getAPIKeyPhase } from '../../utils/apikeys';\nimport useAsync from \"react-use/lib/useAsync\";\nimport {\n Box,\n Chip,\n Typography,\n IconButton,\n Tooltip,\n CircularProgress,\n Dialog,\n DialogTitle,\n DialogContent,\n DialogActions,\n Button,\n makeStyles,\n} from \"@material-ui/core\";\nimport { Skeleton } from \"@material-ui/lab\";\nimport { SimpleRequestAccessDialog } from \"../SimpleRequestAccessDialog\";\nimport VisibilityIcon from \"@material-ui/icons/Visibility\";\nimport VisibilityOffIcon from \"@material-ui/icons/VisibilityOff\";\nimport FileCopyIcon from \"@material-ui/icons/FileCopy\";\nimport WarningIcon from \"@material-ui/icons/Warning\";\nimport DeleteIcon from \"@material-ui/icons/Delete\";\nimport { ConfirmDeleteDialog } from \"../ConfirmDeleteDialog\";\nimport { FilterPanel, FilterSection, FilterState } from \"../FilterPanel\";\nimport { APIKey, APIProduct } from \"../../types/api-management\";\nimport { getMyApiKeysStatusChipStyle } from \"../../utils/styles\";\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 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 rejectedBanner: {\n backgroundColor: theme.palette.error.light,\n border: `1px solid ${theme.palette.error.main}`,\n borderRadius: theme.shape.borderRadius,\n padding: theme.spacing(1.5, 2),\n marginBottom: theme.spacing(2),\n display: \"flex\",\n alignItems: \"center\",\n gap: theme.spacing(1),\n },\n}));\n\ninterface ExpandedRowProps {\n request: APIKey;\n}\n\nconst ExpandedRowContent = ({ request }: ExpandedRowProps) => {\n const classes = useStyles();\n const isRejected = getAPIKeyPhase(request.status?.conditions) === \"Denied\";\n const apiProductName = request.spec.apiProductRef?.name || \"unknown\";\n\n return (\n <Box className={classes.useCasePanel} onClick={(e) => e.stopPropagation()}>\n {isRejected && (\n <Box className={classes.rejectedBanner}>\n <WarningIcon color=\"error\" fontSize=\"small\" />\n <Typography variant=\"body2\">\n This API key was denied.{\" \"}\n <Link to={`/catalog/default/api/${apiProductName}/api-keys`}>\n Request a new API key\n </Link>\n </Typography>\n </Box>\n )}\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\nexport const MyApiKeysTable = () => {\n const classes = useStyles();\n const navigate = useNavigate();\n const kuadrantApi = useApi(kuadrantApiRef);\n const alertApi = useApi(alertApiRef);\n\n const [requestDialogOpen, setRequestDialogOpen] = useState(false);\n const [visibleKeys, setVisibleKeys] = useState<Set<string>>(new Set());\n const [refresh, setRefresh] = useState(0);\n const [deleting, setDeleting] = useState<string | null>(null);\n const [deleteDialogState, setDeleteDialogState] = useState<{\n open: boolean;\n request: APIKey | null;\n }>({ open: false, request: null });\n const [apiKeyValues, setApiKeyValues] = useState<Map<string, string>>(\n new Map(),\n );\n const [apiKeyLoading, setApiKeyLoading] = useState<Set<string>>(new Set());\n const [showOnceWarningOpen, setShowOnceWarningOpen] = useState(false);\n const [pendingKeyReveal, setPendingKeyReveal] = useState<{\n namespace: string;\n name: string;\n } | null>(null);\n const [optimisticallyDeleted, setOptimisticallyDeleted] = useState<\n Set<string>\n >(new Set());\n\n const [filters, setFilters] = useState<FilterState>({\n status: [],\n apiProduct: [],\n tier: [],\n });\n\n const {\n value: data,\n loading,\n error,\n } = useAsync(async () => {\n const [requestsData, productsData] = await Promise.all([\n kuadrantApi.getRequests(),\n kuadrantApi.getApiProducts(),\n ]);\n\n const requests: APIKey[] = requestsData.items || [];\n const products: APIProduct[] = productsData.items || [];\n\n // build owner map from products\n const ownerMap = new Map<string, string>();\n products.forEach((p) => {\n const key = `${p.metadata.namespace}/${p.metadata.name}`;\n const owner = p.metadata.annotations?.[\"backstage.io/owner\"] || \"unknown\";\n ownerMap.set(key, owner);\n });\n\n return { requests, products, ownerMap };\n }, [kuadrantApi, refresh]);\n\n const allRequests = useMemo(() => {\n if (!data?.requests) return [];\n return data.requests.filter(\n (r: APIKey) => !optimisticallyDeleted.has(r.metadata.name),\n );\n }, [data?.requests, optimisticallyDeleted]);\n\n // pass through phase as-is for UI display\n const toUiStatus = (phase: ReturnType<typeof getAPIKeyPhase>) => phase;\n\n // filter options from data\n const filterSections: FilterSection[] = useMemo(() => {\n const statusCounts = { Approved: 0, Pending: 0, Denied: 0, Failed: 0 };\n const apiProductCounts = new Map<string, number>();\n const tierCounts = new Map<string, number>();\n\n allRequests.forEach((r: APIKey) => {\n const status = toUiStatus(getAPIKeyPhase(r.status?.conditions));\n statusCounts[status as keyof typeof statusCounts]++;\n\n const apiProduct = r.spec.apiProductRef?.name || \"unknown\";\n apiProductCounts.set(\n apiProduct,\n (apiProductCounts.get(apiProduct) || 0) + 1,\n );\n\n const tier = r.spec.planTier || \"unknown\";\n tierCounts.set(tier, (tierCounts.get(tier) || 0) + 1);\n });\n\n return [\n {\n id: \"status\",\n title: \"Status\",\n options: [\n { value: \"Approved\", label: \"Active\", count: statusCounts.Approved },\n { value: \"Pending\", label: \"Pending\", count: statusCounts.Pending },\n {\n value: \"Denied\",\n label: \"Denied\",\n count: statusCounts.Denied,\n },\n { value: \"Failed\", label: \"Failed\", count: statusCounts.Failed },\n ],\n },\n {\n id: \"apiProduct\",\n title: \"API Product\",\n options: Array.from(apiProductCounts.entries()).map(\n ([name, count]) => ({\n value: name,\n label: name,\n count,\n }),\n ),\n collapsed: apiProductCounts.size > 5,\n },\n {\n id: \"tier\",\n title: \"Tier\",\n options: Array.from(tierCounts.entries()).map(([tier, count]) => ({\n value: tier,\n label: tier.charAt(0).toUpperCase() + tier.slice(1),\n count,\n })),\n },\n ];\n }, [allRequests]);\n\n // filtered requests\n const filteredRequests = useMemo(() => {\n return allRequests.filter((r: APIKey) => {\n // status filter\n if (filters.status.length > 0) {\n const status = toUiStatus(getAPIKeyPhase(r.status?.conditions));\n if (!filters.status.includes(status)) return false;\n }\n\n // api product filter\n if (filters.apiProduct.length > 0) {\n const apiProduct = r.spec.apiProductRef?.name || \"unknown\";\n if (!filters.apiProduct.includes(apiProduct)) return false;\n }\n\n // tier filter\n if (filters.tier.length > 0) {\n const tier = r.spec.planTier || \"unknown\";\n if (!filters.tier.includes(tier)) return false;\n }\n\n return true;\n });\n }, [allRequests, filters]);\n\n const toggleKeyVisibility = (keyName: string) => {\n setVisibleKeys((prev) => {\n const newSet = new Set(prev);\n if (newSet.has(keyName)) {\n newSet.delete(keyName);\n } else {\n newSet.add(keyName);\n }\n return newSet;\n });\n };\n\n const fetchApiKeyFromSecret = async (\n requestNamespace: string,\n requestName: string,\n ) => {\n const key = `${requestNamespace}/${requestName}`;\n if (apiKeyLoading.has(key)) return;\n\n setApiKeyLoading((prev) => new Set(prev).add(key));\n try {\n const result = await kuadrantApi.getApiKeySecret(requestNamespace, requestName);\n setApiKeyValues((prev) => new Map(prev).set(key, result.apiKey));\n } catch (err) {\n const errorMessage =\n err instanceof Error ? err.message : \"unknown error occurred\";\n alertApi.post({\n message: `Failed to fetch api key: ${errorMessage}`,\n severity: \"error\",\n display: \"transient\",\n });\n } finally {\n setApiKeyLoading((prev) => {\n const next = new Set(prev);\n next.delete(key);\n return next;\n });\n }\n };\n\n const clearApiKeyValue = (requestNamespace: string, requestName: string) => {\n const key = `${requestNamespace}/${requestName}`;\n setApiKeyValues((prev) => {\n const next = new Map(prev);\n next.delete(key);\n return next;\n });\n };\n\n const handleDeleteConfirm = async () => {\n if (!deleteDialogState.request) return;\n\n const request = deleteDialogState.request;\n const requestName = request.metadata.name;\n\n setOptimisticallyDeleted((prev) => new Set(prev).add(requestName));\n setDeleting(requestName);\n\n try {\n await kuadrantApi.deleteRequest(request.metadata.namespace, request.metadata.name);\n setRefresh((r) => r + 1);\n alertApi.post({\n message: \"API key deleted\",\n severity: \"success\",\n display: \"transient\",\n });\n setDeleteDialogState({ open: false, request: null });\n } catch (err) {\n console.error(\"Error deleting request:\", err);\n setOptimisticallyDeleted((prev) => {\n const next = new Set(prev);\n next.delete(requestName);\n return next;\n });\n const errorMessage = err instanceof Error ? err.message : \"unknown error occurred\";\n alertApi.post({\n message: `Failed to delete APIKey. ${errorMessage}`,\n severity: 'error',\n display: 'transient',\n });\n } finally {\n setDeleting(null);\n }\n };\n\n const handleDeleteCancel = () => {\n setDeleteDialogState({ open: false, request: null });\n };\n\n const columns: TableColumn<APIKey>[] = [\n {\n title: \"API Product\",\n field: \"spec.apiProductRef.name\",\n render: (row: APIKey) => {\n const apiProductName = row.spec.apiProductRef?.name || \"unknown\";\n return (\n <Link to={`/catalog/default/api/${apiProductName}/api-keys`}>\n <strong>{apiProductName}</strong>\n </Link>\n );\n },\n },\n {\n title: \"Owner\",\n field: \"owner\",\n render: (row: APIKey) => {\n const key = `${row.metadata.namespace}/${row.spec.apiProductRef?.name}`;\n const owner = data?.ownerMap?.get(key) || \"unknown\";\n // strip 'user:default/' prefix if present\n const displayOwner = owner.replace(/^user:default\\//, \"\");\n return <Typography variant=\"body2\">{displayOwner}</Typography>;\n },\n },\n {\n title: \"Status\",\n field: \"status.conditions\",\n render: (row: APIKey) => {\n const phase = getAPIKeyPhase(row.status?.conditions);\n const displayPhase = toUiStatus(phase);\n const label = displayPhase === \"Approved\" ? \"Active\" : displayPhase;\n return (\n <Chip label={label} size=\"small\" style={getMyApiKeysStatusChipStyle(phase)} />\n );\n },\n },\n {\n title: \"Tier\",\n field: \"spec.planTier\",\n render: (row: APIKey) => (\n <Chip label={row.spec.planTier} size=\"small\" variant=\"outlined\" />\n ),\n },\n {\n title: \"API Key\",\n field: \"status.secretRef\",\n filtering: false,\n render: (row: APIKey) => {\n if (getAPIKeyPhase(row.status?.conditions) !== \"Approved\") {\n return (\n <Typography variant=\"body2\" color=\"textSecondary\">\n -\n </Typography>\n );\n }\n\n const key = `${row.metadata.namespace}/${row.metadata.name}`;\n const isVisible = visibleKeys.has(row.metadata.name);\n const isLoading = apiKeyLoading.has(key);\n const apiKeyValue = apiKeyValues.get(key);\n\n const handleRevealClick = () => {\n if (isVisible) {\n clearApiKeyValue(row.metadata.namespace, row.metadata.name);\n toggleKeyVisibility(row.metadata.name);\n } else {\n setPendingKeyReveal({\n namespace: row.metadata.namespace,\n name: row.metadata.name,\n });\n setShowOnceWarningOpen(true);\n }\n };\n\n const handleCopy = async () => {\n if (apiKeyValue) {\n await navigator.clipboard.writeText(apiKeyValue);\n alertApi.post({\n message: \"API key copied to clipboard\",\n severity: \"success\",\n display: \"transient\",\n });\n }\n };\n\n return (\n <Box display=\"flex\" alignItems=\"center\" style={{ gap: 8 }}>\n <Box fontFamily=\"monospace\" fontSize=\"0.875rem\">\n {isLoading\n ? \"Loading...\"\n : isVisible && apiKeyValue\n ? apiKeyValue\n : \"•\".repeat(20)}\n </Box>\n {isVisible && apiKeyValue && (\n <Tooltip title=\"Copy to clipboard\">\n <IconButton size=\"small\" onClick={handleCopy}>\n <FileCopyIcon fontSize=\"small\" />\n </IconButton>\n </Tooltip>\n )}\n <Tooltip\n title={\n isVisible ? \"Hide API key\" : \"Reveal API key\"\n }\n >\n <span>\n <IconButton\n size=\"small\"\n onClick={handleRevealClick}\n disabled={isLoading}\n >\n {isVisible ? (\n <VisibilityOffIcon fontSize=\"small\" />\n ) : (\n <VisibilityIcon fontSize=\"small\" />\n )}\n </IconButton>\n </span>\n </Tooltip>\n </Box>\n );\n },\n },\n {\n title: \"Requested\",\n field: \"metadata.creationTimestamp\",\n render: (row: APIKey) => {\n if (!row.metadata.creationTimestamp) {\n return <Typography variant=\"body2\">-</Typography>;\n }\n const date = new Date(row.metadata.creationTimestamp);\n return (\n <Typography variant=\"body2\">{date.toLocaleDateString()}</Typography>\n );\n },\n },\n {\n title: \"Actions\",\n filtering: false,\n width: \"100px\",\n render: (row: APIKey) => {\n const isDeleting = deleting === row.metadata.name;\n if (isDeleting) {\n return <CircularProgress size={20} />;\n }\n return (\n <Box display=\"flex\" style={{ gap: 4 }}>\n <Tooltip title=\"View details\">\n <IconButton\n size=\"small\"\n onClick={(e) => {\n e.stopPropagation();\n navigate(\n `/kuadrant/api-keys/${row.metadata.namespace}/${row.metadata.name}`,\n );\n }}\n >\n <VisibilityIcon fontSize=\"small\" />\n </IconButton>\n </Tooltip>\n <Tooltip title=\"Delete\">\n <IconButton\n size=\"small\"\n onClick={(e) => {\n e.stopPropagation();\n setDeleteDialogState({ open: true, request: row });\n }}\n >\n <DeleteIcon fontSize=\"small\" />\n </IconButton>\n </Tooltip>\n </Box>\n );\n },\n },\n ];\n\n const detailPanelConfig = useMemo(\n () => [\n {\n render: (data: any) => {\n const request = data.rowData as APIKey;\n if (!request?.metadata?.name) {\n return <Box />;\n }\n return <ExpandedRowContent request={request} />;\n },\n },\n ],\n [],\n );\n\n if (loading) {\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 return (\n <>\n <Box display=\"flex\" justifyContent=\"flex-end\" mb={2} px={2}>\n <Button\n variant=\"contained\"\n color=\"primary\"\n onClick={() => setRequestDialogOpen(true)}\n data-testid=\"request-access-button\"\n >\n Request Access\n </Button>\n </Box>\n <Box className={classes.container}>\n <FilterPanel\n sections={filterSections}\n filters={filters}\n onChange={setFilters}\n />\n <Box className={classes.tableContainer}>\n {allRequests.length === 0 ? (\n <Box p={4} textAlign=\"center\">\n <Typography variant=\"body1\" color=\"textSecondary\" gutterBottom>\n No API keys found. Request access to an API to get started.\n </Typography>\n </Box>\n ) : filteredRequests.length === 0 ? (\n <Box p={4} textAlign=\"center\">\n <Typography variant=\"body1\" color=\"textSecondary\">\n No API keys match the selected filters.\n </Typography>\n </Box>\n ) : (\n <Table\n options={{\n paging: filteredRequests.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={filteredRequests.map((item: APIKey) => ({\n ...item,\n id: item.metadata.name,\n }))}\n detailPanel={detailPanelConfig}\n />\n )}\n </Box>\n </Box>\n\n <ConfirmDeleteDialog\n open={deleteDialogState.open}\n title=\"Delete API Key\"\n description={`Are you sure you want to delete this API key for ${deleteDialogState.request?.spec.apiProductRef?.name || \"this API\"}?`}\n deleting={deleting !== null}\n onConfirm={handleDeleteConfirm}\n onCancel={handleDeleteCancel}\n />\n\n <Dialog\n open={showOnceWarningOpen}\n onClose={() => {\n setShowOnceWarningOpen(false);\n setPendingKeyReveal(null);\n }}\n maxWidth=\"sm\"\n >\n <DialogTitle>\n <Box display=\"flex\" alignItems=\"center\">\n <WarningIcon color=\"primary\" style={{ marginRight: 8 }} />\n View API Key\n </Box>\n </DialogTitle>\n <DialogContent>\n <Typography variant=\"body1\" paragraph>\n You are about to reveal the API key. Make sure to copy and store it\n securely.\n </Typography>\n <Typography variant=\"body2\" color=\"textSecondary\">\n The key will remain accessible for future viewing if needed.\n </Typography>\n </DialogContent>\n <DialogActions>\n <Button\n onClick={() => {\n setShowOnceWarningOpen(false);\n setPendingKeyReveal(null);\n }}\n >\n Cancel\n </Button>\n <Button\n variant=\"contained\"\n color=\"primary\"\n onClick={() => {\n if (pendingKeyReveal) {\n fetchApiKeyFromSecret(\n pendingKeyReveal.namespace,\n pendingKeyReveal.name,\n );\n toggleKeyVisibility(pendingKeyReveal.name);\n }\n setShowOnceWarningOpen(false);\n setPendingKeyReveal(null);\n }}\n >\n Reveal API Key\n </Button>\n </DialogActions>\n </Dialog>\n\n <SimpleRequestAccessDialog\n open={requestDialogOpen}\n onClose={() => setRequestDialogOpen(false)}\n onSuccess={() => {\n setRequestDialogOpen(false);\n setRefresh((prev) => prev + 1);\n }}\n />\n </>\n );\n};\n"],"names":["data"],"mappings":"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"}
@@ -1,12 +1,12 @@
1
1
  import React from 'react';
2
2
  import { Box, Typography } from '@material-ui/core';
3
- import { Progress } from '@backstage/core-components';
3
+ import { Skeleton } from '@material-ui/lab';
4
4
  import { useKuadrantPermission } from '../../utils/permissions.esm.js';
5
5
 
6
6
  const PermissionGate = ({ children, permission, fallback, errorMessage }) => {
7
7
  const { allowed, loading, error } = useKuadrantPermission(permission);
8
8
  if (loading) {
9
- return /* @__PURE__ */ React.createElement(Progress, null);
9
+ return /* @__PURE__ */ React.createElement(Box, { p: 2 }, [...Array(5)].map((_, i) => /* @__PURE__ */ React.createElement(Box, { key: i, p: 2 }, /* @__PURE__ */ React.createElement(Skeleton, { variant: "text", width: "100%" }))));
10
10
  }
11
11
  if (error) {
12
12
  return /* @__PURE__ */ React.createElement(Box, { p: 4 }, /* @__PURE__ */ React.createElement(Typography, { color: "error" }, "Unable to check permissions: ", error.message), /* @__PURE__ */ React.createElement(Typography, { variant: "body2", color: "textSecondary" }, "Please try again or contact your administrator"));
@@ -1 +1 @@
1
- {"version":3,"file":"PermissionGate.esm.js","sources":["../../../src/components/PermissionGate/PermissionGate.tsx"],"sourcesContent":["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"],"names":[],"mappings":";;;;;AAaO,MAAM,iBAAiB,CAAC,EAAE,UAAU,UAAY,EAAA,QAAA,EAAU,cAAwC,KAAA;AACvG,EAAA,MAAM,EAAE,OAAS,EAAA,OAAA,EAAS,KAAM,EAAA,GAAI,sBAAsB,UAAU,CAAA;AAEpE,EAAA,IAAI,OAAS,EAAA;AACX,IAAA,2CAAQ,QAAS,EAAA,IAAA,CAAA;AAAA;AAGnB,EAAA,IAAI,KAAO,EAAA;AACT,IAAA,2CACG,GAAI,EAAA,EAAA,CAAA,EAAG,qBACL,KAAA,CAAA,aAAA,CAAA,UAAA,EAAA,EAAW,OAAM,OAAQ,EAAA,EAAA,+BAAA,EACM,MAAM,OACtC,CAAA,sCACC,UAAW,EAAA,EAAA,OAAA,EAAQ,SAAQ,KAAM,EAAA,eAAA,EAAA,EAAgB,gDAElD,CACF,CAAA;AAAA;AAIJ,EAAA,IAAI,CAAC,OAAS,EAAA;AACZ,IAAA,IAAI,QAAU,EAAA;AACZ,MAAA,iEAAU,QAAS,CAAA;AAAA;AAErB,IACE,uBAAA,KAAA,CAAA,aAAA,CAAC,GAAI,EAAA,EAAA,CAAA,EAAG,CACN,EAAA,kBAAA,KAAA,CAAA,aAAA,CAAC,cAAW,KAAM,EAAA,eAAA,EAAA,EACf,YAAgB,IAAA,6CACnB,CACA,kBAAA,KAAA,CAAA,aAAA,CAAC,OAAI,EAAI,EAAA,CAAA,EAAA,kBACN,KAAA,CAAA,aAAA,CAAA,UAAA,EAAA,EAAW,OAAQ,EAAA,SAAA,EAAU,KAAM,EAAA,eAAA,EAAA,EAAgB,uBAC5B,EAAA,UAAA,CAAW,IACnC,CACF,CACF,CAAA;AAAA;AAIJ,EAAA,iEAAU,QAAS,CAAA;AACrB;;;;"}
1
+ {"version":3,"file":"PermissionGate.esm.js","sources":["../../../src/components/PermissionGate/PermissionGate.tsx"],"sourcesContent":["import React from 'react';\nimport { Typography, Box } from '@material-ui/core';\nimport { Skeleton } from '@material-ui/lab';\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 (\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 (\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"],"names":[],"mappings":";;;;;AAaO,MAAM,iBAAiB,CAAC,EAAE,UAAU,UAAY,EAAA,QAAA,EAAU,cAAwC,KAAA;AACvG,EAAA,MAAM,EAAE,OAAS,EAAA,OAAA,EAAS,KAAM,EAAA,GAAI,sBAAsB,UAAU,CAAA;AAEpE,EAAA,IAAI,OAAS,EAAA;AACX,IAAA,uBACG,KAAA,CAAA,aAAA,CAAA,GAAA,EAAA,EAAI,CAAG,EAAA,CAAA,EAAA,EACL,CAAC,GAAG,KAAM,CAAA,CAAC,CAAC,CAAA,CAAE,GAAI,CAAA,CAAC,CAAG,EAAA,CAAA,qBACpB,KAAA,CAAA,aAAA,CAAA,GAAA,EAAA,EAAI,GAAK,EAAA,CAAA,EAAG,CAAG,EAAA,CAAA,EAAA,kBACb,KAAA,CAAA,aAAA,CAAA,QAAA,EAAA,EAAS,OAAQ,EAAA,MAAA,EAAO,KAAM,EAAA,MAAA,EAAO,CACxC,CACD,CACH,CAAA;AAAA;AAIJ,EAAA,IAAI,KAAO,EAAA;AACT,IAAA,2CACG,GAAI,EAAA,EAAA,CAAA,EAAG,qBACL,KAAA,CAAA,aAAA,CAAA,UAAA,EAAA,EAAW,OAAM,OAAQ,EAAA,EAAA,+BAAA,EACM,MAAM,OACtC,CAAA,sCACC,UAAW,EAAA,EAAA,OAAA,EAAQ,SAAQ,KAAM,EAAA,eAAA,EAAA,EAAgB,gDAElD,CACF,CAAA;AAAA;AAIJ,EAAA,IAAI,CAAC,OAAS,EAAA;AACZ,IAAA,IAAI,QAAU,EAAA;AACZ,MAAA,iEAAU,QAAS,CAAA;AAAA;AAErB,IACE,uBAAA,KAAA,CAAA,aAAA,CAAC,GAAI,EAAA,EAAA,CAAA,EAAG,CACN,EAAA,kBAAA,KAAA,CAAA,aAAA,CAAC,cAAW,KAAM,EAAA,eAAA,EAAA,EACf,YAAgB,IAAA,6CACnB,CACA,kBAAA,KAAA,CAAA,aAAA,CAAC,OAAI,EAAI,EAAA,CAAA,EAAA,kBACN,KAAA,CAAA,aAAA,CAAA,UAAA,EAAA,EAAW,OAAQ,EAAA,SAAA,EAAU,KAAM,EAAA,eAAA,EAAA,EAAgB,uBAC5B,EAAA,UAAA,CAAW,IACnC,CACF,CACF,CAAA;AAAA;AAIJ,EAAA,iEAAU,QAAS,CAAA;AACrB;;;;"}
@@ -30,25 +30,39 @@ const RequestAccessDialog = ({
30
30
  setCreating(true);
31
31
  setCreateError(null);
32
32
  try {
33
- await kuadrantApi.createRequest({
34
- apiProductName,
35
- namespace,
36
- planTier: selectedPlan,
37
- useCase: useCase.trim() || "",
38
- userEmail
39
- });
40
- alertApi.post({
41
- message: "API key requested successfully",
42
- severity: "success",
43
- display: "transient"
44
- });
45
- setSelectedPlan("");
46
- setUseCase("");
47
- onSuccess();
48
- } catch (err) {
49
- const errorMessage = err instanceof Error ? err.message : "unknown error occurred";
33
+ const randomSuffix = Math.random().toString(36).substring(2, 10);
34
+ const secretName = `${apiProductName}-${randomSuffix}-secret`.toLowerCase().replace(/[^a-z0-9-]/g, "-");
35
+ const apiKeyValue = crypto.randomUUID().replace(/-/g, "");
36
+ await kuadrantApi.createSecret(secretName, apiKeyValue);
37
+ try {
38
+ await kuadrantApi.createRequest({
39
+ apiProductName,
40
+ namespace,
41
+ planTier: selectedPlan,
42
+ useCase: useCase.trim() || "",
43
+ userEmail,
44
+ secretName
45
+ });
46
+ alertApi.post({
47
+ message: `Request submitted successfully. Pending API owner approval.`,
48
+ severity: "info",
49
+ display: "transient"
50
+ });
51
+ setSelectedPlan("");
52
+ setUseCase("");
53
+ onSuccess();
54
+ } catch (apiKeyError) {
55
+ try {
56
+ await kuadrantApi.deleteSecret(secretName);
57
+ } catch (deleteError) {
58
+ console.warn("Failed to cleanup orphaned secret:", deleteError);
59
+ }
60
+ throw apiKeyError;
61
+ }
62
+ } catch (error) {
63
+ const errorMessage = error instanceof Error ? error.message : "unknown error occurred";
50
64
  alertApi.post({
51
- message: `Failed to request API key: ${errorMessage}`,
65
+ message: `Failed to create request: ${errorMessage}`,
52
66
  severity: "error",
53
67
  display: "transient"
54
68
  });