refactor(web): restore interface for managing DASD from web client#3143
refactor(web): restore interface for managing DASD from web client#3143joseivanlopez merged 51 commits intoagama-project:masterfrom
Conversation
a66d780 to
3a239fd
Compare
- It makes easier to generate the types for the UI.
3a239fd to
3e38491
Compare
Apply only the minimal required changes (including commenting out lines) to satisfy linters and the test suite, providing a clean baseline for adapting the DASD web UI to the new API. Upcoming work will likely require updating the DASDTable component to support two modes: config and system, and to handle both device types accordingly.
928e8ed to
de7ce9f
Compare
Add tests for useAddDevice and useRemoveDevice while eliminating duplicate helper functions that simply wrapped model/config/dasd calls. Hooks now call model/config/dasd#addDevice and removeDevice directly instead of maintaining wrapper functions. The separation between model/config/dasd and hooks/model/config/dasd is worth to be re-evaluated, since consolidating them might help to reduce indirection and ease testing, as the hooks already provide the primary interface.. Commit also adds test-utils/tanstack-query for query-key-based mocking when hooks share modules with their dependencies.
And also add some more for dasd#useConfig hook based on the ones added for useSystem.
0230cc3 to
eef0a81
Compare
Needed for merging information from both hooks at dasd, useConfig and useSystem. There was a "mergeSources" utils added previously in the iSCSI context that it's not valid for what is needed now. Most probably, iSCSI would move in the DASD behavior direction and mergeSource deprecated or drop.
eef0a81 to
b4fc457
Compare
Previously, extendCollection returned only items from the base
collection extended with data from the extension collection. Now returns
an object with both extended and unmatched items, enabling use cases
like:
- Identifying which extension items have no match in the base collection
- Validation and reporting without additional filtering
- Single source of truth for both intersection and difference
Before:
const result = extendCollection(config, { with: system, matching: 'id' })
After:
const { extended } = extendCollection(config, { with: system, matching: 'id' })
Drop the in-table empty state approach (Bullseye inside a colSpan Td) in
favor of an early return.
Rendering the empty state outside and instead of the table is a better
approach since it avoids visual noise from sortable column headers that
would be rendered but serve no purpose with no data to sort.
Also fix a typo in the documentation ("single" -> "none").
And write pending tests, although one of them has to be skipped until the code will be refactored to satisfy it.
It allows to apply PatternFly text utility styles. https://www.patternfly.org/utility-classes/text
Still pending some refactorizations and, more important, the call to the setConfig request when an action is performed. Also, worth reviewing when an action is shown and when not.
0fce31e to
71faf42
Compare
Accepts an optional filter predicate to exclude entries from the result. Useful when building filter selectors from translated option maps.
Partial rollback of changes done in commit b83d94b. Row actions are always available and act only on their own device, while the bulk toolbar acts on the current selection. Previously, row actions were hidden when devices were selected in order to avoid confusion between single-device and bulk actions. However, this would cause accessibility issues for keyboard and screen reader users who would lose their interaction point mid-navigation with no clear guidance on where actions had moved. Alternatives were explored but discarded: - Disabling the toggle: while keyboard navigation is preserved, the "more" icon (three horizontal dots) is already rendered in a muted gray style making it practically indistinguishable from its disabled state. Combined with PatternFly's Tooltip not triggering on disabled elements, sighted keyboard users would have no visual feedback about why the toggle is inactive and where to go instead. - Visually hiding the toggle: sighted keyboard users would tab onto an invisible element with no feedback. - Per-row skip links: semantically wrong and fatiguing for screen reader users. A hidden "Skip to bulk actions" link per row would be announced on every row, adding repetitive noise. Skip links should be stable, always-present, and bypass navigation blocks instead of replace contextual controls. Replacing per-row action toggles with a skip link conflates navigation with action and increases cognitive load. - Split interaction models for sighted vs screen reader users: rejected on principle. Accessibility best practice is "same model, different presentation", not different interaction models per user type. Creating AT-only affordances or hidden interaction paths is not accessibility — it is a hidden compensation for unstable UI. The core a11y principle at play is: don't remove contextual affordances when context changes, clarify the context instead. Keeping both row actions and bulk toolbar always available is the safest baseline that respects this principle. Further iterations will explore a smoother solution that works for all users without altering the DOM abruptly when selection changes.
Add an aria-live="polite" region to BulkActionsToolbar so that selection state changes are announced as they happen. Two sets of strings are used: concise visual text for sighted users and more descriptive sr-only text providing fuller context. The visual text is marked aria-hidden to prevent double announcements.
Created in the context of adding labeled action menus to DASDTable rows Add SimpleDropdown, a plain dropdown menu with a "more actions" toggle and a labeled group header. Intended as a tiny replacement for PatternFly's ActionsColumn when a group label is needed to provide context about which row the actions apply to. The label is shown both as the aria-label of the toggle button and as the visible group header inside the open menu, improving accessibility for screen reader users navigating action menus in tables. Add `itemActionsComponent` prop to SelectableDataTable to allow callers to provide a custom component for rendering the actions cell, falling back to PatternFly's ActionsColumn when not provided. Last but not least, use SimpleDropdown in DASDTable making the channel identifier shown as a group label when the actions menu is open, making it clear which device the actions belong to.
joseivanlopez
left a comment
There was a problem hiding this comment.
LGTM. Only changelog is missing.
web/src/hooks/model/config/dasd.ts
Outdated
| * | ||
| * FIXME: Read todo note below. | ||
| * @todo Consider returning an empty object ({}) instead of undefined to simplify | ||
| * consuming code and eliminate the need for fallback checks throughout the codebase. | ||
| */ |
There was a problem hiding this comment.
We discussed this in a meeting and while we haven't reached a final conclusion but different point of view, the direction we're leaning toward is using null to represent "nothing found", aligning with language intent despite its well-known typeof quirk (see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/null#description). Alongside this, we'd rely on explicit "defaults" (imported from a shared utility module) to reconstruct the expected shape from scratch when needed.
Not defaulting to an empty or default object does make destructuring slightly more harder to write and follow, but beyond small drawbacks the final solution should focus providing a consistent, predictable pattern as key benefits, as well as avoids mixing null and undefined return types, which can silently become the root cause of unexpected crashes when accessing properties down the render chain (e.g., null passing through a something !== undefined check and then causing a property access to blow up).
For now, I'm removing these comments to keep the PR diff clean. We'll revisit and document the agreed pattern once the team lands on it.
ancorgs
left a comment
There was a problem hiding this comment.
This was already cross-reviewed and tested by @joseivanlopez and @dgdavid. So I'm approving it based on my trust on them (to make it mergeable at Github).
Agama tables lacked any visual feedback when users hovered with mouse or navigated rows with the keyboard, making it hard to track which row user is on. PF's built-in solution (isClickable on Tr) was intentionally avoided since it provides the hover highlight out of the box but also adds a pointer cursor and implies the row is clickable, which is not the common use case for Agama tables at this moment (check slightly related commit ae2d3a2 in which the usage of isClickable was discarded). Thus, a custom CSS rule has been added for covering three interaction cases: * Mouse hover, standard `:hover` * Keyboard navigation, `:focus-within`, intentionally broad to cover all focusable elements including checkboxes. This ensures keyboard users always know which row they are on. The (small) tradeoff is a residual highlight after checkbox selection that persists until focus moves elsewhere. Since it's not expected mouse users stop suddenly interacting, this is an acceptable edge case where the benefit for keyboard users outweighs the minor annoyance (for a brief amount of time) for mouse users. * Action menu open, `:has(.pf-v6-c-menu-toggle[aria-expanded="true"])`, which required fixing a missing `isExpanded` prop on `SimpleDropdown` as part of this PR. The highlight color reuses the same value used for button and menu option hover states for consistency across interactive elements. Defining another color for these elements or a dedicated token for row highlighting is left as a future improvement, though it is not a priority for the team in the mid-term given the amount of other ongoing work. <img width="2048" height="1536" alt="localhost_8080_ (10)" src="https://github.com/user-attachments/assets/3752b712-3a0e-4398-8afa-2a3fc45c73a4" /> <img width="2048" height="1536" alt="localhost_8080_ (9)" src="https://github.com/user-attachments/assets/9696544e-0d93-4a7a-8cec-6d7774ce2d7a" /> --- Related to * #3143 * #3092 * #2459
) As a follow up of #3143, restores the DASD format progress by adapting `DASDFormatProgress` to the new API v2 event model, using `DASDFormatChanged` websocket events to drive progress state and only rendering when formatting is actually active. To support injecting the per-device progress details into the existing backdrop overlay, `ProgressBackdrop` was extended with an `extraContent` prop, which can be used by pages to inject any extra content of their convenience to the progress overlay. This PR was also taken as an opportunity to improve the readability of the progress overlay, on hold since #2947, by wrapping its content in a Card layout, which provides a clear visual container, structured spacing, and scrollable content for long step messages. A `waitingLabel` prop was added as another minor improvement to let consumers override the default `"Refreshing data..."` message shown while queries finish refetching.
… 38 via SR 1337998 https://build.opensuse.org/request/show/1337998 by user IGonzalezSosa + anag_factory - Do not automatically update issues con language change. When to update them is handled by agama-web-server (gh#agama-project/agama#3262). - Allow to reuse LVM volume groups, volumes and thin pools (jsc#PED-15104, bsc#1254718 and gh#agama-project/agama#3171). - Provide new D-Bus API for zFCP (gh#agama-project/agama#3184). - Replace D-Bus methods by attributes in order to allow caching data (related to bsc#1258466). - Allow reactivating a DASD if enabling DIAG failed (gh#agama-project/agama#3143).
https://build.opensuse.org/request/show/1338003 by user IGonzalezSosa + anag_factory - Remove code to deal with the old HTTP API (gh#agama-project/agama#3258). - Allow downloading the user config (jsc#PED-15453). - Improve registration and software issues reporting (related to bsc#1258034). - Drop vulnerable dev dependency no longer needed (bsc#1259117). - Restores DASD format progress with API v2 event model (gh#agama-project/agama#3143). - Improves progress backdrop layout and readbility (gh#agama-project/agama#2947). - Add visual feedback on table row hover and focus (gh#agama-project/agama#3233). - Update web dependencies to their latest available versions as of 2026-03-02 (gh#agama-project/agama#3232). - Do not reset the configuration on product selection (bsc#1258032). - Do not show empty software page (related to bsc#1258922). - Restore the interfa
Prepare to release version 19. * #1829 * #2508 * #2772 * #2818 * #2826 * #2848 * #2860 * #2863 * #2864 * #2866 * #2867 * #2869 * #2870 * #2871 * #2872 * #2873 * #2874 * #2875 * #2876 * #2877 * #2880 * #2881 * #2882 * #2884 * #2885 * #2886 * #2891 * #2892 * #2893 * #2894 * #2895 * #2896 * #2897 * #2898 * #2899 * #2900 * #2901 * #2902 * #2903 * #2904 * #2908 * #2909 * #2910 * #2912 * #2913 * #2914 * #2915 * #2916 * #2917 * #2918 * #2920 * #2921 * #2923 * #2924 * #2926 * #2928 * #2929 * #2930 * #2933 * #2934 * #2935 * #2936 * #2937 * #2938 * #2939 * #2942 * #2943 * #2944 * #2945 * #2946 * #2947 * #2948 * #2949 * #2950 * #2951 * #2952 * #2954 * #2955 * #2956 * #2957 * #2958 * #2959 * #2960 * #2961 * #2963 * #2964 * #2965 * #2967 * #2968 * #2969 * #2970 * #2971 * #2972 * #2974 * #2975 * #2977 * #2978 * #2980 * #2981 * #2982 * #2983 * #2984 * #2988 * #2989 * #2990 * #2991 * #2992 * #2993 * #2994 * #2995 * #2996 * #2997 * #2998 * #2999 * #3000 * #3001 * #3002 * #3004 * #3005 * #3006 * #3007 * #3008 * #3009 * #3011 * #3012 * #3013 * #3014 * #3015 * #3016 * #3018 * #3019 * #3020 * #3021 * #3022 * #3023 * #3024 * #3025 * #3026 * #3027 * #3028 * #3029 * #3030 * #3031 * #3033 * #3034 * #3035 * #3036 * #3037 * #3039 * #3040 * #3041 * #3042 * #3043 * #3044 * #3045 * #3046 * #3047 * #3048 * #3049 * #3050 * #3051 * #3052 * #3053 * #3054 * #3055 * #3056 * #3057 * #3058 * #3060 * #3061 * #3062 * #3063 * #3064 * #3065 * #3066 * #3067 * #3068 * #3069 * #3070 * #3071 * #3072 * #3073 * #3074 * #3075 * #3076 * #3077 * #3078 * #3079 * #3086 * #3087 * #3088 * #3089 * #3090 * #3091 * #3092 * #3093 * #3094 * #3095 * #3096 * #3097 * #3098 * #3099 * #3100 * #3101 * #3102 * #3103 * #3104 * #3105 * #3106 * #3107 * #3108 * #3109 * #3110 * #3112 * #3113 * #3114 * #3115 * #3116 * #3117 * #3118 * #3119 * #3120 * #3122 * #3123 * #3124 * #3127 * #3128 * #3129 * #3130 * #3131 * #3133 * #3134 * #3135 * #3136 * #3137 * #3138 * #3139 * #3140 * #3141 * #3142 * #3143 * #3144 * #3145 * #3146 * #3147 * #3148 * #3149 * #3150 * #3151 * #3152 * #3153 * #3154 * #3155 * #3157 * #3158 * #3159 * #3160 * #3161 * #3162 * #3163 * #3164 * #3165 * #3166 * #3167 * #3168 * #3169 * #3170 * #3174 * #3175 * #3176 * #3177 * #3178 * #3179 * #3181 * #3182 * #3184 * #3185 * #3186 * #3188 * #3189 * #3190 * #3191 * #3192 * #3194 * #3195 * #3196 * #3197 * #3198 * #3199 * #3200 * #3201 * #3202 * #3203 * #3205 * #3206 * #3208 * #3209 * #3210 * #3213 * #3214 * #3215 * #3216 * #3217 * #3218 * #3219 * #3220 * #3222 * #3223 * #3224 * #3225 * #3226 * #3227 * #3228 * #3229 * #3230 * #3231 * #3232 * #3233 * #3234 * #3235 * #3236 * #3237 * #3238 * #3239 * #3240 * #3241 * #3242 * #3243 * #3244 * #3246 * #3247 * #3248 * #3250 * #3251 * #3252 * #3253 * #3254 * #3255 * #3256 * #3257 * #3258 * #3259 * #3260 * #3261 * #3262 * #3263 * #3265 * #3266 * #3267 * #3268 * #3269 * #3270 * #3271 * #3272 * #3273 * #3274 * #3275 * #3276 * #3277 * #3278 * #3279 * #3280 * #3281 * #3282 * #3283 * #3284 * #3285 * #3286 * #3287 * #3288 * #3289 * #3290 * #3291
Bring back the DASD user interface fully adapted to the HTTP v2 API and to the latest web client look&feel (https://trello.com/c/xdvueNDg/, private link)
Warning
The format progress has not been adapted as part of this PR and will be addressed in a follow up one.