@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,11 +1,11 @@
1
1
  import React, { useState, useMemo } from 'react';
2
2
  import { useAsync } from 'react-use';
3
3
  import { CodeSnippet, ResponseErrorPanel, Table } from '@backstage/core-components';
4
- import { Box, Typography, Tabs, Tab, Grid, Button, Menu, MenuItem, Dialog, DialogTitle, DialogContent, DialogActions, Chip, Tooltip, IconButton, CircularProgress } from '@material-ui/core';
4
+ import { Box, Typography, Tabs, Tab, Grid, Button, Menu, MenuItem, Chip, Tooltip, IconButton, CircularProgress } from '@material-ui/core';
5
5
  import { Skeleton } from '@material-ui/lab';
6
6
  import { useApi, identityApiRef, alertApiRef } from '@backstage/core-plugin-api';
7
7
  import { kuadrantApiRef } from '../../api.esm.js';
8
- import { useEntity } from '@backstage/plugin-catalog-react';
8
+ import { useEntity, catalogApiRef } from '@backstage/plugin-catalog-react';
9
9
  import VisibilityIcon from '@material-ui/icons/Visibility';
10
10
  import VisibilityOffIcon from '@material-ui/icons/VisibilityOff';
11
11
  import HourglassEmptyIcon from '@material-ui/icons/HourglassEmpty';
@@ -13,9 +13,9 @@ import CancelIcon from '@material-ui/icons/Cancel';
13
13
  import AddIcon from '@material-ui/icons/Add';
14
14
  import MoreVertIcon from '@material-ui/icons/MoreVert';
15
15
  import FileCopyIcon from '@material-ui/icons/FileCopy';
16
- import WarningIcon from '@material-ui/icons/Warning';
17
16
  import { kuadrantApiKeyCreatePermission, kuadrantApiKeyDeleteOwnPermission, kuadrantApiKeyDeleteAllPermission, kuadrantApiKeyUpdateOwnPermission } from '../../permissions.esm.js';
18
17
  import { useKuadrantPermission, canDeleteResource } from '../../utils/permissions.esm.js';
18
+ import { getAPIKeyPhase } from '../../utils/apikeys.esm.js';
19
19
  import { EditAPIKeyDialog } from '../EditAPIKeyDialog/EditAPIKeyDialog.esm.js';
20
20
  import { ConfirmDeleteDialog } from '../ConfirmDeleteDialog/ConfirmDeleteDialog.esm.js';
21
21
  import { generateAuthCodeSnippets } from '../../utils/codeSnippets.esm.js';
@@ -25,6 +25,7 @@ const ApiKeyManagementTab = ({
25
25
  namespace: propNamespace
26
26
  }) => {
27
27
  const { entity } = useEntity();
28
+ const catalogAPI = useApi(catalogApiRef);
28
29
  const kuadrantApi = useApi(kuadrantApiRef);
29
30
  const identityApi = useApi(identityApiRef);
30
31
  const alertApi = useApi(alertApiRef);
@@ -44,29 +45,28 @@ const ApiKeyManagementTab = ({
44
45
  /* @__PURE__ */ new Map()
45
46
  );
46
47
  const [apiKeyLoading, setApiKeyLoading] = useState(/* @__PURE__ */ new Set());
47
- const [alreadyReadKeys, setAlreadyReadKeys] = useState(
48
- /* @__PURE__ */ new Set()
49
- );
50
- const [showOnceWarningOpen, setShowOnceWarningOpen] = useState(false);
51
- const [pendingKeyReveal, setPendingKeyReveal] = useState(null);
52
48
  const apiProductName = entity.metadata.annotations?.["kuadrant.io/apiproduct"] || entity.metadata.name;
53
49
  const namespace = entity.metadata.annotations?.["kuadrant.io/namespace"] || propNamespace || "default";
54
50
  useAsync(async () => {
55
51
  const identity = await identityApi.getBackstageIdentity();
56
52
  const profile = await identityApi.getProfileInfo();
57
53
  setUserId(identity.userEntityRef);
58
- setUserEmail(profile.email || "");
54
+ let email = profile.email || "";
55
+ if (!email && identity.userEntityRef) {
56
+ const userEntity = await catalogAPI.getEntityByRef(identity.userEntityRef);
57
+ if (userEntity?.spec?.profile?.email) {
58
+ email = userEntity.spec.profile.email;
59
+ }
60
+ }
61
+ setUserEmail(email);
59
62
  }, [identityApi]);
60
63
  const {
61
64
  value: requests,
62
65
  loading: requestsLoading,
63
66
  error: requestsError
64
67
  } = useAsync(async () => {
65
- const data = await kuadrantApi.getRequestsByNamespace(namespace);
66
- return (data.items || []).filter(
67
- (r) => r.spec.apiProductRef.name === apiProductName && r.metadata.namespace === namespace
68
- // APIProducts and APIKeys (and its Secret) will be in the same NS
69
- );
68
+ const data = await kuadrantApi.getRequestsByApiProduct(apiProductName, namespace);
69
+ return data.items || [];
70
70
  }, [apiProductName, namespace, refresh, kuadrantApi]);
71
71
  const {
72
72
  value: apiProduct,
@@ -100,11 +100,11 @@ const ApiKeyManagementTab = ({
100
100
  loading: updateRequestPermissionLoading,
101
101
  error: updateRequestPermissionError
102
102
  } = useKuadrantPermission(kuadrantApiKeyUpdateOwnPermission);
103
- const handleDeleteRequest = async (name) => {
104
- setOptimisticallyDeleted((prev) => new Set(prev).add(name));
105
- setDeleting(name);
103
+ const handleDeleteRequest = async (deleteNamespace, deleteName) => {
104
+ setOptimisticallyDeleted((prev) => new Set(prev).add(deleteName));
105
+ setDeleting(deleteName);
106
106
  try {
107
- await kuadrantApi.deleteRequest(namespace, name);
107
+ await kuadrantApi.deleteRequest(deleteNamespace, deleteName);
108
108
  alertApi.post({
109
109
  message: "API key deleted successfully",
110
110
  severity: "success",
@@ -115,7 +115,7 @@ const ApiKeyManagementTab = ({
115
115
  const errorMessage = err instanceof Error ? err.message : "unknown error occurred";
116
116
  setOptimisticallyDeleted((prev) => {
117
117
  const next = new Set(prev);
118
- next.delete(name);
118
+ next.delete(deleteName);
119
119
  return next;
120
120
  });
121
121
  alertApi.post({
@@ -136,23 +136,14 @@ const ApiKeyManagementTab = ({
136
136
  try {
137
137
  const data = await kuadrantApi.getApiKeySecret(requestNamespace, requestName);
138
138
  setApiKeyValues((prev) => new Map(prev).set(key, data.apiKey));
139
- setAlreadyReadKeys((prev) => new Set(prev).add(key));
139
+ toggleVisibility(requestName);
140
140
  } catch (err) {
141
141
  const errorMessage = err instanceof Error ? err.message : "unknown error occurred";
142
- if (errorMessage.includes("403") || errorMessage.includes("already been viewed")) {
143
- setAlreadyReadKeys((prev) => new Set(prev).add(key));
144
- alertApi.post({
145
- message: "This API key has already been viewed and cannot be retrieved again.",
146
- severity: "warning",
147
- display: "transient"
148
- });
149
- } else {
150
- alertApi.post({
151
- message: `Failed to fetch api key: ${errorMessage}`,
152
- severity: "error",
153
- display: "transient"
154
- });
155
- }
142
+ alertApi.post({
143
+ message: `Failed to fetch api key: ${errorMessage}`,
144
+ severity: "error",
145
+ display: "transient"
146
+ });
156
147
  } finally {
157
148
  setApiKeyLoading((prev) => {
158
149
  const next = new Set(prev);
@@ -200,7 +191,10 @@ const ApiKeyManagementTab = ({
200
191
  };
201
192
  const handleDeleteConfirm = async () => {
202
193
  if (!deleteDialogState.request) return;
203
- await handleDeleteRequest(deleteDialogState.request.metadata.name);
194
+ await handleDeleteRequest(
195
+ deleteDialogState.request.metadata.namespace,
196
+ deleteDialogState.request.metadata.name
197
+ );
204
198
  setDeleteDialogState({ open: false, request: null });
205
199
  };
206
200
  const handleDeleteCancel = () => {
@@ -344,13 +338,13 @@ const ApiKeyManagementTab = ({
344
338
  );
345
339
  const plans = apiProduct?.status?.discoveredPlans || [];
346
340
  const pendingRequests = myRequests.filter(
347
- (r) => !r.status?.phase || r.status.phase === "Pending"
341
+ (r) => getAPIKeyPhase(r.status?.conditions) === "Pending"
348
342
  );
349
343
  const approvedRequests = myRequests.filter(
350
- (r) => r.status?.phase === "Approved"
344
+ (r) => getAPIKeyPhase(r.status?.conditions) === "Approved"
351
345
  );
352
346
  const rejectedRequests = myRequests.filter(
353
- (r) => r.status?.phase === "Rejected"
347
+ (r) => getAPIKeyPhase(r.status?.conditions) === "Denied"
354
348
  );
355
349
  const approvedColumns = [
356
350
  {
@@ -360,8 +354,13 @@ const ApiKeyManagementTab = ({
360
354
  },
361
355
  {
362
356
  title: "Approved",
363
- field: "status.reviewedAt",
364
- render: (row) => /* @__PURE__ */ React.createElement(Typography, { variant: "body2" }, row.status?.reviewedAt ? new Date(row.status.reviewedAt).toLocaleDateString() : "-")
357
+ field: "status.conditions",
358
+ render: (row) => {
359
+ const approvalDate = row.status?.conditions?.find(
360
+ (c) => c.type === "Approved" && c.status === "True"
361
+ )?.lastTransitionTime;
362
+ return /* @__PURE__ */ React.createElement(Typography, { variant: "body2" }, approvalDate ? new Date(approvalDate).toLocaleDateString() : "-");
363
+ }
365
364
  },
366
365
  {
367
366
  title: "API Key",
@@ -373,33 +372,16 @@ const ApiKeyManagementTab = ({
373
372
  const isVisible = visibleKeys.has(row.metadata.name);
374
373
  const isLoading = apiKeyLoading.has(key);
375
374
  const apiKeyValue = apiKeyValues.get(key);
376
- const hasSecretRef = row.status?.secretRef?.name;
377
- const canReadSecret = row.status?.canReadSecret !== false;
378
- const isAlreadyRead = alreadyReadKeys.has(key) || !canReadSecret;
375
+ const hasSecretRef = Boolean(row.spec?.secretRef?.name);
379
376
  if (!hasSecretRef) {
380
377
  return /* @__PURE__ */ React.createElement(Typography, { variant: "body2", color: "textSecondary" }, "Awaiting secret...");
381
378
  }
382
- if (isAlreadyRead && !apiKeyValue) {
383
- 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(
384
- Typography,
385
- {
386
- variant: "body2",
387
- color: "textSecondary",
388
- style: { fontFamily: "monospace", marginRight: 8 }
389
- },
390
- "Already viewed"
391
- ), /* @__PURE__ */ React.createElement(VisibilityOffIcon, { fontSize: "small", color: "disabled" })));
392
- }
393
379
  const handleRevealClick = () => {
394
380
  if (isVisible) {
395
381
  clearApiKeyValue(row.metadata.namespace, row.metadata.name);
396
382
  toggleVisibility(row.metadata.name);
397
- } else if (!isAlreadyRead) {
398
- setPendingKeyReveal({
399
- namespace: row.metadata.namespace,
400
- name: row.metadata.name
401
- });
402
- setShowOnceWarningOpen(true);
383
+ } else {
384
+ fetchApiKeyFromSecret(row.metadata.namespace, row.metadata.name);
403
385
  }
404
386
  };
405
387
  const handleCopy = async () => {
@@ -425,14 +407,14 @@ const ApiKeyManagementTab = ({
425
407
  ), 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(
426
408
  Tooltip,
427
409
  {
428
- title: isVisible ? "Hide API key" : "Reveal API key (one-time only)"
410
+ title: isVisible ? "Hide API key" : "Reveal API key"
429
411
  },
430
412
  /* @__PURE__ */ React.createElement("span", null, /* @__PURE__ */ React.createElement(
431
413
  IconButton,
432
414
  {
433
415
  size: "small",
434
416
  onClick: handleRevealClick,
435
- disabled: isLoading || isAlreadyRead && !apiKeyValue
417
+ disabled: isLoading
436
418
  },
437
419
  isVisible ? /* @__PURE__ */ React.createElement(VisibilityOffIcon, null) : /* @__PURE__ */ React.createElement(VisibilityIcon, null)
438
420
  ))
@@ -479,9 +461,9 @@ const ApiKeyManagementTab = ({
479
461
  const requestColumns = [
480
462
  {
481
463
  title: "Status",
482
- field: "status.phase",
464
+ field: "status.conditions",
483
465
  render: (row) => {
484
- const phase = row.status?.phase || "Pending";
466
+ const phase = getAPIKeyPhase(row.status?.conditions || []);
485
467
  const isPending = phase === "Pending";
486
468
  return /* @__PURE__ */ React.createElement(
487
469
  Chip,
@@ -528,11 +510,12 @@ const ApiKeyManagementTab = ({
528
510
  },
529
511
  {
530
512
  title: "Reviewed",
531
- field: "status.reviewedAt",
513
+ field: "status.conditions",
532
514
  render: (row) => {
533
- if (!row.status?.reviewedAt)
534
- return /* @__PURE__ */ React.createElement(Typography, { variant: "body2" }, "-");
535
- return /* @__PURE__ */ React.createElement(Typography, { variant: "body2" }, new Date(row.status.reviewedAt).toLocaleDateString());
515
+ const approvedDate = row.status?.conditions?.find(
516
+ (c) => (c.type === "Approved" || c.type === "Denied") && c.status === "True"
517
+ )?.lastTransitionTime;
518
+ return /* @__PURE__ */ React.createElement(Typography, { variant: "body2" }, approvedDate ? new Date(approvedDate).toLocaleDateString() : "-");
536
519
  }
537
520
  },
538
521
  {
@@ -545,7 +528,7 @@ const ApiKeyManagementTab = ({
545
528
  if (isDeleting) {
546
529
  return /* @__PURE__ */ React.createElement(CircularProgress, { size: 20 });
547
530
  }
548
- const isPending = !row.status?.phase || row.status.phase === "Pending";
531
+ const isPending = getAPIKeyPhase(row.status?.conditions || []) === "Pending";
549
532
  const ownerId = row.spec.requestedBy.userId;
550
533
  const canDelete = canDeleteResource(
551
534
  ownerId,
@@ -592,12 +575,22 @@ const ApiKeyManagementTab = ({
592
575
  color: "primary",
593
576
  startIcon: /* @__PURE__ */ React.createElement(AddIcon, null),
594
577
  onClick: () => setRequestDialogOpen(true),
595
- disabled: plans.length === 0,
578
+ disabled: plans.length === 0 || !userEmail,
596
579
  "data-testid": "request-api-access-button",
597
580
  "data-plans-count": plans.length
598
581
  },
599
582
  "Request API Access"
600
583
  ),
584
+ !userEmail && /* @__PURE__ */ React.createElement(
585
+ Typography,
586
+ {
587
+ variant: "caption",
588
+ color: "textSecondary",
589
+ style: { marginTop: 4 },
590
+ "data-testid": "no-email-message"
591
+ },
592
+ '"Email address is required"'
593
+ ),
601
594
  plans.length === 0 && /* @__PURE__ */ React.createElement(
602
595
  Typography,
603
596
  {
@@ -641,7 +634,7 @@ const ApiKeyManagementTab = ({
641
634
  )), rejectedRequests.length > 0 && /* @__PURE__ */ React.createElement(Grid, { item: true }, /* @__PURE__ */ React.createElement(
642
635
  Table,
643
636
  {
644
- title: "Rejected Requests",
637
+ title: "Denied Requests",
645
638
  options: {
646
639
  paging: rejectedRequests.length > 5,
647
640
  pageSize: 20,
@@ -696,7 +689,7 @@ const ApiKeyManagementTab = ({
696
689
  anchorPosition: menuAnchor || { top: 0, left: 0 }
697
690
  },
698
691
  menuRequest && (() => {
699
- const isPending = !menuRequest.status?.phase || menuRequest.status.phase === "Pending";
692
+ const isPending = getAPIKeyPhase(menuRequest.status?.conditions || []) === "Pending";
700
693
  const ownerId = menuRequest.spec.requestedBy.userId;
701
694
  const canEdit = canUpdateRequest && ownerId === userId && isPending;
702
695
  const items = [];
@@ -727,51 +720,11 @@ const ApiKeyManagementTab = ({
727
720
  {
728
721
  open: deleteDialogState.open,
729
722
  title: "Delete Request",
730
- description: `Are you sure you want to delete this ${deleteDialogState.request?.status?.phase === "Approved" ? "API key" : "request"}?`,
723
+ description: `Are you sure you want to delete this ${getAPIKeyPhase(deleteDialogState.request?.status?.conditions || []) === "Approved" ? "API key" : "request"}?`,
731
724
  deleting: deleting !== null,
732
725
  onConfirm: handleDeleteConfirm,
733
726
  onCancel: handleDeleteCancel
734
727
  }
735
- ), /* @__PURE__ */ React.createElement(
736
- Dialog,
737
- {
738
- open: showOnceWarningOpen,
739
- onClose: () => {
740
- setShowOnceWarningOpen(false);
741
- setPendingKeyReveal(null);
742
- },
743
- maxWidth: "sm"
744
- },
745
- /* @__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")),
746
- /* @__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.")),
747
- /* @__PURE__ */ React.createElement(DialogActions, null, /* @__PURE__ */ React.createElement(
748
- Button,
749
- {
750
- onClick: () => {
751
- setShowOnceWarningOpen(false);
752
- setPendingKeyReveal(null);
753
- }
754
- },
755
- "Cancel"
756
- ), /* @__PURE__ */ React.createElement(
757
- Button,
758
- {
759
- variant: "contained",
760
- color: "primary",
761
- onClick: () => {
762
- if (pendingKeyReveal) {
763
- fetchApiKeyFromSecret(
764
- pendingKeyReveal.namespace,
765
- pendingKeyReveal.name
766
- );
767
- toggleVisibility(pendingKeyReveal.name);
768
- }
769
- setShowOnceWarningOpen(false);
770
- setPendingKeyReveal(null);
771
- }
772
- },
773
- "Reveal API Key"
774
- ))
775
728
  ));
776
729
  };
777
730