Skip to content

fix(clusters): close out the remaining engine v2 review threads - #3064

Merged
rmnbrd merged 9 commits into
feat/cluster-engine-v2from
fix/cluster-engine-v2-review-threads
Oct 5, 2026
Merged

rmnbrd merged 9 commits into
feat/cluster-engine-v2from
fix/cluster-engine-v2-review-threads

Conversation

@rmnbrd

@rmnbrd rmnbrd commented Oct 5, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Follow-up to #2997, after #3057, #3060 and #3063. 14 Cubic and Copilot threads were still open on #2997. Some were already addressed by the earlier follow-ups. This PR fixes the rest, one commit per change, and the threads are replied to and resolved on #2997.

Fixed here

  • Error association (Copilot): catalog input errors on toggles, checkboxes and allowed-value selects are now linked to their control with aria-describedby and aria-invalid.
  • Stale select (Cubic): the allowed-values select no longer keeps the old option once its value is cleared.
  • Modal close button (Cubic): Modal close button gets aria-label="Close", so the cluster-add test queries it by role instead of the FontAwesome class.
  • EKS Anywhere card (Cubic): when access has to be requested, the card has a dashed, muted look in addition to its "Request access" label.
  • Cluster inputs (Cubic): setting an input back to what it displays (saved value or default) is no longer counted as a change and is not sent.
  • Install step (Copilot): leaving the page on the Operator install step asks for confirmation (router navigation and page unload). The flow's own navigation once the Operator connects is not blocked.

Already addressed by earlier follow-ups

Nested object-array items, the isItemModalOpenRef cleanup, edits made while saving, the initial validation of the add-item modal, the Operator panel tooltip, reverted edits being saved, and the duplicated provider icon name.

Not changed

omitEmptyValues still drops ''. A cleared defaulted field falls back to the schema default on save, and sending '' risks failing minLength/required checks on the backend.

Testing

  • Jest for clusters/feature, console-shared and shared/ui pass
  • ESLint clean (warnings only, pre-existing); tsc clean on clusters/feature

🤖 Generated with Claude Code


Summary by cubic

Closes the remaining review threads on the cluster engine v2 creation flow by fixing six small bugs and usability issues.

  • Catalog input errors are now tied to their controls with aria-invalid and aria-describedby, using IDs that stay unique when the same field key appears more than once on a page.
  • The allowed-values select resets when its value is cleared instead of keeping the stale option.
  • The Modal close button gets aria-label="Close".
  • Provider cards that require access request (EKS Anywhere) render with a dashed, muted style.
  • Setting a cluster input back to its displayed value no longer counts as a change or is sent on save.
  • Leaving the Operator install step now asks for confirmation, while the flow's own navigation once the Operator connects is not blocked.

Written for commit 81f028b. Summary will update on new commits.

Review in cubic

rmnbrd and others added 6 commits October 5, 2026 08:44
… technologies

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…ss is granted

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…anged

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Copilot AI balanced review requested due to automatic review settings October 5, 2026 06:48
@nx-cloud

nx-cloud Bot commented Oct 5, 2026 •

Copy link
Copy Markdown

View your CI Pipeline Execution ↗ for commit 81f028b

Command Status Duration Result
nx run console:build --parallel=3 --configurati... ✅ Succeeded 2s View ↗
nx affected --target=test --parallel=3 --config... ✅ Succeeded <1s View ↗
nx affected --target=lint --parallel=3 ✅ Succeeded 2m 45s View ↗
nx-cloud record -- yarn nx format:check ✅ Succeeded 6s View ↗

💡 Verify your cache is correct by running tasks in a sandbox. Read docs ↗


☁️ Nx Cloud last updated this comment at 2026-10-05 09:49:18 UTC

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟡 Changes recommended

Cluster-input tracking loses in-flight reversions and mishandles implicit boolean defaults, while generated error IDs are not instance-unique.

Review effort: Balanced
Findings: 2 Medium severity

Open (2)
What changed in this PR

Improves Engine v2 cluster creation and profile behavior, accessibility, and navigation safety.

Changes:

  • Associates validation errors with catalog controls and fixes stale selects.
  • Normalizes cluster-input change tracking and protects installation navigation.
  • Improves modal accessibility and unavailable provider styling.
File Description
libs/​shared/​ui/​src/​lib/​components/​modal/​modal.tsx Labels the modal close button.
libs/​shared/​ui/​src/​lib/​components/​inputs/​input-toggle/​input-toggle.tsx Adds validation ARIA properties.
libs/​shared/​ui/​src/​lib/​components/​inputs/​input-select-small/​input-select-small.tsx Adds validation ARIA properties.
libs/​shared/​console-shared/​src/​lib/​catalog-variable-input/​catalog-variable-input.tsx Links errors and resets cleared selects.
libs/​shared/​console-shared/​src/​lib/​catalog-variable-input/​catalog-variable-input.spec.tsx Tests error association and select clearing.
libs/​domains/​clusters/​feature/​src/​lib/​cluster-profile/​cluster-profile.spec.tsx Tests default-value reversion.
libs/​domains/​clusters/​feature/​src/​lib/​cluster-profile/​cluster-profile-context.tsx Adjusts cluster-input change tracking.
libs/​domains/​clusters/​feature/​src/​lib/​cluster-add/​cluster-add.tsx Adds navigation protection and unavailable-card styling.
libs/​domains/​clusters/​feature/​src/​lib/​cluster-add/​cluster-add.spec.tsx Tests modal semantics and navigation blocking.

💡 Configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread libs/domains/clusters/feature/src/lib/cluster-profile/cluster-profile-context.tsx Outdated

@cubic-dev-ai cubic-dev-ai Bot left a comment •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All reported issues were addressed across 9 files

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

Comment thread libs/domains/clusters/feature/src/lib/cluster-profile/cluster-profile-context.tsx Outdated
Comment thread libs/domains/clusters/feature/src/lib/cluster-add/cluster-add.spec.tsx Outdated
rmnbrd and others added 3 commits October 5, 2026 09:03
…fies

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
@codecov

codecov Bot commented Oct 5, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 92.30769% with 2 lines in your changes missing coverage. Please review.
⚠️ Please upload report for BASE (feat/cluster-engine-v2@7b35347). Learn more about missing BASE report.

Files with missing lines Patch % Lines
...usters/feature/src/lib/cluster-add/cluster-add.tsx 90.00% 0 Missing and 1 partial ⚠️
...rc/lib/cluster-profile/cluster-profile-context.tsx 80.00% 1 Missing ⚠️
Additional details and impacted files
@@                    Coverage Diff                    @@
##             feat/cluster-engine-v2    #3064   +/-   ##
=========================================================
  Coverage                          ?   53.00%           
=========================================================
  Files                             ?     1305           
  Lines                             ?    29107           
  Branches                          ?     8899           
=========================================================
  Hits                              ?    15427           
  Misses                            ?    11218           
  Partials                          ?     2462           
Flag Coverage Δ
unittests 53.00% <92.30%> (?)

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@rmnbrd
rmnbrd merged commit 4f11880 into feat/cluster-engine-v2 Oct 5, 2026
12 of 13 checks passed
@rmnbrd
rmnbrd deleted the fix/cluster-engine-v2-review-threads branch October 5, 2026 09:58
rmnbrd added a commit that referenced this pull request Oct 14, 2026
* Add Profile page

* Implement main Profile page UI elements

* fix(clusters): disable unavailable cluster profile controls

- Remove unused cluster actions
- Disable the log infrastructure toggle and update its test

* feat(clusters): support dynamic platform configuration

- Resolve cluster bindings and component configuration previews
- Render API-defined fields and validation states in cluster profiles

* feat(clusters): add the cluster profile layer sidebar

- Add searchable, selectable layer and component navigation with status indicators
- Reuse the shared search input and expose its accessible label

* feat(clusters): arrange profile inputs in compact rows

- Add row layouts with truncated descriptions and tooltips
- Align profile controls and errors consistently

* feat(clusters): show positive empty state for unconfigured components

- Add a positive variant to the shared EmptyState component
- Use it when a cluster profile component needs no configuration

* fix(clusters): constrain profile page to its container

* fix(clusters): match profile skeleton to configuration rows

* chore(clusters): log profile schema responses in development

* fix(clusters): preserve resolved profile fields on refresh

- Show configuration skeletons only until displayed components resolve
- Keep the last resolved fields visible when background refreshes fail

* fix(clusters): match profile tab icons to sidebar

- Reuse the sidebar component icon in profile tabs
- Assert matching icons for Loki and Alloy

* fix(clusters): remove operator footer from profile sidebar

- Add bottom spacing to the profile configuration panel

* feat(clusters): support nested profile configuration fields

- Add and edit array items through validated modals
- Show nested field violations and enforce array limits

* feat(clusters): remove heading

* fix(clusters): use section for profile content region

* feat(clusters): add searchable cluster profile settings

- Persist profile search in the URL and filter matching layers, components, and fields
- Highlight search matches in configuration labels and descriptions

* feat(clusters): save and deploy profile changes

* refactor(clusters): move profile state into context

* fix(shared-ui): order highlight text classes consistently

* fix(clusters): remove profile header surface background

* feat(clusters): add Engine V2 cluster creation flow

* fix(clusters): disable components without configuration

- Skip non-configurable components when opening profile layers or URL selections
- Hide their tabs and explain disabled sidebar items

* fix(clusters): reflect resolved layer statuses in profile

- Disable skipped and Qovery-managed layers using cluster configuration
- Show a status-specific explanation when a layer is disabled

* fix(ui): preserve input defaults and select accessibility

- Omit undefined search defaults from rendered input attributes
- Keep small select aria labels explicit
- Center select chevrons vertically

* fix(clusters): detect Engine v2 clusters for deployment actions

- Use Operator status to identify Engine v2 clusters
- Restrict deployment actions for those clusters

* feat(clusters): show Operator status in cluster profile

* fix(clusters): prevent dismissing install flow

- Keep the creation modal open during Operator installation
- Cover dismissal before and after installation in ClusterAdd specs

* fix(clusters): create self-managed clusters without a template

- Send only edited Operator configuration and allow default platform selection
- Clarify Operator installation guidance and cover template loading

* fix(clusters): block creation when templates fail to load

- Show a retry option when Operator templates cannot be loaded
- Keep cluster creation disabled until templates load successfully

* fix(clusters): remove obsolete requirement status badge

* fix(clusters): use list items for layer sidebar states

* fix(clusters): use navbar links for profile components

- Replace tab buttons with Navbar links
- Update navigation tests for link semantics and keyboard movement

* fix(clusters): prevent leaving flow during cluster creation

* fix(clusters): block saving invalid profile changes

- Disable save actions until component checks pass
- Cover violations, missing inputs, and unresolved checks

* fix(clusters): reset profile state when switching clusters

* feat(clusters): add component routes to cluster profile

* fix(clusters): ignore cached Operator status when disabled

- Gate Engine v2 detection on the feature flag and self-managed cluster type
- Cover disabled, managed, and unattached cluster cases

* fix(clusters): prevent duplicate Operator updates

- Disable the update button while an update is in progress
- Cover version arguments and in-progress behavior with tests

* fix(clusters): remove obsolete update button comment

* fix(clusters): wait for profile feature flag to load

* fix(clusters): expose profile navbar as navigation

* fix(clusters): stop loading when template queries are disabled

- Gate template loading on the query being enabled
- Cover supported, failed, and unsupported cluster states

* fix(clusters): remove gateway API warning indicator

* test(clusters): verify self-managed cluster selection tracking

* fix(clusters): block saving for offscreen invalid components

- Include edited components outside the active section in configuration resolution
- Keep save actions disabled when any edited component has validation errors

* test(clusters): cover Operator update action visibility

* fix(clusters): remove disabled profile controls

* fix(clusters): close item modal when profile unmounts

- Track the array item modal lifecycle and close it on profile unmount
- Cover modal cleanup with a regression test

* fix(clusters): address engine v2 review comments (#3057)

* fix(clusters): wait for the Operator configuration check before creating

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* fix(clusters): stop polling clusters without Operator and show status errors

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* fix(clusters): block incomplete or invalid profile array items

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* fix(clusters): show the cluster provider and layers on every profile width

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* fix(ui): name and sync profile inputs for assistive tech and navigation

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* fix(clusters): mark EKS Anywhere as an access request

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* chore(ui): rename the search highlight surface token

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* fix(clusters): require resolved Operator inputs before creating

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* fix(clusters): ignore paused or outdated Operator checks

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* fix(clusters): let a failed Operator check be retried

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* fix(clusters): map vendor names to their profile header icons

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* test(clusters): assert the array items added from defaults

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* fix(clusters): show Operator status errors over the cached status

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* fix(ui): show the clear button for external search values

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* chore(clusters): engine v2 review improvements (#3060)

* fix(clusters): keep profile edits made while saving

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* fix(clusters): redirect only once when the Operator connects

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* fix(clusters): track the item modal however it is dismissed

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* perf(clusters): only debounce profile edits, not component switches

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* fix(clusters): use the brand focus outline on profile sidebar buttons

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* fix(clusters): show OVH, Oracle and IBM icons in cluster avatars

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* refactor(clusters): use ClusterAvatar in the profile header

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* fix(clusters): align Operator and profile search copy

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* refactor(clusters): use the layer-group icon in the profile sidebar

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* refactor(clusters): keep the HTTP status helper private to data-access

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* test(ui): drive InputSearch with userEvent

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* refactor(clusters): read route ids in the Operator status components

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* test(clusters): cover the platform configuration helpers

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* test(clusters): drop an unused testing import

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* UI tweak

* perf(clusters): debounce profile edits instead of preview requests

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* fix(clusters): only mention the search when the sidebar has one

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* fix(clusters): report the item modal mount state explicitly

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* chore(clusters): remove profile API response logging

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* fix(clusters): address remaining Cubic and Copilot review feedback on engine v2 (#3063)

* fix(clusters): do not select a disabled layer when none can be opened

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* fix(clusters): do not open non-configurable components matched by search

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* fix(clusters): keep polling the Operator status while the Operator is being installed

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* fix(clusters): leave out reverted edits when saving the profile

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* fix(shared): mask sensitive number inputs

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* fix(clusters): hide decorative provider icons from assistive technologies

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* test(clusters): cover analytics of the EKS Anywhere access request

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* test(clusters): drop keyboard simulation on a disabled update button

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* fix(clusters): show the Operator status in a popover so its action is keyboard reachable

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* test(clusters): cover an enabled layer with nothing to configure

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* fix(clusters): give the Operator status popover an accessible name

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* fix(clusters): hide cloned SVG provider icons from assistive technologies

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* test(clusters): scope the decorative icon assertion to the rendered cluster-add

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Sonnet 5.5 <noreply@anthropic.com>

* fix(clusters): close out the remaining engine v2 review threads (#3064)

* fix(shared): tie catalog input errors to their controls for assistive technologies

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* fix(shared): reset the allowed-values select when its value is cleared

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* fix(shared): give the modal close button an accessible name

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* feat(clusters): style the EKS Anywhere card as unavailable until access is granted

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* fix(clusters): do not mark a cluster input reset to its default as changed

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* feat(clusters): confirm before leaving the Operator install step

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* test(clusters): name the install step blocker test after what it verifies

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* fix(shared): derive catalog input error ids per instance

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* fix(clusters): compare cluster input edits as the inputs display them

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Sonnet 5.5 <noreply@anthropic.com>

* fix(clusters): resolve engine v2 build and profile issues

- Ignore test files when generating TanStack routes
- Normalize platform requirement types and provider icon props
- Upgrade React and the TypeScript Axios SDK

* fix(clusters): show resolved values for read-only fields

- Disable read-only profile inputs and display their API-resolved values
- Add regression coverage for the read-only field behavior

* fix(clusters): keep disabled sensitive fields masked

* refactor(clusters): address engine v2 review comments (#3099)

* fix(clusters): keep read-only fields disabled in the array item modal

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* feat(clusters): warn before leaving the profile with unsaved changes

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* refactor(shared): move isHttpStatus next to the Axios interceptor

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* refactor(clusters): rename useIsEngineV2Cluster to useIsOperatorManagedCluster

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* refactor(clusters): default platform configuration hook keys to empty strings

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* refactor(clusters): move platform configuration hooks next to the other cluster hooks

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* refactor(clusters): move platform configuration utils next to the other cluster utils

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* refactor(clusters): use the shared Heading and Section in the self-managed creation flow

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* refactor(clusters): type the creation flow layouts with PropsWithChildren

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* refactor(clusters): show unmapped Operator violations in a Callout

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* chore(clusters): export the profile tree like the other modules

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* refactor(catalog): move the catalog variable helpers and input into their own library

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* refactor(ui): use cva for the EmptyState size and variant classes

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* docs(ui): add HighlightText stories

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* refactor(ui): drop the unused Tooltip arrow class and collision padding props

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* refactor(ui): control the InputSearch value instead of syncing its default value

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* refactor(clusters): rename useIsOperatorManagedCluster to useIsOperatorAttached

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* refactor(ui): keep the InputSelectSmall accessible name opt-in

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* refactor(clusters): simplify the cluster profile layout

- Remove the cluster header and its unused context data
- Add a divider to the profile sidebar

* fix(clusters): show empty state when no settings match search

- Detect when the selected component matches only hidden settings
- Cover the filtered settings empty state

* refactor(clusters): clarify layer is not configurable yet

* refactor(clusters): clarify when the Operator status row is clickable

- Add hover and pointer styling only when the status panel can open
- Cover clickable and unavailable status states in the footer spec

* test(clusters): clarify Operator status row clickability coverage

* fix(clusters): keep profile saving available during checks

- Allow saving while configuration edits are being checked again
- Keep saving blocked when checks fail or report violations or missing inputs

* fix(clusters): keep the refresh error visible when no setting matches the search

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* docs(clusters): describe that the last save verdict holds during rechecks

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* refactor(schema-fields): rename the catalog lib to a shared schema fields library

The library holds schema-driven field definitions, validation and inputs. It is not tied to
the service catalog and is meant to be shared across domains, so it moves to
@qovery/shared/schema-fields/feature and drops the Catalog and Variable prefixes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* test(ui): render InputSearch specs with the shared test utils

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>

* feat(clusters): only show the profile for Engine v2 clusters (#3105)

feat(clusters): only show the profile for clusters attached to the Operator

The Profile tab and route were gated on the feature flag alone, so every cluster had them.
They now also require a self-managed cluster attached to the Qovery Operator, like the
Operator-specific cluster actions. useIsOperatorAttached reports undefined until the flags,
the cluster and its Operator status are loaded, so the route does not redirect too early.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
erebe added a commit that referenced this pull request Oct 14, 2026
* feat(clusters): label Operator updates in deployment history (#3098)

* chore(skills): clarify implementation and review guidance (#3101)

* chore(skills): clarify implementation and review guidance

* chore(skills): refine actionable review rules

* chore(skills): synchronize standards rule index

* chore(skills): define operation display mismatches

* chore(skills): clarify conditional class composition

* chore(skills): clarify domain placement and library ownership

* chore(skills): align legacy shared library guidance

* chore(skills): consolidate implementation and review guidance

- Align clsx/twMerge guidance across rules
- Move code placement and console-shared rules to project architecture
- Compile implementation and review rules into AGENTS.md and SKILL.md
- Drop tool-specific cubic section and tighten wording into bullets

* chore(skills): reconcile shared helper placement

* feat(audit-logs): label Operator update events (#3104)

Bump qovery-typescript-axios to 1.1.1010 for the OPERATOR_UPDATE and
MAINTENANCE_OPERATOR audit event types. They read "Operator Update" and
"Maintenance · Operator Update", with the icons of their TRIGGER_DEPLOY and
MAINTENANCE counterparts, and show up in the Event filter.

* feat(qov-2363): Set SAML local storage even if coming from direct link (#3100)

* feat(qov-2363) Set SAML local storage even if coming from direct link

* refacto: Use the useLocalStorage hook

---------

Co-authored-by: Melvin Zottola <mzottola@qovery.com>

* feat(environments): add deploy by version (#3014)

* feat(environments): add deploy by version

* fix(environments): harden deploy by version

* fix(environments): keep version menu above modal

* fix(environments): pin deploy modal actions

* test(environments): clarify deploy modal option coverage

* fix(environments): redirect actions to deployment pipeline

* fix(environments): share pipeline toast navigation

* test(environments): mock tanstack params in redeploy flag

* fix(environments): update environment pipeline hook callers

* fix(toast): show loading for async actions

* fix(shared-ui): catch toast action errors

* fix(shared-ui): allow toast callbacks to return values

* chore(environments): group pipeline navigation hook and helper

* fix(environments): use registry details for version selection

* feat: introduce new engine (#2997)

* Add Profile page

* Implement main Profile page UI elements

* fix(clusters): disable unavailable cluster profile controls

- Remove unused cluster actions
- Disable the log infrastructure toggle and update its test

* feat(clusters): support dynamic platform configuration

- Resolve cluster bindings and component configuration previews
- Render API-defined fields and validation states in cluster profiles

* feat(clusters): add the cluster profile layer sidebar

- Add searchable, selectable layer and component navigation with status indicators
- Reuse the shared search input and expose its accessible label

* feat(clusters): arrange profile inputs in compact rows

- Add row layouts with truncated descriptions and tooltips
- Align profile controls and errors consistently

* feat(clusters): show positive empty state for unconfigured components

- Add a positive variant to the shared EmptyState component
- Use it when a cluster profile component needs no configuration

* fix(clusters): constrain profile page to its container

* fix(clusters): match profile skeleton to configuration rows

* chore(clusters): log profile schema responses in development

* fix(clusters): preserve resolved profile fields on refresh

- Show configuration skeletons only until displayed components resolve
- Keep the last resolved fields visible when background refreshes fail

* fix(clusters): match profile tab icons to sidebar

- Reuse the sidebar component icon in profile tabs
- Assert matching icons for Loki and Alloy

* fix(clusters): remove operator footer from profile sidebar

- Add bottom spacing to the profile configuration panel

* feat(clusters): support nested profile configuration fields

- Add and edit array items through validated modals
- Show nested field violations and enforce array limits

* feat(clusters): remove heading

* fix(clusters): use section for profile content region

* feat(clusters): add searchable cluster profile settings

- Persist profile search in the URL and filter matching layers, components, and fields
- Highlight search matches in configuration labels and descriptions

* feat(clusters): save and deploy profile changes

* refactor(clusters): move profile state into context

* fix(shared-ui): order highlight text classes consistently

* fix(clusters): remove profile header surface background

* feat(clusters): add Engine V2 cluster creation flow

* fix(clusters): disable components without configuration

- Skip non-configurable components when opening profile layers or URL selections
- Hide their tabs and explain disabled sidebar items

* fix(clusters): reflect resolved layer statuses in profile

- Disable skipped and Qovery-managed layers using cluster configuration
- Show a status-specific explanation when a layer is disabled

* fix(ui): preserve input defaults and select accessibility

- Omit undefined search defaults from rendered input attributes
- Keep small select aria labels explicit
- Center select chevrons vertically

* fix(clusters): detect Engine v2 clusters for deployment actions

- Use Operator status to identify Engine v2 clusters
- Restrict deployment actions for those clusters

* feat(clusters): show Operator status in cluster profile

* fix(clusters): prevent dismissing install flow

- Keep the creation modal open during Operator installation
- Cover dismissal before and after installation in ClusterAdd specs

* fix(clusters): create self-managed clusters without a template

- Send only edited Operator configuration and allow default platform selection
- Clarify Operator installation guidance and cover template loading

* fix(clusters): block creation when templates fail to load

- Show a retry option when Operator templates cannot be loaded
- Keep cluster creation disabled until templates load successfully

* fix(clusters): remove obsolete requirement status badge

* fix(clusters): use list items for layer sidebar states

* fix(clusters): use navbar links for profile components

- Replace tab buttons with Navbar links
- Update navigation tests for link semantics and keyboard movement

* fix(clusters): prevent leaving flow during cluster creation

* fix(clusters): block saving invalid profile changes

- Disable save actions until component checks pass
- Cover violations, missing inputs, and unresolved checks

* fix(clusters): reset profile state when switching clusters

* feat(clusters): add component routes to cluster profile

* fix(clusters): ignore cached Operator status when disabled

- Gate Engine v2 detection on the feature flag and self-managed cluster type
- Cover disabled, managed, and unattached cluster cases

* fix(clusters): prevent duplicate Operator updates

- Disable the update button while an update is in progress
- Cover version arguments and in-progress behavior with tests

* fix(clusters): remove obsolete update button comment

* fix(clusters): wait for profile feature flag to load

* fix(clusters): expose profile navbar as navigation

* fix(clusters): stop loading when template queries are disabled

- Gate template loading on the query being enabled
- Cover supported, failed, and unsupported cluster states

* fix(clusters): remove gateway API warning indicator

* test(clusters): verify self-managed cluster selection tracking

* fix(clusters): block saving for offscreen invalid components

- Include edited components outside the active section in configuration resolution
- Keep save actions disabled when any edited component has validation errors

* test(clusters): cover Operator update action visibility

* fix(clusters): remove disabled profile controls

* fix(clusters): close item modal when profile unmounts

- Track the array item modal lifecycle and close it on profile unmount
- Cover modal cleanup with a regression test

* fix(clusters): address engine v2 review comments (#3057)

* fix(clusters): wait for the Operator configuration check before creating

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* fix(clusters): stop polling clusters without Operator and show status errors

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* fix(clusters): block incomplete or invalid profile array items

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* fix(clusters): show the cluster provider and layers on every profile width

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* fix(ui): name and sync profile inputs for assistive tech and navigation

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* fix(clusters): mark EKS Anywhere as an access request

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* chore(ui): rename the search highlight surface token

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* fix(clusters): require resolved Operator inputs before creating

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* fix(clusters): ignore paused or outdated Operator checks

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* fix(clusters): let a failed Operator check be retried

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* fix(clusters): map vendor names to their profile header icons

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* test(clusters): assert the array items added from defaults

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* fix(clusters): show Operator status errors over the cached status

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* fix(ui): show the clear button for external search values

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* chore(clusters): engine v2 review improvements (#3060)

* fix(clusters): keep profile edits made while saving

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* fix(clusters): redirect only once when the Operator connects

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* fix(clusters): track the item modal however it is dismissed

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* perf(clusters): only debounce profile edits, not component switches

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* fix(clusters): use the brand focus outline on profile sidebar buttons

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* fix(clusters): show OVH, Oracle and IBM icons in cluster avatars

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* refactor(clusters): use ClusterAvatar in the profile header

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* fix(clusters): align Operator and profile search copy

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* refactor(clusters): use the layer-group icon in the profile sidebar

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* refactor(clusters): keep the HTTP status helper private to data-access

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* test(ui): drive InputSearch with userEvent

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* refactor(clusters): read route ids in the Operator status components

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* test(clusters): cover the platform configuration helpers

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* test(clusters): drop an unused testing import

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* UI tweak

* perf(clusters): debounce profile edits instead of preview requests

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* fix(clusters): only mention the search when the sidebar has one

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* fix(clusters): report the item modal mount state explicitly

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* chore(clusters): remove profile API response logging

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* fix(clusters): address remaining Cubic and Copilot review feedback on engine v2 (#3063)

* fix(clusters): do not select a disabled layer when none can be opened

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* fix(clusters): do not open non-configurable components matched by search

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* fix(clusters): keep polling the Operator status while the Operator is being installed

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* fix(clusters): leave out reverted edits when saving the profile

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* fix(shared): mask sensitive number inputs

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* fix(clusters): hide decorative provider icons from assistive technologies

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* test(clusters): cover analytics of the EKS Anywhere access request

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* test(clusters): drop keyboard simulation on a disabled update button

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* fix(clusters): show the Operator status in a popover so its action is keyboard reachable

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* test(clusters): cover an enabled layer with nothing to configure

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* fix(clusters): give the Operator status popover an accessible name

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* fix(clusters): hide cloned SVG provider icons from assistive technologies

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* test(clusters): scope the decorative icon assertion to the rendered cluster-add

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Sonnet 5.5 <noreply@anthropic.com>

* fix(clusters): close out the remaining engine v2 review threads (#3064)

* fix(shared): tie catalog input errors to their controls for assistive technologies

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* fix(shared): reset the allowed-values select when its value is cleared

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* fix(shared): give the modal close button an accessible name

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* feat(clusters): style the EKS Anywhere card as unavailable until access is granted

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* fix(clusters): do not mark a cluster input reset to its default as changed

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* feat(clusters): confirm before leaving the Operator install step

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* test(clusters): name the install step blocker test after what it verifies

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* fix(shared): derive catalog input error ids per instance

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* fix(clusters): compare cluster input edits as the inputs display them

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Sonnet 5.5 <noreply@anthropic.com>

* fix(clusters): resolve engine v2 build and profile issues

- Ignore test files when generating TanStack routes
- Normalize platform requirement types and provider icon props
- Upgrade React and the TypeScript Axios SDK

* fix(clusters): show resolved values for read-only fields

- Disable read-only profile inputs and display their API-resolved values
- Add regression coverage for the read-only field behavior

* fix(clusters): keep disabled sensitive fields masked

* refactor(clusters): address engine v2 review comments (#3099)

* fix(clusters): keep read-only fields disabled in the array item modal

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* feat(clusters): warn before leaving the profile with unsaved changes

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* refactor(shared): move isHttpStatus next to the Axios interceptor

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* refactor(clusters): rename useIsEngineV2Cluster to useIsOperatorManagedCluster

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* refactor(clusters): default platform configuration hook keys to empty strings

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* refactor(clusters): move platform configuration hooks next to the other cluster hooks

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* refactor(clusters): move platform configuration utils next to the other cluster utils

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* refactor(clusters): use the shared Heading and Section in the self-managed creation flow

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* refactor(clusters): type the creation flow layouts with PropsWithChildren

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* refactor(clusters): show unmapped Operator violations in a Callout

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* chore(clusters): export the profile tree like the other modules

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* refactor(catalog): move the catalog variable helpers and input into their own library

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* refactor(ui): use cva for the EmptyState size and variant classes

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* docs(ui): add HighlightText stories

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* refactor(ui): drop the unused Tooltip arrow class and collision padding props

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* refactor(ui): control the InputSearch value instead of syncing its default value

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* refactor(clusters): rename useIsOperatorManagedCluster to useIsOperatorAttached

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* refactor(ui): keep the InputSelectSmall accessible name opt-in

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* refactor(clusters): simplify the cluster profile layout

- Remove the cluster header and its unused context data
- Add a divider to the profile sidebar

* fix(clusters): show empty state when no settings match search

- Detect when the selected component matches only hidden settings
- Cover the filtered settings empty state

* refactor(clusters): clarify layer is not configurable yet

* refactor(clusters): clarify when the Operator status row is clickable

- Add hover and pointer styling only when the status panel can open
- Cover clickable and unavailable status states in the footer spec

* test(clusters): clarify Operator status row clickability coverage

* fix(clusters): keep profile saving available during checks

- Allow saving while configuration edits are being checked again
- Keep saving blocked when checks fail or report violations or missing inputs

* fix(clusters): keep the refresh error visible when no setting matches the search

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* docs(clusters): describe that the last save verdict holds during rechecks

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* refactor(schema-fields): rename the catalog lib to a shared schema fields library

The library holds schema-driven field definitions, validation and inputs. It is not tied to
the service catalog and is meant to be shared across domains, so it moves to
@qovery/shared/schema-fields/feature and drops the Catalog and Variable prefixes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* test(ui): render InputSearch specs with the shared test utils

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>

* feat(clusters): only show the profile for Engine v2 clusters (#3105)

feat(clusters): only show the profile for clusters attached to the Operator

The Profile tab and route were gated on the feature flag alone, so every cluster had them.
They now also require a self-managed cluster attached to the Qovery Operator, like the
Operator-specific cluster actions. useIsOperatorAttached reports undefined until the flags,
the cluster and its Operator status are loaded, so the route does not redirect too early.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* feat(api-tokens): show last usage in token lists (#3107)

Help users assess token activity directly from organization settings when
reviewing credentials to keep or remove.

Show Last used beside creation details for regular and policy API tokens.
Format the timestamp as a human-readable age relative to when the list
loads, keeping that reference stable across rerenders. Show the exact UTC
timestamp on hover and No recorded usage when the value is null or absent.

Extend the list prop types with optional last_used_at support while the
pinned generated API client does not yet declare the field.

Test relative formatting, placement, hover timestamps, missing values, and
the fixed reference time across rerenders for both lists.

---------

Co-authored-by: Pierre GB <pgerbelot@qovery.com>
Co-authored-by: Melvin Zottola <37779145+mzottola@users.noreply.github.com>
Co-authored-by: Melvin Zottola <mzottola@qovery.com>
Co-authored-by: Théo Grandin <theo.grandin74@gmail.com>
Co-authored-by: Romain Billard <rmnbrd@users.noreply.github.com>
Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-authored-by: Erèbe - Romain Gerard <erebe@erebe.eu>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants