@kuadrant/kuadrant-backstage-plugin-frontend 0.0.2-dev-d2ba42b → 0.0.2-dev-8189c1c
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/api.esm.js +236 -0
- package/dist/api.esm.js.map +1 -0
- package/dist/apis.esm.js +15 -0
- package/dist/apis.esm.js.map +1 -0
- package/dist/components/ApiAccessCard/ApiAccessCard.esm.js +25 -36
- package/dist/components/ApiAccessCard/ApiAccessCard.esm.js.map +1 -1
- package/dist/components/ApiKeyDetailPage/ApiKeyDetailPage.esm.js +24 -36
- package/dist/components/ApiKeyDetailPage/ApiKeyDetailPage.esm.js.map +1 -1
- package/dist/components/ApiKeyManagementTab/ApiKeyManagementTab.esm.js +20 -46
- package/dist/components/ApiKeyManagementTab/ApiKeyManagementTab.esm.js.map +1 -1
- package/dist/components/ApiProductDetailPage/ApiProductDetailPage.esm.js +9 -43
- package/dist/components/ApiProductDetailPage/ApiProductDetailPage.esm.js.map +1 -1
- package/dist/components/ApiProductDetails/ApiProductDetails.esm.js.map +1 -1
- package/dist/components/ApiProductInfoCard/ApiProductInfoCard.esm.js +5 -13
- package/dist/components/ApiProductInfoCard/ApiProductInfoCard.esm.js.map +1 -1
- package/dist/components/ApiProductOpenApiAlert/ApiProductOpenApiAlert.esm.js +7 -10
- package/dist/components/ApiProductOpenApiAlert/ApiProductOpenApiAlert.esm.js.map +1 -1
- package/dist/components/ApiProductPolicies/ApiProductPolicies.esm.js +113 -0
- package/dist/components/ApiProductPolicies/ApiProductPolicies.esm.js.map +1 -0
- package/dist/components/ApprovalQueueTable/ApprovalQueueTable.esm.js +32 -64
- package/dist/components/ApprovalQueueTable/ApprovalQueueTable.esm.js.map +1 -1
- package/dist/components/CreateAPIProductDialog/CreateAPIProductDialog.esm.js +85 -63
- package/dist/components/CreateAPIProductDialog/CreateAPIProductDialog.esm.js.map +1 -1
- package/dist/components/EditAPIKeyDialog/EditAPIKeyDialog.esm.js +8 -18
- package/dist/components/EditAPIKeyDialog/EditAPIKeyDialog.esm.js.map +1 -1
- package/dist/components/EditAPIProductDialog/EditAPIProductDialog.esm.js +56 -35
- package/dist/components/EditAPIProductDialog/EditAPIProductDialog.esm.js.map +1 -1
- package/dist/components/EntityApiApprovalTab/EntityApiApprovalTab.esm.js +9 -25
- package/dist/components/EntityApiApprovalTab/EntityApiApprovalTab.esm.js.map +1 -1
- package/dist/components/KuadrantPage/ApiProductsPage.esm.js +20 -54
- package/dist/components/KuadrantPage/ApiProductsPage.esm.js.map +1 -1
- package/dist/components/MyApiKeysTable/MyApiKeysTable.esm.js +25 -52
- package/dist/components/MyApiKeysTable/MyApiKeysTable.esm.js.map +1 -1
- package/dist/components/RequestAccessDialog/RequestAccessDialog.esm.js +10 -25
- package/dist/components/RequestAccessDialog/RequestAccessDialog.esm.js.map +1 -1
- package/dist/index.d.ts +510 -1
- package/dist/index.esm.js +3 -1
- package/dist/index.esm.js.map +1 -1
- package/dist/permissions.esm.js +12 -2
- package/dist/permissions.esm.js.map +1 -1
- package/dist/utils/policies.esm.js +11 -0
- package/dist/utils/policies.esm.js.map +1 -0
- package/dist-scalprum/internal.plugin-kuadrant.1ed3b3b414caa08ac5be.js +2 -0
- package/dist-scalprum/internal.plugin-kuadrant.1ed3b3b414caa08ac5be.js.map +1 -0
- package/dist-scalprum/plugin-manifest.json +3 -3
- package/dist-scalprum/static/2967.17aec2fb.chunk.js +2 -0
- package/dist-scalprum/static/2967.17aec2fb.chunk.js.map +1 -0
- package/dist-scalprum/static/{3947.ff1c25cf.chunk.js → 3947.ad129ba4.chunk.js} +1 -1
- package/dist-scalprum/static/{3947.ff1c25cf.chunk.js.map → 3947.ad129ba4.chunk.js.map} +1 -1
- package/dist-scalprum/static/3976.c8138b52.chunk.js +2 -0
- package/dist-scalprum/static/3976.c8138b52.chunk.js.map +1 -0
- package/dist-scalprum/static/4447.d924bc59.chunk.js +2 -0
- package/dist-scalprum/static/4447.d924bc59.chunk.js.map +1 -0
- package/dist-scalprum/static/5203.11ef2211.chunk.js +2 -0
- package/dist-scalprum/static/5203.11ef2211.chunk.js.map +1 -0
- package/dist-scalprum/static/6371.d849c508.chunk.js +2 -0
- package/dist-scalprum/static/6371.d849c508.chunk.js.map +1 -0
- package/dist-scalprum/static/6387.79be6155.chunk.js +2 -0
- package/dist-scalprum/static/6387.79be6155.chunk.js.map +1 -0
- package/dist-scalprum/static/6800.6faeb7c6.chunk.js +2 -0
- package/dist-scalprum/static/6800.6faeb7c6.chunk.js.map +1 -0
- package/dist-scalprum/static/69.b6afd1fe.chunk.js +2 -0
- package/dist-scalprum/static/69.b6afd1fe.chunk.js.map +1 -0
- package/dist-scalprum/static/7005.98c5e400.chunk.js +2 -0
- package/dist-scalprum/static/7005.98c5e400.chunk.js.map +1 -0
- package/dist-scalprum/static/7270.4a71807b.chunk.js +2 -0
- package/dist-scalprum/static/7270.4a71807b.chunk.js.map +1 -0
- package/dist-scalprum/static/7791.0a1d55bc.chunk.js +2 -0
- package/dist-scalprum/static/7791.0a1d55bc.chunk.js.map +1 -0
- package/dist-scalprum/static/8789.2f437443.chunk.js +2 -0
- package/dist-scalprum/static/8789.2f437443.chunk.js.map +1 -0
- package/dist-scalprum/static/9051.d45ac154.chunk.js +2 -0
- package/dist-scalprum/static/9051.d45ac154.chunk.js.map +1 -0
- package/dist-scalprum/static/{2946.a35243f1.chunk.js → 9370.2e9fe34b.chunk.js} +3 -3
- package/dist-scalprum/static/9370.2e9fe34b.chunk.js.map +1 -0
- package/dist-scalprum/static/9838.966ce0a0.chunk.js +2 -0
- package/dist-scalprum/static/9838.966ce0a0.chunk.js.map +1 -0
- package/dist-scalprum/static/exposed-PluginRoot.3b24e5af.chunk.js +2 -0
- package/dist-scalprum/static/{exposed-PluginRoot.8d8f0b09.chunk.js.map → exposed-PluginRoot.3b24e5af.chunk.js.map} +1 -1
- package/package.json +3 -1
- package/dist/components/PlanPolicyDetailsCard/PlanPolicyDetails.esm.js +0 -48
- package/dist/components/PlanPolicyDetailsCard/PlanPolicyDetails.esm.js.map +0 -1
- package/dist-scalprum/internal.plugin-kuadrant.eacc31ca4d6c1340f8a8.js +0 -2
- package/dist-scalprum/internal.plugin-kuadrant.eacc31ca4d6c1340f8a8.js.map +0 -1
- package/dist-scalprum/static/2946.a35243f1.chunk.js.map +0 -1
- package/dist-scalprum/static/2967.5bade048.chunk.js +0 -2
- package/dist-scalprum/static/2967.5bade048.chunk.js.map +0 -1
- package/dist-scalprum/static/3650.89dfc64c.chunk.js +0 -2
- package/dist-scalprum/static/3650.89dfc64c.chunk.js.map +0 -1
- package/dist-scalprum/static/3976.4cf18515.chunk.js +0 -2
- package/dist-scalprum/static/3976.4cf18515.chunk.js.map +0 -1
- package/dist-scalprum/static/4447.adbf663f.chunk.js +0 -2
- package/dist-scalprum/static/4447.adbf663f.chunk.js.map +0 -1
- package/dist-scalprum/static/5203.fce2a28f.chunk.js +0 -2
- package/dist-scalprum/static/5203.fce2a28f.chunk.js.map +0 -1
- package/dist-scalprum/static/6371.d45f37cc.chunk.js +0 -2
- package/dist-scalprum/static/6371.d45f37cc.chunk.js.map +0 -1
- package/dist-scalprum/static/6800.cd5c7bcb.chunk.js +0 -2
- package/dist-scalprum/static/6800.cd5c7bcb.chunk.js.map +0 -1
- package/dist-scalprum/static/7005.72759857.chunk.js +0 -2
- package/dist-scalprum/static/7005.72759857.chunk.js.map +0 -1
- package/dist-scalprum/static/7270.9473c969.chunk.js +0 -2
- package/dist-scalprum/static/7270.9473c969.chunk.js.map +0 -1
- package/dist-scalprum/static/7791.01371352.chunk.js +0 -2
- package/dist-scalprum/static/7791.01371352.chunk.js.map +0 -1
- package/dist-scalprum/static/8789.30227526.chunk.js +0 -2
- package/dist-scalprum/static/8789.30227526.chunk.js.map +0 -1
- package/dist-scalprum/static/8804.63919453.chunk.js +0 -2
- package/dist-scalprum/static/8804.63919453.chunk.js.map +0 -1
- package/dist-scalprum/static/exposed-PluginRoot.8d8f0b09.chunk.js +0 -2
- /package/dist-scalprum/static/{2946.a35243f1.chunk.js.LICENSE.txt → 9370.2e9fe34b.chunk.js.LICENSE.txt} +0 -0
|
@@ -2,12 +2,14 @@ import React, { useState, useEffect } from 'react';
|
|
|
2
2
|
import { makeStyles, Dialog, DialogTitle, DialogContent, Box, Typography, Grid, TextField, InputAdornment, IconButton, Chip, Tooltip, MenuItem, FormControl, RadioGroup, FormControlLabel, Radio, DialogActions, Button, CircularProgress } from '@material-ui/core';
|
|
3
3
|
import InfoOutlinedIcon from '@material-ui/icons/InfoOutlined';
|
|
4
4
|
import AddIcon from '@material-ui/icons/Add';
|
|
5
|
-
import { useApi
|
|
5
|
+
import { useApi } from '@backstage/core-plugin-api';
|
|
6
|
+
import { kuadrantApiRef } from '../../api.esm.js';
|
|
6
7
|
import { Alert } from '@material-ui/lab';
|
|
8
|
+
import useAsync from 'react-use/lib/useAsync';
|
|
7
9
|
import { Progress } from '@backstage/core-components';
|
|
8
|
-
import {
|
|
10
|
+
import { ApiProductPolicies } from '../ApiProductPolicies/ApiProductPolicies.esm.js';
|
|
9
11
|
import { validateURL } from '../../utils/validation.esm.js';
|
|
10
|
-
import {
|
|
12
|
+
import { getPolicyForRoute } from '../../utils/policies.esm.js';
|
|
11
13
|
|
|
12
14
|
const useStyles = makeStyles((theme) => ({
|
|
13
15
|
asterisk: {
|
|
@@ -31,9 +33,7 @@ const useStyles = makeStyles((theme) => ({
|
|
|
31
33
|
}));
|
|
32
34
|
const EditAPIProductDialog = ({ open, onClose, onSuccess, namespace, name }) => {
|
|
33
35
|
const classes = useStyles();
|
|
34
|
-
const
|
|
35
|
-
const fetchApi = useApi(fetchApiRef);
|
|
36
|
-
const backendUrl = config.getString("backend.baseUrl");
|
|
36
|
+
const kuadrantApi = useApi(kuadrantApiRef);
|
|
37
37
|
const [loading, setLoading] = useState(false);
|
|
38
38
|
const [displayName, setDisplayName] = useState("");
|
|
39
39
|
const [description, setDescription] = useState("");
|
|
@@ -48,7 +48,8 @@ const EditAPIProductDialog = ({ open, onClose, onSuccess, namespace, name }) =>
|
|
|
48
48
|
const [contactTeam, setContactTeam] = useState("");
|
|
49
49
|
const [docsURL, setDocsURL] = useState("");
|
|
50
50
|
const [openAPISpec, setOpenAPISpec] = useState("");
|
|
51
|
-
const [
|
|
51
|
+
const [planPolicyProps, setPlanPoliciesProps] = useState(null);
|
|
52
|
+
const [authPolicyProps, setAuthPolicyProps] = useState(null);
|
|
52
53
|
const [error, setError] = useState("");
|
|
53
54
|
const [saving, setSaving] = useState(false);
|
|
54
55
|
const [openAPISpecError, setOpenAPISpecError] = useState(null);
|
|
@@ -56,13 +57,7 @@ const EditAPIProductDialog = ({ open, onClose, onSuccess, namespace, name }) =>
|
|
|
56
57
|
if (open && namespace && name) {
|
|
57
58
|
setLoading(true);
|
|
58
59
|
setError("");
|
|
59
|
-
|
|
60
|
-
if (!res.ok) {
|
|
61
|
-
const error2 = await handleFetchError(res);
|
|
62
|
-
throw new Error(`failed to load API product. ${error2}`);
|
|
63
|
-
}
|
|
64
|
-
return res.json();
|
|
65
|
-
}).then((data) => {
|
|
60
|
+
kuadrantApi.getApiProduct(namespace, name).then((data) => {
|
|
66
61
|
setDisplayName(data.spec.displayName || "");
|
|
67
62
|
setDescription(data.spec.description || "");
|
|
68
63
|
setVersion(data.spec.version || "v1");
|
|
@@ -75,7 +70,28 @@ const EditAPIProductDialog = ({ open, onClose, onSuccess, namespace, name }) =>
|
|
|
75
70
|
setContactTeam(data.spec.contact?.team || "");
|
|
76
71
|
setDocsURL(data.spec.documentation?.docsURL || "");
|
|
77
72
|
setOpenAPISpec(data.spec.documentation?.openAPISpecURL || "");
|
|
78
|
-
|
|
73
|
+
const planPolicyCondition = data.status?.conditions?.find(
|
|
74
|
+
(c) => c.type === "PlanPolicyDiscovered"
|
|
75
|
+
) || null;
|
|
76
|
+
setPlanPoliciesProps({
|
|
77
|
+
statusCondition: planPolicyCondition,
|
|
78
|
+
discoveredPlans: data.status?.discoveredPlans || null
|
|
79
|
+
});
|
|
80
|
+
const authPolicyCondition = data.status?.conditions?.find(
|
|
81
|
+
(c) => c.type === "AuthPolicyDiscovered"
|
|
82
|
+
) || null;
|
|
83
|
+
const parseNameFromMessage = (value) => {
|
|
84
|
+
const parts = value.split(" ");
|
|
85
|
+
return parts.length >= 3 ? parts[2] : "";
|
|
86
|
+
};
|
|
87
|
+
const authPolicyName = authPolicyCondition?.status === "True" ? parseNameFromMessage(authPolicyCondition.message ?? "") : "";
|
|
88
|
+
setAuthPolicyProps({
|
|
89
|
+
statusCondition: authPolicyCondition,
|
|
90
|
+
namespacedName: {
|
|
91
|
+
name: authPolicyName,
|
|
92
|
+
namespace: data.metadata.namespace
|
|
93
|
+
}
|
|
94
|
+
});
|
|
79
95
|
setOpenAPISpecError(null);
|
|
80
96
|
setLoading(false);
|
|
81
97
|
}).catch((err) => {
|
|
@@ -83,12 +99,29 @@ const EditAPIProductDialog = ({ open, onClose, onSuccess, namespace, name }) =>
|
|
|
83
99
|
setLoading(false);
|
|
84
100
|
});
|
|
85
101
|
}
|
|
86
|
-
}, [open, namespace, name,
|
|
102
|
+
}, [open, namespace, name, kuadrantApi]);
|
|
87
103
|
useEffect(() => {
|
|
88
104
|
if (open) {
|
|
89
105
|
setOpenAPISpecError(null);
|
|
90
106
|
}
|
|
91
107
|
}, [open]);
|
|
108
|
+
const {
|
|
109
|
+
value: rateLimitPolicies,
|
|
110
|
+
error: rateLimitPoliciesError
|
|
111
|
+
} = useAsync(async () => {
|
|
112
|
+
return await kuadrantApi.getRateLimitPolicies();
|
|
113
|
+
}, [kuadrantApi, open]);
|
|
114
|
+
const selectedRateLimitPolicy = targetRef ? getPolicyForRoute(rateLimitPolicies?.items, namespace, targetRef.name) : null;
|
|
115
|
+
const rateLimitPolicyAcceptedCondition = selectedRateLimitPolicy?.status?.conditions?.find(
|
|
116
|
+
(c) => c.type === "Accepted"
|
|
117
|
+
);
|
|
118
|
+
const rateLimitPolicyProps = {
|
|
119
|
+
namespacedName: {
|
|
120
|
+
namespace: selectedRateLimitPolicy?.metadata.namespace,
|
|
121
|
+
name: selectedRateLimitPolicy?.metadata.name
|
|
122
|
+
},
|
|
123
|
+
statusCondition: rateLimitPolicyAcceptedCondition
|
|
124
|
+
};
|
|
92
125
|
const handleOpenAPISpecChange = (value) => {
|
|
93
126
|
setOpenAPISpec(value);
|
|
94
127
|
setOpenAPISpecError(validateURL(value));
|
|
@@ -112,6 +145,7 @@ const EditAPIProductDialog = ({ open, onClose, onSuccess, namespace, name }) =>
|
|
|
112
145
|
}
|
|
113
146
|
try {
|
|
114
147
|
const patch = {
|
|
148
|
+
// @ts-ignore We are applying a partial obj, not full
|
|
115
149
|
metadata: {
|
|
116
150
|
labels: {
|
|
117
151
|
lifecycle
|
|
@@ -139,20 +173,7 @@ const EditAPIProductDialog = ({ open, onClose, onSuccess, namespace, name }) =>
|
|
|
139
173
|
} : {}
|
|
140
174
|
}
|
|
141
175
|
};
|
|
142
|
-
|
|
143
|
-
`${backendUrl}/api/kuadrant/apiproducts/${namespace}/${name}`,
|
|
144
|
-
{
|
|
145
|
-
method: "PATCH",
|
|
146
|
-
headers: {
|
|
147
|
-
"Content-Type": "application/json"
|
|
148
|
-
},
|
|
149
|
-
body: JSON.stringify(patch)
|
|
150
|
-
}
|
|
151
|
-
);
|
|
152
|
-
if (!response.ok) {
|
|
153
|
-
const error2 = await handleFetchError(response);
|
|
154
|
-
throw new Error(`failed to patch APIProduct. ${error2}`);
|
|
155
|
-
}
|
|
176
|
+
await kuadrantApi.updateApiProduct(namespace, name, patch);
|
|
156
177
|
onSuccess();
|
|
157
178
|
onClose();
|
|
158
179
|
} catch (err) {
|
|
@@ -161,7 +182,7 @@ const EditAPIProductDialog = ({ open, onClose, onSuccess, namespace, name }) =>
|
|
|
161
182
|
setSaving(false);
|
|
162
183
|
}
|
|
163
184
|
};
|
|
164
|
-
return /* @__PURE__ */ React.createElement(Dialog, { open, onClose, maxWidth: "md", fullWidth: true }, /* @__PURE__ */ React.createElement(DialogTitle, null, "Edit API Product"), /* @__PURE__ */ React.createElement(DialogContent, null, error && /* @__PURE__ */ React.createElement(Alert, { severity: "error", style: { marginBottom: 16 } }, error), loading ? /* @__PURE__ */ React.createElement(Progress, null) : /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(Box, { className: classes.sectionHeader }, /* @__PURE__ */ React.createElement(Typography, { variant: "subtitle1" }, /* @__PURE__ */ React.createElement("strong", null, "API product info"))), /* @__PURE__ */ React.createElement(Grid, { container: true, spacing: 2 }, /* @__PURE__ */ React.createElement(Grid, { item: true, xs: 6 }, /* @__PURE__ */ React.createElement(
|
|
185
|
+
return /* @__PURE__ */ React.createElement(Dialog, { open, onClose, maxWidth: "md", fullWidth: true }, /* @__PURE__ */ React.createElement(DialogTitle, null, "Edit API Product"), /* @__PURE__ */ React.createElement(DialogContent, null, error && /* @__PURE__ */ React.createElement(Alert, { severity: "error", style: { marginBottom: 16 } }, error), rateLimitPoliciesError && /* @__PURE__ */ React.createElement(Alert, { severity: "error", style: { marginBottom: 16 } }, /* @__PURE__ */ React.createElement("strong", null, "Failed to load RateLimitPolicies:"), " ", rateLimitPoliciesError.message), loading ? /* @__PURE__ */ React.createElement(Progress, null) : /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(Box, { className: classes.sectionHeader }, /* @__PURE__ */ React.createElement(Typography, { variant: "subtitle1" }, /* @__PURE__ */ React.createElement("strong", null, "API product info"))), /* @__PURE__ */ React.createElement(Grid, { container: true, spacing: 2 }, /* @__PURE__ */ React.createElement(Grid, { item: true, xs: 6 }, /* @__PURE__ */ React.createElement(
|
|
165
186
|
TextField,
|
|
166
187
|
{
|
|
167
188
|
fullWidth: true,
|
|
@@ -287,11 +308,11 @@ const EditAPIProductDialog = ({ open, onClose, onSuccess, namespace, name }) =>
|
|
|
287
308
|
margin: "normal"
|
|
288
309
|
}
|
|
289
310
|
))), targetRef && /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(Box, { className: classes.sectionHeader }, /* @__PURE__ */ React.createElement(Typography, { variant: "subtitle1" }, /* @__PURE__ */ React.createElement("strong", null, "HTTPRoute policies")), /* @__PURE__ */ React.createElement(Tooltip, { title: "Shows the associated policies and rate limit tiers for the HTTPRoute" }, /* @__PURE__ */ React.createElement(InfoOutlinedIcon, { className: classes.infoIcon }))), /* @__PURE__ */ React.createElement(
|
|
290
|
-
|
|
311
|
+
ApiProductPolicies,
|
|
291
312
|
{
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
313
|
+
planPolicy: planPolicyProps,
|
|
314
|
+
authPolicy: authPolicyProps,
|
|
315
|
+
rateLimitPolicy: rateLimitPolicyProps,
|
|
295
316
|
includeTopMargin: false
|
|
296
317
|
}
|
|
297
318
|
)), /* @__PURE__ */ React.createElement(Box, { className: classes.sectionHeader }, /* @__PURE__ */ React.createElement(Typography, { variant: "subtitle1" }, /* @__PURE__ */ React.createElement("strong", null, "Lifecycle and Visibility")), /* @__PURE__ */ React.createElement(Tooltip, { title: "Control the lifecycle state and catalog visibility of this API product" }, /* @__PURE__ */ React.createElement(InfoOutlinedIcon, { className: classes.infoIcon }))), /* @__PURE__ */ React.createElement(Grid, { container: true, spacing: 2 }, /* @__PURE__ */ React.createElement(Grid, { item: true, xs: 6 }, /* @__PURE__ */ React.createElement(
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"EditAPIProductDialog.esm.js","sources":["../../../src/components/EditAPIProductDialog/EditAPIProductDialog.tsx"],"sourcesContent":["import React, { useState, useEffect } from 'react';\nimport {\n Dialog,\n DialogTitle,\n DialogContent,\n DialogActions,\n Button,\n TextField,\n Box,\n Typography,\n Chip,\n Grid,\n MenuItem,\n CircularProgress,\n makeStyles,\n FormControl,\n RadioGroup,\n FormControlLabel,\n Radio,\n Tooltip,\n IconButton,\n InputAdornment,\n} from '@material-ui/core';\nimport InfoOutlinedIcon from '@material-ui/icons/InfoOutlined';\nimport AddIcon from '@material-ui/icons/Add';\nimport { useApi, configApiRef, fetchApiRef } from '@backstage/core-plugin-api';\nimport { Alert } from '@material-ui/lab';\nimport { Progress } from '@backstage/core-components';\nimport { PlanPolicyDetails } from '../PlanPolicyDetailsCard';\nimport { validateURL } from '../../utils/validation';\nimport { handleFetchError } from \"../../utils/errors\";\nimport { Lifecycle } from '../../types/api-management';\n\nconst useStyles = makeStyles((theme) => ({\n asterisk: {\n color: '#f44336',\n },\n sectionHeader: {\n display: 'flex',\n alignItems: 'center',\n gap: theme.spacing(0.5),\n marginTop: theme.spacing(2),\n marginBottom: theme.spacing(1),\n },\n infoIcon: {\n fontSize: 18,\n color: theme.palette.text.secondary,\n },\n tagChip: {\n marginRight: theme.spacing(0.5),\n marginBottom: theme.spacing(0.5),\n },\n}));\n\ninterface EditAPIProductDialogProps {\n open: boolean;\n onClose: () => void;\n onSuccess: () => void;\n namespace: string;\n name: string;\n}\n\nexport const EditAPIProductDialog = ({ open, onClose, onSuccess, namespace, name }: EditAPIProductDialogProps) => {\n const classes = useStyles();\n const 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 [lifecycle, setLifecycle] = useState<Lifecycle>('production');\n const [approvalMode, setApprovalMode] = useState<'automatic' | 'manual'>('manual');\n const [tags, setTags] = useState<string[]>([]);\n const [targetRef, setTargetRef] = useState<any>(null);\n const [tagInput, setTagInput] = useState('');\n const [contactEmail, setContactEmail] = useState('');\n const [contactTeam, setContactTeam] = useState('');\n const [docsURL, setDocsURL] = useState('');\n const [openAPISpec, setOpenAPISpec] = useState('');\n const [discoveredPlans, setdiscoveredPlans] = useState([]);\n const [error, setError] = useState('');\n const [saving, setSaving] = useState(false);\n const [openAPISpecError, setOpenAPISpecError] = useState<string | null>(null);\n\n // Load APIProduct data when dialog opens\n useEffect(() => {\n if (open && namespace && name) {\n setLoading(true);\n setError('');\n\n fetchApi.fetch(`${backendUrl}/api/kuadrant/apiproducts/${namespace}/${name}`)\n .then(async res => {\n if (!res.ok) {\n const error = await handleFetchError(res);\n throw new Error(`failed to load API product. ${error}`);\n }\n return res.json();\n })\n .then(data => {\n setDisplayName(data.spec.displayName || '');\n setDescription(data.spec.description || '');\n setVersion(data.spec.version || 'v1');\n setPublishStatus(data.spec.publishStatus || 'Draft');\n setLifecycle(data.metadata.labels?.lifecycle || 'production');\n setApprovalMode(data.spec.approvalMode || 'manual');\n setTags(data.spec.tags || []);\n setTargetRef(data.spec.targetRef || null);\n setContactEmail(data.spec.contact?.email || '');\n setContactTeam(data.spec.contact?.team || '');\n setDocsURL(data.spec.documentation?.docsURL || '');\n setOpenAPISpec(data.spec.documentation?.openAPISpecURL || '');\n setdiscoveredPlans(data.status.discoveredPlans || null);\n setOpenAPISpecError(null);\n setLoading(false);\n })\n .catch(err => {\n setError(err.message || 'Failed to load API product');\n setLoading(false);\n });\n }\n }, [open, namespace, name, backendUrl, fetchApi]);\n\n useEffect(() => {\n if (open) {\n setOpenAPISpecError(null);\n }\n }, [open]);\n\n const handleOpenAPISpecChange = (value: string) => {\n setOpenAPISpec(value);\n setOpenAPISpecError(validateURL(value));\n };\n\n const handleAddTag = () => {\n if (tagInput.trim() && !tags.includes(tagInput.trim())) {\n setTags([...tags, tagInput.trim()]);\n setTagInput('');\n }\n };\n\n const handleDeleteTag = (tagToDelete: string) => {\n setTags(tags.filter(tag => tag !== tagToDelete));\n };\n\n const handleSave = async () => {\n setError('');\n setSaving(true);\n\n // validate retired APIs cannot be published\n if (lifecycle === 'retired' && publishStatus === 'Published') {\n setError('Cannot publish a retired API product. Please set publish status to Draft.');\n setSaving(false);\n return;\n }\n\n try {\n const patch = {\n metadata: {\n labels: {\n lifecycle,\n },\n },\n spec: {\n displayName,\n description,\n version,\n publishStatus,\n approvalMode,\n tags,\n targetRef,\n ...(contactEmail || contactTeam ? {\n contact: {\n ...(contactEmail && { email: contactEmail }),\n ...(contactTeam && { team: contactTeam }),\n },\n } : {}),\n ...(docsURL || openAPISpec ? {\n documentation: {\n ...(docsURL && { docsURL }),\n ...(openAPISpec && { openAPISpecURL: openAPISpec }),\n },\n } : {}),\n },\n };\n\n const response = await fetchApi.fetch(\n `${backendUrl}/api/kuadrant/apiproducts/${namespace}/${name}`,\n {\n method: 'PATCH',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify(patch),\n }\n );\n\n if (!response.ok) {\n const error = await handleFetchError(response);\n throw new Error(`failed to patch APIProduct. ${error}`);\n }\n\n onSuccess();\n onClose();\n } catch (err) {\n setError(err instanceof Error ? err.message : String(err));\n } finally {\n setSaving(false);\n }\n };\n\n return (\n <Dialog open={open} onClose={onClose} maxWidth=\"md\" fullWidth>\n <DialogTitle>Edit API Product</DialogTitle>\n <DialogContent>\n {error && (\n <Alert severity=\"error\" style={{ marginBottom: 16 }}>\n {error}\n </Alert>\n )}\n {loading ? (\n <Progress />\n ) : (\n <>\n {/* API product info section */}\n <Box className={classes.sectionHeader}>\n <Typography variant=\"subtitle1\"><strong>API product info</strong></Typography>\n </Box>\n <Grid container spacing={2}>\n <Grid item xs={6}>\n <TextField\n fullWidth\n label=\"API product name\"\n value={displayName}\n onChange={e => setDisplayName(e.target.value)}\n placeholder=\"My API\"\n helperText=\"Give a unique name for your API product\"\n margin=\"normal\"\n required\n disabled={saving}\n InputLabelProps={{\n classes: {\n asterisk: classes.asterisk,\n },\n }}\n />\n </Grid>\n <Grid item xs={6}>\n <TextField\n fullWidth\n label=\"Resource name\"\n value={name}\n disabled\n helperText=\"Kubernetes resource name (immutable)\"\n margin=\"normal\"\n />\n </Grid>\n <Grid item xs={6}>\n <TextField\n fullWidth\n label=\"Version\"\n value={version}\n onChange={e => setVersion(e.target.value)}\n placeholder=\"v1\"\n helperText=\"Give a version to your API product\"\n margin=\"normal\"\n disabled={saving}\n />\n </Grid>\n <Grid item xs={6}>\n <TextField\n fullWidth\n label=\"Tag\"\n value={tagInput}\n onChange={e => setTagInput(e.target.value)}\n onKeyPress={e => {\n if (e.key === 'Enter') {\n e.preventDefault();\n handleAddTag();\n }\n }}\n placeholder=\"Add tag\"\n helperText=\"Add a tag to your API product\"\n margin=\"normal\"\n disabled={saving}\n InputProps={{\n endAdornment: tagInput ? (\n <InputAdornment position=\"end\">\n <IconButton size=\"small\" onClick={handleAddTag} disabled={saving}>\n <AddIcon fontSize=\"small\" />\n </IconButton>\n </InputAdornment>\n ) : undefined,\n }}\n />\n </Grid>\n {tags.length > 0 && (\n <Grid item xs={12}>\n <Box display=\"flex\" flexWrap=\"wrap\">\n {tags.map(tag => (\n <Chip\n key={tag}\n label={tag}\n onDelete={saving ? undefined : () => handleDeleteTag(tag)}\n size=\"small\"\n className={classes.tagChip}\n disabled={saving}\n />\n ))}\n </Box>\n </Grid>\n )}\n <Grid item xs={12}>\n <TextField\n fullWidth\n label=\"Description\"\n value={description}\n onChange={e => setDescription(e.target.value)}\n placeholder=\"API description\"\n margin=\"normal\"\n multiline\n rows={2}\n required\n disabled={saving}\n InputLabelProps={{\n classes: {\n asterisk: classes.asterisk,\n },\n }}\n />\n </Grid>\n </Grid>\n\n {/* Associated route section */}\n <Box className={classes.sectionHeader}>\n <Typography variant=\"subtitle1\"><strong>Associated route</strong></Typography>\n <Tooltip title=\"The HTTPRoute this API product is associated with\">\n <InfoOutlinedIcon className={classes.infoIcon} />\n </Tooltip>\n </Box>\n <Grid container spacing={2}>\n <Grid item xs={12}>\n <TextField\n fullWidth\n label=\"OpenAPI Spec URL\"\n value={openAPISpec}\n onChange={e => handleOpenAPISpecChange(e.target.value)}\n placeholder=\"https://api.example.com/openapi.json\"\n helperText={openAPISpecError || \"Enter the full path to your API spec file\"}\n error={!!openAPISpecError}\n margin=\"normal\"\n disabled={saving}\n />\n </Grid>\n <Grid item xs={12}>\n <TextField\n fullWidth\n label=\"Documentation URL\"\n value={docsURL}\n onChange={e => setDocsURL(e.target.value)}\n placeholder=\"https://docs.example.com/api\"\n helperText=\"Link to external documentation for this API\"\n margin=\"normal\"\n disabled={saving}\n />\n </Grid>\n {targetRef && (\n <Grid item xs={12}>\n <TextField\n fullWidth\n label=\"HTTPRoute\"\n value={`${targetRef.namespace || namespace}/${targetRef.name}`}\n disabled\n helperText=\"Target HTTPRoute (immutable)\"\n margin=\"normal\"\n />\n </Grid>\n )}\n </Grid>\n\n {/* HTTPRoute policies section */}\n {targetRef && (\n <>\n <Box className={classes.sectionHeader}>\n <Typography variant=\"subtitle1\"><strong>HTTPRoute policies</strong></Typography>\n <Tooltip title=\"Shows the associated policies and rate limit tiers for the HTTPRoute\">\n <InfoOutlinedIcon className={classes.infoIcon} />\n </Tooltip>\n </Box>\n <PlanPolicyDetails\n discoveredPlans={discoveredPlans}\n alertSeverity=\"info\"\n alertMessage=\"No PlanPolicy found for this HTTPRoute.\"\n includeTopMargin={false}\n />\n </>\n )}\n\n {/* Lifecycle and Visibility section */}\n <Box className={classes.sectionHeader}>\n <Typography variant=\"subtitle1\"><strong>Lifecycle and Visibility</strong></Typography>\n <Tooltip title=\"Control the lifecycle state and catalog visibility of this API product\">\n <InfoOutlinedIcon className={classes.infoIcon} />\n </Tooltip>\n </Box>\n <Grid container spacing={2}>\n <Grid item xs={6}>\n <TextField\n fullWidth\n select\n label=\"Lifecycle\"\n value={lifecycle}\n onChange={e => setLifecycle(e.target.value as Lifecycle)}\n margin=\"normal\"\n helperText=\"API lifecycle state\"\n disabled={saving}\n >\n <MenuItem value=\"experimental\">Experimental</MenuItem>\n <MenuItem value=\"production\">Production</MenuItem>\n <MenuItem value=\"deprecated\">Deprecated</MenuItem>\n <MenuItem value=\"retired\">Retired</MenuItem>\n </TextField>\n </Grid>\n <Grid item xs={6}>\n <TextField\n fullWidth\n select\n label=\"Publish Status\"\n value={publishStatus}\n onChange={e => setPublishStatus(e.target.value as 'Draft' | 'Published')}\n margin=\"normal\"\n helperText=\"Controls catalog visibility\"\n disabled={saving}\n >\n <MenuItem value=\"Draft\">Draft</MenuItem>\n <MenuItem value=\"Published\">Published</MenuItem>\n </TextField>\n </Grid>\n </Grid>\n\n {/* API Key approval section */}\n <Box className={classes.sectionHeader}>\n <Typography variant=\"subtitle1\"><strong>API Key approval</strong></Typography>\n <Tooltip title=\"Choose how API key requests are handled for this product\">\n <InfoOutlinedIcon className={classes.infoIcon} />\n </Tooltip>\n </Box>\n <FormControl component=\"fieldset\" disabled={saving}>\n <RadioGroup\n row\n value={approvalMode}\n onChange={e => setApprovalMode(e.target.value as 'automatic' | 'manual')}\n >\n <FormControlLabel\n value=\"manual\"\n control={<Radio color=\"primary\" />}\n label={\n <Box>\n <Typography variant=\"body2\">Need manual approval</Typography>\n <Typography variant=\"caption\" color=\"textSecondary\">\n Requires approval for requesting this API\n </Typography>\n </Box>\n }\n />\n <FormControlLabel\n value=\"automatic\"\n control={<Radio color=\"primary\" />}\n label={\n <Box>\n <Typography variant=\"body2\">Automatic</Typography>\n <Typography variant=\"caption\" color=\"textSecondary\">\n Keys are created without need to be approved\n </Typography>\n </Box>\n }\n />\n </RadioGroup>\n </FormControl>\n </>\n )}\n </DialogContent>\n <DialogActions>\n <Button onClick={onClose} disabled={saving}>Cancel</Button>\n <Button\n onClick={handleSave}\n color=\"primary\"\n variant=\"contained\"\n disabled={saving || loading || !displayName || !description || !!openAPISpecError}\n startIcon={saving ? <CircularProgress size={16} color=\"inherit\" /> : undefined}\n >\n {saving ? 'Saving...' : 'Save'}\n </Button>\n </DialogActions>\n </Dialog>\n );\n};\n"],"names":["error"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"EditAPIProductDialog.esm.js","sources":["../../../src/components/EditAPIProductDialog/EditAPIProductDialog.tsx"],"sourcesContent":["import React, { useState, useEffect } from 'react';\nimport {\n Dialog,\n DialogTitle,\n DialogContent,\n DialogActions,\n Button,\n TextField,\n Box,\n Typography,\n Chip,\n Grid,\n MenuItem,\n CircularProgress,\n makeStyles,\n FormControl,\n RadioGroup,\n FormControlLabel,\n Radio,\n Tooltip,\n IconButton,\n InputAdornment,\n} from '@material-ui/core';\nimport InfoOutlinedIcon from '@material-ui/icons/InfoOutlined';\nimport AddIcon from '@material-ui/icons/Add';\nimport { useApi } from '@backstage/core-plugin-api';\nimport { kuadrantApiRef } from '../../api';\nimport { Alert } from '@material-ui/lab';\nimport useAsync from 'react-use/lib/useAsync';\nimport { Progress } from '@backstage/core-components';\nimport { ApiProductPolicies, PlanPoliciesProps, AuthPoliciesProps, RateLimitPoliciesProps } from '../ApiProductPolicies';\nimport { validateURL } from '../../utils/validation';\nimport { APIProduct } from \"../../types/api-management.ts\";\nimport { Lifecycle } from '../../types/api-management';\nimport { getPolicyForRoute } from '../../utils/policies';\n\nconst useStyles = makeStyles((theme) => ({\n asterisk: {\n color: '#f44336',\n },\n sectionHeader: {\n display: 'flex',\n alignItems: 'center',\n gap: theme.spacing(0.5),\n marginTop: theme.spacing(2),\n marginBottom: theme.spacing(1),\n },\n infoIcon: {\n fontSize: 18,\n color: theme.palette.text.secondary,\n },\n tagChip: {\n marginRight: theme.spacing(0.5),\n marginBottom: theme.spacing(0.5),\n },\n}));\n\ninterface EditAPIProductDialogProps {\n open: boolean;\n onClose: () => void;\n onSuccess: () => void;\n namespace: string;\n name: string;\n}\n\nexport const EditAPIProductDialog = ({ open, onClose, onSuccess, namespace, name }: EditAPIProductDialogProps) => {\n const classes = useStyles();\n const kuadrantApi = useApi(kuadrantApiRef);\n const [loading, setLoading] = useState(false);\n const [displayName, setDisplayName] = useState('');\n const [description, setDescription] = useState('');\n const [version, setVersion] = useState('v1');\n const [publishStatus, setPublishStatus] = useState<'Draft' | 'Published'>('Draft');\n const [lifecycle, setLifecycle] = useState<Lifecycle>('production');\n const [approvalMode, setApprovalMode] = useState<'automatic' | 'manual'>('manual');\n const [tags, setTags] = useState<string[]>([]);\n const [targetRef, setTargetRef] = useState<any>(null);\n const [tagInput, setTagInput] = useState('');\n const [contactEmail, setContactEmail] = useState('');\n const [contactTeam, setContactTeam] = useState('');\n const [docsURL, setDocsURL] = useState('');\n const [openAPISpec, setOpenAPISpec] = useState('');\n const [planPolicyProps, setPlanPoliciesProps] = useState<PlanPoliciesProps | null>(null);\n const [authPolicyProps, setAuthPolicyProps] = useState<AuthPoliciesProps | null>(null);\n const [error, setError] = useState('');\n const [saving, setSaving] = useState(false);\n const [openAPISpecError, setOpenAPISpecError] = useState<string | null>(null);\n\n // Load APIProduct data when dialog opens\n useEffect(() => {\n if (open && namespace && name) {\n setLoading(true);\n setError('');\n kuadrantApi.getApiProduct(namespace, name)\n .then(data => {\n setDisplayName(data.spec.displayName || '');\n setDescription(data.spec.description || '');\n setVersion(data.spec.version || 'v1');\n setPublishStatus(data.spec.publishStatus || 'Draft');\n setLifecycle(data.metadata.labels?.lifecycle as Lifecycle || 'production' as Lifecycle);\n setApprovalMode(data.spec.approvalMode || 'manual');\n setTags(data.spec.tags || []);\n setTargetRef(data.spec.targetRef || null);\n setContactEmail(data.spec.contact?.email || '');\n setContactTeam(data.spec.contact?.team || '');\n setDocsURL(data.spec.documentation?.docsURL || '');\n setOpenAPISpec(data.spec.documentation?.openAPISpecURL || '');\n const planPolicyCondition = data.status?.conditions?.find(\n (c: any) => c.type === \"PlanPolicyDiscovered\"\n ) || null;\n setPlanPoliciesProps({\n statusCondition: planPolicyCondition,\n discoveredPlans: data.status?.discoveredPlans || null,\n });\n const authPolicyCondition = data.status?.conditions?.find(\n (c: any) => c.type === \"AuthPolicyDiscovered\"\n ) || null;\n // Parse the auth policy name from the AuthPolicyDiscovered condition message\n // It's the only place to get the policy name without fetching all the policies.\n // Consider enhancing the developer portal controller to provide name in an structured way\n const parseNameFromMessage = (value: string) => {\n const parts = value.split(' ');\n return parts.length >= 3 ? parts[2] : '';\n };\n const authPolicyName = authPolicyCondition?.status === \"True\" ? parseNameFromMessage(authPolicyCondition.message ?? \"\") : \"\";\n setAuthPolicyProps({\n statusCondition: authPolicyCondition,\n namespacedName: {\n name: authPolicyName,\n namespace: data.metadata.namespace,\n },\n });\n setOpenAPISpecError(null);\n setLoading(false);\n })\n .catch(err => {\n setError(err.message || 'Failed to load API product');\n setLoading(false);\n });\n }\n }, [open, namespace, name, kuadrantApi]);\n\n useEffect(() => {\n if (open) {\n setOpenAPISpecError(null);\n }\n }, [open]);\n\n // load ratelimitpolicies\n const {\n value: rateLimitPolicies,\n error: rateLimitPoliciesError\n } = useAsync(async () => {\n return await kuadrantApi.getRateLimitPolicies();\n }, [kuadrantApi, open]);\n\n const selectedRateLimitPolicy = targetRef\n ? getPolicyForRoute(rateLimitPolicies?.items, namespace, targetRef.name)\n : null;\n const rateLimitPolicyAcceptedCondition = selectedRateLimitPolicy?.status?.conditions?.find(\n (c: any) => c.type === \"Accepted\"\n );\n const rateLimitPolicyProps: RateLimitPoliciesProps = {\n namespacedName: {\n namespace: selectedRateLimitPolicy?.metadata.namespace,\n name: selectedRateLimitPolicy?.metadata.name,\n },\n statusCondition: rateLimitPolicyAcceptedCondition,\n }\n\n const handleOpenAPISpecChange = (value: string) => {\n setOpenAPISpec(value);\n setOpenAPISpecError(validateURL(value));\n };\n\n const handleAddTag = () => {\n if (tagInput.trim() && !tags.includes(tagInput.trim())) {\n setTags([...tags, tagInput.trim()]);\n setTagInput('');\n }\n };\n\n const handleDeleteTag = (tagToDelete: string) => {\n setTags(tags.filter(tag => tag !== tagToDelete));\n };\n\n const handleSave = async () => {\n setError('');\n setSaving(true);\n\n // validate retired APIs cannot be published\n if (lifecycle === 'retired' && publishStatus === 'Published') {\n setError('Cannot publish a retired API product. Please set publish status to Draft.');\n setSaving(false);\n return;\n }\n\n try {\n const patch: Partial<APIProduct> = {\n // @ts-ignore We are applying a partial obj, not full\n metadata: {\n labels: {\n lifecycle,\n },\n },\n spec: {\n displayName,\n description,\n version,\n publishStatus,\n approvalMode,\n tags,\n targetRef,\n ...(contactEmail || contactTeam ? {\n contact: {\n ...(contactEmail && { email: contactEmail }),\n ...(contactTeam && { team: contactTeam }),\n },\n } : {}),\n ...(docsURL || openAPISpec ? {\n documentation: {\n ...(docsURL && { docsURL }),\n ...(openAPISpec && { openAPISpecURL: openAPISpec }),\n },\n } : {}),\n },\n };\n\n await kuadrantApi.updateApiProduct(namespace, name, patch);\n onSuccess();\n onClose();\n } catch (err) {\n setError(err instanceof Error ? err.message : String(err));\n } finally {\n setSaving(false);\n }\n };\n\n return (\n <Dialog open={open} onClose={onClose} maxWidth=\"md\" fullWidth>\n <DialogTitle>Edit API Product</DialogTitle>\n <DialogContent>\n {error && (\n <Alert severity=\"error\" style={{ marginBottom: 16 }}>\n {error}\n </Alert>\n )}\n {rateLimitPoliciesError && (\n <Alert severity=\"error\" style={{ marginBottom: 16 }}>\n <strong>Failed to load RateLimitPolicies:</strong> {rateLimitPoliciesError.message}\n </Alert>\n )}\n {loading ? (\n <Progress />\n ) : (\n <>\n {/* API product info section */}\n <Box className={classes.sectionHeader}>\n <Typography variant=\"subtitle1\"><strong>API product info</strong></Typography>\n </Box>\n <Grid container spacing={2}>\n <Grid item xs={6}>\n <TextField\n fullWidth\n label=\"API product name\"\n value={displayName}\n onChange={e => setDisplayName(e.target.value)}\n placeholder=\"My API\"\n helperText=\"Give a unique name for your API product\"\n margin=\"normal\"\n required\n disabled={saving}\n InputLabelProps={{\n classes: {\n asterisk: classes.asterisk,\n },\n }}\n />\n </Grid>\n <Grid item xs={6}>\n <TextField\n fullWidth\n label=\"Resource name\"\n value={name}\n disabled\n helperText=\"Kubernetes resource name (immutable)\"\n margin=\"normal\"\n />\n </Grid>\n <Grid item xs={6}>\n <TextField\n fullWidth\n label=\"Version\"\n value={version}\n onChange={e => setVersion(e.target.value)}\n placeholder=\"v1\"\n helperText=\"Give a version to your API product\"\n margin=\"normal\"\n disabled={saving}\n />\n </Grid>\n <Grid item xs={6}>\n <TextField\n fullWidth\n label=\"Tag\"\n value={tagInput}\n onChange={e => setTagInput(e.target.value)}\n onKeyPress={e => {\n if (e.key === 'Enter') {\n e.preventDefault();\n handleAddTag();\n }\n }}\n placeholder=\"Add tag\"\n helperText=\"Add a tag to your API product\"\n margin=\"normal\"\n disabled={saving}\n InputProps={{\n endAdornment: tagInput ? (\n <InputAdornment position=\"end\">\n <IconButton size=\"small\" onClick={handleAddTag} disabled={saving}>\n <AddIcon fontSize=\"small\" />\n </IconButton>\n </InputAdornment>\n ) : undefined,\n }}\n />\n </Grid>\n {tags.length > 0 && (\n <Grid item xs={12}>\n <Box display=\"flex\" flexWrap=\"wrap\">\n {tags.map(tag => (\n <Chip\n key={tag}\n label={tag}\n onDelete={saving ? undefined : () => handleDeleteTag(tag)}\n size=\"small\"\n className={classes.tagChip}\n disabled={saving}\n />\n ))}\n </Box>\n </Grid>\n )}\n <Grid item xs={12}>\n <TextField\n fullWidth\n label=\"Description\"\n value={description}\n onChange={e => setDescription(e.target.value)}\n placeholder=\"API description\"\n margin=\"normal\"\n multiline\n rows={2}\n required\n disabled={saving}\n InputLabelProps={{\n classes: {\n asterisk: classes.asterisk,\n },\n }}\n />\n </Grid>\n </Grid>\n\n {/* Associated route section */}\n <Box className={classes.sectionHeader}>\n <Typography variant=\"subtitle1\"><strong>Associated route</strong></Typography>\n <Tooltip title=\"The HTTPRoute this API product is associated with\">\n <InfoOutlinedIcon className={classes.infoIcon} />\n </Tooltip>\n </Box>\n <Grid container spacing={2}>\n <Grid item xs={12}>\n <TextField\n fullWidth\n label=\"OpenAPI Spec URL\"\n value={openAPISpec}\n onChange={e => handleOpenAPISpecChange(e.target.value)}\n placeholder=\"https://api.example.com/openapi.json\"\n helperText={openAPISpecError || \"Enter the full path to your API spec file\"}\n error={!!openAPISpecError}\n margin=\"normal\"\n disabled={saving}\n />\n </Grid>\n <Grid item xs={12}>\n <TextField\n fullWidth\n label=\"Documentation URL\"\n value={docsURL}\n onChange={e => setDocsURL(e.target.value)}\n placeholder=\"https://docs.example.com/api\"\n helperText=\"Link to external documentation for this API\"\n margin=\"normal\"\n disabled={saving}\n />\n </Grid>\n {targetRef && (\n <Grid item xs={12}>\n <TextField\n fullWidth\n label=\"HTTPRoute\"\n value={`${targetRef.namespace || namespace}/${targetRef.name}`}\n disabled\n helperText=\"Target HTTPRoute (immutable)\"\n margin=\"normal\"\n />\n </Grid>\n )}\n </Grid>\n\n {/* HTTPRoute policies section */}\n {targetRef && (\n <>\n <Box className={classes.sectionHeader}>\n <Typography variant=\"subtitle1\"><strong>HTTPRoute policies</strong></Typography>\n <Tooltip title=\"Shows the associated policies and rate limit tiers for the HTTPRoute\">\n <InfoOutlinedIcon className={classes.infoIcon} />\n </Tooltip>\n </Box>\n <ApiProductPolicies\n planPolicy={planPolicyProps}\n authPolicy={authPolicyProps}\n rateLimitPolicy={rateLimitPolicyProps}\n includeTopMargin={false}\n />\n </>\n )}\n\n {/* Lifecycle and Visibility section */}\n <Box className={classes.sectionHeader}>\n <Typography variant=\"subtitle1\"><strong>Lifecycle and Visibility</strong></Typography>\n <Tooltip title=\"Control the lifecycle state and catalog visibility of this API product\">\n <InfoOutlinedIcon className={classes.infoIcon} />\n </Tooltip>\n </Box>\n <Grid container spacing={2}>\n <Grid item xs={6}>\n <TextField\n fullWidth\n select\n label=\"Lifecycle\"\n value={lifecycle}\n onChange={e => setLifecycle(e.target.value as Lifecycle)}\n margin=\"normal\"\n helperText=\"API lifecycle state\"\n disabled={saving}\n >\n <MenuItem value=\"experimental\">Experimental</MenuItem>\n <MenuItem value=\"production\">Production</MenuItem>\n <MenuItem value=\"deprecated\">Deprecated</MenuItem>\n <MenuItem value=\"retired\">Retired</MenuItem>\n </TextField>\n </Grid>\n <Grid item xs={6}>\n <TextField\n fullWidth\n select\n label=\"Publish Status\"\n value={publishStatus}\n onChange={e => setPublishStatus(e.target.value as 'Draft' | 'Published')}\n margin=\"normal\"\n helperText=\"Controls catalog visibility\"\n disabled={saving}\n >\n <MenuItem value=\"Draft\">Draft</MenuItem>\n <MenuItem value=\"Published\">Published</MenuItem>\n </TextField>\n </Grid>\n </Grid>\n\n {/* API Key approval section */}\n <Box className={classes.sectionHeader}>\n <Typography variant=\"subtitle1\"><strong>API Key approval</strong></Typography>\n <Tooltip title=\"Choose how API key requests are handled for this product\">\n <InfoOutlinedIcon className={classes.infoIcon} />\n </Tooltip>\n </Box>\n <FormControl component=\"fieldset\" disabled={saving}>\n <RadioGroup\n row\n value={approvalMode}\n onChange={e => setApprovalMode(e.target.value as 'automatic' | 'manual')}\n >\n <FormControlLabel\n value=\"manual\"\n control={<Radio color=\"primary\" />}\n label={\n <Box>\n <Typography variant=\"body2\">Need manual approval</Typography>\n <Typography variant=\"caption\" color=\"textSecondary\">\n Requires approval for requesting this API\n </Typography>\n </Box>\n }\n />\n <FormControlLabel\n value=\"automatic\"\n control={<Radio color=\"primary\" />}\n label={\n <Box>\n <Typography variant=\"body2\">Automatic</Typography>\n <Typography variant=\"caption\" color=\"textSecondary\">\n Keys are created without need to be approved\n </Typography>\n </Box>\n }\n />\n </RadioGroup>\n </FormControl>\n </>\n )}\n </DialogContent>\n <DialogActions>\n <Button onClick={onClose} disabled={saving}>Cancel</Button>\n <Button\n onClick={handleSave}\n color=\"primary\"\n variant=\"contained\"\n disabled={saving || loading || !displayName || !description || !!openAPISpecError}\n startIcon={saving ? <CircularProgress size={16} color=\"inherit\" /> : undefined}\n >\n {saving ? 'Saving...' : 'Save'}\n </Button>\n </DialogActions>\n </Dialog>\n );\n};\n"],"names":[],"mappings":"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"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import React, { useState } from 'react';
|
|
2
2
|
import { useEntity } from '@backstage/plugin-catalog-react';
|
|
3
|
-
import { useApi,
|
|
3
|
+
import { useApi, identityApiRef, alertApiRef } from '@backstage/core-plugin-api';
|
|
4
|
+
import { kuadrantApiRef } from '../../api.esm.js';
|
|
4
5
|
import { useAsync } from 'react-use';
|
|
5
6
|
import { Progress, ResponseErrorPanel, Table } from '@backstage/core-components';
|
|
6
7
|
import { kuadrantApiKeyApprovePermission } from '../../permissions.esm.js';
|
|
@@ -9,7 +10,6 @@ import { makeStyles, Box, Typography, Dialog, DialogTitle, DialogContent, TextFi
|
|
|
9
10
|
import CheckCircleIcon from '@material-ui/icons/CheckCircle';
|
|
10
11
|
import CancelIcon from '@material-ui/icons/Cancel';
|
|
11
12
|
import { getApprovalQueueStatusChipStyle } from '../../utils/styles.esm.js';
|
|
12
|
-
import { handleFetchError } from '../../utils/errors.esm.js';
|
|
13
13
|
|
|
14
14
|
const useStyles = makeStyles((theme) => ({
|
|
15
15
|
useCasePanel: {
|
|
@@ -83,11 +83,9 @@ const ApprovalDialog = ({
|
|
|
83
83
|
};
|
|
84
84
|
const EntityApiApprovalTab = () => {
|
|
85
85
|
const { entity } = useEntity();
|
|
86
|
-
const
|
|
87
|
-
const fetchApi = useApi(fetchApiRef);
|
|
86
|
+
const kuadrantApi = useApi(kuadrantApiRef);
|
|
88
87
|
const identityApi = useApi(identityApiRef);
|
|
89
88
|
const alertApi = useApi(alertApiRef);
|
|
90
|
-
const backendUrl = config.getString("backend.baseUrl");
|
|
91
89
|
const apiProductName = entity.metadata.annotations?.["kuadrant.io/apiproduct"] || entity.metadata.name;
|
|
92
90
|
const namespace = entity.metadata.annotations?.["kuadrant.io/namespace"] || "default";
|
|
93
91
|
const [refresh, setRefresh] = useState(0);
|
|
@@ -105,20 +103,13 @@ const EntityApiApprovalTab = () => {
|
|
|
105
103
|
const { value, loading, error } = useAsync(async () => {
|
|
106
104
|
const identity = await identityApi.getBackstageIdentity();
|
|
107
105
|
const reviewedBy = identity.userEntityRef;
|
|
108
|
-
const
|
|
109
|
-
`${backendUrl}/api/kuadrant/requests`
|
|
110
|
-
);
|
|
111
|
-
if (!response.ok) {
|
|
112
|
-
const err = await handleFetchError(response);
|
|
113
|
-
throw new Error(`Failed to fetch requests. ${err}`);
|
|
114
|
-
}
|
|
115
|
-
const data = await response.json();
|
|
106
|
+
const data = await kuadrantApi.getRequests();
|
|
116
107
|
const allRequests = data.items || [];
|
|
117
108
|
const filtered = allRequests.filter(
|
|
118
109
|
(r) => r.spec.apiProductRef?.name === apiProductName && r.metadata.namespace === namespace
|
|
119
110
|
);
|
|
120
111
|
return { requests: filtered, reviewedBy };
|
|
121
|
-
}, [
|
|
112
|
+
}, [kuadrantApi, identityApi, apiProductName, namespace, refresh]);
|
|
122
113
|
const handleApprove = (request) => {
|
|
123
114
|
setDialogState({
|
|
124
115
|
open: true,
|
|
@@ -138,17 +129,10 @@ const EntityApiApprovalTab = () => {
|
|
|
138
129
|
const handleConfirm = async () => {
|
|
139
130
|
if (!dialogState.request || !value) return;
|
|
140
131
|
setDialogState((prev) => ({ ...prev, processing: true }));
|
|
141
|
-
const
|
|
132
|
+
const isApprove = dialogState.action === "approve";
|
|
133
|
+
const requestFn = isApprove ? (ns, n, r) => kuadrantApi.approveRequest(ns, n, r) : (ns, n, r) => kuadrantApi.rejectRequest(ns, n, r);
|
|
142
134
|
try {
|
|
143
|
-
|
|
144
|
-
method: "POST",
|
|
145
|
-
headers: { "Content-Type": "application/json" },
|
|
146
|
-
body: JSON.stringify({ reviewedBy: value.reviewedBy })
|
|
147
|
-
});
|
|
148
|
-
if (!response.ok) {
|
|
149
|
-
const err = await handleFetchError(response);
|
|
150
|
-
throw new Error(err);
|
|
151
|
-
}
|
|
135
|
+
await requestFn(dialogState.request.metadata.namespace, dialogState.request.metadata.name, value.reviewedBy);
|
|
152
136
|
setDialogState({
|
|
153
137
|
open: false,
|
|
154
138
|
request: null,
|
|
@@ -157,7 +141,7 @@ const EntityApiApprovalTab = () => {
|
|
|
157
141
|
});
|
|
158
142
|
setRefresh((r) => r + 1);
|
|
159
143
|
alertApi.post({
|
|
160
|
-
message: `API key ${
|
|
144
|
+
message: `API key ${isApprove ? "approved" : "rejected"}`,
|
|
161
145
|
severity: "success",
|
|
162
146
|
display: "transient"
|
|
163
147
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"EntityApiApprovalTab.esm.js","sources":["../../../src/components/EntityApiApprovalTab/EntityApiApprovalTab.tsx"],"sourcesContent":["import React, { useState } from \"react\";\nimport { useEntity } from \"@backstage/plugin-catalog-react\";\nimport {\n useApi,\n configApiRef,\n fetchApiRef,\n identityApiRef,\n alertApiRef,\n} from \"@backstage/core-plugin-api\";\nimport { useAsync } from \"react-use\";\nimport {\n Table,\n TableColumn,\n Progress,\n ResponseErrorPanel,\n} from \"@backstage/core-components\";\nimport { kuadrantApiKeyApprovePermission } from \"../../permissions\";\nimport { useKuadrantPermission } from \"../../utils/permissions\";\nimport {\n Box,\n Typography,\n Chip,\n IconButton,\n Tooltip,\n Button,\n Dialog,\n DialogTitle,\n DialogContent,\n DialogActions,\n TextField,\n CircularProgress,\n makeStyles,\n} from \"@material-ui/core\";\nimport CheckCircleIcon from \"@material-ui/icons/CheckCircle\";\nimport CancelIcon from \"@material-ui/icons/Cancel\";\nimport { APIKey } from \"../../types/api-management\";\nimport { getApprovalQueueStatusChipStyle } from \"../../utils/styles\";\nimport {handleFetchError} from \"../../utils/errors.ts\";\n\nconst useStyles = makeStyles((theme) => ({\n useCasePanel: {\n padding: theme.spacing(2),\n backgroundColor: theme.palette.background.default,\n },\n useCaseLabel: {\n fontWeight: 600,\n marginBottom: theme.spacing(1),\n color: theme.palette.text.secondary,\n textTransform: \"uppercase\",\n fontSize: \"0.75rem\",\n },\n}));\n\ninterface ExpandedRowProps {\n request: APIKey;\n}\n\nconst ExpandedRowContent = ({ request }: ExpandedRowProps) => {\n const classes = useStyles();\n\n return (\n <Box className={classes.useCasePanel} onClick={(e) => e.stopPropagation()}>\n <Typography className={classes.useCaseLabel}>Use Case</Typography>\n <Typography variant=\"body2\">\n {request.spec.useCase || \"No use case provided\"}\n </Typography>\n </Box>\n );\n};\n\ninterface ApprovalDialogProps {\n open: boolean;\n request: APIKey | null;\n action: \"approve\" | \"reject\";\n processing: boolean;\n onClose: () => void;\n onConfirm: (confirmText: string) => void;\n}\n\nconst ApprovalDialog = ({\n open,\n request,\n action,\n processing,\n onClose,\n onConfirm,\n}: ApprovalDialogProps) => {\n const [confirmText, setConfirmText] = useState(\"\");\n\n const handleClose = () => {\n setConfirmText(\"\");\n onClose();\n };\n\n const handleConfirm = () => {\n onConfirm(confirmText);\n setConfirmText(\"\");\n };\n\n const isReject = action === \"reject\";\n const expectedText = request?.metadata.name || \"\";\n const isConfirmValid = confirmText === expectedText;\n\n return (\n <Dialog\n open={open}\n onClose={processing ? undefined : handleClose}\n maxWidth=\"sm\"\n fullWidth\n >\n <DialogTitle>\n {isReject ? \"Reject API key\" : \"Approve API key\"}\n </DialogTitle>\n <DialogContent>\n {request && (\n <>\n <Typography variant=\"body2\" paragraph>\n <strong>Requester:</strong> {request.spec.requestedBy.userId}\n </Typography>\n <Typography variant=\"body2\" paragraph>\n <strong>Tier:</strong> {request.spec.planTier}\n </Typography>\n {request.spec.useCase && (\n <Typography variant=\"body2\" paragraph>\n <strong>Use Case:</strong> {request.spec.useCase}\n </Typography>\n )}\n {isReject && (\n <Box mt={2} p={2} bgcolor=\"error.light\" borderRadius={1}>\n <Typography variant=\"body2\">\n This action will permanently deny access. The user will need\n to submit a new request.\n </Typography>\n </Box>\n )}\n <Box mt={2}>\n <TextField\n fullWidth\n label={`Type \"${expectedText}\" to confirm`}\n value={confirmText}\n onChange={(e) => setConfirmText(e.target.value)}\n disabled={processing}\n autoFocus\n />\n </Box>\n </>\n )}\n </DialogContent>\n <DialogActions>\n <Button onClick={handleClose} disabled={processing}>\n Cancel\n </Button>\n <Button\n onClick={handleConfirm}\n color={isReject ? \"secondary\" : \"primary\"}\n variant=\"contained\"\n disabled={!isConfirmValid || processing}\n startIcon={\n processing ? (\n <CircularProgress size={16} color=\"inherit\" />\n ) : undefined\n }\n >\n {processing\n ? isReject\n ? \"Rejecting...\"\n : \"Approving...\"\n : isReject\n ? \"Reject\"\n : \"Approve\"}\n </Button>\n </DialogActions>\n </Dialog>\n );\n};\n\nexport const EntityApiApprovalTab = () => {\n const { entity } = useEntity();\n const config = useApi(configApiRef);\n const fetchApi = useApi(fetchApiRef);\n const identityApi = useApi(identityApiRef);\n const alertApi = useApi(alertApiRef);\n const backendUrl = config.getString(\"backend.baseUrl\");\n\n const apiProductName =\n entity.metadata.annotations?.[\"kuadrant.io/apiproduct\"] ||\n entity.metadata.name;\n const namespace =\n entity.metadata.annotations?.[\"kuadrant.io/namespace\"] || \"default\";\n\n const [refresh, setRefresh] = useState(0);\n const [dialogState, setDialogState] = useState<{\n open: boolean;\n request: APIKey | null;\n action: \"approve\" | \"reject\";\n processing: boolean;\n }>({\n open: false,\n request: null,\n action: \"approve\",\n processing: false,\n });\n\n const {\n allowed: canApprove,\n loading: permissionLoading,\n error: permissionError,\n } = useKuadrantPermission(kuadrantApiKeyApprovePermission);\n\n const { value, loading, error } = useAsync(async () => {\n const identity = await identityApi.getBackstageIdentity();\n const reviewedBy = identity.userEntityRef;\n\n const response = await fetchApi.fetch(\n `${backendUrl}/api/kuadrant/requests`,\n );\n if (!response.ok) {\n const err = await handleFetchError(response);\n throw new Error(`Failed to fetch requests. ${err}`);\n }\n\n const data = await response.json();\n const allRequests: APIKey[] = data.items || [];\n\n // filter to this API product only\n const filtered = allRequests.filter(\n (r) =>\n r.spec.apiProductRef?.name === apiProductName &&\n r.metadata.namespace === namespace,\n );\n\n return { requests: filtered, reviewedBy };\n }, [backendUrl, fetchApi, identityApi, apiProductName, namespace, refresh]);\n\n const handleApprove = (request: APIKey) => {\n setDialogState({\n open: true,\n request,\n action: \"approve\",\n processing: false,\n });\n };\n\n const handleReject = (request: APIKey) => {\n setDialogState({\n open: true,\n request,\n action: \"reject\",\n processing: false,\n });\n };\n\n const handleConfirm = async () => {\n if (!dialogState.request || !value) return;\n\n setDialogState((prev) => ({ ...prev, processing: true }));\n\n const endpoint =\n dialogState.action === \"approve\"\n ? `${backendUrl}/api/kuadrant/requests/${dialogState.request.metadata.namespace}/${dialogState.request.metadata.name}/approve`\n : `${backendUrl}/api/kuadrant/requests/${dialogState.request.metadata.namespace}/${dialogState.request.metadata.name}/reject`;\n\n try {\n const response = await fetchApi.fetch(endpoint, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ reviewedBy: value.reviewedBy }),\n });\n\n if (!response.ok) {\n const err = await handleFetchError(response);\n throw new Error(err);\n }\n\n setDialogState({\n open: false,\n request: null,\n action: \"approve\",\n processing: false,\n });\n setRefresh((r) => r + 1);\n alertApi.post({\n message: `API key ${dialogState.action === \"approve\" ? \"approved\" : \"rejected\"}`,\n severity: \"success\",\n display: \"transient\",\n });\n } catch (err) {\n console.error(`Error ${dialogState.action}ing request:`, err);\n setDialogState((prev) => ({ ...prev, processing: false }));\n const errorMessage = err instanceof Error ? err.message : \"unknown error occurred\";\n alertApi.post({\n message: `Failed to ${dialogState.action} APIKey. ${errorMessage}`,\n severity: 'error',\n display: 'transient',\n });\n }\n };\n\n if (loading || permissionLoading) {\n return <Progress />;\n }\n\n if (error) {\n return <ResponseErrorPanel error={error} />;\n }\n\n if (permissionError) {\n return (\n <Box p={2}>\n <Typography color=\"error\">\n Unable to check permissions: {permissionError.message}\n </Typography>\n </Box>\n );\n }\n\n if (!canApprove) {\n return (\n <Box p={3} textAlign=\"center\">\n <Typography variant=\"body1\" color=\"textSecondary\">\n You don't have permission to view the approval queue for this API.\n </Typography>\n </Box>\n );\n }\n\n const requests = value?.requests || [];\n const pendingRequests = requests.filter(\n (r) => !r.status?.phase || r.status.phase === \"Pending\",\n );\n const approvedRequests = requests.filter(\n (r) => r.status?.phase === \"Approved\",\n );\n const rejectedRequests = requests.filter(\n (r) => r.status?.phase === \"Rejected\",\n );\n\n const columns: TableColumn<APIKey>[] = [\n {\n title: \"Requester\",\n field: \"spec.requestedBy.userId\",\n render: (row) => (\n <Typography variant=\"body2\">{row.spec.requestedBy.userId}</Typography>\n ),\n },\n {\n title: \"Status\",\n field: \"status.phase\",\n render: (row) => {\n const phase = row.status?.phase || \"Pending\";\n const label = phase === \"Approved\" ? \"Active\" : phase;\n return (\n <Chip label={label} size=\"small\" style={getApprovalQueueStatusChipStyle(phase)} />\n );\n },\n },\n {\n title: \"Tier\",\n field: \"spec.planTier\",\n render: (row) => (\n <Chip label={row.spec.planTier} size=\"small\" variant=\"outlined\" />\n ),\n },\n {\n title: \"Requested\",\n field: \"metadata.creationTimestamp\",\n render: (row) => {\n if (!row.metadata.creationTimestamp)\n return <Typography variant=\"body2\">-</Typography>;\n return (\n <Typography variant=\"body2\">\n {new Date(row.metadata.creationTimestamp).toLocaleDateString()}\n </Typography>\n );\n },\n },\n {\n title: \"Actions\",\n filtering: false,\n render: (row) => {\n const phase = row.status?.phase || \"Pending\";\n if (phase !== \"Pending\") return null;\n return (\n <Box display=\"flex\" style={{ gap: 4 }}>\n <Tooltip title=\"Approve\">\n <IconButton size=\"small\" onClick={() => handleApprove(row)}>\n <CheckCircleIcon color=\"primary\" />\n </IconButton>\n </Tooltip>\n <Tooltip title=\"Reject\">\n <IconButton size=\"small\" onClick={() => handleReject(row)}>\n <CancelIcon color=\"error\" />\n </IconButton>\n </Tooltip>\n </Box>\n );\n },\n },\n ];\n\n const detailPanelConfig = [\n {\n render: (data: any) => {\n const request = data.rowData as APIKey;\n if (!request?.metadata?.name) return <Box />;\n return <ExpandedRowContent request={request} />;\n },\n },\n ];\n\n return (\n <Box p={2}>\n <Box mb={2}>\n <Typography variant=\"body2\" color=\"textSecondary\">\n {pendingRequests.length} pending, {approvedRequests.length} approved,{\" \"}\n {rejectedRequests.length} rejected\n </Typography>\n </Box>\n\n {requests.length === 0 ? (\n <Box p={3} textAlign=\"center\">\n <Typography variant=\"body1\" color=\"textSecondary\">\n No API keys for this API.\n </Typography>\n </Box>\n ) : (\n <Table\n options={{\n paging: requests.length > 10,\n pageSize: 20,\n search: true,\n filtering: false,\n debounceInterval: 300,\n toolbar: true,\n emptyRowsWhenPaging: false,\n }}\n columns={columns}\n data={requests.map((item) => ({ ...item, id: item.metadata.name }))}\n detailPanel={detailPanelConfig}\n />\n )}\n\n <ApprovalDialog\n open={dialogState.open}\n request={dialogState.request}\n action={dialogState.action}\n processing={dialogState.processing}\n onClose={() =>\n setDialogState({\n open: false,\n request: null,\n action: \"approve\",\n processing: false,\n })\n }\n onConfirm={handleConfirm}\n />\n </Box>\n );\n};\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"EntityApiApprovalTab.esm.js","sources":["../../../src/components/EntityApiApprovalTab/EntityApiApprovalTab.tsx"],"sourcesContent":["import React, { useState } from \"react\";\nimport { useEntity } from \"@backstage/plugin-catalog-react\";\nimport {\n useApi,\n identityApiRef,\n alertApiRef,\n} from \"@backstage/core-plugin-api\";\nimport { kuadrantApiRef } from '../../api';\nimport { useAsync } from \"react-use\";\nimport {\n Table,\n TableColumn,\n Progress,\n ResponseErrorPanel,\n} from \"@backstage/core-components\";\nimport { kuadrantApiKeyApprovePermission } from \"../../permissions\";\nimport { useKuadrantPermission } from \"../../utils/permissions\";\nimport {\n Box,\n Typography,\n Chip,\n IconButton,\n Tooltip,\n Button,\n Dialog,\n DialogTitle,\n DialogContent,\n DialogActions,\n TextField,\n CircularProgress,\n makeStyles,\n} from \"@material-ui/core\";\nimport CheckCircleIcon from \"@material-ui/icons/CheckCircle\";\nimport CancelIcon from \"@material-ui/icons/Cancel\";\nimport { APIKey } from \"../../types/api-management\";\nimport { getApprovalQueueStatusChipStyle } from \"../../utils/styles\";\n\nconst useStyles = makeStyles((theme) => ({\n useCasePanel: {\n padding: theme.spacing(2),\n backgroundColor: theme.palette.background.default,\n },\n useCaseLabel: {\n fontWeight: 600,\n marginBottom: theme.spacing(1),\n color: theme.palette.text.secondary,\n textTransform: \"uppercase\",\n fontSize: \"0.75rem\",\n },\n}));\n\ninterface ExpandedRowProps {\n request: APIKey;\n}\n\nconst ExpandedRowContent = ({ request }: ExpandedRowProps) => {\n const classes = useStyles();\n\n return (\n <Box className={classes.useCasePanel} onClick={(e) => e.stopPropagation()}>\n <Typography className={classes.useCaseLabel}>Use Case</Typography>\n <Typography variant=\"body2\">\n {request.spec.useCase || \"No use case provided\"}\n </Typography>\n </Box>\n );\n};\n\ninterface ApprovalDialogProps {\n open: boolean;\n request: APIKey | null;\n action: \"approve\" | \"reject\";\n processing: boolean;\n onClose: () => void;\n onConfirm: (confirmText: string) => void;\n}\n\nconst ApprovalDialog = ({\n open,\n request,\n action,\n processing,\n onClose,\n onConfirm,\n}: ApprovalDialogProps) => {\n const [confirmText, setConfirmText] = useState(\"\");\n\n const handleClose = () => {\n setConfirmText(\"\");\n onClose();\n };\n\n const handleConfirm = () => {\n onConfirm(confirmText);\n setConfirmText(\"\");\n };\n\n const isReject = action === \"reject\";\n const expectedText = request?.metadata.name || \"\";\n const isConfirmValid = confirmText === expectedText;\n\n return (\n <Dialog\n open={open}\n onClose={processing ? undefined : handleClose}\n maxWidth=\"sm\"\n fullWidth\n >\n <DialogTitle>\n {isReject ? \"Reject API key\" : \"Approve API key\"}\n </DialogTitle>\n <DialogContent>\n {request && (\n <>\n <Typography variant=\"body2\" paragraph>\n <strong>Requester:</strong> {request.spec.requestedBy.userId}\n </Typography>\n <Typography variant=\"body2\" paragraph>\n <strong>Tier:</strong> {request.spec.planTier}\n </Typography>\n {request.spec.useCase && (\n <Typography variant=\"body2\" paragraph>\n <strong>Use Case:</strong> {request.spec.useCase}\n </Typography>\n )}\n {isReject && (\n <Box mt={2} p={2} bgcolor=\"error.light\" borderRadius={1}>\n <Typography variant=\"body2\">\n This action will permanently deny access. The user will need\n to submit a new request.\n </Typography>\n </Box>\n )}\n <Box mt={2}>\n <TextField\n fullWidth\n label={`Type \"${expectedText}\" to confirm`}\n value={confirmText}\n onChange={(e) => setConfirmText(e.target.value)}\n disabled={processing}\n autoFocus\n />\n </Box>\n </>\n )}\n </DialogContent>\n <DialogActions>\n <Button onClick={handleClose} disabled={processing}>\n Cancel\n </Button>\n <Button\n onClick={handleConfirm}\n color={isReject ? \"secondary\" : \"primary\"}\n variant=\"contained\"\n disabled={!isConfirmValid || processing}\n startIcon={\n processing ? (\n <CircularProgress size={16} color=\"inherit\" />\n ) : undefined\n }\n >\n {processing\n ? isReject\n ? \"Rejecting...\"\n : \"Approving...\"\n : isReject\n ? \"Reject\"\n : \"Approve\"}\n </Button>\n </DialogActions>\n </Dialog>\n );\n};\n\nexport const EntityApiApprovalTab = () => {\n const { entity } = useEntity();\n const kuadrantApi = useApi(kuadrantApiRef);\n const identityApi = useApi(identityApiRef);\n const alertApi = useApi(alertApiRef);\n\n const apiProductName =\n entity.metadata.annotations?.[\"kuadrant.io/apiproduct\"] ||\n entity.metadata.name;\n const namespace =\n entity.metadata.annotations?.[\"kuadrant.io/namespace\"] || \"default\";\n\n const [refresh, setRefresh] = useState(0);\n const [dialogState, setDialogState] = useState<{\n open: boolean;\n request: APIKey | null;\n action: \"approve\" | \"reject\";\n processing: boolean;\n }>({\n open: false,\n request: null,\n action: \"approve\",\n processing: false,\n });\n\n const {\n allowed: canApprove,\n loading: permissionLoading,\n error: permissionError,\n } = useKuadrantPermission(kuadrantApiKeyApprovePermission);\n\n const { value, loading, error } = useAsync(async () => {\n const identity = await identityApi.getBackstageIdentity();\n const reviewedBy = identity.userEntityRef;\n\n const data = await kuadrantApi.getRequests();\n const allRequests: APIKey[] = data.items || [];\n\n // filter to this API product only\n const filtered = allRequests.filter(\n (r) =>\n r.spec.apiProductRef?.name === apiProductName &&\n r.metadata.namespace === namespace,\n );\n\n return { requests: filtered, reviewedBy };\n }, [kuadrantApi, identityApi, apiProductName, namespace, refresh]);\n\n const handleApprove = (request: APIKey) => {\n setDialogState({\n open: true,\n request,\n action: \"approve\",\n processing: false,\n });\n };\n\n const handleReject = (request: APIKey) => {\n setDialogState({\n open: true,\n request,\n action: \"reject\",\n processing: false,\n });\n };\n\n const handleConfirm = async () => {\n if (!dialogState.request || !value) return;\n\n setDialogState((prev) => ({ ...prev, processing: true }));\n\n const isApprove = dialogState.action === \"approve\"\n const requestFn = isApprove\n ? (ns: string, n: string, r: string) => kuadrantApi.approveRequest(ns, n, r)\n : (ns: string, n: string, r: string) => kuadrantApi.rejectRequest(ns, n, r)\n\n try {\n await requestFn(dialogState.request.metadata.namespace, dialogState.request.metadata.name, value.reviewedBy);\n\n setDialogState({\n open: false,\n request: null,\n action: \"approve\",\n processing: false,\n });\n setRefresh((r) => r + 1);\n alertApi.post({\n message: `API key ${isApprove ? \"approved\" : \"rejected\"}`,\n severity: \"success\",\n display: \"transient\",\n });\n } catch (err) {\n console.error(`Error ${dialogState.action}ing request:`, err);\n setDialogState((prev) => ({ ...prev, processing: false }));\n const errorMessage = err instanceof Error ? err.message : \"unknown error occurred\";\n alertApi.post({\n message: `Failed to ${dialogState.action} APIKey. ${errorMessage}`,\n severity: 'error',\n display: 'transient',\n });\n }\n };\n\n if (loading || permissionLoading) {\n return <Progress />;\n }\n\n if (error) {\n return <ResponseErrorPanel error={error} />;\n }\n\n if (permissionError) {\n return (\n <Box p={2}>\n <Typography color=\"error\">\n Unable to check permissions: {permissionError.message}\n </Typography>\n </Box>\n );\n }\n\n if (!canApprove) {\n return (\n <Box p={3} textAlign=\"center\">\n <Typography variant=\"body1\" color=\"textSecondary\">\n You don't have permission to view the approval queue for this API.\n </Typography>\n </Box>\n );\n }\n\n const requests = value?.requests || [];\n const pendingRequests = requests.filter(\n (r) => !r.status?.phase || r.status.phase === \"Pending\",\n );\n const approvedRequests = requests.filter(\n (r) => r.status?.phase === \"Approved\",\n );\n const rejectedRequests = requests.filter(\n (r) => r.status?.phase === \"Rejected\",\n );\n\n const columns: TableColumn<APIKey>[] = [\n {\n title: \"Requester\",\n field: \"spec.requestedBy.userId\",\n render: (row) => (\n <Typography variant=\"body2\">{row.spec.requestedBy.userId}</Typography>\n ),\n },\n {\n title: \"Status\",\n field: \"status.phase\",\n render: (row) => {\n const phase = row.status?.phase || \"Pending\";\n const label = phase === \"Approved\" ? \"Active\" : phase;\n return (\n <Chip label={label} size=\"small\" style={getApprovalQueueStatusChipStyle(phase)} />\n );\n },\n },\n {\n title: \"Tier\",\n field: \"spec.planTier\",\n render: (row) => (\n <Chip label={row.spec.planTier} size=\"small\" variant=\"outlined\" />\n ),\n },\n {\n title: \"Requested\",\n field: \"metadata.creationTimestamp\",\n render: (row) => {\n if (!row.metadata.creationTimestamp)\n return <Typography variant=\"body2\">-</Typography>;\n return (\n <Typography variant=\"body2\">\n {new Date(row.metadata.creationTimestamp).toLocaleDateString()}\n </Typography>\n );\n },\n },\n {\n title: \"Actions\",\n filtering: false,\n render: (row) => {\n const phase = row.status?.phase || \"Pending\";\n if (phase !== \"Pending\") return null;\n return (\n <Box display=\"flex\" style={{ gap: 4 }}>\n <Tooltip title=\"Approve\">\n <IconButton size=\"small\" onClick={() => handleApprove(row)}>\n <CheckCircleIcon color=\"primary\" />\n </IconButton>\n </Tooltip>\n <Tooltip title=\"Reject\">\n <IconButton size=\"small\" onClick={() => handleReject(row)}>\n <CancelIcon color=\"error\" />\n </IconButton>\n </Tooltip>\n </Box>\n );\n },\n },\n ];\n\n const detailPanelConfig = [\n {\n render: (data: any) => {\n const request = data.rowData as APIKey;\n if (!request?.metadata?.name) return <Box />;\n return <ExpandedRowContent request={request} />;\n },\n },\n ];\n\n return (\n <Box p={2}>\n <Box mb={2}>\n <Typography variant=\"body2\" color=\"textSecondary\">\n {pendingRequests.length} pending, {approvedRequests.length} approved,{\" \"}\n {rejectedRequests.length} rejected\n </Typography>\n </Box>\n\n {requests.length === 0 ? (\n <Box p={3} textAlign=\"center\">\n <Typography variant=\"body1\" color=\"textSecondary\">\n No API keys for this API.\n </Typography>\n </Box>\n ) : (\n <Table\n options={{\n paging: requests.length > 10,\n pageSize: 20,\n search: true,\n filtering: false,\n debounceInterval: 300,\n toolbar: true,\n emptyRowsWhenPaging: false,\n }}\n columns={columns}\n data={requests.map((item) => ({ ...item, id: item.metadata.name }))}\n detailPanel={detailPanelConfig}\n />\n )}\n\n <ApprovalDialog\n open={dialogState.open}\n request={dialogState.request}\n action={dialogState.action}\n processing={dialogState.processing}\n onClose={() =>\n setDialogState({\n open: false,\n request: null,\n action: \"approve\",\n processing: false,\n })\n }\n onConfirm={handleConfirm}\n />\n </Box>\n );\n};\n"],"names":[],"mappings":"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"}
|