@kuadrant/kuadrant-backstage-plugin-frontend 0.0.2-dev-3d7caf4 → 0.0.2-dev-24d0757

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (81) hide show
  1. package/dist/assets/empty-state-illustration.png +0 -0
  2. package/dist/components/ApiKeyManagementTab/ApiKeyManagementTab.esm.js +6 -1
  3. package/dist/components/ApiKeyManagementTab/ApiKeyManagementTab.esm.js.map +1 -1
  4. package/dist/components/ApiProductDetailPage/ApiProductDetailPage.esm.js +248 -0
  5. package/dist/components/ApiProductDetailPage/ApiProductDetailPage.esm.js.map +1 -0
  6. package/dist/components/ApiProductDetailPage/index.esm.js +2 -0
  7. package/dist/components/ApiProductDetailPage/index.esm.js.map +1 -0
  8. package/dist/components/ApiProductDetails/ApiProductDetails.esm.js +86 -0
  9. package/dist/components/ApiProductDetails/ApiProductDetails.esm.js.map +1 -0
  10. package/dist/components/ApiProductInfoCard/ApiProductInfoCard.esm.js +24 -43
  11. package/dist/components/ApiProductInfoCard/ApiProductInfoCard.esm.js.map +1 -1
  12. package/dist/components/ApprovalQueueTable/ApprovalQueueTable.esm.js +2 -1
  13. package/dist/components/ApprovalQueueTable/ApprovalQueueTable.esm.js.map +1 -1
  14. package/dist/components/CreateAPIProductDialog/CreateAPIProductDialog.esm.js +148 -134
  15. package/dist/components/CreateAPIProductDialog/CreateAPIProductDialog.esm.js.map +1 -1
  16. package/dist/components/EditAPIProductDialog/EditAPIProductDialog.esm.js +104 -128
  17. package/dist/components/EditAPIProductDialog/EditAPIProductDialog.esm.js.map +1 -1
  18. package/dist/components/KuadrantPage/KuadrantPage.esm.js +328 -125
  19. package/dist/components/KuadrantPage/KuadrantPage.esm.js.map +1 -1
  20. package/dist/components/MyApiKeysTable/MyApiKeysTable.esm.js +8 -2
  21. package/dist/components/MyApiKeysTable/MyApiKeysTable.esm.js.map +1 -1
  22. package/dist/index.d.ts +2 -1
  23. package/dist/index.esm.js +1 -1
  24. package/dist/plugin.esm.js +8 -1
  25. package/dist/plugin.esm.js.map +1 -1
  26. package/dist/utils/validation.esm.js +1 -11
  27. package/dist/utils/validation.esm.js.map +1 -1
  28. package/dist-scalprum/{internal.plugin-kuadrant.793ab10dddb55e70abe2.js → internal.plugin-kuadrant.95817f34e88db81b5e8f.js} +2 -2
  29. package/dist-scalprum/internal.plugin-kuadrant.95817f34e88db81b5e8f.js.map +1 -0
  30. package/dist-scalprum/plugin-manifest.json +2 -2
  31. package/dist-scalprum/static/2759.fceb317f.chunk.js +2 -0
  32. package/dist-scalprum/static/2759.fceb317f.chunk.js.map +1 -0
  33. package/dist-scalprum/static/2928.4303c12e.chunk.js +3 -0
  34. package/dist-scalprum/static/2928.4303c12e.chunk.js.map +1 -0
  35. package/dist-scalprum/static/2967.ac3a4bee.chunk.js +2 -0
  36. package/dist-scalprum/static/2967.ac3a4bee.chunk.js.map +1 -0
  37. package/dist-scalprum/static/{6979.9699b350.chunk.js → 2987.1da15560.chunk.js} +2 -2
  38. package/dist-scalprum/static/2987.1da15560.chunk.js.map +1 -0
  39. package/dist-scalprum/static/3459.5c90b5a3.chunk.js +2 -0
  40. package/dist-scalprum/static/3459.5c90b5a3.chunk.js.map +1 -0
  41. package/dist-scalprum/static/3503.66b6e510.chunk.js +2 -0
  42. package/dist-scalprum/static/3503.66b6e510.chunk.js.map +1 -0
  43. package/dist-scalprum/static/{3650.aa8552f3.chunk.js → 3650.515c743a.chunk.js} +2 -2
  44. package/dist-scalprum/static/3650.515c743a.chunk.js.map +1 -0
  45. package/dist-scalprum/static/4682.6959fcd1.chunk.js +2 -0
  46. package/dist-scalprum/static/4682.6959fcd1.chunk.js.map +1 -0
  47. package/dist-scalprum/static/5010.a4aa0f8e.chunk.js +3 -0
  48. package/dist-scalprum/static/5010.a4aa0f8e.chunk.js.map +1 -0
  49. package/dist-scalprum/static/5453.280127dd.chunk.js +2 -0
  50. package/dist-scalprum/static/5453.280127dd.chunk.js.map +1 -0
  51. package/dist-scalprum/static/6422.97baf774.chunk.js +2 -0
  52. package/dist-scalprum/static/6422.97baf774.chunk.js.map +1 -0
  53. package/dist-scalprum/static/7791.12162a71.chunk.js +2 -0
  54. package/dist-scalprum/static/7791.12162a71.chunk.js.map +1 -0
  55. package/dist-scalprum/static/8799.7c749838.chunk.js +2 -0
  56. package/dist-scalprum/static/8799.7c749838.chunk.js.map +1 -0
  57. package/dist-scalprum/static/empty-state-illustration.7e3ad5a9..png +0 -0
  58. package/dist-scalprum/static/exposed-PluginRoot.a5792fb2.chunk.js +2 -0
  59. package/dist-scalprum/static/exposed-PluginRoot.a5792fb2.chunk.js.map +1 -0
  60. package/package.json +1 -1
  61. package/dist-scalprum/internal.plugin-kuadrant.793ab10dddb55e70abe2.js.map +0 -1
  62. package/dist-scalprum/static/2120.44884438.chunk.js +0 -3
  63. package/dist-scalprum/static/2120.44884438.chunk.js.map +0 -1
  64. package/dist-scalprum/static/2967.c684efaf.chunk.js +0 -2
  65. package/dist-scalprum/static/2967.c684efaf.chunk.js.map +0 -1
  66. package/dist-scalprum/static/3650.aa8552f3.chunk.js.map +0 -1
  67. package/dist-scalprum/static/5010.acf9a415.chunk.js +0 -3
  68. package/dist-scalprum/static/5010.acf9a415.chunk.js.map +0 -1
  69. package/dist-scalprum/static/5453.c1f90bdf.chunk.js +0 -2
  70. package/dist-scalprum/static/5453.c1f90bdf.chunk.js.map +0 -1
  71. package/dist-scalprum/static/6813.036a322f.chunk.js +0 -2
  72. package/dist-scalprum/static/6813.036a322f.chunk.js.map +0 -1
  73. package/dist-scalprum/static/6979.9699b350.chunk.js.map +0 -1
  74. package/dist-scalprum/static/7684.3d1fc1a1.chunk.js +0 -2
  75. package/dist-scalprum/static/7684.3d1fc1a1.chunk.js.map +0 -1
  76. package/dist-scalprum/static/8416.3604a311.chunk.js +0 -2
  77. package/dist-scalprum/static/8416.3604a311.chunk.js.map +0 -1
  78. package/dist-scalprum/static/exposed-PluginRoot.16bf7897.chunk.js +0 -2
  79. package/dist-scalprum/static/exposed-PluginRoot.16bf7897.chunk.js.map +0 -1
  80. /package/dist-scalprum/static/{2120.44884438.chunk.js.LICENSE.txt → 2928.4303c12e.chunk.js.LICENSE.txt} +0 -0
  81. /package/dist-scalprum/static/{5010.acf9a415.chunk.js.LICENSE.txt → 5010.a4aa0f8e.chunk.js.LICENSE.txt} +0 -0
@@ -1,16 +1,33 @@
1
1
  import React, { useState, useEffect } from 'react';
2
- import { makeStyles, Dialog, DialogTitle, DialogContent, Box, Button, Typography, Grid, TextField, MenuItem, Chip, DialogActions, CircularProgress } from '@material-ui/core';
2
+ import { makeStyles, Dialog, DialogTitle, DialogContent, Box, Button, Typography, Grid, TextField, InputAdornment, IconButton, Chip, Tooltip, MenuItem, FormControl, RadioGroup, FormControlLabel, Radio, DialogActions, CircularProgress } from '@material-ui/core';
3
+ import InfoOutlinedIcon from '@material-ui/icons/InfoOutlined';
4
+ import AddIcon from '@material-ui/icons/Add';
3
5
  import { useApi, configApiRef, fetchApiRef } from '@backstage/core-plugin-api';
4
6
  import { Alert } from '@material-ui/lab';
5
7
  import useAsync from 'react-use/lib/useAsync';
6
8
  import { PlanPolicyDetails } from '../PlanPolicyDetailsCard/PlanPolicyDetails.esm.js';
7
- import { validateKubernetesName, validateEmail, validateURL } from '../../utils/validation.esm.js';
9
+ import { validateKubernetesName, validateURL } from '../../utils/validation.esm.js';
8
10
 
9
- const useStyles = makeStyles({
11
+ const useStyles = makeStyles((theme) => ({
10
12
  asterisk: {
11
13
  color: "#f44336"
14
+ },
15
+ sectionHeader: {
16
+ display: "flex",
17
+ alignItems: "center",
18
+ gap: theme.spacing(0.5),
19
+ marginTop: theme.spacing(2),
20
+ marginBottom: theme.spacing(1)
21
+ },
22
+ infoIcon: {
23
+ fontSize: 18,
24
+ color: theme.palette.text.secondary
25
+ },
26
+ tagChip: {
27
+ marginRight: theme.spacing(0.5),
28
+ marginBottom: theme.spacing(0.5)
12
29
  }
13
- });
30
+ }));
14
31
  const CreateAPIProductDialog = ({ open, onClose, onSuccess }) => {
15
32
  const classes = useStyles();
16
33
  const config = useApi(configApiRef);
@@ -33,8 +50,6 @@ const CreateAPIProductDialog = ({ open, onClose, onSuccess }) => {
33
50
  const [creating, setCreating] = useState(false);
34
51
  const [httpRoutesRetry, setHttpRoutesRetry] = useState(0);
35
52
  const [nameError, setNameError] = useState(null);
36
- const [contactEmailError, setContactEmailError] = useState(null);
37
- const [docsURLError, setDocsURLError] = useState(null);
38
53
  const [openAPISpecError, setOpenAPISpecError] = useState(null);
39
54
  const {
40
55
  value: httpRoutes,
@@ -63,11 +78,23 @@ const CreateAPIProductDialog = ({ open, onClose, onSuccess }) => {
63
78
  };
64
79
  const selectedRouteInfo = selectedHTTPRoute ? selectedHTTPRoute.split("/") : null;
65
80
  const selectedPolicy = selectedRouteInfo ? getPlanPolicyForRoute(selectedRouteInfo[0], selectedRouteInfo[1]) : null;
81
+ const formatTierInfo = (policy) => {
82
+ if (!policy?.spec?.plans) return "";
83
+ const tiers = Object.entries(policy.spec.plans).map(([name2, plan]) => {
84
+ const limit = plan?.limits?.requests;
85
+ if (!limit) return name2;
86
+ return `${name2}: ${limit.count}/${limit.period}`;
87
+ }).join("; ");
88
+ return tiers ? ` (${tiers})` : "";
89
+ };
90
+ const getPolicyInfoForRoute = (routeNamespace, routeName) => {
91
+ const policy = getPlanPolicyForRoute(routeNamespace, routeName);
92
+ if (!policy) return "N/A";
93
+ return `${policy.metadata.name}${formatTierInfo(policy)}`;
94
+ };
66
95
  useEffect(() => {
67
96
  if (open) {
68
97
  setNameError(null);
69
- setContactEmailError(null);
70
- setDocsURLError(null);
71
98
  setOpenAPISpecError(null);
72
99
  }
73
100
  }, [open]);
@@ -75,14 +102,6 @@ const CreateAPIProductDialog = ({ open, onClose, onSuccess }) => {
75
102
  setName(value);
76
103
  setNameError(validateKubernetesName(value));
77
104
  };
78
- const handleContactEmailChange = (value) => {
79
- setContactEmail(value);
80
- setContactEmailError(validateEmail(value));
81
- };
82
- const handleDocsURLChange = (value) => {
83
- setDocsURL(value);
84
- setDocsURLError(validateURL(value));
85
- };
86
105
  const handleOpenAPISpecChange = (value) => {
87
106
  setOpenAPISpec(value);
88
107
  setOpenAPISpecError(validateURL(value));
@@ -134,7 +153,7 @@ const CreateAPIProductDialog = ({ open, onClose, onSuccess }) => {
134
153
  ...docsURL || openAPISpec ? {
135
154
  documentation: {
136
155
  ...docsURL && { docsURL },
137
- ...openAPISpec && { openAPISpec }
156
+ ...openAPISpec && { openAPISpecURL: openAPISpec }
138
157
  }
139
158
  } : {}
140
159
  }
@@ -150,7 +169,7 @@ const CreateAPIProductDialog = ({ open, onClose, onSuccess }) => {
150
169
  const errorData = await response.json();
151
170
  throw new Error(errorData.error || "failed to create apiproduct");
152
171
  }
153
- onSuccess();
172
+ onSuccess({ namespace, name, displayName });
154
173
  handleClose();
155
174
  } catch (err) {
156
175
  setError(err instanceof Error ? err.message : String(err));
@@ -174,12 +193,10 @@ const CreateAPIProductDialog = ({ open, onClose, onSuccess }) => {
174
193
  setOpenAPISpec("");
175
194
  setError("");
176
195
  setNameError(null);
177
- setContactEmailError(null);
178
- setDocsURLError(null);
179
196
  setOpenAPISpecError(null);
180
197
  onClose();
181
198
  };
182
- const hasValidationErrors = !!nameError || !!contactEmailError || !!docsURLError || !!openAPISpecError;
199
+ const hasValidationErrors = !!nameError || !!openAPISpecError;
183
200
  return /* @__PURE__ */ React.createElement(Dialog, { open, onClose: handleClose, maxWidth: "md", fullWidth: true }, /* @__PURE__ */ React.createElement(DialogTitle, null, "Create API Product"), /* @__PURE__ */ React.createElement(DialogContent, null, error && /* @__PURE__ */ React.createElement(Alert, { severity: "error", style: { marginBottom: 16 } }, error), httpRoutesError && /* @__PURE__ */ React.createElement(Alert, { severity: "error", style: { marginBottom: 16 } }, /* @__PURE__ */ React.createElement("strong", null, "Failed to load HTTPRoutes:"), " ", httpRoutesError.message, /* @__PURE__ */ React.createElement(Box, { mt: 1 }, /* @__PURE__ */ React.createElement(
184
201
  Button,
185
202
  {
@@ -188,16 +205,15 @@ const CreateAPIProductDialog = ({ open, onClose, onSuccess }) => {
188
205
  onClick: () => setHttpRoutesRetry((prev) => prev + 1)
189
206
  },
190
207
  "Retry"
191
- ))), planPoliciesError && /* @__PURE__ */ React.createElement(Alert, { severity: "warning", style: { marginBottom: 16 } }, /* @__PURE__ */ React.createElement("strong", null, "Failed to load PlanPolicies:"), " ", planPoliciesError.message, /* @__PURE__ */ React.createElement(Typography, { variant: "body2", style: { marginTop: 8 } }, "You can still create the API Product, but plan information may be incomplete.")), /* @__PURE__ */ React.createElement(Grid, { container: true, spacing: 2 }, /* @__PURE__ */ React.createElement(Grid, { item: true, xs: 6 }, /* @__PURE__ */ React.createElement(
208
+ ))), planPoliciesError && /* @__PURE__ */ React.createElement(Alert, { severity: "warning", style: { marginBottom: 16 } }, /* @__PURE__ */ React.createElement("strong", null, "Failed to load PlanPolicies:"), " ", planPoliciesError.message, /* @__PURE__ */ React.createElement(Typography, { variant: "body2", style: { marginTop: 8 } }, "You can still create the API Product, but plan information may be incomplete.")), /* @__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(
192
209
  TextField,
193
210
  {
194
211
  fullWidth: true,
195
- label: "Name",
196
- value: name,
197
- onChange: (e) => handleNameChange(e.target.value),
198
- placeholder: "my-api",
199
- helperText: nameError || "Kubernetes resource name (lowercase, hyphens)",
200
- error: !!nameError,
212
+ label: "API product name",
213
+ value: displayName,
214
+ onChange: (e) => setDisplayName(e.target.value),
215
+ placeholder: "My API",
216
+ helperText: "Give a unique name for your API product",
201
217
  margin: "normal",
202
218
  required: true,
203
219
  disabled: creating,
@@ -211,10 +227,12 @@ const CreateAPIProductDialog = ({ open, onClose, onSuccess }) => {
211
227
  TextField,
212
228
  {
213
229
  fullWidth: true,
214
- label: "Display Name",
215
- value: displayName,
216
- onChange: (e) => setDisplayName(e.target.value),
217
- placeholder: "My API",
230
+ label: "Resource name",
231
+ value: name,
232
+ onChange: (e) => handleNameChange(e.target.value),
233
+ placeholder: "my-api",
234
+ helperText: nameError || "Kubernetes resource name with lowercase, hyphens. Eg.flight_API",
235
+ error: !!nameError,
218
236
  margin: "normal",
219
237
  required: true,
220
238
  disabled: creating,
@@ -232,38 +250,48 @@ const CreateAPIProductDialog = ({ open, onClose, onSuccess }) => {
232
250
  value: version,
233
251
  onChange: (e) => setVersion(e.target.value),
234
252
  placeholder: "v1",
253
+ helperText: "Give a version to your API product",
235
254
  margin: "normal",
236
- disabled: creating
255
+ required: true,
256
+ disabled: creating,
257
+ InputLabelProps: {
258
+ classes: {
259
+ asterisk: classes.asterisk
260
+ }
261
+ }
237
262
  }
238
- )), /* @__PURE__ */ React.createElement(Grid, { item: true, xs: 12 }, /* @__PURE__ */ React.createElement(
263
+ )), /* @__PURE__ */ React.createElement(Grid, { item: true, xs: 6 }, /* @__PURE__ */ React.createElement(
239
264
  TextField,
240
265
  {
241
266
  fullWidth: true,
242
- select: true,
243
- label: "Approval Mode",
244
- value: approvalMode,
245
- onChange: (e) => setApprovalMode(e.target.value),
267
+ label: "Tag",
268
+ value: tagInput,
269
+ onChange: (e) => setTagInput(e.target.value),
270
+ onKeyPress: (e) => {
271
+ if (e.key === "Enter") {
272
+ e.preventDefault();
273
+ handleAddTag();
274
+ }
275
+ },
276
+ placeholder: "Add tag",
277
+ helperText: "Add a tag to your API product",
246
278
  margin: "normal",
247
- helperText: "Automatic: keys are created immediately. Manual: requires approval.",
248
- disabled: creating
249
- },
250
- /* @__PURE__ */ React.createElement(MenuItem, { value: "manual" }, "Manual"),
251
- /* @__PURE__ */ React.createElement(MenuItem, { value: "automatic" }, "Automatic")
252
- )), /* @__PURE__ */ React.createElement(Grid, { item: true, xs: 12 }, /* @__PURE__ */ React.createElement(
253
- TextField,
279
+ disabled: creating,
280
+ InputProps: {
281
+ endAdornment: tagInput ? /* @__PURE__ */ React.createElement(InputAdornment, { position: "end" }, /* @__PURE__ */ React.createElement(IconButton, { size: "small", onClick: handleAddTag, disabled: creating }, /* @__PURE__ */ React.createElement(AddIcon, { fontSize: "small" }))) : undefined
282
+ }
283
+ }
284
+ )), tags.length > 0 && /* @__PURE__ */ React.createElement(Grid, { item: true, xs: 12 }, /* @__PURE__ */ React.createElement(Box, { display: "flex", flexWrap: "wrap" }, tags.map((tag) => /* @__PURE__ */ React.createElement(
285
+ Chip,
254
286
  {
255
- fullWidth: true,
256
- select: true,
257
- label: "Publish Status",
258
- value: publishStatus,
259
- onChange: (e) => setPublishStatus(e.target.value),
260
- margin: "normal",
261
- helperText: "Draft: hidden from catalog. Published: visible to consumers.",
287
+ key: tag,
288
+ label: tag,
289
+ onDelete: creating ? undefined : () => handleDeleteTag(tag),
290
+ size: "small",
291
+ className: classes.tagChip,
262
292
  disabled: creating
263
- },
264
- /* @__PURE__ */ React.createElement(MenuItem, { value: "Draft" }, "Draft"),
265
- /* @__PURE__ */ React.createElement(MenuItem, { value: "Published" }, "Published")
266
- )), /* @__PURE__ */ React.createElement(Grid, { item: true, xs: 12 }, /* @__PURE__ */ React.createElement(
293
+ }
294
+ )))), /* @__PURE__ */ React.createElement(Grid, { item: true, xs: 12 }, /* @__PURE__ */ React.createElement(
267
295
  TextField,
268
296
  {
269
297
  fullWidth: true,
@@ -282,27 +310,38 @@ const CreateAPIProductDialog = ({ open, onClose, onSuccess }) => {
282
310
  }
283
311
  }
284
312
  }
285
- )), /* @__PURE__ */ React.createElement(Grid, { item: true, xs: 12 }, /* @__PURE__ */ React.createElement(Typography, { variant: "subtitle2", gutterBottom: true, style: { marginTop: 16 } }, "Tags"), /* @__PURE__ */ React.createElement(Box, { display: "flex", flexWrap: "wrap", marginBottom: 1, style: { gap: 8 } }, tags.map((tag) => /* @__PURE__ */ React.createElement(
286
- Chip,
313
+ ))), /* @__PURE__ */ React.createElement(Box, { className: classes.sectionHeader }, /* @__PURE__ */ React.createElement(Typography, { variant: "subtitle1" }, /* @__PURE__ */ React.createElement("strong", null, "Add API and Associate route")), /* @__PURE__ */ React.createElement(Tooltip, { title: "Register an existing API and associate HTTPRoute for your API product" }, /* @__PURE__ */ React.createElement(InfoOutlinedIcon, { className: classes.infoIcon }))), /* @__PURE__ */ React.createElement(Grid, { container: true, spacing: 2 }, /* @__PURE__ */ React.createElement(Grid, { item: true, xs: 12 }, /* @__PURE__ */ React.createElement(
314
+ TextField,
287
315
  {
288
- key: tag,
289
- label: tag,
290
- onDelete: creating ? undefined : () => handleDeleteTag(tag),
291
- size: "small",
292
- disabled: creating
316
+ fullWidth: true,
317
+ label: "OpenAPI Spec URL",
318
+ value: openAPISpec,
319
+ onChange: (e) => handleOpenAPISpecChange(e.target.value),
320
+ placeholder: "https://api.example.com/openapi.json",
321
+ helperText: openAPISpecError || "Enter the full path to your API spec file",
322
+ error: !!openAPISpecError,
323
+ margin: "normal",
324
+ required: true,
325
+ disabled: creating,
326
+ InputLabelProps: {
327
+ classes: {
328
+ asterisk: classes.asterisk
329
+ }
330
+ }
293
331
  }
294
- ))), /* @__PURE__ */ React.createElement(Box, { display: "flex", style: { gap: 8 } }, /* @__PURE__ */ React.createElement(
332
+ )), /* @__PURE__ */ React.createElement(Grid, { item: true, xs: 12 }, /* @__PURE__ */ React.createElement(
295
333
  TextField,
296
334
  {
297
335
  fullWidth: true,
298
- size: "small",
299
- value: tagInput,
300
- onChange: (e) => setTagInput(e.target.value),
301
- onKeyPress: (e) => e.key === "Enter" && handleAddTag(),
302
- placeholder: "Add tag",
336
+ label: "Documentation URL",
337
+ value: docsURL,
338
+ onChange: (e) => setDocsURL(e.target.value),
339
+ placeholder: "https://docs.example.com/api",
340
+ helperText: "Link to external documentation for this API",
341
+ margin: "normal",
303
342
  disabled: creating
304
343
  }
305
- ), /* @__PURE__ */ React.createElement(Button, { onClick: handleAddTag, variant: "outlined", size: "small", disabled: creating }, "Add"))), /* @__PURE__ */ React.createElement(Grid, { item: true, xs: 12 }, /* @__PURE__ */ React.createElement(
344
+ )), /* @__PURE__ */ React.createElement(Grid, { item: true, xs: 12 }, /* @__PURE__ */ React.createElement(
306
345
  TextField,
307
346
  {
308
347
  fullWidth: true,
@@ -312,7 +351,7 @@ const CreateAPIProductDialog = ({ open, onClose, onSuccess }) => {
312
351
  onChange: (e) => setSelectedHTTPRoute(e.target.value),
313
352
  margin: "normal",
314
353
  required: true,
315
- helperText: httpRoutesError ? "Unable to load HTTPRoutes. Please retry." : "Select an HTTPRoute (backstage.io/expose: true). APIProduct will be created in the same namespace.",
354
+ helperText: httpRoutesError ? "Unable to load HTTPRoutes. Please retry." : "Select an HTTPRoute. Eg.backstage.io/expose:true. API product will be created in the same namespace.",
316
355
  error: !!httpRoutesError,
317
356
  disabled: httpRoutesLoading || creating || !!httpRoutesError,
318
357
  InputLabelProps: {
@@ -327,76 +366,51 @@ const CreateAPIProductDialog = ({ open, onClose, onSuccess }) => {
327
366
  httpRoutesLoading && /* @__PURE__ */ React.createElement(MenuItem, { value: "" }, "Loading..."),
328
367
  httpRoutesError && /* @__PURE__ */ React.createElement(MenuItem, { value: "" }, "Error loading routes"),
329
368
  !httpRoutesLoading && !httpRoutesError && httpRoutes && httpRoutes.length === 0 && /* @__PURE__ */ React.createElement(MenuItem, { value: "" }, "No HTTPRoutes available"),
330
- !httpRoutesLoading && !httpRoutesError && httpRoutes && httpRoutes.map((route) => /* @__PURE__ */ React.createElement(
331
- MenuItem,
332
- {
333
- key: `${route.metadata.namespace}/${route.metadata.name}`,
334
- value: `${route.metadata.namespace}/${route.metadata.name}`
335
- },
336
- route.metadata.name,
337
- " (",
338
- route.metadata.namespace,
339
- ")"
340
- ))
341
- )), selectedHTTPRoute && /* @__PURE__ */ React.createElement(Grid, { item: true, xs: 12 }, /* @__PURE__ */ React.createElement(
369
+ !httpRoutesLoading && !httpRoutesError && httpRoutes && httpRoutes.map((route) => {
370
+ const routeNs = route.metadata.namespace;
371
+ const routeName = route.metadata.name;
372
+ const policyInfo = getPolicyInfoForRoute(routeNs, routeName);
373
+ return /* @__PURE__ */ React.createElement(
374
+ MenuItem,
375
+ {
376
+ key: `${routeNs}/${routeName}`,
377
+ value: `${routeNs}/${routeName}`
378
+ },
379
+ /* @__PURE__ */ React.createElement(Box, null, /* @__PURE__ */ React.createElement(Typography, { variant: "body1" }, routeName), /* @__PURE__ */ React.createElement(Typography, { variant: "caption", color: "textSecondary" }, "Associated PlanPolicy: ", policyInfo))
380
+ );
381
+ })
382
+ ))), selectedHTTPRoute && /* @__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 selected HTTPRoute" }, /* @__PURE__ */ React.createElement(InfoOutlinedIcon, { className: classes.infoIcon }))), /* @__PURE__ */ React.createElement(
342
383
  PlanPolicyDetails,
343
384
  {
344
385
  selectedPolicy,
345
386
  alertSeverity: "warning",
346
387
  alertMessage: "No PlanPolicy found for this HTTPRoute. API keys and rate limiting may not be available.",
347
- includeTopMargin: true
348
- }
349
- )), /* @__PURE__ */ React.createElement(Grid, { item: true, xs: 6 }, /* @__PURE__ */ React.createElement(
350
- TextField,
351
- {
352
- fullWidth: true,
353
- label: "Contact Email",
354
- value: contactEmail,
355
- onChange: (e) => handleContactEmailChange(e.target.value),
356
- placeholder: "api-team@example.com",
357
- helperText: contactEmailError || "Contact email for API support",
358
- error: !!contactEmailError,
359
- margin: "normal",
360
- disabled: creating
361
- }
362
- )), /* @__PURE__ */ React.createElement(Grid, { item: true, xs: 6 }, /* @__PURE__ */ React.createElement(
363
- TextField,
364
- {
365
- fullWidth: true,
366
- label: "Contact Team",
367
- value: contactTeam,
368
- onChange: (e) => setContactTeam(e.target.value),
369
- placeholder: "platform-team",
370
- margin: "normal",
371
- disabled: creating
372
- }
373
- )), /* @__PURE__ */ React.createElement(Grid, { item: true, xs: 6 }, /* @__PURE__ */ React.createElement(
374
- TextField,
375
- {
376
- fullWidth: true,
377
- label: "Docs URL",
378
- value: docsURL,
379
- onChange: (e) => handleDocsURLChange(e.target.value),
380
- placeholder: "https://api.example.com/docs",
381
- helperText: docsURLError || "Link to API documentation",
382
- error: !!docsURLError,
383
- margin: "normal",
384
- disabled: creating
388
+ includeTopMargin: false
385
389
  }
386
- )), /* @__PURE__ */ React.createElement(Grid, { item: true, xs: 6 }, /* @__PURE__ */ React.createElement(
387
- TextField,
390
+ )), /* @__PURE__ */ React.createElement(Box, { className: classes.sectionHeader }, /* @__PURE__ */ React.createElement(Typography, { variant: "subtitle1" }, /* @__PURE__ */ React.createElement("strong", null, "API Key approval")), /* @__PURE__ */ React.createElement(Tooltip, { title: "Choose how API key requests are handled for this product" }, /* @__PURE__ */ React.createElement(InfoOutlinedIcon, { className: classes.infoIcon }))), /* @__PURE__ */ React.createElement(FormControl, { component: "fieldset", disabled: creating }, /* @__PURE__ */ React.createElement(
391
+ RadioGroup,
388
392
  {
389
- fullWidth: true,
390
- label: "OpenAPI Spec URL",
391
- value: openAPISpec,
392
- onChange: (e) => handleOpenAPISpecChange(e.target.value),
393
- placeholder: "https://api.example.com/openapi.json",
394
- helperText: openAPISpecError || "Link to OpenAPI specification",
395
- error: !!openAPISpecError,
396
- margin: "normal",
397
- disabled: creating
398
- }
399
- )))), /* @__PURE__ */ React.createElement(DialogActions, null, /* @__PURE__ */ React.createElement(Button, { onClick: handleClose, disabled: creating }, "Cancel"), /* @__PURE__ */ React.createElement(
393
+ row: true,
394
+ value: approvalMode,
395
+ onChange: (e) => setApprovalMode(e.target.value)
396
+ },
397
+ /* @__PURE__ */ React.createElement(
398
+ FormControlLabel,
399
+ {
400
+ value: "manual",
401
+ control: /* @__PURE__ */ React.createElement(Radio, { color: "primary" }),
402
+ label: /* @__PURE__ */ React.createElement(Box, null, /* @__PURE__ */ React.createElement(Typography, { variant: "body2" }, "Need manual approval"), /* @__PURE__ */ React.createElement(Typography, { variant: "caption", color: "textSecondary" }, "Requires approval for requesting this API"))
403
+ }
404
+ ),
405
+ /* @__PURE__ */ React.createElement(
406
+ FormControlLabel,
407
+ {
408
+ value: "automatic",
409
+ control: /* @__PURE__ */ React.createElement(Radio, { color: "primary" }),
410
+ label: /* @__PURE__ */ React.createElement(Box, null, /* @__PURE__ */ React.createElement(Typography, { variant: "body2" }, "Automatic"), /* @__PURE__ */ React.createElement(Typography, { variant: "caption", color: "textSecondary" }, "Keys are created without need to be approved"))
411
+ }
412
+ )
413
+ ))), /* @__PURE__ */ React.createElement(DialogActions, null, /* @__PURE__ */ React.createElement(Button, { onClick: handleClose, disabled: creating }, "Cancel"), /* @__PURE__ */ React.createElement(
400
414
  Button,
401
415
  {
402
416
  onClick: handleCreate,
@@ -1 +1 @@
1
- {"version":3,"file":"CreateAPIProductDialog.esm.js","sources":["../../../src/components/CreateAPIProductDialog/CreateAPIProductDialog.tsx"],"sourcesContent":["import React, {useEffect, useState} from 'react';\nimport {\n Dialog,\n DialogTitle,\n DialogContent,\n DialogActions,\n Button,\n TextField,\n Box,\n Typography,\n Chip,\n Grid,\n MenuItem,\n CircularProgress,\n makeStyles,\n} 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';\nimport { validateKubernetesName, validateEmail, validateURL } from '../../utils/validation';\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 const [httpRoutesRetry, setHttpRoutesRetry] = useState(0);\n const [nameError, setNameError] = useState<string | null>(null);\n const [contactEmailError, setContactEmailError] = useState<string | null>(null);\n const [docsURLError, setDocsURLError] = useState<string | null>(null);\n const [openAPISpecError, setOpenAPISpecError] = useState<string | null>(null);\n const {\n value: httpRoutes,\n loading: httpRoutesLoading,\n error: httpRoutesError\n } = 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, httpRoutesRetry]);\n\n // load planpolicies with full details to show associated plans\n const {\n value: planPolicies,\n error: planPoliciesError\n } = 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 useEffect(() => {\n if (open) {\n setNameError(null);\n setContactEmailError(null);\n setDocsURLError(null);\n setOpenAPISpecError(null);\n }\n }, [open]);\n\n // validate handlers\n const handleNameChange = (value: string) => {\n setName(value);\n setNameError(validateKubernetesName(value));\n };\n\n const handleContactEmailChange = (value: string) => {\n setContactEmail(value);\n setContactEmailError(validateEmail(value));\n };\n\n const handleDocsURLChange = (value: string) => {\n setDocsURL(value);\n setDocsURLError(validateURL(value));\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 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: 'devportal.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 setNameError(null);\n setContactEmailError(null);\n setDocsURLError(null);\n setOpenAPISpecError(null);\n onClose();\n };\n\n const hasValidationErrors = !!nameError || !!contactEmailError || !!docsURLError || !!openAPISpecError;\n\n return (\n <Dialog open={open} onClose={handleClose} maxWidth=\"md\" fullWidth>\n <DialogTitle>Create API Product</DialogTitle>\n <DialogContent>\n {error && (\n <Alert severity=\"error\" style={{ marginBottom: 16 }}>\n {error}\n </Alert>\n )}\n {httpRoutesError && (\n <Alert severity=\"error\" style={{ marginBottom: 16 }}>\n <strong>Failed to load HTTPRoutes:</strong> {httpRoutesError.message}\n <Box mt={1}>\n <Button\n size=\"small\"\n variant=\"outlined\"\n onClick={() => setHttpRoutesRetry(prev => prev + 1)}\n >\n Retry\n </Button>\n </Box>\n </Alert>\n )}\n\n {planPoliciesError && (\n <Alert severity=\"warning\" style={{ marginBottom: 16 }}>\n <strong>Failed to load PlanPolicies:</strong> {planPoliciesError.message}\n <Typography variant=\"body2\" style={{ marginTop: 8 }}>\n You can still create the API Product, but plan information may be incomplete.\n </Typography>\n </Alert>\n )}\n <Grid container spacing={2}>\n <Grid item xs={6}>\n <TextField\n fullWidth\n label=\"Name\"\n value={name}\n onChange={e => handleNameChange(e.target.value)}\n placeholder=\"my-api\"\n helperText={nameError || \"Kubernetes resource name (lowercase, hyphens)\"}\n error={!!nameError}\n margin=\"normal\"\n required\n disabled={creating}\n InputLabelProps={{\n classes: {\n asterisk: classes.asterisk,\n },\n }}\n />\n </Grid>\n <Grid item xs={6}>\n <TextField\n fullWidth\n label=\"Display Name\"\n value={displayName}\n onChange={e => setDisplayName(e.target.value)}\n placeholder=\"My API\"\n margin=\"normal\"\n required\n disabled={creating}\n InputLabelProps={{\n classes: {\n asterisk: classes.asterisk,\n },\n }}\n />\n </Grid>\n <Grid item xs={6}>\n <TextField\n fullWidth\n label=\"Version\"\n value={version}\n onChange={e => setVersion(e.target.value)}\n placeholder=\"v1\"\n margin=\"normal\"\n disabled={creating}\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 disabled={creating}\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 disabled={creating}\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 disabled={creating}\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={creating ? undefined : () => handleDeleteTag(tag)}\n size=\"small\"\n disabled={creating}\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 disabled={creating}\n />\n <Button onClick={handleAddTag} variant=\"outlined\" size=\"small\" disabled={creating}>\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={\n httpRoutesError\n ? \"Unable to load HTTPRoutes. Please retry.\"\n : \"Select an HTTPRoute (backstage.io/expose: true). APIProduct will be created in the same namespace.\"\n }\n error={!!httpRoutesError}\n disabled={httpRoutesLoading || creating || !!httpRoutesError}\n InputLabelProps={{\n classes: {\n asterisk: classes.asterisk,\n },\n }}\n SelectProps={{\n 'data-testid': 'httproute-select',\n } as any}\n >\n {httpRoutesLoading && (\n <MenuItem value=\"\">Loading...</MenuItem>\n )}\n {httpRoutesError && (\n <MenuItem value=\"\">Error loading routes</MenuItem>\n )}\n {!httpRoutesLoading && !httpRoutesError && httpRoutes && httpRoutes.length === 0 && (\n <MenuItem value=\"\">No HTTPRoutes available</MenuItem>\n )}\n {!httpRoutesLoading && !httpRoutesError && httpRoutes && httpRoutes.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 => handleContactEmailChange(e.target.value)}\n placeholder=\"api-team@example.com\"\n helperText={contactEmailError || \"Contact email for API support\"}\n error={!!contactEmailError}\n margin=\"normal\"\n disabled={creating}\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 disabled={creating}\n />\n </Grid>\n <Grid item xs={6}>\n <TextField\n fullWidth\n label=\"Docs URL\"\n value={docsURL}\n onChange={e => handleDocsURLChange(e.target.value)}\n placeholder=\"https://api.example.com/docs\"\n helperText={docsURLError || \"Link to API documentation\"}\n error={!!docsURLError}\n margin=\"normal\"\n disabled={creating}\n />\n </Grid>\n <Grid item xs={6}>\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 || \"Link to OpenAPI specification\"}\n error={!!openAPISpecError}\n margin=\"normal\"\n disabled={creating}\n />\n </Grid>\n </Grid>\n </DialogContent>\n <DialogActions>\n <Button onClick={handleClose} disabled={creating}>Cancel</Button>\n <Button\n onClick={handleCreate}\n color=\"primary\"\n variant=\"contained\"\n disabled={creating || !name || !displayName || !description || !selectedHTTPRoute || hasValidationErrors}\n startIcon={creating ? <CircularProgress size={16} color=\"inherit\" /> : undefined}\n >\n {creating ? 'Creating...' : 'Create'}\n </Button>\n </DialogActions>\n </Dialog>\n );\n};\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"CreateAPIProductDialog.esm.js","sources":["../../../src/components/CreateAPIProductDialog/CreateAPIProductDialog.tsx"],"sourcesContent":["import React, {useEffect, useState} from 'react';\nimport {\n Dialog,\n DialogTitle,\n DialogContent,\n DialogActions,\n Button,\n TextField,\n Box,\n Typography,\n Chip,\n Grid,\n MenuItem,\n CircularProgress,\n makeStyles,\n FormControl,\n RadioGroup,\n FormControlLabel,\n Radio,\n Tooltip,\n IconButton,\n InputAdornment,\n} from '@material-ui/core';\nimport InfoOutlinedIcon from '@material-ui/icons/InfoOutlined';\nimport AddIcon from '@material-ui/icons/Add';\nimport { useApi, configApiRef, fetchApiRef } from '@backstage/core-plugin-api';\nimport { Alert } from '@material-ui/lab';\nimport useAsync from 'react-use/lib/useAsync';\nimport { PlanPolicyDetails } from '../PlanPolicyDetailsCard';\nimport { validateKubernetesName, validateURL } from '../../utils/validation';\n\nconst useStyles = makeStyles((theme) => ({\n asterisk: {\n color: '#f44336',\n },\n sectionHeader: {\n display: 'flex',\n alignItems: 'center',\n gap: theme.spacing(0.5),\n marginTop: theme.spacing(2),\n marginBottom: theme.spacing(1),\n },\n infoIcon: {\n fontSize: 18,\n color: theme.palette.text.secondary,\n },\n tagChip: {\n marginRight: theme.spacing(0.5),\n marginBottom: theme.spacing(0.5),\n },\n}));\n\ninterface CreateAPIProductDialogProps {\n open: boolean;\n onClose: () => void;\n onSuccess: (productInfo: { namespace: string; name: string; displayName: string }) => void;\n}\n\nexport const CreateAPIProductDialog = ({ open, onClose, onSuccess }: CreateAPIProductDialogProps) => {\n const classes = useStyles();\n const 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 const [httpRoutesRetry, setHttpRoutesRetry] = useState(0);\n const [nameError, setNameError] = useState<string | null>(null);\n const [openAPISpecError, setOpenAPISpecError] = useState<string | null>(null);\n const {\n value: httpRoutes,\n loading: httpRoutesLoading,\n error: httpRoutesError\n } = 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, httpRoutesRetry]);\n\n // load planpolicies with full details to show associated plans\n const {\n value: planPolicies,\n error: planPoliciesError\n } = 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 // format tier info for dropdown display\n const formatTierInfo = (policy: any): string => {\n if (!policy?.spec?.plans) return '';\n const tiers = Object.entries(policy.spec.plans)\n .map(([name, plan]: [string, any]) => {\n const limit = plan?.limits?.requests;\n if (!limit) return name;\n return `${name}: ${limit.count}/${limit.period}`;\n })\n .join('; ');\n return tiers ? ` (${tiers})` : '';\n };\n\n // get policy info for a route (for dropdown display)\n const getPolicyInfoForRoute = (routeNamespace: string, routeName: string): string => {\n const policy = getPlanPolicyForRoute(routeNamespace, routeName);\n if (!policy) return 'N/A';\n return `${policy.metadata.name}${formatTierInfo(policy)}`;\n };\n\n useEffect(() => {\n if (open) {\n setNameError(null);\n setOpenAPISpecError(null);\n }\n }, [open]);\n\n // validate handlers\n const handleNameChange = (value: string) => {\n setName(value);\n setNameError(validateKubernetesName(value));\n };\n\n const 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 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: 'devportal.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 && { openAPISpecURL: 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({ namespace, name, displayName });\n handleClose();\n } catch (err) {\n setError(err instanceof Error ? err.message : String(err));\n } finally {\n setCreating(false);\n }\n };\n\n const 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 setNameError(null);\n setOpenAPISpecError(null);\n onClose();\n };\n\n const hasValidationErrors = !!nameError || !!openAPISpecError;\n\n return (\n <Dialog open={open} onClose={handleClose} maxWidth=\"md\" fullWidth>\n <DialogTitle>Create API Product</DialogTitle>\n <DialogContent>\n {error && (\n <Alert severity=\"error\" style={{ marginBottom: 16 }}>\n {error}\n </Alert>\n )}\n {httpRoutesError && (\n <Alert severity=\"error\" style={{ marginBottom: 16 }}>\n <strong>Failed to load HTTPRoutes:</strong> {httpRoutesError.message}\n <Box mt={1}>\n <Button\n size=\"small\"\n variant=\"outlined\"\n onClick={() => setHttpRoutesRetry(prev => prev + 1)}\n >\n Retry\n </Button>\n </Box>\n </Alert>\n )}\n\n {planPoliciesError && (\n <Alert severity=\"warning\" style={{ marginBottom: 16 }}>\n <strong>Failed to load PlanPolicies:</strong> {planPoliciesError.message}\n <Typography variant=\"body2\" style={{ marginTop: 8 }}>\n You can still create the API Product, but plan information may be incomplete.\n </Typography>\n </Alert>\n )}\n {/* 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={creating}\n InputLabelProps={{\n classes: {\n asterisk: classes.asterisk,\n },\n }}\n />\n </Grid>\n <Grid item xs={6}>\n <TextField\n fullWidth\n label=\"Resource name\"\n value={name}\n onChange={e => handleNameChange(e.target.value)}\n placeholder=\"my-api\"\n helperText={nameError || \"Kubernetes resource name with lowercase, hyphens. Eg.flight_API\"}\n error={!!nameError}\n margin=\"normal\"\n required\n disabled={creating}\n InputLabelProps={{\n classes: {\n asterisk: classes.asterisk,\n },\n }}\n />\n </Grid>\n <Grid item xs={6}>\n <TextField\n fullWidth\n label=\"Version\"\n value={version}\n onChange={e => setVersion(e.target.value)}\n placeholder=\"v1\"\n helperText=\"Give a version to your API product\"\n margin=\"normal\"\n required\n disabled={creating}\n InputLabelProps={{\n classes: {\n asterisk: classes.asterisk,\n },\n }}\n />\n </Grid>\n <Grid item xs={6}>\n <TextField\n fullWidth\n label=\"Tag\"\n value={tagInput}\n onChange={e => setTagInput(e.target.value)}\n onKeyPress={e => {\n if (e.key === 'Enter') {\n e.preventDefault();\n handleAddTag();\n }\n }}\n placeholder=\"Add tag\"\n helperText=\"Add a tag to your API product\"\n margin=\"normal\"\n disabled={creating}\n InputProps={{\n endAdornment: tagInput ? (\n <InputAdornment position=\"end\">\n <IconButton size=\"small\" onClick={handleAddTag} disabled={creating}>\n <AddIcon fontSize=\"small\" />\n </IconButton>\n </InputAdornment>\n ) : undefined,\n }}\n />\n </Grid>\n {tags.length > 0 && (\n <Grid item xs={12}>\n <Box display=\"flex\" flexWrap=\"wrap\">\n {tags.map(tag => (\n <Chip\n key={tag}\n label={tag}\n onDelete={creating ? undefined : () => handleDeleteTag(tag)}\n size=\"small\"\n className={classes.tagChip}\n disabled={creating}\n />\n ))}\n </Box>\n </Grid>\n )}\n <Grid item xs={12}>\n <TextField\n fullWidth\n label=\"Description\"\n value={description}\n onChange={e => setDescription(e.target.value)}\n placeholder=\"API description\"\n margin=\"normal\"\n multiline\n rows={2}\n required\n disabled={creating}\n InputLabelProps={{\n classes: {\n asterisk: classes.asterisk,\n },\n }}\n />\n </Grid>\n </Grid>\n\n {/* Add API and Associate route section */}\n <Box className={classes.sectionHeader}>\n <Typography variant=\"subtitle1\"><strong>Add API and Associate route</strong></Typography>\n <Tooltip title=\"Register an existing API and associate HTTPRoute for your API product\">\n <InfoOutlinedIcon className={classes.infoIcon} />\n </Tooltip>\n </Box>\n <Grid container spacing={2}>\n <Grid item xs={12}>\n <TextField\n fullWidth\n label=\"OpenAPI Spec URL\"\n value={openAPISpec}\n onChange={e => handleOpenAPISpecChange(e.target.value)}\n placeholder=\"https://api.example.com/openapi.json\"\n helperText={openAPISpecError || \"Enter the full path to your API spec file\"}\n error={!!openAPISpecError}\n margin=\"normal\"\n required\n disabled={creating}\n InputLabelProps={{\n classes: {\n asterisk: classes.asterisk,\n },\n }}\n />\n </Grid>\n <Grid item xs={12}>\n <TextField\n fullWidth\n label=\"Documentation URL\"\n value={docsURL}\n onChange={e => setDocsURL(e.target.value)}\n placeholder=\"https://docs.example.com/api\"\n helperText=\"Link to external documentation for this API\"\n margin=\"normal\"\n disabled={creating}\n />\n </Grid>\n <Grid item xs={12}>\n <TextField\n fullWidth\n select\n label=\"HTTPRoute\"\n value={selectedHTTPRoute}\n onChange={e => setSelectedHTTPRoute(e.target.value)}\n margin=\"normal\"\n required\n helperText={\n httpRoutesError\n ? \"Unable to load HTTPRoutes. Please retry.\"\n : \"Select an HTTPRoute. Eg.backstage.io/expose:true. API product will be created in the same namespace.\"\n }\n error={!!httpRoutesError}\n disabled={httpRoutesLoading || creating || !!httpRoutesError}\n InputLabelProps={{\n classes: {\n asterisk: classes.asterisk,\n },\n }}\n SelectProps={{\n 'data-testid': 'httproute-select',\n } as any}\n >\n {httpRoutesLoading && (\n <MenuItem value=\"\">Loading...</MenuItem>\n )}\n {httpRoutesError && (\n <MenuItem value=\"\">Error loading routes</MenuItem>\n )}\n {!httpRoutesLoading && !httpRoutesError && httpRoutes && httpRoutes.length === 0 && (\n <MenuItem value=\"\">No HTTPRoutes available</MenuItem>\n )}\n {!httpRoutesLoading && !httpRoutesError && httpRoutes && httpRoutes.map((route: any) => {\n const routeNs = route.metadata.namespace;\n const routeName = route.metadata.name;\n const policyInfo = getPolicyInfoForRoute(routeNs, routeName);\n return (\n <MenuItem\n key={`${routeNs}/${routeName}`}\n value={`${routeNs}/${routeName}`}\n >\n <Box>\n <Typography variant=\"body1\">{routeName}</Typography>\n <Typography variant=\"caption\" color=\"textSecondary\">\n Associated PlanPolicy: {policyInfo}\n </Typography>\n </Box>\n </MenuItem>\n );\n })}\n </TextField>\n </Grid>\n </Grid>\n\n {/* HTTPRoute policies section */}\n {selectedHTTPRoute && (\n <>\n <Box className={classes.sectionHeader}>\n <Typography variant=\"subtitle1\"><strong>HTTPRoute policies</strong></Typography>\n <Tooltip title=\"Shows the associated policies and rate limit tiers for the selected HTTPRoute\">\n <InfoOutlinedIcon className={classes.infoIcon} />\n </Tooltip>\n </Box>\n <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={false}\n />\n </>\n )}\n\n {/* API Key approval section */}\n <Box className={classes.sectionHeader}>\n <Typography variant=\"subtitle1\"><strong>API Key approval</strong></Typography>\n <Tooltip title=\"Choose how API key requests are handled for this product\">\n <InfoOutlinedIcon className={classes.infoIcon} />\n </Tooltip>\n </Box>\n <FormControl component=\"fieldset\" disabled={creating}>\n <RadioGroup\n row\n value={approvalMode}\n onChange={e => setApprovalMode(e.target.value as 'automatic' | 'manual')}\n >\n <FormControlLabel\n value=\"manual\"\n control={<Radio color=\"primary\" />}\n label={\n <Box>\n <Typography variant=\"body2\">Need manual approval</Typography>\n <Typography variant=\"caption\" color=\"textSecondary\">\n Requires approval for requesting this API\n </Typography>\n </Box>\n }\n />\n <FormControlLabel\n value=\"automatic\"\n control={<Radio color=\"primary\" />}\n label={\n <Box>\n <Typography variant=\"body2\">Automatic</Typography>\n <Typography variant=\"caption\" color=\"textSecondary\">\n Keys are created without need to be approved\n </Typography>\n </Box>\n }\n />\n </RadioGroup>\n </FormControl>\n </DialogContent>\n <DialogActions>\n <Button onClick={handleClose} disabled={creating}>Cancel</Button>\n <Button\n onClick={handleCreate}\n color=\"primary\"\n variant=\"contained\"\n disabled={creating || !name || !displayName || !description || !selectedHTTPRoute || hasValidationErrors}\n startIcon={creating ? <CircularProgress size={16} color=\"inherit\" /> : undefined}\n >\n {creating ? 'Creating...' : 'Create'}\n </Button>\n </DialogActions>\n </Dialog>\n );\n};\n"],"names":["name"],"mappings":"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"}