]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
mgr/dashboard: persist table selection across server side page changes 69712/head
authorNaman Munet <naman.munet@ibm.com>
Wed, 24 Jun 2026 14:03:54 +0000 (19:33 +0530)
committerNaman Munet <naman.munet@ibm.com>
Mon, 29 Jun 2026 09:57:47 +0000 (15:27 +0530)
Fixes: https://tracker.ceph.com/issues/77651
Signed-off-by: Naman Munet <naman.munet@ibm.com>
src/pybind/mgr/dashboard/frontend/src/app/shared/datatable/table/table.component.ts

index a261212f324d7271222ec8689bd5f659a9b41dcf..39386aba9810df1b86fae8c9345118d644063c17 100644 (file)
@@ -1265,43 +1265,78 @@ export class TableComponent implements AfterViewInit, OnInit, OnChanges, OnDestr
    * or some selected items may have been removed.
    */
   updateSelected() {
-    if (!this.selection?.selected?.length) return;
+    // In server-side mode, if data is empty or not yet loaded, preserve existing selection
+    // This prevents clearing selection during page transitions when data is being fetched
+    if (this.serverSide && (!this.data || this.data.length === 0)) {
+      return;
+    }
+
+    const itemsFoundOnCurrentPage = new Set();
+    const itemsFromOtherPages = new Set();
 
-    const newSelected = new Set();
     this.selection.selected.forEach((selectedItem) => {
+      let foundOnCurrentPage = false;
       for (const row of this.data) {
         if (selectedItem[this.identifier] === row[this.identifier]) {
-          newSelected.add(row);
+          itemsFoundOnCurrentPage.add(row);
+          foundOnCurrentPage = true;
+          break;
         }
       }
+      // For server-side pagination, preserve items not on current page
+      if (!foundOnCurrentPage && this.serverSide) {
+        itemsFromOtherPages.add(selectedItem);
+      }
     });
 
-    const newSelectedArray = Array.from(newSelected.values());
+    const selectedItemsOnCurrentPage = Array.from(itemsFoundOnCurrentPage.values());
+    const selectedItemsOnOtherPages = Array.from(itemsFromOtherPages.values());
+
+    // For server-side pagination, if no items found on current page but we have
+    // items from other pages, preserve them
+    if (
+      selectedItemsOnCurrentPage.length === 0 &&
+      selectedItemsOnOtherPages.length > 0 &&
+      this.serverSide
+    ) {
+      // No items on current page are selected, but we have selections from other pages
+      // Keep the selection with items from other pages
+      this.selection.selected = selectedItemsOnOtherPages;
+      if (this.updateSelectionOnRefresh !== 'never') {
+        this.updateSelection.emit(_.clone(this.selection));
+      }
+      return;
+    }
 
-    if (newSelectedArray.length === 0) {
+    if (selectedItemsOnCurrentPage.length === 0) {
       this.selection.selected = [];
       this.updateSelection.emit(_.clone(this.selection));
       return;
     }
 
-    newSelectedArray.forEach((selection: any) => {
+    selectedItemsOnCurrentPage.forEach((selectedItem: any) => {
       const rowIndex = this.model.data.findIndex(
         (row: TableItem[]) =>
-          _.get(row, [0, 'selected', this.identifier]) === selection[this.identifier]
+          _.get(row, [0, 'selected', this.identifier]) === selectedItem[this.identifier]
       );
       if (rowIndex > -1) {
         this.model.selectRow(rowIndex, true);
       }
     });
 
+    // For server-side pagination, combine found items with items from other pages
+    const finalSelection = this.serverSide
+      ? [...selectedItemsOnCurrentPage, ...selectedItemsOnOtherPages]
+      : selectedItemsOnCurrentPage;
+
     if (
       this.updateSelectionOnRefresh === 'onChange' &&
-      _.isEqual(this.selection.selected, newSelectedArray)
+      _.isEqual(this.selection.selected, finalSelection)
     ) {
       return;
     }
 
-    this.selection.selected = newSelectedArray;
+    this.selection.selected = finalSelection;
 
     if (this.updateSelectionOnRefresh !== 'never') {
       this.updateSelection.emit(_.clone(this.selection));