@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 +1 @@
1
- {"version":3,"file":"RequestAccessDialog.esm.js","sources":["../../../src/components/RequestAccessDialog/RequestAccessDialog.tsx"],"sourcesContent":["import React, { useState } from 'react';\nimport {\n Dialog,\n DialogTitle,\n DialogContent,\n DialogActions,\n Button,\n TextField,\n Select,\n MenuItem,\n FormControl,\n InputLabel,\n Box,\n Typography,\n CircularProgress,\n} from '@material-ui/core';\nimport InfoIcon from '@material-ui/icons/Info';\nimport {\n useApi,\n alertApiRef,\n} from '@backstage/core-plugin-api';\nimport { kuadrantApiRef } from '../../api';\nimport { Plan } from \"../../types/api-management.ts\";\n\nexport interface RequestAccessDialogProps {\n open: boolean;\n onClose: () => void;\n onSuccess: () => void;\n apiProductName: string;\n namespace: string;\n userEmail: string;\n plans: Plan[];\n}\n\nexport const RequestAccessDialog = ({\n open,\n onClose,\n onSuccess,\n apiProductName,\n namespace,\n userEmail,\n plans,\n}: RequestAccessDialogProps) => {\n const kuadrantApi = useApi(kuadrantApiRef);\n const alertApi = useApi(alertApiRef);\n\n const [selectedPlan, setSelectedPlan] = useState('');\n const [useCase, setUseCase] = useState('');\n const [creating, setCreating] = useState(false);\n const [createError, setCreateError] = useState<string | null>(null);\n\n const handleClose = () => {\n setSelectedPlan('');\n setUseCase('');\n setCreateError(null);\n onClose();\n };\n\n const handleRequestAccess = async () => {\n if (!selectedPlan) return;\n\n setCreating(true);\n setCreateError(null);\n try {\n await kuadrantApi.createRequest({\n apiProductName,\n namespace,\n planTier: selectedPlan,\n useCase: useCase.trim() || '',\n userEmail,\n });\n\n alertApi.post({\n message: 'API key requested successfully',\n severity: 'success',\n display: 'transient',\n });\n\n setSelectedPlan('');\n setUseCase('');\n onSuccess();\n } catch (err) {\n const errorMessage =\n err instanceof Error ? err.message : 'unknown error occurred';\n alertApi.post({\n message: `Failed to request API key: ${errorMessage}`,\n severity: 'error',\n display: 'transient',\n });\n setCreateError(errorMessage);\n } finally {\n setCreating(false);\n }\n };\n\n return (\n <Dialog open={open} onClose={handleClose} maxWidth=\"sm\" fullWidth>\n <DialogTitle>Request API Access</DialogTitle>\n <DialogContent>\n <Box\n mb={2}\n p={1.5}\n bgcolor=\"info.light\"\n borderRadius={1}\n display=\"flex\"\n alignItems=\"flex-start\"\n style={{ gap: 8 }}\n >\n <InfoIcon\n color=\"primary\"\n fontSize=\"small\"\n style={{ marginTop: 2 }}\n />\n <Typography variant=\"body2\">\n Your request will be reviewed by an API owner before access is\n granted.\n </Typography>\n </Box>\n {createError && (\n <Box\n mb={2}\n p={2}\n bgcolor=\"error.main\"\n color=\"error.contrastText\"\n borderRadius={1}\n >\n <Typography variant=\"body2\">{createError}</Typography>\n </Box>\n )}\n <FormControl\n fullWidth\n margin=\"normal\"\n disabled={creating}\n data-testid=\"tier-select-form\"\n >\n <InputLabel id=\"tier-select-label\">Select Tier</InputLabel>\n <Select\n labelId=\"tier-select-label\"\n data-testid=\"tier-select\"\n value={selectedPlan}\n onChange={(e) => setSelectedPlan(e.target.value as string)}\n disabled={creating}\n >\n {plans.map((plan: Plan) => {\n const limitDesc = Object.entries(plan.limits || {})\n .map(([key, val]) => `${val} per ${key}`)\n .join(', ');\n return (\n <MenuItem\n key={plan.tier}\n value={plan.tier}\n data-testid={`tier-option-${plan.tier}`}\n >\n {plan.tier} {limitDesc ? `(${limitDesc})` : ''}\n </MenuItem>\n );\n })}\n </Select>\n </FormControl>\n <TextField\n label=\"Use Case (optional)\"\n placeholder=\"Describe how you plan to use this API\"\n multiline\n rows={3}\n fullWidth\n margin=\"normal\"\n value={useCase}\n onChange={(e) => setUseCase(e.target.value)}\n helperText=\"Explain your intended use of this API for admin review\"\n disabled={creating}\n />\n </DialogContent>\n <DialogActions>\n <Button onClick={handleClose} disabled={creating}>\n Cancel\n </Button>\n <Button\n onClick={handleRequestAccess}\n color=\"primary\"\n variant=\"contained\"\n disabled={!selectedPlan || creating}\n startIcon={\n creating ? (\n <CircularProgress size={16} color=\"inherit\" />\n ) : undefined\n }\n >\n {creating ? 'Submitting...' : 'Submit Request'}\n </Button>\n </DialogActions>\n </Dialog>\n );\n};\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"RequestAccessDialog.esm.js","sources":["../../../src/components/RequestAccessDialog/RequestAccessDialog.tsx"],"sourcesContent":["import React, { useState } from 'react';\nimport {\n Dialog,\n DialogTitle,\n DialogContent,\n DialogActions,\n Button,\n TextField,\n Select,\n MenuItem,\n FormControl,\n InputLabel,\n Box,\n Typography,\n CircularProgress,\n} from '@material-ui/core';\nimport InfoIcon from '@material-ui/icons/Info';\nimport {\n useApi,\n alertApiRef,\n} from '@backstage/core-plugin-api';\nimport { kuadrantApiRef } from '../../api';\nimport { Plan } from \"../../types/api-management.ts\";\n\nexport interface RequestAccessDialogProps {\n open: boolean;\n onClose: () => void;\n onSuccess: () => void;\n apiProductName: string;\n namespace: string;\n userEmail: string;\n plans: Plan[];\n}\n\nexport const RequestAccessDialog = ({\n open,\n onClose,\n onSuccess,\n apiProductName,\n namespace,\n userEmail,\n plans,\n}: RequestAccessDialogProps) => {\n const kuadrantApi = useApi(kuadrantApiRef);\n const alertApi = useApi(alertApiRef);\n\n const [selectedPlan, setSelectedPlan] = useState('');\n const [useCase, setUseCase] = useState('');\n const [creating, setCreating] = useState(false);\n const [createError, setCreateError] = useState<string | null>(null);\n\n const handleClose = () => {\n setSelectedPlan('');\n setUseCase('');\n setCreateError(null);\n onClose();\n };\n\n const handleRequestAccess = async () => {\n if (!selectedPlan) return;\n\n setCreating(true);\n setCreateError(null);\n\n try {\n // 1. generate secret name and API key value\n const randomSuffix = Math.random().toString(36).substring(2, 10);\n const secretName = `${apiProductName}-${randomSuffix}-secret`\n .toLowerCase()\n .replace(/[^a-z0-9-]/g, '-');\n const apiKeyValue = crypto.randomUUID().replace(/-/g, '');\n\n // 2. create secret in consumer's namespace first (design doc: secret before APIKey)\n await kuadrantApi.createSecret(secretName, apiKeyValue);\n\n try {\n // 3. create APIKey referencing the pre-existing secret\n await kuadrantApi.createRequest({\n apiProductName,\n namespace,\n planTier: selectedPlan,\n useCase: useCase.trim() || '',\n userEmail,\n secretName,\n });\n\n alertApi.post({\n message: `Request submitted successfully. Pending API owner approval.`,\n severity: 'info',\n display: 'transient',\n });\n\n setSelectedPlan('');\n setUseCase('');\n onSuccess();\n\n } catch (apiKeyError) {\n // cleanup orphaned secret if APIKey creation fails\n try {\n await kuadrantApi.deleteSecret(secretName);\n } catch (deleteError) {\n console.warn('Failed to cleanup orphaned secret:', deleteError);\n }\n throw apiKeyError;\n }\n\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : 'unknown error occurred';\n alertApi.post({\n message: `Failed to create request: ${errorMessage}`,\n severity: 'error',\n display: 'transient',\n });\n setCreateError(errorMessage);\n } finally {\n setCreating(false);\n }\n };\n\n return (\n <Dialog open={open} onClose={handleClose} maxWidth=\"sm\" fullWidth>\n <DialogTitle>Request API Access</DialogTitle>\n <DialogContent>\n <Box\n mb={2}\n p={1.5}\n bgcolor=\"info.light\"\n borderRadius={1}\n display=\"flex\"\n alignItems=\"flex-start\"\n style={{ gap: 8 }}\n >\n <InfoIcon\n color=\"primary\"\n fontSize=\"small\"\n style={{ marginTop: 2 }}\n />\n <Typography variant=\"body2\">\n Your request will be reviewed by an API owner before access is\n granted.\n </Typography>\n </Box>\n {createError && (\n <Box\n mb={2}\n p={2}\n bgcolor=\"error.main\"\n color=\"error.contrastText\"\n borderRadius={1}\n >\n <Typography variant=\"body2\">{createError}</Typography>\n </Box>\n )}\n <FormControl\n fullWidth\n margin=\"normal\"\n disabled={creating}\n data-testid=\"tier-select-form\"\n >\n <InputLabel id=\"tier-select-label\">Select Tier</InputLabel>\n <Select\n labelId=\"tier-select-label\"\n data-testid=\"tier-select\"\n value={selectedPlan}\n onChange={(e) => setSelectedPlan(e.target.value as string)}\n disabled={creating}\n >\n {plans.map((plan: Plan) => {\n const limitDesc = Object.entries(plan.limits || {})\n .map(([key, val]) => `${val} per ${key}`)\n .join(', ');\n return (\n <MenuItem\n key={plan.tier}\n value={plan.tier}\n data-testid={`tier-option-${plan.tier}`}\n >\n {plan.tier} {limitDesc ? `(${limitDesc})` : ''}\n </MenuItem>\n );\n })}\n </Select>\n </FormControl>\n <TextField\n label=\"Use Case (optional)\"\n placeholder=\"Describe how you plan to use this API\"\n multiline\n rows={3}\n fullWidth\n margin=\"normal\"\n value={useCase}\n onChange={(e) => setUseCase(e.target.value)}\n helperText=\"Explain your intended use of this API for admin review\"\n disabled={creating}\n />\n </DialogContent>\n <DialogActions>\n <Button onClick={handleClose} disabled={creating}>\n Cancel\n </Button>\n <Button\n onClick={handleRequestAccess}\n color=\"primary\"\n variant=\"contained\"\n disabled={!selectedPlan || creating}\n startIcon={\n creating ? (\n <CircularProgress size={16} color=\"inherit\" />\n ) : undefined\n }\n >\n {creating ? 'Submitting...' : 'Submit Request'}\n </Button>\n </DialogActions>\n </Dialog>\n );\n};\n"],"names":[],"mappings":"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"}
@@ -2,6 +2,7 @@ import React, { useState } from 'react';
2
2
  import { Dialog, DialogTitle, DialogContent, Typography, FormControl, InputLabel, Select, MenuItem, FormHelperText, TextField, DialogActions, Button, CircularProgress } from '@material-ui/core';
3
3
  import { useApi, configApiRef, fetchApiRef, alertApiRef, identityApiRef } from '@backstage/core-plugin-api';
4
4
  import useAsync from 'react-use/lib/useAsync';
5
+ import { kuadrantApiRef } from '../../api.esm.js';
5
6
 
6
7
  const SimpleRequestAccessDialog = ({
7
8
  open,
@@ -12,6 +13,7 @@ const SimpleRequestAccessDialog = ({
12
13
  const fetchApi = useApi(fetchApiRef);
13
14
  const alertApi = useApi(alertApiRef);
14
15
  const identityApi = useApi(identityApiRef);
16
+ const kuadrantApi = useApi(kuadrantApiRef);
15
17
  const backendUrl = config.getString("backend.baseUrl");
16
18
  const [selectedApi, setSelectedApi] = useState("");
17
19
  const [selectedTier, setSelectedTier] = useState("");
@@ -53,6 +55,12 @@ const SimpleRequestAccessDialog = ({
53
55
  const [namespace, apiProductName] = selectedApi.split("/");
54
56
  setCreating(true);
55
57
  try {
58
+ const identity = await identityApi.getBackstageIdentity();
59
+ const username = identity.userEntityRef.split("/")[1] || "unknown";
60
+ const randomSuffix = Math.random().toString(36).substring(2, 10);
61
+ const secretName = `${username}-${apiProductName}-secret-${randomSuffix}`.toLowerCase().replace(/[^a-z0-9-]/g, "-");
62
+ const apiKeyValue = crypto.randomUUID().replace(/-/g, "");
63
+ await kuadrantApi.createSecret(secretName, apiKeyValue);
56
64
  const response = await fetchApi.fetch(
57
65
  `${backendUrl}/api/kuadrant/requests`,
58
66
  {
@@ -65,7 +73,8 @@ const SimpleRequestAccessDialog = ({
65
73
  namespace,
66
74
  planTier: selectedTier,
67
75
  useCase: useCase.trim() || "",
68
- userEmail: userEmail || "unknown"
76
+ userEmail: userEmail || "unknown",
77
+ secretName
69
78
  })
70
79
  }
71
80
  );
@@ -85,7 +94,8 @@ const SimpleRequestAccessDialog = ({
85
94
  namespace,
86
95
  planTier: selectedTier,
87
96
  useCase: useCase.trim() || "",
88
- userEmail: userEmail || "unknown"
97
+ userEmail: userEmail || "unknown",
98
+ secretName: "(generated)"
89
99
  }
90
100
  });
91
101
  const rawError = errorData.error || errorData.message || `Server returned ${response.status}`;
@@ -104,6 +114,7 @@ const SimpleRequestAccessDialog = ({
104
114
  } else if (response.status >= 500) {
105
115
  errorMsg = `Server error: ${rawError}`;
106
116
  }
117
+ await kuadrantApi.deleteSecret(secretName).catch((e) => console.warn("Failed to cleanup orphaned secret:", e));
107
118
  throw new Error(errorMsg);
108
119
  }
109
120
  alertApi.post({
@@ -1 +1 @@
1
- {"version":3,"file":"SimpleRequestAccessDialog.esm.js","sources":["../../../src/components/SimpleRequestAccessDialog/SimpleRequestAccessDialog.tsx"],"sourcesContent":["import React, { useState } from 'react';\nimport {\n Dialog,\n DialogTitle,\n DialogContent,\n DialogActions,\n Button,\n TextField,\n Select,\n MenuItem,\n FormControl,\n InputLabel,\n Typography,\n CircularProgress,\n FormHelperText,\n} from '@material-ui/core';\nimport {\n useApi,\n configApiRef,\n fetchApiRef,\n alertApiRef,\n identityApiRef,\n} from '@backstage/core-plugin-api';\nimport useAsync from 'react-use/lib/useAsync';\n\nexport interface SimpleRequestAccessDialogProps {\n open: boolean;\n onClose: () => void;\n onSuccess: () => void;\n}\n\ntype ApiProduct = {\n metadata: {\n name: string;\n namespace: string;\n };\n spec?: {\n publishStatus?: string;\n };\n status?: {\n discoveredPlans?: Array<{\n tier: string;\n limits?: Record<string, number>;\n }>;\n };\n};\n\nexport const SimpleRequestAccessDialog = ({\n open,\n onClose,\n onSuccess,\n}: SimpleRequestAccessDialogProps) => {\n const config = useApi(configApiRef);\n const fetchApi = useApi(fetchApiRef);\n const alertApi = useApi(alertApiRef);\n const identityApi = useApi(identityApiRef);\n const backendUrl = config.getString('backend.baseUrl');\n\n const [selectedApi, setSelectedApi] = useState('');\n const [selectedTier, setSelectedTier] = useState('');\n const [useCase, setUseCase] = useState('');\n const [creating, setCreating] = useState(false);\n\n // Fetch all published API products\n const {\n value: apiProducts,\n loading: loadingProducts,\n } = useAsync(async () => {\n if (!open) return [];\n const response = await fetchApi.fetch(\n `${backendUrl}/api/kuadrant/apiproducts`,\n );\n if (!response.ok) {\n throw new Error('Failed to fetch API products');\n }\n const data = await response.json();\n // Filter to only show Published products\n return (data.items || []).filter(\n (p: ApiProduct) => p.spec?.publishStatus === 'Published',\n );\n }, [backendUrl, fetchApi, open]);\n\n // Get user email\n const { value: userEmail } = useAsync(async () => {\n const identity = await identityApi.getBackstageIdentity();\n\n // Extract username from userEntityRef (e.g., \"user:default/john\" -> \"john\")\n const username = identity.userEntityRef.split('/')[1] || 'unknown';\n\n // Construct email from username\n return `${username}@example.com`;\n }, [identityApi]);\n\n // Get available tiers for selected API\n const selectedProduct = apiProducts?.find(\n (p: ApiProduct) =>\n `${p.metadata.namespace}/${p.metadata.name}` === selectedApi,\n );\n const availableTiers = selectedProduct?.status?.discoveredPlans || [];\n\n const handleClose = () => {\n setSelectedApi('');\n setSelectedTier('');\n setUseCase('');\n onClose();\n };\n\n const handleSubmit = async () => {\n if (!selectedApi || !selectedTier) return;\n\n const [namespace, apiProductName] = selectedApi.split('/');\n\n setCreating(true);\n try {\n const response = await fetchApi.fetch(\n `${backendUrl}/api/kuadrant/requests`,\n {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({\n apiProductName,\n namespace,\n planTier: selectedTier,\n useCase: useCase.trim() || '',\n userEmail: userEmail || 'unknown',\n }),\n },\n );\n\n if (!response.ok) {\n let errorData;\n try {\n errorData = await response.json();\n } catch {\n errorData = { error: `Server returned ${response.status} ${response.statusText}` };\n }\n\n console.error('Backend error response:', {\n status: response.status,\n statusText: response.statusText,\n errorData,\n requestBody: {\n apiProductName,\n namespace,\n planTier: selectedTier,\n useCase: useCase.trim() || '',\n userEmail: userEmail || 'unknown',\n }\n });\n\n // Extract user-friendly error message\n const rawError = errorData.error || errorData.message || `Server returned ${response.status}`;\n\n // Try to extract validation error details from Kubernetes error messages\n // Example: \"failed to create apikeys: APIKey.devportal.kuadrant.io \"name\" is invalid: spec.requestedBy.email: Invalid value: \"admin\": spec.requestedBy.email in body should match '^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$'\"\n let errorMsg = rawError;\n\n if (rawError.includes('spec.requestedBy.email')) {\n errorMsg = 'Invalid email format. Please contact your administrator to update your profile email.';\n } else if (rawError.includes('is invalid:')) {\n // Extract the validation message after \"is invalid:\"\n const match = rawError.match(/is invalid: (.+?)(?:\\s+\\(|$)/);\n if (match) {\n errorMsg = `Validation error: ${match[1]}`;\n }\n } else if (response.status === 403) {\n errorMsg = 'You do not have permission to request access to this API.';\n } else if (response.status === 404) {\n errorMsg = 'The selected API or tier was not found.';\n } else if (response.status >= 500) {\n errorMsg = `Server error: ${rawError}`;\n }\n\n throw new Error(errorMsg);\n }\n\n alertApi.post({\n message: 'API key requested successfully',\n severity: 'success',\n display: 'transient',\n });\n\n handleClose();\n onSuccess();\n } catch (err) {\n const errorMessage =\n err instanceof Error ? err.message : 'unknown error occurred';\n console.error('Failed to create API key request:', {\n error: err,\n selectedApi,\n selectedTier,\n userEmail,\n });\n alertApi.post({\n message: `Failed to request API key: ${errorMessage}`,\n severity: 'error',\n display: 'permanent',\n });\n } finally {\n setCreating(false);\n }\n };\n\n return (\n <Dialog open={open} onClose={handleClose} maxWidth=\"sm\" fullWidth>\n <DialogTitle>Request API key</DialogTitle>\n <DialogContent>\n <Typography variant=\"body2\" color=\"textSecondary\">\n Submit your request to generate an API key.\n </Typography>\n\n <FormControl fullWidth margin=\"normal\" disabled={creating || loadingProducts}>\n <InputLabel id=\"api-select-label\" required>\n API\n </InputLabel>\n <Select\n labelId=\"api-select-label\"\n value={selectedApi}\n onChange={e => {\n setSelectedApi(e.target.value as string);\n setSelectedTier(''); // Reset tier when API changes\n }}\n disabled={creating || loadingProducts}\n data-testid=\"api-select\"\n >\n {loadingProducts ? (\n <MenuItem disabled>Loading...</MenuItem>\n ) : (\n apiProducts?.map((product: ApiProduct) => (\n <MenuItem\n key={`${product.metadata.namespace}/${product.metadata.name}`}\n value={`${product.metadata.namespace}/${product.metadata.name}`}\n >\n {product.metadata.name}\n </MenuItem>\n ))\n )}\n </Select>\n <FormHelperText>\n Select one API. Please submit separate requests for multiple APIs.\n </FormHelperText>\n </FormControl>\n\n <FormControl\n fullWidth\n margin=\"normal\"\n disabled={creating || !selectedApi}\n required\n >\n <InputLabel id=\"tier-select-label\">Tiers</InputLabel>\n <Select\n labelId=\"tier-select-label\"\n value={selectedTier}\n onChange={e => setSelectedTier(e.target.value as string)}\n disabled={creating || !selectedApi}\n data-testid=\"tier-select\"\n >\n {!selectedApi ? (\n <MenuItem disabled>Select an API first</MenuItem>\n ) : availableTiers.length === 0 ? (\n <MenuItem disabled>No tiers available</MenuItem>\n ) : (\n availableTiers.map((plan: { tier: string; limits?: Record<string, number> }) => {\n const limitDesc = Object.entries(plan.limits || {})\n .map(([key, val]) => `${val} per ${key}`)\n .join(', ');\n return (\n <MenuItem key={plan.tier} value={plan.tier}>\n {plan.tier} {limitDesc ? `(${limitDesc})` : ''}\n </MenuItem>\n );\n })\n )}\n </Select>\n <FormHelperText>Select an API to view available tiers.</FormHelperText>\n </FormControl>\n\n <TextField\n label=\"Use case\"\n placeholder=\"Briefly describe your specific use case of using this API key\"\n multiline\n rows={2}\n fullWidth\n margin=\"normal\"\n value={useCase}\n onChange={e => setUseCase(e.target.value)}\n disabled={creating}\n inputProps={{ 'data-testid': 'usecase-input' }}\n />\n </DialogContent>\n <DialogActions>\n <Button onClick={handleClose} disabled={creating} data-testid=\"cancel-button\">\n Cancel\n </Button>\n <Button\n onClick={handleSubmit}\n color=\"primary\"\n variant=\"contained\"\n disabled={!selectedApi || !selectedTier || creating}\n startIcon={\n creating ? (\n <CircularProgress size={16} color=\"inherit\" />\n ) : undefined\n }\n data-testid=\"submit-button\"\n >\n {creating ? 'Submitting...' : 'Request'}\n </Button>\n </DialogActions>\n </Dialog>\n );\n};\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"SimpleRequestAccessDialog.esm.js","sources":["../../../src/components/SimpleRequestAccessDialog/SimpleRequestAccessDialog.tsx"],"sourcesContent":["import React, { useState } from 'react';\nimport {\n Dialog,\n DialogTitle,\n DialogContent,\n DialogActions,\n Button,\n TextField,\n Select,\n MenuItem,\n FormControl,\n InputLabel,\n Typography,\n CircularProgress,\n FormHelperText,\n} from '@material-ui/core';\nimport {\n useApi,\n configApiRef,\n fetchApiRef,\n alertApiRef,\n identityApiRef,\n} from '@backstage/core-plugin-api';\nimport useAsync from 'react-use/lib/useAsync';\nimport { kuadrantApiRef } from '../../api';\n\nexport interface SimpleRequestAccessDialogProps {\n open: boolean;\n onClose: () => void;\n onSuccess: () => void;\n}\n\ntype ApiProduct = {\n metadata: {\n name: string;\n namespace: string;\n };\n spec?: {\n publishStatus?: string;\n };\n status?: {\n discoveredPlans?: Array<{\n tier: string;\n limits?: Record<string, number>;\n }>;\n };\n};\n\nexport const SimpleRequestAccessDialog = ({\n open,\n onClose,\n onSuccess,\n}: SimpleRequestAccessDialogProps) => {\n const config = useApi(configApiRef);\n const fetchApi = useApi(fetchApiRef);\n const alertApi = useApi(alertApiRef);\n const identityApi = useApi(identityApiRef);\n const kuadrantApi = useApi(kuadrantApiRef);\n const backendUrl = config.getString('backend.baseUrl');\n\n const [selectedApi, setSelectedApi] = useState('');\n const [selectedTier, setSelectedTier] = useState('');\n const [useCase, setUseCase] = useState('');\n const [creating, setCreating] = useState(false);\n\n // Fetch all published API products\n const {\n value: apiProducts,\n loading: loadingProducts,\n } = useAsync(async () => {\n if (!open) return [];\n const response = await fetchApi.fetch(\n `${backendUrl}/api/kuadrant/apiproducts`,\n );\n if (!response.ok) {\n throw new Error('Failed to fetch API products');\n }\n const data = await response.json();\n // Filter to only show Published products\n return (data.items || []).filter(\n (p: ApiProduct) => p.spec?.publishStatus === 'Published',\n );\n }, [backendUrl, fetchApi, open]);\n\n // Get user email\n const { value: userEmail } = useAsync(async () => {\n const identity = await identityApi.getBackstageIdentity();\n\n // Extract username from userEntityRef (e.g., \"user:default/john\" -> \"john\")\n const username = identity.userEntityRef.split('/')[1] || 'unknown';\n\n // Construct email from username\n return `${username}@example.com`;\n }, [identityApi]);\n\n // Get available tiers for selected API\n const selectedProduct = apiProducts?.find(\n (p: ApiProduct) =>\n `${p.metadata.namespace}/${p.metadata.name}` === selectedApi,\n );\n const availableTiers = selectedProduct?.status?.discoveredPlans || [];\n\n const handleClose = () => {\n setSelectedApi('');\n setSelectedTier('');\n setUseCase('');\n onClose();\n };\n\n const handleSubmit = async () => {\n if (!selectedApi || !selectedTier) return;\n\n const [namespace, apiProductName] = selectedApi.split('/');\n\n setCreating(true);\n try {\n // 1. generate secret name and API key value\n const identity = await identityApi.getBackstageIdentity();\n const username = identity.userEntityRef.split('/')[1] || 'unknown';\n const randomSuffix = Math.random().toString(36).substring(2, 10);\n const secretName = `${username}-${apiProductName}-secret-${randomSuffix}`\n .toLowerCase()\n .replace(/[^a-z0-9-]/g, '-');\n const apiKeyValue = crypto.randomUUID().replace(/-/g, '');\n\n // 2. create secret first (design doc: secret must exist before APIKey)\n await kuadrantApi.createSecret(secretName, apiKeyValue);\n\n // 3. create APIKey referencing the pre-existing secret\n const response = await fetchApi.fetch(\n `${backendUrl}/api/kuadrant/requests`,\n {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({\n apiProductName,\n namespace,\n planTier: selectedTier,\n useCase: useCase.trim() || '',\n userEmail: userEmail || 'unknown',\n secretName,\n }),\n },\n );\n\n if (!response.ok) {\n let errorData;\n try {\n errorData = await response.json();\n } catch {\n errorData = { error: `Server returned ${response.status} ${response.statusText}` };\n }\n\n console.error('Backend error response:', {\n status: response.status,\n statusText: response.statusText,\n errorData,\n requestBody: {\n apiProductName,\n namespace,\n planTier: selectedTier,\n useCase: useCase.trim() || '',\n userEmail: userEmail || 'unknown',\n secretName: '(generated)',\n }\n });\n\n // Extract user-friendly error message\n const rawError = errorData.error || errorData.message || `Server returned ${response.status}`;\n\n // Try to extract validation error details from Kubernetes error messages\n // Example: \"failed to create apikeys: APIKey.devportal.kuadrant.io \"name\" is invalid: spec.requestedBy.email: Invalid value: \"admin\": spec.requestedBy.email in body should match '^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$'\"\n let errorMsg = rawError;\n\n if (rawError.includes('spec.requestedBy.email')) {\n errorMsg = 'Invalid email format. Please contact your administrator to update your profile email.';\n } else if (rawError.includes('is invalid:')) {\n // Extract the validation message after \"is invalid:\"\n const match = rawError.match(/is invalid: (.+?)(?:\\s+\\(|$)/);\n if (match) {\n errorMsg = `Validation error: ${match[1]}`;\n }\n } else if (response.status === 403) {\n errorMsg = 'You do not have permission to request access to this API.';\n } else if (response.status === 404) {\n errorMsg = 'The selected API or tier was not found.';\n } else if (response.status >= 500) {\n errorMsg = `Server error: ${rawError}`;\n }\n\n // cleanup orphaned secret since APIKey creation failed\n await kuadrantApi.deleteSecret(secretName)\n .catch(e => console.warn('Failed to cleanup orphaned secret:', e));\n\n throw new Error(errorMsg);\n }\n\n alertApi.post({\n message: 'API key requested successfully',\n severity: 'success',\n display: 'transient',\n });\n\n handleClose();\n onSuccess();\n } catch (err) {\n const errorMessage =\n err instanceof Error ? err.message : 'unknown error occurred';\n console.error('Failed to create API key request:', {\n error: err,\n selectedApi,\n selectedTier,\n userEmail,\n });\n alertApi.post({\n message: `Failed to request API key: ${errorMessage}`,\n severity: 'error',\n display: 'permanent',\n });\n } finally {\n setCreating(false);\n }\n };\n\n return (\n <Dialog open={open} onClose={handleClose} maxWidth=\"sm\" fullWidth>\n <DialogTitle>Request API key</DialogTitle>\n <DialogContent>\n <Typography variant=\"body2\" color=\"textSecondary\">\n Submit your request to generate an API key.\n </Typography>\n\n <FormControl fullWidth margin=\"normal\" disabled={creating || loadingProducts}>\n <InputLabel id=\"api-select-label\" required>\n API\n </InputLabel>\n <Select\n labelId=\"api-select-label\"\n value={selectedApi}\n onChange={e => {\n setSelectedApi(e.target.value as string);\n setSelectedTier(''); // Reset tier when API changes\n }}\n disabled={creating || loadingProducts}\n data-testid=\"api-select\"\n >\n {loadingProducts ? (\n <MenuItem disabled>Loading...</MenuItem>\n ) : (\n apiProducts?.map((product: ApiProduct) => (\n <MenuItem\n key={`${product.metadata.namespace}/${product.metadata.name}`}\n value={`${product.metadata.namespace}/${product.metadata.name}`}\n >\n {product.metadata.name}\n </MenuItem>\n ))\n )}\n </Select>\n <FormHelperText>\n Select one API. Please submit separate requests for multiple APIs.\n </FormHelperText>\n </FormControl>\n\n <FormControl\n fullWidth\n margin=\"normal\"\n disabled={creating || !selectedApi}\n required\n >\n <InputLabel id=\"tier-select-label\">Tiers</InputLabel>\n <Select\n labelId=\"tier-select-label\"\n value={selectedTier}\n onChange={e => setSelectedTier(e.target.value as string)}\n disabled={creating || !selectedApi}\n data-testid=\"tier-select\"\n >\n {!selectedApi ? (\n <MenuItem disabled>Select an API first</MenuItem>\n ) : availableTiers.length === 0 ? (\n <MenuItem disabled>No tiers available</MenuItem>\n ) : (\n availableTiers.map((plan: { tier: string; limits?: Record<string, number> }) => {\n const limitDesc = Object.entries(plan.limits || {})\n .map(([key, val]) => `${val} per ${key}`)\n .join(', ');\n return (\n <MenuItem key={plan.tier} value={plan.tier}>\n {plan.tier} {limitDesc ? `(${limitDesc})` : ''}\n </MenuItem>\n );\n })\n )}\n </Select>\n <FormHelperText>Select an API to view available tiers.</FormHelperText>\n </FormControl>\n\n <TextField\n label=\"Use case\"\n placeholder=\"Briefly describe your specific use case of using this API key\"\n multiline\n rows={2}\n fullWidth\n margin=\"normal\"\n value={useCase}\n onChange={e => setUseCase(e.target.value)}\n disabled={creating}\n inputProps={{ 'data-testid': 'usecase-input' }}\n />\n </DialogContent>\n <DialogActions>\n <Button onClick={handleClose} disabled={creating} data-testid=\"cancel-button\">\n Cancel\n </Button>\n <Button\n onClick={handleSubmit}\n color=\"primary\"\n variant=\"contained\"\n disabled={!selectedApi || !selectedTier || creating}\n startIcon={\n creating ? (\n <CircularProgress size={16} color=\"inherit\" />\n ) : undefined\n }\n data-testid=\"submit-button\"\n >\n {creating ? 'Submitting...' : 'Request'}\n </Button>\n </DialogActions>\n </Dialog>\n );\n};\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ import React from 'react';
2
+ import ApiOutlined from '@mui/icons-material/ApiOutlined';
3
+ import KeyOutlined from '@mui/icons-material/KeyOutlined';
4
+ import ApprovalOutlined from '@mui/icons-material/ApprovalOutlined';
5
+
6
+ const ApiIcon = (props) => /* @__PURE__ */ React.createElement(ApiOutlined, { ...props });
7
+ const KeyIcon = (props) => /* @__PURE__ */ React.createElement(KeyOutlined, { ...props });
8
+ const ApprovalIcon = (props) => /* @__PURE__ */ React.createElement(ApprovalOutlined, { ...props });
9
+
10
+ export { ApiIcon, ApprovalIcon, KeyIcon };
11
+ //# sourceMappingURL=icons.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"icons.esm.js","sources":["../../src/components/icons.tsx"],"sourcesContent":["import React from 'react';\nimport ApiOutlined from '@mui/icons-material/ApiOutlined';\nimport KeyOutlined from '@mui/icons-material/KeyOutlined';\nimport ApprovalOutlined from '@mui/icons-material/ApprovalOutlined';\nimport { SvgIconProps } from '@mui/material/SvgIcon';\n\nexport const ApiIcon = (props: SvgIconProps) => <ApiOutlined {...props} />;\nexport const KeyIcon = (props: SvgIconProps) => <KeyOutlined {...props} />;\nexport const ApprovalIcon = (props: SvgIconProps) => <ApprovalOutlined {...props} />;\n"],"names":[],"mappings":";;;;;AAMO,MAAM,UAAU,CAAC,KAAA,qBAAyB,KAAA,CAAA,aAAA,CAAA,WAAA,EAAA,EAAa,GAAG,KAAO,EAAA;AACjE,MAAM,UAAU,CAAC,KAAA,qBAAyB,KAAA,CAAA,aAAA,CAAA,WAAA,EAAA,EAAa,GAAG,KAAO,EAAA;AACjE,MAAM,eAAe,CAAC,KAAA,qBAAyB,KAAA,CAAA,aAAA,CAAA,gBAAA,EAAA,EAAkB,GAAG,KAAO,EAAA;;;;"}
package/dist/index.d.ts CHANGED
@@ -2,6 +2,7 @@ import * as react from 'react';
2
2
  import react__default from 'react';
3
3
  import * as _backstage_core_plugin_api from '@backstage/core-plugin-api';
4
4
  import { DiscoveryApi, FetchApi, IdentityApi } from '@backstage/core-plugin-api';
5
+ import { SvgIconProps } from '@mui/material/SvgIcon';
5
6
  import * as _backstage_plugin_permission_common from '@backstage/plugin-permission-common';
6
7
 
7
8
  interface ApiKeyManagementTabProps {
@@ -27,12 +28,17 @@ declare const EntityKuadrantApiKeyManagementTab: ({ namespace: propNamespace, }:
27
28
  declare const EntityKuadrantApiKeysContent: ({ namespace: propNamespace, }: ApiKeyManagementTabProps) => react.JSX.Element;
28
29
  declare const EntityKuadrantApiProductInfoContent: () => react.JSX.Element;
29
30
  declare const ApiKeyDetailPage: () => react.JSX.Element;
30
- declare const EntityKuadrantApiApprovalTab: () => react.JSX.Element;
31
31
  declare const EntityKuadrantApiProductOpenApiAlert: () => react.JSX.Element | null;
32
32
  declare const ApiProductDetailPage: () => react.JSX.Element;
33
33
 
34
34
  declare const ApiProductInfoCard: () => react__default.JSX.Element;
35
35
 
36
+ declare const KuadrantIcon: (props: SvgIconProps) => react__default.JSX.Element;
37
+
38
+ declare const ApiIcon: (props: SvgIconProps) => react__default.JSX.Element;
39
+ declare const KeyIcon: (props: SvgIconProps) => react__default.JSX.Element;
40
+ declare const ApprovalIcon: (props: SvgIconProps) => react__default.JSX.Element;
41
+
36
42
  /**
37
43
  * permission definitions for the kuadrant plugin
38
44
  *
@@ -150,7 +156,7 @@ declare const kuadrantApiKeyApprovePermission: _backstage_plugin_permission_comm
150
156
  declare const kuadrantPermissions: (_backstage_plugin_permission_common.BasicPermission | _backstage_plugin_permission_common.ResourcePermission<"apiproduct">)[];
151
157
 
152
158
  type PlanTier = string;
153
- type RequestPhase = 'Pending' | 'Approved' | 'Rejected';
159
+ type RequestPhase = 'Pending' | 'Approved' | 'Denied';
154
160
  interface PlanLimits {
155
161
  daily?: number;
156
162
  weekly?: number;
@@ -173,6 +179,7 @@ interface StatusCondition {
173
179
  interface APIKeySpec {
174
180
  apiProductRef: {
175
181
  name: string;
182
+ namespace: string;
176
183
  };
177
184
  planTier: PlanTier;
178
185
  useCase: string;
@@ -180,6 +187,9 @@ interface APIKeySpec {
180
187
  userId: string;
181
188
  email: string;
182
189
  };
190
+ secretRef: {
191
+ name: string;
192
+ };
183
193
  }
184
194
  interface CredentialsAuthorizationHeader {
185
195
  prefix?: string;
@@ -214,16 +224,21 @@ interface APIKeyAuthScheme {
214
224
  credentials?: Credentials;
215
225
  }
216
226
  interface APIKeyStatus {
227
+ /** @deprecated Use getAPIKeyPhase(conditions) instead. Will be removed after all components migrated. */
217
228
  phase?: RequestPhase;
229
+ /** @deprecated Will be removed in future version. */
218
230
  reviewedBy?: string;
231
+ /** @deprecated Will be removed in future version. */
219
232
  reviewedAt?: string;
220
- apiHostname?: string;
221
- limits?: PlanLimits;
233
+ /** @deprecated Use spec.secretRef instead. */
222
234
  secretRef?: {
223
235
  name: string;
224
236
  key: string;
225
237
  };
238
+ /** @deprecated Secret viewing no longer restricted. Will be removed in future version. */
226
239
  canReadSecret?: boolean;
240
+ apiHostname?: string;
241
+ limits?: PlanLimits;
227
242
  authScheme?: APIKeyAuthScheme;
228
243
  conditions?: StatusCondition[];
229
244
  }
@@ -246,6 +261,7 @@ interface APIKeyRequest {
246
261
  planTier: PlanTier;
247
262
  useCase: string;
248
263
  userEmail: string;
264
+ secretName?: string;
249
265
  }
250
266
  interface APIProductSpec {
251
267
  displayName: string;
@@ -449,6 +465,20 @@ interface KuadrantAPI {
449
465
  * @returns Promise with list of requests in the namespace
450
466
  */
451
467
  getRequestsByNamespace(namespace: string): Promise<KuadrantList<APIKey>>;
468
+ /**
469
+ * Fetch the current user's API key requests for a specific APIProduct
470
+ * @param apiProductName - Name of the APIProduct
471
+ * @param apiProductNamespace - Namespace of the APIProduct
472
+ * @returns Promise with list of the user's API key requests for this product
473
+ */
474
+ getRequestsByApiProduct(apiProductName: string, apiProductNamespace: string): Promise<KuadrantList<APIKey>>;
475
+ /**
476
+ * Fetch all API key requests for a specific APIProduct (admin view)
477
+ * @param apiProductName - Name of the APIProduct
478
+ * @param apiProductNamespace - Namespace of the APIProduct
479
+ * @returns Promise with list of all API key requests for this product
480
+ */
481
+ getAllRequestsByApiProduct(apiProductName: string, apiProductNamespace: string): Promise<KuadrantList<APIKey>>;
452
482
  /**
453
483
  * Fetch a single API key request
454
484
  * @param namespace - API key request name
@@ -490,7 +520,7 @@ interface KuadrantAPI {
490
520
  * @param namespace - Kubernetes namespace
491
521
  * @param name - API key request name
492
522
  * @param reviewedBy - Reviewed By User / System
493
- * @returns Promise with the rejected API key
523
+ * @returns Promise with the denied API key
494
524
  */
495
525
  rejectRequest(namespace: string, name: string, reviewedBy: string): Promise<APIKey>;
496
526
  /**
@@ -587,6 +617,20 @@ interface KuadrantAPI {
587
617
  * @returns Promise with list of all ratelimitpolicies
588
618
  */
589
619
  getRateLimitPolicies(): Promise<KuadrantList<RateLimitPolicy>>;
620
+ /**
621
+ * Create a secret in consumer's own namespace
622
+ * Backend determines namespace from authenticated user identity.
623
+ * @param name - Secret name
624
+ * @param apiKeyValue - API key value to store
625
+ * @returns Promise that resolves when secret is created
626
+ */
627
+ createSecret(name: string, apiKeyValue: string): Promise<void>;
628
+ /**
629
+ * Delete a secret from consumer's own namespace
630
+ * @param name - Secret name
631
+ * @returns Promise that resolves when secret is deleted
632
+ */
633
+ deleteSecret(name: string): Promise<void>;
590
634
  }
591
635
  /**
592
636
  * API reference for the Kuadrant API
@@ -616,6 +660,8 @@ declare class KuadrantApiClient implements KuadrantAPI {
616
660
  getRequests(): Promise<KuadrantList<APIKey>>;
617
661
  getAllRequests(): Promise<KuadrantList<APIKey>>;
618
662
  getRequestsByNamespace(namespace: string): Promise<KuadrantList<APIKey>>;
663
+ getRequestsByApiProduct(apiProductName: string, apiProductNamespace: string): Promise<KuadrantList<APIKey>>;
664
+ getAllRequestsByApiProduct(apiProductName: string, apiProductNamespace: string): Promise<KuadrantList<APIKey>>;
619
665
  getRequest(namespace: string, name: string): Promise<APIKey>;
620
666
  createRequest(request: APIKeyRequest): Promise<APIKey>;
621
667
  updateRequest(namespace: string, name: string, patch: Partial<APIKeySpec>): Promise<APIKey>;
@@ -642,6 +688,8 @@ declare class KuadrantApiClient implements KuadrantAPI {
642
688
  getPlanPolicies(): Promise<KuadrantList<PlanPolicy>>;
643
689
  getAuthPolicies(): Promise<KuadrantList<AuthPolicy>>;
644
690
  getRateLimitPolicies(): Promise<KuadrantList<RateLimitPolicy>>;
691
+ createSecret(name: string, apiKeyValue: string): Promise<void>;
692
+ deleteSecret(name: string): Promise<void>;
645
693
  }
646
694
 
647
695
  /**
@@ -654,4 +702,4 @@ declare const kuadrantApiFactory: _backstage_core_plugin_api.ApiFactory<Kuadrant
654
702
  identityApi: _backstage_core_plugin_api.IdentityApi;
655
703
  }>;
656
704
 
657
- export { ApiAccessCard, ApiKeyApprovalPage, ApiKeyDetailPage, ApiKeyManagementTab, ApiProductDetailPage, ApiProductInfoCard, ApiProductsPage, EntityKuadrantApiAccessCard, EntityKuadrantApiApprovalTab, EntityKuadrantApiKeyManagementTab, EntityKuadrantApiKeysContent, EntityKuadrantApiProductInfoContent, EntityKuadrantApiProductOpenApiAlert, type KuadrantAPI, KuadrantPage, MyApiKeysPage, kuadrantApiFactory, kuadrantApiKeyApprovePermission, kuadrantApiKeyCreatePermission, kuadrantApiKeyDeleteAllPermission, kuadrantApiKeyDeleteOwnPermission, kuadrantApiKeyReadAllPermission, kuadrantApiKeyReadOwnPermission, kuadrantApiKeyUpdateAllPermission, kuadrantApiKeyUpdateOwnPermission, kuadrantApiProductCreatePermission, kuadrantApiProductDeleteAllPermission, kuadrantApiProductDeleteOwnPermission, kuadrantApiProductListPermission, kuadrantApiProductReadAllPermission, kuadrantApiProductReadOwnPermission, kuadrantApiProductUpdateAllPermission, kuadrantApiProductUpdateOwnPermission, kuadrantApiRef, kuadrantAuthPolicyListPermission, kuadrantPermissions, kuadrantPlanPolicyCreatePermission, kuadrantPlanPolicyDeletePermission, kuadrantPlanPolicyListPermission, kuadrantPlanPolicyReadPermission, kuadrantPlanPolicyUpdatePermission, kuadrantPlugin, kuadrantRateLimitPolicyListPermission };
705
+ export { ApiAccessCard, ApiIcon, ApiKeyApprovalPage, ApiKeyDetailPage, ApiKeyManagementTab, ApiProductDetailPage, ApiProductInfoCard, ApiProductsPage, ApprovalIcon, EntityKuadrantApiAccessCard, EntityKuadrantApiKeyManagementTab, EntityKuadrantApiKeysContent, EntityKuadrantApiProductInfoContent, EntityKuadrantApiProductOpenApiAlert, KeyIcon, type KuadrantAPI, KuadrantIcon, KuadrantPage, MyApiKeysPage, kuadrantApiFactory, kuadrantApiKeyApprovePermission, kuadrantApiKeyCreatePermission, kuadrantApiKeyDeleteAllPermission, kuadrantApiKeyDeleteOwnPermission, kuadrantApiKeyReadAllPermission, kuadrantApiKeyReadOwnPermission, kuadrantApiKeyUpdateAllPermission, kuadrantApiKeyUpdateOwnPermission, kuadrantApiProductCreatePermission, kuadrantApiProductDeleteAllPermission, kuadrantApiProductDeleteOwnPermission, kuadrantApiProductListPermission, kuadrantApiProductReadAllPermission, kuadrantApiProductReadOwnPermission, kuadrantApiProductUpdateAllPermission, kuadrantApiProductUpdateOwnPermission, kuadrantApiRef, kuadrantAuthPolicyListPermission, kuadrantPermissions, kuadrantPlanPolicyCreatePermission, kuadrantPlanPolicyDeletePermission, kuadrantPlanPolicyListPermission, kuadrantPlanPolicyReadPermission, kuadrantPlanPolicyUpdatePermission, kuadrantPlugin, kuadrantRateLimitPolicyListPermission };
package/dist/index.esm.js CHANGED
@@ -1,7 +1,9 @@
1
- export { ApiKeyApprovalPage, ApiKeyDetailPage, ApiProductDetailPage, ApiProductsPage, EntityKuadrantApiAccessCard, EntityKuadrantApiApprovalTab, EntityKuadrantApiKeyManagementTab, EntityKuadrantApiKeysContent, EntityKuadrantApiProductInfoContent, EntityKuadrantApiProductOpenApiAlert, KuadrantPage, MyApiKeysPage, kuadrantPlugin } from './plugin.esm.js';
1
+ export { ApiKeyApprovalPage, ApiKeyDetailPage, ApiProductDetailPage, ApiProductsPage, EntityKuadrantApiAccessCard, EntityKuadrantApiKeyManagementTab, EntityKuadrantApiKeysContent, EntityKuadrantApiProductInfoContent, EntityKuadrantApiProductOpenApiAlert, KuadrantPage, MyApiKeysPage, kuadrantPlugin } from './plugin.esm.js';
2
2
  export { ApiAccessCard } from './components/ApiAccessCard/ApiAccessCard.esm.js';
3
3
  export { ApiKeyManagementTab } from './components/ApiKeyManagementTab/ApiKeyManagementTab.esm.js';
4
4
  export { ApiProductInfoCard } from './components/ApiProductInfoCard/ApiProductInfoCard.esm.js';
5
+ export { KuadrantIcon } from './components/KuadrantIcon/KuadrantIcon.esm.js';
6
+ export { ApiIcon, ApprovalIcon, KeyIcon } from './components/icons.esm.js';
5
7
  export { kuadrantApiKeyApprovePermission, kuadrantApiKeyCreatePermission, kuadrantApiKeyDeleteAllPermission, kuadrantApiKeyDeleteOwnPermission, kuadrantApiKeyReadAllPermission, kuadrantApiKeyReadOwnPermission, kuadrantApiKeyUpdateAllPermission, kuadrantApiKeyUpdateOwnPermission, kuadrantApiProductCreatePermission, kuadrantApiProductDeleteAllPermission, kuadrantApiProductDeleteOwnPermission, kuadrantApiProductListPermission, kuadrantApiProductReadAllPermission, kuadrantApiProductReadOwnPermission, kuadrantApiProductUpdateAllPermission, kuadrantApiProductUpdateOwnPermission, kuadrantAuthPolicyListPermission, kuadrantPermissions, kuadrantPlanPolicyCreatePermission, kuadrantPlanPolicyDeletePermission, kuadrantPlanPolicyListPermission, kuadrantPlanPolicyReadPermission, kuadrantPlanPolicyUpdatePermission, kuadrantRateLimitPolicyListPermission } from './permissions.esm.js';
6
8
  export { kuadrantApiRef } from './api.esm.js';
7
9
  export { kuadrantApiFactory } from './apis.esm.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.esm.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;"}
1
+ {"version":3,"file":"index.esm.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;"}
@@ -32,7 +32,7 @@ const MyApiKeysPage = kuadrantPlugin.provide(
32
32
  const ApiKeyApprovalPage = kuadrantPlugin.provide(
33
33
  createRoutableExtension({
34
34
  name: "ApiKeyApprovalPage",
35
- component: () => import('./components/ApiKeyApprovalPage/index.esm.js').then((m) => m.ApiKeyApprovalPage),
35
+ component: () => import('./components/ApiKeyApprovalPage/index.esm.js').then((m) => m.ApiKeyApprovalPageWithPermissions),
36
36
  mountPoint: rootRouteRef
37
37
  })
38
38
  );
@@ -75,14 +75,6 @@ const ApiKeyDetailPage = kuadrantPlugin.provide(
75
75
  mountPoint: rootRouteRef
76
76
  })
77
77
  );
78
- const EntityKuadrantApiApprovalTab = kuadrantPlugin.provide(
79
- createComponentExtension({
80
- name: "EntityKuadrantApiApprovalTab",
81
- component: {
82
- lazy: () => import('./components/EntityApiApprovalTab/index.esm.js').then((m) => m.EntityApiApprovalTab)
83
- }
84
- })
85
- );
86
78
  const EntityKuadrantApiProductOpenApiAlert = kuadrantPlugin.provide(
87
79
  createComponentExtension({
88
80
  name: "EntityKuadrantApiProductOpenApiAlert",
@@ -99,5 +91,5 @@ const ApiProductDetailPage = kuadrantPlugin.provide(
99
91
  })
100
92
  );
101
93
 
102
- export { ApiKeyApprovalPage, ApiKeyDetailPage, ApiProductDetailPage, ApiProductsPage, EntityKuadrantApiAccessCard, EntityKuadrantApiApprovalTab, EntityKuadrantApiKeyManagementTab, EntityKuadrantApiKeysContent, EntityKuadrantApiProductInfoContent, EntityKuadrantApiProductOpenApiAlert, KuadrantPage, MyApiKeysPage, kuadrantPlugin };
94
+ export { ApiKeyApprovalPage, ApiKeyDetailPage, ApiProductDetailPage, ApiProductsPage, EntityKuadrantApiAccessCard, EntityKuadrantApiKeyManagementTab, EntityKuadrantApiKeysContent, EntityKuadrantApiProductInfoContent, EntityKuadrantApiProductOpenApiAlert, KuadrantPage, MyApiKeysPage, kuadrantPlugin };
103
95
  //# sourceMappingURL=plugin.esm.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"plugin.esm.js","sources":["../src/plugin.ts"],"sourcesContent":["import {\n createPlugin,\n createRoutableExtension,\n createComponentExtension,\n} from '@backstage/core-plugin-api';\n\nimport { rootRouteRef, resourceRouteRef } from './routes';\n\nexport const kuadrantPlugin = createPlugin({\n id: 'kuadrant',\n routes: {\n root: rootRouteRef,\n resource: resourceRouteRef,\n },\n});\n\nexport const KuadrantPage = kuadrantPlugin.provide(\n createRoutableExtension({\n name: 'KuadrantPage',\n component: () =>\n import('./components/KuadrantPage').then(m => m.ApiProductsPage),\n mountPoint: rootRouteRef,\n }),\n);\n\nexport const ApiProductsPage = kuadrantPlugin.provide(\n createRoutableExtension({\n name: 'ApiProductsPage',\n component: () =>\n import('./components/KuadrantPage').then(m => m.ApiProductsPage),\n mountPoint: rootRouteRef,\n }),\n);\n\nexport const MyApiKeysPage = kuadrantPlugin.provide(\n createRoutableExtension({\n name: 'MyApiKeysPage',\n component: () =>\n import('./components/MyApiKeysPage').then(m => m.MyApiKeysPage),\n mountPoint: rootRouteRef,\n }),\n);\n\nexport const ApiKeyApprovalPage = kuadrantPlugin.provide(\n createRoutableExtension({\n name: 'ApiKeyApprovalPage',\n component: () =>\n import('./components/ApiKeyApprovalPage').then(m => m.ApiKeyApprovalPage),\n mountPoint: rootRouteRef,\n }),\n);\n\nexport const EntityKuadrantApiAccessCard = kuadrantPlugin.provide(\n createComponentExtension({\n name: 'EntityKuadrantApiAccessCard',\n component: {\n lazy: () =>\n import('./components/ApiAccessCard').then(m => m.ApiAccessCard),\n },\n }),\n);\n\nexport const EntityKuadrantApiKeyManagementTab = kuadrantPlugin.provide(\n createComponentExtension({\n name: 'EntityKuadrantApiKeyManagementTab',\n component: {\n lazy: () =>\n import('./components/ApiKeyManagementTab').then(m => m.ApiKeyManagementTab),\n },\n }),\n);\n\n// entity content extension for api keys tab\nexport const EntityKuadrantApiKeysContent = kuadrantPlugin.provide(\n createComponentExtension({\n name: 'EntityKuadrantApiKeysContent',\n component: {\n lazy: () =>\n import('./components/ApiKeyManagementTab').then(m => m.ApiKeyManagementTab),\n },\n }),\n);\n\nexport const EntityKuadrantApiProductInfoContent = kuadrantPlugin.provide(\n createComponentExtension({\n name: 'EntityKuadrantApiProductInfoContent',\n component: {\n lazy: () =>\n import('./components/ApiProductInfoCard').then(m => m.ApiProductInfoCard),\n },\n }),\n);\n\nexport const ApiKeyDetailPage = kuadrantPlugin.provide(\n createRoutableExtension({\n name: 'ApiKeyDetailPage',\n component: () =>\n import('./components/ApiKeyDetailPage').then(m => m.ApiKeyDetailPage),\n mountPoint: rootRouteRef,\n }),\n);\n\nexport const EntityKuadrantApiApprovalTab = kuadrantPlugin.provide(\n createComponentExtension({\n name: 'EntityKuadrantApiApprovalTab',\n component: {\n lazy: () =>\n import('./components/EntityApiApprovalTab').then(m => m.EntityApiApprovalTab),\n },\n }),\n);\n\nexport const EntityKuadrantApiProductOpenApiAlert = kuadrantPlugin.provide(\n createComponentExtension({\n name: 'EntityKuadrantApiProductOpenApiAlert',\n component: {\n lazy: () =>\n import('./components/ApiProductOpenApiAlert').then(m => m.ApiProductOpenApiAlert),\n },\n }),\n);\n\nexport const ApiProductDetailPage = kuadrantPlugin.provide(\n createRoutableExtension({\n name: 'ApiProductDetailPage',\n component: () =>\n import('./components/ApiProductDetailPage').then(m => m.ApiProductDetailPage),\n mountPoint: rootRouteRef,\n }),\n);\n"],"names":[],"mappings":";;;AAQO,MAAM,iBAAiB,YAAa,CAAA;AAAA,EACzC,EAAI,EAAA,UAAA;AAAA,EACJ,MAAQ,EAAA;AAAA,IACN,IAAM,EAAA,YAAA;AAAA,IACN,QAAU,EAAA;AAAA;AAEd,CAAC;AAEM,MAAM,eAAe,cAAe,CAAA,OAAA;AAAA,EACzC,uBAAwB,CAAA;AAAA,IACtB,IAAM,EAAA,cAAA;AAAA,IACN,SAAA,EAAW,MACT,OAAO,wCAA2B,EAAE,IAAK,CAAA,CAAA,CAAA,KAAK,EAAE,eAAe,CAAA;AAAA,IACjE,UAAY,EAAA;AAAA,GACb;AACH;AAEO,MAAM,kBAAkB,cAAe,CAAA,OAAA;AAAA,EAC5C,uBAAwB,CAAA;AAAA,IACtB,IAAM,EAAA,iBAAA;AAAA,IACN,SAAA,EAAW,MACT,OAAO,wCAA2B,EAAE,IAAK,CAAA,CAAA,CAAA,KAAK,EAAE,eAAe,CAAA;AAAA,IACjE,UAAY,EAAA;AAAA,GACb;AACH;AAEO,MAAM,gBAAgB,cAAe,CAAA,OAAA;AAAA,EAC1C,uBAAwB,CAAA;AAAA,IACtB,IAAM,EAAA,eAAA;AAAA,IACN,SAAA,EAAW,MACT,OAAO,yCAA4B,EAAE,IAAK,CAAA,CAAA,CAAA,KAAK,EAAE,aAAa,CAAA;AAAA,IAChE,UAAY,EAAA;AAAA,GACb;AACH;AAEO,MAAM,qBAAqB,cAAe,CAAA,OAAA;AAAA,EAC/C,uBAAwB,CAAA;AAAA,IACtB,IAAM,EAAA,oBAAA;AAAA,IACN,SAAA,EAAW,MACT,OAAO,8CAAiC,EAAE,IAAK,CAAA,CAAA,CAAA,KAAK,EAAE,kBAAkB,CAAA;AAAA,IAC1E,UAAY,EAAA;AAAA,GACb;AACH;AAEO,MAAM,8BAA8B,cAAe,CAAA,OAAA;AAAA,EACxD,wBAAyB,CAAA;AAAA,IACvB,IAAM,EAAA,6BAAA;AAAA,IACN,SAAW,EAAA;AAAA,MACT,IAAA,EAAM,MACJ,OAAO,yCAA4B,EAAE,IAAK,CAAA,CAAA,CAAA,KAAK,EAAE,aAAa;AAAA;AAClE,GACD;AACH;AAEO,MAAM,oCAAoC,cAAe,CAAA,OAAA;AAAA,EAC9D,wBAAyB,CAAA;AAAA,IACvB,IAAM,EAAA,mCAAA;AAAA,IACN,SAAW,EAAA;AAAA,MACT,IAAA,EAAM,MACJ,OAAO,+CAAkC,EAAE,IAAK,CAAA,CAAA,CAAA,KAAK,EAAE,mBAAmB;AAAA;AAC9E,GACD;AACH;AAGO,MAAM,+BAA+B,cAAe,CAAA,OAAA;AAAA,EACzD,wBAAyB,CAAA;AAAA,IACvB,IAAM,EAAA,8BAAA;AAAA,IACN,SAAW,EAAA;AAAA,MACT,IAAA,EAAM,MACJ,OAAO,+CAAkC,EAAE,IAAK,CAAA,CAAA,CAAA,KAAK,EAAE,mBAAmB;AAAA;AAC9E,GACD;AACH;AAEO,MAAM,sCAAsC,cAAe,CAAA,OAAA;AAAA,EAChE,wBAAyB,CAAA;AAAA,IACvB,IAAM,EAAA,qCAAA;AAAA,IACN,SAAW,EAAA;AAAA,MACT,IAAA,EAAM,MACJ,OAAO,8CAAiC,EAAE,IAAK,CAAA,CAAA,CAAA,KAAK,EAAE,kBAAkB;AAAA;AAC5E,GACD;AACH;AAEO,MAAM,mBAAmB,cAAe,CAAA,OAAA;AAAA,EAC7C,uBAAwB,CAAA;AAAA,IACtB,IAAM,EAAA,kBAAA;AAAA,IACN,SAAA,EAAW,MACT,OAAO,4CAA+B,EAAE,IAAK,CAAA,CAAA,CAAA,KAAK,EAAE,gBAAgB,CAAA;AAAA,IACtE,UAAY,EAAA;AAAA,GACb;AACH;AAEO,MAAM,+BAA+B,cAAe,CAAA,OAAA;AAAA,EACzD,wBAAyB,CAAA;AAAA,IACvB,IAAM,EAAA,8BAAA;AAAA,IACN,SAAW,EAAA;AAAA,MACT,IAAA,EAAM,MACJ,OAAO,gDAAmC,EAAE,IAAK,CAAA,CAAA,CAAA,KAAK,EAAE,oBAAoB;AAAA;AAChF,GACD;AACH;AAEO,MAAM,uCAAuC,cAAe,CAAA,OAAA;AAAA,EACjE,wBAAyB,CAAA;AAAA,IACvB,IAAM,EAAA,sCAAA;AAAA,IACN,SAAW,EAAA;AAAA,MACT,IAAA,EAAM,MACJ,OAAO,kDAAqC,EAAE,IAAK,CAAA,CAAA,CAAA,KAAK,EAAE,sBAAsB;AAAA;AACpF,GACD;AACH;AAEO,MAAM,uBAAuB,cAAe,CAAA,OAAA;AAAA,EACjD,uBAAwB,CAAA;AAAA,IACtB,IAAM,EAAA,sBAAA;AAAA,IACN,SAAA,EAAW,MACT,OAAO,gDAAmC,EAAE,IAAK,CAAA,CAAA,CAAA,KAAK,EAAE,oBAAoB,CAAA;AAAA,IAC9E,UAAY,EAAA;AAAA,GACb;AACH;;;;"}
1
+ {"version":3,"file":"plugin.esm.js","sources":["../src/plugin.ts"],"sourcesContent":["import {\n createPlugin,\n createRoutableExtension,\n createComponentExtension,\n} from '@backstage/core-plugin-api';\n\nimport { rootRouteRef, resourceRouteRef } from './routes';\n\nexport const kuadrantPlugin = createPlugin({\n id: 'kuadrant',\n routes: {\n root: rootRouteRef,\n resource: resourceRouteRef,\n },\n});\n\nexport const KuadrantPage = kuadrantPlugin.provide(\n createRoutableExtension({\n name: 'KuadrantPage',\n component: () =>\n import('./components/KuadrantPage').then(m => m.ApiProductsPage),\n mountPoint: rootRouteRef,\n }),\n);\n\nexport const ApiProductsPage = kuadrantPlugin.provide(\n createRoutableExtension({\n name: 'ApiProductsPage',\n component: () =>\n import('./components/KuadrantPage').then(m => m.ApiProductsPage),\n mountPoint: rootRouteRef,\n }),\n);\n\nexport const MyApiKeysPage = kuadrantPlugin.provide(\n createRoutableExtension({\n name: 'MyApiKeysPage',\n component: () =>\n import('./components/MyApiKeysPage').then(m => m.MyApiKeysPage),\n mountPoint: rootRouteRef,\n }),\n);\n\nexport const ApiKeyApprovalPage = kuadrantPlugin.provide(\n createRoutableExtension({\n name: 'ApiKeyApprovalPage',\n component: () =>\n import('./components/ApiKeyApprovalPage').then(m => m.ApiKeyApprovalPageWithPermissions),\n mountPoint: rootRouteRef,\n }),\n);\n\nexport const EntityKuadrantApiAccessCard = kuadrantPlugin.provide(\n createComponentExtension({\n name: 'EntityKuadrantApiAccessCard',\n component: {\n lazy: () =>\n import('./components/ApiAccessCard').then(m => m.ApiAccessCard),\n },\n }),\n);\n\nexport const EntityKuadrantApiKeyManagementTab = kuadrantPlugin.provide(\n createComponentExtension({\n name: 'EntityKuadrantApiKeyManagementTab',\n component: {\n lazy: () =>\n import('./components/ApiKeyManagementTab').then(m => m.ApiKeyManagementTab),\n },\n }),\n);\n\n// entity content extension for api keys tab\nexport const EntityKuadrantApiKeysContent = kuadrantPlugin.provide(\n createComponentExtension({\n name: 'EntityKuadrantApiKeysContent',\n component: {\n lazy: () =>\n import('./components/ApiKeyManagementTab').then(m => m.ApiKeyManagementTab),\n },\n }),\n);\n\nexport const EntityKuadrantApiProductInfoContent = kuadrantPlugin.provide(\n createComponentExtension({\n name: 'EntityKuadrantApiProductInfoContent',\n component: {\n lazy: () =>\n import('./components/ApiProductInfoCard').then(m => m.ApiProductInfoCard),\n },\n }),\n);\n\nexport const ApiKeyDetailPage = kuadrantPlugin.provide(\n createRoutableExtension({\n name: 'ApiKeyDetailPage',\n component: () =>\n import('./components/ApiKeyDetailPage').then(m => m.ApiKeyDetailPage),\n mountPoint: rootRouteRef,\n }),\n);\n\nexport const EntityKuadrantApiProductOpenApiAlert = kuadrantPlugin.provide(\n createComponentExtension({\n name: 'EntityKuadrantApiProductOpenApiAlert',\n component: {\n lazy: () =>\n import('./components/ApiProductOpenApiAlert').then(m => m.ApiProductOpenApiAlert),\n },\n }),\n);\n\nexport const ApiProductDetailPage = kuadrantPlugin.provide(\n createRoutableExtension({\n name: 'ApiProductDetailPage',\n component: () =>\n import('./components/ApiProductDetailPage').then(m => m.ApiProductDetailPage),\n mountPoint: rootRouteRef,\n }),\n);\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ function getAPIKeyPhase(conditions) {
2
+ if (!conditions || conditions.length === 0) {
3
+ return "Pending";
4
+ }
5
+ const approved = conditions.find(
6
+ (c) => c.type === "Approved" && c.status === "True"
7
+ );
8
+ if (approved) return "Approved";
9
+ const denied = conditions.find(
10
+ (c) => c.type === "Denied" && c.status === "True"
11
+ );
12
+ if (denied) return "Denied";
13
+ const failed = conditions.find(
14
+ (c) => c.type === "Failed" && c.status === "True"
15
+ );
16
+ if (failed) return "Failed";
17
+ return "Pending";
18
+ }
19
+
20
+ export { getAPIKeyPhase };
21
+ //# sourceMappingURL=apikeys.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"apikeys.esm.js","sources":["../../src/utils/apikeys.ts"],"sourcesContent":["import { StatusCondition } from '../types/api-management';\n\n/**\n * Derives the APIKey approval phase from Kubernetes conditions.\n *\n * Maps conditions to phases:\n * - Empty conditions array → Pending\n * - Approved condition (status: True) → Approved\n * - Denied condition (status: True) → Denied\n * - Failed condition (status: True) → Failed\n *\n * @param conditions - Array of Kubernetes status conditions\n * @returns Current approval phase\n */\nexport function getAPIKeyPhase(\n conditions?: StatusCondition[]\n): 'Pending' | 'Approved' | 'Denied' | 'Failed' {\n if (!conditions || conditions.length === 0) {\n return 'Pending';\n }\n\n const approved = conditions.find(\n c => c.type === 'Approved' && c.status === 'True'\n );\n if (approved) return 'Approved';\n\n const denied = conditions.find(\n c => c.type === 'Denied' && c.status === 'True'\n );\n if (denied) return 'Denied';\n\n const failed = conditions.find(\n c => c.type === 'Failed' && c.status === 'True'\n );\n if (failed) return 'Failed';\n\n return 'Pending';\n}\n"],"names":[],"mappings":"AAcO,SAAS,eACd,UAC8C,EAAA;AAC9C,EAAA,IAAI,CAAC,UAAA,IAAc,UAAW,CAAA,MAAA,KAAW,CAAG,EAAA;AAC1C,IAAO,OAAA,SAAA;AAAA;AAGT,EAAA,MAAM,WAAW,UAAW,CAAA,IAAA;AAAA,IAC1B,CAAK,CAAA,KAAA,CAAA,CAAE,IAAS,KAAA,UAAA,IAAc,EAAE,MAAW,KAAA;AAAA,GAC7C;AACA,EAAA,IAAI,UAAiB,OAAA,UAAA;AAErB,EAAA,MAAM,SAAS,UAAW,CAAA,IAAA;AAAA,IACxB,CAAK,CAAA,KAAA,CAAA,CAAE,IAAS,KAAA,QAAA,IAAY,EAAE,MAAW,KAAA;AAAA,GAC3C;AACA,EAAA,IAAI,QAAe,OAAA,QAAA;AAEnB,EAAA,MAAM,SAAS,UAAW,CAAA,IAAA;AAAA,IACxB,CAAK,CAAA,KAAA,CAAA,CAAE,IAAS,KAAA,QAAA,IAAY,EAAE,MAAW,KAAA;AAAA,GAC3C;AACA,EAAA,IAAI,QAAe,OAAA,QAAA;AAEnB,EAAO,OAAA,SAAA;AACT;;;;"}
@@ -4,9 +4,12 @@ const getMyApiKeysStatusChipStyle = (phase) => {
4
4
  case "Approved":
5
5
  return { ...base, backgroundColor: "#1976d2", color: "#fff" };
6
6
  // Blue
7
- case "Rejected":
7
+ case "Denied":
8
8
  return { ...base, backgroundColor: "#d32f2f", color: "#fff" };
9
9
  // Red
10
+ case "Failed":
11
+ return { ...base, backgroundColor: "#ed6c02", color: "#fff" };
12
+ // Orange
10
13
  case "Pending":
11
14
  return { ...base, backgroundColor: "#9c27b0", color: "#fff" };
12
15
  // Purple
@@ -20,7 +23,7 @@ const getApprovalQueueStatusChipStyle = (phase) => {
20
23
  case "Approved":
21
24
  return { ...base, backgroundColor: "#2e7d32", color: "#fff" };
22
25
  // Green
23
- case "Rejected":
26
+ case "Denied":
24
27
  return { ...base, backgroundColor: "#d32f2f", color: "#fff" };
25
28
  // Red
26
29
  case "Pending":
@@ -1 +1 @@
1
- {"version":3,"file":"styles.esm.js","sources":["../../src/utils/styles.ts"],"sourcesContent":["import { CSSProperties } from \"react\";\n\n/**\n * Returns inline styles for API key status chips on the My API Keys page.\n */\nexport const getMyApiKeysStatusChipStyle = (phase: string): CSSProperties => {\n const base = { border: \"none\" };\n switch (phase) {\n case \"Approved\":\n return { ...base, backgroundColor: \"#1976d2\", color: \"#fff\" }; // Blue\n case \"Rejected\":\n return { ...base, backgroundColor: \"#d32f2f\", color: \"#fff\" }; // Red\n case \"Pending\":\n return { ...base, backgroundColor: \"#9c27b0\", color: \"#fff\" }; // Purple\n default:\n return { ...base, backgroundColor: \"#9c27b0\", color: \"#fff\" }; // Purple (fallback for Pending)\n }\n};\n\n/**\n * Returns inline styles for API key status chips on the Approval Queue page.\n * Uses inline styles to ensure proper specificity with Material-UI Chip.\n */\nexport const getApprovalQueueStatusChipStyle = (phase: string): CSSProperties => {\n const base = { border: \"none\" };\n switch (phase) {\n case \"Approved\":\n return { ...base, backgroundColor: \"#2e7d32\", color: \"#fff\" }; // Green\n case \"Rejected\":\n return { ...base, backgroundColor: \"#d32f2f\", color: \"#fff\" }; // Red\n case \"Pending\":\n return { ...base, backgroundColor: \"#ed6c02\", color: \"#fff\" }; // Orange\n default:\n return { ...base, backgroundColor: \"#ed6c02\", color: \"#fff\" }; // Orange (fallback for Pending)\n }\n};\n\n/**\n * Returns inline styles for lifecycle chips.\n * Uses inline styles to ensure proper specificity with Material-UI Chip.\n */\nexport const getLifecycleChipStyle = (lifecycle: string): CSSProperties => {\n switch (lifecycle) {\n case \"production\":\n return { backgroundColor: \"#1976d2\", color: \"#fff\" }; // Blue\n case \"experimental\":\n return { backgroundColor: \"#9c27b0\", color: \"#fff\" }; // Purple\n case \"deprecated\":\n return { backgroundColor: \"#ff9800\", color: \"#fff\" }; // Orange\n case \"retired\":\n return { backgroundColor: \"#d32f2f\", color: \"#fff\" }; // Red\n default:\n return {};\n }\n};\n"],"names":[],"mappings":"AAKa,MAAA,2BAAA,GAA8B,CAAC,KAAiC,KAAA;AAC3E,EAAM,MAAA,IAAA,GAAO,EAAE,MAAA,EAAQ,MAAO,EAAA;AAC9B,EAAA,QAAQ,KAAO;AAAA,IACb,KAAK,UAAA;AACH,MAAA,OAAO,EAAE,GAAG,IAAA,EAAM,eAAiB,EAAA,SAAA,EAAW,OAAO,MAAO,EAAA;AAAA;AAAA,IAC9D,KAAK,UAAA;AACH,MAAA,OAAO,EAAE,GAAG,IAAA,EAAM,eAAiB,EAAA,SAAA,EAAW,OAAO,MAAO,EAAA;AAAA;AAAA,IAC9D,KAAK,SAAA;AACH,MAAA,OAAO,EAAE,GAAG,IAAA,EAAM,eAAiB,EAAA,SAAA,EAAW,OAAO,MAAO,EAAA;AAAA;AAAA,IAC9D;AACE,MAAA,OAAO,EAAE,GAAG,IAAA,EAAM,eAAiB,EAAA,SAAA,EAAW,OAAO,MAAO,EAAA;AAAA;AAElE;AAMa,MAAA,+BAAA,GAAkC,CAAC,KAAiC,KAAA;AAC/E,EAAM,MAAA,IAAA,GAAO,EAAE,MAAA,EAAQ,MAAO,EAAA;AAC9B,EAAA,QAAQ,KAAO;AAAA,IACb,KAAK,UAAA;AACH,MAAA,OAAO,EAAE,GAAG,IAAA,EAAM,eAAiB,EAAA,SAAA,EAAW,OAAO,MAAO,EAAA;AAAA;AAAA,IAC9D,KAAK,UAAA;AACH,MAAA,OAAO,EAAE,GAAG,IAAA,EAAM,eAAiB,EAAA,SAAA,EAAW,OAAO,MAAO,EAAA;AAAA;AAAA,IAC9D,KAAK,SAAA;AACH,MAAA,OAAO,EAAE,GAAG,IAAA,EAAM,eAAiB,EAAA,SAAA,EAAW,OAAO,MAAO,EAAA;AAAA;AAAA,IAC9D;AACE,MAAA,OAAO,EAAE,GAAG,IAAA,EAAM,eAAiB,EAAA,SAAA,EAAW,OAAO,MAAO,EAAA;AAAA;AAElE;AAMa,MAAA,qBAAA,GAAwB,CAAC,SAAqC,KAAA;AACzE,EAAA,QAAQ,SAAW;AAAA,IACjB,KAAK,YAAA;AACH,MAAA,OAAO,EAAE,eAAA,EAAiB,SAAW,EAAA,KAAA,EAAO,MAAO,EAAA;AAAA;AAAA,IACrD,KAAK,cAAA;AACH,MAAA,OAAO,EAAE,eAAA,EAAiB,SAAW,EAAA,KAAA,EAAO,MAAO,EAAA;AAAA;AAAA,IACrD,KAAK,YAAA;AACH,MAAA,OAAO,EAAE,eAAA,EAAiB,SAAW,EAAA,KAAA,EAAO,MAAO,EAAA;AAAA;AAAA,IACrD,KAAK,SAAA;AACH,MAAA,OAAO,EAAE,eAAA,EAAiB,SAAW,EAAA,KAAA,EAAO,MAAO,EAAA;AAAA;AAAA,IACrD;AACE,MAAA,OAAO,EAAC;AAAA;AAEd;;;;"}
1
+ {"version":3,"file":"styles.esm.js","sources":["../../src/utils/styles.ts"],"sourcesContent":["import { CSSProperties } from \"react\";\n\n/**\n * Returns inline styles for API key status chips on the My API Keys page.\n */\nexport const getMyApiKeysStatusChipStyle = (phase: string): CSSProperties => {\n const base = { border: \"none\" };\n switch (phase) {\n case \"Approved\":\n return { ...base, backgroundColor: \"#1976d2\", color: \"#fff\" }; // Blue\n case \"Denied\":\n return { ...base, backgroundColor: \"#d32f2f\", color: \"#fff\" }; // Red\n case \"Failed\":\n return { ...base, backgroundColor: \"#ed6c02\", color: \"#fff\" }; // Orange\n case \"Pending\":\n return { ...base, backgroundColor: \"#9c27b0\", color: \"#fff\" }; // Purple\n default:\n return { ...base, backgroundColor: \"#9c27b0\", color: \"#fff\" }; // Purple (fallback for Pending)\n }\n};\n\n/**\n * Returns inline styles for API key status chips on the Approval Queue page.\n * Uses inline styles to ensure proper specificity with Material-UI Chip.\n */\nexport const getApprovalQueueStatusChipStyle = (phase: string): CSSProperties => {\n const base = { border: \"none\" };\n switch (phase) {\n case \"Approved\":\n return { ...base, backgroundColor: \"#2e7d32\", color: \"#fff\" }; // Green\n case \"Denied\":\n return { ...base, backgroundColor: \"#d32f2f\", color: \"#fff\" }; // Red\n case \"Pending\":\n return { ...base, backgroundColor: \"#ed6c02\", color: \"#fff\" }; // Orange\n default:\n return { ...base, backgroundColor: \"#ed6c02\", color: \"#fff\" }; // Orange (fallback for Pending)\n }\n};\n\n/**\n * Returns inline styles for lifecycle chips.\n * Uses inline styles to ensure proper specificity with Material-UI Chip.\n */\nexport const getLifecycleChipStyle = (lifecycle: string): CSSProperties => {\n switch (lifecycle) {\n case \"production\":\n return { backgroundColor: \"#1976d2\", color: \"#fff\" }; // Blue\n case \"experimental\":\n return { backgroundColor: \"#9c27b0\", color: \"#fff\" }; // Purple\n case \"deprecated\":\n return { backgroundColor: \"#ff9800\", color: \"#fff\" }; // Orange\n case \"retired\":\n return { backgroundColor: \"#d32f2f\", color: \"#fff\" }; // Red\n default:\n return {};\n }\n};\n"],"names":[],"mappings":"AAKa,MAAA,2BAAA,GAA8B,CAAC,KAAiC,KAAA;AAC3E,EAAM,MAAA,IAAA,GAAO,EAAE,MAAA,EAAQ,MAAO,EAAA;AAC9B,EAAA,QAAQ,KAAO;AAAA,IACb,KAAK,UAAA;AACH,MAAA,OAAO,EAAE,GAAG,IAAA,EAAM,eAAiB,EAAA,SAAA,EAAW,OAAO,MAAO,EAAA;AAAA;AAAA,IAC9D,KAAK,QAAA;AACH,MAAA,OAAO,EAAE,GAAG,IAAA,EAAM,eAAiB,EAAA,SAAA,EAAW,OAAO,MAAO,EAAA;AAAA;AAAA,IAC9D,KAAK,QAAA;AACH,MAAA,OAAO,EAAE,GAAG,IAAA,EAAM,eAAiB,EAAA,SAAA,EAAW,OAAO,MAAO,EAAA;AAAA;AAAA,IAC9D,KAAK,SAAA;AACH,MAAA,OAAO,EAAE,GAAG,IAAA,EAAM,eAAiB,EAAA,SAAA,EAAW,OAAO,MAAO,EAAA;AAAA;AAAA,IAC9D;AACE,MAAA,OAAO,EAAE,GAAG,IAAA,EAAM,eAAiB,EAAA,SAAA,EAAW,OAAO,MAAO,EAAA;AAAA;AAElE;AAMa,MAAA,+BAAA,GAAkC,CAAC,KAAiC,KAAA;AAC/E,EAAM,MAAA,IAAA,GAAO,EAAE,MAAA,EAAQ,MAAO,EAAA;AAC9B,EAAA,QAAQ,KAAO;AAAA,IACb,KAAK,UAAA;AACH,MAAA,OAAO,EAAE,GAAG,IAAA,EAAM,eAAiB,EAAA,SAAA,EAAW,OAAO,MAAO,EAAA;AAAA;AAAA,IAC9D,KAAK,QAAA;AACH,MAAA,OAAO,EAAE,GAAG,IAAA,EAAM,eAAiB,EAAA,SAAA,EAAW,OAAO,MAAO,EAAA;AAAA;AAAA,IAC9D,KAAK,SAAA;AACH,MAAA,OAAO,EAAE,GAAG,IAAA,EAAM,eAAiB,EAAA,SAAA,EAAW,OAAO,MAAO,EAAA;AAAA;AAAA,IAC9D;AACE,MAAA,OAAO,EAAE,GAAG,IAAA,EAAM,eAAiB,EAAA,SAAA,EAAW,OAAO,MAAO,EAAA;AAAA;AAElE;AAMa,MAAA,qBAAA,GAAwB,CAAC,SAAqC,KAAA;AACzE,EAAA,QAAQ,SAAW;AAAA,IACjB,KAAK,YAAA;AACH,MAAA,OAAO,EAAE,eAAA,EAAiB,SAAW,EAAA,KAAA,EAAO,MAAO,EAAA;AAAA;AAAA,IACrD,KAAK,cAAA;AACH,MAAA,OAAO,EAAE,eAAA,EAAiB,SAAW,EAAA,KAAA,EAAO,MAAO,EAAA;AAAA;AAAA,IACrD,KAAK,YAAA;AACH,MAAA,OAAO,EAAE,eAAA,EAAiB,SAAW,EAAA,KAAA,EAAO,MAAO,EAAA;AAAA;AAAA,IACrD,KAAK,SAAA;AACH,MAAA,OAAO,EAAE,eAAA,EAAiB,SAAW,EAAA,KAAA,EAAO,MAAO,EAAA;AAAA;AAAA,IACrD;AACE,MAAA,OAAO,EAAC;AAAA;AAEd;;;;"}