]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
mgr/dashboard: add rbd list search and disable sorting
authorPere Diaz Bou <pdiazbou@redhat.com>
Fri, 1 Jul 2022 08:16:13 +0000 (10:16 +0200)
committerPere Diaz Bou <pdiazbou@redhat.com>
Tue, 12 Jul 2022 17:09:02 +0000 (19:09 +0200)
- Disable sorting in each column because it will not be possible to
sort with this pagination implementation.
- Add search capabilities to the rbd list pagination endpoint.

Signed-off-by: Pere Diaz Bou <pdiazbou@redhat.com>
src/pybind/mgr/dashboard/controllers/rbd.py
src/pybind/mgr/dashboard/frontend/src/app/ceph/block/iscsi-target-form/iscsi-target-form.component.ts
src/pybind/mgr/dashboard/frontend/src/app/ceph/block/rbd-list/rbd-list.component.ts
src/pybind/mgr/dashboard/frontend/src/app/shared/datatable/table/table.component.ts
src/pybind/mgr/dashboard/frontend/src/app/shared/models/cd-table-fetch-data-context.ts
src/pybind/mgr/dashboard/frontend/src/app/shared/models/cd-user-config.ts
src/pybind/mgr/dashboard/services/rbd.py

index 2f9adf2d9876a31e6cab1432dafb0561995bb216..ddd26b37fe974b47f30560f117416955b559167d 100644 (file)
@@ -78,13 +78,14 @@ class Rbd(RESTController):
     ALLOW_DISABLE_FEATURES = {"exclusive-lock", "object-map", "fast-diff", "deep-flatten",
                               "journaling"}
 
-    def _rbd_list(self, pool_name=None, offset=0, limit=5):
+    def _rbd_list(self, pool_name=None, offset=0, limit=5, search=''):
         if pool_name:
             pools = [pool_name]
         else:
             pools = [p['pool_name'] for p in CephService.get_pool_list('rbd')]
 
-        images, num_total_images = RbdService.rbd_pool_list(pools, offset=offset, limit=limit)
+        images, num_total_images = RbdService.rbd_pool_list(
+            pools, offset=offset, limit=limit, search=search)
         cherrypy.response.headers['X-Total-Count'] = num_total_images
         pool_result = {}
         for i, image in enumerate(images):
@@ -106,8 +107,9 @@ class Rbd(RESTController):
                      'offset': (int, 'offset'),
                  },
                  responses={200: RBD_SCHEMA})
-    def list(self, pool_name=None, offset: int = 0, limit: int = 5):
-        return self._rbd_list(pool_name, offset=offset, limit=limit)
+    def list(self, pool_name=None, offset: int = 0, limit: int = 5,
+             search: str = ''):
+        return self._rbd_list(pool_name, offset=offset, limit=limit, search=search)
 
     @handle_rbd_error()
     @handle_rados_error('pool')
index bf9e73ccbe5c5ea017c9e094de2fb39f27635664..6704b41e6480bba162a4365f829da95d3b3e5a72 100644 (file)
@@ -87,7 +87,7 @@ export class IscsiTargetFormComponent extends CdForm implements OnInit {
   }
 
   ngOnInit() {
-    const rbdListContext = new CdTableFetchDataContext(() => {});
+    const rbdListContext = new CdTableFetchDataContext(() => undefined);
     /* limit -1 to specify all images */
     rbdListContext.pageInfo.limit = -1;
     const promises: any[] = [
index bbbfbe8b7e48c1f4a9da92b16ab35b0361677575..ea25dad289a9b02aae40707fdd41373e1a28fe2c 100644 (file)
@@ -243,11 +243,13 @@ export class RbdListComponent extends ListWithDetails implements OnInit {
       {
         name: $localize`Pool`,
         prop: 'pool_name',
+        sortable: false,
         flexGrow: 2
       },
       {
         name: $localize`Namespace`,
         prop: 'namespace',
+        sortable: false,
         flexGrow: 2
       },
       {
@@ -255,6 +257,7 @@ export class RbdListComponent extends ListWithDetails implements OnInit {
         prop: 'size',
         flexGrow: 1,
         cellClass: 'text-right',
+        sortable: false,
         pipe: this.dimlessBinaryPipe
       },
       {
@@ -262,6 +265,7 @@ export class RbdListComponent extends ListWithDetails implements OnInit {
         prop: 'num_objs',
         flexGrow: 1,
         cellClass: 'text-right',
+        sortable: false,
         pipe: this.dimlessPipe
       },
       {
@@ -269,6 +273,7 @@ export class RbdListComponent extends ListWithDetails implements OnInit {
         prop: 'obj_size',
         flexGrow: 1,
         cellClass: 'text-right',
+        sortable: false,
         pipe: this.dimlessBinaryPipe
       },
       {
@@ -277,6 +282,7 @@ export class RbdListComponent extends ListWithDetails implements OnInit {
         cellClass: 'text-center',
         flexGrow: 1,
         pipe: this.dimlessBinaryPipe,
+        sortable: false,
         cellTemplate: this.provisionedNotAvailableTooltipTpl
       },
       {
@@ -285,18 +291,21 @@ export class RbdListComponent extends ListWithDetails implements OnInit {
         cellClass: 'text-center',
         flexGrow: 1,
         pipe: this.dimlessBinaryPipe,
+        sortable: false,
         cellTemplate: this.totalProvisionedNotAvailableTooltipTpl
       },
       {
         name: $localize`Parent`,
         prop: 'parent',
         flexGrow: 2,
+        sortable: false,
         cellTemplate: this.parentTpl
       },
       {
         name: $localize`Mirroring`,
         prop: 'mirror_mode',
         flexGrow: 3,
+        sortable: false,
         cellTemplate: this.mirroringTpl
       }
     ];
index e09aa7687abaf760bafa3a43a1f4e7fcd40d49c7..7808b833f99eb1540800b9f3162942496fe5c28c 100644 (file)
@@ -342,6 +342,9 @@ export class TableComponent implements AfterContentChecked, OnInit, OnChanges, O
     if (!(this.userConfig.offset >= 0)) {
       this.userConfig.offset = this.table.offset;
     }
+    if (!this.userConfig.search) {
+      this.userConfig.search = this.search;
+    }
     if (!this.userConfig.sorts) {
       this.userConfig.sorts = this.sorts;
     }
@@ -647,6 +650,7 @@ export class TableComponent implements AfterContentChecked, OnInit, OnChanges, O
       });
       context.pageInfo.offset = this.userConfig.offset;
       context.pageInfo.limit = this.userConfig.limit;
+      context.search = this.userConfig.search;
       this.fetchData.emit(context);
       this.updating = true;
     }
@@ -801,19 +805,32 @@ export class TableComponent implements AfterContentChecked, OnInit, OnChanges, O
   }
 
   updateFilter() {
-    let rows = this.columnFilters.length !== 0 ? this.doColumnFiltering() : this.data;
+    if (this.serverSide) {
+      if (this.userConfig.search !== this.search) {
+        // if we don't go back to the first page it will try load
+        // a page which could not exists with an especific search
+        this.userConfig.offset = 0;
+        this.userConfig.limit = this.limit;
+        this.userConfig.search = this.search;
+        this.updating = false;
+        this.reloadData();
+      }
+      this.rows = this.data;
+    } else {
+      let rows = this.columnFilters.length !== 0 ? this.doColumnFiltering() : this.data;
+
+      if (this.search.length > 0 && rows) {
+        const columns = this.localColumns.filter(
+          (c) => c.cellTransformation !== CellTemplate.sparkline
+        );
+        // update the rows
+        rows = this.subSearch(rows, TableComponent.prepareSearch(this.search), columns);
+        // Whenever the filter changes, always go back to the first page
+        this.table.offset = 0;
+      }
 
-    if (this.search.length > 0 && rows) {
-      const columns = this.localColumns.filter(
-        (c) => c.cellTransformation !== CellTemplate.sparkline
-      );
-      // update the rows
-      rows = this.subSearch(rows, TableComponent.prepareSearch(this.search), columns);
-      // Whenever the filter changes, always go back to the first page
-      this.table.offset = 0;
+      this.rows = rows;
     }
-
-    this.rows = rows;
   }
 
   subSearch(data: any[], currentSearch: string[], columns: CdTableColumn[]): any[] {
index bbd1ada04439cfb38c3018404f4ac6f1fc8226b1..56efadeb2baeab64d5b899588774c26b7e1c70eb 100644 (file)
@@ -15,6 +15,7 @@ export class CdTableFetchDataContext {
    */
   error: Function;
   pageInfo: PageInfo = new PageInfo();
+  search = '';
 
   constructor(error: () => void) {
     this.error = error;
@@ -24,10 +25,14 @@ export class CdTableFetchDataContext {
     if (this.pageInfo.limit === null) {
       this.pageInfo.limit = 0;
     }
+    if (this.search === null) {
+      this.search = '';
+    }
     return new HttpParams({
       fromObject: {
         offset: String(this.pageInfo.offset * this.pageInfo.limit),
-        limit: String(this.pageInfo.limit)
+        limit: String(this.pageInfo.limit),
+        search: this.search
       }
     });
   }
index 3bb426b8dc1f72201f70b7dd522b5ebc180c5894..edd1af784872e400dbdb735733d71a5f5a66fba8 100644 (file)
@@ -5,6 +5,7 @@ import { CdTableColumn } from './cd-table-column';
 export interface CdUserConfig {
   limit?: number;
   offset?: number;
+  search?: string;
   sorts?: SortPropDir[];
   columns?: CdTableColumn[];
 }
index 25b9a91977955ae9c89f9c5d6fc59d687b97220d..db88fc606006f1ba2a8f260188da2c914c3c7360 100644 (file)
@@ -428,7 +428,7 @@ class RbdService(object):
         return joint_refs
 
     @classmethod
-    def rbd_pool_list(cls, pool_names: List[str], namespace=None, offset=0, limit=0):
+    def rbd_pool_list(cls, pool_names: List[str], namespace=None, offset=0, limit=0, search=''):
         offset = int(offset)
         limit = int(limit)
         # let's use -1 to denotate we want ALL images for now. Iscsi currently gathers
@@ -439,8 +439,9 @@ class RbdService(object):
         refs = cls._rbd_pool_image_refs(pool_names, namespace)
         image_refs = []
         # transform to list so that we can count
-        for i in refs:
-            image_refs.append(i)
+        for ref in refs:
+            if search in ref['name']:
+                image_refs.append(ref)
 
         result = []
         end = offset + limit