rfellows opened a new pull request, #11126:
URL: https://github.com/apache/nifi/pull/11126

   # NIFI-15816: Add Generic Connector Wizard to NiFi frontend (shared library)
   
   ## Description
   
   This change introduces the **generic connector configuration wizard** into 
the NiFi frontend. In NiFi, **connectors** represent managed data-pipeline 
components whose configuration is often too rich for a single form. The 
**Connector Wizard** is a guided, multi-step experience that walks operators 
through **property groups** defined by the connector's descriptors, validates 
input, supports **connectivity verification**, and finally **applies** the 
configuration to the running system.
   
   The wizard supports two UI modes:
   
   - **Generic (auto-generated) UI** -- Steps and fields are driven from 
server-provided configuration metadata (property groups, types, dependencies, 
allowable values, etc.). The shared library renders the appropriate controls 
without connector-specific Angular code.
   - **Custom UI** -- A connector can supply an external URL; the host 
application embeds that UI in an **iframe**. The parent page and the embedded 
UI coordinate through a **typed `postMessage` protocol** so custom UIs can 
request navigation, report save/verify lifecycle events, and receive 
cluster-related acknowledgments (for example **disconnected-node 
acknowledgment** for mutating NiFi requests) without tight coupling to NiFi's 
internal state shape.
   
   This PR is intentionally **library-first**: reusable wizard UI, state, 
services, and types live under `nifi-frontend/.../libs/shared/` so multiple 
feature areas can host the same wizard with different route shells and store 
wiring.
   
   ## Architecture
   
   ### Layering
   
   - **Presentation** -- `ConnectorWizardComponent` orchestrates the shell 
(stepper / navigation chrome, summary step, documentation side panel, banners). 
Step content is composed from generic building blocks (`WizardComponent`, 
property-group cards, `ConnectorPropertyInput`, step actions, verification UX).
   - **State** -- **NgRx SignalStore** with a composed 
**`withConnectorWizard()`** feature encapsulates wizard lifecycle: loading the 
connector, per-step dirty/saved state, verification results, secrets/assets, 
dynamic allowable values, summary refresh, and apply. An abstract 
**`ConnectorWizardStore`** class is the **Angular DI token**; shared components 
inject that token. Hosts provide either **`StandardConnectorWizardStore`** 
(`signalStore(withConnectorWizard())`) or a **custom store** that composes 
`withConnectorWizard()` with app-specific step rules.
   - **API boundary** -- **`ConnectorConfigurationService`** centralizes REST 
calls for loading connector entities, saving steps, verification, applying 
configuration, uploading assets, and related operations used by the store's 
`rxMethod`-style effects.
   - **Iframe protocol** -- **`ConnectorMessageClient`** (in the shared 
library) is the **child/iframe** API: typed methods emit `postMessage` to 
`window.parent` with **origin scoping** (derived from `document.referrer`), and 
exposes streams such as **`disconnectedNodeAcknowledgment$()`** with strict 
validation of inbound parent messages. **`ConnectorMessageHost`** (NiFi app: 
`pages/connectors/service/connector-message-host.service.ts`) is the **parent** 
listener: it validates **origin**, optional **iframe `contentWindow` matching** 
(anti-spoofing), and message shape via **`isConnectorMessage()`**, then routes 
events (e.g. router navigation). The canonical message contracts live in 
**`connector-message.types.ts`** (`CONNECTOR_MESSAGE_NAMESPACE`, discriminated 
unions, type guards).
   - **Forms** -- **`ConnectorPropertyInput`** implements 
**`ControlValueAccessor`** so reactive forms can render **STRING**, 
**BOOLEAN**, **SECRET**, **ASSET**, and related descriptor-driven types 
consistently, including dynamic allowable values and asset upload hooks.
   
   ### Component diagram
   
   ```mermaid
   flowchart TB
       subgraph HostApp["NiFi app (host)"]
           CC["Connector configure route / shell"]
           CMH["ConnectorMessageHost\n(parent postMessage listener)"]
           CC --> CMH
       end
   
       subgraph SharedLib["libs/shared"]
           CW["ConnectorWizardComponent"]
           CS["ConnectorConfigurationStepComponent"]
           SUM["ConnectorConfigurationSummaryStepComponent"]
           CPI["ConnectorPropertyInput"]
           WZ["WizardComponent"]
           CMC["ConnectorMessageClient\n(iframe child API)"]
           Store["ConnectorWizardStore (DI 
token)\nStandardConnectorWizardStore\n+ withConnectorWizard()"]
           API["ConnectorConfigurationService"]
           Types["Types & validation utils\n(connector config, messages)"]
   
           CW --> CS
           CW --> SUM
           CS --> WZ
           CS --> CPI
           CW --> Store
           CS --> Store
           SUM --> Store
           Store --> API
           CMC --> Types
           CMH --> Types
       end
   
       CC --> CW
       CMC -.->|"postMessage\n(origin-checked)"| CMH
   ```
   
   ## Iframe support and security
   
   Embedded custom UIs use **`ConnectorMessageClient`** to emit structured 
events (navigation, step saved/errors, verify started/success/error, config 
applied/errors, UI ready). The parent uses 
**`ConnectorMessageHost.startListening()`** with an explicit **expected 
origin** (from the connector's `configurationUrl`) and optional **iframe 
element** resolution so **`event.source`** must match the real iframe window 
when available. Inbound messages are accepted only if they pass **namespace + 
type** validation (`isConnectorMessage` / `isParentToConnectorMessage`). 
Child-side **`disconnectedNodeAcknowledgment$()`** similarly requires matching 
**origin**, **`event.source === window.parent`**, and validated payload shape 
-- a **fail-closed** posture for cross-window messaging.
   
   ## Key design decisions
   
   - **`NifiSpinnerDirective`** (and spinner companion) moved into 
**`libs/shared`** so shared wizard code does not duplicate NiFi's native 
loading affordance.
   
   ## User flow (configure -> verify -> apply)
   
   ```mermaid
   sequenceDiagram
       actor User
       participant Host as Host page<br/>(Connector configure)
       participant Wiz as ConnectorWizard<br/>(shared)
       participant Store as ConnectorWizardStore<br/>(withConnectorWizard)
       participant API as ConnectorConfigurationService
       participant IF as Custom UI<br/>(optional iframe)
   
       User->>Host: Open connector configuration
       Host->>Wiz: Host provides store + renders wizard
       Wiz->>Store: initializeWithConnector / loadConnector
       Store->>API: Fetch connector + step metadata
       API-->>Store: Connector + step configs
       Store-->>Wiz: Visible steps, working configuration
   
       alt Generic step
           User->>Wiz: Edit properties (CVA inputs)
           Wiz->>Store: updateUnsavedStepValues / markStepDirty
       else Custom step (iframe)
           IF->>Host: postMessage (step events) via ConnectorMessageClient
           Host->>Store: Route events / state updates
       end
   
       User->>Wiz: Save step / advance
       Store->>API: saveStep (per step)
       API-->>Store: Persisted step configuration
   
       User->>Wiz: Verify (step or all)
       Store->>API: verify endpoints
       API-->>Store: Verification results / errors
       Wiz-->>User: Inline errors, banners, verification dialog progress
   
       User->>Wiz: Apply configuration
       Store->>API: applyConfiguration
       API-->>Store: Success or error
       Wiz-->>User: Snackbar + completion / summary refresh
   ```
   
   ## What's changed (high level)
   
   ### `libs/shared`
   
   - New **connector wizard** module: shell components, **SignalStore** + 
**`withConnectorWizard`**, **step dependency utilities**, **wizard context 
banner**, **documentation panel** (markdown), **custom step directive**, 
**summary** and **configuration** steps, **step actions**, 
**`ConnectorPropertyInput`**, shared **wizard** primitives, 
**`ConnectorConfigurationService`**, **`ConnectorMessageClient`**, 
**`UploadService`**, **`ActiveStepService`**, **value-reference** helpers, 
**connector validation** utilities, and expanded **type** surface for connector 
configuration and messages.
   - **`NifiSpinnerDirective`** relocated from the app into shared (re-exports 
updated).
   - **Barrels** (`components`, `directives`, `services`, `types`, `index`) 
updated to export the new public API.
   
   ### `apps/nifi`
   
   - **Connectors** area: **iframe host wiring** (`ConnectorMessageHost`, 
`connector-configure` integration), **`postMessage` to iframe** for 
disconnected-node acknowledgment after **connector-ui-ready**, and related 
component updates.
   - Broad set of **import rewires** across existing dialogs/forms where 
spinner directives now come from **`@nifi/shared`** instead of a previous local 
path.
   
   ## Testing
   
   - **Vitest** suites ported and adapted to NiFi's frontend test setup.
   - Coverage is heavily weighted toward the **SignalStore** 
(`connector-wizard.store.spec.ts`), **configuration step** (large component 
spec), and **summary step** (extensive table/validation scenarios), plus 
utilities, **wizard** shell, **step actions**, **documentation panel**, 
**context banner**, **custom step directive**, and **iframe host** behavior.
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to