diff --git a/public/app/features/dashboard/dashboard_list_ctrl.ts b/public/app/features/dashboard/dashboard_list_ctrl.ts index 8127edf841c..d29202f16fb 100644 --- a/public/app/features/dashboard/dashboard_list_ctrl.ts +++ b/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(); + } } diff --git a/public/app/features/dashboard/partials/dashboardList.html b/public/app/features/dashboard/partials/dashboardList.html index ac1477bd2d3..4c574c5a5ba 100644 --- a/public/app/features/dashboard/partials/dashboardList.html +++ b/public/app/features/dashboard/partials/dashboardList.html @@ -50,22 +50,26 @@ -
-
- +
+
+ +
+ +
diff --git a/public/app/features/dashboard/specs/dashboard_list_ctrl.jest.ts b/public/app/features/dashboard/specs/dashboard_list_ctrl.jest.ts index e39bdfdb67a..56c2bffdbd9 100644 --- a/public/app/features/dashboard/specs/dashboard_list_ctrl.jest.ts +++ b/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', () => { diff --git a/public/sass/_grafana.scss b/public/sass/_grafana.scss index 70dc88522a6..f067ca3d5cc 100644 --- a/public/sass/_grafana.scss +++ b/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 diff --git a/public/sass/components/_dash_list.scss b/public/sass/components/_dash_list.scss deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/public/sass/components/_dashboard_list.scss b/public/sass/components/_dashboard_list.scss new file mode 100644 index 00000000000..6863dfa785b --- /dev/null +++ b/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; +} \ No newline at end of file