浏览代码

dashlist: Support for check/uncheck all

Marcus Efraimsson 8 年之前
父节点
当前提交
d9ecb59dae

+ 17 - 0
public/app/features/dashboard/dashboard_list_ctrl.ts

@@ -10,6 +10,7 @@ export class DashboardListCtrl {
   navModel: any;
   canDelete = false;
   canMove = false;
+  selectAllChecked = false;
   starredFilterOptions = [{text: 'Filter by Starred', disabled: true}, {text: 'Yes'}, {text: 'No'}];
   selectedStarredFilter: any;
 
@@ -41,6 +42,7 @@ export class DashboardListCtrl {
   initDashboardList(result: any) {
     this.canMove = false;
     this.canDelete = false;
+    this.selectAllChecked = false;
 
     if (!result) {
       this.sections = [];
@@ -185,4 +187,19 @@ export class DashboardListCtrl {
     this.query.starred = this.selectedStarredFilter.text === 'Yes';
     return this.getDashboards();
   }
+
+  onSelectAllChanged() {
+    for (let section of this.sections) {
+      if (!section.hideHeader) {
+        section.checked = this.selectAllChecked;
+      }
+
+      section.items = _.map(section.items, (item) => {
+        item.checked = this.selectAllChecked;
+        return item;
+      });
+    }
+
+    this.selectionChanged();
+  }
 }

+ 20 - 16
public/app/features/dashboard/partials/dashboardList.html

@@ -50,22 +50,26 @@
       </div>
     </div>
 
-      <div style="height: 75%">
-        <div style="display: flex; justify-content: flex-end">
-          <select
-            style="width: 150px;"
-            class="gf-form-input"
-            ng-model="ctrl.selectedStarredFilter"
-            ng-options="t.text disable when t.disabled for t in ctrl.starredFilterOptions"
-            ng-change="ctrl.onStarredFilterChange()"
-          />
-          <select
-            style="width: 150px;"
-            class="gf-form-input"
-            ng-model="ctrl.selectedTagFilter"
-            ng-options="t.term disable when t.disabled for t in ctrl.tagFilterOptions"
-            ng-change="ctrl.onTagFilterChange()"
-          />
+      <div class="dashboard-list">
+        <div class="search-results-filter-row">
+            <gf-form-switch
+              on-change="ctrl.onSelectAllChanged()"
+              checked="ctrl.selectAllChecked"
+            />
+          <div class="search-results-filter-row__filters">
+            <select
+              class="search-results-filter-row__filters-item gf-form-input"
+              ng-model="ctrl.selectedStarredFilter"
+              ng-options="t.text disable when t.disabled for t in ctrl.starredFilterOptions"
+              ng-change="ctrl.onStarredFilterChange()"
+            />
+            <select
+              class="search-results-filter-row__filters-item gf-form-input"
+              ng-model="ctrl.selectedTagFilter"
+              ng-options="t.term disable when t.disabled for t in ctrl.tagFilterOptions"
+              ng-change="ctrl.onTagFilterChange()"
+            />
+          </div>
         </div>
         <div class="search-results-container" ng-show="ctrl.sections.length > 0" grafana-scrollbar>
           <div ng-repeat="section in ctrl.sections" class="search-section">

+ 112 - 25
public/app/features/dashboard/specs/dashboard_list_ctrl.jest.ts

@@ -65,9 +65,9 @@ describe('DashboardListCtrl', () => {
     beforeEach(() => {
       const response = [
         {
-          id: 410,
-          title: "afolder",
-          type: "dash-folder",
+          checked: false,
+          expanded: true,
+          hideHeader: true,
           items: [
             {
               id: 399,
@@ -79,48 +79,41 @@ describe('DashboardListCtrl', () => {
               folderId: 410,
               folderTitle: "afolder",
               folderSlug: "afolder"
-            }
-          ],
-          tags: [],
-          isStarred: false
-        },
-        {
-          id: 0,
-          title: "Root",
-          icon: 'fa fa-folder-open',
-          uri: "db/something-else",
-          type: "dash-db",
-          items: [
+            },
             {
               id: 500,
               title: "Dashboard Test",
               url: "dashboard/db/dashboard-test",
               icon: 'fa fa-folder',
               tags: [],
+              folderId: 499,
               isStarred: false
             }
-          ],
-          tags: [],
-          isStarred: false,
+          ]
         }
       ];
+
       ctrl = createCtrlWithStubs([], response);
     });
 
-    describe('with no filter', () => {
+    describe('with query filter', () => {
       beforeEach(() => {
         ctrl.query.query = 'd';
         ctrl.canMove = true;
         ctrl.canDelete = true;
+        ctrl.selectAllChecked = true;
         return ctrl.getDashboards();
       });
 
       it('should set checked to false on all sections and children', () => {
-        expect(ctrl.sections.length).toEqual(2);
+        expect(ctrl.sections.length).toEqual(1);
         expect(ctrl.sections[0].checked).toEqual(false);
         expect(ctrl.sections[0].items[0].checked).toEqual(false);
-        expect(ctrl.sections[1].checked).toEqual(false);
-        expect(ctrl.sections[1].items[0].checked).toEqual(false);
+        expect(ctrl.sections[0].items[1].checked).toEqual(false);
+      });
+
+      it('should uncheck select all', () => {
+        expect(ctrl.selectAllChecked).toBeFalsy();
       });
 
       it('should disable Move To button', () => {
@@ -130,6 +123,27 @@ describe('DashboardListCtrl', () => {
       it('should disable delete button', () => {
         expect(ctrl.canDelete).toBeFalsy();
       });
+
+      describe('when select all is checked', () => {
+        beforeEach(() => {
+          ctrl.selectAllChecked = true;
+          ctrl.onSelectAllChanged();
+        });
+
+        it('should select all dashboards', () => {
+          expect(ctrl.sections[0].checked).toBeFalsy();
+          expect(ctrl.sections[0].items[0].checked).toBeTruthy();
+          expect(ctrl.sections[0].items[1].checked).toBeTruthy();
+        });
+
+        it('should enable Move To button', () => {
+          expect(ctrl.canMove).toBeTruthy();
+        });
+
+        it('should enable delete button', () => {
+          expect(ctrl.canDelete).toBeTruthy();
+        });
+      });
     });
 
     describe('with tag filter', () => {
@@ -138,7 +152,7 @@ describe('DashboardListCtrl', () => {
       });
 
       it('should set tag filter', () => {
-        expect(ctrl.sections.length).toEqual(2);
+        expect(ctrl.sections.length).toEqual(1);
         expect(ctrl.query.tag[0]).toEqual('test');
       });
     });
@@ -152,13 +166,12 @@ describe('DashboardListCtrl', () => {
       });
 
       it('should set starred filter', () => {
-        expect(ctrl.sections.length).toEqual(2);
+        expect(ctrl.sections.length).toEqual(1);
         expect(ctrl.query.starred).toEqual(true);
       });
     });
   });
 
-
   describe('when selecting dashboards', () => {
     let ctrl;
 
@@ -194,6 +207,80 @@ describe('DashboardListCtrl', () => {
       it('should disable delete button', () => {
         expect(ctrl.canDelete).toBeFalsy();
       });
+
+      describe('when select all is checked', () => {
+        beforeEach(() => {
+          ctrl.selectAllChecked = true;
+          ctrl.onSelectAllChanged();
+        });
+
+        it('should select all folders and dashboards', () => {
+          expect(ctrl.sections[0].checked).toBeTruthy();
+          expect(ctrl.sections[0].items[0].checked).toBeTruthy();
+          expect(ctrl.sections[1].checked).toBeTruthy();
+          expect(ctrl.sections[1].items[0].checked).toBeTruthy();
+        });
+
+        it('should disable Move To button', () => {
+          expect(ctrl.canMove).toBeFalsy();
+        });
+
+        it('should enable delete button', () => {
+          expect(ctrl.canDelete).toBeTruthy();
+        });
+      });
+    });
+
+    describe('and all folders and dashboards are selected', () => {
+      beforeEach(() => {
+        ctrl.sections = [
+          {
+            id: 1,
+            items: [
+              { id: 2, checked: true }
+            ],
+            checked: true
+          },
+          {
+            id: 0,
+            items: [
+              { id: 3, checked: true }
+            ],
+            checked: true
+          }
+        ];
+        ctrl.selectionChanged();
+      });
+
+      it('should disable Move To button', () => {
+        expect(ctrl.canMove).toBeFalsy();
+      });
+
+      it('should enable delete button', () => {
+        expect(ctrl.canDelete).toBeTruthy();
+      });
+
+      describe('when select all is unchecked', () => {
+        beforeEach(() => {
+          ctrl.selectAllChecked = false;
+          ctrl.onSelectAllChanged();
+        });
+
+        it('should uncheck all checked folders and dashboards', () => {
+          expect(ctrl.sections[0].checked).toBeFalsy();
+          expect(ctrl.sections[0].items[0].checked).toBeFalsy();
+          expect(ctrl.sections[1].checked).toBeFalsy();
+          expect(ctrl.sections[1].items[0].checked).toBeFalsy();
+        });
+
+        it('should disable Move To button', () => {
+          expect(ctrl.canMove).toBeFalsy();
+        });
+
+        it('should disable delete button', () => {
+          expect(ctrl.canDelete).toBeFalsy();
+        });
+      });
     });
 
     describe('and one dashboard in root is selected', () => {

+ 1 - 0
public/sass/_grafana.scss

@@ -84,6 +84,7 @@
 @import "components/json_explorer";
 @import "components/code_editor";
 @import "components/dashboard_grid";
+@import "components/dashboard_list";
 
 
 // PAGES

+ 0 - 0
public/sass/components/_dash_list.scss


+ 21 - 0
public/sass/components/_dashboard_list.scss

@@ -0,0 +1,21 @@
+.dashboard-list {
+    height: 75%;
+
+    .search-results-container {
+        padding-left: 0;
+    }
+}
+
+.search-results-filter-row {
+    display: flex;
+    justify-content: space-between;
+}
+
+.search-results-filter-row__filters {
+    display: flex;
+    width: 300px;
+}
+
+.search-results-filter-row__filters-item {
+    width: 150px;
+}