@kuadrant/kuadrant-backstage-plugin-frontend 0.2.0 → 0.2.1
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.
- package/dist/components/ApiKeyManagementTab/ApiKeyManagementTab.esm.js +21 -3
- package/dist/components/ApiKeyManagementTab/ApiKeyManagementTab.esm.js.map +1 -1
- package/dist/components/CreateAPIProductDialog/CreateAPIProductDialog.esm.js +1 -7
- package/dist/components/CreateAPIProductDialog/CreateAPIProductDialog.esm.js.map +1 -1
- package/dist/components/KuadrantIcon/KuadrantIcon.esm.js +22 -0
- package/dist/components/KuadrantIcon/KuadrantIcon.esm.js.map +1 -0
- package/dist/components/icons.esm.js +11 -0
- package/dist/components/icons.esm.js.map +1 -0
- package/dist/index.d.ts +8 -1
- package/dist/index.esm.js +2 -0
- package/dist/index.esm.js.map +1 -1
- package/dist-scalprum/internal.plugin-kuadrant.c4fb9c2347d3ad03a5d0.js +2 -0
- package/dist-scalprum/internal.plugin-kuadrant.c4fb9c2347d3ad03a5d0.js.map +1 -0
- package/dist-scalprum/plugin-manifest.json +3 -3
- package/dist-scalprum/static/{1037.58dd29ad.chunk.js → 1037.25758556.chunk.js} +1 -1
- package/dist-scalprum/static/{1037.58dd29ad.chunk.js.map → 1037.25758556.chunk.js.map} +1 -1
- package/dist-scalprum/static/{1584.ae3779f0.chunk.js → 1584.1e45e570.chunk.js} +2 -2
- package/dist-scalprum/static/{1584.ae3779f0.chunk.js.map → 1584.1e45e570.chunk.js.map} +1 -1
- package/dist-scalprum/static/1719.246c020d.chunk.js +2 -0
- package/dist-scalprum/static/1719.246c020d.chunk.js.map +1 -0
- package/dist-scalprum/static/{1881.8221c002.chunk.js → 1881.56cde36b.chunk.js} +1 -1
- package/dist-scalprum/static/{1881.8221c002.chunk.js.map → 1881.56cde36b.chunk.js.map} +1 -1
- package/dist-scalprum/static/286.ee43f560.chunk.js +2 -0
- package/dist-scalprum/static/286.ee43f560.chunk.js.map +1 -0
- package/dist-scalprum/static/2952.b54bd390.chunk.js +2 -0
- package/dist-scalprum/static/2952.b54bd390.chunk.js.map +1 -0
- package/dist-scalprum/static/2967.0c2ef90e.chunk.js +2 -0
- package/dist-scalprum/static/2967.0c2ef90e.chunk.js.map +1 -0
- package/dist-scalprum/static/3015.1fe097c2.chunk.js +3 -0
- package/dist-scalprum/static/3015.1fe097c2.chunk.js.LICENSE.txt +9 -0
- package/dist-scalprum/static/3015.1fe097c2.chunk.js.map +1 -0
- package/dist-scalprum/static/{3581.b5b97f08.chunk.js → 3581.ebe5968a.chunk.js} +1 -1
- package/dist-scalprum/static/{3581.b5b97f08.chunk.js.map → 3581.ebe5968a.chunk.js.map} +1 -1
- package/dist-scalprum/static/3657.882640ca.chunk.js +3 -0
- package/dist-scalprum/static/3657.882640ca.chunk.js.LICENSE.txt +8 -0
- package/dist-scalprum/static/3657.882640ca.chunk.js.map +1 -0
- package/dist-scalprum/static/{3897.ef4554b5.chunk.js → 3897.6e9c07c0.chunk.js} +1 -1
- package/dist-scalprum/static/{3897.ef4554b5.chunk.js.map → 3897.6e9c07c0.chunk.js.map} +1 -1
- package/dist-scalprum/static/{3947.ad129ba4.chunk.js → 3947.4f4aa8c2.chunk.js} +1 -1
- package/dist-scalprum/static/{3947.ad129ba4.chunk.js.map → 3947.4f4aa8c2.chunk.js.map} +1 -1
- package/dist-scalprum/static/{3976.e0873210.chunk.js → 3976.e8a8fda2.chunk.js} +2 -2
- package/dist-scalprum/static/{3976.e0873210.chunk.js.map → 3976.e8a8fda2.chunk.js.map} +1 -1
- package/dist-scalprum/static/{4083.488ff7a9.chunk.js → 4083.811c4e7a.chunk.js} +2 -2
- package/dist-scalprum/static/{4083.488ff7a9.chunk.js.map → 4083.811c4e7a.chunk.js.map} +1 -1
- package/dist-scalprum/static/4908.196a4425.chunk.js +2 -0
- package/dist-scalprum/static/{5453.3c20d0a6.chunk.js.map → 4908.196a4425.chunk.js.map} +1 -1
- package/dist-scalprum/static/{5010.6241b64f.chunk.js → 5010.4f67737b.chunk.js} +2 -2
- package/dist-scalprum/static/{5010.6241b64f.chunk.js.map → 5010.4f67737b.chunk.js.map} +1 -1
- package/dist-scalprum/static/{512.f1c51799.chunk.js → 512.d592d164.chunk.js} +1 -1
- package/dist-scalprum/static/{512.f1c51799.chunk.js.map → 512.d592d164.chunk.js.map} +1 -1
- package/dist-scalprum/static/{5289.2e686027.chunk.js → 5289.55069930.chunk.js} +2 -2
- package/dist-scalprum/static/{5289.2e686027.chunk.js.map → 5289.55069930.chunk.js.map} +1 -1
- package/dist-scalprum/static/5605.430f697e.chunk.js +2 -0
- package/dist-scalprum/static/5605.430f697e.chunk.js.map +1 -0
- package/dist-scalprum/static/5978.bf347a09.chunk.js +2 -0
- package/dist-scalprum/static/5978.bf347a09.chunk.js.map +1 -0
- package/dist-scalprum/static/6038.63d1f832.chunk.js +3 -0
- package/dist-scalprum/static/6038.63d1f832.chunk.js.LICENSE.txt +8 -0
- package/dist-scalprum/static/6038.63d1f832.chunk.js.map +1 -0
- package/dist-scalprum/static/{6272.b5645dc2.chunk.js → 6272.3ed14ea4.chunk.js} +1 -1
- package/dist-scalprum/static/{6272.b5645dc2.chunk.js.map → 6272.3ed14ea4.chunk.js.map} +1 -1
- package/dist-scalprum/static/635.f63679a5.chunk.js +3 -0
- package/dist-scalprum/static/635.f63679a5.chunk.js.map +1 -0
- package/dist-scalprum/static/6371.7b57ac27.chunk.js +3 -0
- package/dist-scalprum/static/6371.7b57ac27.chunk.js.LICENSE.txt +9 -0
- package/dist-scalprum/static/6371.7b57ac27.chunk.js.map +1 -0
- package/dist-scalprum/static/{6386.2d20c412.chunk.js → 6386.5922f271.chunk.js} +3 -3
- package/dist-scalprum/static/{6386.2d20c412.chunk.js.map → 6386.5922f271.chunk.js.map} +1 -1
- package/dist-scalprum/static/{6426.bf20c588.chunk.js → 6426.4c18bab5.chunk.js} +1 -1
- package/dist-scalprum/static/{6426.bf20c588.chunk.js.map → 6426.4c18bab5.chunk.js.map} +1 -1
- package/dist-scalprum/static/6777.a2b77ec5.chunk.js +2 -0
- package/dist-scalprum/static/6777.a2b77ec5.chunk.js.map +1 -0
- package/dist-scalprum/static/{6800.ddabed69.chunk.js → 6800.a45da2f4.chunk.js} +2 -2
- package/dist-scalprum/static/{6800.ddabed69.chunk.js.map → 6800.a45da2f4.chunk.js.map} +1 -1
- package/dist-scalprum/static/{6972.e47ec97e.chunk.js → 6972.f22b9446.chunk.js} +1 -1
- package/dist-scalprum/static/{6972.e47ec97e.chunk.js.map → 6972.f22b9446.chunk.js.map} +1 -1
- package/dist-scalprum/static/7005.8190ad95.chunk.js +2 -0
- package/dist-scalprum/static/7005.8190ad95.chunk.js.map +1 -0
- package/dist-scalprum/static/7164.5dc4bc72.chunk.js +2 -0
- package/dist-scalprum/static/7164.5dc4bc72.chunk.js.map +1 -0
- package/dist-scalprum/static/{7266.e760b8c3.chunk.js → 7266.3c4174cc.chunk.js} +1 -1
- package/dist-scalprum/static/{7266.e760b8c3.chunk.js.map → 7266.3c4174cc.chunk.js.map} +1 -1
- package/dist-scalprum/static/7270.d52407cd.chunk.js +2 -0
- package/dist-scalprum/static/7270.d52407cd.chunk.js.map +1 -0
- package/dist-scalprum/static/7717.6f5b9dd7.chunk.js +3 -0
- package/dist-scalprum/static/7717.6f5b9dd7.chunk.js.map +1 -0
- package/dist-scalprum/static/{7791.8f84478d.chunk.js → 7791.ad31cf6d.chunk.js} +2 -2
- package/dist-scalprum/static/{7791.8f84478d.chunk.js.map → 7791.ad31cf6d.chunk.js.map} +1 -1
- package/dist-scalprum/static/{8563.46f1a3e1.chunk.js → 8563.6501eafb.chunk.js} +2 -2
- package/dist-scalprum/static/{8563.46f1a3e1.chunk.js.map → 8563.6501eafb.chunk.js.map} +1 -1
- package/dist-scalprum/static/{9079.b6d5c19c.chunk.js → 9079.2ddaea57.chunk.js} +1 -1
- package/dist-scalprum/static/{9079.b6d5c19c.chunk.js.map → 9079.2ddaea57.chunk.js.map} +1 -1
- package/dist-scalprum/static/9239.1acfe112.chunk.js +2 -0
- package/dist-scalprum/static/9239.1acfe112.chunk.js.map +1 -0
- package/dist-scalprum/static/exposed-KuadrantIcon.08abbb96.chunk.js +3 -0
- package/dist-scalprum/static/exposed-KuadrantIcon.08abbb96.chunk.js.LICENSE.txt +9 -0
- package/dist-scalprum/static/exposed-KuadrantIcon.08abbb96.chunk.js.map +1 -0
- package/dist-scalprum/static/exposed-KuadrantPage.5ae00605.chunk.js +2 -0
- package/dist-scalprum/static/exposed-KuadrantPage.5ae00605.chunk.js.map +1 -0
- package/dist-scalprum/static/exposed-PluginRoot.949381c2.chunk.js +2 -0
- package/dist-scalprum/static/exposed-PluginRoot.949381c2.chunk.js.map +1 -0
- package/package.json +6 -3
- package/dist-scalprum/internal.plugin-kuadrant.b3d35dc8b21ce867aa09.js +0 -2
- package/dist-scalprum/internal.plugin-kuadrant.b3d35dc8b21ce867aa09.js.map +0 -1
- package/dist-scalprum/static/1319.ac195ac2.chunk.js +0 -2
- package/dist-scalprum/static/1319.ac195ac2.chunk.js.map +0 -1
- package/dist-scalprum/static/2967.7c6a34cd.chunk.js +0 -2
- package/dist-scalprum/static/2967.7c6a34cd.chunk.js.map +0 -1
- package/dist-scalprum/static/3118.daee3324.chunk.js +0 -3
- package/dist-scalprum/static/3118.daee3324.chunk.js.map +0 -1
- package/dist-scalprum/static/483.d55d6ab2.chunk.js +0 -2
- package/dist-scalprum/static/483.d55d6ab2.chunk.js.map +0 -1
- package/dist-scalprum/static/5203.3df62d7e.chunk.js +0 -2
- package/dist-scalprum/static/5203.3df62d7e.chunk.js.map +0 -1
- package/dist-scalprum/static/5453.3c20d0a6.chunk.js +0 -2
- package/dist-scalprum/static/6371.f183dddb.chunk.js +0 -3
- package/dist-scalprum/static/6371.f183dddb.chunk.js.map +0 -1
- package/dist-scalprum/static/7005.d548f8f1.chunk.js +0 -2
- package/dist-scalprum/static/7005.d548f8f1.chunk.js.map +0 -1
- package/dist-scalprum/static/7270.301a3c46.chunk.js +0 -2
- package/dist-scalprum/static/7270.301a3c46.chunk.js.map +0 -1
- package/dist-scalprum/static/9051.f095a8a1.chunk.js +0 -2
- package/dist-scalprum/static/9051.f095a8a1.chunk.js.map +0 -1
- package/dist-scalprum/static/9838.589f2156.chunk.js +0 -2
- package/dist-scalprum/static/9838.589f2156.chunk.js.map +0 -1
- package/dist-scalprum/static/exposed-PluginRoot.a8448fcc.chunk.js +0 -2
- package/dist-scalprum/static/exposed-PluginRoot.a8448fcc.chunk.js.map +0 -1
- /package/dist-scalprum/static/{1584.ae3779f0.chunk.js.LICENSE.txt → 1584.1e45e570.chunk.js.LICENSE.txt} +0 -0
- /package/dist-scalprum/static/{4083.488ff7a9.chunk.js.LICENSE.txt → 4083.811c4e7a.chunk.js.LICENSE.txt} +0 -0
- /package/dist-scalprum/static/{5010.6241b64f.chunk.js.LICENSE.txt → 5010.4f67737b.chunk.js.LICENSE.txt} +0 -0
- /package/dist-scalprum/static/{6371.f183dddb.chunk.js.LICENSE.txt → 635.f63679a5.chunk.js.LICENSE.txt} +0 -0
- /package/dist-scalprum/static/{6386.2d20c412.chunk.js.LICENSE.txt → 6386.5922f271.chunk.js.LICENSE.txt} +0 -0
- /package/dist-scalprum/static/{3118.daee3324.chunk.js.LICENSE.txt → 7717.6f5b9dd7.chunk.js.LICENSE.txt} +0 -0
- /package/dist-scalprum/static/{8563.46f1a3e1.chunk.js.LICENSE.txt → 8563.6501eafb.chunk.js.LICENSE.txt} +0 -0
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"static/7005.d548f8f1.chunk.js","mappings":"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","sources":["webpack://internal.plugin-kuadrant/./src/components/FilterPanel/FilterPanel.tsx","webpack://internal.plugin-kuadrant/./src/components/PermissionGate/PermissionGate.tsx","webpack://internal.plugin-kuadrant/./src/components/CreateAPIProductDialog/CreateAPIProductDialog.tsx","webpack://internal.plugin-kuadrant/./src/components/KuadrantPage/ApiProductsPage.tsx"],"sourcesContent":["import React from 'react';\nimport {\n Box,\n Typography,\n Checkbox,\n FormControlLabel,\n FormGroup,\n Divider,\n Button,\n Collapse,\n makeStyles,\n} from '@material-ui/core';\nimport ExpandMoreIcon from '@material-ui/icons/ExpandMore';\nimport ExpandLessIcon from '@material-ui/icons/ExpandLess';\n\nconst useStyles = makeStyles(theme => ({\n root: {\n width: 240,\n minWidth: 240,\n padding: theme.spacing(2),\n borderRight: `1px solid ${theme.palette.divider}`,\n backgroundColor: theme.palette.background.paper,\n height: '100%',\n overflowY: 'auto',\n },\n sectionTitle: {\n fontWeight: 600,\n fontSize: '0.75rem',\n textTransform: 'uppercase',\n letterSpacing: '0.05em',\n color: theme.palette.text.secondary,\n marginBottom: theme.spacing(1),\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'space-between',\n cursor: 'pointer',\n userSelect: 'none',\n },\n filterSection: {\n marginBottom: theme.spacing(2),\n },\n checkbox: {\n padding: theme.spacing(0.5),\n },\n checkboxLabel: {\n fontSize: '0.875rem',\n },\n clearButton: {\n marginTop: theme.spacing(2),\n },\n count: {\n fontSize: '0.75rem',\n color: theme.palette.text.secondary,\n marginLeft: theme.spacing(1),\n },\n}));\n\nexport interface FilterOption {\n value: string;\n label: string;\n count?: number;\n}\n\nexport interface FilterSection {\n id: string;\n title: string;\n options: FilterOption[];\n collapsed?: boolean;\n}\n\nexport interface FilterState {\n [sectionId: string]: string[];\n}\n\ninterface FilterPanelProps {\n sections: FilterSection[];\n filters: FilterState;\n onChange: (filters: FilterState) => void;\n onClear?: () => void;\n}\n\nexport const FilterPanel = ({\n sections,\n filters,\n onChange,\n onClear,\n}: FilterPanelProps) => {\n const classes = useStyles();\n const [collapsedSections, setCollapsedSections] = React.useState<Set<string>>(\n new Set(sections.filter(s => s.collapsed).map(s => s.id)),\n );\n\n const toggleSection = (sectionId: string) => {\n setCollapsedSections(prev => {\n const next = new Set(prev);\n if (next.has(sectionId)) {\n next.delete(sectionId);\n } else {\n next.add(sectionId);\n }\n return next;\n });\n };\n\n const handleCheckboxChange = (sectionId: string, value: string) => {\n const currentValues = filters[sectionId] || [];\n const newValues = currentValues.includes(value)\n ? currentValues.filter(v => v !== value)\n : [...currentValues, value];\n\n onChange({\n ...filters,\n [sectionId]: newValues,\n });\n };\n\n const hasActiveFilters = Object.values(filters).some(\n values => values.length > 0,\n );\n\n const handleClear = () => {\n const clearedFilters: FilterState = {};\n sections.forEach(section => {\n clearedFilters[section.id] = [];\n });\n onChange(clearedFilters);\n onClear?.();\n };\n\n return (\n <Box className={classes.root}>\n <Box display=\"flex\" justifyContent=\"space-between\" alignItems=\"center\" mb={2}>\n <Typography variant=\"subtitle2\">Filters</Typography>\n {hasActiveFilters && (\n <Button\n size=\"small\"\n color=\"primary\"\n onClick={handleClear}\n >\n Clear all\n </Button>\n )}\n </Box>\n\n <Divider />\n\n {sections.map(section => {\n const isCollapsed = collapsedSections.has(section.id);\n const selectedCount = (filters[section.id] || []).length;\n\n return (\n <Box key={section.id} className={classes.filterSection} mt={2}>\n <Box\n className={classes.sectionTitle}\n onClick={() => toggleSection(section.id)}\n >\n <Box display=\"flex\" alignItems=\"center\">\n <span>{section.title}</span>\n {selectedCount > 0 && (\n <span className={classes.count}>({selectedCount})</span>\n )}\n </Box>\n {isCollapsed ? (\n <ExpandMoreIcon fontSize=\"small\" />\n ) : (\n <ExpandLessIcon fontSize=\"small\" />\n )}\n </Box>\n\n <Collapse in={!isCollapsed}>\n <FormGroup>\n {section.options.map(option => (\n <FormControlLabel\n key={option.value}\n control={\n <Checkbox\n checked={(filters[section.id] || []).includes(option.value)}\n onChange={() =>\n handleCheckboxChange(section.id, option.value)\n }\n size=\"small\"\n className={classes.checkbox}\n color=\"primary\"\n />\n }\n label={\n <Box display=\"flex\" alignItems=\"center\">\n <span className={classes.checkboxLabel}>\n {option.label}\n </span>\n {option.count !== undefined && (\n <span className={classes.count}>({option.count})</span>\n )}\n </Box>\n }\n />\n ))}\n </FormGroup>\n </Collapse>\n </Box>\n );\n })}\n </Box>\n );\n};\n","import React from 'react';\nimport { Typography, Box } from '@material-ui/core';\nimport { Progress } from '@backstage/core-components';\nimport { Permission } from '@backstage/plugin-permission-common';\nimport { useKuadrantPermission } from '../../utils/permissions';\n\ninterface PermissionGateProps {\n children: React.ReactNode;\n permission: Permission;\n fallback?: React.ReactNode;\n errorMessage?: string;\n}\n\nexport const PermissionGate = ({ children, permission, fallback, errorMessage }: PermissionGateProps) => {\n const { allowed, loading, error } = useKuadrantPermission(permission);\n\n if (loading) {\n return <Progress />;\n }\n\n if (error) {\n return (\n <Box p={4}>\n <Typography color=\"error\">\n Unable to check permissions: {error.message}\n </Typography>\n <Typography variant=\"body2\" color=\"textSecondary\">\n Please try again or contact your administrator\n </Typography>\n </Box>\n );\n }\n\n if (!allowed) {\n if (fallback) {\n return <>{fallback}</>;\n }\n return (\n <Box p={4}>\n <Typography color=\"textSecondary\">\n {errorMessage || 'You don\\'t have permission to view this page'}\n </Typography>\n <Box mt={1}>\n <Typography variant=\"caption\" color=\"textSecondary\">\n Required permission: {permission.name}\n </Typography>\n </Box>\n </Box>\n );\n }\n\n return <>{children}</>;\n};\n","import React, { useEffect, useState } from 'react';\nimport {\n Dialog,\n DialogTitle,\n DialogContent,\n DialogActions,\n Button,\n TextField,\n Box,\n Typography,\n Chip,\n Grid,\n MenuItem,\n CircularProgress,\n makeStyles,\n FormControl,\n RadioGroup,\n FormControlLabel,\n Radio,\n Tooltip,\n IconButton,\n InputAdornment,\n} from '@material-ui/core';\nimport InfoOutlinedIcon from '@material-ui/icons/InfoOutlined';\nimport AddIcon from '@material-ui/icons/Add';\nimport { useApi } from '@backstage/core-plugin-api';\nimport { kuadrantApiRef } from '../../api';\nimport { Alert } from '@material-ui/lab';\nimport useAsync from 'react-use/lib/useAsync';\nimport { ApiProductPolicies } from '../ApiProductPolicies';\nimport { validateKubernetesName, validateURL } from '../../utils/validation';\nimport { APIProduct } from \"../../types/api-management.ts\";\nimport { Lifecycle } from '../../types/api-management';\nimport { getPolicyForRoute } from '../../utils/policies';\n\nconst useStyles = makeStyles((theme) => ({\n asterisk: {\n color: '#f44336',\n },\n sectionHeader: {\n display: 'flex',\n alignItems: 'center',\n gap: theme.spacing(0.5),\n marginTop: theme.spacing(2),\n marginBottom: theme.spacing(1),\n },\n infoIcon: {\n fontSize: 18,\n color: theme.palette.text.secondary,\n },\n tagChip: {\n marginRight: theme.spacing(0.5),\n marginBottom: theme.spacing(0.5),\n },\n}));\n\ninterface CreateAPIProductDialogProps {\n open: boolean;\n onClose: () => void;\n onSuccess: (productInfo: { namespace: string; name: string; displayName: string }) => void;\n}\n\nexport const CreateAPIProductDialog = ({ open, onClose, onSuccess }: CreateAPIProductDialogProps) => {\n const classes = useStyles();\n const kuadrantApi = useApi(kuadrantApiRef);\n\n const [name, setName] = useState('');\n const [displayName, setDisplayName] = useState('');\n const [description, setDescription] = useState('');\n const [version, setVersion] = useState('v1');\n const [approvalMode, setApprovalMode] = useState<'automatic' | 'manual'>('manual');\n const [publishStatus, setPublishStatus] = useState<'Draft' | 'Published'>('Published');\n const [lifecycle, setLifecycle] = useState<Lifecycle>('production');\n const [tags, setTags] = useState<string[]>([]);\n const [tagInput, setTagInput] = useState('');\n const [selectedHTTPRoute, setSelectedHTTPRoute] = useState('');\n const [contactEmail, setContactEmail] = useState('');\n const [contactTeam, setContactTeam] = useState('');\n const [docsURL, setDocsURL] = useState('');\n const [openAPISpec, setOpenAPISpec] = useState('');\n const [error, setError] = useState('');\n const [creating, setCreating] = useState(false);\n const [httpRoutesRetry, setHttpRoutesRetry] = useState(0);\n const [nameError, setNameError] = useState<string | null>(null);\n const [openAPISpecError, setOpenAPISpecError] = useState<string | null>(null);\n const [routeSearchTerm, setRouteSearchTerm] = useState('');\n const [routeSearchField, setRouteSearchField] = useState<'name' | 'namespace' | 'planpolicy'>('name');\n const {\n value: httpRoutes,\n loading: httpRoutesLoading,\n error: httpRoutesError\n } = useAsync(async () => {\n const data = await kuadrantApi.getHttpRoutes();\n return data.items || [];\n }, [kuadrantApi, open, httpRoutesRetry]);\n\n // load planpolicies with full details to show associated plans\n const {\n value: planPolicies,\n error: planPoliciesError\n } = useAsync(async () => {\n return await kuadrantApi.getPlanPolicies();\n }, [kuadrantApi, open]);\n\n // load authpolicies\n const {\n value: authPolicies,\n error: authPoliciesError\n } = useAsync(async () => {\n return await kuadrantApi.getAuthPolicies();\n }, [kuadrantApi, open]);\n\n // load ratelimitpolicies\n const {\n value: rateLimitPolicies,\n error: rateLimitPoliciesError\n } = useAsync(async () => {\n return await kuadrantApi.getRateLimitPolicies();\n }, [kuadrantApi, open]);\n\n // find planpolicy associated with selected httproute\n const getPlanPolicyForRoute = (routeNamespace: string, routeName: string) => {\n return getPolicyForRoute(planPolicies?.items, routeNamespace, routeName);\n };\n\n // find authpolicy associated with selected httproute\n const getAuthPolicyForRoute = (routeNamespace: string, routeName: string) => {\n return getPolicyForRoute(authPolicies?.items, routeNamespace, routeName);\n };\n\n // find ratelimitpolicy associated with selected httproute\n const getRateLimitPolicyForRoute = (routeNamespace: string, routeName: string) => {\n return getPolicyForRoute(rateLimitPolicies?.items, routeNamespace, routeName);\n };\n\n const selectedRouteInfo = selectedHTTPRoute ? selectedHTTPRoute.split('/') : null;\n const selectedPlanPolicy = selectedRouteInfo\n ? getPlanPolicyForRoute(selectedRouteInfo[0], selectedRouteInfo[1])\n : null;\n const planPolicyAcceptedCondition = selectedPlanPolicy?.status?.conditions?.find(\n (c: any) => c.type === \"Accepted\"\n );\n const selectedAuthPolicy = selectedRouteInfo\n ? getAuthPolicyForRoute(selectedRouteInfo[0], selectedRouteInfo[1])\n : null;\n const authPolicyAcceptedCondition = selectedAuthPolicy?.status?.conditions?.find(\n (c: any) => c.type === \"Accepted\"\n );\n const selectedRateLimitPolicy = selectedRouteInfo\n ? getRateLimitPolicyForRoute(selectedRouteInfo[0], selectedRouteInfo[1])\n : null;\n const rateLimitPolicyAcceptedCondition = selectedRateLimitPolicy?.status?.conditions?.find(\n (c: any) => c.type === \"Accepted\"\n );\n const planPolicyProps = {\n statusCondition: planPolicyAcceptedCondition,\n discoveredPlans: selectedPlanPolicy?.spec.plans,\n }\n const authPolicyProps = {\n namespacedName: {\n namespace: selectedAuthPolicy?.metadata.namespace,\n name: selectedAuthPolicy?.metadata.name,\n },\n statusCondition: authPolicyAcceptedCondition,\n }\n const rateLimitPolicyProps = {\n namespacedName: {\n namespace: selectedRateLimitPolicy?.metadata.namespace,\n name: selectedRateLimitPolicy?.metadata.name,\n },\n statusCondition: rateLimitPolicyAcceptedCondition,\n }\n\n // format tier info for dropdown display\n const formatTierInfo = (policy: any): string => {\n if (!policy?.spec?.plans) return '';\n const tiers = Object.entries(policy.spec.plans)\n .map(([name, plan]: [string, any]) => {\n const limit = plan?.limits?.requests;\n if (!limit) return name;\n return `${name}: ${limit.count}/${limit.period}`;\n })\n .join('; ');\n return tiers ? ` (${tiers})` : '';\n };\n\n // get policy info for a route (for dropdown display)\n const getPolicyInfoForRoute = (routeNamespace: string, routeName: string): string => {\n const policy = getPlanPolicyForRoute(routeNamespace, routeName);\n if (!policy) return 'N/A';\n return `${policy.metadata.name}${formatTierInfo(policy)}`;\n };\n\n useEffect(() => {\n if (open) {\n setNameError(null);\n setOpenAPISpecError(null);\n }\n }, [open]);\n\n // validate handlers\n const handleNameChange = (value: string) => {\n setName(value);\n setNameError(validateKubernetesName(value));\n };\n\n const handleDisplayNameChange = (value: string) => {\n setDisplayName(value);\n // Auto-generate Kubernetes resource name from display name with random hex suffix\n if (!name || name.match(/-[a-f0-9]{6}$/)) {\n const baseName = value.toLowerCase().replace(/[^a-z0-9-]/g, '-').replace(/-+/g, '-').replace(/^-|-$/g, '');\n const randomHex = Math.floor(Math.random() * 16777215).toString(16).padStart(6, '0');\n const autoName = `${baseName}-${randomHex}`;\n setName(autoName);\n setNameError(validateKubernetesName(autoName));\n }\n };\n\n const handleOpenAPISpecChange = (value: string) => {\n setOpenAPISpec(value);\n setOpenAPISpecError(validateURL(value));\n };\n\n const handleAddTag = () => {\n if (tagInput.trim() && !tags.includes(tagInput.trim())) {\n setTags([...tags, tagInput.trim()]);\n setTagInput('');\n }\n };\n\n const handleDeleteTag = (tagToDelete: string) => {\n setTags(tags.filter(tag => tag !== tagToDelete));\n };\n\n const handleClose = () => {\n setName('');\n setDisplayName('');\n setDescription('');\n setVersion('v1');\n setApprovalMode('manual');\n setPublishStatus('Published');\n setLifecycle('production');\n setTags([]);\n setTagInput('');\n setSelectedHTTPRoute('');\n setContactEmail('');\n setContactTeam('');\n setDocsURL('');\n setOpenAPISpec('');\n setError('');\n setNameError(null);\n setOpenAPISpecError(null);\n onClose();\n };\n\n const handleCreate = async () => {\n setError('');\n setCreating(true);\n\n try {\n if (!selectedHTTPRoute) {\n throw new Error('Please select an HTTPRoute');\n }\n\n const [selectedRouteNamespace, selectedRouteName] = selectedHTTPRoute.split('/');\n\n // derive namespace from selected httproute\n const namespace = selectedRouteNamespace;\n\n const apiProduct: APIProduct = {\n apiVersion: 'devportal.kuadrant.io/v1alpha1',\n kind: 'APIProduct',\n metadata: {\n name,\n namespace,\n labels: {\n lifecycle,\n },\n },\n spec: {\n displayName,\n description,\n version,\n approvalMode,\n publishStatus,\n tags,\n targetRef: {\n group: 'gateway.networking.k8s.io',\n kind: 'HTTPRoute',\n name: selectedRouteName,\n namespace: selectedRouteNamespace,\n },\n ...(contactEmail || contactTeam ? {\n contact: {\n ...(contactEmail && { email: contactEmail }),\n ...(contactTeam && { team: contactTeam }),\n },\n } : {}),\n ...(docsURL || openAPISpec ? {\n documentation: {\n ...(docsURL && { docsURL }),\n ...(openAPISpec && { openAPISpecURL: openAPISpec }),\n },\n } : {}),\n },\n };\n\n await kuadrantApi.createApiProduct(apiProduct);\n onSuccess({ namespace, name, displayName });\n handleClose();\n } catch (err) {\n setError(err instanceof Error ? err.message : String(err));\n } finally {\n setCreating(false);\n }\n };\n\n const hasValidationErrors = !!nameError || !!openAPISpecError;\n\n return (\n <Dialog open={open} onClose={handleClose} maxWidth=\"md\" fullWidth>\n <DialogTitle>Create API Product</DialogTitle>\n <DialogContent>\n {error && (\n <Alert severity=\"error\" style={{ marginBottom: 16 }}>\n {error}\n </Alert>\n )}\n {httpRoutesError && (\n <Alert severity=\"error\" style={{ marginBottom: 16 }}>\n <strong>Failed to load HTTPRoutes:</strong> {httpRoutesError.message}\n <Box mt={1}>\n <Button\n size=\"small\"\n variant=\"outlined\"\n onClick={() => setHttpRoutesRetry(prev => prev + 1)}\n >\n Retry\n </Button>\n </Box>\n </Alert>\n )}\n\n {planPoliciesError && (\n <Alert severity=\"warning\" style={{ marginBottom: 16 }}>\n <strong>Failed to load PlanPolicies:</strong> {planPoliciesError.message}\n <Typography variant=\"body2\" style={{ marginTop: 8 }}>\n You can still create the API Product, but plan information may be incomplete.\n </Typography>\n </Alert>\n )}\n {authPoliciesError && (\n <Alert severity=\"warning\" style={{ marginBottom: 16 }}>\n <strong>Failed to load AuthPolicies:</strong> {authPoliciesError.message}\n </Alert>\n )}\n {rateLimitPoliciesError && (\n <Alert severity=\"warning\" style={{ marginBottom: 16 }}>\n <strong>Failed to load RateLimitPolicies:</strong> {rateLimitPoliciesError.message}\n </Alert>\n )}\n {/* API product info section */}\n <Box className={classes.sectionHeader}>\n <Typography variant=\"subtitle1\"><strong>API product info</strong></Typography>\n </Box>\n <Grid container spacing={2}>\n <Grid item xs={6}>\n <TextField\n fullWidth\n label=\"API product name\"\n value={displayName}\n onChange={e => handleDisplayNameChange(e.target.value)}\n placeholder=\"My API\"\n helperText=\"Display name for your API product (shown to users)\"\n margin=\"normal\"\n required\n disabled={creating}\n InputLabelProps={{\n classes: {\n asterisk: classes.asterisk,\n },\n }}\n />\n </Grid>\n <Grid item xs={6}>\n <TextField\n fullWidth\n label=\"Kubernetes resource name\"\n value={name}\n onChange={e => handleNameChange(e.target.value)}\n placeholder=\"my-api\"\n helperText={nameError || \"Auto-generated from product name. Only lowercase, numbers, and hyphens allowed.\"}\n error={!!nameError}\n margin=\"normal\"\n required\n disabled={creating}\n InputLabelProps={{\n classes: {\n asterisk: classes.asterisk,\n },\n }}\n />\n </Grid>\n <Grid item xs={6}>\n <TextField\n fullWidth\n label=\"Version\"\n value={version}\n onChange={e => setVersion(e.target.value)}\n placeholder=\"v1\"\n helperText=\"Give a version to your API product\"\n margin=\"normal\"\n required\n disabled={creating}\n InputLabelProps={{\n classes: {\n asterisk: classes.asterisk,\n },\n }}\n />\n </Grid>\n <Grid item xs={6}>\n <TextField\n fullWidth\n label=\"Tag\"\n value={tagInput}\n onChange={e => setTagInput(e.target.value)}\n onKeyPress={e => {\n if (e.key === 'Enter') {\n e.preventDefault();\n handleAddTag();\n }\n }}\n placeholder=\"Add tag\"\n helperText=\"Add a tag to your API product\"\n margin=\"normal\"\n disabled={creating}\n InputProps={{\n endAdornment: tagInput ? (\n <InputAdornment position=\"end\">\n <IconButton size=\"small\" onClick={handleAddTag} disabled={creating}>\n <AddIcon fontSize=\"small\" />\n </IconButton>\n </InputAdornment>\n ) : undefined,\n }}\n />\n </Grid>\n {tags.length > 0 && (\n <Grid item xs={12}>\n <Box display=\"flex\" flexWrap=\"wrap\">\n {tags.map(tag => (\n <Chip\n key={tag}\n label={tag}\n onDelete={creating ? undefined : () => handleDeleteTag(tag)}\n size=\"small\"\n className={classes.tagChip}\n disabled={creating}\n />\n ))}\n </Box>\n </Grid>\n )}\n <Grid item xs={12}>\n <TextField\n fullWidth\n label=\"Description\"\n value={description}\n onChange={e => setDescription(e.target.value)}\n placeholder=\"API description\"\n margin=\"normal\"\n multiline\n rows={2}\n required\n disabled={creating}\n InputLabelProps={{\n classes: {\n asterisk: classes.asterisk,\n },\n }}\n />\n </Grid>\n </Grid>\n\n {/* Add API and Associate route section */}\n <Box className={classes.sectionHeader}>\n <Typography variant=\"subtitle1\"><strong>Add API and Associate route</strong></Typography>\n <Tooltip title=\"Register an existing API and associate HTTPRoute for your API product\">\n <InfoOutlinedIcon className={classes.infoIcon} />\n </Tooltip>\n </Box>\n <Grid container spacing={2}>\n <Grid item xs={12}>\n <TextField\n fullWidth\n label=\"OpenAPI Spec URL\"\n value={openAPISpec}\n onChange={e => handleOpenAPISpecChange(e.target.value)}\n placeholder=\"https://api.example.com/openapi.json\"\n helperText={openAPISpecError || \"Enter the full path to your API spec file\"}\n error={!!openAPISpecError}\n margin=\"normal\"\n required\n disabled={creating}\n InputLabelProps={{\n classes: {\n asterisk: classes.asterisk,\n },\n }}\n />\n </Grid>\n <Grid item xs={12}>\n <TextField\n fullWidth\n label=\"Documentation URL\"\n value={docsURL}\n onChange={e => setDocsURL(e.target.value)}\n placeholder=\"https://docs.example.com/api\"\n helperText=\"Link to external documentation for this API\"\n margin=\"normal\"\n disabled={creating}\n />\n </Grid>\n <Grid item xs={12}>\n <TextField\n fullWidth\n select\n label=\"HTTPRoute\"\n value={selectedHTTPRoute}\n onChange={e => setSelectedHTTPRoute(e.target.value)}\n margin=\"normal\"\n required\n helperText={\n httpRoutesError\n ? \"Unable to load HTTPRoutes. Please retry.\"\n : \"Select an HTTPRoute. APIProduct will be created in the same namespace.\"\n }\n error={!!httpRoutesError}\n disabled={httpRoutesLoading || creating || !!httpRoutesError}\n InputLabelProps={{\n classes: {\n asterisk: classes.asterisk,\n },\n }}\n SelectProps={{\n 'data-testid': 'httproute-select',\n MenuProps: {\n PaperProps: {\n style: { maxHeight: 400 },\n },\n anchorOrigin: {\n vertical: 'bottom',\n horizontal: 'left',\n },\n transformOrigin: {\n vertical: 'top',\n horizontal: 'left',\n },\n getContentAnchorEl: null,\n },\n } as any}\n >\n {/* Search bar inside dropdown */}\n <Box px={2} pt={1} pb={1} style={{ position: 'sticky', top: 0, zIndex: 1 }}>\n <TextField\n fullWidth\n size=\"small\"\n placeholder=\"Search...\"\n value={routeSearchTerm}\n onChange={e => setRouteSearchTerm(e.target.value)}\n onKeyDown={e => e.stopPropagation()}\n onClick={e => e.stopPropagation()}\n InputProps={{\n endAdornment: (\n <InputAdornment position=\"end\">\n <TextField\n select\n size=\"small\"\n value={routeSearchField}\n onChange={e => setRouteSearchField(e.target.value as 'name' | 'namespace' | 'planpolicy')}\n onKeyDown={e => e.stopPropagation()}\n onClick={e => e.stopPropagation()}\n style={{ minWidth: 120 }}\n variant=\"standard\"\n >\n <MenuItem value=\"name\">Name</MenuItem>\n <MenuItem value=\"namespace\">Namespace</MenuItem>\n <MenuItem value=\"planpolicy\">PlanPolicy</MenuItem>\n </TextField>\n </InputAdornment>\n ),\n }}\n />\n </Box>\n {httpRoutesLoading && (\n <MenuItem value=\"\">Loading...</MenuItem>\n )}\n {httpRoutesError && (\n <MenuItem value=\"\">Error loading routes</MenuItem>\n )}\n {!httpRoutesLoading && !httpRoutesError && httpRoutes && httpRoutes.length === 0 && (\n <MenuItem value=\"\">No HTTPRoutes available</MenuItem>\n )}\n {!httpRoutesLoading && !httpRoutesError && httpRoutes && httpRoutes\n .filter((route: any) => {\n if (!routeSearchTerm) return true;\n const routeNs = route.metadata.namespace;\n const routeName = route.metadata.name;\n const policyInfo = getPolicyInfoForRoute(routeNs, routeName);\n const searchLower = routeSearchTerm.toLowerCase();\n\n switch (routeSearchField) {\n case 'name':\n return routeName.toLowerCase().includes(searchLower);\n case 'namespace':\n return routeNs.toLowerCase().includes(searchLower);\n case 'planpolicy':\n return policyInfo.toLowerCase().includes(searchLower);\n default:\n return true;\n }\n })\n .map((route: any) => {\n const routeNs = route.metadata.namespace;\n const routeName = route.metadata.name;\n const policyInfo = getPolicyInfoForRoute(routeNs, routeName);\n return (\n <MenuItem\n key={`${routeNs}/${routeName}`}\n value={`${routeNs}/${routeName}`}\n >\n <Box>\n <Typography variant=\"body1\">{routeName}</Typography>\n <Typography variant=\"caption\" color=\"textSecondary\">\n Associated PlanPolicy: {policyInfo}\n </Typography>\n </Box>\n </MenuItem>\n );\n })}\n </TextField>\n </Grid>\n </Grid>\n\n {/* HTTPRoute policies section */}\n {selectedHTTPRoute && (\n <>\n <Box className={classes.sectionHeader}>\n <Typography variant=\"subtitle1\"><strong>HTTPRoute policies</strong></Typography>\n <Tooltip title=\"Shows the associated policies and rate limit tiers for the selected HTTPRoute\">\n <InfoOutlinedIcon className={classes.infoIcon} />\n </Tooltip>\n </Box>\n <ApiProductPolicies\n planPolicy={planPolicyProps}\n authPolicy={authPolicyProps}\n rateLimitPolicy={rateLimitPolicyProps}\n includeTopMargin={false}\n />\n </>\n )}\n\n <Box className={classes.sectionHeader}>\n <Typography variant=\"subtitle1\"><strong>Lifecycle and Visibility</strong></Typography>\n <Tooltip title=\"Control the lifecycle state and catalog visibility of this API product\">\n <InfoOutlinedIcon className={classes.infoIcon} />\n </Tooltip>\n </Box>\n <Grid container spacing={2}>\n <Grid item xs={6}>\n <TextField\n fullWidth\n select\n label=\"Lifecycle\"\n value={lifecycle}\n onChange={e => setLifecycle(e.target.value as Lifecycle)}\n margin=\"normal\"\n helperText=\"API lifecycle state\"\n disabled={creating}\n >\n <MenuItem value=\"experimental\">Experimental</MenuItem>\n <MenuItem value=\"production\">Production</MenuItem>\n <MenuItem value=\"deprecated\">Deprecated</MenuItem>\n <MenuItem value=\"retired\">Retired</MenuItem>\n </TextField>\n </Grid>\n <Grid item xs={6}>\n <TextField\n fullWidth\n select\n label=\"Publish Status\"\n value={publishStatus}\n onChange={e => setPublishStatus(e.target.value as 'Draft' | 'Published')}\n margin=\"normal\"\n helperText=\"Controls catalog visibility (Draft = hidden from consumers)\"\n disabled={creating}\n >\n <MenuItem value=\"Draft\">Draft</MenuItem>\n <MenuItem value=\"Published\">Published</MenuItem>\n </TextField>\n </Grid>\n </Grid>\n\n {/* API Key approval section */}\n <Box className={classes.sectionHeader}>\n <Typography variant=\"subtitle1\"><strong>API Key approval</strong></Typography>\n <Tooltip title=\"Choose how API key requests are handled for this product\">\n <InfoOutlinedIcon className={classes.infoIcon} />\n </Tooltip>\n </Box>\n <FormControl component=\"fieldset\" disabled={creating}>\n <RadioGroup\n row\n value={approvalMode}\n onChange={e => setApprovalMode(e.target.value as 'automatic' | 'manual')}\n >\n <FormControlLabel\n value=\"manual\"\n control={<Radio color=\"primary\" />}\n label={\n <Box>\n <Typography variant=\"body2\">Need manual approval</Typography>\n <Typography variant=\"caption\" color=\"textSecondary\">\n Requires approval for requesting this API\n </Typography>\n </Box>\n }\n />\n <FormControlLabel\n value=\"automatic\"\n control={<Radio color=\"primary\" />}\n label={\n <Box>\n <Typography variant=\"body2\">Automatic</Typography>\n <Typography variant=\"caption\" color=\"textSecondary\">\n Keys are created without need to be approved\n </Typography>\n </Box>\n }\n />\n </RadioGroup>\n </FormControl>\n </DialogContent>\n <DialogActions>\n <Button onClick={handleClose} disabled={creating}>Cancel</Button>\n <Button\n onClick={handleCreate}\n color=\"primary\"\n variant=\"contained\"\n disabled={creating || !name || !displayName || !description || !selectedHTTPRoute || hasValidationErrors}\n startIcon={creating ? <CircularProgress size={16} color=\"inherit\" /> : undefined}\n >\n {creating ? 'Creating...' : 'Create'}\n </Button>\n </DialogActions>\n </Dialog>\n );\n};\n","import React, { useState, useMemo, useCallback } from \"react\";\nimport {\n Typography,\n Box,\n Chip,\n Button,\n IconButton,\n CircularProgress,\n makeStyles,\n} from \"@material-ui/core\";\nimport AddIcon from \"@material-ui/icons/Add\";\nimport DeleteIcon from \"@material-ui/icons/Delete\";\nimport EditIcon from \"@material-ui/icons/Edit\";\nimport VpnKeyIcon from \"@material-ui/icons/VpnKey\";\nimport LockIcon from \"@material-ui/icons/Lock\";\nimport { FilterPanel, FilterSection, FilterState } from \"../FilterPanel\";\nimport {\n Header,\n Page,\n Content,\n SupportButton,\n ResponseErrorPanel,\n Link,\n Table,\n TableColumn,\n} from \"@backstage/core-components\";\nimport useAsync from \"react-use/lib/useAsync\";\nimport {\n useApi,\n alertApiRef,\n identityApiRef,\n} from \"@backstage/core-plugin-api\";\nimport { catalogApiRef } from \"@backstage/plugin-catalog-react\";\nimport {kuadrantApiRef, KuadrantList} from \"../../api\";\nimport { PermissionGate } from \"../PermissionGate\";\nimport { CreateAPIProductDialog } from \"../CreateAPIProductDialog\";\nimport {\n kuadrantApiProductCreatePermission,\n kuadrantApiProductDeleteOwnPermission,\n kuadrantApiProductDeleteAllPermission,\n kuadrantApiProductUpdateOwnPermission,\n kuadrantApiProductUpdateAllPermission,\n kuadrantApiProductListPermission,\n kuadrantPlanPolicyListPermission,\n} from \"../../permissions\";\nimport { useKuadrantPermission } from \"../../utils/permissions\";\nimport { EditAPIProductDialog } from \"../EditAPIProductDialog\";\nimport { ConfirmDeleteDialog } from \"../ConfirmDeleteDialog\";\nimport { getLifecycleChipStyle } from \"../../utils/styles\";\nimport emptyStateIllustration from \"../../assets/empty-state-illustration.png\";\nimport {APIProduct, PlanPolicy} from \"../../types/api-management.ts\";\n\nconst useStyles = makeStyles((theme) => ({\n container: {\n display: \"flex\",\n height: \"100%\",\n minHeight: 400,\n },\n tableContainer: {\n flex: 1,\n overflow: \"auto\",\n padding: 10,\n },\n emptyState: {\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n padding: theme.spacing(6),\n minHeight: 400,\n },\n emptyStateContent: {\n display: \"flex\",\n alignItems: \"center\",\n gap: theme.spacing(6),\n maxWidth: 900,\n },\n emptyStateText: {\n flex: 1,\n },\n emptyStateTitle: {\n marginBottom: theme.spacing(2),\n },\n emptyStateDescription: {\n marginBottom: theme.spacing(3),\n color: theme.palette.text.secondary,\n },\n emptyStateImage: {\n maxWidth: 400,\n height: \"auto\",\n },\n}));\n\nconst ResourceList = () => {\n const classes = useStyles();\n const kuadrantApi = useApi(kuadrantApiRef);\n const alertApi = useApi(alertApiRef);\n const identityApi = useApi(identityApiRef);\n const catalogApi = useApi(catalogApiRef);\n const [userEntityRef, setUserEntityRef] = useState<string>(\"\");\n const [createDialogOpen, setCreateDialogOpen] = useState(false);\n const [editDialogOpen, setEditDialogOpen] = useState(false);\n const [refreshTrigger, setRefreshTrigger] = useState(0);\n const [deleteDialogOpen, setDeleteDialogOpen] = useState(false);\n const [apiProductToDelete, setApiProductToDelete] = useState<{\n namespace: string;\n name: string;\n } | null>(null);\n const [apiProductToEdit, setApiProductToEdit] = useState<{\n namespace: string;\n name: string;\n } | null>(null);\n const [deleting, setDeleting] = useState(false);\n const [deleteStats, setDeleteStats] = useState<{\n requests: number;\n secrets: number;\n } | null>(null);\n const [filters, setFilters] = useState<FilterState>({\n status: [],\n lifecycle: [],\n policy: [],\n route: [],\n namespace: [],\n tags: [],\n authentication: [],\n });\n\n const {\n allowed: canCreateApiProduct,\n loading: createPermissionLoading,\n error: createPermissionError,\n } = useKuadrantPermission(kuadrantApiProductCreatePermission);\n\n const {\n allowed: canDeleteOwnApiProduct,\n loading: deleteOwnPermissionLoading,\n } = useKuadrantPermission(kuadrantApiProductDeleteOwnPermission);\n\n const {\n allowed: canDeleteAllApiProducts,\n loading: deleteAllPermissionLoading,\n error: deletePermissionError,\n } = useKuadrantPermission(kuadrantApiProductDeleteAllPermission);\n\n const { allowed: canUpdateOwnApiProduct } = useKuadrantPermission(\n kuadrantApiProductUpdateOwnPermission,\n );\n\n const { allowed: canUpdateAllApiProducts } = useKuadrantPermission(\n kuadrantApiProductUpdateAllPermission,\n );\n\n const deletePermissionLoading =\n deleteOwnPermissionLoading || deleteAllPermissionLoading;\n\n const {\n allowed: canListPlanPolicies,\n loading: planPolicyPermissionLoading,\n error: planPolicyPermissionError,\n } = useKuadrantPermission(kuadrantPlanPolicyListPermission);\n\n useAsync(async () => {\n const identity = await identityApi.getBackstageIdentity();\n setUserEntityRef(identity.userEntityRef);\n }, [identityApi]);\n\n const {\n value: apiProducts,\n loading: apiProductsLoading,\n error: apiProductsError,\n } = useAsync(async (): Promise<KuadrantList<APIProduct>> => {\n return kuadrantApi.getApiProducts();\n }, [kuadrantApi, refreshTrigger]);\n\n const {\n value: planPolicies,\n loading: planPoliciesLoading,\n error: planPoliciesError,\n } = useAsync(async (): Promise<KuadrantList<PlanPolicy>> => {\n // skip fetch if user doesn't have permission\n if (!canListPlanPolicies) {\n return { items: [] };\n }\n return kuadrantApi.getPlanPolicies();\n }, [kuadrantApi, refreshTrigger, canListPlanPolicies]);\n\n // fetch catalog entities synced from apiproducts to get lifecycle\n const { value: catalogEntities } = useAsync(async () => {\n const response = await catalogApi.getEntities({\n filter: {\n kind: 'API',\n 'metadata.labels.kuadrant.io/synced': 'true',\n },\n fields: ['metadata.name', 'spec.lifecycle'],\n });\n return response.items;\n }, [catalogApi, refreshTrigger]);\n\n // build name -> lifecycle lookup from catalog entities\n const lifecycleByName = useMemo(() => {\n const map = new Map<string, string>();\n if (catalogEntities) {\n for (const entity of catalogEntities) {\n const lifecycle = (entity.spec as any)?.lifecycle;\n if (lifecycle) {\n map.set(entity.metadata.name, lifecycle);\n }\n }\n }\n return map;\n }, [catalogEntities]);\n\n const getLifecycle = useCallback((product: APIProduct): string | undefined => {\n return lifecycleByName.get(product.metadata.name);\n }, [lifecycleByName]);\n\n // helper to find policy for a given route\n const getPolicyForProduct = useCallback((product: APIProduct): string | null => {\n if (!planPolicies?.items) return null;\n const targetRef = product.spec?.targetRef;\n if (!targetRef) return null;\n\n const policy = planPolicies.items.find((pp: PlanPolicy) => {\n const ref = (pp as any).spec.targetRef;\n return (\n ref?.kind === \"HTTPRoute\" &&\n ref?.name === targetRef.name &&\n (!ref?.namespace || ref?.namespace === (targetRef.namespace || product.metadata.namespace))\n );\n });\n return policy?.metadata.name || null;\n }, [planPolicies]);\n\n // helper to get auth schemes for a product\n const getAuthSchemes = useCallback((product: APIProduct): string[] => {\n const authSchemes = product.status?.discoveredAuthScheme?.authentication || {};\n const schemeObjects = Object.values(authSchemes);\n const schemes: string[] = [];\n\n if (schemeObjects.some((scheme: any) => scheme.hasOwnProperty(\"apiKey\"))) {\n schemes.push(\"API Key\");\n }\n if (schemeObjects.some((scheme: any) => scheme.hasOwnProperty(\"jwt\"))) {\n schemes.push(\"OIDC\");\n }\n if (schemes.length === 0) {\n schemes.push(\"Unknown\");\n }\n return schemes;\n }, []);\n\n const loading =\n apiProductsLoading ||\n planPoliciesLoading ||\n createPermissionLoading ||\n deletePermissionLoading ||\n planPolicyPermissionLoading;\n const error = apiProductsError || planPoliciesError;\n const permissionError =\n createPermissionError || deletePermissionError || planPolicyPermissionError;\n\n const allProducts = useMemo(() => {\n const products = apiProducts?.items || [];\n\n // API consumers (users without create/update permissions) should only see Published products\n // API owners can see all products (Draft and Published)\n if (!canCreateApiProduct && !canUpdateOwnApiProduct && !canUpdateAllApiProducts) {\n return products.filter((p: APIProduct) => {\n const publishStatus = p.spec?.publishStatus || 'Draft';\n return publishStatus === 'Published';\n });\n }\n\n return products;\n }, [apiProducts, canCreateApiProduct, canUpdateOwnApiProduct, canUpdateAllApiProducts]);\n\n const filterSections: FilterSection[] = useMemo(() => {\n const statusCounts = { Draft: 0, Published: 0 };\n const lifecycleCounts = new Map<string, number>();\n const policyCounts = new Map<string, number>();\n const routeCounts = new Map<string, number>();\n const namespaceCounts = new Map<string, number>();\n const tagCounts = new Map<string, number>();\n const authCounts = new Map<string, number>();\n\n allProducts.forEach((p: APIProduct) => {\n const status = p.spec?.publishStatus || \"Draft\";\n statusCounts[status as keyof typeof statusCounts]++;\n\n const lifecycle = getLifecycle(p);\n if (lifecycle) {\n lifecycleCounts.set(lifecycle, (lifecycleCounts.get(lifecycle) || 0) + 1);\n }\n\n const policy = getPolicyForProduct(p) || \"N/A\";\n policyCounts.set(policy, (policyCounts.get(policy) || 0) + 1);\n\n const route = p.spec?.targetRef?.name || \"unknown\";\n routeCounts.set(route, (routeCounts.get(route) || 0) + 1);\n\n const ns = p.metadata.namespace;\n namespaceCounts.set(ns, (namespaceCounts.get(ns) || 0) + 1);\n\n const tags = p.spec?.tags || [];\n tags.forEach((tag: string) => {\n tagCounts.set(tag, (tagCounts.get(tag) || 0) + 1);\n });\n\n const authSchemes = getAuthSchemes(p);\n authSchemes.forEach((scheme: string) => {\n authCounts.set(scheme, (authCounts.get(scheme) || 0) + 1);\n });\n });\n\n const sections: FilterSection[] = [\n {\n id: \"status\",\n title: \"Publish Status\",\n options: [\n { value: \"Draft\", label: \"Draft\", count: statusCounts.Draft },\n { value: \"Published\", label: \"Published\", count: statusCounts.Published },\n ],\n },\n {\n id: \"lifecycle\",\n title: \"Lifecycle\",\n options: Array.from(lifecycleCounts.entries()).map(([state, count]) => ({\n value: state,\n label: state.charAt(0).toUpperCase() + state.slice(1),\n count,\n })),\n },\n {\n id: \"authentication\",\n title: \"Authentication\",\n options: Array.from(authCounts.entries()).map(([scheme, count]) => ({\n value: scheme,\n label: scheme,\n count,\n })),\n },\n {\n id: \"route\",\n title: \"Route\",\n options: Array.from(routeCounts.entries()).map(([name, count]) => ({\n value: name,\n label: name,\n count,\n })),\n collapsed: routeCounts.size > 5,\n },\n {\n id: \"namespace\",\n title: \"Namespace\",\n options: Array.from(namespaceCounts.entries()).map(([ns, count]) => ({\n value: ns,\n label: ns,\n count,\n })),\n collapsed: namespaceCounts.size > 5,\n },\n {\n id: \"tags\",\n title: \"Tags\",\n options: Array.from(tagCounts.entries()).map(([tag, count]) => ({\n value: tag,\n label: tag,\n count,\n })),\n collapsed: tagCounts.size > 5,\n },\n ];\n\n // only show policy filter if user can list planpolicies\n if (canListPlanPolicies) {\n sections.splice(2, 0, {\n id: \"policy\",\n title: \"Policy\",\n options: Array.from(policyCounts.entries()).map(([name, count]) => ({\n value: name,\n label: name,\n count,\n })),\n collapsed: policyCounts.size > 5,\n });\n }\n\n return sections;\n }, [allProducts, getPolicyForProduct, getAuthSchemes, getLifecycle, canListPlanPolicies]);\n\n const filteredProducts = useMemo(() => {\n return allProducts.filter((p: APIProduct) => {\n if (filters.status.length > 0) {\n const status = p.spec?.publishStatus || \"Draft\";\n if (!filters.status.includes(status)) return false;\n }\n\n if (filters.lifecycle && filters.lifecycle.length > 0) {\n const lifecycle = getLifecycle(p);\n if (!lifecycle || !filters.lifecycle.includes(lifecycle)) return false;\n }\n\n if (filters.authentication.length > 0) {\n const authSchemes = getAuthSchemes(p);\n if (!filters.authentication.some((a: string) => authSchemes.includes(a))) return false;\n }\n\n if (filters.policy.length > 0) {\n const policy = getPolicyForProduct(p) || \"N/A\";\n if (!filters.policy.includes(policy)) return false;\n }\n\n if (filters.route.length > 0) {\n const route = p.spec?.targetRef?.name || \"unknown\";\n if (!filters.route.includes(route)) return false;\n }\n\n if (filters.namespace.length > 0) {\n if (!filters.namespace.includes(p.metadata.namespace)) return false;\n }\n\n if (filters.tags.length > 0) {\n const tags = p.spec?.tags || [];\n if (!filters.tags.some((t: string) => tags.includes(t))) return false;\n }\n\n return true;\n });\n }, [allProducts, filters, getPolicyForProduct, getAuthSchemes, getLifecycle]);\n\n const handleCreateSuccess = (productInfo: { namespace: string; name: string; displayName: string }) => {\n setRefreshTrigger((prev) => prev + 1);\n alertApi.post({\n message: `\"${productInfo.displayName}\" created successfully`,\n severity: \"success\",\n display: \"transient\",\n });\n };\n\n const handleEditClick = (namespace: string, name: string) => {\n setApiProductToEdit({ namespace, name });\n setEditDialogOpen(true);\n };\n\n const handleEditSuccess = () => {\n setRefreshTrigger((prev) => prev + 1);\n const productName = apiProductToEdit?.name || \"API Product\";\n alertApi.post({\n message: `\"${productName}\" updated successfully`,\n severity: \"success\",\n display: \"transient\",\n });\n };\n\n const handleDeleteClick = async (namespace: string, name: string) => {\n setApiProductToDelete({ namespace, name });\n setDeleteStats(null);\n\n try {\n const data = await kuadrantApi.getRequestsByNamespace(namespace);\n const related = (data.items || []).filter(\n (r: any) =>\n r.spec.apiName === name && r.spec.apiNamespace === namespace,\n );\n const approved = related.filter(\n (r: any) => r.status?.phase === \"Approved\",\n ).length;\n setDeleteStats({ requests: related.length, secrets: approved });\n } catch (err) {\n const errorMessage =\n err instanceof Error ? err.message : \"unknown error occurred\";\n alertApi.post({\n message: `Failed to delete access request: ${errorMessage}`,\n severity: \"error\",\n display: \"transient\",\n });\n } finally {\n setDeleteDialogOpen(true);\n }\n\n };\n\n const handleDeleteConfirm = async () => {\n if (!apiProductToDelete) return;\n\n setDeleting(true);\n try {\n await kuadrantApi.deleteApiProduct(\n apiProductToDelete.namespace,\n apiProductToDelete.name,\n );\n\n const deletedName = apiProductToDelete?.name || \"API Product\";\n setRefreshTrigger((prev) => prev + 1);\n alertApi.post({\n message: `\"${deletedName}\" deleted successfully`,\n severity: \"success\",\n display: \"transient\",\n });\n } catch (err) {\n const errorMessage =\n err instanceof Error ? err.message : \"unknown error occurred\";\n alertApi.post({\n message: `Failed to delete API Product: ${errorMessage}`,\n severity: \"error\",\n display: \"transient\",\n });\n } finally {\n setDeleting(false);\n setDeleteDialogOpen(false);\n setApiProductToDelete(null);\n }\n };\n\n const handleDeleteCancel = () => {\n setDeleteDialogOpen(false);\n setApiProductToDelete(null);\n };\n\n const handlePublishToggle = async (row: any) => {\n const namespace = row.metadata.namespace;\n const name = row.metadata.name;\n const displayName = row.spec?.displayName || name;\n const currentStatus = row.spec?.publishStatus || \"Draft\";\n const newStatus = currentStatus === \"Published\" ? \"Draft\" : \"Published\";\n // prevent publishing retired APIs\n if (newStatus === \"Published\" && getLifecycle(row) === \"retired\") {\n alertApi.post({\n message: `Cannot publish a retired API product. Please change the lifecycle status first.`,\n severity: \"error\",\n display: \"transient\",\n });\n return;\n }\n\n const productPatch: Partial<APIProduct> = {\n // @ts-ignore partial obj\n spec: {\n publishStatus: newStatus\n },\n }\n\n try {\n await kuadrantApi.updateApiProduct(namespace, name, productPatch);\n\n setRefreshTrigger((prev) => prev + 1);\n alertApi.post({\n message: `\"${displayName}\" ${newStatus === \"Published\" ? \"published\" : \"unpublished\"} successfully`,\n severity: \"success\",\n display: \"transient\",\n });\n } catch (err) {\n const errorMessage =\n err instanceof Error ? err.message : \"unknown error occurred\";\n alertApi.post({\n message: `Failed to update publish status: ${errorMessage}`,\n severity: \"error\",\n display: \"transient\",\n });\n }\n };\n\n const columns: TableColumn[] = [\n {\n title: \"Name\",\n field: \"spec.displayName\",\n render: (row: any) => {\n const displayName = row.spec?.displayName ?? row.metadata.name;\n return (\n <Link to={`/kuadrant/api-products/${row.metadata.namespace}/${row.metadata.name}`}>\n <strong>{displayName}</strong>\n </Link>\n );\n },\n customFilterAndSearch: (term, row: any) => {\n const displayName = row.spec?.displayName || row.metadata.name || \"\";\n return displayName.toLowerCase().includes(term.toLowerCase());\n },\n },\n {\n title: \"Version\",\n field: \"spec.version\",\n render: (row: any) => row.spec?.version || \"-\",\n },\n {\n title: \"Route\",\n field: \"spec.targetRef.name\",\n render: (row: any) => row.spec?.targetRef?.name || \"-\",\n },\n // only show policy column if user can list planpolicies\n ...(canListPlanPolicies\n ? [\n {\n title: \"Policy\",\n field: \"policy\",\n render: (row: any) => getPolicyForProduct(row) || \"N/A\",\n },\n ]\n : []),\n {\n title: \"Tags\",\n field: \"spec.tags\",\n render: (row: any) => {\n const tags = row.spec?.tags || [];\n if (tags.length === 0) return \"-\";\n return (\n <Box display=\"flex\" style={{ gap: 4, flexWrap: \"wrap\" }}>\n {tags.map((tag: string) => (\n <Chip key={tag} label={tag} size=\"small\" variant=\"outlined\" />\n ))}\n </Box>\n );\n },\n },\n {\n title: \"Status\",\n field: \"spec.publishStatus\",\n render: (row: any) => {\n const status = row.spec?.publishStatus || \"Draft\";\n return (\n <Chip\n label={status}\n size=\"small\"\n color={status === \"Published\" ? \"primary\" : \"default\"}\n />\n );\n },\n },\n {\n title: \"Lifecycle\",\n render: (row: any) => {\n const lifecycle = getLifecycle(row);\n if (!lifecycle) return \"-\";\n return (\n <Chip\n label={lifecycle.charAt(0).toUpperCase() + lifecycle.slice(1)}\n size=\"small\"\n style={getLifecycleChipStyle(lifecycle)}\n />\n );\n },\n },\n {\n title: \"Authentication\",\n field: \"status.discoveredAuthScheme\",\n render: (row: any) => {\n const authSchemes =\n row.status?.discoveredAuthScheme?.authentication || {};\n const schemeObjects = Object.values(authSchemes);\n\n const hasApiKey = schemeObjects.some((scheme: any) =>\n scheme.hasOwnProperty(\"apiKey\"),\n );\n const hasJwt = schemeObjects.some((scheme: any) =>\n scheme.hasOwnProperty(\"jwt\"),\n );\n\n if (!hasApiKey && !hasJwt) {\n return (\n <Typography variant=\"body2\" style={{ fontStyle: \"italic\" }}>\n unknown\n </Typography>\n );\n }\n\n return (\n <Box display=\"flex\" style={{ gap: 4 }}>\n {hasApiKey && (\n <Chip\n icon={<VpnKeyIcon />}\n label=\"API Key\"\n size=\"small\"\n color=\"primary\"\n />\n )}\n {hasJwt && (\n <Chip\n icon={<LockIcon />}\n label=\"OIDC\"\n size=\"small\"\n color=\"secondary\"\n />\n )}\n </Box>\n );\n },\n },\n {\n title: \"Namespace\",\n field: \"metadata.namespace\",\n },\n {\n title: \"Actions\",\n field: \"actions\",\n filtering: false,\n render: (row: any) => {\n const owner = row.metadata?.annotations?.[\"backstage.io/owner\"];\n const isOwner = owner === userEntityRef;\n const canEdit =\n canUpdateAllApiProducts || (canUpdateOwnApiProduct && isOwner);\n const canDelete =\n canDeleteAllApiProducts || (canDeleteOwnApiProduct && isOwner);\n const isPublished = row.spec?.publishStatus === \"Published\";\n\n return (\n <Box display=\"flex\" alignItems=\"center\" style={{ gap: 4 }}>\n {canEdit && (\n <Button\n size=\"small\"\n color=\"primary\"\n onClick={() => handlePublishToggle(row)}\n style={{ marginRight: 4, textTransform: \"none\" }}\n >\n {isPublished ? \"Unpublish\" : \"Publish\"}\n </Button>\n )}\n {canEdit && (\n <IconButton\n size=\"small\"\n onClick={() =>\n handleEditClick(row.metadata.namespace, row.metadata.name)\n }\n title=\"Edit API Product\"\n >\n <EditIcon fontSize=\"small\" />\n </IconButton>\n )}\n {canDelete && (\n <IconButton\n size=\"small\"\n onClick={() =>\n handleDeleteClick(row.metadata.namespace, row.metadata.name)\n }\n title=\"Delete API Product\"\n >\n <DeleteIcon fontSize=\"small\" />\n </IconButton>\n )}\n </Box>\n );\n },\n },\n ];\n\n return (\n <Page themeId=\"tool\">\n <Header\n title=\"API Products\"\n subtitle=\"Manage API products for Kubernetes\"\n >\n <SupportButton>Manage API products and plan policies</SupportButton>\n </Header>\n <Content>\n {loading && (\n <Box\n display=\"flex\"\n flexDirection=\"column\"\n alignItems=\"center\"\n justifyContent=\"center\"\n minHeight={300}\n >\n <CircularProgress />\n <Typography variant=\"h6\" style={{ marginTop: 16 }}>\n Loading data...\n </Typography>\n <Typography variant=\"body2\" color=\"textSecondary\">\n Preparing your data... This should only take a moment.\n </Typography>\n </Box>\n )}\n {error && <ResponseErrorPanel error={error} />}\n {permissionError && (\n <Box p={2}>\n <Typography color=\"error\">\n unable to check permissions: {permissionError.message}\n </Typography>\n <Typography variant=\"body2\" color=\"textSecondary\">\n permission:{\" \"}\n {createPermissionError\n ? \"kuadrant.apiproduct.create\"\n : deletePermissionError\n ? \"kuadrant.apiproduct.delete\"\n : planPolicyPermissionError\n ? \"kuadrant.planpolicy.list\"\n : \"unknown\"}\n </Typography>\n <Typography variant=\"body2\" color=\"textSecondary\">\n please try again or contact your administrator\n </Typography>\n </Box>\n )}\n {!loading && !error && !permissionError && allProducts.length === 0 && (\n <Box className={classes.emptyState}>\n <Box className={classes.emptyStateContent}>\n <Box className={classes.emptyStateText}>\n <Typography variant=\"h4\" className={classes.emptyStateTitle}>\n API Product\n </Typography>\n <Typography\n variant=\"body1\"\n className={classes.emptyStateDescription}\n >\n Create API product by registering existing API, associate\n route and policy\n </Typography>\n {canCreateApiProduct && (\n <Button\n variant=\"contained\"\n color=\"primary\"\n startIcon={<AddIcon />}\n onClick={() => setCreateDialogOpen(true)}\n >\n Create API Product\n </Button>\n )}\n </Box>\n <img\n src={emptyStateIllustration}\n alt=\"API Product illustration\"\n className={classes.emptyStateImage}\n />\n </Box>\n </Box>\n )}\n {!loading && !error && !permissionError && allProducts.length > 0 && (\n <Box className={classes.container}>\n <FilterPanel\n sections={filterSections}\n filters={filters}\n onChange={setFilters}\n />\n <Box className={classes.tableContainer}>\n <Box display=\"flex\" justifyContent=\"flex-end\" mb={2}>\n {canCreateApiProduct && (\n <Button\n variant=\"contained\"\n color=\"primary\"\n size=\"small\"\n startIcon={<AddIcon />}\n onClick={() => setCreateDialogOpen(true)}\n >\n Create API Product\n </Button>\n )}\n </Box>\n {filteredProducts.length === 0 ? (\n <Box p={4} textAlign=\"center\">\n <Typography variant=\"body1\" color=\"textSecondary\">\n No API products match the selected filters.\n </Typography>\n </Box>\n ) : (\n <Table\n options={{\n paging: filteredProducts.length > 10,\n pageSize: 20,\n search: true,\n filtering: false,\n debounceInterval: 300,\n toolbar: true,\n emptyRowsWhenPaging: false,\n }}\n columns={columns}\n data={filteredProducts}\n />\n )}\n </Box>\n </Box>\n )}\n <CreateAPIProductDialog\n open={createDialogOpen}\n onClose={() => setCreateDialogOpen(false)}\n onSuccess={handleCreateSuccess}\n />\n <EditAPIProductDialog\n open={editDialogOpen}\n onClose={() => setEditDialogOpen(false)}\n onSuccess={handleEditSuccess}\n namespace={apiProductToEdit?.namespace || \"\"}\n name={apiProductToEdit?.name || \"\"}\n />\n <ConfirmDeleteDialog\n open={deleteDialogOpen}\n title=\"Delete API Product\"\n description={\n deleteStats\n ? `Deleting \"${apiProductToDelete?.name}\" will also remove:\n\n• ${deleteStats.requests} API Key(s)\n• ${deleteStats.secrets} API Key Secret(s)\n\nThis action cannot be undone.`\n : `Deleting \"${apiProductToDelete?.name}\" will also remove all associated API Keys and Secrets.\nThis action cannot be undone.`\n }\n confirmText={apiProductToDelete?.name}\n severity=\"high\"\n deleting={deleting}\n onConfirm={handleDeleteConfirm}\n onCancel={handleDeleteCancel}\n />\n </Content>\n </Page>\n );\n};\n\nexport const ApiProductsPage = () => {\n return (\n <PermissionGate\n permission={kuadrantApiProductListPermission}\n errorMessage=\"you don't have permission to view the Kuadrant page\"\n >\n <ResourceList />\n </PermissionGate>\n );\n};\n"],"names":["useStyles","makeStyles","theme","root","width","minWidth","padding","spacing","borderRight","palette","divider","backgroundColor","background","paper","height","overflowY","sectionTitle","fontWeight","fontSize","textTransform","letterSpacing","color","text","secondary","marginBottom","display","alignItems","justifyContent","cursor","userSelect","filterSection","checkbox","checkboxLabel","clearButton","marginTop","count","marginLeft","FilterPanel","sections","filters","onChange","onClear","classes","collapsedSections","setCollapsedSections","React","Set","filter","s","collapsed","map","id","hasActiveFilters","Object","values","some","length","Box","className","mb","Typography","variant","Button","size","onClick","clearedFilters","forEach","section","Divider","isCollapsed","has","selectedCount","mt","toggleSection","sectionId","prev","next","delete","add","span","title","ExpandMoreIcon","ExpandLessIcon","Collapse","in","FormGroup","options","option","FormControlLabel","control","Checkbox","checked","includes","value","currentValues","newValues","v","handleCheckboxChange","label","undefined","PermissionGate","children","permission","fallback","errorMessage","allowed","loading","error","useKuadrantPermission","Progress","p","message","name","asterisk","sectionHeader","gap","infoIcon","tagChip","marginRight","CreateAPIProductDialog","open","onClose","onSuccess","selectedPlanPolicy","selectedAuthPolicy","selectedRateLimitPolicy","kuadrantApi","useApi","kuadrantApiRef","setName","useState","displayName","setDisplayName","description","setDescription","version","setVersion","approvalMode","setApprovalMode","publishStatus","setPublishStatus","lifecycle","setLifecycle","tags","setTags","tagInput","setTagInput","selectedHTTPRoute","setSelectedHTTPRoute","contactEmail","setContactEmail","contactTeam","setContactTeam","docsURL","setDocsURL","openAPISpec","setOpenAPISpec","setError","creating","setCreating","httpRoutesRetry","setHttpRoutesRetry","nameError","setNameError","openAPISpecError","setOpenAPISpecError","routeSearchTerm","setRouteSearchTerm","routeSearchField","setRouteSearchField","httpRoutes","httpRoutesLoading","httpRoutesError","useAsync","async","getHttpRoutes","items","planPolicies","planPoliciesError","getPlanPolicies","authPolicies","authPoliciesError","getAuthPolicies","rateLimitPolicies","rateLimitPoliciesError","getRateLimitPolicies","getPlanPolicyForRoute","routeNamespace","routeName","getPolicyForRoute","selectedRouteInfo","split","planPolicyAcceptedCondition","status","conditions","find","c","type","authPolicyAcceptedCondition","getRateLimitPolicyForRoute","rateLimitPolicyAcceptedCondition","planPolicyProps","statusCondition","discoveredPlans","spec","plans","authPolicyProps","namespacedName","namespace","metadata","rateLimitPolicyProps","getPolicyInfoForRoute","policy","tiers","entries","plan","limit","limits","requests","period","join","formatTierInfo","useEffect","handleAddTag","trim","handleClose","hasValidationErrors","Dialog","maxWidth","fullWidth","DialogTitle","DialogContent","Alert","severity","style","strong","Grid","container","item","xs","TextField","e","match","autoName","toLowerCase","replace","Math","floor","random","toString","padStart","validateKubernetesName","handleDisplayNameChange","target","placeholder","helperText","margin","required","disabled","InputLabelProps","handleNameChange","onKeyPress","key","preventDefault","InputProps","endAdornment","InputAdornment","position","IconButton","AddIcon","flexWrap","tag","Chip","onDelete","handleDeleteTag","tagToDelete","multiline","rows","Tooltip","InfoOutlinedIcon","handleOpenAPISpecChange","validateURL","select","SelectProps","MenuProps","PaperProps","maxHeight","anchorOrigin","vertical","horizontal","transformOrigin","getContentAnchorEl","px","pt","pb","top","zIndex","onKeyDown","stopPropagation","MenuItem","route","routeNs","policyInfo","searchLower","ApiProductPolicies","planPolicy","authPolicy","rateLimitPolicy","includeTopMargin","FormControl","component","RadioGroup","row","Radio","DialogActions","Error","selectedRouteNamespace","selectedRouteName","apiProduct","apiVersion","kind","labels","targetRef","group","contact","email","team","documentation","openAPISpecURL","createApiProduct","err","String","startIcon","CircularProgress","minHeight","tableContainer","flex","overflow","emptyState","emptyStateContent","emptyStateText","emptyStateTitle","emptyStateDescription","emptyStateImage","ResourceList","alertApi","alertApiRef","identityApi","identityApiRef","catalogApi","catalogApiRef","userEntityRef","setUserEntityRef","createDialogOpen","setCreateDialogOpen","editDialogOpen","setEditDialogOpen","refreshTrigger","setRefreshTrigger","deleteDialogOpen","setDeleteDialogOpen","apiProductToDelete","setApiProductToDelete","apiProductToEdit","setApiProductToEdit","deleting","setDeleting","deleteStats","setDeleteStats","setFilters","authentication","canCreateApiProduct","createPermissionLoading","createPermissionError","kuadrantApiProductCreatePermission","canDeleteOwnApiProduct","deleteOwnPermissionLoading","kuadrantApiProductDeleteOwnPermission","canDeleteAllApiProducts","deleteAllPermissionLoading","deletePermissionError","kuadrantApiProductDeleteAllPermission","canUpdateOwnApiProduct","kuadrantApiProductUpdateOwnPermission","canUpdateAllApiProducts","kuadrantApiProductUpdateAllPermission","deletePermissionLoading","canListPlanPolicies","planPolicyPermissionLoading","planPolicyPermissionError","kuadrantPlanPolicyListPermission","identity","getBackstageIdentity","apiProducts","apiProductsLoading","apiProductsError","getApiProducts","planPoliciesLoading","catalogEntities","getEntities","fields","lifecycleByName","useMemo","Map","entity","set","getLifecycle","useCallback","product","get","getPolicyForProduct","pp","ref","getAuthSchemes","authSchemes","discoveredAuthScheme","schemeObjects","schemes","scheme","hasOwnProperty","push","permissionError","allProducts","products","filterSections","statusCounts","Draft","Published","lifecycleCounts","policyCounts","routeCounts","namespaceCounts","tagCounts","authCounts","ns","Array","from","state","charAt","toUpperCase","slice","splice","filteredProducts","a","t","columns","field","render","Link","to","customFilterAndSearch","term","getLifecycleChipStyle","hasApiKey","hasJwt","icon","VpnKeyIcon","LockIcon","fontStyle","filtering","isOwner","annotations","canEdit","canDelete","isPublished","newStatus","post","productPatch","updateApiProduct","handlePublishToggle","handleEditClick","EditIcon","related","getRequestsByNamespace","r","apiName","apiNamespace","approved","phase","secrets","handleDeleteClick","DeleteIcon","Page","themeId","Header","subtitle","SupportButton","Content","flexDirection","ResponseErrorPanel","img","src","emptyStateIllustration","alt","textAlign","Table","paging","pageSize","search","debounceInterval","toolbar","emptyRowsWhenPaging","data","productInfo","EditAPIProductDialog","productName","ConfirmDeleteDialog","confirmText","onConfirm","deleteApiProduct","deletedName","onCancel","ApiProductsPage","kuadrantApiProductListPermission"],"sourceRoot":""}
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
"use strict";(self.webpackChunkinternal_plugin_kuadrant=self.webpackChunkinternal_plugin_kuadrant||[]).push([[7270],{12229:(e,t,a)=>{a.d(t,{Z:()=>g});var n=a(31085),s=a(95478),r=a.n(s),i=a(10394),l=a(72501),o=a(64947),c=a(37197),d=a(69621),u=a(12981),p=a(86901),m=a(69076),h=a(58837),A=a(6924),f=a(23164);const x=(0,h.A)(e=>({root:{width:240,minWidth:240,padding:e.spacing(2),borderRight:`1px solid ${e.palette.divider}`,backgroundColor:e.palette.background.paper,height:"100%",overflowY:"auto"},sectionTitle:{fontWeight:600,fontSize:"0.75rem",textTransform:"uppercase",letterSpacing:"0.05em",color:e.palette.text.secondary,marginBottom:e.spacing(1),display:"flex",alignItems:"center",justifyContent:"space-between",cursor:"pointer",userSelect:"none"},filterSection:{marginBottom:e.spacing(2)},checkbox:{padding:e.spacing(.5)},checkboxLabel:{fontSize:"0.875rem"},clearButton:{marginTop:e.spacing(2)},count:{fontSize:"0.75rem",color:e.palette.text.secondary,marginLeft:e.spacing(1)}})),g=({sections:e,filters:t,onChange:a,onClear:s})=>{const h=x(),[g,v]=r().useState(new Set(e.filter(e=>e.collapsed).map(e=>e.id))),y=Object.values(t).some(e=>e.length>0);return(0,n.jsxs)(i.A,{className:h.root,children:[(0,n.jsxs)(i.A,{display:"flex",justifyContent:"space-between",alignItems:"center",mb:2,children:[(0,n.jsx)(l.A,{variant:"subtitle2",children:"Filters"}),y&&(0,n.jsx)(o.A,{size:"small",color:"primary",onClick:()=>{const t={};e.forEach(e=>{t[e.id]=[]}),a(t),null==s||s()},children:"Clear all"})]}),(0,n.jsx)(c.A,{}),e.map(e=>{const s=g.has(e.id),r=(t[e.id]||[]).length;return(0,n.jsxs)(i.A,{className:h.filterSection,mt:2,children:[(0,n.jsxs)(i.A,{className:h.sectionTitle,onClick:()=>{return t=e.id,void v(e=>{const a=new Set(e);return a.has(t)?a.delete(t):a.add(t),a});var t},children:[(0,n.jsxs)(i.A,{display:"flex",alignItems:"center",children:[(0,n.jsx)("span",{children:e.title}),r>0&&(0,n.jsxs)("span",{className:h.count,children:["(",r,")"]})]}),s?(0,n.jsx)(A.A,{fontSize:"small"}):(0,n.jsx)(f.A,{fontSize:"small"})]}),(0,n.jsx)(d.A,{in:!s,children:(0,n.jsx)(u.A,{children:e.options.map(s=>(0,n.jsx)(p.A,{control:(0,n.jsx)(m.A,{checked:(t[e.id]||[]).includes(s.value),onChange:()=>((e,n)=>{const s=t[e]||[],r=s.includes(n)?s.filter(e=>e!==n):[...s,n];a({...t,[e]:r})})(e.id,s.value),size:"small",className:h.checkbox,color:"primary"}),label:(0,n.jsxs)(i.A,{display:"flex",alignItems:"center",children:[(0,n.jsx)("span",{className:h.checkboxLabel,children:s.label}),void 0!==s.count&&(0,n.jsxs)("span",{className:h.count,children:["(",s.count,")"]})]})},s.value))})})]},e.id)})]})}},16397:(e,t,a)=>{a.d(t,{e:()=>y});var n=a(31085),s=a(95478),r=a(76891),i=a(61477),l=a(46805),o=a(10394),c=a(72501),d=a(95061),u=a(48543),p=a(81215),m=a(26343),h=a(16249),A=a(93453),f=a(64947),x=a(78467),g=a(22097),v=a(64047);const y=({open:e,onClose:t,onSuccess:a,request:y,availablePlans:j})=>{const b=(0,g.useApi)(v.s),[k,w]=(0,s.useState)(""),[P,S]=(0,s.useState)(""),[C,I]=(0,s.useState)(!1),[q,R]=(0,s.useState)("");(0,s.useEffect)(()=>{e&&y&&(w(y.spec.planTier||""),S(y.spec.useCase||""),R(""))},[e,y]);const $=()=>{C||(R(""),t())};return(0,n.jsxs)(r.A,{open:e,onClose:$,maxWidth:"sm",fullWidth:!0,children:[(0,n.jsx)(i.A,{children:"Edit API Key"}),(0,n.jsxs)(l.A,{children:[q&&(0,n.jsx)(o.A,{mb:2,p:2,bgcolor:"error.main",color:"error.contrastText",borderRadius:1,children:(0,n.jsx)(c.A,{variant:"body2",children:q})}),(0,n.jsxs)(d.A,{fullWidth:!0,margin:"normal",children:[(0,n.jsx)(u.A,{children:"Tier"}),(0,n.jsx)(p.A,{value:k,onChange:e=>w(e.target.value),disabled:C,children:j.map(e=>{const t=Object.entries(e.limits||{}).map(([e,t])=>`${t} per ${e}`).join(", ");return(0,n.jsxs)(m.A,{value:e.tier,children:[e.tier," ",t?`(${t})`:""]},e.tier)})})]}),(0,n.jsx)(h.A,{label:"Use Case",placeholder:"Describe how you plan to use this API",multiline:!0,rows:3,fullWidth:!0,margin:"normal",value:P,onChange:e=>S(e.target.value),disabled:C,helperText:"Explain your intended use of this API for admin review"})]}),(0,n.jsxs)(A.A,{children:[(0,n.jsx)(f.A,{onClick:$,disabled:C,children:"Cancel"}),(0,n.jsx)(f.A,{onClick:async()=>{if(k){R(""),I(!0);try{const e={spec:{planTier:k,useCase:P.trim()}};await b.updateRequest(y.metadata.name,y.metadata.namespace,e),a(),t()}catch(e){console.error("Error updating API key request:",e),R(e instanceof Error?e.message:"Unknown error occurred")}finally{I(!1)}}else R("Please select a tier")},color:"primary",variant:"contained",disabled:!k||C,startIcon:C?(0,n.jsx)(x.A,{size:16,color:"inherit"}):void 0,children:C?"Saving...":"Save Changes"})]})]})}},37270:(e,t,a)=>{a.r(t),a.d(t,{MyApiKeysPage:()=>Z});var n=a(31085),s=a(95478),r=a(289),i=a(15831),l=a(45210),o=a(46681),c=a(49634),d=a(37725),u=a(42367),p=a(25010),m=a(22097),h=a(64047),A=a(91638),f=a(58837),x=a(10394),g=a(72501),v=a(67720),y=a(71677),j=a(29365),b=a(78467),k=a(64947),w=a(37757),P=a(26343),S=a(76891),C=a(61477),I=a(46805),q=a(93453),R=a(4387),$=a(95061),T=a(48543),z=a(81215),E=a(51253),N=a(16249);const W=({open:e,onClose:t,onSuccess:a})=>{var r;const i=(0,m.useApi)(m.configApiRef),l=(0,m.useApi)(m.fetchApiRef),o=(0,m.useApi)(m.alertApiRef),c=(0,m.useApi)(m.identityApiRef),d=i.getString("backend.baseUrl"),[u,p]=(0,s.useState)(""),[h,f]=(0,s.useState)(""),[x,v]=(0,s.useState)(""),[y,j]=(0,s.useState)(!1),{value:w,loading:R}=(0,A.A)(async()=>{if(!e)return[];const t=await l.fetch(`${d}/api/kuadrant/apiproducts`);if(!t.ok)throw new Error("Failed to fetch API products");return((await t.json()).items||[]).filter(e=>{var t;return"Published"===(null===(t=e.spec)||void 0===t?void 0:t.publishStatus)})},[d,l,e]),{value:W}=(0,A.A)(async()=>`${(await c.getBackstageIdentity()).userEntityRef.split("/")[1]||"unknown"}@example.com`,[c]),M=null==w?void 0:w.find(e=>`${e.metadata.namespace}/${e.metadata.name}`===u),B=(null==M||null===(r=M.status)||void 0===r?void 0:r.discoveredPlans)||[],K=()=>{p(""),f(""),v(""),t()};return(0,n.jsxs)(S.A,{open:e,onClose:K,maxWidth:"sm",fullWidth:!0,children:[(0,n.jsx)(C.A,{children:"Request API key"}),(0,n.jsxs)(I.A,{children:[(0,n.jsx)(g.A,{variant:"body2",color:"textSecondary",children:"Submit your request to generate an API key."}),(0,n.jsxs)($.A,{fullWidth:!0,margin:"normal",disabled:y||R,children:[(0,n.jsx)(T.A,{id:"api-select-label",required:!0,children:"API"}),(0,n.jsx)(z.A,{labelId:"api-select-label",value:u,onChange:e=>{p(e.target.value),f("")},disabled:y||R,"data-testid":"api-select",children:R?(0,n.jsx)(P.A,{disabled:!0,children:"Loading..."}):null==w?void 0:w.map(e=>(0,n.jsx)(P.A,{value:`${e.metadata.namespace}/${e.metadata.name}`,children:e.metadata.name},`${e.metadata.namespace}/${e.metadata.name}`))}),(0,n.jsx)(E.A,{children:"Select one API. Please submit separate requests for multiple APIs."})]}),(0,n.jsxs)($.A,{fullWidth:!0,margin:"normal",disabled:y||!u,required:!0,children:[(0,n.jsx)(T.A,{id:"tier-select-label",children:"Tiers"}),(0,n.jsx)(z.A,{labelId:"tier-select-label",value:h,onChange:e=>f(e.target.value),disabled:y||!u,"data-testid":"tier-select",children:u?0===B.length?(0,n.jsx)(P.A,{disabled:!0,children:"No tiers available"}):B.map(e=>{const t=Object.entries(e.limits||{}).map(([e,t])=>`${t} per ${e}`).join(", ");return(0,n.jsxs)(P.A,{value:e.tier,children:[e.tier," ",t?`(${t})`:""]},e.tier)}):(0,n.jsx)(P.A,{disabled:!0,children:"Select an API first"})}),(0,n.jsx)(E.A,{children:"Select an API to view available tiers."})]}),(0,n.jsx)(N.A,{label:"Use case",placeholder:"Briefly describe your specific use case of using this API key",multiline:!0,rows:2,fullWidth:!0,margin:"normal",value:x,onChange:e=>v(e.target.value),disabled:y,inputProps:{"data-testid":"usecase-input"}})]}),(0,n.jsxs)(q.A,{children:[(0,n.jsx)(k.A,{onClick:K,disabled:y,"data-testid":"cancel-button",children:"Cancel"}),(0,n.jsx)(k.A,{onClick:async()=>{if(!u||!h)return;const[e,t]=u.split("/");j(!0);try{const n=await l.fetch(`${d}/api/kuadrant/requests`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({apiProductName:t,namespace:e,planTier:h,useCase:x.trim()||"",userEmail:W||"unknown"})});if(!n.ok){let a;try{a=await n.json()}catch{a={error:`Server returned ${n.status} ${n.statusText}`}}console.error("Backend error response:",{status:n.status,statusText:n.statusText,errorData:a,requestBody:{apiProductName:t,namespace:e,planTier:h,useCase:x.trim()||"",userEmail:W||"unknown"}});const s=a.error||a.message||`Server returned ${n.status}`;let r=s;if(s.includes("spec.requestedBy.email"))r="Invalid email format. Please contact your administrator to update your profile email.";else if(s.includes("is invalid:")){const e=s.match(/is invalid: (.+?)(?:\s+\(|$)/);e&&(r=`Validation error: ${e[1]}`)}else 403===n.status?r="You do not have permission to request access to this API.":404===n.status?r="The selected API or tier was not found.":n.status>=500&&(r=`Server error: ${s}`);throw new Error(r)}o.post({message:"API key requested successfully",severity:"success",display:"transient"}),K(),a()}catch(e){const t=e instanceof Error?e.message:"unknown error occurred";console.error("Failed to create API key request:",{error:e,selectedApi:u,selectedTier:h,userEmail:W}),o.post({message:`Failed to request API key: ${t}`,severity:"error",display:"permanent"})}finally{j(!1)}},color:"primary",variant:"contained",disabled:!u||!h||y,startIcon:y?(0,n.jsx)(b.A,{size:16,color:"inherit"}):void 0,"data-testid":"submit-button",children:y?"Submitting...":"Request"})]})]})};var M=a(32269),B=a(61524),K=a(99594),D=a(77225),F=a(39590),L=a(16397),U=a(63221),_=a(12229),O=a(46299);const V=(0,f.A)(e=>({container:{display:"flex",height:"100%",minHeight:400},tableContainer:{flex:1,overflow:"auto",padding:10},useCasePanel:{padding:e.spacing(2),backgroundColor:e.palette.background.default},useCaseLabel:{fontWeight:600,marginBottom:e.spacing(1),color:e.palette.text.secondary,textTransform:"uppercase",fontSize:"0.75rem"},rejectedBanner:{backgroundColor:e.palette.error.light,border:`1px solid ${e.palette.error.main}`,borderRadius:e.shape.borderRadius,padding:e.spacing(1.5,2),marginBottom:e.spacing(2),display:"flex",alignItems:"center",gap:e.spacing(1)}})),Y=({request:e})=>{var t,a;const s=V(),r="Rejected"===(null===(t=e.status)||void 0===t?void 0:t.phase),i=(null===(a=e.spec.apiProductRef)||void 0===a?void 0:a.name)||"unknown";return(0,n.jsxs)(x.A,{className:s.useCasePanel,onClick:e=>e.stopPropagation(),children:[r&&(0,n.jsxs)(x.A,{className:s.rejectedBanner,children:[(0,n.jsx)(D.A,{color:"error",fontSize:"small"}),(0,n.jsxs)(g.A,{variant:"body2",children:["This API key was rejected."," ",(0,n.jsx)(d.N_,{to:`/catalog/default/api/${i}/api-keys`,children:"Request a new API key"})]})]}),(0,n.jsx)(g.A,{className:s.useCaseLabel,children:"Use Case"}),(0,n.jsx)(g.A,{variant:"body2",children:e.spec.useCase||"No use case provided"})]})},H=()=>{var e,t;const a=V(),r=(0,c.useNavigate)(),i=(0,m.useApi)(h.s),l=(0,m.useApi)(m.alertApiRef),[o,f]=(0,s.useState)(!1),[$,T]=(0,s.useState)(new Set),[z,E]=(0,s.useState)(null),[N,H]=(0,s.useState)(null),[Z,J]=(0,s.useState)({open:!1,request:null,plans:[]}),[X,G]=(0,s.useState)(0),[Q,ee]=(0,s.useState)(null),[te,ae]=(0,s.useState)({open:!1,request:null}),[ne,se]=(0,s.useState)(new Map),[re,ie]=(0,s.useState)(new Set),[le,oe]=(0,s.useState)(new Set),[ce,de]=(0,s.useState)(!1),[ue,pe]=(0,s.useState)(null),[me,he]=(0,s.useState)(new Set),[Ae,fe]=(0,s.useState)({status:[],apiProduct:[],tier:[]}),{value:xe,loading:ge,error:ve}=(0,A.A)(async()=>{const[e,t]=await Promise.all([i.getRequests(),i.getApiProducts()]),a=e.items||[],n=t.items||[],s=new Map;return n.forEach(e=>{var t;const a=`${e.metadata.namespace}/${e.metadata.name}`,n=(null===(t=e.metadata.annotations)||void 0===t?void 0:t["backstage.io/owner"])||"unknown";s.set(a,n)}),{requests:a,products:n,ownerMap:s}},[i,X]),ye=(0,s.useMemo)(()=>(null==xe?void 0:xe.requests)?xe.requests.filter(e=>!me.has(e.metadata.name)):[],[null==xe?void 0:xe.requests,me]),je=(0,s.useMemo)(()=>{const e={Approved:0,Pending:0,Rejected:0},t=new Map,a=new Map;return ye.forEach(n=>{var s,r;const i=(null===(s=n.status)||void 0===s?void 0:s.phase)||"Pending";e[i]++;const l=(null===(r=n.spec.apiProductRef)||void 0===r?void 0:r.name)||"unknown";t.set(l,(t.get(l)||0)+1);const o=n.spec.planTier||"unknown";a.set(o,(a.get(o)||0)+1)}),[{id:"status",title:"Status",options:[{value:"Approved",label:"Active",count:e.Approved},{value:"Pending",label:"Pending",count:e.Pending},{value:"Rejected",label:"Rejected",count:e.Rejected}]},{id:"apiProduct",title:"API Product",options:Array.from(t.entries()).map(([e,t])=>({value:e,label:e,count:t})),collapsed:t.size>5},{id:"tier",title:"Tier",options:Array.from(a.entries()).map(([e,t])=>({value:e,label:e.charAt(0).toUpperCase()+e.slice(1),count:t}))}]},[ye]),be=(0,s.useMemo)(()=>ye.filter(e=>{if(Ae.status.length>0){var t;const a=(null===(t=e.status)||void 0===t?void 0:t.phase)||"Pending";if(!Ae.status.includes(a))return!1}if(Ae.apiProduct.length>0){var a;const t=(null===(a=e.spec.apiProductRef)||void 0===a?void 0:a.name)||"unknown";if(!Ae.apiProduct.includes(t))return!1}if(Ae.tier.length>0){const t=e.spec.planTier||"unknown";if(!Ae.tier.includes(t))return!1}return!0}),[ye,Ae]),ke=e=>{T(t=>{const a=new Set(t);return a.has(e)?a.delete(e):a.add(e),a})},we=()=>{E(null),H(null)},Pe=async()=>{if(!N)return;const e=N;we();try{var t,a;const n=null===(t=e.spec.apiProductRef)||void 0===t?void 0:t.name,s=e.metadata.namespace,r=(null===(a=(await i.getApiProduct(s,n)).status)||void 0===a?void 0:a.discoveredPlans)||[];J({open:!0,request:e,plans:r})}catch(e){console.error("Error fetching plans:",e),J({open:!0,request:N,plans:[]});const t=e instanceof Error?e.message:"unknown error occurred";l.post({message:`Failed to fetch Plans. ${t}`,severity:"error",display:"transient"})}},Se=()=>{if(!N)return;const e=N;we(),ae({open:!0,request:e})},Ce=[{title:"API Product",field:"spec.apiProductRef.name",render:e=>{var t;const a=(null===(t=e.spec.apiProductRef)||void 0===t?void 0:t.name)||"unknown";return(0,n.jsx)(d.N_,{to:`/catalog/default/api/${a}/api-keys`,children:(0,n.jsx)("strong",{children:a})})}},{title:"Owner",field:"owner",render:e=>{var t,a;const s=`${e.metadata.namespace}/${null===(t=e.spec.apiProductRef)||void 0===t?void 0:t.name}`,r=((null==xe||null===(a=xe.ownerMap)||void 0===a?void 0:a.get(s))||"unknown").replace(/^user:default\//,"");return(0,n.jsx)(g.A,{variant:"body2",children:r})}},{title:"Status",field:"status.phase",render:e=>{var t;const a=(null===(t=e.status)||void 0===t?void 0:t.phase)||"Pending",s="Approved"===a?"Active":a;return(0,n.jsx)(v.A,{label:s,size:"small",style:(0,O.g9)(a)})}},{title:"Tier",field:"spec.planTier",render:e=>(0,n.jsx)(v.A,{label:e.spec.planTier,size:"small",variant:"outlined"})},{title:"API Key",field:"status.secretRef",filtering:!1,render:e=>{var t,a,s,r;if("Approved"!==(null===(t=e.status)||void 0===t?void 0:t.phase))return(0,n.jsx)(g.A,{variant:"body2",color:"textSecondary",children:"-"});const i=`${e.metadata.namespace}/${e.metadata.name}`,o=null===(s=e.status)||void 0===s||null===(a=s.secretRef)||void 0===a?void 0:a.name,c=$.has(e.metadata.name),d=re.has(i),u=ne.get(i),p=!1!==(null===(r=e.status)||void 0===r?void 0:r.canReadSecret),m=le.has(i)||!p;return o?m&&!u?(0,n.jsx)(y.Ay,{title:"This API key has already been viewed and cannot be retrieved again",children:(0,n.jsxs)(x.A,{display:"flex",alignItems:"center",children:[(0,n.jsx)(g.A,{variant:"body2",color:"textSecondary",style:{fontFamily:"monospace",marginRight:8},children:"Already viewed"}),(0,n.jsx)(B.A,{fontSize:"small",color:"disabled"})]})}):(0,n.jsxs)(x.A,{display:"flex",alignItems:"center",style:{gap:8},children:[(0,n.jsx)(x.A,{fontFamily:"monospace",fontSize:"0.875rem",children:d?"Loading...":c&&u?u:"•".repeat(20)+"..."}),c&&u&&(0,n.jsx)(y.Ay,{title:"Copy to clipboard",children:(0,n.jsx)(j.A,{size:"small",onClick:async()=>{u&&(await navigator.clipboard.writeText(u),l.post({message:"API key copied to clipboard",severity:"success",display:"transient"}))},children:(0,n.jsx)(K.A,{fontSize:"small"})})}),(0,n.jsx)(y.Ay,{title:c?"Hide API key":"Reveal API key (one-time only)",children:(0,n.jsx)("span",{children:(0,n.jsx)(j.A,{size:"small",onClick:()=>{c?(((e,t)=>{const a=`${e}/${t}`;se(e=>{const t=new Map(e);return t.delete(a),t})})(e.metadata.namespace,e.metadata.name),ke(e.metadata.name)):m||(pe({namespace:e.metadata.namespace,name:e.metadata.name}),de(!0))},disabled:d||m&&!u,children:c?(0,n.jsx)(B.A,{fontSize:"small"}):(0,n.jsx)(M.A,{fontSize:"small"})})})})]}):(0,n.jsx)(g.A,{variant:"body2",color:"textSecondary",children:"Awaiting secret..."})}},{title:"Requested",field:"metadata.creationTimestamp",render:e=>{if(!e.metadata.creationTimestamp)return(0,n.jsx)(g.A,{variant:"body2",children:"-"});const t=new Date(e.metadata.creationTimestamp);return(0,n.jsx)(g.A,{variant:"body2",children:t.toLocaleDateString()})}},{title:"Actions",filtering:!1,width:"100px",render:e=>Q===e.metadata.name?(0,n.jsx)(b.A,{size:20}):(0,n.jsxs)(x.A,{display:"flex",style:{gap:4},children:[(0,n.jsx)(y.Ay,{title:"View details",children:(0,n.jsx)(j.A,{size:"small",onClick:t=>{t.stopPropagation(),r(`/kuadrant/api-keys/${e.metadata.namespace}/${e.metadata.name}`)},children:(0,n.jsx)(M.A,{fontSize:"small"})})}),(0,n.jsx)(y.Ay,{title:"Delete",children:(0,n.jsx)(j.A,{size:"small",onClick:t=>{t.stopPropagation(),ae({open:!0,request:e})},children:(0,n.jsx)(F.A,{fontSize:"small"})})})]})}],Ie=(0,s.useMemo)(()=>[{render:e=>{var t;const a=e.rowData;return(null==a||null===(t=a.metadata)||void 0===t?void 0:t.name)?(0,n.jsx)(Y,{request:a}):(0,n.jsx)(x.A,{})}}],[]);return ge?(0,n.jsx)(x.A,{p:2,children:[...Array(5)].map((e,t)=>(0,n.jsx)(x.A,{p:2,children:(0,n.jsx)(R.A,{variant:"text",width:"100%"})},t))}):ve?(0,n.jsx)(u._,{error:ve}):(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(x.A,{display:"flex",justifyContent:"flex-end",mb:2,px:2,children:(0,n.jsx)(k.A,{variant:"contained",color:"primary",onClick:()=>f(!0),"data-testid":"request-access-button",children:"Request Access"})}),(0,n.jsxs)(x.A,{className:a.container,children:[(0,n.jsx)(_.Z,{sections:je,filters:Ae,onChange:fe}),(0,n.jsx)(x.A,{className:a.tableContainer,children:0===ye.length?(0,n.jsx)(x.A,{p:4,textAlign:"center",children:(0,n.jsx)(g.A,{variant:"body1",color:"textSecondary",gutterBottom:!0,children:"No API keys found. Request access to an API to get started."})}):0===be.length?(0,n.jsx)(x.A,{p:4,textAlign:"center",children:(0,n.jsx)(g.A,{variant:"body1",color:"textSecondary",children:"No API keys match the selected filters."})}):(0,n.jsx)(p.X,{options:{paging:be.length>10,pageSize:20,search:!0,filtering:!1,debounceInterval:300,toolbar:!0,emptyRowsWhenPaging:!1},columns:Ce,data:be.map(e=>({...e,id:e.metadata.name})),detailPanel:Ie})})]}),(0,n.jsx)(w.A,{id:"myapikeys-menu",open:Boolean(z),onClose:we,anchorReference:"anchorPosition",anchorPosition:z||{top:0,left:0},children:N&&(()=>{const e=[];var t;return e.push((0,n.jsx)(P.A,{onClick:()=>{r(`/kuadrant/api-keys/${N.metadata.namespace}/${N.metadata.name}`),we()},children:"View Details"},"view")),(t=N).status&&"Pending"!==t.status.phase||e.push((0,n.jsx)(P.A,{onClick:Pe,children:"Edit"},"edit")),e.push((0,n.jsx)(P.A,{onClick:Se,children:"Delete"},"delete")),e})()}),Z.request&&(0,n.jsx)(L.e,{open:Z.open,request:Z.request,availablePlans:Z.plans,onClose:()=>J({open:!1,request:null,plans:[]}),onSuccess:()=>{J({open:!1,request:null,plans:[]}),G(e=>e+1)}}),(0,n.jsx)(U.K,{open:te.open,title:"Delete API Key",description:`Are you sure you want to delete this API key for ${(null===(t=te.request)||void 0===t||null===(e=t.spec.apiProductRef)||void 0===e?void 0:e.name)||"this API"}?`,deleting:null!==Q,onConfirm:async()=>{if(!te.request)return;const e=te.request,t=e.metadata.name;he(e=>new Set(e).add(t)),ee(t);try{await i.deleteRequest(e.metadata.namespace,e.metadata.name),G(e=>e+1),l.post({message:"API key deleted",severity:"success",display:"transient"}),ae({open:!1,request:null})}catch(e){console.error("Error deleting request:",e),he(e=>{const a=new Set(e);return a.delete(t),a});const a=e instanceof Error?e.message:"unknown error occurred";l.post({message:`Failed to delete APIKey. ${a}`,severity:"error",display:"transient"})}finally{ee(null)}},onCancel:()=>{ae({open:!1,request:null})}}),(0,n.jsxs)(S.A,{open:ce,onClose:()=>{de(!1),pe(null)},maxWidth:"sm",children:[(0,n.jsx)(C.A,{children:(0,n.jsxs)(x.A,{display:"flex",alignItems:"center",children:[(0,n.jsx)(D.A,{color:"primary",style:{marginRight:8}}),"View API Key"]})}),(0,n.jsxs)(I.A,{children:[(0,n.jsxs)(g.A,{variant:"body1",paragraph:!0,children:["This API key can only be viewed ",(0,n.jsx)("strong",{children:"once"}),". After you reveal it, you will not be able to retrieve it again."]}),(0,n.jsx)(g.A,{variant:"body2",color:"textSecondary",children:"Make sure to copy and store it securely before closing this view."})]}),(0,n.jsxs)(q.A,{children:[(0,n.jsx)(k.A,{onClick:()=>{de(!1),pe(null)},children:"Cancel"}),(0,n.jsx)(k.A,{variant:"contained",color:"primary",onClick:()=>{ue&&((async(e,t)=>{const a=`${e}/${t}`;if(!re.has(a)){ie(e=>new Set(e).add(a));try{const n=await i.getApiKeySecret(e,t);se(e=>new Map(e).set(a,n.apiKey)),oe(e=>new Set(e).add(a))}catch(e){const t=e instanceof Error?e.message:"unknown error occurred";t.includes("403")||t.includes("already been viewed")?(oe(e=>new Set(e).add(a)),l.post({message:"This API key has already been viewed and cannot be retrieved again.",severity:"warning",display:"transient"})):l.post({message:`Failed to fetch api key: ${t}`,severity:"error",display:"transient"})}finally{ie(e=>{const t=new Set(e);return t.delete(a),t})}}})(ue.namespace,ue.name),ke(ue.name)),de(!1),pe(null)},children:"Reveal API Key"})]})]}),(0,n.jsx)(W,{open:o,onClose:()=>f(!1),onSuccess:()=>{f(!1),G(e=>e+1)}})]})},Z=()=>(0,n.jsxs)(r.Y,{themeId:"tool",children:[(0,n.jsx)(i.Y,{title:"My API Keys",subtitle:"View and manage your API keys",children:(0,n.jsx)(l.Y,{children:"Manage your API keys and access requests"})}),(0,n.jsx)(o.U,{children:(0,n.jsx)(H,{})})]})},46299:(e,t,a)=>{a.d(t,{ee:()=>r,g9:()=>n,uU:()=>s});const n=e=>{const t={border:"none"};switch(e){case"Approved":return{...t,backgroundColor:"#1976d2",color:"#fff"};case"Rejected":return{...t,backgroundColor:"#d32f2f",color:"#fff"};default:return{...t,backgroundColor:"#9c27b0",color:"#fff"}}},s=e=>{const t={border:"none"};switch(e){case"Approved":return{...t,backgroundColor:"#2e7d32",color:"#fff"};case"Rejected":return{...t,backgroundColor:"#d32f2f",color:"#fff"};default:return{...t,backgroundColor:"#ed6c02",color:"#fff"}}},r=e=>{switch(e){case"production":return{backgroundColor:"#1976d2",color:"#fff"};case"experimental":return{backgroundColor:"#9c27b0",color:"#fff"};case"deprecated":return{backgroundColor:"#ff9800",color:"#fff"};case"retired":return{backgroundColor:"#d32f2f",color:"#fff"};default:return{}}}},63221:(e,t,a)=>{a.d(t,{K:()=>f});var n=a(31085),s=a(95478),r=a(76891),i=a(61477),l=a(10394),o=a(46805),c=a(59461),d=a(72501),u=a(16249),p=a(93453),m=a(64947),h=a(78467),A=a(77225);const f=({open:e,title:t,description:a,confirmText:f,severity:x="normal",deleting:g=!1,onConfirm:v,onCancel:y})=>{const[j,b]=(0,s.useState)("");(0,s.useEffect)(()=>{e||b("")},[e]);const k="high"===x&&f,w=!k||j===f;return(0,n.jsxs)(r.A,{open:e,onClose:g?void 0:y,maxWidth:"sm",fullWidth:!0,children:[(0,n.jsxs)(i.A,{children:["high"===x&&(0,n.jsxs)(l.A,{display:"flex",alignItems:"center",style:{gap:8},children:[(0,n.jsx)(A.A,{color:"error"}),(0,n.jsx)("span",{children:t})]}),"high"!==x&&t]}),(0,n.jsxs)(o.A,{children:[(0,n.jsx)(c.A,{style:{whiteSpace:"pre-line"},children:a}),k&&(0,n.jsxs)(l.A,{mt:2,children:[(0,n.jsxs)(d.A,{variant:"body2",color:"textSecondary",gutterBottom:!0,children:["Type ",(0,n.jsx)("strong",{children:f})," to confirm:"]}),(0,n.jsx)(u.A,{fullWidth:!0,variant:"outlined",size:"small",value:j,onChange:e=>b(e.target.value),disabled:g,autoFocus:!0,placeholder:f})]})]}),(0,n.jsxs)(p.A,{children:[(0,n.jsx)(m.A,{onClick:y,disabled:g,children:"Cancel"}),(0,n.jsx)(m.A,{onClick:()=>{w&&v()},color:"secondary",variant:"contained",disabled:g||!w,startIcon:g?(0,n.jsx)(h.A,{size:16,color:"inherit"}):void 0,children:g?"Deleting...":"Delete"})]})]})}},64047:(e,t,a)=>{a.d(t,{s:()=>s});var n=a(22097);a(54209);const s=(0,n.createApiRef)({id:"plugin.kuadrant.service"})}}]);
|
|
2
|
-
//# sourceMappingURL=7270.301a3c46.chunk.js.map
|