mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
dashfolders: rough draft of bulk edit
This commit is contained in:
parent
7559982b05
commit
7f3293ce80
@ -217,6 +217,12 @@ func setIndexViewData(c *middleware.Context) (*dtos.IndexViewData, error) {
|
|||||||
{Text: "New", Url: setting.AppSubUrl + "/datasources", Icon: "fa fa-fw fa-plus"},
|
{Text: "New", Url: setting.AppSubUrl + "/datasources", Icon: "fa fa-fw fa-plus"},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
Text: "Dashboard List",
|
||||||
|
Description: "Manage Dashboards And Folders",
|
||||||
|
Id: "dashboards",
|
||||||
|
Url: setting.AppSubUrl + "/dashboards",
|
||||||
|
},
|
||||||
{
|
{
|
||||||
Text: "Preferences",
|
Text: "Preferences",
|
||||||
Id: "org",
|
Id: "org",
|
||||||
|
@ -48,10 +48,6 @@ function setupAngularRoutes($routeProvider, $locationProvider) {
|
|||||||
reloadOnSearch: false,
|
reloadOnSearch: false,
|
||||||
pageClass: 'page-dashboard',
|
pageClass: 'page-dashboard',
|
||||||
})
|
})
|
||||||
.when('/dashboards/list', {
|
|
||||||
templateUrl: 'public/app/features/dashboard/partials/dash_list.html',
|
|
||||||
controller : 'DashListCtrl',
|
|
||||||
})
|
|
||||||
.when('/configuration', {
|
.when('/configuration', {
|
||||||
templateUrl: 'public/app/features/admin/partials/configuration_home.html',
|
templateUrl: 'public/app/features/admin/partials/configuration_home.html',
|
||||||
controller : 'ConfigurationHomeCtrl',
|
controller : 'ConfigurationHomeCtrl',
|
||||||
@ -73,6 +69,11 @@ function setupAngularRoutes($routeProvider, $locationProvider) {
|
|||||||
controller : 'DataSourceEditCtrl',
|
controller : 'DataSourceEditCtrl',
|
||||||
controllerAs: 'ctrl',
|
controllerAs: 'ctrl',
|
||||||
})
|
})
|
||||||
|
.when('/dashboards', {
|
||||||
|
templateUrl: 'public/app/features/dashboard/partials/dashboardList.html',
|
||||||
|
controller : 'DashboardListCtrl',
|
||||||
|
controllerAs: 'ctrl',
|
||||||
|
})
|
||||||
.when('/org', {
|
.when('/org', {
|
||||||
templateUrl: 'public/app/features/org/partials/orgDetails.html',
|
templateUrl: 'public/app/features/org/partials/orgDetails.html',
|
||||||
controller : 'OrgDetailsCtrl',
|
controller : 'OrgDetailsCtrl',
|
||||||
|
@ -1,5 +1,3 @@
|
|||||||
///<reference path="../../headers/common.d.ts" />
|
|
||||||
|
|
||||||
export default class AdminListUsersCtrl {
|
export default class AdminListUsersCtrl {
|
||||||
users: any;
|
users: any;
|
||||||
pages = [];
|
pages = [];
|
||||||
|
@ -1,32 +0,0 @@
|
|||||||
define([
|
|
||||||
'./dashboard_ctrl',
|
|
||||||
'./alerting_srv',
|
|
||||||
'./history/history',
|
|
||||||
'./dashboardLoaderSrv',
|
|
||||||
'./dashnav/dashnav',
|
|
||||||
'./submenu/submenu',
|
|
||||||
'./save_as_modal',
|
|
||||||
'./save_modal',
|
|
||||||
'./shareModalCtrl',
|
|
||||||
'./shareSnapshotCtrl',
|
|
||||||
'./dashboard_srv',
|
|
||||||
'./viewStateSrv',
|
|
||||||
'./time_srv',
|
|
||||||
'./unsavedChangesSrv',
|
|
||||||
'./unsaved_changes_modal',
|
|
||||||
'./timepicker/timepicker',
|
|
||||||
'./impression_store',
|
|
||||||
'./upload',
|
|
||||||
'./import/dash_import',
|
|
||||||
'./export/export_modal',
|
|
||||||
'./export_data/export_data_modal',
|
|
||||||
'./ad_hoc_filters',
|
|
||||||
'./repeat_option/repeat_option',
|
|
||||||
'./dashgrid/DashboardGrid',
|
|
||||||
'./dashgrid/PanelLoader',
|
|
||||||
'./dashgrid/RowOptions',
|
|
||||||
'./acl/acl',
|
|
||||||
'./acl/acl',
|
|
||||||
'./folder_picker/picker',
|
|
||||||
'./folder_modal/folder'
|
|
||||||
], function () {});
|
|
36
public/app/features/dashboard/all.ts
Normal file
36
public/app/features/dashboard/all.ts
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
|
||||||
|
import './dashboard_ctrl';
|
||||||
|
import './alerting_srv';
|
||||||
|
import './history/history';
|
||||||
|
import './dashboardLoaderSrv';
|
||||||
|
import './dashnav/dashnav';
|
||||||
|
import './submenu/submenu';
|
||||||
|
import './save_as_modal';
|
||||||
|
import './save_modal';
|
||||||
|
import './shareModalCtrl';
|
||||||
|
import './shareSnapshotCtrl';
|
||||||
|
import './dashboard_srv';
|
||||||
|
import './viewStateSrv';
|
||||||
|
import './time_srv';
|
||||||
|
import './unsavedChangesSrv';
|
||||||
|
import './unsaved_changes_modal';
|
||||||
|
import './timepicker/timepicker';
|
||||||
|
import './impression_store';
|
||||||
|
import './upload';
|
||||||
|
import './import/dash_import';
|
||||||
|
import './export/export_modal';
|
||||||
|
import './export_data/export_data_modal';
|
||||||
|
import './ad_hoc_filters';
|
||||||
|
import './repeat_option/repeat_option';
|
||||||
|
import './dashgrid/DashboardGrid';
|
||||||
|
import './dashgrid/PanelLoader';
|
||||||
|
import './dashgrid/RowOptions';
|
||||||
|
import './acl/acl';
|
||||||
|
import './folder_picker/picker';
|
||||||
|
import './folder_modal/folder';
|
||||||
|
import './move_to_folder_modal/move_to_folder';
|
||||||
|
import coreModule from 'app/core/core_module';
|
||||||
|
|
||||||
|
import {DashboardListCtrl} from './dashboard_list_ctrl';
|
||||||
|
|
||||||
|
coreModule.controller('DashboardListCtrl', DashboardListCtrl);
|
117
public/app/features/dashboard/dashboard_list_ctrl.ts
Normal file
117
public/app/features/dashboard/dashboard_list_ctrl.ts
Normal file
@ -0,0 +1,117 @@
|
|||||||
|
import _ from 'lodash';
|
||||||
|
import appEvents from 'app/core/app_events';
|
||||||
|
|
||||||
|
export class DashboardListCtrl {
|
||||||
|
public dashboards: any [];
|
||||||
|
query: any;
|
||||||
|
navModel: any;
|
||||||
|
canDelete = false;
|
||||||
|
canMove = false;
|
||||||
|
|
||||||
|
/** @ngInject */
|
||||||
|
constructor(private backendSrv, navModelSrv, private $q) {
|
||||||
|
this.navModel = navModelSrv.getNav('cfg', 'dashboards');
|
||||||
|
this.query = '';
|
||||||
|
this.getDashboards();
|
||||||
|
}
|
||||||
|
|
||||||
|
getDashboards() {
|
||||||
|
return this.backendSrv.get(`/api/search?query=${this.query}&mode=tree`).then((result) => {
|
||||||
|
|
||||||
|
this.dashboards = this.groupDashboardsInFolders(result);
|
||||||
|
|
||||||
|
for (let dash of this.dashboards) {
|
||||||
|
dash.checked = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
groupDashboardsInFolders(results) {
|
||||||
|
let byId = _.groupBy(results, 'id');
|
||||||
|
let byFolderId = _.groupBy(results, 'folderId');
|
||||||
|
let finalList = [];
|
||||||
|
|
||||||
|
// add missing parent folders
|
||||||
|
_.each(results, (hit, index) => {
|
||||||
|
if (hit.folderId && !byId[hit.folderId]) {
|
||||||
|
const folder = {
|
||||||
|
id: hit.folderId,
|
||||||
|
uri: `db/${hit.folderSlug}`,
|
||||||
|
title: hit.folderTitle,
|
||||||
|
type: 'dash-folder'
|
||||||
|
};
|
||||||
|
byId[hit.folderId] = folder;
|
||||||
|
results.splice(index, 0, folder);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// group by folder
|
||||||
|
for (let hit of results) {
|
||||||
|
if (hit.folderId) {
|
||||||
|
hit.type = "dash-child";
|
||||||
|
} else {
|
||||||
|
finalList.push(hit);
|
||||||
|
}
|
||||||
|
|
||||||
|
hit.url = 'dashboard/' + hit.uri;
|
||||||
|
|
||||||
|
if (hit.type === 'dash-folder') {
|
||||||
|
if (!byFolderId[hit.id]) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let child of byFolderId[hit.id]) {
|
||||||
|
finalList.push(child);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return finalList;
|
||||||
|
}
|
||||||
|
|
||||||
|
selectionChanged() {
|
||||||
|
const selected = _.filter(this.dashboards, {checked: true}).length;
|
||||||
|
this.canDelete = selected > 0;
|
||||||
|
|
||||||
|
const selectedDashboards = _.filter(this.dashboards, (o) => {
|
||||||
|
return o.checked && (o.type === 'dash-db' || o.type === 'dash-child');
|
||||||
|
}).length;
|
||||||
|
|
||||||
|
const selectedFolders = _.filter(this.dashboards, {checked: true, type: 'dash-folder'}).length;
|
||||||
|
this.canMove = selectedDashboards > 0 && selectedFolders === 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
delete() {
|
||||||
|
const selectedDashboards = _.filter(this.dashboards, {checked: true});
|
||||||
|
|
||||||
|
appEvents.emit('confirm-modal', {
|
||||||
|
title: 'Delete',
|
||||||
|
text: `Do you want to delete the ${selectedDashboards.length} selected dashboards?`,
|
||||||
|
icon: 'fa-trash',
|
||||||
|
yesText: 'Delete',
|
||||||
|
onConfirm: () => {
|
||||||
|
const promises = [];
|
||||||
|
for (let dash of selectedDashboards) {
|
||||||
|
promises.push(this.backendSrv.delete(`/api/dashboards/${dash.uri}`));
|
||||||
|
}
|
||||||
|
|
||||||
|
this.$q.all(promises).then(() => {
|
||||||
|
this.getDashboards();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
moveTo() {
|
||||||
|
const selectedDashboards = _.filter(this.dashboards, {checked: true});
|
||||||
|
|
||||||
|
const template = '<move-to-folder-modal dismiss="dismiss()" ' +
|
||||||
|
'dashboards="model.dashboards" after-save="model.afterSave()">' +
|
||||||
|
'</move-to-folder-modal>`';
|
||||||
|
appEvents.emit('show-modal', {
|
||||||
|
templateHtml: template,
|
||||||
|
modalClass: 'modal--narrow',
|
||||||
|
model: {dashboards: selectedDashboards, afterSave: this.getDashboards.bind(this)}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,29 @@
|
|||||||
|
<div class="modal-body">
|
||||||
|
<div class="modal-header">
|
||||||
|
<h2 class="modal-header-title">
|
||||||
|
<i class="gicon gicon-folder-new"></i>
|
||||||
|
<span class="p-l-1">Choose Dashboard Folder</span>
|
||||||
|
</h2>
|
||||||
|
|
||||||
|
<a class="modal-header-close" ng-click="ctrl.dismiss();">
|
||||||
|
<i class="fa fa-remove"></i>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<form name="ctrl.saveForm" ng-submit="ctrl.save()" class="modal-content folder-modal" novalidate>
|
||||||
|
<p>Move the {{ctrl.dashboards.length}} selected dashboards to the following folder:</p>
|
||||||
|
|
||||||
|
<div class="p-t-2">
|
||||||
|
<div class="gf-form">
|
||||||
|
<folder-picker initial-title="Choose"
|
||||||
|
on-change="ctrl.onFolderChange($folder)"
|
||||||
|
label-class="width-7">
|
||||||
|
</folder-picker>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="gf-form-button-row text-center">
|
||||||
|
<button type="submit" class="btn btn-success" ng-disabled="ctrl.saveForm.$invalid">Move</button>
|
||||||
|
<a class="btn-text" ng-click="ctrl.dismiss();">Cancel</a>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
@ -0,0 +1,61 @@
|
|||||||
|
import coreModule from 'app/core/core_module';
|
||||||
|
import appEvents from 'app/core/app_events';
|
||||||
|
import {DashboardModel} from '../dashboard_model';
|
||||||
|
|
||||||
|
export class MoveToFolderCtrl {
|
||||||
|
dashboards: any;
|
||||||
|
folder: any;
|
||||||
|
dismiss: any;
|
||||||
|
afterSave: any;
|
||||||
|
|
||||||
|
/** @ngInject */
|
||||||
|
constructor(private backendSrv, private $q) {}
|
||||||
|
|
||||||
|
onFolderChange(folder) {
|
||||||
|
this.folder = folder;
|
||||||
|
}
|
||||||
|
|
||||||
|
save() {
|
||||||
|
const promises = [];
|
||||||
|
for (let dash of this.dashboards) {
|
||||||
|
const promise = this.backendSrv.get('/api/dashboards/' + dash.uri).then(fullDash => {
|
||||||
|
const model = new DashboardModel(fullDash.dashboard, fullDash.meta);
|
||||||
|
model.folderId = this.folder.id;
|
||||||
|
model.meta.folderId = this.folder.id;
|
||||||
|
model.meta.folderTitle = this.folder.title;
|
||||||
|
const clone = model.getSaveModelClone();
|
||||||
|
return this.backendSrv.saveDashboard(clone);
|
||||||
|
});
|
||||||
|
|
||||||
|
promises.push(promise);
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.$q.all(promises).then(() => {
|
||||||
|
appEvents.emit('alert-success', ['Dashboards Moved', 'OK']);
|
||||||
|
this.dismiss();
|
||||||
|
|
||||||
|
return this.afterSave();
|
||||||
|
}).then(() => {
|
||||||
|
console.log('afterSave');
|
||||||
|
}).catch(err => {
|
||||||
|
appEvents.emit('alert-error', [err.message]);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function moveToFolderModal() {
|
||||||
|
return {
|
||||||
|
restrict: 'E',
|
||||||
|
templateUrl: 'public/app/features/dashboard/move_to_folder_modal/move_to_folder.html',
|
||||||
|
controller: MoveToFolderCtrl,
|
||||||
|
bindToController: true,
|
||||||
|
controllerAs: 'ctrl',
|
||||||
|
scope: {
|
||||||
|
dismiss: "&",
|
||||||
|
dashboards: "=",
|
||||||
|
afterSave: "&"
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
coreModule.directive('moveToFolderModal', moveToFolderModal);
|
88
public/app/features/dashboard/partials/dashboardList.html
Normal file
88
public/app/features/dashboard/partials/dashboardList.html
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
<div class="scroll-canvas">
|
||||||
|
<div gemini-scrollbar>
|
||||||
|
<navbar model="ctrl.navModel"></navbar>
|
||||||
|
<div class="page-container" style="height: 95%">
|
||||||
|
<div class="page-header">
|
||||||
|
<h1>Dashboards</h1>
|
||||||
|
|
||||||
|
<a class="btn btn-success" href="/dashboard/new">
|
||||||
|
<i class="fa fa-plus"></i>
|
||||||
|
Create Dashboard
|
||||||
|
</a>
|
||||||
|
<a class="btn btn-success" href="/dashboard/new/?editview=new-folder">
|
||||||
|
<i class="fa fa-plus"></i>
|
||||||
|
Create Folder
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
<div class="gf-form width-15 gf-form-group">
|
||||||
|
<span style="position: relative;">
|
||||||
|
<input type="text" class="gf-form-input" placeholder="Find Dashboard by name" tabindex="1" give-focus="true"
|
||||||
|
ng-model="ctrl.query" ng-model-options="{ debounce: 500 }" spellcheck='false' ng-change="ctrl.getDashboards()" />
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="gf-form-group" ng-if="ctrl.dashboards.length > 1">
|
||||||
|
<div class="gf-form-button-row">
|
||||||
|
<button type="button"
|
||||||
|
class="btn gf-form-button btn-secondary"
|
||||||
|
ng-disabled="!ctrl.canMove"
|
||||||
|
ng-click="ctrl.moveTo()"
|
||||||
|
bs-tooltip="ctrl.canMove ? '' : 'Select a dashboard to move (cannot move folders)'" data-placement="bottom">
|
||||||
|
<i class="fa fa-exchange"></i> Move to...
|
||||||
|
</button>
|
||||||
|
<button type="button"
|
||||||
|
class="btn gf-form-button btn-inverse"
|
||||||
|
ng-click="ctrl.delete()"
|
||||||
|
ng-disabled="!ctrl.canDelete">
|
||||||
|
<i class="fa fa-trash"></i> Delete
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="admin-list-table" style="height: 80%">
|
||||||
|
<div gemini-scrollbar>
|
||||||
|
<table class="filter-table form-inline" ng-show="ctrl.dashboards.length > 0">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th class="width-4"></th>
|
||||||
|
<th></th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr bindonce ng-repeat="dashboard in ctrl.dashboards">
|
||||||
|
<td class="filter-table__switch-cell" bs-tooltip="" data-placement="right">
|
||||||
|
<gf-form-switch
|
||||||
|
switch-class="gf-form-switch--table-cell"
|
||||||
|
on-change="ctrl.selectionChanged()"
|
||||||
|
checked="dashboard.checked">
|
||||||
|
</gf-form-switch>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<a class="search-item pointer search-item--{{dashboard.type}}"
|
||||||
|
bo-href-i="{{dashboard.url}}">
|
||||||
|
<span class="search-result-tags">
|
||||||
|
<span ng-click="ctrl.filterByTag(tag, $event)" bindonce ng-repeat="tag in dashboard.tags" tag-color-from-name="tag" class="label label-tag">
|
||||||
|
{{tag}}
|
||||||
|
</span>
|
||||||
|
<i class="fa" bo-class="{'fa-star': dashboard.isStarred, 'fa-star-o': !dashboard.isStarred}"></i>
|
||||||
|
</span>
|
||||||
|
<span class="search-result-link">
|
||||||
|
<i class="fa search-result-icon"></i>
|
||||||
|
<span bo-text="dashboard.title"></span>
|
||||||
|
</span>
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<em class="muted" ng-hide="ctrl.dashboards.length > 0">
|
||||||
|
No Dashboards or Folders found.
|
||||||
|
</em>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
174
public/app/features/dashboard/specs/dashboard_list_ctrl.jest.ts
Normal file
174
public/app/features/dashboard/specs/dashboard_list_ctrl.jest.ts
Normal file
@ -0,0 +1,174 @@
|
|||||||
|
import {DashboardListCtrl} from '../dashboard_list_ctrl';
|
||||||
|
import q from 'q';
|
||||||
|
|
||||||
|
describe('DashboardListCtrl', () => {
|
||||||
|
describe('when fetching dashboards', () => {
|
||||||
|
let ctrl;
|
||||||
|
|
||||||
|
describe('and dashboard has parent that is not in search result', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
const response = [
|
||||||
|
{
|
||||||
|
id: 399,
|
||||||
|
title: "Dashboard Test",
|
||||||
|
uri: "db/dashboard-test",
|
||||||
|
type: "dash-db",
|
||||||
|
tags: [],
|
||||||
|
isStarred: false,
|
||||||
|
folderId: 410,
|
||||||
|
folderTitle: "afolder",
|
||||||
|
folderSlug: "afolder"
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
ctrl = new DashboardListCtrl({get: () => q.resolve(response)}, {getNav: () => {}}, q);
|
||||||
|
return ctrl.getDashboards();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should add the missing parent folder to the result', () => {
|
||||||
|
expect(ctrl.dashboards.length).toEqual(2);
|
||||||
|
expect(ctrl.dashboards[0].id).toEqual(410);
|
||||||
|
expect(ctrl.dashboards[1].id).toEqual(399);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
const response = [
|
||||||
|
{
|
||||||
|
id: 410,
|
||||||
|
title: "afolder",
|
||||||
|
uri: "db/afolder",
|
||||||
|
type: "dash-folder",
|
||||||
|
tags: [],
|
||||||
|
isStarred: false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 3,
|
||||||
|
title: "something else",
|
||||||
|
uri: "db/something-else",
|
||||||
|
type: "dash-db",
|
||||||
|
tags: [],
|
||||||
|
isStarred: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 399,
|
||||||
|
title: "Dashboard Test",
|
||||||
|
uri: "db/dashboard-test",
|
||||||
|
type: "dash-db",
|
||||||
|
tags: [],
|
||||||
|
isStarred: false,
|
||||||
|
folderId: 410,
|
||||||
|
folderTitle: "afolder",
|
||||||
|
folderSlug: "afolder"
|
||||||
|
}
|
||||||
|
];
|
||||||
|
ctrl = new DashboardListCtrl({get: () => q.resolve(response)}, {getNav: () => {}}, null);
|
||||||
|
return ctrl.getDashboards();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should group them in folders', () => {
|
||||||
|
expect(ctrl.dashboards.length).toEqual(3);
|
||||||
|
expect(ctrl.dashboards[0].id).toEqual(410);
|
||||||
|
expect(ctrl.dashboards[1].id).toEqual(399);
|
||||||
|
expect(ctrl.dashboards[2].id).toEqual(3);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('when selecting dashboards', () => {
|
||||||
|
let ctrl;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
ctrl = new DashboardListCtrl({get: () => q.resolve([])}, {getNav: () => {}}, null);
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('and no dashboards are selected', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
ctrl.dashboards = [
|
||||||
|
{id: 1, type: 'dash-folder'},
|
||||||
|
{id: 2, type: 'dash-db'}
|
||||||
|
];
|
||||||
|
ctrl.selectionChanged();
|
||||||
|
});
|
||||||
|
|
||||||
|
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', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
ctrl.dashboards = [
|
||||||
|
{id: 1, type: 'dash-folder'},
|
||||||
|
{id: 2, type: 'dash-db', checked: true}
|
||||||
|
];
|
||||||
|
ctrl.selectionChanged();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should enable Move To button', () => {
|
||||||
|
expect(ctrl.canMove).toBeTruthy();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should enable delete button', () => {
|
||||||
|
expect(ctrl.canDelete).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('and one child dashboard is selected', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
ctrl.dashboards = [
|
||||||
|
{id: 1, type: 'dash-folder'},
|
||||||
|
{id: 2, type: 'dash-child', checked: true}
|
||||||
|
];
|
||||||
|
ctrl.selectionChanged();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should enable Move To button', () => {
|
||||||
|
expect(ctrl.canMove).toBeTruthy();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should enable delete button', () => {
|
||||||
|
expect(ctrl.canDelete).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('and one child dashboard and one dashboard is selected', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
ctrl.dashboards = [
|
||||||
|
{id: 1, type: 'dash-folder'},
|
||||||
|
{id: 2, type: 'dash-child', checked: true}
|
||||||
|
];
|
||||||
|
ctrl.selectionChanged();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should enable Move To button', () => {
|
||||||
|
expect(ctrl.canMove).toBeTruthy();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should enable delete button', () => {
|
||||||
|
expect(ctrl.canDelete).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('and one child dashboard and one folder is selected', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
ctrl.dashboards = [
|
||||||
|
{id: 1, type: 'dash-folder', checked: true},
|
||||||
|
{id: 2, type: 'dash-child', checked: true}
|
||||||
|
];
|
||||||
|
ctrl.selectionChanged();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should disable Move To button', () => {
|
||||||
|
expect(ctrl.canMove).toBeFalsy();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should enable delete button', () => {
|
||||||
|
expect(ctrl.canDelete).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
0
public/sass/components/_dash_list.scss
Normal file
0
public/sass/components/_dash_list.scss
Normal file
Loading…
Reference in New Issue
Block a user