Created common navigation header
This patch adds the nodes/drivers navigation header in accordance to the approved UI specification. The state chart had to be adjusted to make room for the driver section, and a new common ironic root state has been introduced to ensure that the menu remains constant. Change-Id: I57fe522a067d515aa5253888ef6c121c4b95bd61
This commit is contained in:
parent
7a3e960b37
commit
a4798afe90
|
@ -1,4 +1,3 @@
|
|||
|
||||
@import "./bootstrap_variables";
|
||||
@import "../../bower_components/bootstrap-sass/assets/stylesheets/bootstrap";
|
||||
@import "./bootstrap_mixins";
|
||||
|
@ -21,6 +20,17 @@
|
|||
@include box-shadow($shadow);
|
||||
}
|
||||
|
||||
/**
|
||||
* Button default should have button primary active state.
|
||||
*/
|
||||
.btn-default {
|
||||
&.active, &.active:active, &.active:focus, &.active:hover {
|
||||
background-color: $brand-primary;
|
||||
color: $btn-primary-color;
|
||||
border-color: $btn-primary-border;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Custom button gradient styles.
|
||||
*/
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
<!DOCTYPE html>
|
||||
<html ng-app="ironic">
|
||||
<head>
|
||||
<title>OpenStack Bare Metal</title>
|
||||
|
|
|
@ -48,7 +48,7 @@ angular.module('ironic').controller('ConfigurationController',
|
|||
vm.select = function(configuration) {
|
||||
$$selectedConfiguration.set(configuration).$promise.then(
|
||||
function() {
|
||||
$state.go('root.ironic');
|
||||
$state.go('root.ironic.nodes');
|
||||
}
|
||||
);
|
||||
};
|
||||
|
|
|
@ -60,4 +60,17 @@ angular.module('ironic').controller('NodeActionController',
|
|||
}
|
||||
}).result;
|
||||
};
|
||||
|
||||
/**
|
||||
* Enroll a new node.
|
||||
*
|
||||
* @return {Promise} A promise that will resolve true if a node has been added.
|
||||
*/
|
||||
vm.enroll = function() {
|
||||
return $uibModal.open({
|
||||
templateUrl: 'view/ironic/enroll/index.html',
|
||||
controller: 'EnrollModalController as ctrl',
|
||||
backdrop: 'static'
|
||||
}).result;
|
||||
};
|
||||
});
|
||||
|
|
|
@ -49,13 +49,5 @@ angular.module('ironic')
|
|||
$log.info('Set power state on ' + node.uuid + ' to ' + stateName);
|
||||
};
|
||||
|
||||
vm.enroll = function() {
|
||||
$uibModal.open({
|
||||
templateUrl: 'view/ironic/enroll/index.html',
|
||||
controller: 'EnrollModalController as ctrl',
|
||||
backdrop: 'static'
|
||||
}).result.then(vm.loadNodes);
|
||||
};
|
||||
|
||||
vm.loadNodes();
|
||||
});
|
||||
|
|
|
@ -25,7 +25,7 @@ angular.module('ironic', ['ui.router', 'ui.bootstrap', 'ironic.util', 'ironic.ap
|
|||
'use strict';
|
||||
|
||||
// Default UI route
|
||||
$urlRouterProvider.otherwise('/ironic');
|
||||
$urlRouterProvider.otherwise('/ironic/nodes');
|
||||
|
||||
// Enable all of our configuration detection methods
|
||||
$$configurationProvider.$enableDefault(true);
|
||||
|
@ -38,18 +38,18 @@ angular.module('ironic', ['ui.router', 'ui.bootstrap', 'ironic.util', 'ironic.ap
|
|||
.state('root', {
|
||||
abstract: true,
|
||||
url: '',
|
||||
templateUrl: 'view/ironic/index.html'
|
||||
templateUrl: 'view/ironic/root.html'
|
||||
})
|
||||
.state('root.ironic', {
|
||||
abstract: true,
|
||||
url: '/ironic',
|
||||
views: {
|
||||
header: {
|
||||
templateUrl: 'view/ironic/header.html',
|
||||
controller: 'HeaderController as headerCtrl'
|
||||
},
|
||||
main: {
|
||||
templateUrl: 'view/ironic/node_list.html',
|
||||
controller: 'NodeListController as nodeListCtrl'
|
||||
root: {
|
||||
templateUrl: 'view/ironic/ironic.html'
|
||||
}
|
||||
},
|
||||
resolve: {
|
||||
|
@ -72,8 +72,13 @@ angular.module('ironic', ['ui.router', 'ui.bootstrap', 'ironic.util', 'ironic.ap
|
|||
}
|
||||
})
|
||||
.state('root.ironic.nodes', {
|
||||
abstract: true,
|
||||
url: '/nodes'
|
||||
url: '/nodes',
|
||||
views: {
|
||||
'main@root.ironic': {
|
||||
templateUrl: 'view/ironic/node_list.html',
|
||||
controller: 'NodeListController as nodeListCtrl'
|
||||
}
|
||||
}
|
||||
})
|
||||
.state('root.ironic.nodes.detail', {
|
||||
abstract: true,
|
||||
|
@ -84,7 +89,7 @@ angular.module('ironic', ['ui.router', 'ui.bootstrap', 'ironic.util', 'ironic.ap
|
|||
}
|
||||
},
|
||||
views: {
|
||||
'main@root': {
|
||||
'main@root.ironic': {
|
||||
templateUrl: 'view/ironic/detail.html',
|
||||
controller: 'NodeDetailController as nodeCtrl'
|
||||
}
|
||||
|
@ -104,13 +109,21 @@ angular.module('ironic', ['ui.router', 'ui.bootstrap', 'ironic.util', 'ironic.ap
|
|||
templateUrl: 'view/ironic/detail_driver.html',
|
||||
controller: 'NodeDetailDriverController as driverCtrl'
|
||||
})
|
||||
.state('root.ironic.drivers', {
|
||||
url: '/drivers',
|
||||
views: {
|
||||
'main@root.ironic': {
|
||||
templateUrl: 'view/ironic/driver_list.html'
|
||||
}
|
||||
}
|
||||
})
|
||||
.state('root.config', {
|
||||
url: '/config',
|
||||
views: {
|
||||
header: {
|
||||
templateUrl: 'view/ironic/config_header.html'
|
||||
},
|
||||
main: {
|
||||
root: {
|
||||
templateUrl: 'view/ironic/config.html',
|
||||
controller: 'ConfigurationController as ctrl'
|
||||
}
|
||||
|
@ -125,7 +138,7 @@ angular.module('ironic', ['ui.router', 'ui.bootstrap', 'ironic.util', 'ironic.ap
|
|||
if (reason === 'no_config') {
|
||||
$state.go('root.config');
|
||||
} else {
|
||||
$state.go('root.ironic');
|
||||
$state.go('root.ironic.nodes');
|
||||
}
|
||||
});
|
||||
$rootScope.$on('$destroy', listener);
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
<div class="row">
|
||||
<div class="col-xs-12">
|
||||
<h1>Driver List</h1>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-xs-12">
|
||||
Not yet implemented.
|
||||
</div>
|
||||
</div>
|
|
@ -0,0 +1,22 @@
|
|||
<div class="row" ng-controller="NodeActionController as ctrl">
|
||||
<div class="col-xs-6">
|
||||
<div class="btn-group btn-group-lg">
|
||||
<button type="button"
|
||||
active-path="\/ironic\/nodes\/?.*"
|
||||
ui-sref="root.ironic.nodes"
|
||||
class="btn btn-default">Nodes</button>
|
||||
<button type="button"
|
||||
ui-sref="root.ironic.drivers"
|
||||
active-path="\/ironic\/drivers\/?.*"
|
||||
class="btn btn-default">Drivers</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-xs-6">
|
||||
<button ng-click="ctrl.enroll()"
|
||||
class="btn btn-primary btn-lg pull-right">
|
||||
<i class="fa fa-plus"></i> Node
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div ui-view="main">
|
||||
</div>
|
|
@ -1,9 +1,5 @@
|
|||
<div class="row">
|
||||
<div class="col-xs-12">
|
||||
<button ng-click="nodeListCtrl.enroll()" class="btn btn-default pull-right-bottom">
|
||||
<i class="fa fa-gear"></i>
|
||||
Enroll Node
|
||||
</button>
|
||||
<h1>Nodes</h1>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<div class="container-fluid" ui-view="header"></div>
|
||||
</nav>
|
||||
|
||||
<div class="container-fluid" ui-view="main"></div>
|
||||
<div class="container-fluid" ui-view="root"></div>
|
||||
|
||||
<nav class="navbar navbar-default navbar-fixed-bottom">
|
||||
<div class="container-fluid" ui-view="footer"></div>
|
|
@ -113,4 +113,22 @@ describe('Unit: Ironic-webclient NodeActionController',
|
|||
}));
|
||||
});
|
||||
|
||||
describe('$scope.enroll', function() {
|
||||
var enrollInjectionProperties = angular.copy(mockInjectionProperties);
|
||||
enrollInjectionProperties.$uibModal = {
|
||||
open: function() {
|
||||
}
|
||||
};
|
||||
|
||||
it('should open a modal',
|
||||
inject(function($q) {
|
||||
var spy = spyOn(enrollInjectionProperties.$uibModal, 'open').and.callFake(function() {
|
||||
return {result: $q.resolve({})};
|
||||
});
|
||||
var controller = $controller('NodeActionController', enrollInjectionProperties);
|
||||
controller.enroll();
|
||||
|
||||
expect(spy.calls.count()).toBe(1);
|
||||
}));
|
||||
});
|
||||
});
|
||||
|
|
|
@ -106,41 +106,4 @@ describe('Unit: Ironic-webclient node list controller',
|
|||
expect(controller.nodes).toBeFalsy();
|
||||
});
|
||||
});
|
||||
|
||||
describe('$scope.enroll', function() {
|
||||
it('should open a modal',
|
||||
inject(function($q) {
|
||||
var spy = spyOn(mockInjectionProperties.$uibModal, 'open').and.callFake(function() {
|
||||
return {result: $q.resolve({})};
|
||||
});
|
||||
var controller = $controller('NodeListController', mockInjectionProperties);
|
||||
controller.enroll();
|
||||
$httpBackend.flush();
|
||||
|
||||
expect(spy.calls.count()).toBe(1);
|
||||
}));
|
||||
|
||||
it('should reload the node list if a new node was added.',
|
||||
inject(function($q) {
|
||||
// Set up a spy.
|
||||
var spy = spyOn(mockInjectionProperties.$uibModal, 'open').and.callFake(function() {
|
||||
return {result: $q.resolve({})};
|
||||
});
|
||||
|
||||
// Initialize the controller.
|
||||
var controller = $controller('NodeListController', mockInjectionProperties);
|
||||
$httpBackend.flush();
|
||||
|
||||
// Setup expected calls
|
||||
$httpBackend
|
||||
.expectGET('http://ironic.example.com:1000/nodes')
|
||||
.respond(200, []);
|
||||
|
||||
// Call Enroll
|
||||
controller.enroll();
|
||||
$httpBackend.flush();
|
||||
|
||||
expect(spy.calls.count()).toBe(1);
|
||||
}));
|
||||
});
|
||||
});
|
||||
|
|
Loading…
Reference in New Issue