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

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 (30) hide show
  1. package/dist/components/ApprovalQueueTable/ApprovalQueueTable.esm.js +123 -6
  2. package/dist/components/ApprovalQueueTable/ApprovalQueueTable.esm.js.map +1 -1
  3. package/dist/components/CreateAPIProductDialog/CreateAPIProductDialog.esm.js +2 -2
  4. package/dist/components/CreateAPIProductDialog/CreateAPIProductDialog.esm.js.map +1 -1
  5. package/dist/components/EditAPIProductDialog/EditAPIProductDialog.esm.js +5 -23
  6. package/dist/components/EditAPIProductDialog/EditAPIProductDialog.esm.js.map +1 -1
  7. package/dist/components/PlanPolicyDetailsCard/PlanPolicyDetails.esm.js +4 -4
  8. package/dist/components/PlanPolicyDetailsCard/PlanPolicyDetails.esm.js.map +1 -1
  9. package/dist-scalprum/{internal.plugin-kuadrant.09545fa30927eb9a66fd.js → internal.plugin-kuadrant.114cbbe1d3ddb939d776.js} +2 -2
  10. package/dist-scalprum/{internal.plugin-kuadrant.09545fa30927eb9a66fd.js.map → internal.plugin-kuadrant.114cbbe1d3ddb939d776.js.map} +1 -1
  11. package/dist-scalprum/plugin-manifest.json +2 -2
  12. package/dist-scalprum/static/2821.0829f14d.chunk.js +2 -0
  13. package/dist-scalprum/static/2821.0829f14d.chunk.js.map +1 -0
  14. package/dist-scalprum/static/4682.75f17114.chunk.js +2 -0
  15. package/dist-scalprum/static/4682.75f17114.chunk.js.map +1 -0
  16. package/dist-scalprum/static/7236.f3886d59.chunk.js +2 -0
  17. package/dist-scalprum/static/7236.f3886d59.chunk.js.map +1 -0
  18. package/dist-scalprum/static/8799.939d14f9.chunk.js +2 -0
  19. package/dist-scalprum/static/8799.939d14f9.chunk.js.map +1 -0
  20. package/dist-scalprum/static/{exposed-PluginRoot.55777e36.chunk.js → exposed-PluginRoot.ed95fa78.chunk.js} +2 -2
  21. package/dist-scalprum/static/{exposed-PluginRoot.55777e36.chunk.js.map → exposed-PluginRoot.ed95fa78.chunk.js.map} +1 -1
  22. package/package.json +1 -1
  23. package/dist-scalprum/static/2821.972ae33b.chunk.js +0 -2
  24. package/dist-scalprum/static/2821.972ae33b.chunk.js.map +0 -1
  25. package/dist-scalprum/static/3091.9a74ea5f.chunk.js +0 -2
  26. package/dist-scalprum/static/3091.9a74ea5f.chunk.js.map +0 -1
  27. package/dist-scalprum/static/4682.51e5be13.chunk.js +0 -2
  28. package/dist-scalprum/static/4682.51e5be13.chunk.js.map +0 -1
  29. package/dist-scalprum/static/8799.52bbeef1.chunk.js +0 -2
  30. package/dist-scalprum/static/8799.52bbeef1.chunk.js.map +0 -1
@@ -5,7 +5,7 @@
5
5
  "registrationMethod": "callback",
6
6
  "baseURL": "auto",
7
7
  "loadScripts": [
8
- "internal.plugin-kuadrant.09545fa30927eb9a66fd.js"
8
+ "internal.plugin-kuadrant.114cbbe1d3ddb939d776.js"
9
9
  ],
10
- "buildHash": "09545fa30927eb9a66fd0de5b72575f5"
10
+ "buildHash": "114cbbe1d3ddb939d776127ea4f11993"
11
11
  }
@@ -0,0 +1,2 @@
1
+ "use strict";(self.webpackChunkinternal_plugin_kuadrant=self.webpackChunkinternal_plugin_kuadrant||[]).push([[2821],{12229:(e,t,a)=>{a.d(t,{Z:()=>A});var s=a(31085),n=a(95478),i=a.n(n),l=a(10394),r=a(72501),o=a(64947),c=a(37197),d=a(69621),u=a(12981),p=a(86901),m=a(69076),h=a(58837),g=a(6924),x=a(23164);const v=(0,h.A)(e=>({root:{width:240,minWidth:240,padding:e.spacing(2),borderRight:`1px solid ${e.palette.divider}`,backgroundColor:e.palette.background.paper,height:"100%",overflowY:"auto"},sectionTitle:{fontWeight:600,fontSize:"0.75rem",textTransform:"uppercase",letterSpacing:"0.05em",color:e.palette.text.secondary,marginBottom:e.spacing(1),display:"flex",alignItems:"center",justifyContent:"space-between",cursor:"pointer",userSelect:"none"},filterSection:{marginBottom:e.spacing(2)},checkbox:{padding:e.spacing(.5)},checkboxLabel:{fontSize:"0.875rem"},clearButton:{marginTop:e.spacing(2)},count:{fontSize:"0.75rem",color:e.palette.text.secondary,marginLeft:e.spacing(1)}})),A=({sections:e,filters:t,onChange:a,onClear:n})=>{const h=v(),[A,f]=i().useState(new Set(e.filter(e=>e.collapsed).map(e=>e.id))),y=Object.values(t).some(e=>e.length>0);return(0,s.jsxs)(l.A,{className:h.root,children:[(0,s.jsxs)(l.A,{display:"flex",justifyContent:"space-between",alignItems:"center",mb:2,children:[(0,s.jsx)(r.A,{variant:"subtitle2",children:"Filters"}),y&&(0,s.jsx)(o.A,{size:"small",color:"primary",onClick:()=>{const t={};e.forEach(e=>{t[e.id]=[]}),a(t),null==n||n()},children:"Clear all"})]}),(0,s.jsx)(c.A,{}),e.map(e=>{const n=A.has(e.id),i=(t[e.id]||[]).length;return(0,s.jsxs)(l.A,{className:h.filterSection,mt:2,children:[(0,s.jsxs)(l.A,{className:h.sectionTitle,onClick:()=>{return t=e.id,void f(e=>{const a=new Set(e);return a.has(t)?a.delete(t):a.add(t),a});var t},children:[(0,s.jsxs)(l.A,{display:"flex",alignItems:"center",children:[(0,s.jsx)("span",{children:e.title}),i>0&&(0,s.jsxs)("span",{className:h.count,children:["(",i,")"]})]}),n?(0,s.jsx)(g.A,{fontSize:"small"}):(0,s.jsx)(x.A,{fontSize:"small"})]}),(0,s.jsx)(d.A,{in:!n,children:(0,s.jsx)(u.A,{children:e.options.map(n=>(0,s.jsx)(p.A,{control:(0,s.jsx)(m.A,{checked:(t[e.id]||[]).includes(n.value),onChange:()=>((e,s)=>{const n=t[e]||[],i=n.includes(s)?n.filter(e=>e!==s):[...n,s];a({...t,[e]:i})})(e.id,n.value),size:"small",className:h.checkbox,color:"primary"}),label:(0,s.jsxs)(l.A,{display:"flex",alignItems:"center",children:[(0,s.jsx)("span",{className:h.checkboxLabel,children:n.label}),void 0!==n.count&&(0,s.jsxs)("span",{className:h.count,children:["(",n.count,")"]})]})},n.value))})})]},e.id)})]})}},38599:(e,t,a)=>{a.d(t,{B:()=>o});var s=a(31085),n=(a(95478),a(10394)),i=a(72501),l=a(86687),r=a(46205);const o=({children:e,permission:t,fallback:a,errorMessage:o})=>{const{allowed:c,loading:d,error:u}=(0,r.l)(t);return d?(0,s.jsx)(l.k,{}):u?(0,s.jsxs)(n.A,{p:4,children:[(0,s.jsxs)(i.A,{color:"error",children:["Unable to check permissions: ",u.message]}),(0,s.jsx)(i.A,{variant:"body2",color:"textSecondary",children:"Please try again or contact your administrator"})]}):c?(0,s.jsx)(s.Fragment,{children:e}):a?(0,s.jsx)(s.Fragment,{children:a}):(0,s.jsxs)(n.A,{p:4,children:[(0,s.jsx)(i.A,{color:"textSecondary",children:o||"You don't have permission to view this page"}),(0,s.jsx)(n.A,{mt:1,children:(0,s.jsxs)(i.A,{variant:"caption",color:"textSecondary",children:["Required permission: ",t.name]})})]})}},80243:(e,t,a)=>{a.r(t),a.d(t,{ApiProductsPage:()=>te});var s=a(31085),n=a(95478),i=a(58837),l=a(10394),r=a(67720),o=a(72501),c=a(64947),d=a(29365),u=a(78467),p=a(18466),m=a(39590),h=a(75625),g=a(21702),x=a(85142),v=a(12229),A=a(37725),f=a(289),y=a(15831),j=a(45210),b=a(46681),P=a(42367),S=a(25010),w=a(91638),k=a(22097),I=a(38599),T=a(76891),C=a(61477),N=a(46805),R=a(42899),$=a(16249),z=a(34839),E=a(71677),D=a(26343),H=a(95061),L=a(29635),q=a(86901),M=a(30285),W=a(93453),K=a(89031),O=a(84441),B=a(65867),U=a(24170),F=a(77318);const _=(0,i.A)(e=>({asterisk:{color:"#f44336"},sectionHeader:{display:"flex",alignItems:"center",gap:e.spacing(.5),marginTop:e.spacing(2),marginBottom:e.spacing(1)},infoIcon:{fontSize:18,color:e.palette.text.secondary},tagChip:{marginRight:e.spacing(.5),marginBottom:e.spacing(.5)}})),Y=({open:e,onClose:t,onSuccess:a})=>{const i=_(),m=(0,k.useApi)(k.configApiRef),h=(0,k.useApi)(k.fetchApiRef),g=m.getString("backend.baseUrl"),[x,v]=(0,n.useState)(""),[A,f]=(0,n.useState)(""),[y,j]=(0,n.useState)(""),[b,P]=(0,n.useState)("v1"),[S,I]=(0,n.useState)("manual"),[Y,J]=(0,n.useState)("Published"),[V,G]=(0,n.useState)([]),[Z,X]=(0,n.useState)(""),[Q,ee]=(0,n.useState)(""),[te,ae]=(0,n.useState)(""),[se,ne]=(0,n.useState)(""),[ie,le]=(0,n.useState)(""),[re,oe]=(0,n.useState)(""),[ce,de]=(0,n.useState)(""),[ue,pe]=(0,n.useState)(!1),[me,he]=(0,n.useState)(0),[ge,xe]=(0,n.useState)(null),[ve,Ae]=(0,n.useState)(null),{value:fe,loading:ye,error:je}=(0,w.A)(async()=>{const e=await h.fetch(`${g}/api/kuadrant/httproutes`);if(!e.ok){const t=await(0,F.T)(e);throw new Error(`failed to fetch routes. ${t}`)}return(await e.json()).items||[]},[g,h,e,me]),{value:be,error:Pe}=(0,w.A)(async()=>{const e=await h.fetch(`${g}/api/kuadrant/planpolicies`);if(!e.ok){const t=await(0,F.T)(e);throw new Error(`failed to fetch PlanPolicies. ${t}`)}return await e.json()},[g,h,e]),Se=(e,t)=>(null==be?void 0:be.items)?be.items.find(a=>{const s=a.targetRef;return"HTTPRoute"===(null==s?void 0:s.kind)&&(null==s?void 0:s.name)===t&&(!(null==s?void 0:s.namespace)||(null==s?void 0:s.namespace)===e)}):null,we=Q?Q.split("/"):null,ke=we?Se(we[0],we[1]):null;(0,n.useEffect)(()=>{e&&(xe(null),Ae(null))},[e]);const Ie=()=>{Z.trim()&&!V.includes(Z.trim())&&(G([...V,Z.trim()]),X(""))},Te=()=>{v(""),f(""),j(""),P("v1"),I("manual"),J("Published"),G([]),X(""),ee(""),ae(""),ne(""),le(""),oe(""),de(""),xe(null),Ae(null),t()},Ce=!!ge||!!ve;return(0,s.jsxs)(T.A,{open:e,onClose:Te,maxWidth:"md",fullWidth:!0,children:[(0,s.jsx)(C.A,{children:"Create API Product"}),(0,s.jsxs)(N.A,{children:[ce&&(0,s.jsx)(O.A,{severity:"error",style:{marginBottom:16},children:ce}),je&&(0,s.jsxs)(O.A,{severity:"error",style:{marginBottom:16},children:[(0,s.jsx)("strong",{children:"Failed to load HTTPRoutes:"})," ",je.message,(0,s.jsx)(l.A,{mt:1,children:(0,s.jsx)(c.A,{size:"small",variant:"outlined",onClick:()=>he(e=>e+1),children:"Retry"})})]}),Pe&&(0,s.jsxs)(O.A,{severity:"warning",style:{marginBottom:16},children:[(0,s.jsx)("strong",{children:"Failed to load PlanPolicies:"})," ",Pe.message,(0,s.jsx)(o.A,{variant:"body2",style:{marginTop:8},children:"You can still create the API Product, but plan information may be incomplete."})]}),(0,s.jsx)(l.A,{className:i.sectionHeader,children:(0,s.jsx)(o.A,{variant:"subtitle1",children:(0,s.jsx)("strong",{children:"API product info"})})}),(0,s.jsxs)(R.A,{container:!0,spacing:2,children:[(0,s.jsx)(R.A,{item:!0,xs:6,children:(0,s.jsx)($.A,{fullWidth:!0,label:"API product name",value:A,onChange:e=>f(e.target.value),placeholder:"My API",helperText:"Give a unique name for your API product",margin:"normal",required:!0,disabled:ue,InputLabelProps:{classes:{asterisk:i.asterisk}}})}),(0,s.jsx)(R.A,{item:!0,xs:6,children:(0,s.jsx)($.A,{fullWidth:!0,label:"Resource name",value:x,onChange:e=>{return t=e.target.value,v(t),void xe((0,U.o)(t));var t},placeholder:"my-api",helperText:ge||"Kubernetes resource name with lowercase, hyphens. Eg.flight_API",error:!!ge,margin:"normal",required:!0,disabled:ue,InputLabelProps:{classes:{asterisk:i.asterisk}}})}),(0,s.jsx)(R.A,{item:!0,xs:6,children:(0,s.jsx)($.A,{fullWidth:!0,label:"Version",value:b,onChange:e=>P(e.target.value),placeholder:"v1",helperText:"Give a version to your API product",margin:"normal",required:!0,disabled:ue,InputLabelProps:{classes:{asterisk:i.asterisk}}})}),(0,s.jsx)(R.A,{item:!0,xs:6,children:(0,s.jsx)($.A,{fullWidth:!0,label:"Tag",value:Z,onChange:e=>X(e.target.value),onKeyPress:e=>{"Enter"===e.key&&(e.preventDefault(),Ie())},placeholder:"Add tag",helperText:"Add a tag to your API product",margin:"normal",disabled:ue,InputProps:{endAdornment:Z?(0,s.jsx)(z.A,{position:"end",children:(0,s.jsx)(d.A,{size:"small",onClick:Ie,disabled:ue,children:(0,s.jsx)(p.A,{fontSize:"small"})})}):void 0}})}),V.length>0&&(0,s.jsx)(R.A,{item:!0,xs:12,children:(0,s.jsx)(l.A,{display:"flex",flexWrap:"wrap",children:V.map(e=>(0,s.jsx)(r.A,{label:e,onDelete:ue?void 0:()=>{return t=e,void G(V.filter(e=>e!==t));var t},size:"small",className:i.tagChip,disabled:ue},e))})}),(0,s.jsx)(R.A,{item:!0,xs:12,children:(0,s.jsx)($.A,{fullWidth:!0,label:"Description",value:y,onChange:e=>j(e.target.value),placeholder:"API description",margin:"normal",multiline:!0,rows:2,required:!0,disabled:ue,InputLabelProps:{classes:{asterisk:i.asterisk}}})})]}),(0,s.jsxs)(l.A,{className:i.sectionHeader,children:[(0,s.jsx)(o.A,{variant:"subtitle1",children:(0,s.jsx)("strong",{children:"Add API and Associate route"})}),(0,s.jsx)(E.Ay,{title:"Register an existing API and associate HTTPRoute for your API product",children:(0,s.jsx)(K.A,{className:i.infoIcon})})]}),(0,s.jsxs)(R.A,{container:!0,spacing:2,children:[(0,s.jsx)(R.A,{item:!0,xs:12,children:(0,s.jsx)($.A,{fullWidth:!0,label:"OpenAPI Spec URL",value:re,onChange:e=>{return t=e.target.value,oe(t),void Ae((0,U.q)(t));var t},placeholder:"https://api.example.com/openapi.json",helperText:ve||"Enter the full path to your API spec file",error:!!ve,margin:"normal",required:!0,disabled:ue,InputLabelProps:{classes:{asterisk:i.asterisk}}})}),(0,s.jsx)(R.A,{item:!0,xs:12,children:(0,s.jsx)($.A,{fullWidth:!0,label:"Documentation URL",value:ie,onChange:e=>le(e.target.value),placeholder:"https://docs.example.com/api",helperText:"Link to external documentation for this API",margin:"normal",disabled:ue})}),(0,s.jsx)(R.A,{item:!0,xs:12,children:(0,s.jsxs)($.A,{fullWidth:!0,select:!0,label:"HTTPRoute",value:Q,onChange:e=>ee(e.target.value),margin:"normal",required:!0,helperText:je?"Unable to load HTTPRoutes. Please retry.":"Select an HTTPRoute. APIProduct will be created in the same namespace.",error:!!je,disabled:ye||ue||!!je,InputLabelProps:{classes:{asterisk:i.asterisk}},SelectProps:{"data-testid":"httproute-select"},children:[ye&&(0,s.jsx)(D.A,{value:"",children:"Loading..."}),je&&(0,s.jsx)(D.A,{value:"",children:"Error loading routes"}),!ye&&!je&&fe&&0===fe.length&&(0,s.jsx)(D.A,{value:"",children:"No HTTPRoutes available"}),!ye&&!je&&fe&&fe.map(e=>{const t=e.metadata.namespace,a=e.metadata.name,n=((e,t)=>{const a=Se(e,t);return a?`${a.metadata.name}${(e=>{var t;if(!(null==e||null===(t=e.spec)||void 0===t?void 0:t.plans))return"";const a=Object.entries(e.spec.plans).map(([e,t])=>{var a;const s=null==t||null===(a=t.limits)||void 0===a?void 0:a.requests;return s?`${e}: ${s.count}/${s.period}`:e}).join("; ");return a?` (${a})`:""})(a)}`:"N/A"})(t,a);return(0,s.jsx)(D.A,{value:`${t}/${a}`,children:(0,s.jsxs)(l.A,{children:[(0,s.jsx)(o.A,{variant:"body1",children:a}),(0,s.jsxs)(o.A,{variant:"caption",color:"textSecondary",children:["Associated PlanPolicy: ",n]})]})},`${t}/${a}`)})]})})]}),Q&&ke&&(0,s.jsxs)(s.Fragment,{children:[(0,s.jsxs)(l.A,{className:i.sectionHeader,children:[(0,s.jsx)(o.A,{variant:"subtitle1",children:(0,s.jsx)("strong",{children:"HTTPRoute policies"})}),(0,s.jsx)(E.Ay,{title:"Shows the associated policies and rate limit tiers for the selected HTTPRoute",children:(0,s.jsx)(K.A,{className:i.infoIcon})})]}),(0,s.jsx)(B.g,{discoveredPlans:ke.plans,alertSeverity:"warning",alertMessage:"No PlanPolicy found for this HTTPRoute. API keys and rate limiting may not be available.",includeTopMargin:!1})]}),(0,s.jsxs)(l.A,{className:i.sectionHeader,children:[(0,s.jsx)(o.A,{variant:"subtitle1",children:(0,s.jsx)("strong",{children:"API Key approval"})}),(0,s.jsx)(E.Ay,{title:"Choose how API key requests are handled for this product",children:(0,s.jsx)(K.A,{className:i.infoIcon})})]}),(0,s.jsx)(H.A,{component:"fieldset",disabled:ue,children:(0,s.jsxs)(L.A,{row:!0,value:S,onChange:e=>I(e.target.value),children:[(0,s.jsx)(q.A,{value:"manual",control:(0,s.jsx)(M.A,{color:"primary"}),label:(0,s.jsxs)(l.A,{children:[(0,s.jsx)(o.A,{variant:"body2",children:"Need manual approval"}),(0,s.jsx)(o.A,{variant:"caption",color:"textSecondary",children:"Requires approval for requesting this API"})]})}),(0,s.jsx)(q.A,{value:"automatic",control:(0,s.jsx)(M.A,{color:"primary"}),label:(0,s.jsxs)(l.A,{children:[(0,s.jsx)(o.A,{variant:"body2",children:"Automatic"}),(0,s.jsx)(o.A,{variant:"caption",color:"textSecondary",children:"Keys are created without need to be approved"})]})})]})})]}),(0,s.jsxs)(W.A,{children:[(0,s.jsx)(c.A,{onClick:Te,disabled:ue,children:"Cancel"}),(0,s.jsx)(c.A,{onClick:async()=>{de(""),pe(!0);try{if(!Q)throw new Error("Please select an HTTPRoute");const[e,t]=Q.split("/"),s=e,n={apiVersion:"devportal.kuadrant.io/v1alpha1",kind:"APIProduct",metadata:{name:x,namespace:s},spec:{displayName:A,description:y,version:b,approvalMode:S,publishStatus:Y,tags:V,targetRef:{group:"gateway.networking.k8s.io",kind:"HTTPRoute",name:t,namespace:e},...te||se?{contact:{...te&&{email:te},...se&&{team:se}}}:{},...ie||re?{documentation:{...ie&&{docsURL:ie},...re&&{openAPISpecURL:re}}}:{}}},i=await h.fetch(`${g}/api/kuadrant/apiproducts`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(n)});if(!i.ok){const e=await(0,F.T)(i);throw new Error(`failed to create APIProduct. ${e}`)}a({namespace:s,name:x,displayName:A}),Te()}catch(e){de(e instanceof Error?e.message:String(e))}finally{pe(!1)}},color:"primary",variant:"contained",disabled:ue||!x||!A||!y||!Q||Ce,startIcon:ue?(0,s.jsx)(u.A,{size:16,color:"inherit"}):void 0,children:ue?"Creating...":"Create"})]})]})};var J=a(34955),V=a(46205),G=a(26997),Z=a(63221);const X=a.p+"static/empty-state-illustration.7e3ad5a9..png",Q=(0,i.A)(e=>({container:{display:"flex",height:"100%",minHeight:400},tableContainer:{flex:1,overflow:"auto",padding:10},emptyState:{display:"flex",alignItems:"center",justifyContent:"center",padding:e.spacing(6),minHeight:400},emptyStateContent:{display:"flex",alignItems:"center",gap:e.spacing(6),maxWidth:900},emptyStateText:{flex:1},emptyStateTitle:{marginBottom:e.spacing(2)},emptyStateDescription:{marginBottom:e.spacing(3),color:e.palette.text.secondary},emptyStateImage:{maxWidth:400,height:"auto"}})),ee=()=>{const e=Q(),t=(0,k.useApi)(k.configApiRef),a=(0,k.useApi)(k.fetchApiRef),i=(0,k.useApi)(k.alertApiRef),I=(0,k.useApi)(k.identityApiRef),T=t.getString("backend.baseUrl"),[C,N]=(0,n.useState)(""),[R,$]=(0,n.useState)(!1),[z,E]=(0,n.useState)(!1),[D,H]=(0,n.useState)(0),[L,q]=(0,n.useState)(!1),[M,W]=(0,n.useState)(null),[K,O]=(0,n.useState)(null),[B,U]=(0,n.useState)(!1),[_,ee]=(0,n.useState)(null),[te,ae]=(0,n.useState)({status:[],policy:[],route:[],namespace:[],tags:[],authentication:[]}),{allowed:se,loading:ne,error:ie}=(0,V.l)(J.FL),{allowed:le,loading:re}=(0,V.l)(J.EM),{allowed:oe,loading:ce,error:de}=(0,V.l)(J.R_),{allowed:ue}=(0,V.l)(J.U3),{allowed:pe}=(0,V.l)(J.v_),me=re||ce,{allowed:he,loading:ge,error:xe}=(0,V.l)(J.J);(0,w.A)(async()=>{const e=await I.getBackstageIdentity();N(e.userEntityRef)},[I]);const{value:ve,loading:Ae,error:fe}=(0,w.A)(async()=>{const e=await a.fetch(`${T}/api/kuadrant/apiproducts`);if(!e.ok){const t=await(0,F.T)(e);throw new Error(`failed to fetch APIProducts. ${t}`)}return await e.json()},[T,a,D]),{value:ye,loading:je,error:be}=(0,w.A)(async()=>{if(!he)return{items:[]};const e=await a.fetch(`${T}/api/kuadrant/planpolicies`);if(!e.ok){const t=await(0,F.T)(e);throw new Error(`failed to fetch PlanPolicies: ${t}`)}return await e.json()},[T,a,D,he]),Pe=(0,n.useCallback)(e=>{var t;if(!(null==ye?void 0:ye.items))return null;const a=null===(t=e.spec)||void 0===t?void 0:t.targetRef;if(!a)return null;const s=ye.items.find(t=>{const s=t.targetRef;return"HTTPRoute"===(null==s?void 0:s.kind)&&(null==s?void 0:s.name)===a.name&&(!(null==s?void 0:s.namespace)||(null==s?void 0:s.namespace)===(a.namespace||e.metadata.namespace))});return(null==s?void 0:s.metadata.name)||null},[ye]),Se=(0,n.useCallback)(e=>{var t,a;const s=(null===(a=e.status)||void 0===a||null===(t=a.discoveredAuthScheme)||void 0===t?void 0:t.authentication)||{},n=Object.values(s),i=[];return n.some(e=>e.hasOwnProperty("apiKey"))&&i.push("API Key"),n.some(e=>e.hasOwnProperty("jwt"))&&i.push("OIDC"),0===i.length&&i.push("Unknown"),i},[]),we=Ae||je||ne||me||ge,ke=fe||be,Ie=ie||de||xe,Te=(0,n.useMemo)(()=>(null==ve?void 0:ve.items)||[],[ve]),Ce=(0,n.useMemo)(()=>{const e={Draft:0,Published:0},t=new Map,a=new Map,s=new Map,n=new Map,i=new Map;Te.forEach(l=>{var r,o,c,d;const u=(null===(r=l.spec)||void 0===r?void 0:r.publishStatus)||"Draft";e[u]++;const p=Pe(l)||"N/A";t.set(p,(t.get(p)||0)+1);const m=(null===(c=l.spec)||void 0===c||null===(o=c.targetRef)||void 0===o?void 0:o.name)||"unknown";a.set(m,(a.get(m)||0)+1);const h=l.metadata.namespace;s.set(h,(s.get(h)||0)+1),((null===(d=l.spec)||void 0===d?void 0:d.tags)||[]).forEach(e=>{n.set(e,(n.get(e)||0)+1)}),Se(l).forEach(e=>{i.set(e,(i.get(e)||0)+1)})});const l=[{id:"status",title:"Status",options:[{value:"Draft",label:"Draft",count:e.Draft},{value:"Published",label:"Published",count:e.Published}]},{id:"authentication",title:"Authentication",options:Array.from(i.entries()).map(([e,t])=>({value:e,label:e,count:t}))},{id:"route",title:"Route",options:Array.from(a.entries()).map(([e,t])=>({value:e,label:e,count:t})),collapsed:a.size>5},{id:"namespace",title:"Namespace",options:Array.from(s.entries()).map(([e,t])=>({value:e,label:e,count:t})),collapsed:s.size>5},{id:"tags",title:"Tags",options:Array.from(n.entries()).map(([e,t])=>({value:e,label:e,count:t})),collapsed:n.size>5}];return he&&l.splice(2,0,{id:"policy",title:"Policy",options:Array.from(t.entries()).map(([e,t])=>({value:e,label:e,count:t})),collapsed:t.size>5}),l},[Te,Pe,Se,he]),Ne=(0,n.useMemo)(()=>Te.filter(e=>{if(te.status.length>0){var t;const a=(null===(t=e.spec)||void 0===t?void 0:t.publishStatus)||"Draft";if(!te.status.includes(a))return!1}if(te.authentication.length>0){const t=Se(e);if(!te.authentication.some(e=>t.includes(e)))return!1}if(te.policy.length>0){const t=Pe(e)||"N/A";if(!te.policy.includes(t))return!1}if(te.route.length>0){var a,s;const t=(null===(s=e.spec)||void 0===s||null===(a=s.targetRef)||void 0===a?void 0:a.name)||"unknown";if(!te.route.includes(t))return!1}if(te.namespace.length>0&&!te.namespace.includes(e.metadata.namespace))return!1;if(te.tags.length>0){var n;const t=(null===(n=e.spec)||void 0===n?void 0:n.tags)||[];if(!te.tags.some(e=>t.includes(e)))return!1}return!0}),[Te,te,Pe,Se]),Re=[{title:"Name",field:"spec.displayName",render:e=>{var t,a;const n=null!==(a=null===(t=e.spec)||void 0===t?void 0:t.displayName)&&void 0!==a?a:e.metadata.name;return(0,s.jsx)(A.N_,{to:`/kuadrant/api-products/${e.metadata.namespace}/${e.metadata.name}`,children:(0,s.jsx)("strong",{children:n})})},customFilterAndSearch:(e,t)=>{var a;return((null===(a=t.spec)||void 0===a?void 0:a.displayName)||t.metadata.name||"").toLowerCase().includes(e.toLowerCase())}},{title:"Version",field:"spec.version",render:e=>{var t;return(null===(t=e.spec)||void 0===t?void 0:t.version)||"-"}},{title:"Route",field:"spec.targetRef.name",render:e=>{var t,a;return(null===(a=e.spec)||void 0===a||null===(t=a.targetRef)||void 0===t?void 0:t.name)||"-"}},...he?[{title:"Policy",field:"policy",render:e=>Pe(e)||"N/A"}]:[],{title:"Tags",field:"spec.tags",render:e=>{var t;const a=(null===(t=e.spec)||void 0===t?void 0:t.tags)||[];return 0===a.length?"-":(0,s.jsx)(l.A,{display:"flex",style:{gap:4,flexWrap:"wrap"},children:a.map(e=>(0,s.jsx)(r.A,{label:e,size:"small",variant:"outlined"},e))})}},{title:"Status",field:"spec.publishStatus",render:e=>{var t;const a=(null===(t=e.spec)||void 0===t?void 0:t.publishStatus)||"Draft";return(0,s.jsx)(r.A,{label:a,size:"small",color:"Published"===a?"primary":"default"})}},{title:"Authentication",field:"status.discoveredAuthScheme",render:e=>{var t,a;const n=(null===(a=e.status)||void 0===a||null===(t=a.discoveredAuthScheme)||void 0===t?void 0:t.authentication)||{},i=Object.values(n),c=i.some(e=>e.hasOwnProperty("apiKey")),d=i.some(e=>e.hasOwnProperty("jwt"));return c||d?(0,s.jsxs)(l.A,{display:"flex",style:{gap:4},children:[c&&(0,s.jsx)(r.A,{icon:(0,s.jsx)(g.A,{}),label:"API Key",size:"small",color:"primary"}),d&&(0,s.jsx)(r.A,{icon:(0,s.jsx)(x.A,{}),label:"OIDC",size:"small",color:"secondary"})]}):(0,s.jsx)(o.A,{variant:"body2",style:{fontStyle:"italic"},children:"unknown"})}},{title:"Namespace",field:"metadata.namespace"},{title:"Actions",field:"actions",filtering:!1,render:e=>{var t,n,r;const o=(null===(n=e.metadata)||void 0===n||null===(t=n.annotations)||void 0===t?void 0:t["backstage.io/owner"])===C,u=pe||ue&&o,p=oe||le&&o,g="Published"===(null===(r=e.spec)||void 0===r?void 0:r.publishStatus);return(0,s.jsxs)(l.A,{display:"flex",alignItems:"center",style:{gap:4},children:[u&&(0,s.jsx)(c.A,{size:"small",color:"primary",onClick:()=>(async e=>{var t,s;const n=e.metadata.namespace,l=e.metadata.name,r=(null===(t=e.spec)||void 0===t?void 0:t.displayName)||l,o="Published"===((null===(s=e.spec)||void 0===s?void 0:s.publishStatus)||"Draft")?"Draft":"Published";try{const e=await a.fetch(`${T}/api/kuadrant/apiproducts/${n}/${l}`,{method:"PATCH",headers:{"Content-Type":"application/json"},body:JSON.stringify({spec:{publishStatus:o}})});if(!e.ok){const t=await(0,F.T)(e);throw new Error(t)}H(e=>e+1),i.post({message:`"${r}" ${"Published"===o?"published":"unpublished"} successfully`,severity:"success",display:"transient"})}catch(e){const t=e instanceof Error?e.message:"unknown error occurred";i.post({message:`Failed to update publish status: ${t}`,severity:"error",display:"transient"})}})(e),style:{marginRight:4,textTransform:"none"},children:g?"Unpublish":"Publish"}),u&&(0,s.jsx)(d.A,{size:"small",onClick:()=>{return t=e.metadata.namespace,a=e.metadata.name,O({namespace:t,name:a}),void E(!0);var t,a},title:"Edit API Product",children:(0,s.jsx)(h.A,{fontSize:"small"})}),p&&(0,s.jsx)(d.A,{size:"small",onClick:()=>(async(e,t)=>{W({namespace:e,name:t}),ee(null);try{const s=await a.fetch(`${T}/api/kuadrant/requests?namespace=${e}`);if(!s.ok){const e=await(0,F.T)(s);throw new Error(e)}const n=((await s.json()).items||[]).filter(a=>a.spec.apiName===t&&a.spec.apiNamespace===e),i=n.filter(e=>{var t;return"Approved"===(null===(t=e.status)||void 0===t?void 0:t.phase)}).length;ee({requests:n.length,secrets:i})}catch(e){const t=e instanceof Error?e.message:"unknown error occurred";i.post({message:`Failed to delete access request: ${t}`,severity:"error",display:"transient"})}finally{q(!0)}})(e.metadata.namespace,e.metadata.name),title:"Delete API Product",children:(0,s.jsx)(m.A,{fontSize:"small"})})]})}}];return(0,s.jsxs)(f.Y,{themeId:"tool",children:[(0,s.jsx)(y.Y,{title:"API Products",subtitle:"Manage API products for Kubernetes",children:(0,s.jsx)(j.Y,{children:"Manage API products and plan policies"})}),(0,s.jsxs)(b.U,{children:[we&&(0,s.jsxs)(l.A,{display:"flex",flexDirection:"column",alignItems:"center",justifyContent:"center",minHeight:300,children:[(0,s.jsx)(u.A,{}),(0,s.jsx)(o.A,{variant:"h6",style:{marginTop:16},children:"Loading data..."}),(0,s.jsx)(o.A,{variant:"body2",color:"textSecondary",children:"Preparing your data... This should only take a moment."})]}),ke&&(0,s.jsx)(P._,{error:ke}),Ie&&(0,s.jsxs)(l.A,{p:2,children:[(0,s.jsxs)(o.A,{color:"error",children:["unable to check permissions: ",Ie.message]}),(0,s.jsxs)(o.A,{variant:"body2",color:"textSecondary",children:["permission:"," ",ie?"kuadrant.apiproduct.create":de?"kuadrant.apiproduct.delete":xe?"kuadrant.planpolicy.list":"unknown"]}),(0,s.jsx)(o.A,{variant:"body2",color:"textSecondary",children:"please try again or contact your administrator"})]}),!we&&!ke&&!Ie&&0===Te.length&&(0,s.jsx)(l.A,{className:e.emptyState,children:(0,s.jsxs)(l.A,{className:e.emptyStateContent,children:[(0,s.jsxs)(l.A,{className:e.emptyStateText,children:[(0,s.jsx)(o.A,{variant:"h4",className:e.emptyStateTitle,children:"API Product"}),(0,s.jsx)(o.A,{variant:"body1",className:e.emptyStateDescription,children:"Create API product by registering existing API, associate route and policy"}),se&&(0,s.jsx)(c.A,{variant:"contained",color:"primary",startIcon:(0,s.jsx)(p.A,{}),onClick:()=>$(!0),children:"Create API Product"})]}),(0,s.jsx)("img",{src:X,alt:"API Product illustration",className:e.emptyStateImage})]})}),!we&&!ke&&!Ie&&Te.length>0&&(0,s.jsxs)(l.A,{className:e.container,children:[(0,s.jsx)(v.Z,{sections:Ce,filters:te,onChange:ae}),(0,s.jsxs)(l.A,{className:e.tableContainer,children:[(0,s.jsx)(l.A,{display:"flex",justifyContent:"flex-end",mb:2,children:se&&(0,s.jsx)(c.A,{variant:"contained",color:"primary",size:"small",startIcon:(0,s.jsx)(p.A,{}),onClick:()=>$(!0),children:"Create API Product"})}),0===Ne.length?(0,s.jsx)(l.A,{p:4,textAlign:"center",children:(0,s.jsx)(o.A,{variant:"body1",color:"textSecondary",children:"No API products match the selected filters."})}):(0,s.jsx)(S.X,{options:{paging:Ne.length>10,pageSize:20,search:!0,filtering:!1,debounceInterval:300,toolbar:!0,emptyRowsWhenPaging:!1},columns:Re,data:Ne})]})]}),(0,s.jsx)(Y,{open:R,onClose:()=>$(!1),onSuccess:e=>{H(e=>e+1),i.post({message:`"${e.displayName}" created successfully`,severity:"success",display:"transient"})}}),(0,s.jsx)(G.C,{open:z,onClose:()=>E(!1),onSuccess:()=>{H(e=>e+1);const e=(null==K?void 0:K.name)||"API Product";i.post({message:`"${e}" updated successfully`,severity:"success",display:"transient"})},namespace:(null==K?void 0:K.namespace)||"",name:(null==K?void 0:K.name)||""}),(0,s.jsx)(Z.K,{open:L,title:"Delete API Product",description:_?`Deleting "${null==M?void 0:M.name}" will also remove:\n\n• ${_.requests} API Key(s)\n• ${_.secrets} API Key Secret(s)\n\nThis action cannot be undone.`:`Deleting "${null==M?void 0:M.name}" will also remove all associated API Keys and Secrets.\nThis action cannot be undone.`,confirmText:null==M?void 0:M.name,severity:"high",deleting:B,onConfirm:async()=>{if(M){U(!0);try{const e=await a.fetch(`${T}/api/kuadrant/apiproducts/${M.namespace}/${M.name}`,{method:"DELETE"});if(!e.ok){const t=await(0,F.T)(e);throw new Error(t)}const t=(null==M?void 0:M.name)||"API Product";H(e=>e+1),i.post({message:`"${t}" deleted successfully`,severity:"success",display:"transient"})}catch(e){const t=e instanceof Error?e.message:"unknown error occurred";i.post({message:`Failed to delete API Product: ${t}`,severity:"error",display:"transient"})}finally{U(!1),q(!1),W(null)}}},onCancel:()=>{q(!1),W(null)}})]})]})},te=()=>(0,s.jsx)(I.B,{permission:J.vs,errorMessage:"you don't have permission to view the Kuadrant page",children:(0,s.jsx)(ee,{})})}}]);
2
+ //# sourceMappingURL=2821.0829f14d.chunk.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"static/2821.0829f14d.chunk.js","mappings":"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","sources":["webpack://internal.plugin-kuadrant/./src/components/FilterPanel/FilterPanel.tsx","webpack://internal.plugin-kuadrant/./src/components/PermissionGate/PermissionGate.tsx","webpack://internal.plugin-kuadrant/./src/components/CreateAPIProductDialog/CreateAPIProductDialog.tsx","webpack://internal.plugin-kuadrant/./src/components/KuadrantPage/ApiProductsPage.tsx"],"sourcesContent":["import React from 'react';\nimport {\n Box,\n Typography,\n Checkbox,\n FormControlLabel,\n FormGroup,\n Divider,\n Button,\n Collapse,\n makeStyles,\n} from '@material-ui/core';\nimport ExpandMoreIcon from '@material-ui/icons/ExpandMore';\nimport ExpandLessIcon from '@material-ui/icons/ExpandLess';\n\nconst useStyles = makeStyles(theme => ({\n root: {\n width: 240,\n minWidth: 240,\n padding: theme.spacing(2),\n borderRight: `1px solid ${theme.palette.divider}`,\n backgroundColor: theme.palette.background.paper,\n height: '100%',\n overflowY: 'auto',\n },\n sectionTitle: {\n fontWeight: 600,\n fontSize: '0.75rem',\n textTransform: 'uppercase',\n letterSpacing: '0.05em',\n color: theme.palette.text.secondary,\n marginBottom: theme.spacing(1),\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'space-between',\n cursor: 'pointer',\n userSelect: 'none',\n },\n filterSection: {\n marginBottom: theme.spacing(2),\n },\n checkbox: {\n padding: theme.spacing(0.5),\n },\n checkboxLabel: {\n fontSize: '0.875rem',\n },\n clearButton: {\n marginTop: theme.spacing(2),\n },\n count: {\n fontSize: '0.75rem',\n color: theme.palette.text.secondary,\n marginLeft: theme.spacing(1),\n },\n}));\n\nexport interface FilterOption {\n value: string;\n label: string;\n count?: number;\n}\n\nexport interface FilterSection {\n id: string;\n title: string;\n options: FilterOption[];\n collapsed?: boolean;\n}\n\nexport interface FilterState {\n [sectionId: string]: string[];\n}\n\ninterface FilterPanelProps {\n sections: FilterSection[];\n filters: FilterState;\n onChange: (filters: FilterState) => void;\n onClear?: () => void;\n}\n\nexport const FilterPanel = ({\n sections,\n filters,\n onChange,\n onClear,\n}: FilterPanelProps) => {\n const classes = useStyles();\n const [collapsedSections, setCollapsedSections] = React.useState<Set<string>>(\n new Set(sections.filter(s => s.collapsed).map(s => s.id)),\n );\n\n const toggleSection = (sectionId: string) => {\n setCollapsedSections(prev => {\n const next = new Set(prev);\n if (next.has(sectionId)) {\n next.delete(sectionId);\n } else {\n next.add(sectionId);\n }\n return next;\n });\n };\n\n const handleCheckboxChange = (sectionId: string, value: string) => {\n const currentValues = filters[sectionId] || [];\n const newValues = currentValues.includes(value)\n ? currentValues.filter(v => v !== value)\n : [...currentValues, value];\n\n onChange({\n ...filters,\n [sectionId]: newValues,\n });\n };\n\n const hasActiveFilters = Object.values(filters).some(\n values => values.length > 0,\n );\n\n const handleClear = () => {\n const clearedFilters: FilterState = {};\n sections.forEach(section => {\n clearedFilters[section.id] = [];\n });\n onChange(clearedFilters);\n onClear?.();\n };\n\n return (\n <Box className={classes.root}>\n <Box display=\"flex\" justifyContent=\"space-between\" alignItems=\"center\" mb={2}>\n <Typography variant=\"subtitle2\">Filters</Typography>\n {hasActiveFilters && (\n <Button\n size=\"small\"\n color=\"primary\"\n onClick={handleClear}\n >\n Clear all\n </Button>\n )}\n </Box>\n\n <Divider />\n\n {sections.map(section => {\n const isCollapsed = collapsedSections.has(section.id);\n const selectedCount = (filters[section.id] || []).length;\n\n return (\n <Box key={section.id} className={classes.filterSection} mt={2}>\n <Box\n className={classes.sectionTitle}\n onClick={() => toggleSection(section.id)}\n >\n <Box display=\"flex\" alignItems=\"center\">\n <span>{section.title}</span>\n {selectedCount > 0 && (\n <span className={classes.count}>({selectedCount})</span>\n )}\n </Box>\n {isCollapsed ? (\n <ExpandMoreIcon fontSize=\"small\" />\n ) : (\n <ExpandLessIcon fontSize=\"small\" />\n )}\n </Box>\n\n <Collapse in={!isCollapsed}>\n <FormGroup>\n {section.options.map(option => (\n <FormControlLabel\n key={option.value}\n control={\n <Checkbox\n checked={(filters[section.id] || []).includes(option.value)}\n onChange={() =>\n handleCheckboxChange(section.id, option.value)\n }\n size=\"small\"\n className={classes.checkbox}\n color=\"primary\"\n />\n }\n label={\n <Box display=\"flex\" alignItems=\"center\">\n <span className={classes.checkboxLabel}>\n {option.label}\n </span>\n {option.count !== undefined && (\n <span className={classes.count}>({option.count})</span>\n )}\n </Box>\n }\n />\n ))}\n </FormGroup>\n </Collapse>\n </Box>\n );\n })}\n </Box>\n );\n};\n","import React from 'react';\nimport { Typography, Box } from '@material-ui/core';\nimport { Progress } from '@backstage/core-components';\nimport { Permission } from '@backstage/plugin-permission-common';\nimport { useKuadrantPermission } from '../../utils/permissions';\n\ninterface PermissionGateProps {\n children: React.ReactNode;\n permission: Permission;\n fallback?: React.ReactNode;\n errorMessage?: string;\n}\n\nexport const PermissionGate = ({ children, permission, fallback, errorMessage }: PermissionGateProps) => {\n const { allowed, loading, error } = useKuadrantPermission(permission);\n\n if (loading) {\n return <Progress />;\n }\n\n if (error) {\n return (\n <Box p={4}>\n <Typography color=\"error\">\n Unable to check permissions: {error.message}\n </Typography>\n <Typography variant=\"body2\" color=\"textSecondary\">\n Please try again or contact your administrator\n </Typography>\n </Box>\n );\n }\n\n if (!allowed) {\n if (fallback) {\n return <>{fallback}</>;\n }\n return (\n <Box p={4}>\n <Typography color=\"textSecondary\">\n {errorMessage || 'You don\\'t have permission to view this page'}\n </Typography>\n <Box mt={1}>\n <Typography variant=\"caption\" color=\"textSecondary\">\n Required permission: {permission.name}\n </Typography>\n </Box>\n </Box>\n );\n }\n\n return <>{children}</>;\n};\n","import React, { useEffect, useState } from 'react';\nimport {\n Dialog,\n DialogTitle,\n DialogContent,\n DialogActions,\n Button,\n TextField,\n Box,\n Typography,\n Chip,\n Grid,\n MenuItem,\n CircularProgress,\n makeStyles,\n FormControl,\n RadioGroup,\n FormControlLabel,\n Radio,\n Tooltip,\n IconButton,\n InputAdornment,\n} from '@material-ui/core';\nimport InfoOutlinedIcon from '@material-ui/icons/InfoOutlined';\nimport AddIcon from '@material-ui/icons/Add';\nimport { useApi, 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';\nimport { handleFetchError } from \"../../utils/errors\";\n\nconst useStyles = makeStyles((theme) => ({\n asterisk: {\n color: '#f44336',\n },\n sectionHeader: {\n display: 'flex',\n alignItems: 'center',\n gap: theme.spacing(0.5),\n marginTop: theme.spacing(2),\n marginBottom: theme.spacing(1),\n },\n infoIcon: {\n fontSize: 18,\n color: theme.palette.text.secondary,\n },\n tagChip: {\n marginRight: theme.spacing(0.5),\n marginBottom: theme.spacing(0.5),\n },\n}));\n\ninterface 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\n if (!response.ok) {\n const error = await handleFetchError(response);\n throw new Error(`failed to fetch routes. ${error}`);\n }\n\n const data = await response.json();\n return data.items || [];\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\n if (!response.ok) {\n const error = await handleFetchError(response);\n throw new Error(`failed to fetch PlanPolicies. ${error}`);\n }\n\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 error = await handleFetchError(response);\n throw new Error(`failed to create APIProduct. ${error}`);\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. 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 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 && selectedPolicy && (\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 discoveredPlans={selectedPolicy.plans}\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","import React, { useState, useMemo, useCallback } from \"react\";\nimport {\n Typography,\n Box,\n Chip,\n Button,\n IconButton,\n CircularProgress,\n makeStyles,\n} from \"@material-ui/core\";\nimport AddIcon from \"@material-ui/icons/Add\";\nimport DeleteIcon from \"@material-ui/icons/Delete\";\nimport EditIcon from \"@material-ui/icons/Edit\";\nimport VpnKeyIcon from \"@material-ui/icons/VpnKey\";\nimport LockIcon from \"@material-ui/icons/Lock\";\nimport { FilterPanel, FilterSection, FilterState } from \"../FilterPanel\";\nimport {\n Header,\n Page,\n Content,\n SupportButton,\n ResponseErrorPanel,\n Link,\n Table,\n TableColumn,\n} from \"@backstage/core-components\";\nimport useAsync from \"react-use/lib/useAsync\";\nimport {\n useApi,\n configApiRef,\n fetchApiRef,\n alertApiRef,\n identityApiRef,\n} from \"@backstage/core-plugin-api\";\nimport { PermissionGate } from \"../PermissionGate\";\nimport { CreateAPIProductDialog } from \"../CreateAPIProductDialog\";\nimport {\n kuadrantApiProductCreatePermission,\n kuadrantApiProductDeleteOwnPermission,\n kuadrantApiProductDeleteAllPermission,\n kuadrantApiProductUpdateOwnPermission,\n kuadrantApiProductUpdateAllPermission,\n kuadrantApiProductListPermission,\n kuadrantPlanPolicyListPermission,\n} from \"../../permissions\";\nimport { useKuadrantPermission } from \"../../utils/permissions\";\nimport { handleFetchError } from \"../../utils/errors\";\nimport { EditAPIProductDialog } from \"../EditAPIProductDialog\";\nimport { ConfirmDeleteDialog } from \"../ConfirmDeleteDialog\";\nimport emptyStateIllustration from \"../../assets/empty-state-illustration.png\";\n\ntype KuadrantResource = {\n metadata: {\n name: string;\n namespace: string;\n creationTimestamp: string;\n annotations?: Record<string, string>;\n };\n spec?: any;\n status?: any;\n};\n\ntype KuadrantList = {\n items: KuadrantResource[];\n};\n\nconst useStyles = makeStyles((theme) => ({\n container: {\n display: \"flex\",\n height: \"100%\",\n minHeight: 400,\n },\n tableContainer: {\n flex: 1,\n overflow: \"auto\",\n padding: 10,\n },\n emptyState: {\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n padding: theme.spacing(6),\n minHeight: 400,\n },\n emptyStateContent: {\n display: \"flex\",\n alignItems: \"center\",\n gap: theme.spacing(6),\n maxWidth: 900,\n },\n emptyStateText: {\n flex: 1,\n },\n emptyStateTitle: {\n marginBottom: theme.spacing(2),\n },\n emptyStateDescription: {\n marginBottom: theme.spacing(3),\n color: theme.palette.text.secondary,\n },\n emptyStateImage: {\n maxWidth: 400,\n height: \"auto\",\n },\n}));\n\nconst ResourceList = () => {\n const classes = useStyles();\n const config = useApi(configApiRef);\n const fetchApi = useApi(fetchApiRef);\n const alertApi = useApi(alertApiRef);\n const identityApi = useApi(identityApiRef);\n const backendUrl = config.getString(\"backend.baseUrl\");\n const [userEntityRef, setUserEntityRef] = useState<string>(\"\");\n const [createDialogOpen, setCreateDialogOpen] = useState(false);\n const [editDialogOpen, setEditDialogOpen] = useState(false);\n const [refreshTrigger, setRefreshTrigger] = useState(0);\n const [deleteDialogOpen, setDeleteDialogOpen] = useState(false);\n const [apiProductToDelete, setApiProductToDelete] = useState<{\n namespace: string;\n name: string;\n } | null>(null);\n const [apiProductToEdit, setApiProductToEdit] = useState<{\n namespace: string;\n name: string;\n } | null>(null);\n const [deleting, setDeleting] = useState(false);\n const [deleteStats, setDeleteStats] = useState<{\n requests: number;\n secrets: number;\n } | null>(null);\n const [filters, setFilters] = useState<FilterState>({\n status: [],\n policy: [],\n route: [],\n namespace: [],\n tags: [],\n authentication: [],\n });\n\n const {\n allowed: canCreateApiProduct,\n loading: createPermissionLoading,\n error: createPermissionError,\n } = useKuadrantPermission(kuadrantApiProductCreatePermission);\n\n const {\n allowed: canDeleteOwnApiProduct,\n loading: deleteOwnPermissionLoading,\n } = useKuadrantPermission(kuadrantApiProductDeleteOwnPermission);\n\n const {\n allowed: canDeleteAllApiProducts,\n loading: deleteAllPermissionLoading,\n error: deletePermissionError,\n } = useKuadrantPermission(kuadrantApiProductDeleteAllPermission);\n\n const { allowed: canUpdateOwnApiProduct } = useKuadrantPermission(\n kuadrantApiProductUpdateOwnPermission,\n );\n\n const { allowed: canUpdateAllApiProducts } = useKuadrantPermission(\n kuadrantApiProductUpdateAllPermission,\n );\n\n const deletePermissionLoading =\n deleteOwnPermissionLoading || deleteAllPermissionLoading;\n\n const {\n allowed: canListPlanPolicies,\n loading: planPolicyPermissionLoading,\n error: planPolicyPermissionError,\n } = useKuadrantPermission(kuadrantPlanPolicyListPermission);\n\n useAsync(async () => {\n const identity = await identityApi.getBackstageIdentity();\n setUserEntityRef(identity.userEntityRef);\n }, [identityApi]);\n\n const {\n value: apiProducts,\n loading: apiProductsLoading,\n error: apiProductsError,\n } = useAsync(async (): Promise<KuadrantList> => {\n const response = await fetchApi.fetch(\n `${backendUrl}/api/kuadrant/apiproducts`,\n );\n if (!response.ok) {\n const error = await handleFetchError(response);\n throw new Error(`failed to fetch APIProducts. ${error}`);\n }\n return await response.json();\n }, [backendUrl, fetchApi, refreshTrigger]);\n\n const {\n value: planPolicies,\n loading: planPoliciesLoading,\n error: planPoliciesError,\n } = useAsync(async (): Promise<KuadrantList> => {\n // skip fetch if user doesn't have permission\n if (!canListPlanPolicies) {\n return { items: [] };\n }\n const response = await fetchApi.fetch(\n `${backendUrl}/api/kuadrant/planpolicies`,\n );\n if (!response.ok) {\n const error = await handleFetchError(response);\n throw new Error(`failed to fetch PlanPolicies: ${error}`);\n }\n return await response.json();\n }, [backendUrl, fetchApi, refreshTrigger, canListPlanPolicies]);\n\n // helper to find policy for a given route\n const getPolicyForProduct = useCallback((product: KuadrantResource): string | null => {\n if (!planPolicies?.items) return null;\n const targetRef = product.spec?.targetRef;\n if (!targetRef) return null;\n\n const policy = planPolicies.items.find((pp: KuadrantResource) => {\n const ref = (pp as any).targetRef;\n return (\n ref?.kind === \"HTTPRoute\" &&\n ref?.name === targetRef.name &&\n (!ref?.namespace || ref?.namespace === (targetRef.namespace || product.metadata.namespace))\n );\n });\n return policy?.metadata.name || null;\n }, [planPolicies]);\n\n // helper to get auth schemes for a product\n const getAuthSchemes = useCallback((product: KuadrantResource): string[] => {\n const authSchemes = product.status?.discoveredAuthScheme?.authentication || {};\n const schemeObjects = Object.values(authSchemes);\n const schemes: string[] = [];\n\n if (schemeObjects.some((scheme: any) => scheme.hasOwnProperty(\"apiKey\"))) {\n schemes.push(\"API Key\");\n }\n if (schemeObjects.some((scheme: any) => scheme.hasOwnProperty(\"jwt\"))) {\n schemes.push(\"OIDC\");\n }\n if (schemes.length === 0) {\n schemes.push(\"Unknown\");\n }\n return schemes;\n }, []);\n\n const loading =\n apiProductsLoading ||\n planPoliciesLoading ||\n createPermissionLoading ||\n deletePermissionLoading ||\n planPolicyPermissionLoading;\n const error = apiProductsError || planPoliciesError;\n const permissionError =\n createPermissionError || deletePermissionError || planPolicyPermissionError;\n\n const allProducts = useMemo(() => {\n return apiProducts?.items || [];\n }, [apiProducts]);\n\n const filterSections: FilterSection[] = useMemo(() => {\n const statusCounts = { Draft: 0, Published: 0 };\n const policyCounts = new Map<string, number>();\n const routeCounts = new Map<string, number>();\n const namespaceCounts = new Map<string, number>();\n const tagCounts = new Map<string, number>();\n const authCounts = new Map<string, number>();\n\n allProducts.forEach((p: KuadrantResource) => {\n const status = p.spec?.publishStatus || \"Draft\";\n statusCounts[status as keyof typeof statusCounts]++;\n\n const policy = getPolicyForProduct(p) || \"N/A\";\n policyCounts.set(policy, (policyCounts.get(policy) || 0) + 1);\n\n const route = p.spec?.targetRef?.name || \"unknown\";\n routeCounts.set(route, (routeCounts.get(route) || 0) + 1);\n\n const ns = p.metadata.namespace;\n namespaceCounts.set(ns, (namespaceCounts.get(ns) || 0) + 1);\n\n const tags = p.spec?.tags || [];\n tags.forEach((tag: string) => {\n tagCounts.set(tag, (tagCounts.get(tag) || 0) + 1);\n });\n\n const authSchemes = getAuthSchemes(p);\n authSchemes.forEach((scheme: string) => {\n authCounts.set(scheme, (authCounts.get(scheme) || 0) + 1);\n });\n });\n\n const sections: FilterSection[] = [\n {\n id: \"status\",\n title: \"Status\",\n options: [\n { value: \"Draft\", label: \"Draft\", count: statusCounts.Draft },\n { value: \"Published\", label: \"Published\", count: statusCounts.Published },\n ],\n },\n {\n id: \"authentication\",\n title: \"Authentication\",\n options: Array.from(authCounts.entries()).map(([scheme, count]) => ({\n value: scheme,\n label: scheme,\n count,\n })),\n },\n {\n id: \"route\",\n title: \"Route\",\n options: Array.from(routeCounts.entries()).map(([name, count]) => ({\n value: name,\n label: name,\n count,\n })),\n collapsed: routeCounts.size > 5,\n },\n {\n id: \"namespace\",\n title: \"Namespace\",\n options: Array.from(namespaceCounts.entries()).map(([ns, count]) => ({\n value: ns,\n label: ns,\n count,\n })),\n collapsed: namespaceCounts.size > 5,\n },\n {\n id: \"tags\",\n title: \"Tags\",\n options: Array.from(tagCounts.entries()).map(([tag, count]) => ({\n value: tag,\n label: tag,\n count,\n })),\n collapsed: tagCounts.size > 5,\n },\n ];\n\n // only show policy filter if user can list planpolicies\n if (canListPlanPolicies) {\n sections.splice(2, 0, {\n id: \"policy\",\n title: \"Policy\",\n options: Array.from(policyCounts.entries()).map(([name, count]) => ({\n value: name,\n label: name,\n count,\n })),\n collapsed: policyCounts.size > 5,\n });\n }\n\n return sections;\n }, [allProducts, getPolicyForProduct, getAuthSchemes, canListPlanPolicies]);\n\n const filteredProducts = useMemo(() => {\n return allProducts.filter((p: KuadrantResource) => {\n if (filters.status.length > 0) {\n const status = p.spec?.publishStatus || \"Draft\";\n if (!filters.status.includes(status)) return false;\n }\n\n if (filters.authentication.length > 0) {\n const authSchemes = getAuthSchemes(p);\n if (!filters.authentication.some((a: string) => authSchemes.includes(a))) return false;\n }\n\n if (filters.policy.length > 0) {\n const policy = getPolicyForProduct(p) || \"N/A\";\n if (!filters.policy.includes(policy)) return false;\n }\n\n if (filters.route.length > 0) {\n const route = p.spec?.targetRef?.name || \"unknown\";\n if (!filters.route.includes(route)) return false;\n }\n\n if (filters.namespace.length > 0) {\n if (!filters.namespace.includes(p.metadata.namespace)) return false;\n }\n\n if (filters.tags.length > 0) {\n const tags = p.spec?.tags || [];\n if (!filters.tags.some((t: string) => tags.includes(t))) return false;\n }\n\n return true;\n });\n }, [allProducts, filters, getPolicyForProduct, getAuthSchemes]);\n\n const handleCreateSuccess = (productInfo: { namespace: string; name: string; displayName: string }) => {\n setRefreshTrigger((prev) => prev + 1);\n alertApi.post({\n message: `\"${productInfo.displayName}\" created successfully`,\n severity: \"success\",\n display: \"transient\",\n });\n };\n\n const handleEditClick = (namespace: string, name: string) => {\n setApiProductToEdit({ namespace, name });\n setEditDialogOpen(true);\n };\n\n const handleEditSuccess = () => {\n setRefreshTrigger((prev) => prev + 1);\n const productName = apiProductToEdit?.name || \"API Product\";\n alertApi.post({\n message: `\"${productName}\" updated successfully`,\n severity: \"success\",\n display: \"transient\",\n });\n };\n\n const handleDeleteClick = async (namespace: string, name: string) => {\n setApiProductToDelete({ namespace, name });\n setDeleteStats(null);\n\n try {\n const response = await fetchApi.fetch(\n `${backendUrl}/api/kuadrant/requests?namespace=${namespace}`,\n );\n\n if (!response.ok) {\n const error = await handleFetchError(response);\n throw new Error(error);\n }\n\n const data = await response.json();\n const related = (data.items || []).filter(\n (r: any) =>\n r.spec.apiName === name && r.spec.apiNamespace === namespace,\n );\n const approved = related.filter(\n (r: any) => r.status?.phase === \"Approved\",\n ).length;\n setDeleteStats({ requests: related.length, secrets: approved });\n } catch (err) {\n const errorMessage =\n err instanceof Error ? err.message : \"unknown error occurred\";\n alertApi.post({\n message: `Failed to delete access request: ${errorMessage}`,\n severity: \"error\",\n display: \"transient\",\n });\n } finally {\n setDeleteDialogOpen(true);\n }\n\n };\n\n const handleDeleteConfirm = async () => {\n if (!apiProductToDelete) return;\n\n setDeleting(true);\n try {\n const response = await fetchApi.fetch(\n `${backendUrl}/api/kuadrant/apiproducts/${apiProductToDelete.namespace}/${apiProductToDelete.name}`,\n { method: \"DELETE\" },\n );\n\n if (!response.ok) {\n const error = await handleFetchError(response);\n throw new Error(error);\n }\n\n const deletedName = apiProductToDelete?.name || \"API Product\";\n setRefreshTrigger((prev) => prev + 1);\n alertApi.post({\n message: `\"${deletedName}\" deleted successfully`,\n severity: \"success\",\n display: \"transient\",\n });\n } catch (err) {\n const errorMessage =\n err instanceof Error ? err.message : \"unknown error occurred\";\n alertApi.post({\n message: `Failed to delete API Product: ${errorMessage}`,\n severity: \"error\",\n display: \"transient\",\n });\n } finally {\n setDeleting(false);\n setDeleteDialogOpen(false);\n setApiProductToDelete(null);\n }\n };\n\n const handleDeleteCancel = () => {\n setDeleteDialogOpen(false);\n setApiProductToDelete(null);\n };\n\n const handlePublishToggle = async (row: any) => {\n const namespace = row.metadata.namespace;\n const name = row.metadata.name;\n const displayName = row.spec?.displayName || name;\n const currentStatus = row.spec?.publishStatus || \"Draft\";\n const newStatus = currentStatus === \"Published\" ? \"Draft\" : \"Published\";\n\n try {\n const response = await fetchApi.fetch(\n `${backendUrl}/api/kuadrant/apiproducts/${namespace}/${name}`,\n {\n method: \"PATCH\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n spec: { publishStatus: newStatus },\n }),\n },\n );\n\n if (!response.ok) {\n const error = await handleFetchError(response);\n throw new Error(error);\n }\n\n setRefreshTrigger((prev) => prev + 1);\n alertApi.post({\n message: `\"${displayName}\" ${newStatus === \"Published\" ? \"published\" : \"unpublished\"} successfully`,\n severity: \"success\",\n display: \"transient\",\n });\n } catch (err) {\n const errorMessage =\n err instanceof Error ? err.message : \"unknown error occurred\";\n alertApi.post({\n message: `Failed to update publish status: ${errorMessage}`,\n severity: \"error\",\n display: \"transient\",\n });\n }\n };\n\n const columns: TableColumn[] = [\n {\n title: \"Name\",\n field: \"spec.displayName\",\n render: (row: any) => {\n const displayName = row.spec?.displayName ?? row.metadata.name;\n return (\n <Link to={`/kuadrant/api-products/${row.metadata.namespace}/${row.metadata.name}`}>\n <strong>{displayName}</strong>\n </Link>\n );\n },\n customFilterAndSearch: (term, row: any) => {\n const displayName = row.spec?.displayName || row.metadata.name || \"\";\n return displayName.toLowerCase().includes(term.toLowerCase());\n },\n },\n {\n title: \"Version\",\n field: \"spec.version\",\n render: (row: any) => row.spec?.version || \"-\",\n },\n {\n title: \"Route\",\n field: \"spec.targetRef.name\",\n render: (row: any) => row.spec?.targetRef?.name || \"-\",\n },\n // only show policy column if user can list planpolicies\n ...(canListPlanPolicies\n ? [\n {\n title: \"Policy\",\n field: \"policy\",\n render: (row: any) => getPolicyForProduct(row) || \"N/A\",\n },\n ]\n : []),\n {\n title: \"Tags\",\n field: \"spec.tags\",\n render: (row: any) => {\n const tags = row.spec?.tags || [];\n if (tags.length === 0) return \"-\";\n return (\n <Box display=\"flex\" style={{ gap: 4, flexWrap: \"wrap\" }}>\n {tags.map((tag: string) => (\n <Chip key={tag} label={tag} size=\"small\" variant=\"outlined\" />\n ))}\n </Box>\n );\n },\n },\n {\n title: \"Status\",\n field: \"spec.publishStatus\",\n render: (row: any) => {\n const status = row.spec?.publishStatus || \"Draft\";\n return (\n <Chip\n label={status}\n size=\"small\"\n color={status === \"Published\" ? \"primary\" : \"default\"}\n />\n );\n },\n },\n {\n title: \"Authentication\",\n field: \"status.discoveredAuthScheme\",\n render: (row: any) => {\n const authSchemes =\n row.status?.discoveredAuthScheme?.authentication || {};\n const schemeObjects = Object.values(authSchemes);\n\n const hasApiKey = schemeObjects.some((scheme: any) =>\n scheme.hasOwnProperty(\"apiKey\"),\n );\n const hasJwt = schemeObjects.some((scheme: any) =>\n scheme.hasOwnProperty(\"jwt\"),\n );\n\n if (!hasApiKey && !hasJwt) {\n return (\n <Typography variant=\"body2\" style={{ fontStyle: \"italic\" }}>\n unknown\n </Typography>\n );\n }\n\n return (\n <Box display=\"flex\" style={{ gap: 4 }}>\n {hasApiKey && (\n <Chip\n icon={<VpnKeyIcon />}\n label=\"API Key\"\n size=\"small\"\n color=\"primary\"\n />\n )}\n {hasJwt && (\n <Chip\n icon={<LockIcon />}\n label=\"OIDC\"\n size=\"small\"\n color=\"secondary\"\n />\n )}\n </Box>\n );\n },\n },\n {\n title: \"Namespace\",\n field: \"metadata.namespace\",\n },\n {\n title: \"Actions\",\n field: \"actions\",\n filtering: false,\n render: (row: any) => {\n const owner = row.metadata?.annotations?.[\"backstage.io/owner\"];\n const isOwner = owner === userEntityRef;\n const canEdit =\n canUpdateAllApiProducts || (canUpdateOwnApiProduct && isOwner);\n const canDelete =\n canDeleteAllApiProducts || (canDeleteOwnApiProduct && isOwner);\n const isPublished = row.spec?.publishStatus === \"Published\";\n\n return (\n <Box display=\"flex\" alignItems=\"center\" style={{ gap: 4 }}>\n {canEdit && (\n <Button\n size=\"small\"\n color=\"primary\"\n onClick={() => handlePublishToggle(row)}\n style={{ marginRight: 4, textTransform: \"none\" }}\n >\n {isPublished ? \"Unpublish\" : \"Publish\"}\n </Button>\n )}\n {canEdit && (\n <IconButton\n size=\"small\"\n onClick={() =>\n handleEditClick(row.metadata.namespace, row.metadata.name)\n }\n title=\"Edit API Product\"\n >\n <EditIcon fontSize=\"small\" />\n </IconButton>\n )}\n {canDelete && (\n <IconButton\n size=\"small\"\n onClick={() =>\n handleDeleteClick(row.metadata.namespace, row.metadata.name)\n }\n title=\"Delete API Product\"\n >\n <DeleteIcon fontSize=\"small\" />\n </IconButton>\n )}\n </Box>\n );\n },\n },\n ];\n\n return (\n <Page themeId=\"tool\">\n <Header\n title=\"API Products\"\n subtitle=\"Manage API products for Kubernetes\"\n >\n <SupportButton>Manage API products and plan policies</SupportButton>\n </Header>\n <Content>\n {loading && (\n <Box\n display=\"flex\"\n flexDirection=\"column\"\n alignItems=\"center\"\n justifyContent=\"center\"\n minHeight={300}\n >\n <CircularProgress />\n <Typography variant=\"h6\" style={{ marginTop: 16 }}>\n Loading data...\n </Typography>\n <Typography variant=\"body2\" color=\"textSecondary\">\n Preparing your data... This should only take a moment.\n </Typography>\n </Box>\n )}\n {error && <ResponseErrorPanel error={error} />}\n {permissionError && (\n <Box p={2}>\n <Typography color=\"error\">\n unable to check permissions: {permissionError.message}\n </Typography>\n <Typography variant=\"body2\" color=\"textSecondary\">\n permission:{\" \"}\n {createPermissionError\n ? \"kuadrant.apiproduct.create\"\n : deletePermissionError\n ? \"kuadrant.apiproduct.delete\"\n : planPolicyPermissionError\n ? \"kuadrant.planpolicy.list\"\n : \"unknown\"}\n </Typography>\n <Typography variant=\"body2\" color=\"textSecondary\">\n please try again or contact your administrator\n </Typography>\n </Box>\n )}\n {!loading && !error && !permissionError && allProducts.length === 0 && (\n <Box className={classes.emptyState}>\n <Box className={classes.emptyStateContent}>\n <Box className={classes.emptyStateText}>\n <Typography variant=\"h4\" className={classes.emptyStateTitle}>\n API Product\n </Typography>\n <Typography\n variant=\"body1\"\n className={classes.emptyStateDescription}\n >\n Create API product by registering existing API, associate\n route and policy\n </Typography>\n {canCreateApiProduct && (\n <Button\n variant=\"contained\"\n color=\"primary\"\n startIcon={<AddIcon />}\n onClick={() => setCreateDialogOpen(true)}\n >\n Create API Product\n </Button>\n )}\n </Box>\n <img\n src={emptyStateIllustration}\n alt=\"API Product illustration\"\n className={classes.emptyStateImage}\n />\n </Box>\n </Box>\n )}\n {!loading && !error && !permissionError && allProducts.length > 0 && (\n <Box className={classes.container}>\n <FilterPanel\n sections={filterSections}\n filters={filters}\n onChange={setFilters}\n />\n <Box className={classes.tableContainer}>\n <Box display=\"flex\" justifyContent=\"flex-end\" mb={2}>\n {canCreateApiProduct && (\n <Button\n variant=\"contained\"\n color=\"primary\"\n size=\"small\"\n startIcon={<AddIcon />}\n onClick={() => setCreateDialogOpen(true)}\n >\n Create API Product\n </Button>\n )}\n </Box>\n {filteredProducts.length === 0 ? (\n <Box p={4} textAlign=\"center\">\n <Typography variant=\"body1\" color=\"textSecondary\">\n No API products match the selected filters.\n </Typography>\n </Box>\n ) : (\n <Table\n options={{\n paging: filteredProducts.length > 10,\n pageSize: 20,\n search: true,\n filtering: false,\n debounceInterval: 300,\n toolbar: true,\n emptyRowsWhenPaging: false,\n }}\n columns={columns}\n data={filteredProducts}\n />\n )}\n </Box>\n </Box>\n )}\n <CreateAPIProductDialog\n open={createDialogOpen}\n onClose={() => setCreateDialogOpen(false)}\n onSuccess={handleCreateSuccess}\n />\n <EditAPIProductDialog\n open={editDialogOpen}\n onClose={() => setEditDialogOpen(false)}\n onSuccess={handleEditSuccess}\n namespace={apiProductToEdit?.namespace || \"\"}\n name={apiProductToEdit?.name || \"\"}\n />\n <ConfirmDeleteDialog\n open={deleteDialogOpen}\n title=\"Delete API Product\"\n description={\n deleteStats\n ? `Deleting \"${apiProductToDelete?.name}\" will also remove:\n\n• ${deleteStats.requests} API Key(s)\n• ${deleteStats.secrets} API Key Secret(s)\n\nThis action cannot be undone.`\n : `Deleting \"${apiProductToDelete?.name}\" will also remove all associated API Keys and Secrets.\nThis action cannot be undone.`\n }\n confirmText={apiProductToDelete?.name}\n severity=\"high\"\n deleting={deleting}\n onConfirm={handleDeleteConfirm}\n onCancel={handleDeleteCancel}\n />\n </Content>\n </Page>\n );\n};\n\nexport const ApiProductsPage = () => {\n return (\n <PermissionGate\n permission={kuadrantApiProductListPermission}\n errorMessage=\"you don't have permission to view the Kuadrant page\"\n >\n <ResourceList />\n </PermissionGate>\n );\n};\n"],"names":["useStyles","makeStyles","theme","root","width","minWidth","padding","spacing","borderRight","palette","divider","backgroundColor","background","paper","height","overflowY","sectionTitle","fontWeight","fontSize","textTransform","letterSpacing","color","text","secondary","marginBottom","display","alignItems","justifyContent","cursor","userSelect","filterSection","checkbox","checkboxLabel","clearButton","marginTop","count","marginLeft","FilterPanel","sections","filters","onChange","onClear","classes","collapsedSections","setCollapsedSections","React","Set","filter","s","collapsed","map","id","hasActiveFilters","Object","values","some","length","Box","className","mb","Typography","variant","Button","size","onClick","clearedFilters","forEach","section","Divider","isCollapsed","has","selectedCount","mt","toggleSection","sectionId","prev","next","delete","add","span","title","ExpandMoreIcon","ExpandLessIcon","Collapse","in","FormGroup","options","option","FormControlLabel","control","Checkbox","checked","includes","value","currentValues","newValues","v","handleCheckboxChange","label","undefined","PermissionGate","children","permission","fallback","errorMessage","allowed","loading","error","useKuadrantPermission","Progress","p","message","name","asterisk","sectionHeader","gap","infoIcon","tagChip","marginRight","CreateAPIProductDialog","open","onClose","onSuccess","config","useApi","configApiRef","fetchApi","fetchApiRef","backendUrl","getString","setName","useState","displayName","setDisplayName","description","setDescription","version","setVersion","approvalMode","setApprovalMode","publishStatus","setPublishStatus","tags","setTags","tagInput","setTagInput","selectedHTTPRoute","setSelectedHTTPRoute","contactEmail","setContactEmail","contactTeam","setContactTeam","docsURL","setDocsURL","openAPISpec","setOpenAPISpec","setError","creating","setCreating","httpRoutesRetry","setHttpRoutesRetry","nameError","setNameError","openAPISpecError","setOpenAPISpecError","httpRoutes","httpRoutesLoading","httpRoutesError","useAsync","async","response","fetch","ok","handleFetchError","Error","json","items","planPolicies","planPoliciesError","getPlanPolicyForRoute","routeNamespace","routeName","find","pp","ref","targetRef","kind","namespace","selectedRouteInfo","split","selectedPolicy","useEffect","handleAddTag","trim","handleClose","hasValidationErrors","Dialog","maxWidth","fullWidth","DialogTitle","DialogContent","Alert","severity","style","strong","Grid","container","item","xs","TextField","e","target","placeholder","helperText","margin","required","disabled","InputLabelProps","handleNameChange","validateKubernetesName","onKeyPress","key","preventDefault","InputProps","endAdornment","InputAdornment","position","IconButton","AddIcon","flexWrap","tag","Chip","onDelete","handleDeleteTag","tagToDelete","multiline","rows","Tooltip","InfoOutlinedIcon","handleOpenAPISpecChange","validateURL","select","SelectProps","MenuItem","route","routeNs","metadata","policyInfo","policy","spec","plans","tiers","entries","plan","limit","limits","requests","period","join","formatTierInfo","getPolicyInfoForRoute","PlanPolicyDetails","discoveredPlans","alertSeverity","alertMessage","includeTopMargin","FormControl","component","RadioGroup","row","Radio","DialogActions","selectedRouteNamespace","selectedRouteName","apiProduct","apiVersion","group","contact","email","team","documentation","openAPISpecURL","method","headers","body","JSON","stringify","err","String","startIcon","CircularProgress","minHeight","tableContainer","flex","overflow","emptyState","emptyStateContent","emptyStateText","emptyStateTitle","emptyStateDescription","emptyStateImage","ResourceList","alertApi","alertApiRef","identityApi","identityApiRef","userEntityRef","setUserEntityRef","createDialogOpen","setCreateDialogOpen","editDialogOpen","setEditDialogOpen","refreshTrigger","setRefreshTrigger","deleteDialogOpen","setDeleteDialogOpen","apiProductToDelete","setApiProductToDelete","apiProductToEdit","setApiProductToEdit","deleting","setDeleting","deleteStats","setDeleteStats","setFilters","status","authentication","canCreateApiProduct","createPermissionLoading","createPermissionError","kuadrantApiProductCreatePermission","canDeleteOwnApiProduct","deleteOwnPermissionLoading","kuadrantApiProductDeleteOwnPermission","canDeleteAllApiProducts","deleteAllPermissionLoading","deletePermissionError","kuadrantApiProductDeleteAllPermission","canUpdateOwnApiProduct","kuadrantApiProductUpdateOwnPermission","canUpdateAllApiProducts","kuadrantApiProductUpdateAllPermission","deletePermissionLoading","canListPlanPolicies","planPolicyPermissionLoading","planPolicyPermissionError","kuadrantPlanPolicyListPermission","identity","getBackstageIdentity","apiProducts","apiProductsLoading","apiProductsError","planPoliciesLoading","getPolicyForProduct","useCallback","product","getAuthSchemes","authSchemes","discoveredAuthScheme","schemeObjects","schemes","scheme","hasOwnProperty","push","permissionError","allProducts","useMemo","filterSections","statusCounts","Draft","Published","policyCounts","Map","routeCounts","namespaceCounts","tagCounts","authCounts","set","get","ns","Array","from","splice","filteredProducts","a","t","columns","field","render","Link","to","customFilterAndSearch","term","toLowerCase","hasApiKey","hasJwt","icon","VpnKeyIcon","LockIcon","fontStyle","filtering","isOwner","annotations","canEdit","canDelete","isPublished","newStatus","post","handlePublishToggle","handleEditClick","EditIcon","related","r","apiName","apiNamespace","approved","phase","secrets","handleDeleteClick","DeleteIcon","Page","themeId","Header","subtitle","SupportButton","Content","flexDirection","ResponseErrorPanel","img","src","emptyStateIllustration","alt","textAlign","Table","paging","pageSize","search","debounceInterval","toolbar","emptyRowsWhenPaging","data","productInfo","EditAPIProductDialog","productName","ConfirmDeleteDialog","confirmText","onConfirm","deletedName","onCancel","ApiProductsPage","kuadrantApiProductListPermission"],"sourceRoot":""}
@@ -0,0 +1,2 @@
1
+ "use strict";(self.webpackChunkinternal_plugin_kuadrant=self.webpackChunkinternal_plugin_kuadrant||[]).push([[4682],{5030:(e,t,n)=>{Object.defineProperty(t,"__esModule",{value:!0});var a=n(85608),s=n(95478),r=a.__importDefault(n(10009));t.default=function(e,t,n){void 0===t&&(t=[]),void 0===n&&(n={loading:!1});var i=s.useRef(0),o=r.default(),l=s.useState(n),c=l[0],d=l[1],u=s.useCallback(function(){for(var t=[],n=0;n<arguments.length;n++)t[n]=arguments[n];var s=++i.current;return c.loading||d(function(e){return a.__assign(a.__assign({},e),{loading:!0})}),e.apply(void 0,t).then(function(e){return o()&&s===i.current&&d({value:e,loading:!1}),e},function(e){return o()&&s===i.current&&d({error:e,loading:!1}),e})},t);return[c,u]}},10009:(e,t,n)=>{Object.defineProperty(t,"__esModule",{value:!0});var a=n(95478);t.default=function(){var e=a.useRef(!1),t=a.useCallback(function(){return e.current},[]);return a.useEffect(function(){return e.current=!0,function(){e.current=!1}},[]),t}},12229:(e,t,n)=>{n.d(t,{Z:()=>A});var a=n(31085),s=n(95478),r=n.n(s),i=n(10394),o=n(72501),l=n(64947),c=n(37197),d=n(69621),u=n(12981),p=n(86901),m=n(69076),h=n(58837),g=n(6924),v=n(23164);const x=(0,h.A)(e=>({root:{width:240,minWidth:240,padding:e.spacing(2),borderRight:`1px solid ${e.palette.divider}`,backgroundColor:e.palette.background.paper,height:"100%",overflowY:"auto"},sectionTitle:{fontWeight:600,fontSize:"0.75rem",textTransform:"uppercase",letterSpacing:"0.05em",color:e.palette.text.secondary,marginBottom:e.spacing(1),display:"flex",alignItems:"center",justifyContent:"space-between",cursor:"pointer",userSelect:"none"},filterSection:{marginBottom:e.spacing(2)},checkbox:{padding:e.spacing(.5)},checkboxLabel:{fontSize:"0.875rem"},clearButton:{marginTop:e.spacing(2)},count:{fontSize:"0.75rem",color:e.palette.text.secondary,marginLeft:e.spacing(1)}})),A=({sections:e,filters:t,onChange:n,onClear:s})=>{const h=x(),[A,f]=r().useState(new Set(e.filter(e=>e.collapsed).map(e=>e.id))),j=Object.values(t).some(e=>e.length>0);return(0,a.jsxs)(i.A,{className:h.root,children:[(0,a.jsxs)(i.A,{display:"flex",justifyContent:"space-between",alignItems:"center",mb:2,children:[(0,a.jsx)(o.A,{variant:"subtitle2",children:"Filters"}),j&&(0,a.jsx)(l.A,{size:"small",color:"primary",onClick:()=>{const t={};e.forEach(e=>{t[e.id]=[]}),n(t),null==s||s()},children:"Clear all"})]}),(0,a.jsx)(c.A,{}),e.map(e=>{const s=A.has(e.id),r=(t[e.id]||[]).length;return(0,a.jsxs)(i.A,{className:h.filterSection,mt:2,children:[(0,a.jsxs)(i.A,{className:h.sectionTitle,onClick:()=>{return t=e.id,void f(e=>{const n=new Set(e);return n.has(t)?n.delete(t):n.add(t),n});var t},children:[(0,a.jsxs)(i.A,{display:"flex",alignItems:"center",children:[(0,a.jsx)("span",{children:e.title}),r>0&&(0,a.jsxs)("span",{className:h.count,children:["(",r,")"]})]}),s?(0,a.jsx)(g.A,{fontSize:"small"}):(0,a.jsx)(v.A,{fontSize:"small"})]}),(0,a.jsx)(d.A,{in:!s,children:(0,a.jsx)(u.A,{children:e.options.map(s=>(0,a.jsx)(p.A,{control:(0,a.jsx)(m.A,{checked:(t[e.id]||[]).includes(s.value),onChange:()=>((e,a)=>{const s=t[e]||[],r=s.includes(a)?s.filter(e=>e!==a):[...s,a];n({...t,[e]:r})})(e.id,s.value),size:"small",className:h.checkbox,color:"primary"}),label:(0,a.jsxs)(i.A,{display:"flex",alignItems:"center",children:[(0,a.jsx)("span",{className:h.checkboxLabel,children:s.label}),void 0!==s.count&&(0,a.jsxs)("span",{className:h.count,children:["(",s.count,")"]})]})},s.value))})})]},e.id)})]})}},14682:(e,t,n)=>{n.r(t),n.d(t,{ApiKeysPage:()=>oe});var a=n(31085),s=n(95478),r=n.n(s),i=n(10394),o=n(31653),l=n(38605),c=n(289),d=n(15831),u=n(45210),p=n(46681),m=n(38599),h=n(49634),g=n(37725),v=n(86687),x=n(42367),A=n(25010),f=n(22097),j=n(91638),y=n(58837),b=n(72501),k=n(67720),w=n(71677),S=n(29365),P=n(78467),C=n(37757),R=n(26343),q=n(76891),I=n(61477),$=n(46805),z=n(93453),T=n(64947),B=n(32269),N=n(61524),M=n(99594),E=n(77225),F=n(39590),_=n(16397),L=n(63221),W=n(12229),D=n(46299),O=n(77318);const K=(0,y.A)(e=>({container:{display:"flex",height:"100%",minHeight:400},tableContainer:{flex:1,overflow:"auto",padding:10},useCasePanel:{padding:e.spacing(2),backgroundColor:e.palette.background.default},useCaseLabel:{fontWeight:600,marginBottom:e.spacing(1),color:e.palette.text.secondary,textTransform:"uppercase",fontSize:"0.75rem"},rejectedBanner:{backgroundColor:e.palette.error.light,border:`1px solid ${e.palette.error.main}`,borderRadius:e.shape.borderRadius,padding:e.spacing(1.5,2),marginBottom:e.spacing(2),display:"flex",alignItems:"center",gap:e.spacing(1)}})),U=({request:e})=>{var t,n;const s=K(),r="Rejected"===(null===(t=e.status)||void 0===t?void 0:t.phase),o=(null===(n=e.spec.apiProductRef)||void 0===n?void 0:n.name)||"unknown";return(0,a.jsxs)(i.A,{className:s.useCasePanel,onClick:e=>e.stopPropagation(),children:[r&&(0,a.jsxs)(i.A,{className:s.rejectedBanner,children:[(0,a.jsx)(E.A,{color:"error",fontSize:"small"}),(0,a.jsxs)(b.A,{variant:"body2",children:["This API key was rejected."," ",(0,a.jsx)(g.N_,{to:`/catalog/default/api/${o}/api-keys`,children:"Request a new API key"})]})]}),(0,a.jsx)(b.A,{className:s.useCaseLabel,children:"Use Case"}),(0,a.jsx)(b.A,{variant:"body2",children:e.spec.useCase||"No use case provided"})]})},H=()=>{var e,t;const n=K(),r=(0,h.useNavigate)(),o=(0,f.useApi)(f.configApiRef),l=(0,f.useApi)(f.fetchApiRef),c=(0,f.useApi)(f.alertApiRef),d=o.getString("backend.baseUrl"),[u,p]=(0,s.useState)(new Set),[m,y]=(0,s.useState)(null),[H,V]=(0,s.useState)(null),[Y,Z]=(0,s.useState)({open:!1,request:null,plans:[]}),[J,X]=(0,s.useState)(0),[G,Q]=(0,s.useState)(null),[ee,te]=(0,s.useState)({open:!1,request:null}),[ne,ae]=(0,s.useState)(new Map),[se,re]=(0,s.useState)(new Set),[ie,oe]=(0,s.useState)(new Set),[le,ce]=(0,s.useState)(!1),[de,ue]=(0,s.useState)(null),[pe,me]=(0,s.useState)(new Set),[he,ge]=(0,s.useState)({status:[],apiProduct:[],tier:[]}),{value:ve,loading:xe,error:Ae}=(0,j.A)(async()=>{const[e,t]=await Promise.all([l.fetch(`${d}/api/kuadrant/requests/my`),l.fetch(`${d}/api/kuadrant/apiproducts`)]);if(!e.ok)throw new Error("failed to fetch requests");const n=(await e.json()).items||[];let a=[];t.ok&&(a=(await t.json()).items||[]);const s=new Map;return a.forEach(e=>{var t;const n=`${e.metadata.namespace}/${e.metadata.name}`,a=(null===(t=e.metadata.annotations)||void 0===t?void 0:t["backstage.io/owner"])||"unknown";s.set(n,a)}),{requests:n,products:a,ownerMap:s}},[d,l,J]),fe=(0,s.useMemo)(()=>(null==ve?void 0:ve.requests)?ve.requests.filter(e=>!pe.has(e.metadata.name)):[],[null==ve?void 0:ve.requests,pe]),je=(0,s.useMemo)(()=>{const e={Approved:0,Pending:0,Rejected:0},t=new Map,n=new Map;return fe.forEach(a=>{var s,r;const i=(null===(s=a.status)||void 0===s?void 0:s.phase)||"Pending";e[i]++;const o=(null===(r=a.spec.apiProductRef)||void 0===r?void 0:r.name)||"unknown";t.set(o,(t.get(o)||0)+1);const l=a.spec.planTier||"unknown";n.set(l,(n.get(l)||0)+1)}),[{id:"status",title:"Status",options:[{value:"Approved",label:"Active",count:e.Approved},{value:"Pending",label:"Pending",count:e.Pending},{value:"Rejected",label:"Rejected",count:e.Rejected}]},{id:"apiProduct",title:"API Product",options:Array.from(t.entries()).map(([e,t])=>({value:e,label:e,count:t})),collapsed:t.size>5},{id:"tier",title:"Tier",options:Array.from(n.entries()).map(([e,t])=>({value:e,label:e.charAt(0).toUpperCase()+e.slice(1),count:t}))}]},[fe]),ye=(0,s.useMemo)(()=>fe.filter(e=>{if(he.status.length>0){var t;const n=(null===(t=e.status)||void 0===t?void 0:t.phase)||"Pending";if(!he.status.includes(n))return!1}if(he.apiProduct.length>0){var n;const t=(null===(n=e.spec.apiProductRef)||void 0===n?void 0:n.name)||"unknown";if(!he.apiProduct.includes(t))return!1}if(he.tier.length>0){const t=e.spec.planTier||"unknown";if(!he.tier.includes(t))return!1}return!0}),[fe,he]),be=e=>{p(t=>{const n=new Set(t);return n.has(e)?n.delete(e):n.add(e),n})},ke=()=>{y(null),V(null)},we=async()=>{if(!H)return;const e=H;ke();try{var t;const a=null===(t=e.spec.apiProductRef)||void 0===t?void 0:t.name,s=e.metadata.namespace,r=await l.fetch(`${d}/api/kuadrant/apiproducts/${s}/${a}`);if(r.ok){var n;const t=(null===(n=(await r.json()).spec)||void 0===n?void 0:n.plans)||[];Z({open:!0,request:e,plans:t})}else Z({open:!0,request:e,plans:[]})}catch(t){console.error("Error fetching plans:",t),Z({open:!0,request:e,plans:[]});const n=t instanceof Error?t.message:"unknown error occurred";c.post({message:`Failed to fetch Plans. ${n}`,severity:"error",display:"transient"})}},Se=()=>{if(!H)return;const e=H;ke(),te({open:!0,request:e})},Pe=[{title:"API Product",field:"spec.apiProductRef.name",render:e=>{var t;const n=(null===(t=e.spec.apiProductRef)||void 0===t?void 0:t.name)||"unknown";return(0,a.jsx)(g.N_,{to:`/catalog/default/api/${n}/api-keys`,children:(0,a.jsx)("strong",{children:n})})}},{title:"Owner",field:"owner",render:e=>{var t,n;const s=`${e.metadata.namespace}/${null===(t=e.spec.apiProductRef)||void 0===t?void 0:t.name}`,r=((null==ve||null===(n=ve.ownerMap)||void 0===n?void 0:n.get(s))||"unknown").replace(/^user:default\//,"");return(0,a.jsx)(b.A,{variant:"body2",children:r})}},{title:"Status",field:"status.phase",render:e=>{var t;const n=(null===(t=e.status)||void 0===t?void 0:t.phase)||"Pending",s="Approved"===n?"Active":n;return(0,a.jsx)(k.A,{label:s,size:"small",style:(0,D.S)(n)})}},{title:"Tier",field:"spec.planTier",render:e=>(0,a.jsx)(k.A,{label:e.spec.planTier,size:"small",variant:"outlined"})},{title:"API Key",field:"status.secretRef",filtering:!1,render:e=>{var t,n,s,r;if("Approved"!==(null===(t=e.status)||void 0===t?void 0:t.phase))return(0,a.jsx)(b.A,{variant:"body2",color:"textSecondary",children:"-"});const o=`${e.metadata.namespace}/${e.metadata.name}`,l=null===(s=e.status)||void 0===s||null===(n=s.secretRef)||void 0===n?void 0:n.name,d=u.has(e.metadata.name),p=se.has(o),m=ne.get(o),h=!1!==(null===(r=e.status)||void 0===r?void 0:r.canReadSecret),g=ie.has(o)||!h;return l?g&&!m?(0,a.jsx)(w.Ay,{title:"This API key has already been viewed and cannot be retrieved again",children:(0,a.jsxs)(i.A,{display:"flex",alignItems:"center",children:[(0,a.jsx)(b.A,{variant:"body2",color:"textSecondary",style:{fontFamily:"monospace",marginRight:8},children:"Already viewed"}),(0,a.jsx)(N.A,{fontSize:"small",color:"disabled"})]})}):(0,a.jsxs)(i.A,{display:"flex",alignItems:"center",style:{gap:8},children:[(0,a.jsx)(i.A,{fontFamily:"monospace",fontSize:"0.875rem",children:p?"Loading...":d&&m?m:"•".repeat(20)+"..."}),d&&m&&(0,a.jsx)(w.Ay,{title:"Copy to clipboard",children:(0,a.jsx)(S.A,{size:"small",onClick:async()=>{m&&(await navigator.clipboard.writeText(m),c.post({message:"API key copied to clipboard",severity:"success",display:"transient"}))},children:(0,a.jsx)(M.A,{fontSize:"small"})})}),(0,a.jsx)(w.Ay,{title:d?"Hide API key":"Reveal API key (one-time only)",children:(0,a.jsx)("span",{children:(0,a.jsx)(S.A,{size:"small",onClick:()=>{d?(((e,t)=>{const n=`${e}/${t}`;ae(e=>{const t=new Map(e);return t.delete(n),t})})(e.metadata.namespace,e.metadata.name),be(e.metadata.name)):g||(ue({namespace:e.metadata.namespace,name:e.metadata.name}),ce(!0))},disabled:p||g&&!m,children:d?(0,a.jsx)(N.A,{fontSize:"small"}):(0,a.jsx)(B.A,{fontSize:"small"})})})})]}):(0,a.jsx)(b.A,{variant:"body2",color:"textSecondary",children:"Awaiting secret..."})}},{title:"Requested",field:"metadata.creationTimestamp",render:e=>{if(!e.metadata.creationTimestamp)return(0,a.jsx)(b.A,{variant:"body2",children:"-"});const t=new Date(e.metadata.creationTimestamp);return(0,a.jsx)(b.A,{variant:"body2",children:t.toLocaleDateString()})}},{title:"Actions",filtering:!1,width:"100px",render:e=>G===e.metadata.name?(0,a.jsx)(P.A,{size:20}):(0,a.jsxs)(i.A,{display:"flex",style:{gap:4},children:[(0,a.jsx)(w.Ay,{title:"View details",children:(0,a.jsx)(S.A,{size:"small",onClick:t=>{t.stopPropagation(),r(`/kuadrant/api-keys/${e.metadata.namespace}/${e.metadata.name}`)},children:(0,a.jsx)(B.A,{fontSize:"small"})})}),(0,a.jsx)(w.Ay,{title:"Delete",children:(0,a.jsx)(S.A,{size:"small",onClick:t=>{t.stopPropagation(),te({open:!0,request:e})},children:(0,a.jsx)(F.A,{fontSize:"small"})})})]})}],Ce=(0,s.useMemo)(()=>[{render:e=>{var t;const n=e.rowData;return(null==n||null===(t=n.metadata)||void 0===t?void 0:t.name)?(0,a.jsx)(U,{request:n}):(0,a.jsx)(i.A,{})}}],[]);return xe?(0,a.jsx)(v.k,{}):Ae?(0,a.jsx)(x._,{error:Ae}):(0,a.jsxs)(a.Fragment,{children:[(0,a.jsxs)(i.A,{className:n.container,children:[(0,a.jsx)(W.Z,{sections:je,filters:he,onChange:ge}),(0,a.jsx)(i.A,{className:n.tableContainer,children:0===ye.length?(0,a.jsx)(i.A,{p:4,textAlign:"center",children:(0,a.jsx)(b.A,{variant:"body1",color:"textSecondary",children:0===fe.length?"No API keys found. Request access to an API to get started.":"No API keys match the selected filters."})}):(0,a.jsx)(A.X,{options:{paging:ye.length>10,pageSize:20,search:!0,filtering:!1,debounceInterval:300,toolbar:!0,emptyRowsWhenPaging:!1},columns:Pe,data:ye.map(e=>({...e,id:e.metadata.name})),detailPanel:Ce})})]}),(0,a.jsx)(C.A,{id:"myapikeys-menu",open:Boolean(m),onClose:ke,anchorReference:"anchorPosition",anchorPosition:m||{top:0,left:0},children:H&&(()=>{const e=[];var t;return e.push((0,a.jsx)(R.A,{onClick:()=>{r(`/kuadrant/api-keys/${H.metadata.namespace}/${H.metadata.name}`),ke()},children:"View Details"},"view")),(t=H).status&&"Pending"!==t.status.phase||e.push((0,a.jsx)(R.A,{onClick:we,children:"Edit"},"edit")),e.push((0,a.jsx)(R.A,{onClick:Se,children:"Delete"},"delete")),e})()}),Y.request&&(0,a.jsx)(_.e,{open:Y.open,request:Y.request,availablePlans:Y.plans,onClose:()=>Z({open:!1,request:null,plans:[]}),onSuccess:()=>{Z({open:!1,request:null,plans:[]}),X(e=>e+1)}}),(0,a.jsx)(L.K,{open:ee.open,title:"Delete API Key",description:`Are you sure you want to delete this API key for ${(null===(t=ee.request)||void 0===t||null===(e=t.spec.apiProductRef)||void 0===e?void 0:e.name)||"this API"}?`,deleting:null!==G,onConfirm:async()=>{if(!ee.request)return;const e=ee.request,t=e.metadata.name;me(e=>new Set(e).add(t)),Q(t);try{const t=await l.fetch(`${d}/api/kuadrant/requests/${e.metadata.namespace}/${e.metadata.name}`,{method:"DELETE"});if(!t.ok){const e=await(0,O.T)(t);throw new Error(`Failed to delete request. ${e}`)}X(e=>e+1),c.post({message:"API key deleted",severity:"success",display:"transient"}),te({open:!1,request:null})}catch(e){console.error("Error deleting request:",e),me(e=>{const n=new Set(e);return n.delete(t),n});const n=e instanceof Error?e.message:"unknown error occurred";c.post({message:`Failed to delete APIKey. ${n}`,severity:"error",display:"transient"})}finally{Q(null)}},onCancel:()=>{te({open:!1,request:null})}}),(0,a.jsxs)(q.A,{open:le,onClose:()=>{ce(!1),ue(null)},maxWidth:"sm",children:[(0,a.jsx)(I.A,{children:(0,a.jsxs)(i.A,{display:"flex",alignItems:"center",children:[(0,a.jsx)(E.A,{color:"primary",style:{marginRight:8}}),"View API Key"]})}),(0,a.jsxs)($.A,{children:[(0,a.jsxs)(b.A,{variant:"body1",paragraph:!0,children:["This API key can only be viewed ",(0,a.jsx)("strong",{children:"once"}),". After you reveal it, you will not be able to retrieve it again."]}),(0,a.jsx)(b.A,{variant:"body2",color:"textSecondary",children:"Make sure to copy and store it securely before closing this view."})]}),(0,a.jsxs)(z.A,{children:[(0,a.jsx)(T.A,{onClick:()=>{ce(!1),ue(null)},children:"Cancel"}),(0,a.jsx)(T.A,{variant:"contained",color:"primary",onClick:()=>{de&&((async(e,t)=>{const n=`${e}/${t}`;if(!se.has(n)){re(e=>new Set(e).add(n));try{const a=await l.fetch(`${d}/api/kuadrant/apikeys/${e}/${t}/secret`);if(a.ok){const e=await a.json();ae(t=>new Map(t).set(n,e.apiKey)),oe(e=>new Set(e).add(n))}else 403===a.status&&(oe(e=>new Set(e).add(n)),c.post({message:"This API key has already been viewed and cannot be retrieved again.",severity:"warning",display:"transient"}))}catch(e){const t=e instanceof Error?e.message:"unknown error occurred";c.post({message:`Failed to fetch api key: ${t}`,severity:"error",display:"transient"})}finally{re(e=>{const t=new Set(e);return t.delete(n),t})}}})(de.namespace,de.name),be(de.name)),ce(!1),ue(null)},children:"Reveal API Key"})]})]})]})};var V=n(35015),Y=n(34955),Z=n(46205),J=n(16249),X=n(55429),G=n(92399);const Q=(0,y.A)(e=>({container:{display:"flex",height:"100%",minHeight:400},tableContainer:{flex:1,overflow:"auto",padding:10},useCasePanel:{padding:e.spacing(2),backgroundColor:e.palette.background.default},useCaseLabel:{fontWeight:600,marginBottom:e.spacing(1),color:e.palette.text.secondary,textTransform:"uppercase",fontSize:"0.75rem"},bulkActions:{padding:e.spacing(2),backgroundColor:e.palette.background.default,borderBottom:`1px solid ${e.palette.divider}`,display:"flex",alignItems:"center",justifyContent:"space-between"}})),ee=({open:e,request:t,action:n,processing:s,onClose:o,onConfirm:l})=>{var c,d;const[u,p]=r().useState(""),m="approve"===n?"Approve":"Reject",h="approve"===n?"Approving...":"Rejecting...",g="reject"===n,v=(null==t||null===(c=t.spec.requestedBy)||void 0===c?void 0:c.userId)||"",x=!g||u===v;return r().useEffect(()=>{e||p("")},[e]),(0,a.jsxs)(q.A,{open:e,onClose:s?void 0:o,maxWidth:"sm",fullWidth:!0,children:[(0,a.jsx)(I.A,{children:g?(0,a.jsxs)(i.A,{display:"flex",alignItems:"center",style:{gap:8},children:[(0,a.jsx)(G.A,{color:"error"}),(0,a.jsxs)("span",{children:[m," API Key"]})]}):(0,a.jsxs)("span",{children:[m," API Key"]})}),(0,a.jsx)($.A,{children:t&&(0,a.jsxs)(a.Fragment,{children:[(0,a.jsxs)("p",{children:[(0,a.jsx)("strong",{children:"User:"})," ",t.spec.requestedBy.userId]}),(0,a.jsxs)("p",{children:[(0,a.jsx)("strong",{children:"API:"})," ",(null===(d=t.spec.apiProductRef)||void 0===d?void 0:d.name)||"unknown"]}),(0,a.jsxs)("p",{children:[(0,a.jsx)("strong",{children:"Tier:"})," ",t.spec.planTier]}),(0,a.jsxs)(i.A,{mb:2,children:[(0,a.jsx)(b.A,{variant:"body2",component:"span",style:{fontWeight:"bold"},children:"Use Case:"})," ",(0,a.jsx)(b.A,{variant:"body2",component:"span",style:{whiteSpace:"pre-wrap"},children:t.spec.useCase||"-"})]}),g&&(0,a.jsxs)(i.A,{mt:2,children:[(0,a.jsxs)(b.A,{variant:"body2",color:"textSecondary",gutterBottom:!0,children:["Type ",(0,a.jsx)("strong",{children:v})," to confirm rejection:"]}),(0,a.jsx)(J.A,{fullWidth:!0,variant:"outlined",size:"small",value:u,onChange:e=>p(e.target.value),disabled:s,autoFocus:!0,placeholder:v})]})]})}),(0,a.jsxs)(z.A,{children:[(0,a.jsx)(T.A,{onClick:o,disabled:s,children:"Cancel"}),(0,a.jsx)(T.A,{onClick:l,color:"approve"===n?"primary":"secondary",variant:"contained",disabled:s||!x,startIcon:s?(0,a.jsx)(P.A,{size:16,color:"inherit"}):void 0,children:s?h:m})]})]})},te=({open:e,requests:t,action:n,processing:s,onClose:r,onConfirm:o})=>{const l="approve"===n,c=l?"Approve All":"Reject All",d=l?"Approving...":"Rejecting...";return(0,a.jsxs)(q.A,{open:e,onClose:s?void 0:r,maxWidth:"md",fullWidth:!0,children:[(0,a.jsxs)(I.A,{children:[l?"Approve":"Reject"," ",t.length," API Keys"]}),(0,a.jsxs)($.A,{children:[(0,a.jsxs)(b.A,{variant:"body2",paragraph:!0,children:["You are about to ",l?"approve":"reject"," the following API keys:"]}),(0,a.jsx)(i.A,{mb:2,maxHeight:200,overflow:"auto",children:t.map(e=>{var t;return(0,a.jsx)(i.A,{mb:1,p:1,bgcolor:"background.default",children:(0,a.jsxs)(b.A,{variant:"body2",children:[(0,a.jsx)("strong",{children:e.spec.requestedBy.userId})," -"," ",(null===(t=e.spec.apiProductRef)||void 0===t?void 0:t.name)||"unknown"," (",e.spec.planTier,")"]})},`${e.metadata.namespace}/${e.metadata.name}`)})})]}),(0,a.jsxs)(z.A,{children:[(0,a.jsx)(T.A,{onClick:r,disabled:s,children:"Cancel"}),(0,a.jsx)(T.A,{onClick:o,color:l?"primary":"secondary",variant:"contained",disabled:s,startIcon:s?(0,a.jsx)(P.A,{size:16,color:"inherit"}):void 0,children:s?d:c})]})]})},ne=({request:e})=>{const t=Q();return(0,a.jsxs)(i.A,{className:t.useCasePanel,onClick:e=>e.stopPropagation(),children:[(0,a.jsx)(b.A,{className:t.useCaseLabel,children:"Use Case"}),(0,a.jsx)(b.A,{variant:"body2",children:e.spec.useCase||"No use case provided"})]})},ae=(0,y.A)(e=>({successSection:{padding:e.spacing(2),backgroundColor:e.palette.success.main+"14",borderRadius:e.shape.borderRadius,marginBottom:e.spacing(2),border:`1px solid ${e.palette.success.main}40`},failureSection:{padding:e.spacing(2),backgroundColor:e.palette.error.main+"14",borderRadius:e.shape.borderRadius,marginBottom:e.spacing(2),border:`1px solid ${e.palette.error.main}40`},warningSection:{padding:e.spacing(2),backgroundColor:e.palette.warning.main+"14",borderRadius:e.shape.borderRadius,marginBottom:e.spacing(2),border:`1px solid ${e.palette.warning.main}40`},statRow:{display:"flex",alignItems:"center",gap:e.spacing(1)},errorList:{marginTop:e.spacing(2),padding:0,listStyle:"none"},errorItem:{padding:e.spacing(1.5),marginBottom:e.spacing(1),backgroundColor:e.palette.background.paper,borderRadius:e.shape.borderRadius,border:`1px solid ${e.palette.divider}`},errorName:{fontWeight:600,fontSize:"0.875rem",marginBottom:e.spacing(.5)},errorMessage:{fontSize:"0.813rem",color:e.palette.error.main,fontFamily:"monospace",wordBreak:"break-word"},expandButton:{marginTop:e.spacing(1),padding:e.spacing(.5)}})),se=({open:e,results:t,isApprove:n,onClose:r})=>{const o=ae(),[l,c]=(0,s.useState)(!0),d=t.filter(e=>e.success),u=t.filter(e=>!e.success),p=d.length>0;return(0,a.jsxs)(q.A,{open:e,onClose:r,maxWidth:"md",fullWidth:!0,children:[(0,a.jsx)(I.A,{children:(0,a.jsx)(i.A,{display:"flex",alignItems:"center",style:{gap:8},children:p?(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(G.A,{style:{color:"#ff9800"}}),(0,a.jsxs)("span",{children:["Bulk ",n?"Approve":"Reject"," Completed with Issues"]})]}):(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(G.A,{color:"error"}),(0,a.jsxs)("span",{children:["Bulk ",n?"Approve":"Reject"," Failed"]})]})})}),(0,a.jsxs)($.A,{children:[p&&(0,a.jsx)(i.A,{className:o.successSection,children:(0,a.jsxs)(i.A,{className:o.statRow,children:[(0,a.jsx)(X.A,{style:{color:"#4caf50"}}),(0,a.jsxs)(b.A,{variant:"body1",children:[(0,a.jsx)("strong",{children:d.length})," API key",1!==d.length?"s":""," ",n?"approved":"rejected"," successfully"]})]})}),(0,a.jsxs)(i.A,{className:p?o.warningSection:o.failureSection,children:[(0,a.jsxs)(i.A,{className:o.statRow,children:[(0,a.jsx)(G.A,{color:"error"}),(0,a.jsxs)(b.A,{variant:"body1",children:[(0,a.jsx)("strong",{children:u.length})," request",1!==u.length?"s":""," failed"]})]}),(0,a.jsxs)(T.A,{size:"small",className:o.expandButton,onClick:()=>c(!l),children:[l?"Hide":"Show"," Error Details"]}),l&&(0,a.jsx)("ul",{className:o.errorList,children:u.map((e,t)=>(0,a.jsxs)("li",{className:o.errorItem,children:[(0,a.jsxs)("div",{className:o.errorName,children:[e.namespace,"/",e.name]}),(0,a.jsx)("div",{className:o.errorMessage,children:e.error||"Unknown error"})]},e.name||t))})]})]}),(0,a.jsx)(z.A,{children:(0,a.jsx)(T.A,{onClick:r,color:"primary",variant:"contained",children:"Close"})})]})},re=()=>{var e;const t=Q(),n=(0,f.useApi)(f.configApiRef),r=(0,f.useApi)(f.fetchApiRef),o=(0,f.useApi)(f.identityApiRef),l=(0,f.useApi)(f.alertApiRef),c=n.getString("backend.baseUrl"),[d,u]=(0,s.useState)(0),[p,m]=(0,s.useState)([]),[h,j]=(0,s.useState)({open:!1,request:null,action:"approve",processing:!1}),[y,w]=(0,s.useState)({open:!1,requests:[],action:"approve",processing:!1}),[S,P]=(0,s.useState)({open:!1,results:[],isApprove:!0}),[C,R]=(0,s.useState)({status:[],apiProduct:[],tier:[]}),{allowed:q,loading:I,error:$}=(0,Z.l)(Y.z4),{allowed:z,loading:B,error:N}=(0,Z.l)(Y.q0),M=I||B,E=$||N,{value:F,loading:_,error:L}=(0,V.A)(async()=>{const e=(await o.getBackstageIdentity()).userEntityRef,[t,n]=await Promise.all([r.fetch(`${c}/api/kuadrant/requests`),r.fetch(`${c}/api/kuadrant/apiproducts`)]);if(!t.ok)return{allRequests:[],reviewedBy:e,ownedApiProducts:new Set};const a=t.headers.get("content-type");if(!(null==a?void 0:a.includes("application/json")))return l.post({message:"Unexpected content-type from the server response.",display:"transient",severity:"warning"}),{allRequests:[],reviewedBy:e,ownedApiProducts:new Set};const s=(await t.json()).items||[],i=new Set;if(n.ok){const t=await n.json();for(const n of t.items||[]){var d,u;(null===(u=n.metadata)||void 0===u||null===(d=u.annotations)||void 0===d?void 0:d["backstage.io/owner"])===e&&i.add(`${n.metadata.namespace}/${n.metadata.name}`)}}return{allRequests:s,reviewedBy:e,ownedApiProducts:i}},[c,r,o,d]),K=(0,s.useMemo)(()=>{if(!(null==F?void 0:F.allRequests))return[];const e={Approved:0,Pending:0,Rejected:0},t=new Map,n=new Map;return F.allRequests.forEach(a=>{var s,r;const i=(null===(s=a.status)||void 0===s?void 0:s.phase)||"Pending";e[i]++;const o=(null===(r=a.spec.apiProductRef)||void 0===r?void 0:r.name)||"unknown";t.set(o,(t.get(o)||0)+1);const l=a.spec.planTier||"unknown";n.set(l,(n.get(l)||0)+1)}),[{id:"status",title:"Status",options:[{value:"Pending",label:"Pending",count:e.Pending},{value:"Approved",label:"Approved",count:e.Approved},{value:"Rejected",label:"Rejected",count:e.Rejected}]},{id:"apiProduct",title:"API Product",options:Array.from(t.entries()).map(([e,t])=>({value:e,label:e,count:t})),collapsed:t.size>5},{id:"tier",title:"Tier",options:Array.from(n.entries()).map(([e,t])=>({value:e,label:e.charAt(0).toUpperCase()+e.slice(1),count:t}))}]},[null==F?void 0:F.allRequests]),U=(0,s.useMemo)(()=>(null==F?void 0:F.allRequests)?F.allRequests.filter(e=>{if(C.status.length>0){var t;const n=(null===(t=e.status)||void 0===t?void 0:t.phase)||"Pending";if(!C.status.includes(n))return!1}if(C.apiProduct.length>0){var n;const t=(null===(n=e.spec.apiProductRef)||void 0===n?void 0:n.name)||"unknown";if(!C.apiProduct.includes(t))return!1}if(C.tier.length>0){const t=e.spec.planTier||"unknown";if(!C.tier.includes(t))return!1}return!0}):[],[null==F?void 0:F.allRequests,C]),H=e=>new Date(e).toLocaleDateString("en-GB",{year:"numeric",month:"short",day:"numeric"}),J=[{title:"Requester",field:"spec.requestedBy.userId",render:e=>(0,a.jsx)(b.A,{variant:"body2",children:e.spec.requestedBy.userId})},{title:"API Product",field:"spec.apiProductRef.name",render:e=>{var t;const n=(null===(t=e.spec.apiProductRef)||void 0===t?void 0:t.name)||"unknown";return(0,a.jsx)(g.N_,{to:`/catalog/default/api/${n}`,children:(0,a.jsx)("strong",{children:n})})}},{title:"Status",field:"status.phase",render:e=>{var t;const n=(null===(t=e.status)||void 0===t?void 0:t.phase)||"Pending";return(0,a.jsx)(k.A,{label:n,size:"small",style:(0,D.S)(n)})}},{title:"Tier",field:"spec.planTier",render:e=>(0,a.jsx)(k.A,{label:e.spec.planTier,size:"small",variant:"outlined"})},{title:"Requested",field:"metadata.creationTimestamp",render:e=>(0,a.jsx)(b.A,{variant:"body2",children:e.metadata.creationTimestamp?H(e.metadata.creationTimestamp):"-"})},{title:"Reviewed By",field:"status.reviewedBy",render:e=>{var t;if(!(null===(t=e.status)||void 0===t?void 0:t.reviewedBy))return(0,a.jsx)(b.A,{variant:"body2",color:"textSecondary",children:"-"});const n=e.status.reviewedBy.replace(/^user:default\//,""),s="system"===n;return(0,a.jsxs)(i.A,{children:[(0,a.jsx)(b.A,{variant:"body2",children:s?"Automatic":n}),e.status.reviewedAt&&(0,a.jsx)(b.A,{variant:"caption",color:"textSecondary",children:H(e.status.reviewedAt)})]})}},{title:"Actions",filtering:!1,render:e=>{var t,n,s;if("Pending"!==((null===(t=e.status)||void 0===t?void 0:t.phase)||"Pending"))return null;const r=`${e.metadata.namespace}/${(null===(n=e.spec.apiProductRef)||void 0===n?void 0:n.name)||"unknown"}`;var o;const l=null!==(o=null==F||null===(s=F.ownedApiProducts)||void 0===s?void 0:s.has(r))&&void 0!==o&&o;return q||z&&l?(0,a.jsxs)(i.A,{display:"flex",style:{gap:8},children:[(0,a.jsx)(T.A,{size:"small",startIcon:(0,a.jsx)(X.A,{}),onClick:()=>{j({open:!0,request:e,action:"approve",processing:!1})},color:"primary",variant:"outlined",children:"Approve"}),(0,a.jsx)(T.A,{size:"small",startIcon:(0,a.jsx)(G.A,{}),onClick:()=>{j({open:!0,request:e,action:"reject",processing:!1})},color:"secondary",variant:"outlined",children:"Reject"})]}):null}}],ae=(0,s.useMemo)(()=>[{render:e=>{var t;const n=e.rowData;return(null==n||null===(t=n.metadata)||void 0===t?void 0:t.name)?(0,a.jsx)(ne,{request:n}):(0,a.jsx)(i.A,{})}}],[]);if(_||M)return(0,a.jsx)(v.k,{});if(L)return(0,a.jsx)(x._,{error:L});if(E)return(0,a.jsx)(i.A,{p:2,children:(0,a.jsxs)(b.A,{color:"error",children:["Unable to check permissions: ",E.message]})});const re=q||z;return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsxs)(i.A,{className:t.container,children:[(0,a.jsx)(W.Z,{sections:K,filters:C,onChange:R}),(0,a.jsxs)(i.A,{className:t.tableContainer,children:[p.length>0&&(0,a.jsxs)(i.A,{className:t.bulkActions,children:[(0,a.jsxs)(b.A,{variant:"body2",children:[p.length," request",1!==p.length?"s":""," selected"]}),(0,a.jsxs)(i.A,{display:"flex",style:{gap:8},children:[(0,a.jsx)(T.A,{size:"small",variant:"contained",color:"primary",startIcon:(0,a.jsx)(X.A,{}),onClick:()=>{0!==p.length&&w({open:!0,requests:p,action:"approve",processing:!1})},children:"Approve Selected"}),(0,a.jsx)(T.A,{size:"small",variant:"contained",color:"secondary",startIcon:(0,a.jsx)(G.A,{}),onClick:()=>{0!==p.length&&w({open:!0,requests:p,action:"reject",processing:!1})},children:"Reject Selected"})]})]}),0===U.length?(0,a.jsx)(i.A,{p:4,textAlign:"center",children:(0,a.jsx)(b.A,{variant:"body1",color:"textSecondary",children:0===(null==F||null===(e=F.allRequests)||void 0===e?void 0:e.length)?"No API keys found.":"No API keys match the selected filters."})}):(0,a.jsx)(A.X,{options:{selection:re,showSelectAllCheckbox:U.some(e=>{var t;return!(null===(t=e.status)||void 0===t?void 0:t.phase)||"Pending"===e.status.phase}),selectionProps:e=>{var t,n;return{disabled:"Pending"!==(null===(t=e.status)||void 0===t?void 0:t.phase)&&void 0!==(null===(n=e.status)||void 0===n?void 0:n.phase)}},paging:U.length>10,pageSize:20,search:!0,filtering:!1,debounceInterval:300,showTextRowsSelected:!1,toolbar:!0,emptyRowsWhenPaging:!1},columns:J,data:U.map(e=>{const t=p.some(t=>t.metadata.name===e.metadata.name&&t.metadata.namespace===e.metadata.namespace);return{...e,id:e.metadata.name,tableData:{checked:t}}}),onSelectionChange:e=>{const t=e.filter(e=>{var t;return!(null===(t=e.status)||void 0===t?void 0:t.phase)||"Pending"===e.status.phase});m(t)},detailPanel:ae})]})]}),(0,a.jsx)(ee,{open:h.open,request:h.request,action:h.action,processing:h.processing,onClose:()=>j({open:!1,request:null,action:"approve",processing:!1}),onConfirm:async()=>{if(!h.request||!F)return;j(e=>({...e,processing:!0}));const e="approve"===h.action?`${c}/api/kuadrant/requests/${h.request.metadata.namespace}/${h.request.metadata.name}/approve`:`${c}/api/kuadrant/requests/${h.request.metadata.namespace}/${h.request.metadata.name}/reject`;try{const t=await r.fetch(e,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({reviewedBy:F.reviewedBy})});if(!t.ok){const e=await(0,O.T)(t);throw new Error(e)}j({open:!1,request:null,action:"approve",processing:!1}),m(e=>e.filter(e=>{var t,n;return e.metadata.name!==(null===(t=h.request)||void 0===t?void 0:t.metadata.name)||e.metadata.namespace!==(null===(n=h.request)||void 0===n?void 0:n.metadata.namespace)})),u(e=>e+1);const n="approve"===h.action?"approved":"rejected";l.post({message:`API key ${n}`,severity:"success",display:"transient"})}catch(e){console.error(`error ${h.action}ing request:`,e),j(e=>({...e,processing:!1}));const t=e instanceof Error?e.message:"unknown error occurred";l.post({message:`Failed to ${h.action} API key. ${t}`,severity:"error",display:"transient"})}}}),(0,a.jsx)(te,{open:y.open,requests:y.requests,action:y.action,processing:y.processing,onClose:()=>w({open:!1,requests:[],action:"approve",processing:!1}),onConfirm:async()=>{if(!F||0===y.requests.length)return;w(e=>({...e,processing:!0})),P({open:!1,results:[],isApprove:!0});const e="approve"===y.action,t=e?`${c}/api/kuadrant/requests/bulk-approve`:`${c}/api/kuadrant/requests/bulk-reject`;try{const n=await r.fetch(t,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({requests:y.requests.map(e=>({namespace:e.metadata.namespace,name:e.metadata.name})),reviewedBy:F.reviewedBy})});if(!n.ok){const e=await(0,O.T)(n);throw new Error(e)}const a=(await n.json()).results||[],s=a.filter(e=>e.success),i=0===a.filter(e=>!e.success).length,o=e?"approved":"rejected";w({open:!1,requests:[],action:"approve",processing:!1}),P({open:!i,results:a,isApprove:e}),m([]),u(e=>e+1),i&&l.post({message:`${s.length} API keys ${o}`,severity:"success",display:"transient"})}catch(e){console.error(`error bulk ${y.action}ing requests:`,e),w(e=>({...e,processing:!1}));const t=e instanceof Error?e.message:"unknown error occurred";l.post({message:`Failed to bulk ${y.action} API keys. ${t}`,severity:"error",display:"transient"})}}}),(0,a.jsx)(se,{open:S.open,results:S.results,isApprove:S.isApprove,onClose:()=>P({open:!1,results:[],isApprove:!0})})]})},ie=()=>{const[e,t]=(0,s.useState)(0),{allowed:n,loading:r}=(0,Z.l)(Y.KV);return(0,a.jsxs)(c.Y,{themeId:"tool",children:[(0,a.jsx)(d.Y,{title:"API Keys",subtitle:"API keys management for Kubernetes",children:(0,a.jsx)(u.Y,{children:"Manage your API keys and access requests"})}),(0,a.jsxs)(p.U,{children:[(0,a.jsx)(i.A,{mb:2,children:(0,a.jsxs)(o.A,{value:e,onChange:(e,n)=>{t(n)},indicatorColor:"primary",textColor:"primary",children:[(0,a.jsx)(l.A,{label:"My API keys","data-testid":"my-api-keys-tab"}),!r&&n&&(0,a.jsx)(l.A,{label:"API keys approval","data-testid":"api-keys-approval-tab"})]})}),0===e&&(0,a.jsx)(H,{}),1===e&&n&&(0,a.jsx)(re,{})]})]})},oe=()=>(0,a.jsx)(m.B,{permission:Y.DS,errorMessage:"you don't have permission to view the API Keys page",children:(0,a.jsx)(ie,{})})},23164:(e,t,n)=>{var a=n(4293),s=n(78920);t.A=void 0;var r=s(n(95478)),i=(0,a(n(74044)).default)(r.createElement("path",{d:"M12 8l-6 6 1.41 1.41L12 10.83l4.59 4.58L18 14z"}),"ExpandLess");t.A=i},27799:(e,t,n)=>{var a=n(4293),s=n(78920);t.A=void 0;var r=s(n(95478)),i=(0,a(n(74044)).default)(r.createElement("path",{d:"M21 5v6.59l-3-3.01-4 4.01-4-4-4 4-3-3.01V5c0-1.1.9-2 2-2h14c1.1 0 2 .9 2 2zm-3 6.42l3 3.01V19c0 1.1-.9 2-2 2H5c-1.1 0-2-.9-2-2v-6.58l3 2.99 4-4 4 4 4-3.99z"}),"BrokenImage");t.A=i},38599:(e,t,n)=>{n.d(t,{B:()=>l});var a=n(31085),s=(n(95478),n(10394)),r=n(72501),i=n(86687),o=n(46205);const l=({children:e,permission:t,fallback:n,errorMessage:l})=>{const{allowed:c,loading:d,error:u}=(0,o.l)(t);return d?(0,a.jsx)(i.k,{}):u?(0,a.jsxs)(s.A,{p:4,children:[(0,a.jsxs)(r.A,{color:"error",children:["Unable to check permissions: ",u.message]}),(0,a.jsx)(r.A,{variant:"body2",color:"textSecondary",children:"Please try again or contact your administrator"})]}):c?(0,a.jsx)(a.Fragment,{children:e}):n?(0,a.jsx)(a.Fragment,{children:n}):(0,a.jsxs)(s.A,{p:4,children:[(0,a.jsx)(r.A,{color:"textSecondary",children:l||"You don't have permission to view this page"}),(0,a.jsx)(s.A,{mt:1,children:(0,a.jsxs)(r.A,{variant:"caption",color:"textSecondary",children:["Required permission: ",t.name]})})]})}},39590:(e,t,n)=>{var a=n(4293),s=n(78920);t.A=void 0;var r=s(n(95478)),i=(0,a(n(74044)).default)(r.createElement("path",{d:"M6 19c0 1.1.9 2 2 2h8c1.1 0 2-.9 2-2V7H6v12zM19 4h-3.5l-1-1h-5l-1 1H5v2h14V4z"}),"Delete");t.A=i},45210:(e,t,n)=>{n.d(t,{Y:()=>q});var a=n(31085),s=n(22097),r=n(10394),i=n(64947),o=n(93453),l=n(29365),c=n(46423),d=n(5951),u=n(26343),p=n(28233),m=n(55197),h=n(37976),g=n(72501),v=n(5893),x=n(95478),A=(n(45250),n(49634),n(21006)),f=n(75501);const j=()=>{const{t:e}=(0,f.useTranslationRef)(A.O);return{url:"https://github.com/backstage/backstage/issues",items:[{title:e("supportConfig.default.title"),icon:"warning",links:[{title:e("supportConfig.default.linkTitle"),url:"https://github.com/backstage/backstage/blob/master/app-config.yaml"}]}]}};var y=n(27799);function b(e){const{id:t,Fallback:n=y.A,...r}=e,i=(0,s.useApp)().getSystemIcon(t)??n;return(0,a.jsx)(i,{...r})}function k(e){return(0,a.jsx)(b,{id:"help",...e})}var w=n(37725);const S=(0,h.makeStyles)({popoverList:{minWidth:260,maxWidth:400},menuItem:{whiteSpace:"normal"}},{name:"BackstageSupportButton"}),P=({icon:e})=>{const t=(0,s.useApp)(),n=e?t.getSystemIcon(e)??k:k;return(0,a.jsx)(n,{})},C=({link:e})=>(0,a.jsx)(w.N_,{to:e.url,children:e.title??e.url}),R=({item:e})=>(0,a.jsxs)(u.A,{button:!1,children:[(0,a.jsx)(c.A,{children:(0,a.jsx)(P,{icon:e.icon})}),(0,a.jsx)(d.A,{primary:e.title,secondary:e.links?.reduce((e,t,n)=>[...e,n>0&&(0,a.jsx)("br",{},n),(0,a.jsx)(C,{link:t},t.url)],[])})]});function q(e){const{t}=(0,f.useTranslationRef)(A.O),{title:n,items:c,children:d}=e,{items:h}=function(){const e=(0,s.useApiHolder)().get(s.configApiRef),t=e?.getOptionalConfig("app.support"),n=j();return t?{url:t.getString("url"),items:t.getConfigArray("items").flatMap(e=>({title:e.getString("title"),icon:e.getOptionalString("icon"),links:(e.getOptionalConfigArray("links")??[]).flatMap(e=>({url:e.getString("url"),title:e.getOptionalString("title")??""}))}))}:n}(),[y,b]=(0,x.useState)(!1),[w,P]=(0,x.useState)(null),C=S(),q=(0,s.useApi)(s.configApiRef).getOptionalConfig("app.support"),I=(0,v.A)(e=>e.breakpoints.down("sm")),$=e=>{P(e.currentTarget),b(!0)},z=()=>{b(!1)};return q?(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(r.A,{display:"flex",ml:1,children:I?(0,a.jsx)(l.A,{color:"primary",size:"small",onClick:$,"data-testid":"support-button","aria-label":"Support",children:(0,a.jsx)(k,{})}):(0,a.jsx)(i.A,{"data-testid":"support-button","aria-label":"Support",color:"primary",onClick:$,startIcon:(0,a.jsx)(k,{}),children:t("supportButton.title")})}),(0,a.jsxs)(m.Ay,{"data-testid":"support-button-popover",open:y,anchorEl:w,anchorOrigin:{vertical:"bottom",horizontal:"right"},transformOrigin:{vertical:"top",horizontal:"right"},onClose:z,children:[(0,a.jsxs)(p.A,{className:C.popoverList,autoFocusItem:Boolean(w),children:[n&&(0,a.jsx)(u.A,{button:!1,alignItems:"flex-start",className:C.menuItem,children:(0,a.jsx)(g.A,{variant:"subtitle1",children:n})}),x.Children.map(d,(e,t)=>(0,a.jsx)(u.A,{button:!1,alignItems:"flex-start",className:C.menuItem,children:e},`child-${t}`)),(c??h).map((e,t)=>(0,a.jsx)(R,{item:e},`item-${t}`))]}),(0,a.jsx)(o.A,{children:(0,a.jsx)(i.A,{color:"primary",onClick:z,"aria-label":"Close",children:t("supportButton.close")})})]})]}):null}},46299:(e,t,n)=>{n.d(t,{S:()=>a});const a=e=>{const t={border:"none"};switch(e){case"Approved":return{...t,backgroundColor:"#4caf50",color:"#fff"};case"Rejected":return{...t,backgroundColor:"#f44336",color:"#fff"};default:return{...t,backgroundColor:"#ff9800",color:"#fff"}}}},55429:(e,t,n)=>{var a=n(4293),s=n(78920);t.A=void 0;var r=s(n(95478)),i=(0,a(n(74044)).default)(r.createElement("path",{d:"M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z"}),"CheckCircle");t.A=i},91638:(e,t,n)=>{var a=n(85608),s=n(95478),r=a.__importDefault(n(5030));t.A=function(e,t){void 0===t&&(t=[]);var n=r.default(e,t,{loading:!0}),a=n[0],i=n[1];return s.useEffect(function(){i()},[i]),a}}}]);
2
+ //# sourceMappingURL=4682.75f17114.chunk.js.map