From 15224172e916ec35c260bf870c01baa2bc3ec3a5 Mon Sep 17 00:00:00 2001 From: Lokananda Prabhu Date: Wed, 21 Jan 2026 11:50:19 +0530 Subject: [PATCH] Add fetch:error:silent for widget fetch errors --- .../.changeset/fetch-error-silent.md | 5 ++++ .../docs/orchestratorFormWidgets.md | 5 ++++ .../src/uiPropTypes.ts | 1 + .../src/utils/useFetchAndEvaluate.ts | 3 ++- .../src/widgets/ActiveDropdown.tsx | 24 ++++++++++++++++--- .../src/widgets/ActiveMultiSelect.tsx | 13 ++++++---- .../src/widgets/ActiveText.tsx | 7 +++--- .../src/widgets/ActiveTextInput.tsx | 6 +++-- .../src/widgets/SchemaUpdater.tsx | 6 +++-- 9 files changed, 55 insertions(+), 15 deletions(-) create mode 100644 workspaces/orchestrator/.changeset/fetch-error-silent.md diff --git a/workspaces/orchestrator/.changeset/fetch-error-silent.md b/workspaces/orchestrator/.changeset/fetch-error-silent.md new file mode 100644 index 0000000000..a236dcfe4e --- /dev/null +++ b/workspaces/orchestrator/.changeset/fetch-error-silent.md @@ -0,0 +1,5 @@ +--- +'@red-hat-developer-hub/backstage-plugin-orchestrator-form-widgets': patch +--- + +Add fetch:error:silent support to suppress fetch errors in widgets. diff --git a/workspaces/orchestrator/docs/orchestratorFormWidgets.md b/workspaces/orchestrator/docs/orchestratorFormWidgets.md index 06f3503f0a..07a15efb79 100644 --- a/workspaces/orchestrator/docs/orchestratorFormWidgets.md +++ b/workspaces/orchestrator/docs/orchestratorFormWidgets.md @@ -217,6 +217,7 @@ The widget supports following `ui:props`: - fetch:body - fetch:retrigger - fetch:error:ignoreUnready +- fetch:error:silent - fetch:response:value - fetch:response:mandatory @@ -300,6 +301,7 @@ The widget supports following `ui:props`: - fetch:body - fetch:retrigger - fetch:error:ignoreUnready +- fetch:error:silent - fetch:response:value - fetch:response:default - fetch:response:autocomplete @@ -340,6 +342,7 @@ The widget supports following `ui:props`: - fetch:body - fetch:retrigger - fetch:error:ignoreUnready +- fetch:error:silent - fetch:response:value - fetch:response:default - fetch:response:label @@ -389,6 +392,7 @@ The widget supports following `ui:props`: - fetch:body - fetch:retrigger - fetch:error:ignoreUnready +- fetch:error:silent - fetch:response:autocomplete - fetch:response:mandatory - fetch:response:value @@ -527,6 +531,7 @@ Various selectors (like `fetch:response:*`) are processed by the [jsonata](https | fetch:body | An object representing the body of an HTTP POST request. Not used with the GET method. Property value can be a string template or an array of strings. templates. | `{“foo”: “bar $${{identityApi.token}}”, "myArray": ["constant", "$${{current.solutionName}}"]}` | | fetch:retrigger | An array of keys/key families as described in the Backstage API Exposed Parts. If the value referenced by any key from this list is changed, the fetch is triggered. | `["current.solutionName", "identityApi.profileName"]` | | fetch:error:ignoreUnready | When set to `true`, suppresses fetch error display until all `fetch:retrigger` dependencies have non-empty values. This is useful when fetch depends on other fields that are not filled yet, preventing expected errors from being displayed during initial load. | `true`, `false` (default: `false`) | +| fetch:error:silent | When set to `true`, suppresses fetch error display when the fetch request returns a non-OK status (4xx/5xx). Use this when you want to handle error states via conditional UI instead of showing the widget error. | `true`, `false` (default: `false`) | | fetch:response:default | A static default value that is applied immediately when the widget mounts, before any fetch completes. Acts as a fallback when fetch fails or has not completed yet. Gets overridden by `fetch:response:value` once fetch succeeds. For ActiveTextInput/ActiveDropdown use a string, for ActiveMultiSelect use a string array. | `"create"` (string) or `["tag1", "tag2"]` (array) | | fetch:response:\[YOUR_KEY\] | A JSONata selector (string) or object value for extracting data from the fetch response. There can be any count of the \[YOUR_KEY\] properties, so a single fetch response can be used to retrieve multiple records. Supports both string selectors and object type values. | Account.Order.Product.ProductID | | fetch:response:label | Special (well-known) case of the fetch:response:\[YOUR_KEY\] . Used i.e. by the ActiveDropdown to label the items. | | diff --git a/workspaces/orchestrator/plugins/orchestrator-form-widgets/src/uiPropTypes.ts b/workspaces/orchestrator/plugins/orchestrator-form-widgets/src/uiPropTypes.ts index 117cadf169..c164ab3e8a 100644 --- a/workspaces/orchestrator/plugins/orchestrator-form-widgets/src/uiPropTypes.ts +++ b/workspaces/orchestrator/plugins/orchestrator-form-widgets/src/uiPropTypes.ts @@ -26,6 +26,7 @@ export type UiProps = { 'fetch:body'?: Record; 'fetch:retrigger'?: string[]; 'fetch:error:ignoreUnready'?: boolean; + 'fetch:error:silent'?: boolean; [key: `fetch:response:${string}`]: JsonValue; }; diff --git a/workspaces/orchestrator/plugins/orchestrator-form-widgets/src/utils/useFetchAndEvaluate.ts b/workspaces/orchestrator/plugins/orchestrator-form-widgets/src/utils/useFetchAndEvaluate.ts index 7beeb22007..98b17595c2 100644 --- a/workspaces/orchestrator/plugins/orchestrator-form-widgets/src/utils/useFetchAndEvaluate.ts +++ b/workspaces/orchestrator/plugins/orchestrator-form-widgets/src/utils/useFetchAndEvaluate.ts @@ -108,6 +108,7 @@ export const useFetchAndEvaluate = ( return { text: resultText, loading: completeLoading, - error: error ?? fetchError, + error, + fetchError, }; }; diff --git a/workspaces/orchestrator/plugins/orchestrator-form-widgets/src/widgets/ActiveDropdown.tsx b/workspaces/orchestrator/plugins/orchestrator-form-widgets/src/widgets/ActiveDropdown.tsx index 9208a11390..6e7243bf92 100644 --- a/workspaces/orchestrator/plugins/orchestrator-form-widgets/src/widgets/ActiveDropdown.tsx +++ b/workspaces/orchestrator/plugins/orchestrator-form-widgets/src/widgets/ActiveDropdown.tsx @@ -156,8 +156,11 @@ export const ActiveDropdown: Widget< } }, [handleChange, value, values, isChangedByUser, staticDefaultValue]); - if (localError ?? error) { - return ; + const shouldShowFetchError = uiProps['fetch:error:silent'] !== true; + const suppressFetchError = !shouldShowFetchError && !!error; + const displayError = localError ?? (shouldShowFetchError ? error : undefined); + if (displayError) { + return ; } // Compute display options: use fetched options, or fall back to static default @@ -165,12 +168,27 @@ export const ActiveDropdown: Widget< const hasFallbackDefault = !hasOptions && staticDefaultValue; // Show loading only if we have no options AND no fallback default - if (completeLoading && !hasFallbackDefault) { + if (completeLoading && !hasFallbackDefault && !suppressFetchError) { return ; } // If still loading but no options yet and no fallback, show spinner if (!hasOptions && !hasFallbackDefault) { + if (suppressFetchError) { + return ( + + {label} +