Repository navigation
feat(api-tokens): show last usage in token lists - #3107
Conversation
|
View your CI Pipeline Execution ↗ for commit 97cc348
💡 Verify your cache is correct by running tasks in a sandbox. Read docs ↗ ☁️ Nx Cloud last updated this comment at |
|
View your CI Pipeline Execution ↗ for commit 9cf22eb ☁️ Nx Cloud last updated this comment at |
There was a problem hiding this comment.
All reported issues were addressed across 5 files
Reply with feedback, questions, or to request a fix.
View guided diff | Turn on auto-fix | Re-trigger cubic
a407f35 to
f1c05fd
Compare
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## staging #3107 +/- ##
===========================================
- Coverage 53.73% 53.12% -0.61%
===========================================
Files 1338 1413 +75
Lines 29912 31701 +1789
Branches 9130 9411 +281
===========================================
+ Hits 16072 16842 +770
- Misses 11308 12214 +906
- Partials 2532 2645 +113
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
|
@erebe Could we also not show anything when there's no usage instead of "Last used: No recorded usage"? It will be easier to scan for those who are actually used that way |
f80bba5 to
a925f31
Compare
Yes that's possible, but a bit deceptive. In the end, after the first usage something will be always displayed. |
|
@erebe I think it's better, if no usage recorded not point of showing it, and visually it will be easier to detect those who were never used VS those we have been used if you need to do some cleaning |
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.
a925f31 to
97cc348
Compare
|
|
@erebe Thanks 🫶 |
* 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>

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.
Summary by cubic
Shows when API tokens were last used in organization settings so users can decide which credentials to keep or remove.
last_used_atis null or absent.qovery-typescript-axiosto1.1.1011to declarelast_used_aton token types.Written for commit 97cc348. Summary will update on new commits.