refactor(web): improve appearance and performace of DASD page #2648
Merged
refactor(web): improve appearance and performace of DASD page #2648
Conversation
In the latest version of the Agama interface, Page.Sections elements are used to wrap specific regions of a page, not the entire page itself. This commit removes an outdated full-page wrapper at DASD page to align with that practice.
Ensures that item deselection works even when the deselected object is equal in value but not the same instance (i.e. different memory reference). This can happen when operations like sorting produce a new list containing objects with the same content but different references. Previously, strict reference comparison prevented proper deselection in these cases. Now component uses Radashi's `isEqual` method, which relies on same-value equality using `Object.is()`[1], to correctly identify selected items. [1] https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Equality_comparisons_and_sameness#same-value_equality_using_object.is
This makes it possible to use the centralized table wrapper with tables that require sorting behavior, such as the one listing DASD devices. By centralizing table logic, we ensure consistent look & feel, improve code reuse, and automatically benefit from enhancements applied to the shared component.
Enables selecting or unselecting all items at once when using the "multiple" selection mode, by rendering a checkbox in the selection column header.
6f9c584 to
8f61fb3
Compare
Add the `itemEqualityFn` prop to core/SelectableDataTable to allow custom logic for comparing items during selection. This helps avoid issues with deep comparisons that might fail when a property changes in an object while the previous value is still held in the selected state. It also supports cases where items don't have a stable ID or require alternative comparison logic. By default, the component compares items using the `itemIdKey` (defaults to `"id"`). If the key is missing, strict equality (`===`) is used as a fallback.
Replaces the custom table implementation with the generic SelectableDataTable component, preserving the existing structure and behavior. This change removes the complex logic that handled selection persistence across filtering. That approach was not only hard to maintain but also introduced cognitive overhead and edge cases. Instead, selection is now cleared when filters are applied, leading to simpler, more predictable behavior.
Since returning "void" does not fullfill the requirement of return a ReactNode.
Adds optional support for displaying per-row action menus in the SelectableDataTable component. When provided, an additional column is rendered containing a menu with actions specific to each item.
By using Readonly and Pick utility types to avoid duplicating definition and documentation of some properties.
Moved device actions to a toolbar above the table that only shows up when there’s at least one device selected. A hint is shown when nothing is selected to let users know actions will be available there. This replaces the former "Perform an action" menu, which was disabled until something was selected and could be confusing at first glance. This should improve usability by making all available actions visible upfront and saving clicks. Additionally, per-device actions are now accessible via an actions menu in the "Actions" column, making it easier to perform actions individually. A better code organization is expected in upcoming commits.
Replaces multiple local useState hooks (filters, sorting, selection, and formatting) with a unified useReducer setup. This centralizes state management, improves readability, and sets the stage for future enhancements like combined filters or reset behavior. Also renames `formatRequested` to `devicesToFormat`, merging it with former `selectedDevices` to avoid maintaining redundant selection-related state.
Adds a missing `return` keyword in the value function for the "DIAG" column, which prevented proper rendering of "Yes"/"No" labels. Also improves the overall documentation for DASD table columns.
Adds support for filtering DASD devices by their current status. Also refactors the filtering logic to support combining multiple filters and resets the device selection on each filter change to avoid stale selections.
Allows users to filter devices by whether they are formatted, unformatted, or both. It should help to improves usability when managing large sets of DASD devices.
Improves clarity, accessibility, and reusability by extracting shared filter components. Adds missing unit tests.
Refactor how some internals are built to reduce code duplication and declutter the DASDTable component a bit.
Adds a new `emptyState` prop that allows rendering custom content when the items array is empty. The empty state spans all columns (including selection and actions, if enabled).
Renders a friendly interface when the DASD device list is empty, including a custom icon, explanation message, and a "Clear all filters" action.
4cbcc30 to
92fbdce
Compare
Distinguish between when there are no DASD devices in the system and when no devices match the applied filters. This provides more accurate feedback to the user in the empty state UI.
But not if there are no items to show/select/unselect.
dgdavid
commented
Aug 17, 2025
| * data across nested calls. | ||
| * | ||
| * - `rowIndex` is intentionally mutable and is updated as rows are rendered. | ||
| * - `sortedBy` and `updateSorting` are read-only references to external sorting state. |
Contributor
Author
There was a problem hiding this comment.
There are now more read-only props, refactor that comment.
| <Popup isOpen title={sprintf(_("Format device %s"), device.id)}> | ||
| <Content> | ||
| <Stack hasGutter> | ||
| <Text isBold>{_("This action could destroy any data stored on the device.")}</Text> |
Contributor
Author
There was a problem hiding this comment.
This is the original message was there before starting this refactorization, but I'd say it is "will" not "could".
dgdavid
commented
Aug 18, 2025
| type DASDTableAction = | ||
| | { type: "UPDATE_SORTING"; payload: DASDTableState["sortedBy"] } | ||
| | { type: "UPDATE_FILTERS"; payload: DASDTableState["filters"] } | ||
| | { type: "RESET_FILTERS" } |
Contributor
Author
There was a problem hiding this comment.
Maybe "CLEAR_FILTERS" is a better naming. Applies to all "reset_filters" and also to "reset_selection"
Tracks DASD devices undergoing async mutations using a new `waitingFor` state property. A modal is shown to indicate progress and disappears once all pending actions are complete. Listens for `DASDDeviceChanged` events to update the state accordingly. This should be considered a workaround to provide user feedback and prevent further actions while operations are in progress, until a more robust solution is implemented.
teclator
reviewed
Aug 18, 2025
Contributor
|
In general LGTM, some of the issues found are not related to the current changes, so, please add the changelog entry and mark it as ready for review. I just fixed an issue when sorting which was produced by changes done by #2412. |
dgdavid
commented
Aug 18, 2025
| value: (d: DASDDevice) => | ||
| // Displays comma-separated partition info as individual lines using <div> | ||
| d.partitionInfo.split(",").map((d: string) => <div key={d}>{d}</div>), | ||
| sortingKey: "partitionInfo", |
Contributor
Author
This comment was marked as outdated.
This comment was marked as outdated.
Co-authored-by: Knut Alejandro Anderssen González <kanderssen@suse.de>
Co-authored-by: David Díaz <1691872+dgdavid@users.noreply.github.com>
bmwiedemann
pushed a commit
to bmwiedemann/openSUSE
that referenced
this pull request
Aug 21, 2025
https://build.opensuse.org/request/show/1300561 by user IGonzalezSosa + anag_factory - Refactor DASD page to make it more usable and improve its performance (related to bsc#1247444, gh#agama-project/agama#2648). - Enforce ESP partition id for /boot/efi partitions manually defined (bsc#1248189). - Fix messages about automatic storage sizes (gh#agama-project/agama#2657).
dgdavid
added a commit
that referenced
this pull request
Sep 2, 2025
) During the [work to improve the DASD page](#2648), the core component used to build rich tables was extended to support user-driven sorting. This makes it possible to add a small enhancement to the device selector dialog on the storage page, allowing users to sort the available devices by either **name** or **size**, useful when setting up the installation in a system with an noticeable amount of disks.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
Some users have reported that the DASD page hangs for them, although it hasn't be reproducible by the Agama team members until now.
Solution
Although the issue couldn't be reproduced, the entire page has been reimplemented to use the same component that the main storage page uses for creating the device selector. This change helps reduce duplicated code, brings the page up to date, and increases the chances of catching bugs earlier in the shared component.
In addition to the component migration, several usability improvements have been made:
Screenshots
Click to show/hide some screenshots
Note: these screenshots might be outdated. They will not be updated during code review unless the interface changes drastically due to requested changes.