@kuadrant/kuadrant-backstage-plugin-frontend 0.0.2-dev-0b744dd → 0.0.2-dev-9be93a3

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 (145) hide show
  1. package/dist/api.esm.js +220 -0
  2. package/dist/api.esm.js.map +1 -0
  3. package/dist/apis.esm.js +15 -0
  4. package/dist/apis.esm.js.map +1 -0
  5. package/dist/components/ApiAccessCard/ApiAccessCard.esm.js +27 -37
  6. package/dist/components/ApiAccessCard/ApiAccessCard.esm.js.map +1 -1
  7. package/dist/components/ApiKeyApprovalPage/ApiKeyApprovalPage.esm.js +10 -0
  8. package/dist/components/ApiKeyApprovalPage/ApiKeyApprovalPage.esm.js.map +1 -0
  9. package/dist/components/ApiKeyApprovalPage/index.esm.js +2 -0
  10. package/dist/components/ApiKeyDetailPage/ApiKeyDetailPage.esm.js +28 -40
  11. package/dist/components/ApiKeyDetailPage/ApiKeyDetailPage.esm.js.map +1 -1
  12. package/dist/components/ApiKeyManagementTab/ApiKeyManagementTab.esm.js +20 -46
  13. package/dist/components/ApiKeyManagementTab/ApiKeyManagementTab.esm.js.map +1 -1
  14. package/dist/components/ApiProductDetailPage/ApiProductDetailPage.esm.js +27 -35
  15. package/dist/components/ApiProductDetailPage/ApiProductDetailPage.esm.js.map +1 -1
  16. package/dist/components/ApiProductDetails/ApiProductDetails.esm.js +13 -3
  17. package/dist/components/ApiProductDetails/ApiProductDetails.esm.js.map +1 -1
  18. package/dist/components/ApiProductInfoCard/ApiProductInfoCard.esm.js +5 -13
  19. package/dist/components/ApiProductInfoCard/ApiProductInfoCard.esm.js.map +1 -1
  20. package/dist/components/ApiProductOpenApiAlert/ApiProductOpenApiAlert.esm.js +7 -10
  21. package/dist/components/ApiProductOpenApiAlert/ApiProductOpenApiAlert.esm.js.map +1 -1
  22. package/dist/components/ApprovalQueueTable/ApprovalQueueTable.esm.js +34 -66
  23. package/dist/components/ApprovalQueueTable/ApprovalQueueTable.esm.js.map +1 -1
  24. package/dist/components/CreateAPIProductDialog/CreateAPIProductDialog.esm.js +143 -58
  25. package/dist/components/CreateAPIProductDialog/CreateAPIProductDialog.esm.js.map +1 -1
  26. package/dist/components/EditAPIKeyDialog/EditAPIKeyDialog.esm.js +8 -18
  27. package/dist/components/EditAPIKeyDialog/EditAPIKeyDialog.esm.js.map +1 -1
  28. package/dist/components/EditAPIProductDialog/EditAPIProductDialog.esm.js +52 -30
  29. package/dist/components/EditAPIProductDialog/EditAPIProductDialog.esm.js.map +1 -1
  30. package/dist/components/EntityApiApprovalTab/EntityApiApprovalTab.esm.js +11 -27
  31. package/dist/components/EntityApiApprovalTab/EntityApiApprovalTab.esm.js.map +1 -1
  32. package/dist/components/KuadrantPage/ApiProductsPage.esm.js +71 -55
  33. package/dist/components/KuadrantPage/ApiProductsPage.esm.js.map +1 -1
  34. package/dist/components/MyApiKeysPage/MyApiKeysPage.esm.js +10 -0
  35. package/dist/components/MyApiKeysPage/MyApiKeysPage.esm.js.map +1 -0
  36. package/dist/components/MyApiKeysPage/index.esm.js +2 -0
  37. package/dist/components/MyApiKeysPage/index.esm.js.map +1 -0
  38. package/dist/components/MyApiKeysTable/MyApiKeysTable.esm.js +51 -57
  39. package/dist/components/MyApiKeysTable/MyApiKeysTable.esm.js.map +1 -1
  40. package/dist/components/RequestAccessDialog/RequestAccessDialog.esm.js +10 -25
  41. package/dist/components/RequestAccessDialog/RequestAccessDialog.esm.js.map +1 -1
  42. package/dist/components/SimpleRequestAccessDialog/SimpleRequestAccessDialog.esm.js +206 -0
  43. package/dist/components/SimpleRequestAccessDialog/SimpleRequestAccessDialog.esm.js.map +1 -0
  44. package/dist/index.d.ts +461 -2
  45. package/dist/index.esm.js +3 -1
  46. package/dist/index.esm.js.map +1 -1
  47. package/dist/plugin.esm.js +11 -4
  48. package/dist/plugin.esm.js.map +1 -1
  49. package/dist/utils/styles.esm.js +44 -5
  50. package/dist/utils/styles.esm.js.map +1 -1
  51. package/dist-scalprum/internal.plugin-kuadrant.8bf02d5482a5a3ed6337.js +2 -0
  52. package/dist-scalprum/internal.plugin-kuadrant.8bf02d5482a5a3ed6337.js.map +1 -0
  53. package/dist-scalprum/plugin-manifest.json +3 -3
  54. package/dist-scalprum/static/2118.82433765.chunk.js +2 -0
  55. package/dist-scalprum/static/2118.82433765.chunk.js.map +1 -0
  56. package/dist-scalprum/static/2967.28e7c7f8.chunk.js +2 -0
  57. package/dist-scalprum/static/2967.28e7c7f8.chunk.js.map +1 -0
  58. package/dist-scalprum/static/369.2374941c.chunk.js +2 -0
  59. package/dist-scalprum/static/369.2374941c.chunk.js.map +1 -0
  60. package/dist-scalprum/static/3947.ff1c25cf.chunk.js +2 -0
  61. package/dist-scalprum/static/3947.ff1c25cf.chunk.js.map +1 -0
  62. package/dist-scalprum/static/3976.cf3ec7be.chunk.js +2 -0
  63. package/dist-scalprum/static/3976.cf3ec7be.chunk.js.map +1 -0
  64. package/dist-scalprum/static/4447.222bb58d.chunk.js +2 -0
  65. package/dist-scalprum/static/4447.222bb58d.chunk.js.map +1 -0
  66. package/dist-scalprum/static/5010.4ef96c87.chunk.js +3 -0
  67. package/dist-scalprum/static/5010.4ef96c87.chunk.js.map +1 -0
  68. package/dist-scalprum/static/5203.e92a3353.chunk.js +2 -0
  69. package/dist-scalprum/static/5203.e92a3353.chunk.js.map +1 -0
  70. package/dist-scalprum/static/6371.6ee1f11d.chunk.js +2 -0
  71. package/dist-scalprum/static/6371.6ee1f11d.chunk.js.map +1 -0
  72. package/dist-scalprum/static/6422.969d9b8c.chunk.js +2 -0
  73. package/dist-scalprum/static/6422.969d9b8c.chunk.js.map +1 -0
  74. package/dist-scalprum/static/6800.a7645f4c.chunk.js +2 -0
  75. package/dist-scalprum/static/6800.a7645f4c.chunk.js.map +1 -0
  76. package/dist-scalprum/static/69.1decc5e8.chunk.js +2 -0
  77. package/dist-scalprum/static/69.1decc5e8.chunk.js.map +1 -0
  78. package/dist-scalprum/static/7005.a9f73153.chunk.js +2 -0
  79. package/dist-scalprum/static/7005.a9f73153.chunk.js.map +1 -0
  80. package/dist-scalprum/static/7270.b0e185f1.chunk.js +2 -0
  81. package/dist-scalprum/static/7270.b0e185f1.chunk.js.map +1 -0
  82. package/dist-scalprum/static/7791.5c1eea8a.chunk.js +2 -0
  83. package/dist-scalprum/static/7791.5c1eea8a.chunk.js.map +1 -0
  84. package/dist-scalprum/static/{6763.d6cd937f.chunk.js → 8563.46f1a3e1.chunk.js} +3 -3
  85. package/dist-scalprum/static/8563.46f1a3e1.chunk.js.map +1 -0
  86. package/dist-scalprum/static/8789.84963cbc.chunk.js +2 -0
  87. package/dist-scalprum/static/8789.84963cbc.chunk.js.map +1 -0
  88. package/dist-scalprum/static/8804.63919453.chunk.js +2 -0
  89. package/dist-scalprum/static/8804.63919453.chunk.js.map +1 -0
  90. package/dist-scalprum/static/9051.db875198.chunk.js +2 -0
  91. package/dist-scalprum/static/9051.db875198.chunk.js.map +1 -0
  92. package/dist-scalprum/static/{2946.a35243f1.chunk.js → 9370.2e9fe34b.chunk.js} +3 -3
  93. package/dist-scalprum/static/9370.2e9fe34b.chunk.js.map +1 -0
  94. package/dist-scalprum/static/9838.5df9b1de.chunk.js +2 -0
  95. package/dist-scalprum/static/9838.5df9b1de.chunk.js.map +1 -0
  96. package/dist-scalprum/static/exposed-PluginRoot.8a8dd91f.chunk.js +2 -0
  97. package/dist-scalprum/static/exposed-PluginRoot.8a8dd91f.chunk.js.map +1 -0
  98. package/package.json +3 -1
  99. package/dist/components/ApiKeysPage/ApiKeysPage.esm.js +0 -43
  100. package/dist/components/ApiKeysPage/ApiKeysPage.esm.js.map +0 -1
  101. package/dist/components/ApiKeysPage/index.esm.js +0 -2
  102. package/dist-scalprum/internal.plugin-kuadrant.114cbbe1d3ddb939d776.js +0 -2
  103. package/dist-scalprum/internal.plugin-kuadrant.114cbbe1d3ddb939d776.js.map +0 -1
  104. package/dist-scalprum/static/2821.0829f14d.chunk.js +0 -2
  105. package/dist-scalprum/static/2821.0829f14d.chunk.js.map +0 -1
  106. package/dist-scalprum/static/2946.a35243f1.chunk.js.map +0 -1
  107. package/dist-scalprum/static/2967.65c51af8.chunk.js +0 -2
  108. package/dist-scalprum/static/2967.65c51af8.chunk.js.map +0 -1
  109. package/dist-scalprum/static/3650.ee76eba9.chunk.js +0 -2
  110. package/dist-scalprum/static/3650.ee76eba9.chunk.js.map +0 -1
  111. package/dist-scalprum/static/3947.7458971d.chunk.js +0 -2
  112. package/dist-scalprum/static/3947.7458971d.chunk.js.map +0 -1
  113. package/dist-scalprum/static/3984.647ef00c.chunk.js +0 -2
  114. package/dist-scalprum/static/3984.647ef00c.chunk.js.map +0 -1
  115. package/dist-scalprum/static/4651.c85cecc4.chunk.js +0 -2
  116. package/dist-scalprum/static/4651.c85cecc4.chunk.js.map +0 -1
  117. package/dist-scalprum/static/4682.75f17114.chunk.js +0 -2
  118. package/dist-scalprum/static/4682.75f17114.chunk.js.map +0 -1
  119. package/dist-scalprum/static/5010.0cd6c959.chunk.js +0 -3
  120. package/dist-scalprum/static/5010.0cd6c959.chunk.js.map +0 -1
  121. package/dist-scalprum/static/5203.b654e8e0.chunk.js +0 -2
  122. package/dist-scalprum/static/5203.b654e8e0.chunk.js.map +0 -1
  123. package/dist-scalprum/static/5453.ecdee66d.chunk.js +0 -2
  124. package/dist-scalprum/static/5453.ecdee66d.chunk.js.map +0 -1
  125. package/dist-scalprum/static/6371.d45f37cc.chunk.js +0 -2
  126. package/dist-scalprum/static/6371.d45f37cc.chunk.js.map +0 -1
  127. package/dist-scalprum/static/6763.d6cd937f.chunk.js.map +0 -1
  128. package/dist-scalprum/static/6800.20f46859.chunk.js +0 -2
  129. package/dist-scalprum/static/6800.20f46859.chunk.js.map +0 -1
  130. package/dist-scalprum/static/6840.1653e6b0.chunk.js +0 -2
  131. package/dist-scalprum/static/6840.1653e6b0.chunk.js.map +0 -1
  132. package/dist-scalprum/static/7236.f3886d59.chunk.js +0 -2
  133. package/dist-scalprum/static/7236.f3886d59.chunk.js.map +0 -1
  134. package/dist-scalprum/static/7791.ac1ac509.chunk.js +0 -2
  135. package/dist-scalprum/static/7791.ac1ac509.chunk.js.map +0 -1
  136. package/dist-scalprum/static/8172.cbe1f2c4.chunk.js +0 -2
  137. package/dist-scalprum/static/8172.cbe1f2c4.chunk.js.map +0 -1
  138. package/dist-scalprum/static/8799.939d14f9.chunk.js +0 -2
  139. package/dist-scalprum/static/8799.939d14f9.chunk.js.map +0 -1
  140. package/dist-scalprum/static/exposed-PluginRoot.ed95fa78.chunk.js +0 -2
  141. package/dist-scalprum/static/exposed-PluginRoot.ed95fa78.chunk.js.map +0 -1
  142. /package/dist/components/{ApiKeysPage → ApiKeyApprovalPage}/index.esm.js.map +0 -0
  143. /package/dist-scalprum/static/{5010.0cd6c959.chunk.js.LICENSE.txt → 5010.4ef96c87.chunk.js.LICENSE.txt} +0 -0
  144. /package/dist-scalprum/static/{6763.d6cd937f.chunk.js.LICENSE.txt → 8563.46f1a3e1.chunk.js.LICENSE.txt} +0 -0
  145. /package/dist-scalprum/static/{2946.a35243f1.chunk.js.LICENSE.txt → 9370.2e9fe34b.chunk.js.LICENSE.txt} +0 -0
@@ -1 +1 @@
1
- {"version":3,"file":"EditAPIProductDialog.esm.js","sources":["../../../src/components/EditAPIProductDialog/EditAPIProductDialog.tsx"],"sourcesContent":["import React, { useState, useEffect } from 'react';\nimport {\n Dialog,\n DialogTitle,\n DialogContent,\n DialogActions,\n Button,\n TextField,\n Box,\n Typography,\n Chip,\n Grid,\n CircularProgress,\n makeStyles,\n FormControl,\n RadioGroup,\n FormControlLabel,\n Radio,\n Tooltip,\n IconButton,\n InputAdornment,\n} from '@material-ui/core';\nimport InfoOutlinedIcon from '@material-ui/icons/InfoOutlined';\nimport AddIcon from '@material-ui/icons/Add';\nimport { useApi, configApiRef, fetchApiRef } from '@backstage/core-plugin-api';\nimport { Alert } from '@material-ui/lab';\nimport { Progress } from '@backstage/core-components';\nimport { PlanPolicyDetails } from '../PlanPolicyDetailsCard';\nimport { validateURL } from '../../utils/validation';\nimport { handleFetchError } from \"../../utils/errors\";\n\nconst useStyles = makeStyles((theme) => ({\n asterisk: {\n color: '#f44336',\n },\n sectionHeader: {\n display: 'flex',\n alignItems: 'center',\n gap: theme.spacing(0.5),\n marginTop: theme.spacing(2),\n marginBottom: theme.spacing(1),\n },\n infoIcon: {\n fontSize: 18,\n color: theme.palette.text.secondary,\n },\n tagChip: {\n marginRight: theme.spacing(0.5),\n marginBottom: theme.spacing(0.5),\n },\n}));\n\ninterface EditAPIProductDialogProps {\n open: boolean;\n onClose: () => void;\n onSuccess: () => void;\n namespace: string;\n name: string;\n}\n\nexport const EditAPIProductDialog = ({ open, onClose, onSuccess, namespace, name }: EditAPIProductDialogProps) => {\n const classes = useStyles();\n const config = useApi(configApiRef);\n const fetchApi = useApi(fetchApiRef);\n const backendUrl = config.getString('backend.baseUrl');\n const [loading, setLoading] = useState(false);\n const [displayName, setDisplayName] = useState('');\n const [description, setDescription] = useState('');\n const [version, setVersion] = useState('v1');\n const [publishStatus, setPublishStatus] = useState<'Draft' | 'Published'>('Draft');\n const [approvalMode, setApprovalMode] = useState<'automatic' | 'manual'>('manual');\n const [tags, setTags] = useState<string[]>([]);\n const [targetRef, setTargetRef] = useState<any>(null);\n const [tagInput, setTagInput] = useState('');\n const [contactEmail, setContactEmail] = useState('');\n const [contactTeam, setContactTeam] = useState('');\n const [docsURL, setDocsURL] = useState('');\n const [openAPISpec, setOpenAPISpec] = useState('');\n const [discoveredPlans, setdiscoveredPlans] = useState([]);\n const [error, setError] = useState('');\n const [saving, setSaving] = useState(false);\n const [openAPISpecError, setOpenAPISpecError] = useState<string | null>(null);\n\n // Load APIProduct data when dialog opens\n useEffect(() => {\n if (open && namespace && name) {\n setLoading(true);\n setError('');\n\n fetchApi.fetch(`${backendUrl}/api/kuadrant/apiproducts/${namespace}/${name}`)\n .then(async res => {\n if (!res.ok) {\n const error = await handleFetchError(res);\n throw new Error(`failed to load API product. ${error}`);\n }\n return res.json();\n })\n .then(data => {\n setDisplayName(data.spec.displayName || '');\n setDescription(data.spec.description || '');\n setVersion(data.spec.version || 'v1');\n setPublishStatus(data.spec.publishStatus || 'Draft');\n setApprovalMode(data.spec.approvalMode || 'manual');\n setTags(data.spec.tags || []);\n setTargetRef(data.spec.targetRef || null);\n setContactEmail(data.spec.contact?.email || '');\n setContactTeam(data.spec.contact?.team || '');\n setDocsURL(data.spec.documentation?.docsURL || '');\n setOpenAPISpec(data.spec.documentation?.openAPISpecURL || '');\n setdiscoveredPlans(data.status.discoveredPlans || null);\n setOpenAPISpecError(null);\n setLoading(false);\n })\n .catch(err => {\n setError(err.message || 'Failed to load API product');\n setLoading(false);\n });\n }\n }, [open, namespace, name, backendUrl, fetchApi]);\n\n useEffect(() => {\n if (open) {\n setOpenAPISpecError(null);\n }\n }, [open]);\n\n const handleOpenAPISpecChange = (value: string) => {\n setOpenAPISpec(value);\n setOpenAPISpecError(validateURL(value));\n };\n\n const handleAddTag = () => {\n if (tagInput.trim() && !tags.includes(tagInput.trim())) {\n setTags([...tags, tagInput.trim()]);\n setTagInput('');\n }\n };\n\n const handleDeleteTag = (tagToDelete: string) => {\n setTags(tags.filter(tag => tag !== tagToDelete));\n };\n\n const handleSave = async () => {\n setError('');\n setSaving(true);\n\n try {\n const patch = {\n spec: {\n displayName,\n description,\n version,\n publishStatus,\n approvalMode,\n tags,\n targetRef,\n ...(contactEmail || contactTeam ? {\n contact: {\n ...(contactEmail && { email: contactEmail }),\n ...(contactTeam && { team: contactTeam }),\n },\n } : {}),\n ...(docsURL || openAPISpec ? {\n documentation: {\n ...(docsURL && { docsURL }),\n ...(openAPISpec && { openAPISpecURL: openAPISpec }),\n },\n } : {}),\n },\n };\n\n const response = await fetchApi.fetch(\n `${backendUrl}/api/kuadrant/apiproducts/${namespace}/${name}`,\n {\n method: 'PATCH',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify(patch),\n }\n );\n\n if (!response.ok) {\n const error = await handleFetchError(response);\n throw new Error(`failed to patch APIProduct. ${error}`);\n }\n\n onSuccess();\n onClose();\n } catch (err) {\n setError(err instanceof Error ? err.message : String(err));\n } finally {\n setSaving(false);\n }\n };\n\n return (\n <Dialog open={open} onClose={onClose} maxWidth=\"md\" fullWidth>\n <DialogTitle>Edit API Product</DialogTitle>\n <DialogContent>\n {error && (\n <Alert severity=\"error\" style={{ marginBottom: 16 }}>\n {error}\n </Alert>\n )}\n {loading ? (\n <Progress />\n ) : (\n <>\n {/* API product info section */}\n <Box className={classes.sectionHeader}>\n <Typography variant=\"subtitle1\"><strong>API product info</strong></Typography>\n </Box>\n <Grid container spacing={2}>\n <Grid item xs={6}>\n <TextField\n fullWidth\n label=\"API product name\"\n value={displayName}\n onChange={e => setDisplayName(e.target.value)}\n placeholder=\"My API\"\n helperText=\"Give a unique name for your API product\"\n margin=\"normal\"\n required\n disabled={saving}\n InputLabelProps={{\n classes: {\n asterisk: classes.asterisk,\n },\n }}\n />\n </Grid>\n <Grid item xs={6}>\n <TextField\n fullWidth\n label=\"Resource name\"\n value={name}\n disabled\n helperText=\"Kubernetes resource name (immutable)\"\n margin=\"normal\"\n />\n </Grid>\n <Grid item xs={6}>\n <TextField\n fullWidth\n label=\"Version\"\n value={version}\n onChange={e => setVersion(e.target.value)}\n placeholder=\"v1\"\n helperText=\"Give a version to your API product\"\n margin=\"normal\"\n disabled={saving}\n />\n </Grid>\n <Grid item xs={6}>\n <TextField\n fullWidth\n label=\"Tag\"\n value={tagInput}\n onChange={e => setTagInput(e.target.value)}\n onKeyPress={e => {\n if (e.key === 'Enter') {\n e.preventDefault();\n handleAddTag();\n }\n }}\n placeholder=\"Add tag\"\n helperText=\"Add a tag to your API product\"\n margin=\"normal\"\n disabled={saving}\n InputProps={{\n endAdornment: tagInput ? (\n <InputAdornment position=\"end\">\n <IconButton size=\"small\" onClick={handleAddTag} disabled={saving}>\n <AddIcon fontSize=\"small\" />\n </IconButton>\n </InputAdornment>\n ) : undefined,\n }}\n />\n </Grid>\n {tags.length > 0 && (\n <Grid item xs={12}>\n <Box display=\"flex\" flexWrap=\"wrap\">\n {tags.map(tag => (\n <Chip\n key={tag}\n label={tag}\n onDelete={saving ? undefined : () => handleDeleteTag(tag)}\n size=\"small\"\n className={classes.tagChip}\n disabled={saving}\n />\n ))}\n </Box>\n </Grid>\n )}\n <Grid item xs={12}>\n <TextField\n fullWidth\n label=\"Description\"\n value={description}\n onChange={e => setDescription(e.target.value)}\n placeholder=\"API description\"\n margin=\"normal\"\n multiline\n rows={2}\n required\n disabled={saving}\n InputLabelProps={{\n classes: {\n asterisk: classes.asterisk,\n },\n }}\n />\n </Grid>\n </Grid>\n\n {/* Associated route section */}\n <Box className={classes.sectionHeader}>\n <Typography variant=\"subtitle1\"><strong>Associated route</strong></Typography>\n <Tooltip title=\"The HTTPRoute this API product is associated with\">\n <InfoOutlinedIcon className={classes.infoIcon} />\n </Tooltip>\n </Box>\n <Grid container spacing={2}>\n <Grid item xs={12}>\n <TextField\n fullWidth\n label=\"OpenAPI Spec URL\"\n value={openAPISpec}\n onChange={e => handleOpenAPISpecChange(e.target.value)}\n placeholder=\"https://api.example.com/openapi.json\"\n helperText={openAPISpecError || \"Enter the full path to your API spec file\"}\n error={!!openAPISpecError}\n margin=\"normal\"\n disabled={saving}\n />\n </Grid>\n <Grid item xs={12}>\n <TextField\n fullWidth\n label=\"Documentation URL\"\n value={docsURL}\n onChange={e => setDocsURL(e.target.value)}\n placeholder=\"https://docs.example.com/api\"\n helperText=\"Link to external documentation for this API\"\n margin=\"normal\"\n disabled={saving}\n />\n </Grid>\n {targetRef && (\n <Grid item xs={12}>\n <TextField\n fullWidth\n label=\"HTTPRoute\"\n value={`${targetRef.namespace || namespace}/${targetRef.name}`}\n disabled\n helperText=\"Target HTTPRoute (immutable)\"\n margin=\"normal\"\n />\n </Grid>\n )}\n </Grid>\n\n {/* HTTPRoute policies section */}\n {targetRef && (\n <>\n <Box className={classes.sectionHeader}>\n <Typography variant=\"subtitle1\"><strong>HTTPRoute policies</strong></Typography>\n <Tooltip title=\"Shows the associated policies and rate limit tiers for the HTTPRoute\">\n <InfoOutlinedIcon className={classes.infoIcon} />\n </Tooltip>\n </Box>\n <PlanPolicyDetails\n discoveredPlans={discoveredPlans}\n alertSeverity=\"info\"\n alertMessage=\"No PlanPolicy found for this HTTPRoute.\"\n includeTopMargin={false}\n />\n </>\n )}\n\n {/* API Key approval section */}\n <Box className={classes.sectionHeader}>\n <Typography variant=\"subtitle1\"><strong>API Key approval</strong></Typography>\n <Tooltip title=\"Choose how API key requests are handled for this product\">\n <InfoOutlinedIcon className={classes.infoIcon} />\n </Tooltip>\n </Box>\n <FormControl component=\"fieldset\" disabled={saving}>\n <RadioGroup\n row\n value={approvalMode}\n onChange={e => setApprovalMode(e.target.value as 'automatic' | 'manual')}\n >\n <FormControlLabel\n value=\"manual\"\n control={<Radio color=\"primary\" />}\n label={\n <Box>\n <Typography variant=\"body2\">Need manual approval</Typography>\n <Typography variant=\"caption\" color=\"textSecondary\">\n Requires approval for requesting this API\n </Typography>\n </Box>\n }\n />\n <FormControlLabel\n value=\"automatic\"\n control={<Radio color=\"primary\" />}\n label={\n <Box>\n <Typography variant=\"body2\">Automatic</Typography>\n <Typography variant=\"caption\" color=\"textSecondary\">\n Keys are created without need to be approved\n </Typography>\n </Box>\n }\n />\n </RadioGroup>\n </FormControl>\n </>\n )}\n </DialogContent>\n <DialogActions>\n <Button onClick={onClose} disabled={saving}>Cancel</Button>\n <Button\n onClick={handleSave}\n color=\"primary\"\n variant=\"contained\"\n disabled={saving || loading || !displayName || !description || !!openAPISpecError}\n startIcon={saving ? <CircularProgress size={16} color=\"inherit\" /> : undefined}\n >\n {saving ? 'Saving...' : 'Save'}\n </Button>\n </DialogActions>\n </Dialog>\n );\n};\n"],"names":["error"],"mappings":"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"}
1
+ {"version":3,"file":"EditAPIProductDialog.esm.js","sources":["../../../src/components/EditAPIProductDialog/EditAPIProductDialog.tsx"],"sourcesContent":["import React, { useState, useEffect } from 'react';\nimport {\n Dialog,\n DialogTitle,\n DialogContent,\n DialogActions,\n Button,\n TextField,\n Box,\n Typography,\n Chip,\n Grid,\n MenuItem,\n CircularProgress,\n makeStyles,\n FormControl,\n RadioGroup,\n FormControlLabel,\n Radio,\n Tooltip,\n IconButton,\n InputAdornment,\n} from '@material-ui/core';\nimport InfoOutlinedIcon from '@material-ui/icons/InfoOutlined';\nimport AddIcon from '@material-ui/icons/Add';\nimport { useApi } from '@backstage/core-plugin-api';\nimport { kuadrantApiRef } from '../../api';\nimport { Alert } from '@material-ui/lab';\nimport { Progress } from '@backstage/core-components';\nimport { PlanPolicyDetails } from '../PlanPolicyDetailsCard';\nimport { validateURL } from '../../utils/validation';\nimport {APIProduct, Plan} from \"../../types/api-management.ts\";\nimport { Lifecycle } from '../../types/api-management';\n\nconst useStyles = makeStyles((theme) => ({\n asterisk: {\n color: '#f44336',\n },\n sectionHeader: {\n display: 'flex',\n alignItems: 'center',\n gap: theme.spacing(0.5),\n marginTop: theme.spacing(2),\n marginBottom: theme.spacing(1),\n },\n infoIcon: {\n fontSize: 18,\n color: theme.palette.text.secondary,\n },\n tagChip: {\n marginRight: theme.spacing(0.5),\n marginBottom: theme.spacing(0.5),\n },\n}));\n\ninterface EditAPIProductDialogProps {\n open: boolean;\n onClose: () => void;\n onSuccess: () => void;\n namespace: string;\n name: string;\n}\n\nexport const EditAPIProductDialog = ({ open, onClose, onSuccess, namespace, name }: EditAPIProductDialogProps) => {\n const classes = useStyles();\n const kuadrantApi = useApi(kuadrantApiRef);\n const [loading, setLoading] = useState(false);\n const [displayName, setDisplayName] = useState('');\n const [description, setDescription] = useState('');\n const [version, setVersion] = useState('v1');\n const [publishStatus, setPublishStatus] = useState<'Draft' | 'Published'>('Draft');\n const [lifecycle, setLifecycle] = useState<Lifecycle>('production');\n const [approvalMode, setApprovalMode] = useState<'automatic' | 'manual'>('manual');\n const [tags, setTags] = useState<string[]>([]);\n const [targetRef, setTargetRef] = useState<any>(null);\n const [tagInput, setTagInput] = useState('');\n const [contactEmail, setContactEmail] = useState('');\n const [contactTeam, setContactTeam] = useState('');\n const [docsURL, setDocsURL] = useState('');\n const [openAPISpec, setOpenAPISpec] = useState('');\n const [discoveredPlans, setdiscoveredPlans] = useState<Plan[]>([]);\n const [error, setError] = useState('');\n const [saving, setSaving] = useState(false);\n const [openAPISpecError, setOpenAPISpecError] = useState<string | null>(null);\n\n // Load APIProduct data when dialog opens\n useEffect(() => {\n if (open && namespace && name) {\n setLoading(true);\n setError('');\n kuadrantApi.getApiProduct(namespace, name)\n .then(data => {\n setDisplayName(data.spec.displayName || '');\n setDescription(data.spec.description || '');\n setVersion(data.spec.version || 'v1');\n setPublishStatus(data.spec.publishStatus || 'Draft');\n setLifecycle(data.metadata.labels?.lifecycle as Lifecycle || 'production' as Lifecycle);\n setApprovalMode(data.spec.approvalMode || 'manual');\n setTags(data.spec.tags || []);\n setTargetRef(data.spec.targetRef || null);\n setContactEmail(data.spec.contact?.email || '');\n setContactTeam(data.spec.contact?.team || '');\n setDocsURL(data.spec.documentation?.docsURL || '');\n setOpenAPISpec(data.spec.documentation?.openAPISpecURL || '');\n setdiscoveredPlans(data.status?.discoveredPlans || []);\n setOpenAPISpecError(null);\n setLoading(false);\n })\n .catch(err => {\n setError(err.message || 'Failed to load API product');\n setLoading(false);\n });\n }\n }, [open, namespace, name, kuadrantApi]);\n\n useEffect(() => {\n if (open) {\n setOpenAPISpecError(null);\n }\n }, [open]);\n\n const handleOpenAPISpecChange = (value: string) => {\n setOpenAPISpec(value);\n setOpenAPISpecError(validateURL(value));\n };\n\n const handleAddTag = () => {\n if (tagInput.trim() && !tags.includes(tagInput.trim())) {\n setTags([...tags, tagInput.trim()]);\n setTagInput('');\n }\n };\n\n const handleDeleteTag = (tagToDelete: string) => {\n setTags(tags.filter(tag => tag !== tagToDelete));\n };\n\n const handleSave = async () => {\n setError('');\n setSaving(true);\n\n // validate retired APIs cannot be published\n if (lifecycle === 'retired' && publishStatus === 'Published') {\n setError('Cannot publish a retired API product. Please set publish status to Draft.');\n setSaving(false);\n return;\n }\n\n try {\n const patch: Partial<APIProduct> = {\n // @ts-ignore We are applying a partial obj, not full\n metadata: {\n labels: {\n lifecycle,\n },\n },\n spec: {\n displayName,\n description,\n version,\n publishStatus,\n approvalMode,\n tags,\n targetRef,\n ...(contactEmail || contactTeam ? {\n contact: {\n ...(contactEmail && { email: contactEmail }),\n ...(contactTeam && { team: contactTeam }),\n },\n } : {}),\n ...(docsURL || openAPISpec ? {\n documentation: {\n ...(docsURL && { docsURL }),\n ...(openAPISpec && { openAPISpecURL: openAPISpec }),\n },\n } : {}),\n },\n };\n\n await kuadrantApi.updateApiProduct(namespace, name, patch);\n onSuccess();\n onClose();\n } catch (err) {\n setError(err instanceof Error ? err.message : String(err));\n } finally {\n setSaving(false);\n }\n };\n\n return (\n <Dialog open={open} onClose={onClose} maxWidth=\"md\" fullWidth>\n <DialogTitle>Edit API Product</DialogTitle>\n <DialogContent>\n {error && (\n <Alert severity=\"error\" style={{ marginBottom: 16 }}>\n {error}\n </Alert>\n )}\n {loading ? (\n <Progress />\n ) : (\n <>\n {/* API product info section */}\n <Box className={classes.sectionHeader}>\n <Typography variant=\"subtitle1\"><strong>API product info</strong></Typography>\n </Box>\n <Grid container spacing={2}>\n <Grid item xs={6}>\n <TextField\n fullWidth\n label=\"API product name\"\n value={displayName}\n onChange={e => setDisplayName(e.target.value)}\n placeholder=\"My API\"\n helperText=\"Give a unique name for your API product\"\n margin=\"normal\"\n required\n disabled={saving}\n InputLabelProps={{\n classes: {\n asterisk: classes.asterisk,\n },\n }}\n />\n </Grid>\n <Grid item xs={6}>\n <TextField\n fullWidth\n label=\"Resource name\"\n value={name}\n disabled\n helperText=\"Kubernetes resource name (immutable)\"\n margin=\"normal\"\n />\n </Grid>\n <Grid item xs={6}>\n <TextField\n fullWidth\n label=\"Version\"\n value={version}\n onChange={e => setVersion(e.target.value)}\n placeholder=\"v1\"\n helperText=\"Give a version to your API product\"\n margin=\"normal\"\n disabled={saving}\n />\n </Grid>\n <Grid item xs={6}>\n <TextField\n fullWidth\n label=\"Tag\"\n value={tagInput}\n onChange={e => setTagInput(e.target.value)}\n onKeyPress={e => {\n if (e.key === 'Enter') {\n e.preventDefault();\n handleAddTag();\n }\n }}\n placeholder=\"Add tag\"\n helperText=\"Add a tag to your API product\"\n margin=\"normal\"\n disabled={saving}\n InputProps={{\n endAdornment: tagInput ? (\n <InputAdornment position=\"end\">\n <IconButton size=\"small\" onClick={handleAddTag} disabled={saving}>\n <AddIcon fontSize=\"small\" />\n </IconButton>\n </InputAdornment>\n ) : undefined,\n }}\n />\n </Grid>\n {tags.length > 0 && (\n <Grid item xs={12}>\n <Box display=\"flex\" flexWrap=\"wrap\">\n {tags.map(tag => (\n <Chip\n key={tag}\n label={tag}\n onDelete={saving ? undefined : () => handleDeleteTag(tag)}\n size=\"small\"\n className={classes.tagChip}\n disabled={saving}\n />\n ))}\n </Box>\n </Grid>\n )}\n <Grid item xs={12}>\n <TextField\n fullWidth\n label=\"Description\"\n value={description}\n onChange={e => setDescription(e.target.value)}\n placeholder=\"API description\"\n margin=\"normal\"\n multiline\n rows={2}\n required\n disabled={saving}\n InputLabelProps={{\n classes: {\n asterisk: classes.asterisk,\n },\n }}\n />\n </Grid>\n </Grid>\n\n {/* Associated route section */}\n <Box className={classes.sectionHeader}>\n <Typography variant=\"subtitle1\"><strong>Associated route</strong></Typography>\n <Tooltip title=\"The HTTPRoute this API product is associated with\">\n <InfoOutlinedIcon className={classes.infoIcon} />\n </Tooltip>\n </Box>\n <Grid container spacing={2}>\n <Grid item xs={12}>\n <TextField\n fullWidth\n label=\"OpenAPI Spec URL\"\n value={openAPISpec}\n onChange={e => handleOpenAPISpecChange(e.target.value)}\n placeholder=\"https://api.example.com/openapi.json\"\n helperText={openAPISpecError || \"Enter the full path to your API spec file\"}\n error={!!openAPISpecError}\n margin=\"normal\"\n disabled={saving}\n />\n </Grid>\n <Grid item xs={12}>\n <TextField\n fullWidth\n label=\"Documentation URL\"\n value={docsURL}\n onChange={e => setDocsURL(e.target.value)}\n placeholder=\"https://docs.example.com/api\"\n helperText=\"Link to external documentation for this API\"\n margin=\"normal\"\n disabled={saving}\n />\n </Grid>\n {targetRef && (\n <Grid item xs={12}>\n <TextField\n fullWidth\n label=\"HTTPRoute\"\n value={`${targetRef.namespace || namespace}/${targetRef.name}`}\n disabled\n helperText=\"Target HTTPRoute (immutable)\"\n margin=\"normal\"\n />\n </Grid>\n )}\n </Grid>\n\n {/* HTTPRoute policies section */}\n {targetRef && (\n <>\n <Box className={classes.sectionHeader}>\n <Typography variant=\"subtitle1\"><strong>HTTPRoute policies</strong></Typography>\n <Tooltip title=\"Shows the associated policies and rate limit tiers for the HTTPRoute\">\n <InfoOutlinedIcon className={classes.infoIcon} />\n </Tooltip>\n </Box>\n <PlanPolicyDetails\n discoveredPlans={discoveredPlans}\n alertSeverity=\"info\"\n alertMessage=\"No PlanPolicy found for this HTTPRoute.\"\n includeTopMargin={false}\n />\n </>\n )}\n\n {/* Lifecycle and Visibility section */}\n <Box className={classes.sectionHeader}>\n <Typography variant=\"subtitle1\"><strong>Lifecycle and Visibility</strong></Typography>\n <Tooltip title=\"Control the lifecycle state and catalog visibility of this API product\">\n <InfoOutlinedIcon className={classes.infoIcon} />\n </Tooltip>\n </Box>\n <Grid container spacing={2}>\n <Grid item xs={6}>\n <TextField\n fullWidth\n select\n label=\"Lifecycle\"\n value={lifecycle}\n onChange={e => setLifecycle(e.target.value as Lifecycle)}\n margin=\"normal\"\n helperText=\"API lifecycle state\"\n disabled={saving}\n >\n <MenuItem value=\"experimental\">Experimental</MenuItem>\n <MenuItem value=\"production\">Production</MenuItem>\n <MenuItem value=\"deprecated\">Deprecated</MenuItem>\n <MenuItem value=\"retired\">Retired</MenuItem>\n </TextField>\n </Grid>\n <Grid item xs={6}>\n <TextField\n fullWidth\n select\n label=\"Publish Status\"\n value={publishStatus}\n onChange={e => setPublishStatus(e.target.value as 'Draft' | 'Published')}\n margin=\"normal\"\n helperText=\"Controls catalog visibility\"\n disabled={saving}\n >\n <MenuItem value=\"Draft\">Draft</MenuItem>\n <MenuItem value=\"Published\">Published</MenuItem>\n </TextField>\n </Grid>\n </Grid>\n\n {/* API Key approval section */}\n <Box className={classes.sectionHeader}>\n <Typography variant=\"subtitle1\"><strong>API Key approval</strong></Typography>\n <Tooltip title=\"Choose how API key requests are handled for this product\">\n <InfoOutlinedIcon className={classes.infoIcon} />\n </Tooltip>\n </Box>\n <FormControl component=\"fieldset\" disabled={saving}>\n <RadioGroup\n row\n value={approvalMode}\n onChange={e => setApprovalMode(e.target.value as 'automatic' | 'manual')}\n >\n <FormControlLabel\n value=\"manual\"\n control={<Radio color=\"primary\" />}\n label={\n <Box>\n <Typography variant=\"body2\">Need manual approval</Typography>\n <Typography variant=\"caption\" color=\"textSecondary\">\n Requires approval for requesting this API\n </Typography>\n </Box>\n }\n />\n <FormControlLabel\n value=\"automatic\"\n control={<Radio color=\"primary\" />}\n label={\n <Box>\n <Typography variant=\"body2\">Automatic</Typography>\n <Typography variant=\"caption\" color=\"textSecondary\">\n Keys are created without need to be approved\n </Typography>\n </Box>\n }\n />\n </RadioGroup>\n </FormControl>\n </>\n )}\n </DialogContent>\n <DialogActions>\n <Button onClick={onClose} disabled={saving}>Cancel</Button>\n <Button\n onClick={handleSave}\n color=\"primary\"\n variant=\"contained\"\n disabled={saving || loading || !displayName || !description || !!openAPISpecError}\n startIcon={saving ? <CircularProgress size={16} color=\"inherit\" /> : undefined}\n >\n {saving ? 'Saving...' : 'Save'}\n </Button>\n </DialogActions>\n </Dialog>\n );\n};\n"],"names":[],"mappings":"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"}
@@ -1,6 +1,7 @@
1
1
  import React, { useState } from 'react';
2
2
  import { useEntity } from '@backstage/plugin-catalog-react';
3
- import { useApi, configApiRef, fetchApiRef, identityApiRef, alertApiRef } from '@backstage/core-plugin-api';
3
+ import { useApi, identityApiRef, alertApiRef } from '@backstage/core-plugin-api';
4
+ import { kuadrantApiRef } from '../../api.esm.js';
4
5
  import { useAsync } from 'react-use';
5
6
  import { Progress, ResponseErrorPanel, Table } from '@backstage/core-components';
6
7
  import { kuadrantApiKeyApprovePermission } from '../../permissions.esm.js';
@@ -8,8 +9,7 @@ import { useKuadrantPermission } from '../../utils/permissions.esm.js';
8
9
  import { makeStyles, Box, Typography, Dialog, DialogTitle, DialogContent, TextField, DialogActions, Button, CircularProgress, Chip, Tooltip, IconButton } from '@material-ui/core';
9
10
  import CheckCircleIcon from '@material-ui/icons/CheckCircle';
10
11
  import CancelIcon from '@material-ui/icons/Cancel';
11
- import { getStatusChipStyle } from '../../utils/styles.esm.js';
12
- import { handleFetchError } from '../../utils/errors.esm.js';
12
+ import { getApprovalQueueStatusChipStyle } from '../../utils/styles.esm.js';
13
13
 
14
14
  const useStyles = makeStyles((theme) => ({
15
15
  useCasePanel: {
@@ -83,11 +83,9 @@ const ApprovalDialog = ({
83
83
  };
84
84
  const EntityApiApprovalTab = () => {
85
85
  const { entity } = useEntity();
86
- const config = useApi(configApiRef);
87
- const fetchApi = useApi(fetchApiRef);
86
+ const kuadrantApi = useApi(kuadrantApiRef);
88
87
  const identityApi = useApi(identityApiRef);
89
88
  const alertApi = useApi(alertApiRef);
90
- const backendUrl = config.getString("backend.baseUrl");
91
89
  const apiProductName = entity.metadata.annotations?.["kuadrant.io/apiproduct"] || entity.metadata.name;
92
90
  const namespace = entity.metadata.annotations?.["kuadrant.io/namespace"] || "default";
93
91
  const [refresh, setRefresh] = useState(0);
@@ -105,20 +103,13 @@ const EntityApiApprovalTab = () => {
105
103
  const { value, loading, error } = useAsync(async () => {
106
104
  const identity = await identityApi.getBackstageIdentity();
107
105
  const reviewedBy = identity.userEntityRef;
108
- const response = await fetchApi.fetch(
109
- `${backendUrl}/api/kuadrant/requests`
110
- );
111
- if (!response.ok) {
112
- const err = await handleFetchError(response);
113
- throw new Error(`Failed to fetch requests. ${err}`);
114
- }
115
- const data = await response.json();
106
+ const data = await kuadrantApi.getRequests();
116
107
  const allRequests = data.items || [];
117
108
  const filtered = allRequests.filter(
118
109
  (r) => r.spec.apiProductRef?.name === apiProductName && r.metadata.namespace === namespace
119
110
  );
120
111
  return { requests: filtered, reviewedBy };
121
- }, [backendUrl, fetchApi, identityApi, apiProductName, namespace, refresh]);
112
+ }, [kuadrantApi, identityApi, apiProductName, namespace, refresh]);
122
113
  const handleApprove = (request) => {
123
114
  setDialogState({
124
115
  open: true,
@@ -138,17 +129,10 @@ const EntityApiApprovalTab = () => {
138
129
  const handleConfirm = async () => {
139
130
  if (!dialogState.request || !value) return;
140
131
  setDialogState((prev) => ({ ...prev, processing: true }));
141
- const endpoint = dialogState.action === "approve" ? `${backendUrl}/api/kuadrant/requests/${dialogState.request.metadata.namespace}/${dialogState.request.metadata.name}/approve` : `${backendUrl}/api/kuadrant/requests/${dialogState.request.metadata.namespace}/${dialogState.request.metadata.name}/reject`;
132
+ const isApprove = dialogState.action === "approve";
133
+ const requestFn = isApprove ? (ns, n, r) => kuadrantApi.approveRequest(ns, n, r) : (ns, n, r) => kuadrantApi.rejectRequest(ns, n, r);
142
134
  try {
143
- const response = await fetchApi.fetch(endpoint, {
144
- method: "POST",
145
- headers: { "Content-Type": "application/json" },
146
- body: JSON.stringify({ reviewedBy: value.reviewedBy })
147
- });
148
- if (!response.ok) {
149
- const err = await handleFetchError(response);
150
- throw new Error(err);
151
- }
135
+ await requestFn(dialogState.request.metadata.namespace, dialogState.request.metadata.name, value.reviewedBy);
152
136
  setDialogState({
153
137
  open: false,
154
138
  request: null,
@@ -157,7 +141,7 @@ const EntityApiApprovalTab = () => {
157
141
  });
158
142
  setRefresh((r) => r + 1);
159
143
  alertApi.post({
160
- message: `API key ${dialogState.action === "approve" ? "approved" : "rejected"}`,
144
+ message: `API key ${isApprove ? "approved" : "rejected"}`,
161
145
  severity: "success",
162
146
  display: "transient"
163
147
  });
@@ -206,7 +190,7 @@ const EntityApiApprovalTab = () => {
206
190
  render: (row) => {
207
191
  const phase = row.status?.phase || "Pending";
208
192
  const label = phase === "Approved" ? "Active" : phase;
209
- return /* @__PURE__ */ React.createElement(Chip, { label, size: "small", style: getStatusChipStyle(phase) });
193
+ return /* @__PURE__ */ React.createElement(Chip, { label, size: "small", style: getApprovalQueueStatusChipStyle(phase) });
210
194
  }
211
195
  },
212
196
  {
@@ -1 +1 @@
1
- {"version":3,"file":"EntityApiApprovalTab.esm.js","sources":["../../../src/components/EntityApiApprovalTab/EntityApiApprovalTab.tsx"],"sourcesContent":["import React, { useState } from \"react\";\nimport { useEntity } from \"@backstage/plugin-catalog-react\";\nimport {\n useApi,\n configApiRef,\n fetchApiRef,\n identityApiRef,\n alertApiRef,\n} from \"@backstage/core-plugin-api\";\nimport { useAsync } from \"react-use\";\nimport {\n Table,\n TableColumn,\n Progress,\n ResponseErrorPanel,\n} from \"@backstage/core-components\";\nimport { kuadrantApiKeyApprovePermission } from \"../../permissions\";\nimport { useKuadrantPermission } from \"../../utils/permissions\";\nimport {\n Box,\n Typography,\n Chip,\n IconButton,\n Tooltip,\n Button,\n Dialog,\n DialogTitle,\n DialogContent,\n DialogActions,\n TextField,\n CircularProgress,\n makeStyles,\n} from \"@material-ui/core\";\nimport CheckCircleIcon from \"@material-ui/icons/CheckCircle\";\nimport CancelIcon from \"@material-ui/icons/Cancel\";\nimport { APIKey } from \"../../types/api-management\";\nimport { getStatusChipStyle } from \"../../utils/styles\";\nimport {handleFetchError} from \"../../utils/errors.ts\";\n\nconst useStyles = makeStyles((theme) => ({\n useCasePanel: {\n padding: theme.spacing(2),\n backgroundColor: theme.palette.background.default,\n },\n useCaseLabel: {\n fontWeight: 600,\n marginBottom: theme.spacing(1),\n color: theme.palette.text.secondary,\n textTransform: \"uppercase\",\n fontSize: \"0.75rem\",\n },\n}));\n\ninterface ExpandedRowProps {\n request: APIKey;\n}\n\nconst ExpandedRowContent = ({ request }: ExpandedRowProps) => {\n const classes = useStyles();\n\n return (\n <Box className={classes.useCasePanel} onClick={(e) => e.stopPropagation()}>\n <Typography className={classes.useCaseLabel}>Use Case</Typography>\n <Typography variant=\"body2\">\n {request.spec.useCase || \"No use case provided\"}\n </Typography>\n </Box>\n );\n};\n\ninterface ApprovalDialogProps {\n open: boolean;\n request: APIKey | null;\n action: \"approve\" | \"reject\";\n processing: boolean;\n onClose: () => void;\n onConfirm: (confirmText: string) => void;\n}\n\nconst ApprovalDialog = ({\n open,\n request,\n action,\n processing,\n onClose,\n onConfirm,\n}: ApprovalDialogProps) => {\n const [confirmText, setConfirmText] = useState(\"\");\n\n const handleClose = () => {\n setConfirmText(\"\");\n onClose();\n };\n\n const handleConfirm = () => {\n onConfirm(confirmText);\n setConfirmText(\"\");\n };\n\n const isReject = action === \"reject\";\n const expectedText = request?.metadata.name || \"\";\n const isConfirmValid = confirmText === expectedText;\n\n return (\n <Dialog\n open={open}\n onClose={processing ? undefined : handleClose}\n maxWidth=\"sm\"\n fullWidth\n >\n <DialogTitle>\n {isReject ? \"Reject API key\" : \"Approve API key\"}\n </DialogTitle>\n <DialogContent>\n {request && (\n <>\n <Typography variant=\"body2\" paragraph>\n <strong>Requester:</strong> {request.spec.requestedBy.userId}\n </Typography>\n <Typography variant=\"body2\" paragraph>\n <strong>Tier:</strong> {request.spec.planTier}\n </Typography>\n {request.spec.useCase && (\n <Typography variant=\"body2\" paragraph>\n <strong>Use Case:</strong> {request.spec.useCase}\n </Typography>\n )}\n {isReject && (\n <Box mt={2} p={2} bgcolor=\"error.light\" borderRadius={1}>\n <Typography variant=\"body2\">\n This action will permanently deny access. The user will need\n to submit a new request.\n </Typography>\n </Box>\n )}\n <Box mt={2}>\n <TextField\n fullWidth\n label={`Type \"${expectedText}\" to confirm`}\n value={confirmText}\n onChange={(e) => setConfirmText(e.target.value)}\n disabled={processing}\n autoFocus\n />\n </Box>\n </>\n )}\n </DialogContent>\n <DialogActions>\n <Button onClick={handleClose} disabled={processing}>\n Cancel\n </Button>\n <Button\n onClick={handleConfirm}\n color={isReject ? \"secondary\" : \"primary\"}\n variant=\"contained\"\n disabled={!isConfirmValid || processing}\n startIcon={\n processing ? (\n <CircularProgress size={16} color=\"inherit\" />\n ) : undefined\n }\n >\n {processing\n ? isReject\n ? \"Rejecting...\"\n : \"Approving...\"\n : isReject\n ? \"Reject\"\n : \"Approve\"}\n </Button>\n </DialogActions>\n </Dialog>\n );\n};\n\nexport const EntityApiApprovalTab = () => {\n const { entity } = useEntity();\n const config = useApi(configApiRef);\n const fetchApi = useApi(fetchApiRef);\n const identityApi = useApi(identityApiRef);\n const alertApi = useApi(alertApiRef);\n const backendUrl = config.getString(\"backend.baseUrl\");\n\n const apiProductName =\n entity.metadata.annotations?.[\"kuadrant.io/apiproduct\"] ||\n entity.metadata.name;\n const namespace =\n entity.metadata.annotations?.[\"kuadrant.io/namespace\"] || \"default\";\n\n const [refresh, setRefresh] = useState(0);\n const [dialogState, setDialogState] = useState<{\n open: boolean;\n request: APIKey | null;\n action: \"approve\" | \"reject\";\n processing: boolean;\n }>({\n open: false,\n request: null,\n action: \"approve\",\n processing: false,\n });\n\n const {\n allowed: canApprove,\n loading: permissionLoading,\n error: permissionError,\n } = useKuadrantPermission(kuadrantApiKeyApprovePermission);\n\n const { value, loading, error } = useAsync(async () => {\n const identity = await identityApi.getBackstageIdentity();\n const reviewedBy = identity.userEntityRef;\n\n const response = await fetchApi.fetch(\n `${backendUrl}/api/kuadrant/requests`,\n );\n if (!response.ok) {\n const err = await handleFetchError(response);\n throw new Error(`Failed to fetch requests. ${err}`);\n }\n\n const data = await response.json();\n const allRequests: APIKey[] = data.items || [];\n\n // filter to this API product only\n const filtered = allRequests.filter(\n (r) =>\n r.spec.apiProductRef?.name === apiProductName &&\n r.metadata.namespace === namespace,\n );\n\n return { requests: filtered, reviewedBy };\n }, [backendUrl, fetchApi, identityApi, apiProductName, namespace, refresh]);\n\n const handleApprove = (request: APIKey) => {\n setDialogState({\n open: true,\n request,\n action: \"approve\",\n processing: false,\n });\n };\n\n const handleReject = (request: APIKey) => {\n setDialogState({\n open: true,\n request,\n action: \"reject\",\n processing: false,\n });\n };\n\n const handleConfirm = async () => {\n if (!dialogState.request || !value) return;\n\n setDialogState((prev) => ({ ...prev, processing: true }));\n\n const endpoint =\n dialogState.action === \"approve\"\n ? `${backendUrl}/api/kuadrant/requests/${dialogState.request.metadata.namespace}/${dialogState.request.metadata.name}/approve`\n : `${backendUrl}/api/kuadrant/requests/${dialogState.request.metadata.namespace}/${dialogState.request.metadata.name}/reject`;\n\n try {\n const response = await fetchApi.fetch(endpoint, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ reviewedBy: value.reviewedBy }),\n });\n\n if (!response.ok) {\n const err = await handleFetchError(response);\n throw new Error(err);\n }\n\n setDialogState({\n open: false,\n request: null,\n action: \"approve\",\n processing: false,\n });\n setRefresh((r) => r + 1);\n alertApi.post({\n message: `API key ${dialogState.action === \"approve\" ? \"approved\" : \"rejected\"}`,\n severity: \"success\",\n display: \"transient\",\n });\n } catch (err) {\n console.error(`Error ${dialogState.action}ing request:`, err);\n setDialogState((prev) => ({ ...prev, processing: false }));\n const errorMessage = err instanceof Error ? err.message : \"unknown error occurred\";\n alertApi.post({\n message: `Failed to ${dialogState.action} APIKey. ${errorMessage}`,\n severity: 'error',\n display: 'transient',\n });\n }\n };\n\n if (loading || permissionLoading) {\n return <Progress />;\n }\n\n if (error) {\n return <ResponseErrorPanel error={error} />;\n }\n\n if (permissionError) {\n return (\n <Box p={2}>\n <Typography color=\"error\">\n Unable to check permissions: {permissionError.message}\n </Typography>\n </Box>\n );\n }\n\n if (!canApprove) {\n return (\n <Box p={3} textAlign=\"center\">\n <Typography variant=\"body1\" color=\"textSecondary\">\n You don't have permission to view the approval queue for this API.\n </Typography>\n </Box>\n );\n }\n\n const requests = value?.requests || [];\n const pendingRequests = requests.filter(\n (r) => !r.status?.phase || r.status.phase === \"Pending\",\n );\n const approvedRequests = requests.filter(\n (r) => r.status?.phase === \"Approved\",\n );\n const rejectedRequests = requests.filter(\n (r) => r.status?.phase === \"Rejected\",\n );\n\n const columns: TableColumn<APIKey>[] = [\n {\n title: \"Requester\",\n field: \"spec.requestedBy.userId\",\n render: (row) => (\n <Typography variant=\"body2\">{row.spec.requestedBy.userId}</Typography>\n ),\n },\n {\n title: \"Status\",\n field: \"status.phase\",\n render: (row) => {\n const phase = row.status?.phase || \"Pending\";\n const label = phase === \"Approved\" ? \"Active\" : phase;\n return (\n <Chip label={label} size=\"small\" style={getStatusChipStyle(phase)} />\n );\n },\n },\n {\n title: \"Tier\",\n field: \"spec.planTier\",\n render: (row) => (\n <Chip label={row.spec.planTier} size=\"small\" variant=\"outlined\" />\n ),\n },\n {\n title: \"Requested\",\n field: \"metadata.creationTimestamp\",\n render: (row) => {\n if (!row.metadata.creationTimestamp)\n return <Typography variant=\"body2\">-</Typography>;\n return (\n <Typography variant=\"body2\">\n {new Date(row.metadata.creationTimestamp).toLocaleDateString()}\n </Typography>\n );\n },\n },\n {\n title: \"Actions\",\n filtering: false,\n render: (row) => {\n const phase = row.status?.phase || \"Pending\";\n if (phase !== \"Pending\") return null;\n return (\n <Box display=\"flex\" style={{ gap: 4 }}>\n <Tooltip title=\"Approve\">\n <IconButton size=\"small\" onClick={() => handleApprove(row)}>\n <CheckCircleIcon color=\"primary\" />\n </IconButton>\n </Tooltip>\n <Tooltip title=\"Reject\">\n <IconButton size=\"small\" onClick={() => handleReject(row)}>\n <CancelIcon color=\"error\" />\n </IconButton>\n </Tooltip>\n </Box>\n );\n },\n },\n ];\n\n const detailPanelConfig = [\n {\n render: (data: any) => {\n const request = data.rowData as APIKey;\n if (!request?.metadata?.name) return <Box />;\n return <ExpandedRowContent request={request} />;\n },\n },\n ];\n\n return (\n <Box p={2}>\n <Box mb={2}>\n <Typography variant=\"body2\" color=\"textSecondary\">\n {pendingRequests.length} pending, {approvedRequests.length} approved,{\" \"}\n {rejectedRequests.length} rejected\n </Typography>\n </Box>\n\n {requests.length === 0 ? (\n <Box p={3} textAlign=\"center\">\n <Typography variant=\"body1\" color=\"textSecondary\">\n No API keys for this API.\n </Typography>\n </Box>\n ) : (\n <Table\n options={{\n paging: requests.length > 10,\n pageSize: 20,\n search: true,\n filtering: false,\n debounceInterval: 300,\n toolbar: true,\n emptyRowsWhenPaging: false,\n }}\n columns={columns}\n data={requests.map((item) => ({ ...item, id: item.metadata.name }))}\n detailPanel={detailPanelConfig}\n />\n )}\n\n <ApprovalDialog\n open={dialogState.open}\n request={dialogState.request}\n action={dialogState.action}\n processing={dialogState.processing}\n onClose={() =>\n setDialogState({\n open: false,\n request: null,\n action: \"approve\",\n processing: false,\n })\n }\n onConfirm={handleConfirm}\n />\n </Box>\n );\n};\n"],"names":[],"mappings":";;;;;;;;;;;;;AAuCA,MAAM,SAAA,GAAY,UAAW,CAAA,CAAC,KAAW,MAAA;AAAA,EACvC,YAAc,EAAA;AAAA,IACZ,OAAA,EAAS,KAAM,CAAA,OAAA,CAAQ,CAAC,CAAA;AAAA,IACxB,eAAA,EAAiB,KAAM,CAAA,OAAA,CAAQ,UAAW,CAAA;AAAA,GAC5C;AAAA,EACA,YAAc,EAAA;AAAA,IACZ,UAAY,EAAA,GAAA;AAAA,IACZ,YAAA,EAAc,KAAM,CAAA,OAAA,CAAQ,CAAC,CAAA;AAAA,IAC7B,KAAA,EAAO,KAAM,CAAA,OAAA,CAAQ,IAAK,CAAA,SAAA;AAAA,IAC1B,aAAe,EAAA,WAAA;AAAA,IACf,QAAU,EAAA;AAAA;AAEd,CAAE,CAAA,CAAA;AAMF,MAAM,kBAAqB,GAAA,CAAC,EAAE,OAAA,EAAgC,KAAA;AAC5D,EAAA,MAAM,UAAU,SAAU,EAAA;AAE1B,EACE,uBAAA,KAAA,CAAA,aAAA,CAAC,GAAI,EAAA,EAAA,SAAA,EAAW,OAAQ,CAAA,YAAA,EAAc,OAAS,EAAA,CAAC,CAAM,KAAA,CAAA,CAAE,eAAgB,EAAA,EAAA,kBACrE,KAAA,CAAA,aAAA,CAAA,UAAA,EAAA,EAAW,WAAW,OAAQ,CAAA,YAAA,EAAA,EAAc,UAAQ,CAAA,kBACpD,KAAA,CAAA,aAAA,CAAA,UAAA,EAAA,EAAW,OAAQ,EAAA,OAAA,EAAA,EACjB,OAAQ,CAAA,IAAA,CAAK,OAAW,IAAA,sBAC3B,CACF,CAAA;AAEJ,CAAA;AAWA,MAAM,iBAAiB,CAAC;AAAA,EACtB,IAAA;AAAA,EACA,OAAA;AAAA,EACA,MAAA;AAAA,EACA,UAAA;AAAA,EACA,OAAA;AAAA,EACA;AACF,CAA2B,KAAA;AACzB,EAAA,MAAM,CAAC,WAAA,EAAa,cAAc,CAAA,GAAI,SAAS,EAAE,CAAA;AAEjD,EAAA,MAAM,cAAc,MAAM;AACxB,IAAA,cAAA,CAAe,EAAE,CAAA;AACjB,IAAQ,OAAA,EAAA;AAAA,GACV;AAEA,EAAA,MAAM,gBAAgB,MAAM;AAC1B,IAAA,SAAA,CAAU,WAAW,CAAA;AACrB,IAAA,cAAA,CAAe,EAAE,CAAA;AAAA,GACnB;AAEA,EAAA,MAAM,WAAW,MAAW,KAAA,QAAA;AAC5B,EAAM,MAAA,YAAA,GAAe,OAAS,EAAA,QAAA,CAAS,IAAQ,IAAA,EAAA;AAC/C,EAAA,MAAM,iBAAiB,WAAgB,KAAA,YAAA;AAEvC,EACE,uBAAA,KAAA,CAAA,aAAA;AAAA,IAAC,MAAA;AAAA,IAAA;AAAA,MACC,IAAA;AAAA,MACA,OAAA,EAAS,aAAa,SAAY,GAAA,WAAA;AAAA,MAClC,QAAS,EAAA,IAAA;AAAA,MACT,SAAS,EAAA;AAAA,KAAA;AAAA,oBAER,KAAA,CAAA,aAAA,CAAA,WAAA,EAAA,IAAA,EACE,QAAW,GAAA,gBAAA,GAAmB,iBACjC,CAAA;AAAA,oBACC,KAAA,CAAA,aAAA,CAAA,aAAA,EAAA,IAAA,EACE,OACC,oBAAA,KAAA,CAAA,aAAA,CAAA,KAAA,CAAA,QAAA,EAAA,IAAA,sCACG,UAAW,EAAA,EAAA,OAAA,EAAQ,OAAQ,EAAA,SAAA,EAAS,wBAClC,KAAA,CAAA,aAAA,CAAA,QAAA,EAAA,IAAA,EAAO,YAAU,CAAA,EAAS,KAAE,OAAQ,CAAA,IAAA,CAAK,WAAY,CAAA,MACxD,mBACC,KAAA,CAAA,aAAA,CAAA,UAAA,EAAA,EAAW,OAAQ,EAAA,OAAA,EAAQ,WAAS,IACnC,EAAA,kBAAA,KAAA,CAAA,aAAA,CAAC,QAAO,EAAA,IAAA,EAAA,OAAK,GAAS,GAAE,EAAA,OAAA,CAAQ,IAAK,CAAA,QACvC,GACC,OAAQ,CAAA,IAAA,CAAK,OACZ,oBAAA,KAAA,CAAA,aAAA,CAAC,UAAW,EAAA,EAAA,OAAA,EAAQ,OAAQ,EAAA,SAAA,EAAS,wBAClC,KAAA,CAAA,aAAA,CAAA,QAAA,EAAA,IAAA,EAAO,WAAS,CAAA,EAAS,KAAE,OAAQ,CAAA,IAAA,CAAK,OAC3C,CAAA,EAED,4BACE,KAAA,CAAA,aAAA,CAAA,GAAA,EAAA,EAAI,EAAI,EAAA,CAAA,EAAG,GAAG,CAAG,EAAA,OAAA,EAAQ,aAAc,EAAA,YAAA,EAAc,qBACnD,KAAA,CAAA,aAAA,CAAA,UAAA,EAAA,EAAW,OAAQ,EAAA,OAAA,EAAA,EAAQ,uFAG5B,CACF,CAAA,kBAED,KAAA,CAAA,aAAA,CAAA,GAAA,EAAA,EAAI,IAAI,CACP,EAAA,kBAAA,KAAA,CAAA,aAAA;AAAA,MAAC,SAAA;AAAA,MAAA;AAAA,QACC,SAAS,EAAA,IAAA;AAAA,QACT,KAAA,EAAO,SAAS,YAAY,CAAA,YAAA,CAAA;AAAA,QAC5B,KAAO,EAAA,WAAA;AAAA,QACP,UAAU,CAAC,CAAA,KAAM,cAAe,CAAA,CAAA,CAAE,OAAO,KAAK,CAAA;AAAA,QAC9C,QAAU,EAAA,UAAA;AAAA,QACV,SAAS,EAAA;AAAA;AAAA,KAEb,CACF,CAEJ,CAAA;AAAA,oBACA,KAAA,CAAA,aAAA,CAAC,qCACE,KAAA,CAAA,aAAA,CAAA,MAAA,EAAA,EAAO,SAAS,WAAa,EAAA,QAAA,EAAU,UAAY,EAAA,EAAA,QAEpD,CACA,kBAAA,KAAA,CAAA,aAAA;AAAA,MAAC,MAAA;AAAA,MAAA;AAAA,QACC,OAAS,EAAA,aAAA;AAAA,QACT,KAAA,EAAO,WAAW,WAAc,GAAA,SAAA;AAAA,QAChC,OAAQ,EAAA,WAAA;AAAA,QACR,QAAA,EAAU,CAAC,cAAkB,IAAA,UAAA;AAAA,QAC7B,SAAA,EACE,6BACG,KAAA,CAAA,aAAA,CAAA,gBAAA,EAAA,EAAiB,MAAM,EAAI,EAAA,KAAA,EAAM,WAAU,CAC1C,GAAA;AAAA,OAAA;AAAA,MAGL,UACG,GAAA,QAAA,GACE,cACA,GAAA,cAAA,GACF,WACE,QACA,GAAA;AAAA,KAEV;AAAA,GACF;AAEJ,CAAA;AAEO,MAAM,uBAAuB,MAAM;AACxC,EAAM,MAAA,EAAE,MAAO,EAAA,GAAI,SAAU,EAAA;AAC7B,EAAM,MAAA,MAAA,GAAS,OAAO,YAAY,CAAA;AAClC,EAAM,MAAA,QAAA,GAAW,OAAO,WAAW,CAAA;AACnC,EAAM,MAAA,WAAA,GAAc,OAAO,cAAc,CAAA;AACzC,EAAM,MAAA,QAAA,GAAW,OAAO,WAAW,CAAA;AACnC,EAAM,MAAA,UAAA,GAAa,MAAO,CAAA,SAAA,CAAU,iBAAiB,CAAA;AAErD,EAAA,MAAM,iBACJ,MAAO,CAAA,QAAA,CAAS,cAAc,wBAAwB,CAAA,IACtD,OAAO,QAAS,CAAA,IAAA;AAClB,EAAA,MAAM,SACJ,GAAA,MAAA,CAAO,QAAS,CAAA,WAAA,GAAc,uBAAuB,CAAK,IAAA,SAAA;AAE5D,EAAA,MAAM,CAAC,OAAA,EAAS,UAAU,CAAA,GAAI,SAAS,CAAC,CAAA;AACxC,EAAA,MAAM,CAAC,WAAA,EAAa,cAAc,CAAA,GAAI,QAKnC,CAAA;AAAA,IACD,IAAM,EAAA,KAAA;AAAA,IACN,OAAS,EAAA,IAAA;AAAA,IACT,MAAQ,EAAA,SAAA;AAAA,IACR,UAAY,EAAA;AAAA,GACb,CAAA;AAED,EAAM,MAAA;AAAA,IACJ,OAAS,EAAA,UAAA;AAAA,IACT,OAAS,EAAA,iBAAA;AAAA,IACT,KAAO,EAAA;AAAA,GACT,GAAI,sBAAsB,+BAA+B,CAAA;AAEzD,EAAA,MAAM,EAAE,KAAO,EAAA,OAAA,EAAS,KAAM,EAAA,GAAI,SAAS,YAAY;AACrD,IAAM,MAAA,QAAA,GAAW,MAAM,WAAA,CAAY,oBAAqB,EAAA;AACxD,IAAA,MAAM,aAAa,QAAS,CAAA,aAAA;AAE5B,IAAM,MAAA,QAAA,GAAW,MAAM,QAAS,CAAA,KAAA;AAAA,MAC9B,GAAG,UAAU,CAAA,sBAAA;AAAA,KACf;AACA,IAAI,IAAA,CAAC,SAAS,EAAI,EAAA;AAChB,MAAM,MAAA,GAAA,GAAM,MAAM,gBAAA,CAAiB,QAAQ,CAAA;AAC3C,MAAA,MAAM,IAAI,KAAA,CAAM,CAA6B,0BAAA,EAAA,GAAG,CAAE,CAAA,CAAA;AAAA;AAGpD,IAAM,MAAA,IAAA,GAAO,MAAM,QAAA,CAAS,IAAK,EAAA;AACjC,IAAM,MAAA,WAAA,GAAwB,IAAK,CAAA,KAAA,IAAS,EAAC;AAG7C,IAAA,MAAM,WAAW,WAAY,CAAA,MAAA;AAAA,MAC3B,CAAC,MACC,CAAE,CAAA,IAAA,CAAK,eAAe,IAAS,KAAA,cAAA,IAC/B,CAAE,CAAA,QAAA,CAAS,SAAc,KAAA;AAAA,KAC7B;AAEA,IAAO,OAAA,EAAE,QAAU,EAAA,QAAA,EAAU,UAAW,EAAA;AAAA,GAC1C,EAAG,CAAC,UAAY,EAAA,QAAA,EAAU,aAAa,cAAgB,EAAA,SAAA,EAAW,OAAO,CAAC,CAAA;AAE1E,EAAM,MAAA,aAAA,GAAgB,CAAC,OAAoB,KAAA;AACzC,IAAe,cAAA,CAAA;AAAA,MACb,IAAM,EAAA,IAAA;AAAA,MACN,OAAA;AAAA,MACA,MAAQ,EAAA,SAAA;AAAA,MACR,UAAY,EAAA;AAAA,KACb,CAAA;AAAA,GACH;AAEA,EAAM,MAAA,YAAA,GAAe,CAAC,OAAoB,KAAA;AACxC,IAAe,cAAA,CAAA;AAAA,MACb,IAAM,EAAA,IAAA;AAAA,MACN,OAAA;AAAA,MACA,MAAQ,EAAA,QAAA;AAAA,MACR,UAAY,EAAA;AAAA,KACb,CAAA;AAAA,GACH;AAEA,EAAA,MAAM,gBAAgB,YAAY;AAChC,IAAA,IAAI,CAAC,WAAA,CAAY,OAAW,IAAA,CAAC,KAAO,EAAA;AAEpC,IAAA,cAAA,CAAe,CAAC,IAAU,MAAA,EAAE,GAAG,IAAM,EAAA,UAAA,EAAY,MAAO,CAAA,CAAA;AAExD,IAAA,MAAM,QACJ,GAAA,WAAA,CAAY,MAAW,KAAA,SAAA,GACnB,CAAG,EAAA,UAAU,CAA0B,uBAAA,EAAA,WAAA,CAAY,OAAQ,CAAA,QAAA,CAAS,SAAS,CAAA,CAAA,EAAI,WAAY,CAAA,OAAA,CAAQ,QAAS,CAAA,IAAI,CAClH,QAAA,CAAA,GAAA,CAAA,EAAG,UAAU,CAAA,uBAAA,EAA0B,WAAY,CAAA,OAAA,CAAQ,QAAS,CAAA,SAAS,CAAI,CAAA,EAAA,WAAA,CAAY,OAAQ,CAAA,QAAA,CAAS,IAAI,CAAA,OAAA,CAAA;AAExH,IAAI,IAAA;AACF,MAAA,MAAM,QAAW,GAAA,MAAM,QAAS,CAAA,KAAA,CAAM,QAAU,EAAA;AAAA,QAC9C,MAAQ,EAAA,MAAA;AAAA,QACR,OAAA,EAAS,EAAE,cAAA,EAAgB,kBAAmB,EAAA;AAAA,QAC9C,MAAM,IAAK,CAAA,SAAA,CAAU,EAAE,UAAY,EAAA,KAAA,CAAM,YAAY;AAAA,OACtD,CAAA;AAED,MAAI,IAAA,CAAC,SAAS,EAAI,EAAA;AAChB,QAAM,MAAA,GAAA,GAAM,MAAM,gBAAA,CAAiB,QAAQ,CAAA;AAC3C,QAAM,MAAA,IAAI,MAAM,GAAG,CAAA;AAAA;AAGrB,MAAe,cAAA,CAAA;AAAA,QACb,IAAM,EAAA,KAAA;AAAA,QACN,OAAS,EAAA,IAAA;AAAA,QACT,MAAQ,EAAA,SAAA;AAAA,QACR,UAAY,EAAA;AAAA,OACb,CAAA;AACD,MAAW,UAAA,CAAA,CAAC,CAAM,KAAA,CAAA,GAAI,CAAC,CAAA;AACvB,MAAA,QAAA,CAAS,IAAK,CAAA;AAAA,QACZ,SAAS,CAAW,QAAA,EAAA,WAAA,CAAY,MAAW,KAAA,SAAA,GAAY,aAAa,UAAU,CAAA,CAAA;AAAA,QAC9E,QAAU,EAAA,SAAA;AAAA,QACV,OAAS,EAAA;AAAA,OACV,CAAA;AAAA,aACM,GAAK,EAAA;AACZ,MAAA,OAAA,CAAQ,KAAM,CAAA,CAAA,MAAA,EAAS,WAAY,CAAA,MAAM,gBAAgB,GAAG,CAAA;AAC5D,MAAA,cAAA,CAAe,CAAC,IAAU,MAAA,EAAE,GAAG,IAAM,EAAA,UAAA,EAAY,OAAQ,CAAA,CAAA;AACzD,MAAA,MAAM,YAAe,GAAA,GAAA,YAAe,KAAQ,GAAA,GAAA,CAAI,OAAU,GAAA,wBAAA;AAC1D,MAAA,QAAA,CAAS,IAAK,CAAA;AAAA,QACZ,OAAS,EAAA,CAAA,UAAA,EAAa,WAAY,CAAA,MAAM,YAAY,YAAY,CAAA,CAAA;AAAA,QAChE,QAAU,EAAA,OAAA;AAAA,QACV,OAAS,EAAA;AAAA,OACV,CAAA;AAAA;AACH,GACF;AAEA,EAAA,IAAI,WAAW,iBAAmB,EAAA;AAChC,IAAA,2CAAQ,QAAS,EAAA,IAAA,CAAA;AAAA;AAGnB,EAAA,IAAI,KAAO,EAAA;AACT,IAAO,uBAAA,KAAA,CAAA,aAAA,CAAC,sBAAmB,KAAc,EAAA,CAAA;AAAA;AAG3C,EAAA,IAAI,eAAiB,EAAA;AACnB,IACE,uBAAA,KAAA,CAAA,aAAA,CAAC,GAAI,EAAA,EAAA,CAAA,EAAG,CACN,EAAA,kBAAA,KAAA,CAAA,aAAA,CAAC,UAAW,EAAA,EAAA,KAAA,EAAM,OAAQ,EAAA,EAAA,+BAAA,EACM,eAAgB,CAAA,OAChD,CACF,CAAA;AAAA;AAIJ,EAAA,IAAI,CAAC,UAAY,EAAA;AACf,IAAA,uBACG,KAAA,CAAA,aAAA,CAAA,GAAA,EAAA,EAAI,CAAG,EAAA,CAAA,EAAG,SAAU,EAAA,QAAA,EAAA,kBAClB,KAAA,CAAA,aAAA,CAAA,UAAA,EAAA,EAAW,OAAQ,EAAA,OAAA,EAAQ,KAAM,EAAA,eAAA,EAAA,EAAgB,oEAElD,CACF,CAAA;AAAA;AAIJ,EAAM,MAAA,QAAA,GAAW,KAAO,EAAA,QAAA,IAAY,EAAC;AACrC,EAAA,MAAM,kBAAkB,QAAS,CAAA,MAAA;AAAA,IAC/B,CAAC,MAAM,CAAC,CAAA,CAAE,QAAQ,KAAS,IAAA,CAAA,CAAE,OAAO,KAAU,KAAA;AAAA,GAChD;AACA,EAAA,MAAM,mBAAmB,QAAS,CAAA,MAAA;AAAA,IAChC,CAAC,CAAA,KAAM,CAAE,CAAA,MAAA,EAAQ,KAAU,KAAA;AAAA,GAC7B;AACA,EAAA,MAAM,mBAAmB,QAAS,CAAA,MAAA;AAAA,IAChC,CAAC,CAAA,KAAM,CAAE,CAAA,MAAA,EAAQ,KAAU,KAAA;AAAA,GAC7B;AAEA,EAAA,MAAM,OAAiC,GAAA;AAAA,IACrC;AAAA,MACE,KAAO,EAAA,WAAA;AAAA,MACP,KAAO,EAAA,yBAAA;AAAA,MACP,MAAA,EAAQ,CAAC,GAAA,qBACN,KAAA,CAAA,aAAA,CAAA,UAAA,EAAA,EAAW,SAAQ,OAAS,EAAA,EAAA,GAAA,CAAI,IAAK,CAAA,WAAA,CAAY,MAAO;AAAA,KAE7D;AAAA,IACA;AAAA,MACE,KAAO,EAAA,QAAA;AAAA,MACP,KAAO,EAAA,cAAA;AAAA,MACP,MAAA,EAAQ,CAAC,GAAQ,KAAA;AACf,QAAM,MAAA,KAAA,GAAQ,GAAI,CAAA,MAAA,EAAQ,KAAS,IAAA,SAAA;AACnC,QAAM,MAAA,KAAA,GAAQ,KAAU,KAAA,UAAA,GAAa,QAAW,GAAA,KAAA;AAChD,QACE,uBAAA,KAAA,CAAA,aAAA,CAAC,QAAK,KAAc,EAAA,IAAA,EAAK,SAAQ,KAAO,EAAA,kBAAA,CAAmB,KAAK,CAAG,EAAA,CAAA;AAAA;AAEvE,KACF;AAAA,IACA;AAAA,MACE,KAAO,EAAA,MAAA;AAAA,MACP,KAAO,EAAA,eAAA;AAAA,MACP,MAAQ,EAAA,CAAC,GACP,qBAAA,KAAA,CAAA,aAAA,CAAC,IAAK,EAAA,EAAA,KAAA,EAAO,GAAI,CAAA,IAAA,CAAK,QAAU,EAAA,IAAA,EAAK,OAAQ,EAAA,OAAA,EAAQ,UAAW,EAAA;AAAA,KAEpE;AAAA,IACA;AAAA,MACE,KAAO,EAAA,WAAA;AAAA,MACP,KAAO,EAAA,4BAAA;AAAA,MACP,MAAA,EAAQ,CAAC,GAAQ,KAAA;AACf,QAAI,IAAA,CAAC,IAAI,QAAS,CAAA,iBAAA;AAChB,UAAA,uBAAQ,KAAA,CAAA,aAAA,CAAA,UAAA,EAAA,EAAW,OAAQ,EAAA,OAAA,EAAA,EAAQ,GAAC,CAAA;AACtC,QACE,uBAAA,KAAA,CAAA,aAAA,CAAC,UAAW,EAAA,EAAA,OAAA,EAAQ,OACjB,EAAA,EAAA,IAAI,IAAK,CAAA,GAAA,CAAI,QAAS,CAAA,iBAAiB,CAAE,CAAA,kBAAA,EAC5C,CAAA;AAAA;AAEJ,KACF;AAAA,IACA;AAAA,MACE,KAAO,EAAA,SAAA;AAAA,MACP,SAAW,EAAA,KAAA;AAAA,MACX,MAAA,EAAQ,CAAC,GAAQ,KAAA;AACf,QAAM,MAAA,KAAA,GAAQ,GAAI,CAAA,MAAA,EAAQ,KAAS,IAAA,SAAA;AACnC,QAAI,IAAA,KAAA,KAAU,WAAkB,OAAA,IAAA;AAChC,QACE,uBAAA,KAAA,CAAA,aAAA,CAAC,OAAI,OAAQ,EAAA,MAAA,EAAO,OAAO,EAAE,GAAA,EAAK,CAAE,EAAA,EAAA,kBACjC,KAAA,CAAA,aAAA,CAAA,OAAA,EAAA,EAAQ,OAAM,SACb,EAAA,kBAAA,KAAA,CAAA,aAAA,CAAC,cAAW,IAAK,EAAA,OAAA,EAAQ,SAAS,MAAM,aAAA,CAAc,GAAG,CAAA,EAAA,kBACtD,KAAA,CAAA,aAAA,CAAA,eAAA,EAAA,EAAgB,OAAM,SAAU,EAAA,CACnC,CACF,CACA,kBAAA,KAAA,CAAA,aAAA,CAAC,WAAQ,KAAM,EAAA,QAAA,EAAA,kBACZ,KAAA,CAAA,aAAA,CAAA,UAAA,EAAA,EAAW,IAAK,EAAA,OAAA,EAAQ,SAAS,MAAM,YAAA,CAAa,GAAG,CACtD,EAAA,kBAAA,KAAA,CAAA,aAAA,CAAC,cAAW,KAAM,EAAA,OAAA,EAAQ,CAC5B,CACF,CACF,CAAA;AAAA;AAEJ;AACF,GACF;AAEA,EAAA,MAAM,iBAAoB,GAAA;AAAA,IACxB;AAAA,MACE,MAAA,EAAQ,CAAC,IAAc,KAAA;AACrB,QAAA,MAAM,UAAU,IAAK,CAAA,OAAA;AACrB,QAAA,IAAI,CAAC,OAAS,EAAA,QAAA,EAAU,IAAM,EAAA,2CAAQ,GAAI,EAAA,IAAA,CAAA;AAC1C,QAAO,uBAAA,KAAA,CAAA,aAAA,CAAC,sBAAmB,OAAkB,EAAA,CAAA;AAAA;AAC/C;AACF,GACF;AAEA,EAAA,2CACG,GAAI,EAAA,EAAA,CAAA,EAAG,qBACL,KAAA,CAAA,aAAA,CAAA,GAAA,EAAA,EAAI,IAAI,CACP,EAAA,kBAAA,KAAA,CAAA,aAAA,CAAC,cAAW,OAAQ,EAAA,OAAA,EAAQ,OAAM,eAC/B,EAAA,EAAA,eAAA,CAAgB,QAAO,YAAW,EAAA,gBAAA,CAAiB,QAAO,YAAW,EAAA,GAAA,EACrE,iBAAiB,MAAO,EAAA,WAC3B,CACF,CAEC,EAAA,QAAA,CAAS,WAAW,CACnB,mBAAA,KAAA,CAAA,aAAA,CAAC,OAAI,CAAG,EAAA,CAAA,EAAG,WAAU,QACnB,EAAA,kBAAA,KAAA,CAAA,aAAA,CAAC,cAAW,OAAQ,EAAA,OAAA,EAAQ,OAAM,eAAgB,EAAA,EAAA,2BAElD,CACF,CAEA,mBAAA,KAAA,CAAA,aAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MACC,OAAS,EAAA;AAAA,QACP,MAAA,EAAQ,SAAS,MAAS,GAAA,EAAA;AAAA,QAC1B,QAAU,EAAA,EAAA;AAAA,QACV,MAAQ,EAAA,IAAA;AAAA,QACR,SAAW,EAAA,KAAA;AAAA,QACX,gBAAkB,EAAA,GAAA;AAAA,QAClB,OAAS,EAAA,IAAA;AAAA,QACT,mBAAqB,EAAA;AAAA,OACvB;AAAA,MACA,OAAA;AAAA,MACA,IAAM,EAAA,QAAA,CAAS,GAAI,CAAA,CAAC,IAAU,MAAA,EAAE,GAAG,IAAA,EAAM,EAAI,EAAA,IAAA,CAAK,QAAS,CAAA,IAAA,EAAO,CAAA,CAAA;AAAA,MAClE,WAAa,EAAA;AAAA;AAAA,GAIjB,kBAAA,KAAA,CAAA,aAAA;AAAA,IAAC,cAAA;AAAA,IAAA;AAAA,MACC,MAAM,WAAY,CAAA,IAAA;AAAA,MAClB,SAAS,WAAY,CAAA,OAAA;AAAA,MACrB,QAAQ,WAAY,CAAA,MAAA;AAAA,MACpB,YAAY,WAAY,CAAA,UAAA;AAAA,MACxB,OAAA,EAAS,MACP,cAAe,CAAA;AAAA,QACb,IAAM,EAAA,KAAA;AAAA,QACN,OAAS,EAAA,IAAA;AAAA,QACT,MAAQ,EAAA,SAAA;AAAA,QACR,UAAY,EAAA;AAAA,OACb,CAAA;AAAA,MAEH,SAAW,EAAA;AAAA;AAAA,GAEf,CAAA;AAEJ;;;;"}
1
+ {"version":3,"file":"EntityApiApprovalTab.esm.js","sources":["../../../src/components/EntityApiApprovalTab/EntityApiApprovalTab.tsx"],"sourcesContent":["import React, { useState } from \"react\";\nimport { useEntity } from \"@backstage/plugin-catalog-react\";\nimport {\n useApi,\n identityApiRef,\n alertApiRef,\n} from \"@backstage/core-plugin-api\";\nimport { kuadrantApiRef } from '../../api';\nimport { useAsync } from \"react-use\";\nimport {\n Table,\n TableColumn,\n Progress,\n ResponseErrorPanel,\n} from \"@backstage/core-components\";\nimport { kuadrantApiKeyApprovePermission } from \"../../permissions\";\nimport { useKuadrantPermission } from \"../../utils/permissions\";\nimport {\n Box,\n Typography,\n Chip,\n IconButton,\n Tooltip,\n Button,\n Dialog,\n DialogTitle,\n DialogContent,\n DialogActions,\n TextField,\n CircularProgress,\n makeStyles,\n} from \"@material-ui/core\";\nimport CheckCircleIcon from \"@material-ui/icons/CheckCircle\";\nimport CancelIcon from \"@material-ui/icons/Cancel\";\nimport { APIKey } from \"../../types/api-management\";\nimport { getApprovalQueueStatusChipStyle } from \"../../utils/styles\";\n\nconst useStyles = makeStyles((theme) => ({\n useCasePanel: {\n padding: theme.spacing(2),\n backgroundColor: theme.palette.background.default,\n },\n useCaseLabel: {\n fontWeight: 600,\n marginBottom: theme.spacing(1),\n color: theme.palette.text.secondary,\n textTransform: \"uppercase\",\n fontSize: \"0.75rem\",\n },\n}));\n\ninterface ExpandedRowProps {\n request: APIKey;\n}\n\nconst ExpandedRowContent = ({ request }: ExpandedRowProps) => {\n const classes = useStyles();\n\n return (\n <Box className={classes.useCasePanel} onClick={(e) => e.stopPropagation()}>\n <Typography className={classes.useCaseLabel}>Use Case</Typography>\n <Typography variant=\"body2\">\n {request.spec.useCase || \"No use case provided\"}\n </Typography>\n </Box>\n );\n};\n\ninterface ApprovalDialogProps {\n open: boolean;\n request: APIKey | null;\n action: \"approve\" | \"reject\";\n processing: boolean;\n onClose: () => void;\n onConfirm: (confirmText: string) => void;\n}\n\nconst ApprovalDialog = ({\n open,\n request,\n action,\n processing,\n onClose,\n onConfirm,\n}: ApprovalDialogProps) => {\n const [confirmText, setConfirmText] = useState(\"\");\n\n const handleClose = () => {\n setConfirmText(\"\");\n onClose();\n };\n\n const handleConfirm = () => {\n onConfirm(confirmText);\n setConfirmText(\"\");\n };\n\n const isReject = action === \"reject\";\n const expectedText = request?.metadata.name || \"\";\n const isConfirmValid = confirmText === expectedText;\n\n return (\n <Dialog\n open={open}\n onClose={processing ? undefined : handleClose}\n maxWidth=\"sm\"\n fullWidth\n >\n <DialogTitle>\n {isReject ? \"Reject API key\" : \"Approve API key\"}\n </DialogTitle>\n <DialogContent>\n {request && (\n <>\n <Typography variant=\"body2\" paragraph>\n <strong>Requester:</strong> {request.spec.requestedBy.userId}\n </Typography>\n <Typography variant=\"body2\" paragraph>\n <strong>Tier:</strong> {request.spec.planTier}\n </Typography>\n {request.spec.useCase && (\n <Typography variant=\"body2\" paragraph>\n <strong>Use Case:</strong> {request.spec.useCase}\n </Typography>\n )}\n {isReject && (\n <Box mt={2} p={2} bgcolor=\"error.light\" borderRadius={1}>\n <Typography variant=\"body2\">\n This action will permanently deny access. The user will need\n to submit a new request.\n </Typography>\n </Box>\n )}\n <Box mt={2}>\n <TextField\n fullWidth\n label={`Type \"${expectedText}\" to confirm`}\n value={confirmText}\n onChange={(e) => setConfirmText(e.target.value)}\n disabled={processing}\n autoFocus\n />\n </Box>\n </>\n )}\n </DialogContent>\n <DialogActions>\n <Button onClick={handleClose} disabled={processing}>\n Cancel\n </Button>\n <Button\n onClick={handleConfirm}\n color={isReject ? \"secondary\" : \"primary\"}\n variant=\"contained\"\n disabled={!isConfirmValid || processing}\n startIcon={\n processing ? (\n <CircularProgress size={16} color=\"inherit\" />\n ) : undefined\n }\n >\n {processing\n ? isReject\n ? \"Rejecting...\"\n : \"Approving...\"\n : isReject\n ? \"Reject\"\n : \"Approve\"}\n </Button>\n </DialogActions>\n </Dialog>\n );\n};\n\nexport const EntityApiApprovalTab = () => {\n const { entity } = useEntity();\n const kuadrantApi = useApi(kuadrantApiRef);\n const identityApi = useApi(identityApiRef);\n const alertApi = useApi(alertApiRef);\n\n const apiProductName =\n entity.metadata.annotations?.[\"kuadrant.io/apiproduct\"] ||\n entity.metadata.name;\n const namespace =\n entity.metadata.annotations?.[\"kuadrant.io/namespace\"] || \"default\";\n\n const [refresh, setRefresh] = useState(0);\n const [dialogState, setDialogState] = useState<{\n open: boolean;\n request: APIKey | null;\n action: \"approve\" | \"reject\";\n processing: boolean;\n }>({\n open: false,\n request: null,\n action: \"approve\",\n processing: false,\n });\n\n const {\n allowed: canApprove,\n loading: permissionLoading,\n error: permissionError,\n } = useKuadrantPermission(kuadrantApiKeyApprovePermission);\n\n const { value, loading, error } = useAsync(async () => {\n const identity = await identityApi.getBackstageIdentity();\n const reviewedBy = identity.userEntityRef;\n\n const data = await kuadrantApi.getRequests();\n const allRequests: APIKey[] = data.items || [];\n\n // filter to this API product only\n const filtered = allRequests.filter(\n (r) =>\n r.spec.apiProductRef?.name === apiProductName &&\n r.metadata.namespace === namespace,\n );\n\n return { requests: filtered, reviewedBy };\n }, [kuadrantApi, identityApi, apiProductName, namespace, refresh]);\n\n const handleApprove = (request: APIKey) => {\n setDialogState({\n open: true,\n request,\n action: \"approve\",\n processing: false,\n });\n };\n\n const handleReject = (request: APIKey) => {\n setDialogState({\n open: true,\n request,\n action: \"reject\",\n processing: false,\n });\n };\n\n const handleConfirm = async () => {\n if (!dialogState.request || !value) return;\n\n setDialogState((prev) => ({ ...prev, processing: true }));\n\n const isApprove = dialogState.action === \"approve\"\n const requestFn = isApprove\n ? (ns: string, n: string, r: string) => kuadrantApi.approveRequest(ns, n, r)\n : (ns: string, n: string, r: string) => kuadrantApi.rejectRequest(ns, n, r)\n\n try {\n await requestFn(dialogState.request.metadata.namespace, dialogState.request.metadata.name, value.reviewedBy);\n\n setDialogState({\n open: false,\n request: null,\n action: \"approve\",\n processing: false,\n });\n setRefresh((r) => r + 1);\n alertApi.post({\n message: `API key ${isApprove ? \"approved\" : \"rejected\"}`,\n severity: \"success\",\n display: \"transient\",\n });\n } catch (err) {\n console.error(`Error ${dialogState.action}ing request:`, err);\n setDialogState((prev) => ({ ...prev, processing: false }));\n const errorMessage = err instanceof Error ? err.message : \"unknown error occurred\";\n alertApi.post({\n message: `Failed to ${dialogState.action} APIKey. ${errorMessage}`,\n severity: 'error',\n display: 'transient',\n });\n }\n };\n\n if (loading || permissionLoading) {\n return <Progress />;\n }\n\n if (error) {\n return <ResponseErrorPanel error={error} />;\n }\n\n if (permissionError) {\n return (\n <Box p={2}>\n <Typography color=\"error\">\n Unable to check permissions: {permissionError.message}\n </Typography>\n </Box>\n );\n }\n\n if (!canApprove) {\n return (\n <Box p={3} textAlign=\"center\">\n <Typography variant=\"body1\" color=\"textSecondary\">\n You don't have permission to view the approval queue for this API.\n </Typography>\n </Box>\n );\n }\n\n const requests = value?.requests || [];\n const pendingRequests = requests.filter(\n (r) => !r.status?.phase || r.status.phase === \"Pending\",\n );\n const approvedRequests = requests.filter(\n (r) => r.status?.phase === \"Approved\",\n );\n const rejectedRequests = requests.filter(\n (r) => r.status?.phase === \"Rejected\",\n );\n\n const columns: TableColumn<APIKey>[] = [\n {\n title: \"Requester\",\n field: \"spec.requestedBy.userId\",\n render: (row) => (\n <Typography variant=\"body2\">{row.spec.requestedBy.userId}</Typography>\n ),\n },\n {\n title: \"Status\",\n field: \"status.phase\",\n render: (row) => {\n const phase = row.status?.phase || \"Pending\";\n const label = phase === \"Approved\" ? \"Active\" : phase;\n return (\n <Chip label={label} size=\"small\" style={getApprovalQueueStatusChipStyle(phase)} />\n );\n },\n },\n {\n title: \"Tier\",\n field: \"spec.planTier\",\n render: (row) => (\n <Chip label={row.spec.planTier} size=\"small\" variant=\"outlined\" />\n ),\n },\n {\n title: \"Requested\",\n field: \"metadata.creationTimestamp\",\n render: (row) => {\n if (!row.metadata.creationTimestamp)\n return <Typography variant=\"body2\">-</Typography>;\n return (\n <Typography variant=\"body2\">\n {new Date(row.metadata.creationTimestamp).toLocaleDateString()}\n </Typography>\n );\n },\n },\n {\n title: \"Actions\",\n filtering: false,\n render: (row) => {\n const phase = row.status?.phase || \"Pending\";\n if (phase !== \"Pending\") return null;\n return (\n <Box display=\"flex\" style={{ gap: 4 }}>\n <Tooltip title=\"Approve\">\n <IconButton size=\"small\" onClick={() => handleApprove(row)}>\n <CheckCircleIcon color=\"primary\" />\n </IconButton>\n </Tooltip>\n <Tooltip title=\"Reject\">\n <IconButton size=\"small\" onClick={() => handleReject(row)}>\n <CancelIcon color=\"error\" />\n </IconButton>\n </Tooltip>\n </Box>\n );\n },\n },\n ];\n\n const detailPanelConfig = [\n {\n render: (data: any) => {\n const request = data.rowData as APIKey;\n if (!request?.metadata?.name) return <Box />;\n return <ExpandedRowContent request={request} />;\n },\n },\n ];\n\n return (\n <Box p={2}>\n <Box mb={2}>\n <Typography variant=\"body2\" color=\"textSecondary\">\n {pendingRequests.length} pending, {approvedRequests.length} approved,{\" \"}\n {rejectedRequests.length} rejected\n </Typography>\n </Box>\n\n {requests.length === 0 ? (\n <Box p={3} textAlign=\"center\">\n <Typography variant=\"body1\" color=\"textSecondary\">\n No API keys for this API.\n </Typography>\n </Box>\n ) : (\n <Table\n options={{\n paging: requests.length > 10,\n pageSize: 20,\n search: true,\n filtering: false,\n debounceInterval: 300,\n toolbar: true,\n emptyRowsWhenPaging: false,\n }}\n columns={columns}\n data={requests.map((item) => ({ ...item, id: item.metadata.name }))}\n detailPanel={detailPanelConfig}\n />\n )}\n\n <ApprovalDialog\n open={dialogState.open}\n request={dialogState.request}\n action={dialogState.action}\n processing={dialogState.processing}\n onClose={() =>\n setDialogState({\n open: false,\n request: null,\n action: \"approve\",\n processing: false,\n })\n }\n onConfirm={handleConfirm}\n />\n </Box>\n );\n};\n"],"names":[],"mappings":"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"}
@@ -8,14 +8,15 @@ import LockIcon from '@material-ui/icons/Lock';
8
8
  import { FilterPanel } from '../FilterPanel/FilterPanel.esm.js';
9
9
  import { Page, Header, SupportButton, Content, ResponseErrorPanel, Table, Link } from '@backstage/core-components';
10
10
  import useAsync from 'react-use/lib/useAsync';
11
- import { useApi, configApiRef, fetchApiRef, alertApiRef, identityApiRef } from '@backstage/core-plugin-api';
11
+ import { useApi, alertApiRef, identityApiRef } from '@backstage/core-plugin-api';
12
+ import { kuadrantApiRef } from '../../api.esm.js';
12
13
  import { PermissionGate } from '../PermissionGate/PermissionGate.esm.js';
13
14
  import { CreateAPIProductDialog } from '../CreateAPIProductDialog/CreateAPIProductDialog.esm.js';
14
15
  import { kuadrantApiProductListPermission, kuadrantApiProductCreatePermission, kuadrantApiProductDeleteOwnPermission, kuadrantApiProductDeleteAllPermission, kuadrantApiProductUpdateOwnPermission, kuadrantApiProductUpdateAllPermission, kuadrantPlanPolicyListPermission } from '../../permissions.esm.js';
15
16
  import { useKuadrantPermission } from '../../utils/permissions.esm.js';
16
- import { handleFetchError } from '../../utils/errors.esm.js';
17
17
  import { EditAPIProductDialog } from '../EditAPIProductDialog/EditAPIProductDialog.esm.js';
18
18
  import { ConfirmDeleteDialog } from '../ConfirmDeleteDialog/ConfirmDeleteDialog.esm.js';
19
+ import { getLifecycleChipStyle } from '../../utils/styles.esm.js';
19
20
  import emptyStateIllustration from '../../assets/empty-state-illustration.png';
20
21
 
21
22
  const useStyles = makeStyles((theme) => ({
@@ -59,11 +60,9 @@ const useStyles = makeStyles((theme) => ({
59
60
  }));
60
61
  const ResourceList = () => {
61
62
  const classes = useStyles();
62
- const config = useApi(configApiRef);
63
- const fetchApi = useApi(fetchApiRef);
63
+ const kuadrantApi = useApi(kuadrantApiRef);
64
64
  const alertApi = useApi(alertApiRef);
65
65
  const identityApi = useApi(identityApiRef);
66
- const backendUrl = config.getString("backend.baseUrl");
67
66
  const [userEntityRef, setUserEntityRef] = useState("");
68
67
  const [createDialogOpen, setCreateDialogOpen] = useState(false);
69
68
  const [editDialogOpen, setEditDialogOpen] = useState(false);
@@ -75,6 +74,7 @@ const ResourceList = () => {
75
74
  const [deleteStats, setDeleteStats] = useState(null);
76
75
  const [filters, setFilters] = useState({
77
76
  status: [],
77
+ lifecycle: [],
78
78
  policy: [],
79
79
  route: [],
80
80
  namespace: [],
@@ -116,15 +116,8 @@ const ResourceList = () => {
116
116
  loading: apiProductsLoading,
117
117
  error: apiProductsError
118
118
  } = useAsync(async () => {
119
- const response = await fetchApi.fetch(
120
- `${backendUrl}/api/kuadrant/apiproducts`
121
- );
122
- if (!response.ok) {
123
- const error2 = await handleFetchError(response);
124
- throw new Error(`failed to fetch APIProducts. ${error2}`);
125
- }
126
- return await response.json();
127
- }, [backendUrl, fetchApi, refreshTrigger]);
119
+ return kuadrantApi.getApiProducts();
120
+ }, [kuadrantApi, refreshTrigger]);
128
121
  const {
129
122
  value: planPolicies,
130
123
  loading: planPoliciesLoading,
@@ -133,15 +126,8 @@ const ResourceList = () => {
133
126
  if (!canListPlanPolicies) {
134
127
  return { items: [] };
135
128
  }
136
- const response = await fetchApi.fetch(
137
- `${backendUrl}/api/kuadrant/planpolicies`
138
- );
139
- if (!response.ok) {
140
- const error2 = await handleFetchError(response);
141
- throw new Error(`failed to fetch PlanPolicies: ${error2}`);
142
- }
143
- return await response.json();
144
- }, [backendUrl, fetchApi, refreshTrigger, canListPlanPolicies]);
129
+ return kuadrantApi.getPlanPolicies();
130
+ }, [kuadrantApi, refreshTrigger, canListPlanPolicies]);
145
131
  const getPolicyForProduct = useCallback((product) => {
146
132
  if (!planPolicies?.items) return null;
147
133
  const targetRef = product.spec?.targetRef;
@@ -171,10 +157,18 @@ const ResourceList = () => {
171
157
  const error = apiProductsError || planPoliciesError;
172
158
  const permissionError = createPermissionError || deletePermissionError || planPolicyPermissionError;
173
159
  const allProducts = useMemo(() => {
174
- return apiProducts?.items || [];
175
- }, [apiProducts]);
160
+ const products = apiProducts?.items || [];
161
+ if (!canCreateApiProduct && !canUpdateOwnApiProduct && !canUpdateAllApiProducts) {
162
+ return products.filter((p) => {
163
+ const publishStatus = p.spec?.publishStatus || "Draft";
164
+ return publishStatus === "Published";
165
+ });
166
+ }
167
+ return products;
168
+ }, [apiProducts, canCreateApiProduct, canUpdateOwnApiProduct, canUpdateAllApiProducts]);
176
169
  const filterSections = useMemo(() => {
177
170
  const statusCounts = { Draft: 0, Published: 0 };
171
+ const lifecycleCounts = /* @__PURE__ */ new Map();
178
172
  const policyCounts = /* @__PURE__ */ new Map();
179
173
  const routeCounts = /* @__PURE__ */ new Map();
180
174
  const namespaceCounts = /* @__PURE__ */ new Map();
@@ -183,6 +177,8 @@ const ResourceList = () => {
183
177
  allProducts.forEach((p) => {
184
178
  const status = p.spec?.publishStatus || "Draft";
185
179
  statusCounts[status]++;
180
+ const lifecycle = p.metadata.labels?.lifecycle || "production";
181
+ lifecycleCounts.set(lifecycle, (lifecycleCounts.get(lifecycle) || 0) + 1);
186
182
  const policy = getPolicyForProduct(p) || "N/A";
187
183
  policyCounts.set(policy, (policyCounts.get(policy) || 0) + 1);
188
184
  const route = p.spec?.targetRef?.name || "unknown";
@@ -201,12 +197,21 @@ const ResourceList = () => {
201
197
  const sections = [
202
198
  {
203
199
  id: "status",
204
- title: "Status",
200
+ title: "Publish Status",
205
201
  options: [
206
202
  { value: "Draft", label: "Draft", count: statusCounts.Draft },
207
203
  { value: "Published", label: "Published", count: statusCounts.Published }
208
204
  ]
209
205
  },
206
+ {
207
+ id: "lifecycle",
208
+ title: "Lifecycle",
209
+ options: Array.from(lifecycleCounts.entries()).map(([state, count]) => ({
210
+ value: state,
211
+ label: state.charAt(0).toUpperCase() + state.slice(1),
212
+ count
213
+ }))
214
+ },
210
215
  {
211
216
  id: "authentication",
212
217
  title: "Authentication",
@@ -267,6 +272,10 @@ const ResourceList = () => {
267
272
  const status = p.spec?.publishStatus || "Draft";
268
273
  if (!filters.status.includes(status)) return false;
269
274
  }
275
+ if (filters.lifecycle && filters.lifecycle.length > 0) {
276
+ const lifecycle = p.metadata.labels?.lifecycle || "production";
277
+ if (!filters.lifecycle.includes(lifecycle)) return false;
278
+ }
270
279
  if (filters.authentication.length > 0) {
271
280
  const authSchemes = getAuthSchemes(p);
272
281
  if (!filters.authentication.some((a) => authSchemes.includes(a))) return false;
@@ -314,14 +323,7 @@ const ResourceList = () => {
314
323
  setApiProductToDelete({ namespace, name });
315
324
  setDeleteStats(null);
316
325
  try {
317
- const response = await fetchApi.fetch(
318
- `${backendUrl}/api/kuadrant/requests?namespace=${namespace}`
319
- );
320
- if (!response.ok) {
321
- const error2 = await handleFetchError(response);
322
- throw new Error(error2);
323
- }
324
- const data = await response.json();
326
+ const data = await kuadrantApi.getRequestsByNamespace(namespace);
325
327
  const related = (data.items || []).filter(
326
328
  (r) => r.spec.apiName === name && r.spec.apiNamespace === namespace
327
329
  );
@@ -344,14 +346,10 @@ const ResourceList = () => {
344
346
  if (!apiProductToDelete) return;
345
347
  setDeleting(true);
346
348
  try {
347
- const response = await fetchApi.fetch(
348
- `${backendUrl}/api/kuadrant/apiproducts/${apiProductToDelete.namespace}/${apiProductToDelete.name}`,
349
- { method: "DELETE" }
349
+ await kuadrantApi.deleteApiProduct(
350
+ apiProductToDelete.namespace,
351
+ apiProductToDelete.name
350
352
  );
351
- if (!response.ok) {
352
- const error2 = await handleFetchError(response);
353
- throw new Error(error2);
354
- }
355
353
  const deletedName = apiProductToDelete?.name || "API Product";
356
354
  setRefreshTrigger((prev) => prev + 1);
357
355
  alertApi.post({
@@ -382,21 +380,23 @@ const ResourceList = () => {
382
380
  const displayName = row.spec?.displayName || name;
383
381
  const currentStatus = row.spec?.publishStatus || "Draft";
384
382
  const newStatus = currentStatus === "Published" ? "Draft" : "Published";
385
- try {
386
- const response = await fetchApi.fetch(
387
- `${backendUrl}/api/kuadrant/apiproducts/${namespace}/${name}`,
388
- {
389
- method: "PATCH",
390
- headers: { "Content-Type": "application/json" },
391
- body: JSON.stringify({
392
- spec: { publishStatus: newStatus }
393
- })
394
- }
395
- );
396
- if (!response.ok) {
397
- const error2 = await handleFetchError(response);
398
- throw new Error(error2);
383
+ const lifecycle = row.metadata.labels?.lifecycle;
384
+ if (newStatus === "Published" && lifecycle === "retired") {
385
+ alertApi.post({
386
+ message: `Cannot publish a retired API product. Please change the lifecycle status first.`,
387
+ severity: "error",
388
+ display: "transient"
389
+ });
390
+ return;
391
+ }
392
+ const productPatch = {
393
+ // @ts-ignore partial obj
394
+ spec: {
395
+ publishStatus: newStatus
399
396
  }
397
+ };
398
+ try {
399
+ await kuadrantApi.updateApiProduct(namespace, name, productPatch);
400
400
  setRefreshTrigger((prev) => prev + 1);
401
401
  alertApi.post({
402
402
  message: `"${displayName}" ${newStatus === "Published" ? "published" : "unpublished"} successfully`,
@@ -467,6 +467,22 @@ const ResourceList = () => {
467
467
  );
468
468
  }
469
469
  },
470
+ {
471
+ title: "Lifecycle",
472
+ field: "metadata.labels.lifecycle",
473
+ render: (row) => {
474
+ const lifecycle = row.metadata.labels?.lifecycle;
475
+ if (!lifecycle) return "-";
476
+ return /* @__PURE__ */ React.createElement(
477
+ Chip,
478
+ {
479
+ label: lifecycle.charAt(0).toUpperCase() + lifecycle.slice(1),
480
+ size: "small",
481
+ style: getLifecycleChipStyle(lifecycle)
482
+ }
483
+ );
484
+ }
485
+ },
470
486
  {
471
487
  title: "Authentication",
472
488
  field: "status.discoveredAuthScheme",