Merge "Add global resolution and grouping key options."

This commit is contained in:
Jenkins 2016-01-07 20:01:32 +00:00 committed by Gerrit Code Review
commit c0e53ac836
18 changed files with 300 additions and 65 deletions

View File

@ -5,7 +5,10 @@ var controllersModule = require('./_index');
/**
* @ngInject
*/
function GroupedRunsController(pageTitleService, healthService, runMetadataKey, name, currentDate) {
function GroupedRunsController(
$scope, pageTitleService, healthService, viewService,
runMetadataKey, name, currentDate) {
// ViewModel
var vm = this;
@ -17,6 +20,10 @@ function GroupedRunsController(pageTitleService, healthService, runMetadataKey,
vm.runMetadataKey = decodeURIComponent(runMetadataKey);
vm.name = decodeURIComponent(name);
// update the global grouping key - if we arrived here directly, it will not
// be set already
viewService.groupKey(runMetadataKey);
// Updates the page title based on the selected runMetadataKey
pageTitleService.update(vm.runMetadataKey);
@ -105,13 +112,17 @@ function GroupedRunsController(pageTitleService, healthService, runMetadataKey,
healthService.getRunsForRunMetadataKey(vm.runMetadataKey, vm.name, {
start_date: startDate,
stop_date: stopDate,
datetime_resolution: 'hour'
datetime_resolution: viewService.resolution().key
}).then(function(response) {
vm.processData(response.data);
});
};
vm.loadData();
$scope.$on('view:resolution', function(event, resolution) {
vm.loadData();
});
}
controllersModule.controller('GroupedRunsController', GroupedRunsController);

View File

@ -5,7 +5,7 @@ var controllersModule = require('./_index');
/**
* @ngInject
*/
function HomeController(healthService, startDate, projectService) {
function HomeController($scope, healthService, startDate, projectService, viewService) {
var byFailRateDesc = function(project1, project2) {
// To get descending order, project2 should come first
@ -65,36 +65,33 @@ function HomeController(healthService, startDate, projectService) {
};
};
function loadRunMetadataKeys() {
healthService.getRunMetadataKeys().then(function(response) {
vm.runMetadataKeys = response.data;
});
}
var loadData = function(runMetadataKey) {
var groupBy = runMetadataKey || vm.selectedRunMetadataKey;
vm.selectedRunMetadataKey = groupBy;
var start = new Date(startDate);
start.setDate(start.getDate() - 20);
healthService.getRunsGroupedByMetadataPerDatetime(groupBy, {
healthService.getRunsGroupedByMetadataPerDatetime(vm.groupKey, {
start_date: start,
datetime_resolution: 'hour'
datetime_resolution: viewService.resolution().key
}).then(function(response) {
vm.processData(response.data);
processData(response.data);
});
};
// ViewModel
var vm = this;
vm.searchProject = '';
vm.selectedRunMetadataKey = 'project';
vm.loadRunMetadataKeys = loadRunMetadataKeys;
vm.processData = processData;
vm.loadData = loadData;
vm.groupKey = viewService.groupKey();
vm.searchProject = '';
vm.loadData();
vm.loadRunMetadataKeys();
loadData();
$scope.$on('view:groupKey', function(event, groupKey) {
vm.groupKey = groupKey;
loadData(groupKey);
});
$scope.$on('view:resolution', function(event, resolution) {
loadData();
});
}
controllersModule.controller('HomeController', HomeController);

View File

@ -5,7 +5,7 @@ var controllersModule = require('./_index');
/**
* @ngInject
*/
function JobController(healthService, jobName, startDate) {
function JobController($scope, healthService, viewService, jobName, startDate) {
// ViewModel
var vm = this;
@ -141,13 +141,17 @@ function JobController(healthService, jobName, startDate) {
healthService.getTestsFromBuildName(vm.name, {
start_date: start,
datetime_resolution: 'hour'
datetime_resolution: viewService.resolution().key
}).then(function(response) {
vm.processData(response.data);
});
};
vm.loadData();
$scope.$on('view:resolution', function(event, resolution) {
vm.loadData();
});
}
controllersModule.controller('JobController', JobController);

View File

@ -5,7 +5,7 @@ var controllersModule = require('./_index');
/**
* @ngInject
*/
function TestController(healthService, testService, startDate, testId) {
function TestController($scope, healthService, testService, viewService, startDate, testId) {
// ViewModel
var vm = this;
@ -119,12 +119,17 @@ function TestController(healthService, testService, startDate, testId) {
beginDate.setDate(startDate.getDate() - 15);
healthService.getTestRunList(vm.testName, {
start_date: beginDate,
stop_date: stopDate
stop_date: stopDate,
datetime_resolution: viewService.resolution().key
}).then(function(response) {
vm.processData(response.data);
});
};
vm.loadData();
$scope.$on('view:resolution', function(event, resolution) {
vm.loadData();
});
}
controllersModule.controller('TestController', TestController);

View File

@ -8,7 +8,37 @@ var directivesModule = require('./_index.js');
function crumbMenu() {
var link = function(scope, element, attrs, ctrl, transclude) {
transclude(function(clone) {
angular.element(element[0].querySelector('ol')).append(clone);
angular.element(element[0].querySelector('nav ul')).append(clone);
});
};
/**
* @ngInject
*/
var controller = function($scope, healthService, viewService) {
$scope.resolutionOptions = viewService.resolutionOptions();
$scope.selectedResolution = viewService.resolution();
$scope.selectedGroupKey = viewService.groupKey();
$scope.groupKeys = [];
$scope.setResolution = function(resolution) {
viewService.resolution(resolution);
};
$scope.setGroupKey = function(groupKey) {
viewService.groupKey(groupKey);
};
$scope.$on('view:resolution', function(event, resolution) {
$scope.selectedResolution = resolution;
});
$scope.$on('view:groupKey', function(event, groupKey) {
$scope.selectedGroupKey = groupKey;
});
healthService.getRunMetadataKeys().then(function(response) {
$scope.groupKeys = response.data;
});
};
@ -16,7 +46,12 @@ function crumbMenu() {
restrict: 'E',
transclude: true,
templateUrl: 'crumb-menu.html',
link: link
link: link,
controller: controller,
scope: {
'showGroupKey': '@',
'showResolution': '@'
}
};
}

42
app/js/services/view.js Normal file
View File

@ -0,0 +1,42 @@
'use strict';
var servicesModule = require('./_index.js');
/**
* @ngInject
*/
var viewService = function($rootScope) {
var resolutionOptions = [
{ name: 'Second', key: 'sec'},
{ name: 'Minute', key: 'min' },
{ name: 'Hour', key: 'hour' },
{ name: 'Day', key: 'day' }
];
var resolution = resolutionOptions[2];
var groupKey = 'project';
return {
resolution: function(res) {
if (arguments.length === 1) {
resolution = res;
$rootScope.$broadcast('view:resolution', res);
}
return resolution;
},
resolutionOptions: function() {
return resolutionOptions;
},
groupKey: function(key) {
if (arguments.length === 1) {
groupKey = key;
$rootScope.$broadcast('view:groupKey', groupKey);
}
return groupKey;
}
};
};
servicesModule.factory('viewService', viewService);

View File

@ -0,0 +1,94 @@
.nav-breadcrumb > li:not(:last-child):after {
content: " ";
display: block;
width: 0;
height: 0;
border-top: 17px solid transparent;
border-bottom: 17px solid transparent;
border-left: 10px solid #f8f8f8;
position: absolute;
top: 50%;
margin-top: -17px;
left: 100%;
z-index: 3;
}
.nav-breadcrumb > li:not(:last-child):before {
content: " ";
display: block;
width: 0;
height: 0;
border-top: 17px solid transparent;
border-bottom: 17px solid transparent;
border-left: 10px solid rgb(173, 173, 173);
position: absolute;
top: 50%;
margin-top: -17px;
margin-left: 1px;
left: 100%;
z-index: 3;
}
.navbar-breadcrumb {
min-height: 10px;
}
.navbar-breadcrumb ul:not(.nav-breadcrumb) > li > a {
padding: 6px 10px;
}
.nav-breadcrumb > li {
padding:6px 12px 6px 24px;
}
.nav-breadcrumb > li > a {
padding: 0px;
}
.nav-breadcrumb li:not(:last-child):hover {
background-color: #ebebeb;
}
.nav-breadcrumb > li:first-child {
padding:6px 6px 6px 10px;
}
.btn-breadcrumb > li:last-child {
padding:6px 18px 6px 24px;
}
.nav-breadcrumb > li:not(:last-child):after {
border-left: 10px solid #f8f8f8;
}
.nav-breadcrumb > li:not(:last-child):before {
border-left: 10px solid #ccc;
}
.nav-breadcrumb > li:hover:not(:last-child):after {
border-left: 10px solid #ebebeb;
}
.nav-breadcrumb > li:hover:not(:last-child):before {
border-left: 10px solid #adadad;
}
.navbar-form-xs {
padding: 0px 20px;
margin: 5px 8px;
}
.input-xs {
height: 22px;
padding: 0px 10px;
font-size: 12px;
line-height: 1.5;
border-radius: 3px;
}
.navbar-breadcrumb .container-fluid li[dropdown]:not(:last-child):before {
background: #ebebeb;
width: 1px;
content: "";
display:block;
position: absolute;
top:0;
bottom: 0;
right: 0;
}
.navbar-breadcrumb ul.dropdown-menu a {
cursor: pointer;
}

View File

@ -332,7 +332,7 @@ $grid-columns: 12 !default;
$grid-gutter-width: 30px !default;
// Navbar collapse
//** Point at which the navbar becomes uncollapsed.
$grid-float-breakpoint: $screen-sm-min !default;
$grid-float-breakpoint: 0px !default;
//** Point at which the navbar begins collapsing.
$grid-float-breakpoint-max: ($grid-float-breakpoint - 1) !default;

View File

@ -6,3 +6,4 @@
@import 'nv.d3';
@import 'header';
@import 'footer';
@import 'breadcrumbs'

View File

@ -1,17 +1,62 @@
<ol class="breadcrumb">
<li dropdown>
<span ng-switch on="'tests' | isState">
<a ng-switch-when="true" dropdown-toggle href>Tests <fa name="caret-down"></fa></a>
<a ng-switch-default dropdown-toggle href>Overview <fa name="caret-down"></fa></a>
</span>
<nav class="navbar-breadcrumb navbar navbar-default">
<ul class="nav navbar-nav navbar-left nav-breadcrumb">
<li><a ui-sref="home"><fa name="home"></fa></a></li>
<li dropdown>
<span ng-switch on="'tests' | isState">
<a ng-switch-when="true" dropdown-toggle href>
Tests <fa name="caret-down"></fa>
</a>
<a ng-switch-default dropdown-toggle href>
Overview <fa name="caret-down"></fa>
</a>
</span>
<ul role="menu" class="dropdown-menu">
<li>
<a ui-sref="home"><fa name="line-chart" fw></fa> Overview</a>
<ul role="menu" class="dropdown-menu">
<li>
<a ui-sref="home"><fa name="line-chart" fw></fa> Overview</a>
</li>
<li>
<a ui-sref="tests"><fa name="bar-chart" fw></fa> Tests</a>
</li>
</ul>
</li>
</ul>
<div class="container-fluid">
<ul class="nav navbar-nav navbar-right">
<li dropdown ng-if="showGroupKey == 'true'">
<a dropdown-toggle href title="Group By Key">
<fa name="key"></fa>
&nbsp;Grouping: {{selectedGroupKey}}&nbsp;
<fa name="caret-down"></fa>
</a>
<ul role="menu" class="dropdown-menu">
<li ng-repeat="key in groupKeys">
<a ng-click="setGroupKey(key)">
{{key}}
<fa name="check"
class="pull-right"
ng-if="key == selectedGroupKey"></fa>
</a>
</li>
</ul>
</li>
<li>
<a ui-sref="tests"><fa name="bar-chart" fw></fa> Tests</a>
<li dropdown ng-if="showResolution == 'true'">
<a dropdown-toggle href title="Resolution">
<fa name="expand"></fa>
&nbsp;Resolution: {{selectedResolution.key}}&nbsp;
<fa name="caret-down"></fa>
</a>
<ul role="menu" class="dropdown-menu">
<li ng-repeat="res in resolutionOptions">
<a ng-click="setResolution(res)">
{{res.name}}
<fa name="check"
class="pull-right"
ng-if="res == selectedResolution"></fa>
</a>
</li>
</ul>
</li>
</ul>
</li>
</ol>
</div>
</nav>

View File

@ -1,7 +1,7 @@
<header class="bs-header">
<div class="container">
<h1 class="page-header">{{ groupedRuns.name }} jobs</h1>
<crumb-menu>
<crumb-menu show-resolution="true">
<li>Project: {{ groupedRuns.name }}</li>
</crumb-menu>
</div>

View File

@ -3,7 +3,7 @@
<div class="row">
<div class="col-lg-12">
<h1 class="page-header">OpenStack Health</h1>
<crumb-menu></crumb-menu>
<crumb-menu show-group-key="true" show-resolution="true"></crumb-menu>
<loading-indicator></loading-indicator>
</div>
</div>
@ -36,15 +36,6 @@
<div class="row">
<div class="col-lg-12">
<form>
<div class="form-group">
<label for="sel1">Group information by:</label>
<select ng-init="selectedRunMetadataKey = 'project'"
ng-model="selectedRunMetadataKey"
ng-options="runMetadataKey for runMetadataKey in home.runMetadataKeys"
ng-change="home.loadData(selectedRunMetadataKey)"
class="form-control">
</select>
</div>
<div class="form-group">
<div class="input-group">
<div class="input-group-addon"><i class="fa fa-search"></i></div>
@ -56,7 +47,7 @@
<div class="col-lg-4" ng-repeat="project in home.projects | filter:home.searchProject">
<div class="panel panel-default">
<div class="panel-heading">
<a ui-sref="groupedRuns({ runMetadataKey: home.selectedRunMetadataKey, name: project.name })">
<a ui-sref="groupedRuns({ runMetadataKey: home.groupKey, name: project.name })">
<h3 class="panel-title">{{project.name}}</h3>
</a>
</div>

View File

@ -1,7 +1,7 @@
<header class="bs-header">
<div class="container">
<h1 class="page-header">{{ job.name }} tests</h1>
<crumb-menu>
<crumb-menu show-resolution="true">
<li>Job: {{ job.name }}</li>
</crumb-menu>
</div>

View File

@ -1,7 +1,7 @@
<header class="bs-header">
<div class="container">
<h1 class="page-header">{{ testCtrl.testShortName }}</h1>
<crumb-menu>
<crumb-menu show-resolution="true">
<li>Test: {{testCtrl.testShortName }}</li>
</crumb-menu>
</div>

View File

@ -4,11 +4,12 @@ describe('GroupedRunsController', function() {
module('app.controllers');
});
var $httpBackend, $controller, healthService;
var $scope, $httpBackend, $controller, healthService;
var API_ROOT = 'http://8.8.4.4:8080';
var DEFAULT_CURRENT_DATE = new Date();
beforeEach(inject(function(_$httpBackend_, _$controller_, _healthService_) {
beforeEach(inject(function($rootScope, _$httpBackend_, _$controller_, _healthService_) {
$scope = $rootScope.$new();
$httpBackend = _$httpBackend_;
mockConfigService();
mockHealthService();
@ -78,6 +79,7 @@ describe('GroupedRunsController', function() {
it('should process chart data correctly', function() {
var groupedRunsController = $controller('GroupedRunsController', {
$scope: $scope,
healthService: healthService,
runMetadataKey: 'project',
name: 'openstack/cinder',
@ -104,6 +106,7 @@ describe('GroupedRunsController', function() {
it('should process chart data rate correctly', function() {
var groupedRunsController = $controller('GroupedRunsController', {
$scope: $scope,
healthService: healthService,
runMetadataKey: 'project',
name: 'openstack/cinder',

View File

@ -3,7 +3,7 @@ describe('HomeController', function() {
module('app');
});
var $controller, homeController, projectService;
var $scope, $controller, homeController, projectService;
var mockResponse = { data: {} };
var mockMetadataKeysResponse = {
data: {
@ -15,7 +15,8 @@ describe('HomeController', function() {
}
};
beforeEach(inject(function(_$controller_) {
beforeEach(inject(function($rootScope, _$controller_) {
$scope = $rootScope.$new();
$controller = _$controller_;
var defaultStartDate = new Date();
@ -36,6 +37,7 @@ describe('HomeController', function() {
};
homeController = $controller('HomeController', {
$scope: $scope,
healthService: healthService,
startDate: defaultStartDate,
projectService: projectService

View File

@ -4,17 +4,17 @@ describe('JobController', function() {
module('app.controllers');
});
var $httpBackend, $controller, healthService;
var $scope, $httpBackend, $controller, healthService;
var API_ROOT = 'http://8.8.4.4:8080';
var DEFAULT_START_DATE = new Date();
beforeEach(inject(function(_$httpBackend_, _$controller_, _healthService_) {
beforeEach(inject(function($rootScope, _$httpBackend_, _$controller_, _healthService_) {
$httpBackend = _$httpBackend_;
mockConfigService();
mockHealthService();
$scope = $rootScope.$new();
$controller = _$controller_;
healthService = _healthService_;
}));
@ -64,6 +64,7 @@ describe('JobController', function() {
it('should process chart data correctly', function() {
var jobController = $controller('JobController', {
$scope: $scope,
healthService: healthService,
jobName: 'gate-tempest-dsvm-neutron-full',
startDate: DEFAULT_START_DATE
@ -97,6 +98,7 @@ describe('JobController', function() {
it('should process chart data rate correctly', function() {
var jobController = $controller('JobController', {
$scope: $scope,
healthService: healthService,
jobName: 'gate-tempest-dsvm-neutron-full',
startDate: DEFAULT_START_DATE
@ -115,6 +117,7 @@ describe('JobController', function() {
it('should process tests correctly', function() {
var jobController = $controller('JobController', {
$scope: $scope,
healthService: healthService,
jobName: 'gate-tempest-dsvm-neutron-full',
startDate: DEFAULT_START_DATE

View File

@ -4,16 +4,17 @@ describe('TestsController', function() {
module('app.controllers');
});
var $httpBackend, $controller, healthService;
var $scope, $httpBackend, $controller, healthService;
var API_ROOT = 'http://8.8.4.4:8080';
var DEFAULT_START_DATE = new Date();
beforeEach(inject(function(_$httpBackend_, _$controller_, _healthService_) {
beforeEach(inject(function($rootScope, _$httpBackend_, _$controller_, _healthService_) {
$httpBackend = _$httpBackend_;
mockConfigService();
mockHealthService();
$scope = $rootScope.$new();
$controller = _$controller_;
healthService = _healthService_;
}));
@ -61,7 +62,8 @@ describe('TestsController', function() {
it('should process chart data correctly', function() {
var testsController = $controller('TestsController', {
healthService: healthService
healthService: healthService,
$scope: $scope
});
$httpBackend.flush();