-
Notifications
You must be signed in to change notification settings - Fork 63
fix(mcp): make Step 1 draft Gateway selectable as HTTPRoute parentRef and fix some bug #809
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
cfde3ad
ee39c11
7bbf91e
dcb9dae
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -22,7 +22,7 @@ import { | |
| K8sResourceCommon, | ||
| } from '@openshift-console/dynamic-plugin-sdk'; | ||
|
|
||
| interface GatewayForSelect extends K8sResourceCommon { | ||
| export interface GatewayForSelect extends K8sResourceCommon { | ||
| spec?: { | ||
| listeners?: Array<{ | ||
| name: string; | ||
|
|
@@ -66,14 +66,24 @@ interface ParentReferencesSelectProps { | |
| parentRefs: ParentReference[]; | ||
| onChange: (parentRefs: ParentReference[]) => void; | ||
| isDisabled?: boolean; | ||
| // Additional Gateways to include in the selector that aren't yet persisted in | ||
| // the cluster (e.g. a draft Gateway defined earlier in a wizard). Merged with | ||
| // the live watch results, deduped by namespace/name (real Gateways win). | ||
| extraGateways?: GatewayForSelect[]; | ||
| } | ||
|
|
||
| const ParentReferencesSelect: React.FC<ParentReferencesSelectProps> = ({ | ||
| parentRefs, | ||
| onChange, | ||
| isDisabled = false, | ||
| extraGateways, | ||
| }) => { | ||
| const { t } = useTranslation('plugin__kuadrant-console-plugin'); | ||
| // Stabilize the optional prop reference. A default `[]` literal would be a new | ||
| // array on every render, so effects that depend on it would re-run each render | ||
| // and, via setAvailableGateways, spin an infinite update loop in the standalone | ||
| // form (where no extraGateways are passed). | ||
| const stableExtraGateways = React.useMemo(() => extraGateways ?? [], [extraGateways]); | ||
| const [availableGateways, setAvailableGateways] = React.useState<GatewayForSelect[]>([]); | ||
| const [activeNamespace] = useActiveNamespace(); | ||
| const isAllNamespaces = !activeNamespace || activeNamespace === '#ALL_NS#'; | ||
|
|
@@ -93,10 +103,33 @@ const ParentReferencesSelect: React.FC<ParentReferencesSelectProps> = ({ | |
| useK8sWatchResource<GatewayForSelect[]>(gatewayResource); | ||
|
|
||
| React.useEffect(() => { | ||
| if (gatewayLoaded && !gatewayError && Array.isArray(gatewayData)) { | ||
| setAvailableGateways(gatewayData); | ||
| } | ||
| }, [gatewayData, gatewayLoaded, gatewayError]); | ||
| const watched = gatewayLoaded && !gatewayError && Array.isArray(gatewayData) ? gatewayData : []; | ||
| // Merge in any draft Gateways, deduped by namespace/name. A real Gateway from | ||
| // the watch takes precedence over a draft with the same key. | ||
| const keyOf = (gw: GatewayForSelect) => `${gw.metadata?.namespace}/${gw.metadata?.name}`; | ||
| const watchedKeys = new Set(watched.map(keyOf)); | ||
| const drafts = stableExtraGateways.filter((gw) => !watchedKeys.has(keyOf(gw))); | ||
| setAvailableGateways([...watched, ...drafts]); | ||
| }, [gatewayData, gatewayLoaded, gatewayError, stableExtraGateways]); | ||
|
|
||
| // Reconcile parentRefs against the available Gateways when draft Gateways are in | ||
| // play (wizard context only). If a selected Gateway disappears — e.g. a draft | ||
| // Gateway is renamed in an earlier wizard step — clear the stale selection so the | ||
| // form can't emit an HTTPRoute pointing at a Gateway that no longer exists. | ||
| // Gated on extraGateways so the standalone Create/Edit HTTPRoute page is untouched. | ||
| React.useEffect(() => { | ||
| if (stableExtraGateways.length === 0 || !gatewayLoaded) return; | ||
| const validNames = new Set(availableGateways.map((gw) => gw.metadata?.name)); | ||
| let changed = false; | ||
| const reconciled = parentRefs.map((ref) => { | ||
| if (ref.gatewayName && !validNames.has(ref.gatewayName)) { | ||
| changed = true; | ||
| return { ...ref, gatewayName: '', gatewayNamespace: '', sectionName: '', port: 0 }; | ||
| } | ||
| return ref; | ||
| }); | ||
| if (changed) onChange(reconciled); | ||
|
Comment on lines
+124
to
+131
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🗄️ Data Integrity & Integration | 🟡 Minor | ⚡ Quick win Reconcile listener changes, not only Gateway removal. If the draft Gateway keeps the same identity but Step 1 changes 🤖 Prompt for AI Agents |
||
| }, [availableGateways, gatewayLoaded, stableExtraGateways.length, parentRefs, onChange]); | ||
|
|
||
| // Gateway validation function | ||
| const validateGateway = (gateway: GatewayForSelect): string | null => { | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.