@kuadrant/kuadrant-backstage-plugin-frontend 0.0.2-dev-30af554 → 0.0.2-dev-752cfa1
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/KuadrantPage/KuadrantPage.esm.js +9 -1
- package/dist/components/KuadrantPage/KuadrantPage.esm.js.map +1 -1
- package/dist-scalprum/{internal.plugin-kuadrant.86c50e4da6b961c623e9.js → internal.plugin-kuadrant.95464756fb5320a8f8b8.js} +2 -2
- package/dist-scalprum/{internal.plugin-kuadrant.86c50e4da6b961c623e9.js.map → internal.plugin-kuadrant.95464756fb5320a8f8b8.js.map} +1 -1
- package/dist-scalprum/plugin-manifest.json +2 -2
- package/dist-scalprum/static/{7632.646001ce.chunk.js → 7632.4c95ea50.chunk.js} +2 -2
- package/dist-scalprum/static/7632.4c95ea50.chunk.js.map +1 -0
- package/package.json +1 -1
- package/dist-scalprum/static/7632.646001ce.chunk.js.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"static/7632.4c95ea50.chunk.js","mappings":"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","sources":["webpack://internal.plugin-kuadrant/./src/components/EditAPIKeyRequestDialog/EditAPIKeyRequestDialog.tsx","webpack://internal.plugin-kuadrant/./src/components/MyApiKeysCard/MyApiKeysCard.tsx","webpack://internal.plugin-kuadrant/./src/components/PermissionGate/PermissionGate.tsx","webpack://internal.plugin-kuadrant/./src/components/PlanPolicyDetailsCard/PlanPolicyDetails.tsx","webpack://internal.plugin-kuadrant/./src/components/CreateAPIProductDialog/CreateAPIProductDialog.tsx","webpack://internal.plugin-kuadrant/./src/components/EditAPIProductDialog/EditAPIProductDialog.tsx","webpack://internal.plugin-kuadrant/./src/components/KuadrantPage/KuadrantPage.tsx"],"sourcesContent":["import React, { useState, useEffect } from 'react';\nimport {\n Dialog,\n DialogTitle,\n DialogContent,\n DialogActions,\n Button,\n TextField,\n Box,\n Typography,\n FormControl,\n InputLabel,\n Select,\n MenuItem,\n} from '@material-ui/core';\nimport { useApi, configApiRef, fetchApiRef } from '@backstage/core-plugin-api';\nimport { APIKeyRequest } from '../../types/api-management';\n\ninterface EditAPIKeyRequestDialogProps {\n open: boolean;\n onClose: () => void;\n onSuccess: () => void;\n request: APIKeyRequest;\n availablePlans: Array<{\n tier: string;\n description?: string;\n limits?: any;\n }>;\n}\n\nexport const EditAPIKeyRequestDialog = ({\n open,\n onClose,\n onSuccess,\n request,\n availablePlans,\n}: EditAPIKeyRequestDialogProps) => {\n const config = useApi(configApiRef);\n const fetchApi = useApi(fetchApiRef);\n const backendUrl = config.getString('backend.baseUrl');\n\n const [planTier, setPlanTier] = useState('');\n const [useCase, setUseCase] = useState('');\n const [saving, setSaving] = useState(false);\n const [error, setError] = useState('');\n\n useEffect(() => {\n if (open && request) {\n setPlanTier(request.spec.planTier || '');\n setUseCase(request.spec.useCase || '');\n setError('');\n }\n }, [open, request]);\n\n const handleSave = async () => {\n if (!planTier) {\n setError('Please select a plan tier');\n return;\n }\n\n setError('');\n setSaving(true);\n\n try {\n const patch = {\n spec: {\n planTier,\n useCase: useCase.trim(),\n },\n };\n\n const response = await fetchApi.fetch(\n `${backendUrl}/api/kuadrant/requests/${request.metadata.namespace}/${request.metadata.name}`,\n {\n method: 'PATCH',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify(patch),\n }\n );\n\n if (!response.ok) {\n const errorData = await response.json().catch(() => ({}));\n throw new Error(errorData.error || `Failed to update request: ${response.status}`);\n }\n\n onSuccess();\n onClose();\n } catch (err) {\n console.error('Error updating API key request:', err);\n setError(err instanceof Error ? err.message : 'Unknown error occurred');\n } finally {\n setSaving(false);\n }\n };\n\n const handleClose = () => {\n if (!saving) {\n setError('');\n onClose();\n }\n };\n\n return (\n <Dialog open={open} onClose={handleClose} maxWidth=\"sm\" fullWidth>\n <DialogTitle>Edit API Access Request</DialogTitle>\n <DialogContent>\n {error && (\n <Box mb={2} p={2} bgcolor=\"error.main\" color=\"error.contrastText\" borderRadius={1}>\n <Typography variant=\"body2\">{error}</Typography>\n </Box>\n )}\n\n <FormControl fullWidth margin=\"normal\">\n <InputLabel>Plan Tier</InputLabel>\n <Select\n value={planTier}\n onChange={(e) => setPlanTier(e.target.value as string)}\n disabled={saving}\n >\n {availablePlans.map((plan) => {\n const limitDesc = Object.entries(plan.limits || {})\n .map(([key, val]) => `${val} per ${key}`)\n .join(', ');\n return (\n <MenuItem key={plan.tier} value={plan.tier}>\n {plan.tier} {limitDesc ? `(${limitDesc})` : ''}\n </MenuItem>\n );\n })}\n </Select>\n </FormControl>\n\n <TextField\n label=\"Use Case\"\n placeholder=\"Describe how you plan to use this API\"\n multiline\n rows={3}\n fullWidth\n margin=\"normal\"\n value={useCase}\n onChange={(e) => setUseCase(e.target.value)}\n disabled={saving}\n helperText=\"Explain your intended use of this API for admin review\"\n />\n </DialogContent>\n <DialogActions>\n <Button onClick={handleClose} disabled={saving}>\n Cancel\n </Button>\n <Button\n onClick={handleSave}\n color=\"primary\"\n disabled={!planTier || saving}\n >\n {saving ? 'Saving...' : 'Save Changes'}\n </Button>\n </DialogActions>\n </Dialog>\n );\n};\n","import React, { useState } from 'react';\nimport { InfoCard, Table, TableColumn, Link } from '@backstage/core-components';\nimport { useApi, configApiRef, fetchApiRef, identityApiRef } from '@backstage/core-plugin-api';\nimport useAsync from 'react-use/lib/useAsync';\nimport { Box, Chip, Typography, Tabs, Tab, IconButton, Tooltip, Menu, MenuItem } from '@material-ui/core';\nimport VisibilityIcon from '@material-ui/icons/Visibility';\nimport VisibilityOffIcon from '@material-ui/icons/VisibilityOff';\nimport MoreVertIcon from '@material-ui/icons/MoreVert';\nimport { EditAPIKeyRequestDialog } from '../EditAPIKeyRequestDialog';\nimport { APIKeyRequest } from '../../types/api-management';\n\nexport const MyApiKeysCard = () => {\n const config = useApi(configApiRef);\n const fetchApi = useApi(fetchApiRef);\n const identityApi = useApi(identityApiRef);\n const backendUrl = config.getString('backend.baseUrl');\n const [selectedTab, setSelectedTab] = useState(0);\n const [, setUserId] = useState<string>('');\n const [visibleKeys, setVisibleKeys] = useState<Set<string>>(new Set());\n const [menuAnchor, setMenuAnchor] = useState<{ top: number; left: number } | null>(null);\n const [menuRequest, setMenuRequest] = useState<APIKeyRequest | null>(null);\n const [editDialogState, setEditDialogState] = useState<{ open: boolean; request: APIKeyRequest | null; plans: any[] }>({\n open: false,\n request: null,\n plans: [],\n });\n const [refresh, setRefresh] = useState(0);\n\n useAsync(async () => {\n const identity = await identityApi.getBackstageIdentity();\n const extractedUserId = identity.userEntityRef.split('/')[1] || 'guest';\n console.log(`MyApiKeysCard: setting userId from userEntityRef: ${identity.userEntityRef} -> \"${extractedUserId}\"`);\n setUserId(extractedUserId);\n }, [identityApi]);\n\n const { value: requests, loading, error } = useAsync(async () => {\n const response = await fetchApi.fetch(\n `${backendUrl}/api/kuadrant/requests/my`\n );\n if (!response.ok) {\n throw new Error('failed to fetch requests');\n }\n const data = await response.json();\n return data.items || [];\n }, [backendUrl, fetchApi, refresh]);\n\n if (loading) {\n return (\n <InfoCard title=\"My API Keys\">\n <Typography>Loading...</Typography>\n </InfoCard>\n );\n }\n\n if (error) {\n return (\n <InfoCard title=\"My API Keys\">\n <Typography color=\"error\">Error loading API keys: {error.message}</Typography>\n </InfoCard>\n );\n }\n\n const allRequests = requests || [];\n const approvedRequests = allRequests.filter((r: APIKeyRequest) => r.status?.phase === 'Approved');\n const pendingRequests = allRequests.filter((r: APIKeyRequest) => !r.status?.phase || r.status.phase === 'Pending');\n const rejectedRequests = allRequests.filter((r: APIKeyRequest) => r.status?.phase === 'Rejected');\n\n const toggleKeyVisibility = (keyName: string) => {\n setVisibleKeys(prev => {\n const newSet = new Set(prev);\n if (newSet.has(keyName)) {\n newSet.delete(keyName);\n } else {\n newSet.add(keyName);\n }\n return newSet;\n });\n };\n\n const handleMenuClose = () => {\n setMenuAnchor(null);\n setMenuRequest(null);\n };\n\n const handleEdit = async () => {\n if (!menuRequest) return;\n\n const request = menuRequest;\n handleMenuClose();\n\n // Fetch available plans for this API\n try {\n const apiProductResponse = await fetchApi.fetch(\n `${backendUrl}/api/kuadrant/apiproducts/${request.spec.apiNamespace}/${request.spec.apiName}`\n );\n\n if (apiProductResponse.ok) {\n const apiProduct = await apiProductResponse.json();\n const plans = apiProduct.spec?.plans || [];\n setEditDialogState({ open: true, request, plans });\n } else {\n console.error('Failed to fetch API product');\n setEditDialogState({ open: true, request, plans: [] });\n }\n } catch (err) {\n console.error('Error fetching plans:', err);\n setEditDialogState({ open: true, request, plans: [] });\n }\n };\n\n const handleDelete = async () => {\n if (!menuRequest) return;\n\n const request = menuRequest;\n handleMenuClose();\n\n if (!window.confirm('Are you sure you want to delete this request?')) {\n return;\n }\n\n try {\n const response = await fetchApi.fetch(\n `${backendUrl}/api/kuadrant/requests/${request.metadata.namespace}/${request.metadata.name}`,\n { method: 'DELETE' }\n );\n\n if (!response.ok) {\n throw new Error('Failed to delete request');\n }\n\n setRefresh(r => r + 1);\n } catch (err) {\n console.error('Error deleting request:', err);\n alert('Failed to delete request');\n }\n };\n\n const columns: TableColumn<APIKeyRequest>[] = [\n {\n title: 'API Product',\n field: 'spec.apiName',\n render: (row: APIKeyRequest) => (\n <Link to={`/catalog/default/api/${row.spec.apiName}/api-keys`}>\n <strong>{row.spec.apiName}</strong>\n </Link>\n ),\n },\n {\n title: 'Plan',\n field: 'spec.planTier',\n render: (row: APIKeyRequest) => {\n const color = row.spec.planTier === 'gold' ? 'primary' :\n row.spec.planTier === 'silver' ? 'default' : 'secondary';\n return <Chip label={row.spec.planTier} color={color} size=\"small\" />;\n },\n },\n {\n title: 'Use Case',\n field: 'spec.useCase',\n render: (row: APIKeyRequest) => {\n if (!row.spec.useCase) {\n return <Typography variant=\"body2\">-</Typography>;\n }\n return (\n <Tooltip title={row.spec.useCase} placement=\"top\">\n <Typography\n variant=\"body2\"\n style={{\n maxWidth: '200px',\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n whiteSpace: 'nowrap',\n }}\n >\n {row.spec.useCase}\n </Typography>\n </Tooltip>\n );\n },\n },\n {\n title: 'Status',\n field: 'status.phase',\n render: (row: APIKeyRequest) => {\n const phase = row.status?.phase || 'Pending';\n const color = phase === 'Approved' ? 'primary' :\n phase === 'Rejected' ? 'secondary' : 'default';\n return <Chip label={phase} color={color} size=\"small\" />;\n },\n },\n {\n title: 'Reason',\n render: (row: APIKeyRequest) => {\n if (row.status?.reason) {\n const color = row.status.phase === 'Rejected' ? 'error' : 'textPrimary';\n return (\n <Tooltip title={row.status.reason} placement=\"top\">\n <Typography\n variant=\"body2\"\n color={color}\n style={{\n maxWidth: '200px',\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n whiteSpace: 'nowrap',\n }}\n >\n {row.status.reason}\n </Typography>\n </Tooltip>\n );\n }\n return <Typography variant=\"body2\" color=\"textSecondary\">-</Typography>;\n },\n },\n {\n title: 'Reviewed By',\n render: (row: APIKeyRequest) => {\n if ((row.status?.phase === 'Approved' || row.status?.phase === 'Rejected') && row.status.reviewedBy) {\n const reviewedDate = row.status.reviewedAt ? new Date(row.status.reviewedAt).toLocaleDateString() : '';\n return (\n <Box>\n <Typography variant=\"body2\">{row.status.reviewedBy}</Typography>\n {reviewedDate && (\n <Typography variant=\"caption\" color=\"textSecondary\">\n {reviewedDate}\n </Typography>\n )}\n </Box>\n );\n }\n return <Typography variant=\"body2\" color=\"textSecondary\">-</Typography>;\n },\n },\n {\n title: 'API Key',\n render: (row: APIKeyRequest) => {\n if (row.status?.phase === 'Approved' && row.status.apiKey) {\n const isVisible = visibleKeys.has(row.metadata.name);\n return (\n <Box display=\"flex\" alignItems=\"center\" style={{ gap: 8 }}>\n <Box fontFamily=\"monospace\" fontSize=\"0.875rem\">\n {isVisible ? row.status.apiKey : '•'.repeat(20) + '...'}\n </Box>\n <Tooltip title={isVisible ? 'hide key' : 'show key'}>\n <IconButton\n size=\"small\"\n onClick={() => toggleKeyVisibility(row.metadata.name)}\n >\n {isVisible ? <VisibilityOffIcon fontSize=\"small\" /> : <VisibilityIcon fontSize=\"small\" />}\n </IconButton>\n </Tooltip>\n </Box>\n );\n }\n return <Typography variant=\"body2\" color=\"textSecondary\">-</Typography>;\n },\n },\n {\n title: 'Requested',\n field: 'metadata.creationTimestamp',\n render: (row: APIKeyRequest) => {\n if (!row.metadata.creationTimestamp) {\n return <Typography variant=\"body2\">-</Typography>;\n }\n const date = new Date(row.metadata.creationTimestamp);\n return <Typography variant=\"body2\">{date.toLocaleDateString()}</Typography>;\n },\n },\n {\n title: '',\n render: (row: APIKeyRequest) => {\n return (\n <IconButton\n size=\"small\"\n onClick={(e) => {\n e.stopPropagation();\n const rect = e.currentTarget.getBoundingClientRect();\n setMenuAnchor({ top: rect.bottom, left: rect.left });\n setMenuRequest(row);\n }}\n aria-controls={menuAnchor ? 'myapikeys-menu' : undefined}\n aria-haspopup=\"true\"\n >\n <MoreVertIcon />\n </IconButton>\n );\n },\n },\n ];\n\n const getTabData = () => {\n switch (selectedTab) {\n case 0:\n return approvedRequests;\n case 1:\n return pendingRequests;\n case 2:\n return rejectedRequests;\n default:\n return allRequests;\n }\n };\n\n const getTabColumns = () => {\n switch (selectedTab) {\n case 0: // Active - no Reason\n return columns.filter(col => col.title !== 'Reason');\n case 1: // Pending - no Reason, Reviewed By, API Key\n return columns.filter(col =>\n col.title !== 'Reason' &&\n col.title !== 'Reviewed By' &&\n col.title !== 'API Key'\n );\n case 2: // Rejected - no API Key\n return columns.filter(col => col.title !== 'API Key');\n default:\n return columns;\n }\n };\n\n const tabData = getTabData();\n const tabColumns = getTabColumns();\n const isPending = (row: APIKeyRequest) => !row.status || row.status.phase === 'Pending';\n\n return (\n <>\n <InfoCard\n title=\"My API Keys\"\n subheader={`${approvedRequests.length} active, ${pendingRequests.length} pending`}\n >\n <Box mb={2}>\n <Tabs\n value={selectedTab}\n onChange={(_, newValue) => setSelectedTab(newValue)}\n indicatorColor=\"primary\"\n textColor=\"primary\"\n >\n <Tab label={`Active (${approvedRequests.length})`} />\n <Tab label={`Pending (${pendingRequests.length})`} />\n <Tab label={`Rejected (${rejectedRequests.length})`} />\n </Tabs>\n </Box>\n {tabData.length === 0 ? (\n <Box p={3} textAlign=\"center\">\n <Typography variant=\"body1\" color=\"textSecondary\">\n {selectedTab === 0 && 'No active API keys. Request access to an API to get started.'}\n {selectedTab === 1 && 'No pending requests.'}\n {selectedTab === 2 && 'No rejected requests.'}\n </Typography>\n </Box>\n ) : (\n <Table\n options={{\n paging: tabData.length > 10,\n pageSize: 10,\n search: false,\n toolbar: false,\n }}\n columns={tabColumns}\n data={tabData.map((item: APIKeyRequest) => ({\n ...item,\n id: item.metadata.name,\n }))}\n />\n )}\n </InfoCard>\n\n <Menu\n id=\"myapikeys-menu\"\n open={Boolean(menuAnchor)}\n onClose={handleMenuClose}\n anchorReference=\"anchorPosition\"\n anchorPosition={menuAnchor || { top: 0, left: 0 }}\n >\n {menuRequest && (() => {\n const items = [];\n if (isPending(menuRequest)) {\n items.push(<MenuItem key=\"edit\" onClick={handleEdit}>Edit</MenuItem>);\n }\n items.push(<MenuItem key=\"delete\" onClick={handleDelete}>Delete</MenuItem>);\n return items;\n })()}\n </Menu>\n\n {editDialogState.request && (\n <EditAPIKeyRequestDialog\n open={editDialogState.open}\n request={editDialogState.request}\n availablePlans={editDialogState.plans}\n onClose={() => setEditDialogState({ open: false, request: null, plans: [] })}\n onSuccess={() => {\n setEditDialogState({ open: false, request: null, plans: [] });\n setRefresh(r => r + 1);\n }}\n />\n )}\n </>\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 from 'react';\nimport { Box, Typography, Chip } from '@material-ui/core';\nimport { Alert } from '@material-ui/lab';\n\ninterface PlanPolicyDetailsProps {\n selectedPolicy: {\n metadata: {\n name: string;\n };\n plans?: Array<{\n tier: string;\n description?: string;\n limits?: {\n daily?: number;\n monthly?: number;\n yearly?: number;\n };\n }>;\n } | null;\n alertSeverity?: 'warning' | 'info';\n alertMessage?: string;\n includeTopMargin?: boolean;\n}\n\nexport const PlanPolicyDetails: React.FC<PlanPolicyDetailsProps> = ({\n selectedPolicy,\n alertSeverity = 'warning',\n alertMessage = 'No PlanPolicy found for this HTTPRoute. API keys and rate limiting may not be available.',\n includeTopMargin = true,\n}) => {\n return (\n <Box\n mt={includeTopMargin ? 1 : 0}\n p={2}\n bgcolor=\"#f5f5f5\"\n borderRadius={1}\n border=\"1px solid #e0e0e0\"\n >\n {selectedPolicy ? (\n <>\n <Typography variant=\"subtitle2\" gutterBottom style={{ fontWeight: 600 }}>\n Associated PlanPolicy: <strong>{selectedPolicy.metadata.name}</strong>\n </Typography>\n\n {selectedPolicy.plans && selectedPolicy.plans.length > 0 ? (\n <>\n <Typography\n variant=\"caption\"\n display=\"block\"\n gutterBottom\n color=\"textSecondary\"\n style={{ marginTop: 8 }}\n >\n Available Plans:\n </Typography>\n <Box display=\"flex\" flexWrap=\"wrap\" mt={1} style={{ gap: 8 }}>\n {selectedPolicy.plans.map((plan: any, idx: number) => {\n const limitText = plan.limits?.daily\n ? `${plan.limits.daily}/day`\n : plan.limits?.monthly\n ? `${plan.limits.monthly}/month`\n : plan.limits?.yearly\n ? `${plan.limits.yearly}/year`\n : 'No limit';\n\n return (\n <Chip\n key={idx}\n label={`${plan.tier}: ${limitText}`}\n size=\"small\"\n variant=\"outlined\"\n color=\"primary\"\n />\n );\n })}\n </Box>\n {selectedPolicy.plans.some((p: any) => p.description) && (\n <Box mt={1}>\n {selectedPolicy.plans.filter((p: any) => p.description).map((plan: any, idx: number) => (\n <Typography key={idx} variant=\"caption\" display=\"block\" color=\"textSecondary\">\n • <strong>{plan.tier}:</strong> {plan.description}\n </Typography>\n ))}\n </Box>\n )}\n </>\n ) : (\n <Typography variant=\"caption\" color=\"textSecondary\">\n No plans defined in this PlanPolicy\n </Typography>\n )}\n </>\n ) : (\n <Alert severity={alertSeverity}>{alertMessage}</Alert>\n )}\n </Box>\n );\n};\n\n","import React, { 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 makeStyles,\n} from '@material-ui/core';\nimport { useApi, configApiRef, fetchApiRef } from '@backstage/core-plugin-api';\nimport { Alert } from '@material-ui/lab';\nimport useAsync from 'react-use/lib/useAsync';\nimport { PlanPolicyDetails } from '../PlanPolicyDetailsCard';\n\nconst useStyles = makeStyles({\n asterisk: {\n color: '#f44336',\n },\n});\n\ninterface CreateAPIProductDialogProps {\n open: boolean;\n onClose: () => void;\n onSuccess: () => void;\n}\n\nexport const CreateAPIProductDialog = ({ open, onClose, onSuccess }: CreateAPIProductDialogProps) => {\n const classes = useStyles();\n const config = useApi(configApiRef);\n const fetchApi = useApi(fetchApiRef);\n const backendUrl = config.getString('backend.baseUrl');\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 [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\n const { value: httpRoutes, loading: httpRoutesLoading } = useAsync(async () => {\n const response = await fetchApi.fetch(`${backendUrl}/api/kuadrant/httproutes`);\n const data = await response.json();\n // filter to only show httproutes annotated for backstage exposure\n return (data.items || []).filter((route: any) =>\n route.metadata.annotations?.['backstage.io/expose'] === 'true'\n );\n }, [backendUrl, fetchApi, open]);\n\n // load planpolicies with full details to show associated plans\n const { value: planPolicies } = useAsync(async () => {\n const response = await fetchApi.fetch(`${backendUrl}/api/kuadrant/planpolicies`);\n return await response.json();\n }, [backendUrl, fetchApi, open]);\n\n // find planpolicy associated with selected httproute\n const getPlanPolicyForRoute = (routeNamespace: string, routeName: string) => {\n if (!planPolicies?.items) return null;\n\n return planPolicies.items.find((pp: any) => {\n const ref = pp.targetRef;\n return (\n ref?.kind === 'HTTPRoute' &&\n ref?.name === routeName &&\n (!ref?.namespace || ref?.namespace === routeNamespace)\n );\n });\n };\n\n const selectedRouteInfo = selectedHTTPRoute ? selectedHTTPRoute.split('/') : null;\n const selectedPolicy = selectedRouteInfo\n ? getPlanPolicyForRoute(selectedRouteInfo[0], selectedRouteInfo[1])\n : null;\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 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 = {\n apiVersion: 'extensions.kuadrant.io/v1alpha1',\n kind: 'APIProduct',\n metadata: {\n name,\n namespace,\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 && { openAPISpec }),\n },\n } : {}),\n },\n };\n\n const response = await fetchApi.fetch(`${backendUrl}/api/kuadrant/apiproducts`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify(apiProduct),\n });\n\n if (!response.ok) {\n const errorData = await response.json();\n throw new Error(errorData.error || 'failed to create apiproduct');\n }\n\n onSuccess();\n handleClose();\n } catch (err) {\n setError(err instanceof Error ? err.message : String(err));\n } finally {\n setCreating(false);\n }\n };\n\n const handleClose = () => {\n setName('');\n setDisplayName('');\n setDescription('');\n setVersion('v1');\n setApprovalMode('manual');\n setPublishStatus('Published');\n setTags([]);\n setTagInput('');\n setSelectedHTTPRoute('');\n setContactEmail('');\n setContactTeam('');\n setDocsURL('');\n setOpenAPISpec('');\n setError('');\n onClose();\n };\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\n <Grid container spacing={2}>\n <Grid item xs={6}>\n <TextField\n fullWidth\n label=\"Name\"\n value={name}\n onChange={e => setName(e.target.value)}\n placeholder=\"my-api\"\n helperText=\"Kubernetes resource name (lowercase, hyphens)\"\n margin=\"normal\"\n required\n InputLabelProps={{\n classes: {\n asterisk: classes.asterisk,\n },\n }}\n />\n </Grid>\n <Grid item xs={6}>\n <TextField\n fullWidth\n label=\"Display Name\"\n value={displayName}\n onChange={e => setDisplayName(e.target.value)}\n placeholder=\"My API\"\n margin=\"normal\"\n required\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 margin=\"normal\"\n />\n </Grid>\n <Grid item xs={12}>\n <TextField\n fullWidth\n select\n label=\"Approval Mode\"\n value={approvalMode}\n onChange={e => setApprovalMode(e.target.value as 'automatic' | 'manual')}\n margin=\"normal\"\n helperText=\"Automatic: keys are created immediately. Manual: requires approval.\"\n >\n <MenuItem value=\"manual\">Manual</MenuItem>\n <MenuItem value=\"automatic\">Automatic</MenuItem>\n </TextField>\n </Grid>\n <Grid item xs={12}>\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=\"Draft: hidden from catalog. Published: visible to consumers.\"\n >\n <MenuItem value=\"Draft\">Draft</MenuItem>\n <MenuItem value=\"Published\">Published</MenuItem>\n </TextField>\n </Grid>\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 InputLabelProps={{\n classes: {\n asterisk: classes.asterisk,\n },\n }}\n />\n </Grid>\n\n <Grid item xs={12}>\n <Typography variant=\"subtitle2\" gutterBottom style={{ marginTop: 16 }}>\n Tags\n </Typography>\n <Box display=\"flex\" flexWrap=\"wrap\" marginBottom={1} style={{ gap: 8 }}>\n {tags.map(tag => (\n <Chip\n key={tag}\n label={tag}\n onDelete={() => handleDeleteTag(tag)}\n size=\"small\"\n />\n ))}\n </Box>\n <Box display=\"flex\" style={{ gap: 8 }}>\n <TextField\n fullWidth\n size=\"small\"\n value={tagInput}\n onChange={e => setTagInput(e.target.value)}\n onKeyPress={e => e.key === 'Enter' && handleAddTag()}\n placeholder=\"Add tag\"\n />\n <Button onClick={handleAddTag} variant=\"outlined\" size=\"small\">\n Add\n </Button>\n </Box>\n </Grid>\n\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=\"Select an HTTPRoute (backstage.io/expose: true). APIProduct will be created in the same namespace.\"\n disabled={httpRoutesLoading}\n InputLabelProps={{\n classes: {\n asterisk: classes.asterisk,\n },\n }}\n >\n {httpRoutesLoading && (\n <MenuItem value=\"\">Loading...</MenuItem>\n )}\n {!httpRoutesLoading && httpRoutes && httpRoutes.length === 0 && (\n <MenuItem value=\"\">No HTTPRoutes available</MenuItem>\n )}\n {!httpRoutesLoading && httpRoutes && httpRoutes.map((route: any) => (\n <MenuItem\n key={`${route.metadata.namespace}/${route.metadata.name}`}\n value={`${route.metadata.namespace}/${route.metadata.name}`}\n >\n {route.metadata.name} ({route.metadata.namespace})\n </MenuItem>\n ))}\n </TextField>\n </Grid>\n {selectedHTTPRoute && (\n <Grid item xs={12}>\n <PlanPolicyDetails\n selectedPolicy={selectedPolicy}\n alertSeverity=\"warning\"\n alertMessage=\"No PlanPolicy found for this HTTPRoute. API keys and rate limiting may not be available.\"\n includeTopMargin={true}\n />\n </Grid>\n )}\n\n <Grid item xs={6}>\n <TextField\n fullWidth\n label=\"Contact Email\"\n value={contactEmail}\n onChange={e => setContactEmail(e.target.value)}\n placeholder=\"api-team@example.com\"\n margin=\"normal\"\n />\n </Grid>\n <Grid item xs={6}>\n <TextField\n fullWidth\n label=\"Contact Team\"\n value={contactTeam}\n onChange={e => setContactTeam(e.target.value)}\n placeholder=\"platform-team\"\n margin=\"normal\"\n />\n </Grid>\n <Grid item xs={6}>\n <TextField\n fullWidth\n label=\"Docs URL\"\n value={docsURL}\n onChange={e => setDocsURL(e.target.value)}\n placeholder=\"https://api.example.com/docs\"\n margin=\"normal\"\n />\n </Grid>\n <Grid item xs={6}>\n <TextField\n fullWidth\n label=\"OpenAPI Spec URL\"\n value={openAPISpec}\n onChange={e => setOpenAPISpec(e.target.value)}\n placeholder=\"https://api.example.com/openapi.json\"\n margin=\"normal\"\n />\n </Grid>\n </Grid>\n </DialogContent>\n <DialogActions>\n <Button onClick={handleClose}>Cancel</Button>\n <Button\n onClick={handleCreate}\n color=\"primary\"\n variant=\"contained\"\n disabled={creating || !name || !displayName || !description || !selectedHTTPRoute}\n >\n {creating ? 'Creating...' : 'Create'}\n </Button>\n </DialogActions>\n </Dialog>\n );\n};\n","import React, { useState, useEffect } from 'react';\nimport {\n Dialog,\n DialogTitle,\n DialogContent,\n DialogActions,\n Button,\n TextField,\n Box,\n Typography,\n Chip,\n Grid,\n MenuItem,\n makeStyles,\n} from '@material-ui/core';\nimport { useApi, configApiRef, fetchApiRef } from '@backstage/core-plugin-api';\nimport { Alert } from '@material-ui/lab';\nimport { Progress } from '@backstage/core-components';\nimport useAsync from 'react-use/lib/useAsync';\nimport { PlanPolicyDetails } from '../PlanPolicyDetailsCard';\n\nconst useStyles = makeStyles({\n asterisk: {\n color: '#f44336',\n },\n});\n\ninterface EditAPIProductDialogProps {\n open: boolean;\n onClose: () => void;\n onSuccess: () => void;\n namespace: string;\n name: string;\n}\n\nexport const EditAPIProductDialog = ({open, onClose, onSuccess, namespace, name}: EditAPIProductDialogProps) => {\n const classes = useStyles();\n const config = useApi(configApiRef);\n const fetchApi = useApi(fetchApiRef);\n const backendUrl = config.getString('backend.baseUrl');\n const [loading, setLoading] = useState(false);\n const [displayName, setDisplayName] = useState('');\n const [description, setDescription] = useState('');\n const [version, setVersion] = useState('v1');\n const [publishStatus, setPublishStatus] = useState<'Draft' | 'Published'>('Draft');\n const [approvalMode, setApprovalMode] = useState<'automatic' | 'manual'>('manual');\n const [tags, setTags] = useState<string[]>([]);\n const [targetRef, setTargetRef] = useState<any>(null);\n const [tagInput, setTagInput] = useState('');\n const [contactEmail, setContactEmail] = useState('');\n const [contactTeam, setContactTeam] = useState('');\n const [docsURL, setDocsURL] = useState('');\n const [openAPISpec, setOpenAPISpec] = useState('');\n const [error, setError] = useState('');\n const [saving, setSaving] = useState(false);\n\n // Load APIProduct data when dialog opens\n useEffect(() => {\n if (open && namespace && name) {\n setLoading(true);\n setError('');\n\n fetchApi.fetch(`${backendUrl}/api/kuadrant/apiproducts/${namespace}/${name}`)\n .then(async res => {\n if (!res.ok) {\n const errorData = await res.json();\n throw new Error(errorData.error || `Failed to fetch API product: ${res.status}`);\n }\n return res.json();\n })\n .then(data => {\n setDisplayName(data.spec.displayName || '');\n setDescription(data.spec.description || '');\n setVersion(data.spec.version || 'v1');\n setPublishStatus(data.spec.publishStatus || 'Draft');\n setApprovalMode(data.spec.approvalMode || 'manual');\n setTags(data.spec.tags || []);\n setTargetRef(data.spec.targetRef || null);\n setContactEmail(data.spec.contact?.email || '');\n setContactTeam(data.spec.contact?.team || '');\n setDocsURL(data.spec.documentation?.docsURL || '');\n setOpenAPISpec(data.spec.documentation?.openAPISpec || '');\n setLoading(false);\n })\n .catch(err => {\n setError(err.message || 'Failed to load API product');\n setLoading(false);\n });\n }\n }, [open, namespace, name, backendUrl, fetchApi]);\n\n // load planpolicies with full details to show associated plans\n const { value: planPolicies } = useAsync(async () => {\n if (!open) return null;\n const response = await fetchApi.fetch(`${backendUrl}/api/kuadrant/planpolicies`);\n return await response.json();\n }, [backendUrl, fetchApi, open]);\n\n // find planpolicy associated with targetRef\n const selectedPolicy = React.useMemo(() => {\n if (!planPolicies?.items || !targetRef) return null;\n\n return planPolicies.items.find((pp: any) => {\n const ref = pp.targetRef;\n return (\n ref?.kind === 'HTTPRoute' &&\n ref?.name === targetRef.name &&\n (!ref?.namespace || ref?.namespace === (targetRef.namespace || namespace))\n );\n });\n }, [planPolicies, targetRef, namespace]);\n\n const handleAddTag = () => {\n if (tagInput.trim() && !tags.includes(tagInput.trim())) {\n setTags([...tags, tagInput.trim()]);\n setTagInput('');\n }\n };\n\n const handleDeleteTag = (tagToDelete: string) => {\n setTags(tags.filter(tag => tag !== tagToDelete));\n };\n\n const handleSave = async () => {\n setError('');\n setSaving(true);\n\n try {\n const patch = {\n spec: {\n displayName,\n description,\n version,\n publishStatus,\n approvalMode,\n tags,\n targetRef,\n ...(contactEmail || contactTeam ? {\n contact: {\n ...(contactEmail && { email: contactEmail }),\n ...(contactTeam && { team: contactTeam }),\n },\n } : {}),\n ...(docsURL || openAPISpec ? {\n documentation: {\n ...(docsURL && { docsURL }),\n ...(openAPISpec && { openAPISpec }),\n },\n } : {}),\n },\n };\n\n const response = await fetchApi.fetch(\n `${backendUrl}/api/kuadrant/apiproducts/${namespace}/${name}`,\n {\n method: 'PATCH',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify(patch),\n }\n );\n\n if (!response.ok) {\n const errorData = await response.json();\n throw new Error(errorData.error || 'failed to update apiproduct');\n }\n\n onSuccess();\n onClose();\n } catch (err) {\n setError(err instanceof Error ? err.message : String(err));\n } finally {\n setSaving(false);\n }\n };\n\n return (\n <Dialog open={open} onClose={onClose} maxWidth=\"md\" fullWidth>\n <DialogTitle>Edit API Product</DialogTitle>\n <DialogContent>\n {error && (\n <Alert severity=\"error\" style={{ marginBottom: 16 }}>\n {error}\n </Alert>\n )}\n\n {loading ? (\n <Progress />\n ) : (\n <Grid container spacing={2}>\n <Grid item xs={6}>\n <TextField\n fullWidth\n label=\"Name\"\n value={name}\n disabled\n helperText=\"Kubernetes resource name (immutable)\"\n margin=\"normal\"\n />\n </Grid>\n <Grid item xs={6}>\n <TextField\n fullWidth\n label=\"Namespace\"\n value={namespace}\n disabled\n helperText=\"Derived from HTTPRoute (immutable)\"\n margin=\"normal\"\n />\n </Grid>\n <Grid item xs={6}>\n <TextField\n fullWidth\n label=\"Display Name\"\n value={displayName}\n onChange={e => setDisplayName(e.target.value)}\n placeholder=\"My API\"\n margin=\"normal\"\n required\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 margin=\"normal\"\n />\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=\"Draft: Hidden from catalog. Published: Visible in catalog.\"\n >\n <MenuItem value=\"Draft\">Draft (Hidden)</MenuItem>\n <MenuItem value=\"Published\">Published (Visible)</MenuItem>\n </TextField>\n </Grid>\n <Grid item xs={6}>\n <TextField\n fullWidth\n select\n label=\"Approval Mode\"\n value={approvalMode}\n onChange={e => setApprovalMode(e.target.value as 'automatic' | 'manual')}\n margin=\"normal\"\n helperText=\"Automatic: keys created immediately. Manual: requires approval.\"\n >\n <MenuItem value=\"manual\">Manual</MenuItem>\n <MenuItem value=\"automatic\">Automatic</MenuItem>\n </TextField>\n </Grid>\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 InputLabelProps={{\n classes: {\n asterisk: classes.asterisk,\n },\n }}\n />\n </Grid>\n\n <Grid item xs={12}>\n <Typography variant=\"subtitle2\" gutterBottom style={{ marginTop: 16 }}>\n Tags\n </Typography>\n <Box display=\"flex\" flexWrap=\"wrap\" marginBottom={1} style={{ gap: 8 }}>\n {tags.map(tag => (\n <Chip\n key={tag}\n label={tag}\n onDelete={() => handleDeleteTag(tag)}\n size=\"small\"\n />\n ))}\n </Box>\n <Box display=\"flex\" style={{ gap: 8 }}>\n <TextField\n fullWidth\n size=\"small\"\n value={tagInput}\n onChange={e => setTagInput(e.target.value)}\n onKeyPress={e => e.key === 'Enter' && handleAddTag()}\n placeholder=\"Add tag\"\n />\n <Button onClick={handleAddTag} variant=\"outlined\" size=\"small\">\n Add\n </Button>\n </Box>\n </Grid>\n {targetRef && (\n <>\n <Grid item xs={12}>\n <TextField\n fullWidth\n label=\"HTTPRoute\"\n value={`${targetRef.namespace || namespace}/${targetRef.name}`}\n disabled\n helperText=\"Target HTTPRoute (immutable)\"\n margin=\"normal\"\n />\n </Grid>\n\n <Grid item xs={12}>\n <PlanPolicyDetails\n selectedPolicy={selectedPolicy}\n alertSeverity=\"info\"\n alertMessage=\"No PlanPolicy found for this HTTPRoute.\"\n includeTopMargin={false}\n />\n </Grid>\n </>\n )}\n\n <Grid item xs={6}>\n <TextField\n fullWidth\n label=\"Contact Email\"\n value={contactEmail}\n onChange={e => setContactEmail(e.target.value)}\n placeholder=\"api-team@example.com\"\n margin=\"normal\"\n />\n </Grid>\n <Grid item xs={6}>\n <TextField\n fullWidth\n label=\"Contact Team\"\n value={contactTeam}\n onChange={e => setContactTeam(e.target.value)}\n placeholder=\"platform-team\"\n margin=\"normal\"\n />\n </Grid>\n <Grid item xs={6}>\n <TextField\n fullWidth\n label=\"Docs URL\"\n value={docsURL}\n onChange={e => setDocsURL(e.target.value)}\n placeholder=\"https://api.example.com/docs\"\n margin=\"normal\"\n />\n </Grid>\n <Grid item xs={6}>\n <TextField\n fullWidth\n label=\"OpenAPI Spec URL\"\n value={openAPISpec}\n onChange={e => setOpenAPISpec(e.target.value)}\n placeholder=\"https://api.example.com/openapi.json\"\n margin=\"normal\"\n />\n </Grid>\n </Grid>\n )}\n </DialogContent>\n <DialogActions>\n <Button onClick={onClose}>Cancel</Button>\n <Button\n onClick={handleSave}\n color=\"primary\"\n variant=\"contained\"\n disabled={saving || loading || !displayName || !description}\n >\n {saving ? 'Saving...' : 'Save'}\n </Button>\n </DialogActions>\n </Dialog>\n );\n};\n","import React, { useState } from 'react';\nimport { Typography, Grid, Box, Chip, Button, IconButton, Dialog, DialogTitle, DialogContent, DialogContentText, DialogActions } 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 {\n InfoCard,\n Header,\n Page,\n Content,\n SupportButton,\n Progress,\n ResponseErrorPanel,\n Link,\n Table,\n TableColumn,\n} from '@backstage/core-components';\nimport useAsync from 'react-use/lib/useAsync';\nimport { useApi, configApiRef, fetchApiRef } from '@backstage/core-plugin-api';\nimport { ApprovalQueueCard } from '../ApprovalQueueCard';\nimport { MyApiKeysCard } from '../MyApiKeysCard';\nimport { PermissionGate } from '../PermissionGate';\nimport { CreateAPIProductDialog } from '../CreateAPIProductDialog';\nimport {\n kuadrantApiProductCreatePermission,\n kuadrantApiProductDeleteOwnPermission,\n kuadrantApiProductDeleteAllPermission,\n kuadrantApiProductUpdateOwnPermission,\n kuadrantApiProductUpdateAllPermission,\n kuadrantApiProductListPermission,\n kuadrantApiKeyRequestReadAllPermission,\n kuadrantApiKeyRequestReadOwnPermission,\n kuadrantPlanPolicyListPermission,\n} from '../../permissions';\nimport { useKuadrantPermission } from '../../utils/permissions';\nimport { EditAPIProductDialog } from '../EditAPIProductDialog';\n\ntype KuadrantResource = {\n metadata: {\n name: string;\n namespace: string;\n creationTimestamp: string;\n };\n spec?: any;\n};\n\ntype KuadrantList = {\n items: KuadrantResource[];\n};\n\nexport const ResourceList = () => {\n const config = useApi(configApiRef);\n const fetchApi = useApi(fetchApiRef);\n const backendUrl = config.getString('backend.baseUrl');\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<{ namespace: string; name: string } | null>(null);\n const [apiProductToEdit, setApiProductToEdit] = useState<{ namespace: string; name: string } | null>(null);\n const [deleting, setDeleting] = useState(false);\n\n const {\n allowed: canCreateApiProduct,\n loading: createPermissionLoading,\n error: createPermissionError,\n } = useKuadrantPermission(kuadrantApiProductCreatePermission);\n\n const {\n allowed: canViewAllRequests,\n loading: approvalQueueAllPermissionLoading,\n } = useKuadrantPermission(kuadrantApiKeyRequestReadAllPermission);\n\n const {\n allowed: canViewOwnRequests,\n loading: approvalQueueOwnPermissionLoading,\n error: approvalQueuePermissionError,\n } = useKuadrantPermission(kuadrantApiKeyRequestReadOwnPermission);\n\n const canViewApprovalQueue = canViewAllRequests || canViewOwnRequests;\n const approvalQueuePermissionLoading = approvalQueueAllPermissionLoading || approvalQueueOwnPermissionLoading;\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 {\n allowed: canUpdateOwnApiProduct,\n } = useKuadrantPermission(kuadrantApiProductUpdateOwnPermission);\n\n const {\n allowed: canUpdateAllApiProducts,\n } = useKuadrantPermission(kuadrantApiProductUpdateAllPermission);\n\n const canDeleteApiProduct = canDeleteOwnApiProduct || canDeleteAllApiProducts;\n const canUpdateApiProduct = canUpdateOwnApiProduct || canUpdateAllApiProducts;\n const deletePermissionLoading = deleteOwnPermissionLoading || deleteAllPermissionLoading;\n\n const {\n allowed: canListPlanPolicies,\n loading: planPolicyPermissionLoading,\n error: planPolicyPermissionError,\n } = useKuadrantPermission(kuadrantPlanPolicyListPermission);\n\n const { value: apiProducts, loading: apiProductsLoading, error: apiProductsError } = useAsync(async (): Promise<KuadrantList> => {\n const response = await fetchApi.fetch(`${backendUrl}/api/kuadrant/apiproducts`);\n return await response.json();\n }, [backendUrl, fetchApi, refreshTrigger]);\n\n const { value: planPolicies, loading: planPoliciesLoading, error: planPoliciesError } = useAsync(async (): Promise<KuadrantList> => {\n const response = await fetchApi.fetch(`${backendUrl}/api/kuadrant/planpolicies`);\n return await response.json();\n }, [backendUrl, fetchApi, refreshTrigger]);\n\n const loading = apiProductsLoading || planPoliciesLoading || createPermissionLoading || approvalQueuePermissionLoading || deletePermissionLoading || planPolicyPermissionLoading;\n const error = apiProductsError || planPoliciesError;\n const permissionError = createPermissionError || approvalQueuePermissionError || deletePermissionError || planPolicyPermissionError;\n\n const handleCreateSuccess = () => {\n setRefreshTrigger(prev => prev + 1);\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 };\n\n const handleDeleteClick = (namespace: string, name: string) => {\n setApiProductToDelete({ namespace, name });\n setDeleteDialogOpen(true);\n };\n\n const handleDeleteConfirm = async () => {\n if (!apiProductToDelete) return;\n\n setDeleting(true);\n try {\n const response = await fetchApi.fetch(\n `${backendUrl}/api/kuadrant/apiproducts/${apiProductToDelete.namespace}/${apiProductToDelete.name}`,\n { method: 'DELETE' }\n );\n\n if (!response.ok) {\n throw new Error('failed to delete apiproduct');\n }\n\n setRefreshTrigger(prev => prev + 1);\n } catch (err) {\n console.error('error deleting apiproduct:', err);\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 formatDate = (dateString: string) => {\n const date = new Date(dateString);\n return date.toLocaleDateString('en-GB', {\n year: 'numeric',\n month: 'short',\n day: 'numeric',\n });\n };\n\n const columns: TableColumn[] = [\n {\n title: 'Name',\n field: 'name',\n render: (row: any) => {\n const publishStatus = row.spec?.publishStatus;\n const isPublished = publishStatus === 'Published';\n const displayName = row.spec?.displayName ?? row.metadata.name;\n\n if (isPublished) {\n return (\n <Link to={`/catalog/default/api/${row.metadata.name}/api-product`}>\n <strong>{displayName}</strong>\n </Link>\n );\n }\n\n return (\n <span className=\"text-muted\">\n <strong>{displayName}</strong>\n </span>\n );\n },\n },\n {\n title: 'Resource Name',\n field: 'metadata.name',\n },\n {\n title: 'Version',\n field: 'spec.version',\n render: (row: any) => row.spec?.version || '-',\n },\n {\n title: 'HTTPRoute',\n field: 'spec.targetRef.name',\n render: (row: any) => row.spec?.targetRef?.name || '-',\n },\n {\n title: 'Publish 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: 'Approval Mode',\n field: 'spec.approvalMode',\n render: (row: any) => {\n const mode = row.spec?.approvalMode || 'manual';\n return (\n <Chip\n label={mode}\n size=\"small\"\n color={mode === 'automatic' ? 'secondary' : 'default'}\n />\n );\n },\n },\n {\n title: 'Namespace',\n field: 'metadata.namespace',\n },\n {\n title: 'Created',\n field: 'metadata.creationTimestamp',\n render: (row: any) => formatDate(row.metadata.creationTimestamp),\n },\n {\n title: 'Actions',\n field: 'actions',\n render: (row: any) => (\n <Box display=\"flex\" style={{ gap: 4 }}>\n {canUpdateApiProduct && (\n <IconButton\n size=\"small\"\n onClick={() => handleEditClick(row.metadata.namespace, row.metadata.name)}\n title=\"Edit API Product\"\n >\n <EditIcon fontSize=\"small\" />\n </IconButton>\n )}\n\n {canDeleteApiProduct && (\n <IconButton\n size=\"small\"\n onClick={() => handleDeleteClick(row.metadata.namespace, row.metadata.name)}\n title=\"Delete API Product\"\n >\n <DeleteIcon fontSize=\"small\" />\n </IconButton>\n )}\n </Box>\n ),\n },\n ];\n\n const planPolicyColumns: TableColumn[] = [\n {\n title: 'Name',\n field: 'metadata.name',\n render: (row: any) => (\n <Link to={`/kuadrant/planpolicy/${row.metadata.namespace}/${row.metadata.name}`}>\n <strong>{row.metadata.name}</strong>\n </Link>\n ),\n },\n {\n title: 'Namespace',\n field: 'metadata.namespace',\n },\n ];\n\n const renderResources = (resources: KuadrantResource[] | undefined) => {\n if (!resources || resources.length === 0) {\n return <Typography variant=\"body2\" color=\"textSecondary\">No API products found</Typography>;\n }\n return (\n <Table\n options={{ paging: false, search: false, toolbar: false }}\n columns={columns}\n data={resources}\n />\n );\n };\n\n const renderPlanPolicies = (resources: KuadrantResource[] | undefined) => {\n if (!resources || resources.length === 0) {\n return <Typography variant=\"body2\" color=\"textSecondary\">No plan policies found</Typography>;\n }\n return (\n <Table\n options={{ paging: false, search: false, toolbar: false }}\n columns={planPolicyColumns}\n data={resources}\n />\n );\n };\n\n return (\n <Page themeId=\"tool\">\n <Header title=\"Kuadrant\" subtitle=\"API management for Kubernetes\">\n <SupportButton>Manage API products and access requests</SupportButton>\n </Header>\n <Content>\n {loading && <Progress />}\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: {createPermissionError ? 'kuadrant.apiproduct.create' :\n deletePermissionError ? 'kuadrant.apiproduct.delete' :\n approvalQueuePermissionError ? 'kuadrant.apikeyrequest.read.all' :\n planPolicyPermissionError ? 'kuadrant.planpolicy.list' : '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 && (\n <Grid container spacing={3} direction=\"column\">\n <Grid item>\n <MyApiKeysCard />\n </Grid>\n\n <Grid item>\n <InfoCard\n title=\"API Products\"\n action={\n canCreateApiProduct ? (\n <Box display=\"flex\" alignItems=\"center\" height=\"100%\" mt={1}>\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 </Box>\n ) : undefined\n }\n >\n {renderResources(apiProducts?.items)}\n </InfoCard>\n </Grid>\n\n {canListPlanPolicies && (\n <Grid item>\n <InfoCard title=\"Plan Policies\">\n {renderPlanPolicies(planPolicies?.items)}\n </InfoCard>\n </Grid>\n )}\n\n {canViewApprovalQueue && (\n <Grid item>\n <ApprovalQueueCard />\n </Grid>\n )}\n </Grid>\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 <Dialog open={deleteDialogOpen} onClose={handleDeleteCancel}>\n <DialogTitle>Delete API Product</DialogTitle>\n <DialogContent>\n <DialogContentText>\n Are you sure you want to delete {apiProductToDelete?.name} from namespace {apiProductToDelete?.namespace}?\n This will permanently remove the API Product from Kubernetes.\n </DialogContentText>\n </DialogContent>\n <DialogActions>\n <Button onClick={handleDeleteCancel} color=\"primary\">\n Cancel\n </Button>\n <Button onClick={handleDeleteConfirm} color=\"secondary\" disabled={deleting}>\n {deleting ? 'Deleting...' : 'Delete'}\n </Button>\n </DialogActions>\n </Dialog>\n </Content>\n </Page>\n );\n};\n\nexport const KuadrantPage = () => {\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":["EditAPIKeyRequestDialog","open","onClose","onSuccess","request","availablePlans","config","useApi","configApiRef","fetchApi","fetchApiRef","backendUrl","getString","planTier","setPlanTier","useState","useCase","setUseCase","saving","setSaving","error","setError","useEffect","spec","handleClose","Dialog","maxWidth","fullWidth","DialogTitle","DialogContent","Box","mb","p","bgcolor","color","borderRadius","Typography","variant","FormControl","margin","InputLabel","Select","value","onChange","e","target","disabled","map","plan","limitDesc","Object","entries","limits","key","val","join","MenuItem","tier","TextField","label","placeholder","multiline","rows","helperText","DialogActions","Button","onClick","async","patch","trim","response","fetch","metadata","namespace","name","method","headers","body","JSON","stringify","ok","errorData","json","catch","Error","status","err","console","message","MyApiKeysCard","identityApi","identityApiRef","selectedTab","setSelectedTab","setUserId","visibleKeys","setVisibleKeys","Set","menuAnchor","setMenuAnchor","menuRequest","setMenuRequest","editDialogState","setEditDialogState","plans","refresh","setRefresh","useAsync","identity","getBackstageIdentity","extractedUserId","userEntityRef","split","log","requests","loading","items","InfoCard","title","allRequests","approvedRequests","filter","r","phase","pendingRequests","rejectedRequests","handleMenuClose","handleEdit","apiProductResponse","apiNamespace","apiName","apiProduct","handleDelete","window","confirm","alert","columns","field","render","row","Link","to","strong","Chip","size","Tooltip","placement","style","overflow","textOverflow","whiteSpace","reason","reviewedBy","reviewedDate","reviewedAt","Date","toLocaleDateString","apiKey","isVisible","has","display","alignItems","gap","fontFamily","fontSize","repeat","IconButton","toggleKeyVisibility","keyName","prev","newSet","delete","add","VisibilityOffIcon","VisibilityIcon","creationTimestamp","date","stopPropagation","rect","currentTarget","getBoundingClientRect","top","bottom","left","aria-controls","undefined","aria-haspopup","MoreVertIcon","tabData","getTabData","tabColumns","col","getTabColumns","subheader","length","Tabs","_","newValue","indicatorColor","textColor","Tab","textAlign","Table","options","paging","pageSize","search","toolbar","data","item","id","Menu","Boolean","anchorReference","anchorPosition","push","PermissionGate","children","permission","fallback","errorMessage","allowed","useKuadrantPermission","Progress","mt","PlanPolicyDetails","selectedPolicy","alertSeverity","alertMessage","includeTopMargin","border","gutterBottom","fontWeight","marginTop","flexWrap","idx","limitText","daily","monthly","yearly","some","description","Alert","severity","useStyles","makeStyles","asterisk","CreateAPIProductDialog","classes","setName","displayName","setDisplayName","setDescription","version","setVersion","approvalMode","setApprovalMode","publishStatus","setPublishStatus","tags","setTags","tagInput","setTagInput","selectedHTTPRoute","setSelectedHTTPRoute","contactEmail","setContactEmail","contactTeam","setContactTeam","docsURL","setDocsURL","openAPISpec","setOpenAPISpec","creating","setCreating","httpRoutes","httpRoutesLoading","route","annotations","planPolicies","selectedRouteInfo","routeNamespace","routeName","find","pp","ref","targetRef","kind","handleAddTag","includes","marginBottom","Grid","container","spacing","xs","required","InputLabelProps","select","tag","onDelete","handleDeleteTag","tagToDelete","onKeyPress","selectedRouteNamespace","selectedRouteName","apiVersion","group","contact","email","team","documentation","String","EditAPIProductDialog","setLoading","setTargetRef","then","res","React","ResourceList","createDialogOpen","setCreateDialogOpen","editDialogOpen","setEditDialogOpen","refreshTrigger","setRefreshTrigger","deleteDialogOpen","setDeleteDialogOpen","apiProductToDelete","setApiProductToDelete","apiProductToEdit","setApiProductToEdit","deleting","setDeleting","canCreateApiProduct","createPermissionLoading","createPermissionError","kuadrantApiProductCreatePermission","canViewAllRequests","approvalQueueAllPermissionLoading","kuadrantApiKeyRequestReadAllPermission","canViewOwnRequests","approvalQueueOwnPermissionLoading","approvalQueuePermissionError","kuadrantApiKeyRequestReadOwnPermission","canViewApprovalQueue","approvalQueuePermissionLoading","canDeleteOwnApiProduct","deleteOwnPermissionLoading","kuadrantApiProductDeleteOwnPermission","canDeleteAllApiProducts","deleteAllPermissionLoading","deletePermissionError","kuadrantApiProductDeleteAllPermission","canUpdateOwnApiProduct","kuadrantApiProductUpdateOwnPermission","canUpdateAllApiProducts","kuadrantApiProductUpdateAllPermission","canDeleteApiProduct","canUpdateApiProduct","deletePermissionLoading","canListPlanPolicies","planPolicyPermissionLoading","planPolicyPermissionError","kuadrantPlanPolicyListPermission","apiProducts","apiProductsLoading","apiProductsError","planPoliciesLoading","planPoliciesError","permissionError","handleDeleteCancel","isPublished","span","className","mode","formatDate","dateString","year","month","day","handleEditClick","EditIcon","handleDeleteClick","DeleteIcon","planPolicyColumns","Page","themeId","Header","subtitle","SupportButton","Content","ResponseErrorPanel","direction","action","height","startIcon","AddIcon","resources","renderPlanPolicies","ApprovalQueueCard","DialogContentText","KuadrantPage","kuadrantApiProductListPermission"],"sourceRoot":""}
|
package/package.json
CHANGED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"static/7632.646001ce.chunk.js","mappings":"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","sources":["webpack://internal.plugin-kuadrant/./src/components/EditAPIKeyRequestDialog/EditAPIKeyRequestDialog.tsx","webpack://internal.plugin-kuadrant/./src/components/MyApiKeysCard/MyApiKeysCard.tsx","webpack://internal.plugin-kuadrant/./src/components/PermissionGate/PermissionGate.tsx","webpack://internal.plugin-kuadrant/./src/components/PlanPolicyDetailsCard/PlanPolicyDetails.tsx","webpack://internal.plugin-kuadrant/./src/components/CreateAPIProductDialog/CreateAPIProductDialog.tsx","webpack://internal.plugin-kuadrant/./src/components/EditAPIProductDialog/EditAPIProductDialog.tsx","webpack://internal.plugin-kuadrant/./src/components/KuadrantPage/KuadrantPage.tsx"],"sourcesContent":["import React, { useState, useEffect } from 'react';\nimport {\n Dialog,\n DialogTitle,\n DialogContent,\n DialogActions,\n Button,\n TextField,\n Box,\n Typography,\n FormControl,\n InputLabel,\n Select,\n MenuItem,\n} from '@material-ui/core';\nimport { useApi, configApiRef, fetchApiRef } from '@backstage/core-plugin-api';\nimport { APIKeyRequest } from '../../types/api-management';\n\ninterface EditAPIKeyRequestDialogProps {\n open: boolean;\n onClose: () => void;\n onSuccess: () => void;\n request: APIKeyRequest;\n availablePlans: Array<{\n tier: string;\n description?: string;\n limits?: any;\n }>;\n}\n\nexport const EditAPIKeyRequestDialog = ({\n open,\n onClose,\n onSuccess,\n request,\n availablePlans,\n}: EditAPIKeyRequestDialogProps) => {\n const config = useApi(configApiRef);\n const fetchApi = useApi(fetchApiRef);\n const backendUrl = config.getString('backend.baseUrl');\n\n const [planTier, setPlanTier] = useState('');\n const [useCase, setUseCase] = useState('');\n const [saving, setSaving] = useState(false);\n const [error, setError] = useState('');\n\n useEffect(() => {\n if (open && request) {\n setPlanTier(request.spec.planTier || '');\n setUseCase(request.spec.useCase || '');\n setError('');\n }\n }, [open, request]);\n\n const handleSave = async () => {\n if (!planTier) {\n setError('Please select a plan tier');\n return;\n }\n\n setError('');\n setSaving(true);\n\n try {\n const patch = {\n spec: {\n planTier,\n useCase: useCase.trim(),\n },\n };\n\n const response = await fetchApi.fetch(\n `${backendUrl}/api/kuadrant/requests/${request.metadata.namespace}/${request.metadata.name}`,\n {\n method: 'PATCH',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify(patch),\n }\n );\n\n if (!response.ok) {\n const errorData = await response.json().catch(() => ({}));\n throw new Error(errorData.error || `Failed to update request: ${response.status}`);\n }\n\n onSuccess();\n onClose();\n } catch (err) {\n console.error('Error updating API key request:', err);\n setError(err instanceof Error ? err.message : 'Unknown error occurred');\n } finally {\n setSaving(false);\n }\n };\n\n const handleClose = () => {\n if (!saving) {\n setError('');\n onClose();\n }\n };\n\n return (\n <Dialog open={open} onClose={handleClose} maxWidth=\"sm\" fullWidth>\n <DialogTitle>Edit API Access Request</DialogTitle>\n <DialogContent>\n {error && (\n <Box mb={2} p={2} bgcolor=\"error.main\" color=\"error.contrastText\" borderRadius={1}>\n <Typography variant=\"body2\">{error}</Typography>\n </Box>\n )}\n\n <FormControl fullWidth margin=\"normal\">\n <InputLabel>Plan Tier</InputLabel>\n <Select\n value={planTier}\n onChange={(e) => setPlanTier(e.target.value as string)}\n disabled={saving}\n >\n {availablePlans.map((plan) => {\n const limitDesc = Object.entries(plan.limits || {})\n .map(([key, val]) => `${val} per ${key}`)\n .join(', ');\n return (\n <MenuItem key={plan.tier} value={plan.tier}>\n {plan.tier} {limitDesc ? `(${limitDesc})` : ''}\n </MenuItem>\n );\n })}\n </Select>\n </FormControl>\n\n <TextField\n label=\"Use Case\"\n placeholder=\"Describe how you plan to use this API\"\n multiline\n rows={3}\n fullWidth\n margin=\"normal\"\n value={useCase}\n onChange={(e) => setUseCase(e.target.value)}\n disabled={saving}\n helperText=\"Explain your intended use of this API for admin review\"\n />\n </DialogContent>\n <DialogActions>\n <Button onClick={handleClose} disabled={saving}>\n Cancel\n </Button>\n <Button\n onClick={handleSave}\n color=\"primary\"\n disabled={!planTier || saving}\n >\n {saving ? 'Saving...' : 'Save Changes'}\n </Button>\n </DialogActions>\n </Dialog>\n );\n};\n","import React, { useState } from 'react';\nimport { InfoCard, Table, TableColumn, Link } from '@backstage/core-components';\nimport { useApi, configApiRef, fetchApiRef, identityApiRef } from '@backstage/core-plugin-api';\nimport useAsync from 'react-use/lib/useAsync';\nimport { Box, Chip, Typography, Tabs, Tab, IconButton, Tooltip, Menu, MenuItem } from '@material-ui/core';\nimport VisibilityIcon from '@material-ui/icons/Visibility';\nimport VisibilityOffIcon from '@material-ui/icons/VisibilityOff';\nimport MoreVertIcon from '@material-ui/icons/MoreVert';\nimport { EditAPIKeyRequestDialog } from '../EditAPIKeyRequestDialog';\nimport { APIKeyRequest } from '../../types/api-management';\n\nexport const MyApiKeysCard = () => {\n const config = useApi(configApiRef);\n const fetchApi = useApi(fetchApiRef);\n const identityApi = useApi(identityApiRef);\n const backendUrl = config.getString('backend.baseUrl');\n const [selectedTab, setSelectedTab] = useState(0);\n const [, setUserId] = useState<string>('');\n const [visibleKeys, setVisibleKeys] = useState<Set<string>>(new Set());\n const [menuAnchor, setMenuAnchor] = useState<{ top: number; left: number } | null>(null);\n const [menuRequest, setMenuRequest] = useState<APIKeyRequest | null>(null);\n const [editDialogState, setEditDialogState] = useState<{ open: boolean; request: APIKeyRequest | null; plans: any[] }>({\n open: false,\n request: null,\n plans: [],\n });\n const [refresh, setRefresh] = useState(0);\n\n useAsync(async () => {\n const identity = await identityApi.getBackstageIdentity();\n const extractedUserId = identity.userEntityRef.split('/')[1] || 'guest';\n console.log(`MyApiKeysCard: setting userId from userEntityRef: ${identity.userEntityRef} -> \"${extractedUserId}\"`);\n setUserId(extractedUserId);\n }, [identityApi]);\n\n const { value: requests, loading, error } = useAsync(async () => {\n const response = await fetchApi.fetch(\n `${backendUrl}/api/kuadrant/requests/my`\n );\n if (!response.ok) {\n throw new Error('failed to fetch requests');\n }\n const data = await response.json();\n return data.items || [];\n }, [backendUrl, fetchApi, refresh]);\n\n if (loading) {\n return (\n <InfoCard title=\"My API Keys\">\n <Typography>Loading...</Typography>\n </InfoCard>\n );\n }\n\n if (error) {\n return (\n <InfoCard title=\"My API Keys\">\n <Typography color=\"error\">Error loading API keys: {error.message}</Typography>\n </InfoCard>\n );\n }\n\n const allRequests = requests || [];\n const approvedRequests = allRequests.filter((r: APIKeyRequest) => r.status?.phase === 'Approved');\n const pendingRequests = allRequests.filter((r: APIKeyRequest) => !r.status?.phase || r.status.phase === 'Pending');\n const rejectedRequests = allRequests.filter((r: APIKeyRequest) => r.status?.phase === 'Rejected');\n\n const toggleKeyVisibility = (keyName: string) => {\n setVisibleKeys(prev => {\n const newSet = new Set(prev);\n if (newSet.has(keyName)) {\n newSet.delete(keyName);\n } else {\n newSet.add(keyName);\n }\n return newSet;\n });\n };\n\n const handleMenuClose = () => {\n setMenuAnchor(null);\n setMenuRequest(null);\n };\n\n const handleEdit = async () => {\n if (!menuRequest) return;\n\n const request = menuRequest;\n handleMenuClose();\n\n // Fetch available plans for this API\n try {\n const apiProductResponse = await fetchApi.fetch(\n `${backendUrl}/api/kuadrant/apiproducts/${request.spec.apiNamespace}/${request.spec.apiName}`\n );\n\n if (apiProductResponse.ok) {\n const apiProduct = await apiProductResponse.json();\n const plans = apiProduct.spec?.plans || [];\n setEditDialogState({ open: true, request, plans });\n } else {\n console.error('Failed to fetch API product');\n setEditDialogState({ open: true, request, plans: [] });\n }\n } catch (err) {\n console.error('Error fetching plans:', err);\n setEditDialogState({ open: true, request, plans: [] });\n }\n };\n\n const handleDelete = async () => {\n if (!menuRequest) return;\n\n const request = menuRequest;\n handleMenuClose();\n\n if (!window.confirm('Are you sure you want to delete this request?')) {\n return;\n }\n\n try {\n const response = await fetchApi.fetch(\n `${backendUrl}/api/kuadrant/requests/${request.metadata.namespace}/${request.metadata.name}`,\n { method: 'DELETE' }\n );\n\n if (!response.ok) {\n throw new Error('Failed to delete request');\n }\n\n setRefresh(r => r + 1);\n } catch (err) {\n console.error('Error deleting request:', err);\n alert('Failed to delete request');\n }\n };\n\n const columns: TableColumn<APIKeyRequest>[] = [\n {\n title: 'API Product',\n field: 'spec.apiName',\n render: (row: APIKeyRequest) => (\n <Link to={`/catalog/default/api/${row.spec.apiName}/api-keys`}>\n <strong>{row.spec.apiName}</strong>\n </Link>\n ),\n },\n {\n title: 'Plan',\n field: 'spec.planTier',\n render: (row: APIKeyRequest) => {\n const color = row.spec.planTier === 'gold' ? 'primary' :\n row.spec.planTier === 'silver' ? 'default' : 'secondary';\n return <Chip label={row.spec.planTier} color={color} size=\"small\" />;\n },\n },\n {\n title: 'Use Case',\n field: 'spec.useCase',\n render: (row: APIKeyRequest) => {\n if (!row.spec.useCase) {\n return <Typography variant=\"body2\">-</Typography>;\n }\n return (\n <Tooltip title={row.spec.useCase} placement=\"top\">\n <Typography\n variant=\"body2\"\n style={{\n maxWidth: '200px',\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n whiteSpace: 'nowrap',\n }}\n >\n {row.spec.useCase}\n </Typography>\n </Tooltip>\n );\n },\n },\n {\n title: 'Status',\n field: 'status.phase',\n render: (row: APIKeyRequest) => {\n const phase = row.status?.phase || 'Pending';\n const color = phase === 'Approved' ? 'primary' :\n phase === 'Rejected' ? 'secondary' : 'default';\n return <Chip label={phase} color={color} size=\"small\" />;\n },\n },\n {\n title: 'Reason',\n render: (row: APIKeyRequest) => {\n if (row.status?.reason) {\n const color = row.status.phase === 'Rejected' ? 'error' : 'textPrimary';\n return (\n <Tooltip title={row.status.reason} placement=\"top\">\n <Typography\n variant=\"body2\"\n color={color}\n style={{\n maxWidth: '200px',\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n whiteSpace: 'nowrap',\n }}\n >\n {row.status.reason}\n </Typography>\n </Tooltip>\n );\n }\n return <Typography variant=\"body2\" color=\"textSecondary\">-</Typography>;\n },\n },\n {\n title: 'Reviewed By',\n render: (row: APIKeyRequest) => {\n if ((row.status?.phase === 'Approved' || row.status?.phase === 'Rejected') && row.status.reviewedBy) {\n const reviewedDate = row.status.reviewedAt ? new Date(row.status.reviewedAt).toLocaleDateString() : '';\n return (\n <Box>\n <Typography variant=\"body2\">{row.status.reviewedBy}</Typography>\n {reviewedDate && (\n <Typography variant=\"caption\" color=\"textSecondary\">\n {reviewedDate}\n </Typography>\n )}\n </Box>\n );\n }\n return <Typography variant=\"body2\" color=\"textSecondary\">-</Typography>;\n },\n },\n {\n title: 'API Key',\n render: (row: APIKeyRequest) => {\n if (row.status?.phase === 'Approved' && row.status.apiKey) {\n const isVisible = visibleKeys.has(row.metadata.name);\n return (\n <Box display=\"flex\" alignItems=\"center\" style={{ gap: 8 }}>\n <Box fontFamily=\"monospace\" fontSize=\"0.875rem\">\n {isVisible ? row.status.apiKey : '•'.repeat(20) + '...'}\n </Box>\n <Tooltip title={isVisible ? 'hide key' : 'show key'}>\n <IconButton\n size=\"small\"\n onClick={() => toggleKeyVisibility(row.metadata.name)}\n >\n {isVisible ? <VisibilityOffIcon fontSize=\"small\" /> : <VisibilityIcon fontSize=\"small\" />}\n </IconButton>\n </Tooltip>\n </Box>\n );\n }\n return <Typography variant=\"body2\" color=\"textSecondary\">-</Typography>;\n },\n },\n {\n title: 'Requested',\n field: 'metadata.creationTimestamp',\n render: (row: APIKeyRequest) => {\n if (!row.metadata.creationTimestamp) {\n return <Typography variant=\"body2\">-</Typography>;\n }\n const date = new Date(row.metadata.creationTimestamp);\n return <Typography variant=\"body2\">{date.toLocaleDateString()}</Typography>;\n },\n },\n {\n title: '',\n render: (row: APIKeyRequest) => {\n return (\n <IconButton\n size=\"small\"\n onClick={(e) => {\n e.stopPropagation();\n const rect = e.currentTarget.getBoundingClientRect();\n setMenuAnchor({ top: rect.bottom, left: rect.left });\n setMenuRequest(row);\n }}\n aria-controls={menuAnchor ? 'myapikeys-menu' : undefined}\n aria-haspopup=\"true\"\n >\n <MoreVertIcon />\n </IconButton>\n );\n },\n },\n ];\n\n const getTabData = () => {\n switch (selectedTab) {\n case 0:\n return approvedRequests;\n case 1:\n return pendingRequests;\n case 2:\n return rejectedRequests;\n default:\n return allRequests;\n }\n };\n\n const getTabColumns = () => {\n switch (selectedTab) {\n case 0: // Active - no Reason\n return columns.filter(col => col.title !== 'Reason');\n case 1: // Pending - no Reason, Reviewed By, API Key\n return columns.filter(col =>\n col.title !== 'Reason' &&\n col.title !== 'Reviewed By' &&\n col.title !== 'API Key'\n );\n case 2: // Rejected - no API Key\n return columns.filter(col => col.title !== 'API Key');\n default:\n return columns;\n }\n };\n\n const tabData = getTabData();\n const tabColumns = getTabColumns();\n const isPending = (row: APIKeyRequest) => !row.status || row.status.phase === 'Pending';\n\n return (\n <>\n <InfoCard\n title=\"My API Keys\"\n subheader={`${approvedRequests.length} active, ${pendingRequests.length} pending`}\n >\n <Box mb={2}>\n <Tabs\n value={selectedTab}\n onChange={(_, newValue) => setSelectedTab(newValue)}\n indicatorColor=\"primary\"\n textColor=\"primary\"\n >\n <Tab label={`Active (${approvedRequests.length})`} />\n <Tab label={`Pending (${pendingRequests.length})`} />\n <Tab label={`Rejected (${rejectedRequests.length})`} />\n </Tabs>\n </Box>\n {tabData.length === 0 ? (\n <Box p={3} textAlign=\"center\">\n <Typography variant=\"body1\" color=\"textSecondary\">\n {selectedTab === 0 && 'No active API keys. Request access to an API to get started.'}\n {selectedTab === 1 && 'No pending requests.'}\n {selectedTab === 2 && 'No rejected requests.'}\n </Typography>\n </Box>\n ) : (\n <Table\n options={{\n paging: tabData.length > 10,\n pageSize: 10,\n search: false,\n toolbar: false,\n }}\n columns={tabColumns}\n data={tabData.map((item: APIKeyRequest) => ({\n ...item,\n id: item.metadata.name,\n }))}\n />\n )}\n </InfoCard>\n\n <Menu\n id=\"myapikeys-menu\"\n open={Boolean(menuAnchor)}\n onClose={handleMenuClose}\n anchorReference=\"anchorPosition\"\n anchorPosition={menuAnchor || { top: 0, left: 0 }}\n >\n {menuRequest && (() => {\n const items = [];\n if (isPending(menuRequest)) {\n items.push(<MenuItem key=\"edit\" onClick={handleEdit}>Edit</MenuItem>);\n }\n items.push(<MenuItem key=\"delete\" onClick={handleDelete}>Delete</MenuItem>);\n return items;\n })()}\n </Menu>\n\n {editDialogState.request && (\n <EditAPIKeyRequestDialog\n open={editDialogState.open}\n request={editDialogState.request}\n availablePlans={editDialogState.plans}\n onClose={() => setEditDialogState({ open: false, request: null, plans: [] })}\n onSuccess={() => {\n setEditDialogState({ open: false, request: null, plans: [] });\n setRefresh(r => r + 1);\n }}\n />\n )}\n </>\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 from 'react';\nimport { Box, Typography, Chip } from '@material-ui/core';\nimport { Alert } from '@material-ui/lab';\n\ninterface PlanPolicyDetailsProps {\n selectedPolicy: {\n metadata: {\n name: string;\n };\n plans?: Array<{\n tier: string;\n description?: string;\n limits?: {\n daily?: number;\n monthly?: number;\n yearly?: number;\n };\n }>;\n } | null;\n alertSeverity?: 'warning' | 'info';\n alertMessage?: string;\n includeTopMargin?: boolean;\n}\n\nexport const PlanPolicyDetails: React.FC<PlanPolicyDetailsProps> = ({\n selectedPolicy,\n alertSeverity = 'warning',\n alertMessage = 'No PlanPolicy found for this HTTPRoute. API keys and rate limiting may not be available.',\n includeTopMargin = true,\n}) => {\n return (\n <Box\n mt={includeTopMargin ? 1 : 0}\n p={2}\n bgcolor=\"#f5f5f5\"\n borderRadius={1}\n border=\"1px solid #e0e0e0\"\n >\n {selectedPolicy ? (\n <>\n <Typography variant=\"subtitle2\" gutterBottom style={{ fontWeight: 600 }}>\n Associated PlanPolicy: <strong>{selectedPolicy.metadata.name}</strong>\n </Typography>\n\n {selectedPolicy.plans && selectedPolicy.plans.length > 0 ? (\n <>\n <Typography\n variant=\"caption\"\n display=\"block\"\n gutterBottom\n color=\"textSecondary\"\n style={{ marginTop: 8 }}\n >\n Available Plans:\n </Typography>\n <Box display=\"flex\" flexWrap=\"wrap\" mt={1} style={{ gap: 8 }}>\n {selectedPolicy.plans.map((plan: any, idx: number) => {\n const limitText = plan.limits?.daily\n ? `${plan.limits.daily}/day`\n : plan.limits?.monthly\n ? `${plan.limits.monthly}/month`\n : plan.limits?.yearly\n ? `${plan.limits.yearly}/year`\n : 'No limit';\n\n return (\n <Chip\n key={idx}\n label={`${plan.tier}: ${limitText}`}\n size=\"small\"\n variant=\"outlined\"\n color=\"primary\"\n />\n );\n })}\n </Box>\n {selectedPolicy.plans.some((p: any) => p.description) && (\n <Box mt={1}>\n {selectedPolicy.plans.filter((p: any) => p.description).map((plan: any, idx: number) => (\n <Typography key={idx} variant=\"caption\" display=\"block\" color=\"textSecondary\">\n • <strong>{plan.tier}:</strong> {plan.description}\n </Typography>\n ))}\n </Box>\n )}\n </>\n ) : (\n <Typography variant=\"caption\" color=\"textSecondary\">\n No plans defined in this PlanPolicy\n </Typography>\n )}\n </>\n ) : (\n <Alert severity={alertSeverity}>{alertMessage}</Alert>\n )}\n </Box>\n );\n};\n\n","import React, { 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 makeStyles,\n} from '@material-ui/core';\nimport { useApi, configApiRef, fetchApiRef } from '@backstage/core-plugin-api';\nimport { Alert } from '@material-ui/lab';\nimport useAsync from 'react-use/lib/useAsync';\nimport { PlanPolicyDetails } from '../PlanPolicyDetailsCard';\n\nconst useStyles = makeStyles({\n asterisk: {\n color: '#f44336',\n },\n});\n\ninterface CreateAPIProductDialogProps {\n open: boolean;\n onClose: () => void;\n onSuccess: () => void;\n}\n\nexport const CreateAPIProductDialog = ({ open, onClose, onSuccess }: CreateAPIProductDialogProps) => {\n const classes = useStyles();\n const config = useApi(configApiRef);\n const fetchApi = useApi(fetchApiRef);\n const backendUrl = config.getString('backend.baseUrl');\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 [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\n const { value: httpRoutes, loading: httpRoutesLoading } = useAsync(async () => {\n const response = await fetchApi.fetch(`${backendUrl}/api/kuadrant/httproutes`);\n const data = await response.json();\n // filter to only show httproutes annotated for backstage exposure\n return (data.items || []).filter((route: any) =>\n route.metadata.annotations?.['backstage.io/expose'] === 'true'\n );\n }, [backendUrl, fetchApi, open]);\n\n // load planpolicies with full details to show associated plans\n const { value: planPolicies } = useAsync(async () => {\n const response = await fetchApi.fetch(`${backendUrl}/api/kuadrant/planpolicies`);\n return await response.json();\n }, [backendUrl, fetchApi, open]);\n\n // find planpolicy associated with selected httproute\n const getPlanPolicyForRoute = (routeNamespace: string, routeName: string) => {\n if (!planPolicies?.items) return null;\n\n return planPolicies.items.find((pp: any) => {\n const ref = pp.targetRef;\n return (\n ref?.kind === 'HTTPRoute' &&\n ref?.name === routeName &&\n (!ref?.namespace || ref?.namespace === routeNamespace)\n );\n });\n };\n\n const selectedRouteInfo = selectedHTTPRoute ? selectedHTTPRoute.split('/') : null;\n const selectedPolicy = selectedRouteInfo\n ? getPlanPolicyForRoute(selectedRouteInfo[0], selectedRouteInfo[1])\n : null;\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 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 = {\n apiVersion: 'extensions.kuadrant.io/v1alpha1',\n kind: 'APIProduct',\n metadata: {\n name,\n namespace,\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 && { openAPISpec }),\n },\n } : {}),\n },\n };\n\n const response = await fetchApi.fetch(`${backendUrl}/api/kuadrant/apiproducts`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify(apiProduct),\n });\n\n if (!response.ok) {\n const errorData = await response.json();\n throw new Error(errorData.error || 'failed to create apiproduct');\n }\n\n onSuccess();\n handleClose();\n } catch (err) {\n setError(err instanceof Error ? err.message : String(err));\n } finally {\n setCreating(false);\n }\n };\n\n const handleClose = () => {\n setName('');\n setDisplayName('');\n setDescription('');\n setVersion('v1');\n setApprovalMode('manual');\n setPublishStatus('Published');\n setTags([]);\n setTagInput('');\n setSelectedHTTPRoute('');\n setContactEmail('');\n setContactTeam('');\n setDocsURL('');\n setOpenAPISpec('');\n setError('');\n onClose();\n };\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\n <Grid container spacing={2}>\n <Grid item xs={6}>\n <TextField\n fullWidth\n label=\"Name\"\n value={name}\n onChange={e => setName(e.target.value)}\n placeholder=\"my-api\"\n helperText=\"Kubernetes resource name (lowercase, hyphens)\"\n margin=\"normal\"\n required\n InputLabelProps={{\n classes: {\n asterisk: classes.asterisk,\n },\n }}\n />\n </Grid>\n <Grid item xs={6}>\n <TextField\n fullWidth\n label=\"Display Name\"\n value={displayName}\n onChange={e => setDisplayName(e.target.value)}\n placeholder=\"My API\"\n margin=\"normal\"\n required\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 margin=\"normal\"\n />\n </Grid>\n <Grid item xs={12}>\n <TextField\n fullWidth\n select\n label=\"Approval Mode\"\n value={approvalMode}\n onChange={e => setApprovalMode(e.target.value as 'automatic' | 'manual')}\n margin=\"normal\"\n helperText=\"Automatic: keys are created immediately. Manual: requires approval.\"\n >\n <MenuItem value=\"manual\">Manual</MenuItem>\n <MenuItem value=\"automatic\">Automatic</MenuItem>\n </TextField>\n </Grid>\n <Grid item xs={12}>\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=\"Draft: hidden from catalog. Published: visible to consumers.\"\n >\n <MenuItem value=\"Draft\">Draft</MenuItem>\n <MenuItem value=\"Published\">Published</MenuItem>\n </TextField>\n </Grid>\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 InputLabelProps={{\n classes: {\n asterisk: classes.asterisk,\n },\n }}\n />\n </Grid>\n\n <Grid item xs={12}>\n <Typography variant=\"subtitle2\" gutterBottom style={{ marginTop: 16 }}>\n Tags\n </Typography>\n <Box display=\"flex\" flexWrap=\"wrap\" marginBottom={1} style={{ gap: 8 }}>\n {tags.map(tag => (\n <Chip\n key={tag}\n label={tag}\n onDelete={() => handleDeleteTag(tag)}\n size=\"small\"\n />\n ))}\n </Box>\n <Box display=\"flex\" style={{ gap: 8 }}>\n <TextField\n fullWidth\n size=\"small\"\n value={tagInput}\n onChange={e => setTagInput(e.target.value)}\n onKeyPress={e => e.key === 'Enter' && handleAddTag()}\n placeholder=\"Add tag\"\n />\n <Button onClick={handleAddTag} variant=\"outlined\" size=\"small\">\n Add\n </Button>\n </Box>\n </Grid>\n\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=\"Select an HTTPRoute (backstage.io/expose: true). APIProduct will be created in the same namespace.\"\n disabled={httpRoutesLoading}\n InputLabelProps={{\n classes: {\n asterisk: classes.asterisk,\n },\n }}\n >\n {httpRoutesLoading && (\n <MenuItem value=\"\">Loading...</MenuItem>\n )}\n {!httpRoutesLoading && httpRoutes && httpRoutes.length === 0 && (\n <MenuItem value=\"\">No HTTPRoutes available</MenuItem>\n )}\n {!httpRoutesLoading && httpRoutes && httpRoutes.map((route: any) => (\n <MenuItem\n key={`${route.metadata.namespace}/${route.metadata.name}`}\n value={`${route.metadata.namespace}/${route.metadata.name}`}\n >\n {route.metadata.name} ({route.metadata.namespace})\n </MenuItem>\n ))}\n </TextField>\n </Grid>\n {selectedHTTPRoute && (\n <Grid item xs={12}>\n <PlanPolicyDetails\n selectedPolicy={selectedPolicy}\n alertSeverity=\"warning\"\n alertMessage=\"No PlanPolicy found for this HTTPRoute. API keys and rate limiting may not be available.\"\n includeTopMargin={true}\n />\n </Grid>\n )}\n\n <Grid item xs={6}>\n <TextField\n fullWidth\n label=\"Contact Email\"\n value={contactEmail}\n onChange={e => setContactEmail(e.target.value)}\n placeholder=\"api-team@example.com\"\n margin=\"normal\"\n />\n </Grid>\n <Grid item xs={6}>\n <TextField\n fullWidth\n label=\"Contact Team\"\n value={contactTeam}\n onChange={e => setContactTeam(e.target.value)}\n placeholder=\"platform-team\"\n margin=\"normal\"\n />\n </Grid>\n <Grid item xs={6}>\n <TextField\n fullWidth\n label=\"Docs URL\"\n value={docsURL}\n onChange={e => setDocsURL(e.target.value)}\n placeholder=\"https://api.example.com/docs\"\n margin=\"normal\"\n />\n </Grid>\n <Grid item xs={6}>\n <TextField\n fullWidth\n label=\"OpenAPI Spec URL\"\n value={openAPISpec}\n onChange={e => setOpenAPISpec(e.target.value)}\n placeholder=\"https://api.example.com/openapi.json\"\n margin=\"normal\"\n />\n </Grid>\n </Grid>\n </DialogContent>\n <DialogActions>\n <Button onClick={handleClose}>Cancel</Button>\n <Button\n onClick={handleCreate}\n color=\"primary\"\n variant=\"contained\"\n disabled={creating || !name || !displayName || !description || !selectedHTTPRoute}\n >\n {creating ? 'Creating...' : 'Create'}\n </Button>\n </DialogActions>\n </Dialog>\n );\n};\n","import React, { useState, useEffect } from 'react';\nimport {\n Dialog,\n DialogTitle,\n DialogContent,\n DialogActions,\n Button,\n TextField,\n Box,\n Typography,\n Chip,\n Grid,\n MenuItem,\n makeStyles,\n} from '@material-ui/core';\nimport { useApi, configApiRef, fetchApiRef } from '@backstage/core-plugin-api';\nimport { Alert } from '@material-ui/lab';\nimport { Progress } from '@backstage/core-components';\nimport useAsync from 'react-use/lib/useAsync';\nimport { PlanPolicyDetails } from '../PlanPolicyDetailsCard';\n\nconst useStyles = makeStyles({\n asterisk: {\n color: '#f44336',\n },\n});\n\ninterface EditAPIProductDialogProps {\n open: boolean;\n onClose: () => void;\n onSuccess: () => void;\n namespace: string;\n name: string;\n}\n\nexport const EditAPIProductDialog = ({open, onClose, onSuccess, namespace, name}: EditAPIProductDialogProps) => {\n const classes = useStyles();\n const config = useApi(configApiRef);\n const fetchApi = useApi(fetchApiRef);\n const backendUrl = config.getString('backend.baseUrl');\n const [loading, setLoading] = useState(false);\n const [displayName, setDisplayName] = useState('');\n const [description, setDescription] = useState('');\n const [version, setVersion] = useState('v1');\n const [publishStatus, setPublishStatus] = useState<'Draft' | 'Published'>('Draft');\n const [approvalMode, setApprovalMode] = useState<'automatic' | 'manual'>('manual');\n const [tags, setTags] = useState<string[]>([]);\n const [targetRef, setTargetRef] = useState<any>(null);\n const [tagInput, setTagInput] = useState('');\n const [contactEmail, setContactEmail] = useState('');\n const [contactTeam, setContactTeam] = useState('');\n const [docsURL, setDocsURL] = useState('');\n const [openAPISpec, setOpenAPISpec] = useState('');\n const [error, setError] = useState('');\n const [saving, setSaving] = useState(false);\n\n // Load APIProduct data when dialog opens\n useEffect(() => {\n if (open && namespace && name) {\n setLoading(true);\n setError('');\n\n fetchApi.fetch(`${backendUrl}/api/kuadrant/apiproducts/${namespace}/${name}`)\n .then(async res => {\n if (!res.ok) {\n const errorData = await res.json();\n throw new Error(errorData.error || `Failed to fetch API product: ${res.status}`);\n }\n return res.json();\n })\n .then(data => {\n setDisplayName(data.spec.displayName || '');\n setDescription(data.spec.description || '');\n setVersion(data.spec.version || 'v1');\n setPublishStatus(data.spec.publishStatus || 'Draft');\n setApprovalMode(data.spec.approvalMode || 'manual');\n setTags(data.spec.tags || []);\n setTargetRef(data.spec.targetRef || null);\n setContactEmail(data.spec.contact?.email || '');\n setContactTeam(data.spec.contact?.team || '');\n setDocsURL(data.spec.documentation?.docsURL || '');\n setOpenAPISpec(data.spec.documentation?.openAPISpec || '');\n setLoading(false);\n })\n .catch(err => {\n setError(err.message || 'Failed to load API product');\n setLoading(false);\n });\n }\n }, [open, namespace, name, backendUrl, fetchApi]);\n\n // load planpolicies with full details to show associated plans\n const { value: planPolicies } = useAsync(async () => {\n if (!open) return null;\n const response = await fetchApi.fetch(`${backendUrl}/api/kuadrant/planpolicies`);\n return await response.json();\n }, [backendUrl, fetchApi, open]);\n\n // find planpolicy associated with targetRef\n const selectedPolicy = React.useMemo(() => {\n if (!planPolicies?.items || !targetRef) return null;\n\n return planPolicies.items.find((pp: any) => {\n const ref = pp.targetRef;\n return (\n ref?.kind === 'HTTPRoute' &&\n ref?.name === targetRef.name &&\n (!ref?.namespace || ref?.namespace === (targetRef.namespace || namespace))\n );\n });\n }, [planPolicies, targetRef, namespace]);\n\n const handleAddTag = () => {\n if (tagInput.trim() && !tags.includes(tagInput.trim())) {\n setTags([...tags, tagInput.trim()]);\n setTagInput('');\n }\n };\n\n const handleDeleteTag = (tagToDelete: string) => {\n setTags(tags.filter(tag => tag !== tagToDelete));\n };\n\n const handleSave = async () => {\n setError('');\n setSaving(true);\n\n try {\n const patch = {\n spec: {\n displayName,\n description,\n version,\n publishStatus,\n approvalMode,\n tags,\n targetRef,\n ...(contactEmail || contactTeam ? {\n contact: {\n ...(contactEmail && { email: contactEmail }),\n ...(contactTeam && { team: contactTeam }),\n },\n } : {}),\n ...(docsURL || openAPISpec ? {\n documentation: {\n ...(docsURL && { docsURL }),\n ...(openAPISpec && { openAPISpec }),\n },\n } : {}),\n },\n };\n\n const response = await fetchApi.fetch(\n `${backendUrl}/api/kuadrant/apiproducts/${namespace}/${name}`,\n {\n method: 'PATCH',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify(patch),\n }\n );\n\n if (!response.ok) {\n const errorData = await response.json();\n throw new Error(errorData.error || 'failed to update apiproduct');\n }\n\n onSuccess();\n onClose();\n } catch (err) {\n setError(err instanceof Error ? err.message : String(err));\n } finally {\n setSaving(false);\n }\n };\n\n return (\n <Dialog open={open} onClose={onClose} maxWidth=\"md\" fullWidth>\n <DialogTitle>Edit API Product</DialogTitle>\n <DialogContent>\n {error && (\n <Alert severity=\"error\" style={{ marginBottom: 16 }}>\n {error}\n </Alert>\n )}\n\n {loading ? (\n <Progress />\n ) : (\n <Grid container spacing={2}>\n <Grid item xs={6}>\n <TextField\n fullWidth\n label=\"Name\"\n value={name}\n disabled\n helperText=\"Kubernetes resource name (immutable)\"\n margin=\"normal\"\n />\n </Grid>\n <Grid item xs={6}>\n <TextField\n fullWidth\n label=\"Namespace\"\n value={namespace}\n disabled\n helperText=\"Derived from HTTPRoute (immutable)\"\n margin=\"normal\"\n />\n </Grid>\n <Grid item xs={6}>\n <TextField\n fullWidth\n label=\"Display Name\"\n value={displayName}\n onChange={e => setDisplayName(e.target.value)}\n placeholder=\"My API\"\n margin=\"normal\"\n required\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 margin=\"normal\"\n />\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=\"Draft: Hidden from catalog. Published: Visible in catalog.\"\n >\n <MenuItem value=\"Draft\">Draft (Hidden)</MenuItem>\n <MenuItem value=\"Published\">Published (Visible)</MenuItem>\n </TextField>\n </Grid>\n <Grid item xs={6}>\n <TextField\n fullWidth\n select\n label=\"Approval Mode\"\n value={approvalMode}\n onChange={e => setApprovalMode(e.target.value as 'automatic' | 'manual')}\n margin=\"normal\"\n helperText=\"Automatic: keys created immediately. Manual: requires approval.\"\n >\n <MenuItem value=\"manual\">Manual</MenuItem>\n <MenuItem value=\"automatic\">Automatic</MenuItem>\n </TextField>\n </Grid>\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 InputLabelProps={{\n classes: {\n asterisk: classes.asterisk,\n },\n }}\n />\n </Grid>\n\n <Grid item xs={12}>\n <Typography variant=\"subtitle2\" gutterBottom style={{ marginTop: 16 }}>\n Tags\n </Typography>\n <Box display=\"flex\" flexWrap=\"wrap\" marginBottom={1} style={{ gap: 8 }}>\n {tags.map(tag => (\n <Chip\n key={tag}\n label={tag}\n onDelete={() => handleDeleteTag(tag)}\n size=\"small\"\n />\n ))}\n </Box>\n <Box display=\"flex\" style={{ gap: 8 }}>\n <TextField\n fullWidth\n size=\"small\"\n value={tagInput}\n onChange={e => setTagInput(e.target.value)}\n onKeyPress={e => e.key === 'Enter' && handleAddTag()}\n placeholder=\"Add tag\"\n />\n <Button onClick={handleAddTag} variant=\"outlined\" size=\"small\">\n Add\n </Button>\n </Box>\n </Grid>\n {targetRef && (\n <>\n <Grid item xs={12}>\n <TextField\n fullWidth\n label=\"HTTPRoute\"\n value={`${targetRef.namespace || namespace}/${targetRef.name}`}\n disabled\n helperText=\"Target HTTPRoute (immutable)\"\n margin=\"normal\"\n />\n </Grid>\n\n <Grid item xs={12}>\n <PlanPolicyDetails\n selectedPolicy={selectedPolicy}\n alertSeverity=\"info\"\n alertMessage=\"No PlanPolicy found for this HTTPRoute.\"\n includeTopMargin={false}\n />\n </Grid>\n </>\n )}\n\n <Grid item xs={6}>\n <TextField\n fullWidth\n label=\"Contact Email\"\n value={contactEmail}\n onChange={e => setContactEmail(e.target.value)}\n placeholder=\"api-team@example.com\"\n margin=\"normal\"\n />\n </Grid>\n <Grid item xs={6}>\n <TextField\n fullWidth\n label=\"Contact Team\"\n value={contactTeam}\n onChange={e => setContactTeam(e.target.value)}\n placeholder=\"platform-team\"\n margin=\"normal\"\n />\n </Grid>\n <Grid item xs={6}>\n <TextField\n fullWidth\n label=\"Docs URL\"\n value={docsURL}\n onChange={e => setDocsURL(e.target.value)}\n placeholder=\"https://api.example.com/docs\"\n margin=\"normal\"\n />\n </Grid>\n <Grid item xs={6}>\n <TextField\n fullWidth\n label=\"OpenAPI Spec URL\"\n value={openAPISpec}\n onChange={e => setOpenAPISpec(e.target.value)}\n placeholder=\"https://api.example.com/openapi.json\"\n margin=\"normal\"\n />\n </Grid>\n </Grid>\n )}\n </DialogContent>\n <DialogActions>\n <Button onClick={onClose}>Cancel</Button>\n <Button\n onClick={handleSave}\n color=\"primary\"\n variant=\"contained\"\n disabled={saving || loading || !displayName || !description}\n >\n {saving ? 'Saving...' : 'Save'}\n </Button>\n </DialogActions>\n </Dialog>\n );\n};\n","import React, { useState } from 'react';\nimport { Typography, Grid, Box, Chip, Button, IconButton, Dialog, DialogTitle, DialogContent, DialogContentText, DialogActions } 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 {\n InfoCard,\n Header,\n Page,\n Content,\n SupportButton,\n Progress,\n ResponseErrorPanel,\n Link,\n Table,\n TableColumn,\n} from '@backstage/core-components';\nimport useAsync from 'react-use/lib/useAsync';\nimport { useApi, configApiRef, fetchApiRef } from '@backstage/core-plugin-api';\nimport { ApprovalQueueCard } from '../ApprovalQueueCard';\nimport { MyApiKeysCard } from '../MyApiKeysCard';\nimport { PermissionGate } from '../PermissionGate';\nimport { CreateAPIProductDialog } from '../CreateAPIProductDialog';\nimport {\n kuadrantApiProductCreatePermission,\n kuadrantApiProductDeleteOwnPermission,\n kuadrantApiProductDeleteAllPermission,\n kuadrantApiProductUpdateOwnPermission,\n kuadrantApiProductUpdateAllPermission,\n kuadrantApiProductListPermission,\n kuadrantApiKeyRequestReadAllPermission,\n kuadrantApiKeyRequestReadOwnPermission,\n kuadrantPlanPolicyListPermission,\n} from '../../permissions';\nimport { useKuadrantPermission } from '../../utils/permissions';\nimport { EditAPIProductDialog } from '../EditAPIProductDialog';\n\ntype KuadrantResource = {\n metadata: {\n name: string;\n namespace: string;\n creationTimestamp: string;\n };\n spec?: any;\n};\n\ntype KuadrantList = {\n items: KuadrantResource[];\n};\n\nexport const ResourceList = () => {\n const config = useApi(configApiRef);\n const fetchApi = useApi(fetchApiRef);\n const backendUrl = config.getString('backend.baseUrl');\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<{ namespace: string; name: string } | null>(null);\n const [apiProductToEdit, setApiProductToEdit] = useState<{ namespace: string; name: string } | null>(null);\n const [deleting, setDeleting] = useState(false);\n\n const {\n allowed: canCreateApiProduct,\n loading: createPermissionLoading,\n error: createPermissionError,\n } = useKuadrantPermission(kuadrantApiProductCreatePermission);\n\n const {\n allowed: canViewAllRequests,\n loading: approvalQueueAllPermissionLoading,\n } = useKuadrantPermission(kuadrantApiKeyRequestReadAllPermission);\n\n const {\n allowed: canViewOwnRequests,\n loading: approvalQueueOwnPermissionLoading,\n error: approvalQueuePermissionError,\n } = useKuadrantPermission(kuadrantApiKeyRequestReadOwnPermission);\n\n const canViewApprovalQueue = canViewAllRequests || canViewOwnRequests;\n const approvalQueuePermissionLoading = approvalQueueAllPermissionLoading || approvalQueueOwnPermissionLoading;\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 {\n allowed: canUpdateOwnApiProduct,\n } = useKuadrantPermission(kuadrantApiProductUpdateOwnPermission);\n\n const {\n allowed: canUpdateAllApiProducts,\n } = useKuadrantPermission(kuadrantApiProductUpdateAllPermission);\n\n const canDeleteApiProduct = canDeleteOwnApiProduct || canDeleteAllApiProducts;\n const canUpdateApiProduct = canUpdateOwnApiProduct || canUpdateAllApiProducts;\n const deletePermissionLoading = deleteOwnPermissionLoading || deleteAllPermissionLoading;\n\n const {\n allowed: canListPlanPolicies,\n loading: planPolicyPermissionLoading,\n error: planPolicyPermissionError,\n } = useKuadrantPermission(kuadrantPlanPolicyListPermission);\n\n const { value: apiProducts, loading: apiProductsLoading, error: apiProductsError } = useAsync(async (): Promise<KuadrantList> => {\n const response = await fetchApi.fetch(`${backendUrl}/api/kuadrant/apiproducts`);\n return await response.json();\n }, [backendUrl, fetchApi, refreshTrigger]);\n\n const { value: planPolicies, loading: planPoliciesLoading, error: planPoliciesError } = useAsync(async (): Promise<KuadrantList> => {\n const response = await fetchApi.fetch(`${backendUrl}/api/kuadrant/planpolicies`);\n return await response.json();\n }, [backendUrl, fetchApi, refreshTrigger]);\n\n const loading = apiProductsLoading || planPoliciesLoading || createPermissionLoading || approvalQueuePermissionLoading || deletePermissionLoading || planPolicyPermissionLoading;\n const error = apiProductsError || planPoliciesError;\n const permissionError = createPermissionError || approvalQueuePermissionError || deletePermissionError || planPolicyPermissionError;\n\n const handleCreateSuccess = () => {\n setRefreshTrigger(prev => prev + 1);\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 };\n\n const handleDeleteClick = (namespace: string, name: string) => {\n setApiProductToDelete({ namespace, name });\n setDeleteDialogOpen(true);\n };\n\n const handleDeleteConfirm = async () => {\n if (!apiProductToDelete) return;\n\n setDeleting(true);\n try {\n const response = await fetchApi.fetch(\n `${backendUrl}/api/kuadrant/apiproducts/${apiProductToDelete.namespace}/${apiProductToDelete.name}`,\n { method: 'DELETE' }\n );\n\n if (!response.ok) {\n throw new Error('failed to delete apiproduct');\n }\n\n setRefreshTrigger(prev => prev + 1);\n } catch (err) {\n console.error('error deleting apiproduct:', err);\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 formatDate = (dateString: string) => {\n const date = new Date(dateString);\n return date.toLocaleDateString('en-GB', {\n year: 'numeric',\n month: 'short',\n day: 'numeric',\n });\n };\n\n const columns: TableColumn[] = [\n {\n title: 'Name',\n field: 'name',\n render: (row: any) => (\n <Link to={`/catalog/default/api/${row.metadata.name}/api-product`}>\n <strong>{row.spec?.displayName || row.metadata.name}</strong>\n </Link>\n ),\n },\n {\n title: 'Resource Name',\n field: 'metadata.name',\n },\n {\n title: 'Version',\n field: 'spec.version',\n render: (row: any) => row.spec?.version || '-',\n },\n {\n title: 'HTTPRoute',\n field: 'spec.targetRef.name',\n render: (row: any) => row.spec?.targetRef?.name || '-',\n },\n {\n title: 'Publish 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: 'Approval Mode',\n field: 'spec.approvalMode',\n render: (row: any) => {\n const mode = row.spec?.approvalMode || 'manual';\n return (\n <Chip\n label={mode}\n size=\"small\"\n color={mode === 'automatic' ? 'secondary' : 'default'}\n />\n );\n },\n },\n {\n title: 'Namespace',\n field: 'metadata.namespace',\n },\n {\n title: 'Created',\n field: 'metadata.creationTimestamp',\n render: (row: any) => formatDate(row.metadata.creationTimestamp),\n },\n {\n title: 'Actions',\n field: 'actions',\n render: (row: any) => (\n <Box display=\"flex\" style={{ gap: 4 }}>\n {canUpdateApiProduct && (\n <IconButton\n size=\"small\"\n onClick={() => handleEditClick(row.metadata.namespace, row.metadata.name)}\n title=\"Edit API Product\"\n >\n <EditIcon fontSize=\"small\" />\n </IconButton>\n )}\n \n {canDeleteApiProduct && (\n <IconButton\n size=\"small\"\n onClick={() => handleDeleteClick(row.metadata.namespace, row.metadata.name)}\n title=\"Delete API Product\"\n >\n <DeleteIcon fontSize=\"small\" />\n </IconButton>\n )}\n </Box>\n ),\n },\n ];\n\n const planPolicyColumns: TableColumn[] = [\n {\n title: 'Name',\n field: 'metadata.name',\n render: (row: any) => (\n <Link to={`/kuadrant/planpolicy/${row.metadata.namespace}/${row.metadata.name}`}>\n <strong>{row.metadata.name}</strong>\n </Link>\n ),\n },\n {\n title: 'Namespace',\n field: 'metadata.namespace',\n },\n ];\n\n const renderResources = (resources: KuadrantResource[] | undefined) => {\n if (!resources || resources.length === 0) {\n return <Typography variant=\"body2\" color=\"textSecondary\">No API products found</Typography>;\n }\n return (\n <Table\n options={{ paging: false, search: false, toolbar: false }}\n columns={columns}\n data={resources}\n />\n );\n };\n\n const renderPlanPolicies = (resources: KuadrantResource[] | undefined) => {\n if (!resources || resources.length === 0) {\n return <Typography variant=\"body2\" color=\"textSecondary\">No plan policies found</Typography>;\n }\n return (\n <Table\n options={{ paging: false, search: false, toolbar: false }}\n columns={planPolicyColumns}\n data={resources}\n />\n );\n };\n\n return (\n <Page themeId=\"tool\">\n <Header title=\"Kuadrant\" subtitle=\"API management for Kubernetes\">\n <SupportButton>Manage API products and access requests</SupportButton>\n </Header>\n <Content>\n {loading && <Progress />}\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: {createPermissionError ? 'kuadrant.apiproduct.create' :\n deletePermissionError ? 'kuadrant.apiproduct.delete' :\n approvalQueuePermissionError ? 'kuadrant.apikeyrequest.read.all' :\n planPolicyPermissionError ? 'kuadrant.planpolicy.list' : '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 && (\n <Grid container spacing={3} direction=\"column\">\n <Grid item>\n <MyApiKeysCard />\n </Grid>\n\n <Grid item>\n <InfoCard\n title=\"API Products\"\n action={\n canCreateApiProduct ? (\n <Box display=\"flex\" alignItems=\"center\" height=\"100%\" mt={1}>\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 </Box>\n ) : undefined\n }\n >\n {renderResources(apiProducts?.items)}\n </InfoCard>\n </Grid>\n\n {canListPlanPolicies && (\n <Grid item>\n <InfoCard title=\"Plan Policies\">\n {renderPlanPolicies(planPolicies?.items)}\n </InfoCard>\n </Grid>\n )}\n\n {canViewApprovalQueue && (\n <Grid item>\n <ApprovalQueueCard />\n </Grid>\n )}\n </Grid>\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 <Dialog open={deleteDialogOpen} onClose={handleDeleteCancel}>\n <DialogTitle>Delete API Product</DialogTitle>\n <DialogContent>\n <DialogContentText>\n Are you sure you want to delete {apiProductToDelete?.name} from namespace {apiProductToDelete?.namespace}?\n This will permanently remove the API Product from Kubernetes.\n </DialogContentText>\n </DialogContent>\n <DialogActions>\n <Button onClick={handleDeleteCancel} color=\"primary\">\n Cancel\n </Button>\n <Button onClick={handleDeleteConfirm} color=\"secondary\" disabled={deleting}>\n {deleting ? 'Deleting...' : 'Delete'}\n </Button>\n </DialogActions>\n </Dialog>\n </Content>\n </Page>\n );\n};\n\nexport const KuadrantPage = () => {\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":["EditAPIKeyRequestDialog","open","onClose","onSuccess","request","availablePlans","config","useApi","configApiRef","fetchApi","fetchApiRef","backendUrl","getString","planTier","setPlanTier","useState","useCase","setUseCase","saving","setSaving","error","setError","useEffect","spec","handleClose","Dialog","maxWidth","fullWidth","DialogTitle","DialogContent","Box","mb","p","bgcolor","color","borderRadius","Typography","variant","FormControl","margin","InputLabel","Select","value","onChange","e","target","disabled","map","plan","limitDesc","Object","entries","limits","key","val","join","MenuItem","tier","TextField","label","placeholder","multiline","rows","helperText","DialogActions","Button","onClick","async","patch","trim","response","fetch","metadata","namespace","name","method","headers","body","JSON","stringify","ok","errorData","json","catch","Error","status","err","console","message","MyApiKeysCard","identityApi","identityApiRef","selectedTab","setSelectedTab","setUserId","visibleKeys","setVisibleKeys","Set","menuAnchor","setMenuAnchor","menuRequest","setMenuRequest","editDialogState","setEditDialogState","plans","refresh","setRefresh","useAsync","identity","getBackstageIdentity","extractedUserId","userEntityRef","split","log","requests","loading","items","InfoCard","title","allRequests","approvedRequests","filter","r","phase","pendingRequests","rejectedRequests","handleMenuClose","handleEdit","apiProductResponse","apiNamespace","apiName","apiProduct","handleDelete","window","confirm","alert","columns","field","render","row","Link","to","strong","Chip","size","Tooltip","placement","style","overflow","textOverflow","whiteSpace","reason","reviewedBy","reviewedDate","reviewedAt","Date","toLocaleDateString","apiKey","isVisible","has","display","alignItems","gap","fontFamily","fontSize","repeat","IconButton","toggleKeyVisibility","keyName","prev","newSet","delete","add","VisibilityOffIcon","VisibilityIcon","creationTimestamp","date","stopPropagation","rect","currentTarget","getBoundingClientRect","top","bottom","left","aria-controls","undefined","aria-haspopup","MoreVertIcon","tabData","getTabData","tabColumns","col","getTabColumns","subheader","length","Tabs","_","newValue","indicatorColor","textColor","Tab","textAlign","Table","options","paging","pageSize","search","toolbar","data","item","id","Menu","Boolean","anchorReference","anchorPosition","push","PermissionGate","children","permission","fallback","errorMessage","allowed","useKuadrantPermission","Progress","mt","PlanPolicyDetails","selectedPolicy","alertSeverity","alertMessage","includeTopMargin","border","gutterBottom","fontWeight","marginTop","flexWrap","idx","limitText","daily","monthly","yearly","some","description","Alert","severity","useStyles","makeStyles","asterisk","CreateAPIProductDialog","classes","setName","displayName","setDisplayName","setDescription","version","setVersion","approvalMode","setApprovalMode","publishStatus","setPublishStatus","tags","setTags","tagInput","setTagInput","selectedHTTPRoute","setSelectedHTTPRoute","contactEmail","setContactEmail","contactTeam","setContactTeam","docsURL","setDocsURL","openAPISpec","setOpenAPISpec","creating","setCreating","httpRoutes","httpRoutesLoading","route","annotations","planPolicies","selectedRouteInfo","routeNamespace","routeName","find","pp","ref","targetRef","kind","handleAddTag","includes","marginBottom","Grid","container","spacing","xs","required","InputLabelProps","select","tag","onDelete","handleDeleteTag","tagToDelete","onKeyPress","selectedRouteNamespace","selectedRouteName","apiVersion","group","contact","email","team","documentation","String","EditAPIProductDialog","setLoading","setTargetRef","then","res","React","ResourceList","createDialogOpen","setCreateDialogOpen","editDialogOpen","setEditDialogOpen","refreshTrigger","setRefreshTrigger","deleteDialogOpen","setDeleteDialogOpen","apiProductToDelete","setApiProductToDelete","apiProductToEdit","setApiProductToEdit","deleting","setDeleting","canCreateApiProduct","createPermissionLoading","createPermissionError","kuadrantApiProductCreatePermission","canViewAllRequests","approvalQueueAllPermissionLoading","kuadrantApiKeyRequestReadAllPermission","canViewOwnRequests","approvalQueueOwnPermissionLoading","approvalQueuePermissionError","kuadrantApiKeyRequestReadOwnPermission","canViewApprovalQueue","approvalQueuePermissionLoading","canDeleteOwnApiProduct","deleteOwnPermissionLoading","kuadrantApiProductDeleteOwnPermission","canDeleteAllApiProducts","deleteAllPermissionLoading","deletePermissionError","kuadrantApiProductDeleteAllPermission","canUpdateOwnApiProduct","kuadrantApiProductUpdateOwnPermission","canUpdateAllApiProducts","kuadrantApiProductUpdateAllPermission","canDeleteApiProduct","canUpdateApiProduct","deletePermissionLoading","canListPlanPolicies","planPolicyPermissionLoading","planPolicyPermissionError","kuadrantPlanPolicyListPermission","apiProducts","apiProductsLoading","apiProductsError","planPoliciesLoading","planPoliciesError","permissionError","handleDeleteCancel","mode","formatDate","dateString","year","month","day","handleEditClick","EditIcon","handleDeleteClick","DeleteIcon","planPolicyColumns","Page","themeId","Header","subtitle","SupportButton","Content","ResponseErrorPanel","direction","action","height","startIcon","AddIcon","resources","renderPlanPolicies","ApprovalQueueCard","DialogContentText","KuadrantPage","kuadrantApiProductListPermission"],"sourceRoot":""}
|