Merge branch 'master' of github.com:open-cloud/xos
diff --git a/.gitignore b/.gitignore
index cc49c01..451dd79 100644
--- a/.gitignore
+++ b/.gitignore
@@ -8,3 +8,4 @@
xos/core/xoslib/docs
xos/core/xoslib/coverage
node_modules
+xos/xos_configuration/*
diff --git a/xos/core/static/xos.css b/xos/core/static/xos.css
index 40cfcc3..685361e 100644
--- a/xos/core/static/xos.css
+++ b/xos/core/static/xos.css
@@ -62,6 +62,7 @@
-moz-transition: all 0.5s ease;
-o-transition: all 0.5s ease;
transition: all 0.5s ease;
+ background: white;
}
#wrapper.toggled #sidebar-wrapper {
diff --git a/xos/core/xoslib/dashboards/xosCeilometerDashboard.html b/xos/core/xoslib/dashboards/xosCeilometerDashboard.html
index 1db309a..22511f4 100644
--- a/xos/core/xoslib/dashboards/xosCeilometerDashboard.html
+++ b/xos/core/xoslib/dashboards/xosCeilometerDashboard.html
@@ -3,8 +3,9 @@
<!-- browserSync -->
<!-- inject:css -->
-<link rel="stylesheet" href="/static/css/ceilometerDashboard.css">
+<link rel="stylesheet" href="/../../static/css/xosCeilometerDashboard.css">
<!-- endinject -->
+<link rel="stylesheet" href="css/ceilometerDashboard.css">
<div id="xosCeilometerDashboard">
<div ui-view ng-class="stateName"></div>
</div>
diff --git a/xos/core/xoslib/ngXosViews/ceilometerDashboard/.eslintrc b/xos/core/xoslib/ngXosViews/ceilometerDashboard/.eslintrc
index f495e79..868fd4b 100644
--- a/xos/core/xoslib/ngXosViews/ceilometerDashboard/.eslintrc
+++ b/xos/core/xoslib/ngXosViews/ceilometerDashboard/.eslintrc
@@ -16,7 +16,7 @@
],
"rules": {
"quotes": [2, "single"],
- "camelcase": [1, {"properties": "always"}],
+ "camelcase": [0, {"properties": "always"}],
"no-underscore-dangle": 1,
"eqeqeq": [2, "smart"],
"no-alert": 1,
@@ -38,6 +38,7 @@
//"angular/ng_di": [0, "function or array"]
},
"globals" :{
- "angular": true
+ "angular": true,
+ "Chart": true
}
}
\ No newline at end of file
diff --git a/xos/core/xoslib/ngXosViews/ceilometerDashboard/env/default.js b/xos/core/xoslib/ngXosViews/ceilometerDashboard/env/default.js
index 26dd953..8fc0bd5 100644
--- a/xos/core/xoslib/ngXosViews/ceilometerDashboard/env/default.js
+++ b/xos/core/xoslib/ngXosViews/ceilometerDashboard/env/default.js
@@ -8,6 +8,6 @@
module.exports = {
host: 'http://clnode015.clemson.cloudlab.us:9999/',
- xoscsrftoken: 'kL0QrqJ5Y3TbTR6mLgPBGVCMNv2JksQv',
- xossessionid: '8ygydigw52qgc715fgznj15k7nfe1139'
+ xoscsrftoken: 'w0qMPZCk8nByQh9Zy86nPs5OM5G5lKdb',
+ xossessionid: 'kvv2aa1il6u4i7j6yu2399r4tdpdeoxz'
};
diff --git a/xos/core/xoslib/ngXosViews/ceilometerDashboard/gulp/build.js b/xos/core/xoslib/ngXosViews/ceilometerDashboard/gulp/build.js
index d0d38f9..9f9bfb8 100644
--- a/xos/core/xoslib/ngXosViews/ceilometerDashboard/gulp/build.js
+++ b/xos/core/xoslib/ngXosViews/ceilometerDashboard/gulp/build.js
@@ -22,6 +22,10 @@
var inject = require('gulp-inject');
var rename = require('gulp-rename');
var replace = require('gulp-replace');
+var postcss = require('gulp-postcss');
+var autoprefixer = require('autoprefixer');
+var mqpacker = require('css-mqpacker');
+var csswring = require('csswring');
var TEMPLATE_FOOTER = `}]);
angular.module('xos.ceilometerDashboard').run(function($location){$location.path('/')});
@@ -37,6 +41,28 @@
);
});
+ // minify css
+ gulp.task('css', function () {
+ var processors = [
+ autoprefixer({browsers: ['last 1 version']}),
+ mqpacker,
+ csswring
+ ];
+
+ gulp.src([
+ `${options.css}**/*.css`,
+ `!${options.css}dev.css`
+ ])
+ .pipe(postcss(processors))
+ .pipe(gulp.dest(options.tmp + '/css/'));
+ });
+
+ gulp.task('copyCss', ['css'], function(){
+ return gulp.src([`${options.tmp}/css/*.css`])
+ .pipe(concat('xosCeilometerDashboard.css'))
+ .pipe(gulp.dest(options.static + 'css/'))
+ });
+
// compile and minify scripts
gulp.task('scripts', function() {
return gulp.src([
@@ -67,12 +93,15 @@
.pipe(replace(/<!-- bower:css -->(\n.*)*\n<!-- endbower --><!-- endcss -->/, ''))
.pipe(replace(/<!-- bower:js -->(\n.*)*\n<!-- endbower --><!-- endjs -->/, ''))
.pipe(replace(/ng-app=".*"\s/, ''))
+ //rewriting css path
+ // .pipe(replace(/(<link.*">)/, ''))
// injecting minified files
.pipe(
inject(
gulp.src([
options.static + 'js/vendor/xosCeilometerDashboardVendor.js',
- options.static + 'js/xosCeilometerDashboard.js'
+ options.static + 'js/xosCeilometerDashboard.js',
+ options.static + 'css/xosCeilometerDashboard.css'
])
)
)
@@ -107,11 +136,13 @@
gulp.task('build', function() {
runSequence(
+ 'lint',
'templates',
'babel',
'scripts',
'wiredep',
'copyHtml',
+ 'copyCss',
'cleanTmp'
);
});
diff --git a/xos/core/xoslib/ngXosViews/ceilometerDashboard/gulp/server.js b/xos/core/xoslib/ngXosViews/ceilometerDashboard/gulp/server.js
index d176950..7268b13 100644
--- a/xos/core/xoslib/ngXosViews/ceilometerDashboard/gulp/server.js
+++ b/xos/core/xoslib/ngXosViews/ceilometerDashboard/gulp/server.js
@@ -107,7 +107,7 @@
options.api + '*.js',
options.helpers + '**/*.js'
])
- .pipe(debug({title: 'unicorn:'}))
+ // .pipe(debug({title: 'unicorn:'}))
.pipe(angularFilesort()),
{
ignorePath: [options.src, '/../../ngXosLib']
diff --git a/xos/core/xoslib/ngXosViews/ceilometerDashboard/gulpfile.js b/xos/core/xoslib/ngXosViews/ceilometerDashboard/gulpfile.js
index f114774..de911e9 100644
--- a/xos/core/xoslib/ngXosViews/ceilometerDashboard/gulpfile.js
+++ b/xos/core/xoslib/ngXosViews/ceilometerDashboard/gulpfile.js
@@ -5,6 +5,7 @@
var options = {
src: 'src/',
+ css: 'src/css/',
scripts: 'src/js/',
tmp: 'src/.tmp',
dist: 'dist/',
diff --git a/xos/core/xoslib/ngXosViews/ceilometerDashboard/karma.conf.js b/xos/core/xoslib/ngXosViews/ceilometerDashboard/karma.conf.js
index dbd344a..12d0697 100644
--- a/xos/core/xoslib/ngXosViews/ceilometerDashboard/karma.conf.js
+++ b/xos/core/xoslib/ngXosViews/ceilometerDashboard/karma.conf.js
@@ -10,9 +10,8 @@
var bowerComponents = wiredep( {devDependencies: true} )[ 'js' ].map(function( file ){
return path.relative(process.cwd(), file);
});
-
-module.exports = function(config) {
/*eslint-enable*/
+module.exports = function(config) {
config.set({
// base path that will be used to resolve all patterns (eg. files, exclude)
@@ -45,10 +44,17 @@
// available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
preprocessors: {
'src/js/**/*.js': ['babel'],
- 'spec/**/*.test.js': ['babel'],
+ 'spec/**/*.js': ['babel'],
'src/**/*.html': ['ng-html2js']
},
+ babelPreprocessor: {
+ options: {
+ presets: ['es2015'],
+ sourceMap: 'inline'
+ }
+ },
+
ngHtml2JsPreprocessor: {
stripPrefix: 'src/', //strip the src path from template url (http://stackoverflow.com/questions/22869668/karma-unexpected-request-when-testing-angular-directive-even-with-ng-html2js)
moduleName: 'templates' // define the template module name
diff --git a/xos/core/xoslib/ngXosViews/ceilometerDashboard/package.json b/xos/core/xoslib/ngXosViews/ceilometerDashboard/package.json
index ba3a8fd..0a9ccae 100644
--- a/xos/core/xoslib/ngXosViews/ceilometerDashboard/package.json
+++ b/xos/core/xoslib/ngXosViews/ceilometerDashboard/package.json
@@ -7,6 +7,7 @@
"start": "gulp serve",
"prebuild": "npm install && bower install",
"build": "gulp",
+ "pretest": "npm install",
"test": "karma start",
"lint": "eslint src/js/"
},
@@ -19,7 +20,12 @@
"license": "MIT",
"dependencies": {},
"devDependencies": {
+ "autoprefixer": "^6.1.2",
+ "babel": "^6.3.13",
+ "babel-preset-es2015": "^6.3.13",
"browser-sync": "^2.9.11",
+ "css-mqpacker": "^4.0.0",
+ "csswring": "^4.1.1",
"del": "^2.0.2",
"eslint": "^1.8.0",
"eslint-plugin-angular": "linkmesrl/eslint-plugin-angular",
@@ -33,12 +39,21 @@
"gulp-inject": "^3.0.0",
"gulp-minify-html": "^1.0.4",
"gulp-ng-annotate": "^1.1.0",
+ "gulp-postcss": "^6.0.1",
"gulp-rename": "^1.2.2",
"gulp-replace": "^0.5.4",
"gulp-uglify": "^1.4.2",
"http-proxy": "^1.12.0",
+ "jasmine-core": "^2.4.1",
"karma": "^0.13.15",
+ "karma-babel-preprocessor": "^6.0.1",
+ "karma-jasmine": "^0.3.6",
+ "karma-mocha-reporter": "^1.1.3",
+ "karma-ng-html2js-preprocessor": "^0.2.0",
+ "karma-phantomjs-launcher": "^0.2.1",
"lodash": "^3.10.1",
+ "mocha": "^2.3.4",
+ "phantomjs": "^1.9.19",
"proxy-middleware": "^0.15.0",
"run-sequence": "^1.1.4",
"wiredep": "^3.0.0-beta",
diff --git a/xos/core/xoslib/ngXosViews/ceilometerDashboard/spec/.eslintrc b/xos/core/xoslib/ngXosViews/ceilometerDashboard/spec/.eslintrc
new file mode 100644
index 0000000..ad4bc2d
--- /dev/null
+++ b/xos/core/xoslib/ngXosViews/ceilometerDashboard/spec/.eslintrc
@@ -0,0 +1,9 @@
+{
+ "globals" :{
+ "describe": true,
+ "beforeEach": true,
+ "it": true,
+ "inject": true,
+ "expect": true
+ }
+}
diff --git a/xos/core/xoslib/ngXosViews/ceilometerDashboard/spec/backend.mock.js b/xos/core/xoslib/ngXosViews/ceilometerDashboard/spec/backend.mock.js
new file mode 100644
index 0000000..c7642bb
--- /dev/null
+++ b/xos/core/xoslib/ngXosViews/ceilometerDashboard/spec/backend.mock.js
@@ -0,0 +1,98 @@
+'use strict';
+(function () {
+
+ const meters = [
+ // service_1
+ // - slice_1
+ // - resource_1
+ // service_2
+ // - slice_2
+ // - resource_2
+ // - resource_3
+ // - slice_3
+ // - resource_4
+ {
+ service: 'service_1',
+ slice: 'slice_1',
+ resource_name: 'resource_1',
+ resource_id: 'resource_id_1',
+ name: 'instance_1',
+ unit: 'instance'
+ },
+ {
+ service: 'service_2',
+ slice: 'slice_2',
+ resource_name: 'resource_2',
+ resource_id: 'resource_id_2',
+ name: 'instance_2',
+ unit: 'instance'
+ },
+ {
+ service: 'service_2',
+ slice: 'slice_2',
+ resource_name: 'resource_3',
+ resource_id: 'resource_id_3',
+ name: 'instance_2',
+ unit: 'instance'
+ },
+ {
+ service: 'service_2',
+ slice: 'slice_3',
+ resource_name: 'resource_4',
+ resource_id: 'resource_id_4',
+ name: 'instance_3',
+ unit: 'instance'
+ }
+ ];
+
+ const samples = [
+ {
+ meter: 'cpu',
+ resource_name: 'fakeName',
+ project_id: 'fakeTenant',
+ timestamp: '2015-12-15T00:34:08',
+ volume: 110
+ },
+ {
+ meter: 'cpu',
+ resource_name: 'fakeName',
+ project_id: 'fakeTenant',
+ timestamp: '2015-12-15T00:44:08',
+ volume: 120
+ },
+ {
+ meter: 'cpu',
+ resource_name: 'anotherName',
+ project_id: 'anotherTenant',
+ timestamp: '2015-12-15T00:24:08',
+ volume: 210
+ },
+ {
+ meter: 'cpu',
+ resource_name: 'anotherName',
+ project_id: 'anotherTenant',
+ timestamp: '2015-12-15T00:34:08',
+ volume: 220
+ },
+ {
+ meter: 'cpu',
+ resource_name: 'anotherName',
+ project_id: 'anotherTenant',
+ timestamp: '2015-12-15T00:44:08',
+ volume: 230
+ },
+ {
+ meter: 'cpu',
+ resource_name: 'thirdName',
+ project_id: 'thirdTenant',
+ timestamp: '2015-12-15T00:44:08',
+ volume: 310
+ }
+ ];
+
+ angular.module('xos.ceilometerDashboard')
+ .run(($httpBackend) => {
+ $httpBackend.whenGET(/metersamples/).respond(samples);
+ $httpBackend.whenGET(/meters/).respond(meters);
+ });
+})();
diff --git a/xos/core/xoslib/ngXosViews/ceilometerDashboard/spec/ceilometer.test.js b/xos/core/xoslib/ngXosViews/ceilometerDashboard/spec/ceilometer.test.js
new file mode 100644
index 0000000..c5bb850
--- /dev/null
+++ b/xos/core/xoslib/ngXosViews/ceilometerDashboard/spec/ceilometer.test.js
@@ -0,0 +1,137 @@
+'use strict';
+
+describe('In Ceilometer View', () => {
+
+ var scope, element, vm, httpBackend;
+
+ beforeEach(module('xos.ceilometerDashboard'));
+ beforeEach(module('templates'));
+
+ beforeEach(inject(($httpBackend, $rootScope) => {
+ httpBackend = $httpBackend;
+ scope = $rootScope.$new();
+ }))
+
+ describe('The dashboard', () => {
+ beforeEach(inject(function($httpBackend, $compile){
+ element = angular.element('<ceilometer-dashboard></ceilometer-dashboard>');
+ $compile(element)(scope);
+ scope.$digest();
+ vm = element.isolateScope().vm;
+ httpBackend.flush();
+ }));
+
+ describe('when loading meters', () => {
+ it('should group meters by services', () => {
+ expect(Object.keys(vm.projects).length).toBe(2);
+ });
+
+ it('should group services by slices', () => {
+ expect(Object.keys(vm.projects.service_2).length).toBe(2);
+ });
+
+ it('should group slices by resources', () => {
+ expect(Object.keys(vm.projects.service_2.slice_2).length).toBe(2);
+ });
+ });
+ });
+
+ describe('the sample view', () => {
+ beforeEach(inject(function($httpBackend, $compile, $stateParams){
+
+ $stateParams.name = 'fakeName';
+ $stateParams.tenant = 'fakeTenant';
+
+ element = angular.element('<ceilometer-samples></ceilometer-samples>');
+ $compile(element)(scope);
+ scope.$digest();
+ vm = element.isolateScope().vm;
+ httpBackend.flush();
+ }));
+
+ it('should group samples by resource_id', () => {
+ expect(Object.keys(vm.samplesList.fakeTenant).length).toBe(2)
+ expect(Object.keys(vm.samplesList.anotherTenant).length).toBe(3)
+ expect(Object.keys(vm.samplesList.thirdTenant).length).toBe(1)
+ });
+
+ it('should add the comparable samples to the dropdown list', () => {
+ expect(vm.sampleLabels[0].id).toEqual('anotherTenant')
+ expect(vm.sampleLabels[1].id).toEqual('thirdTenant')
+ });
+
+ it('should add the selected meter to the chart', () => {
+ expect(vm.chart.labels.length).toBe(2);
+ expect(vm.chart.series[0]).toBe('fakeTenant');
+ expect(vm.chart.data[0].length).toBe(2);
+ expect(vm.chart.data[0][0]).toBe(110);
+ expect(vm.chart.data[0][1]).toBe(120);
+ expect(vm.chartMeters[0].project_id).toBe('fakeTenant')
+ expect(vm.chartMeters[0].resource_name).toBe('fakeName')
+ });
+
+ it('should add a sample to the chart', () => {
+ vm.addMeterToChart('anotherTenant');
+ expect(vm.chart.labels.length).toBe(3);
+ expect(vm.chart.data[1].length).toBe(3);
+ expect(vm.chart.data[1][0]).toBe(210);
+ expect(vm.chart.data[1][1]).toBe(220);
+ expect(vm.chart.data[1][2]).toBe(230);
+ expect(vm.chartMeters[1].project_id).toBe('anotherTenant')
+ expect(vm.chartMeters[1].resource_name).toBe('anotherName')
+ });
+
+ it('should remove a sample from the chart', () => {
+ // for simplyvity add a tenant (it's tested)
+ vm.addMeterToChart('anotherTenant');
+ vm.removeFromChart(vm.chartMeters[0]);
+ expect(vm.chart.data[0].length).toBe(3);
+ expect(vm.chart.data[0][0]).toBe(210);
+ expect(vm.chart.data[0][1]).toBe(220);
+ expect(vm.chart.data[0][2]).toBe(230);
+ expect(vm.chartMeters[0].project_id).toBe('anotherTenant')
+ expect(vm.chartMeters[0].resource_name).toBe('anotherName')
+ });
+
+ describe('The format sample labels method', () => {
+ it('should create an array of unique labels', () => {
+ // unique because every resource has multiple samples (time-series)
+ const samples = [
+ {project_id: 1, resource_name: 'fakeName'},
+ {project_id: 1, resource_name: 'fakeName'},
+ {project_id: 2, resource_name: 'anotherName'},
+ {project_id: 2, resource_name: 'anotherName'}
+ ];
+
+ const result = vm.formatSamplesLabels(samples);
+
+ expect(result.length).toBe(2);
+ expect(result[0]).toEqual({id: 1, name: 'fakeName'});
+ expect(result[1]).toEqual({id: 2, name: 'anotherName'});
+ });
+ });
+ });
+});
+
+describe('The orderObjectByKey filter', () => {
+ var $filter;
+
+ beforeEach(function () {
+ module('xos.ceilometerDashboard');
+
+ inject(function (_$filter_) {
+ $filter = _$filter_;
+ });
+ });
+
+ it('should order an object by the key value', function () {
+ // Arrange.
+ const list = {c: 3, b: 2, a: 1};
+
+ // call the filter function
+ const result = $filter('orderObjectByKey')(list);
+
+ // Assert.
+ expect(result).toEqual({a: 1, b: 2, c: 3});
+ });
+});
\ No newline at end of file
diff --git a/xos/core/xoslib/ngXosViews/ceilometerDashboard/spec/sample.test.js b/xos/core/xoslib/ngXosViews/ceilometerDashboard/spec/sample.test.js
deleted file mode 100644
index a224095..0000000
--- a/xos/core/xoslib/ngXosViews/ceilometerDashboard/spec/sample.test.js
+++ /dev/null
@@ -1,34 +0,0 @@
-'use strict';
-
-describe('The User List', () => {
-
- var scope, element, isolatedScope, httpBackend;
-
- beforeEach(module('xos.ceilometerDashboard'));
- beforeEach(module('templates'));
-
- beforeEach(inject(function($httpBackend, $compile, $rootScope){
-
- httpBackend = $httpBackend;
- // Setting up mock request
- $httpBackend.expectGET(/meters/).respond([
- {
- email: 'teo@onlab.us',
- firstname: 'Matteo',
- lastname: 'Scandolo'
- }
- ]);
-
- scope = $rootScope.$new();
- element = angular.element('<ceilometer-dashboard></ceilometer-dashboard>');
- $compile(element)(scope);
- scope.$digest();
- isolatedScope = element.isolateScope().vm;
- }));
-
- it('should load 1 users', () => {
- httpBackend.flush();
- expect(isolatedScope.meters.length).toBe(1);
- });
-
-});
\ No newline at end of file
diff --git a/xos/core/xoslib/ngXosViews/ceilometerDashboard/src/css/ceilometerDashboard.css b/xos/core/xoslib/ngXosViews/ceilometerDashboard/src/css/ceilometerDashboard.css
index 9b53d98..879d7b4 100644
--- a/xos/core/xoslib/ngXosViews/ceilometerDashboard/src/css/ceilometerDashboard.css
+++ b/xos/core/xoslib/ngXosViews/ceilometerDashboard/src/css/ceilometerDashboard.css
@@ -1,267 +1,263 @@
-/*ceilometer-dashboard{*/
+#xosCeilometerDashboard{
+ position: relative;
+}
- #xosCeilometerDashboard{
- position: relative;
+/* Panel Layout */
+.panel {
+ margin-top: 10px;
+}
+
+.panel-body:not(:first-child) {
+ border-top: 1px solid #e3e3e3;
+}
+
+.panel-body .row {
+ margin-top: 10px;
+}
+
+/* Chart details */
+.chart {
+ width: 100%;
+ height: 300px;
+}
+
+.btn-chart, .btn-chart:hover {
+ color: #fff;
+}
+
+.side-container {
+ position: relative;
+}
+
+.service-list {
+ margin-top: -10px;
+}
+
+.service-list h3 {
+ margin-top: 0px;
+ margin-bottom: 0px;
+}
+
+.service-list a {
+ text-decoration: none;
+ color: #333;
+}
+
+.meters, .stats {
+ margin-top: 25px;
+ position: absolute;
+ top: 0;
+ left: 0;
+ width: 100%;
+}
+
+/* LOADER */
+.loader {
+ font-size: 10px;
+ margin: 150px auto;
+ text-indent: -9999em;
+ width: 11em;
+ height: 11em;
+ border-radius: 50%;
+ background: #ffffff;
+ background: -moz-linear-gradient(left, #ffffff 10%, rgba(255, 255, 255, 0) 42%);
+ background: -webkit-linear-gradient(left, #ffffff 10%, rgba(255, 255, 255, 0) 42%);
+ background: -o-linear-gradient(left, #ffffff 10%, rgba(255, 255, 255, 0) 42%);
+ background: -ms-linear-gradient(left, #ffffff 10%, rgba(255, 255, 255, 0) 42%);
+ background: linear-gradient(to right, #ffffff 10%, rgba(255, 255, 255, 0) 42%);
+ position: relative;
+ -webkit-animation: load3 1.4s infinite linear;
+ animation: load3 1.4s infinite linear;
+ -webkit-transform: translateZ(0);
+ -ms-transform: translateZ(0);
+ transform: translateZ(0);
+}
+.loader:before {
+ width: 50%;
+ height: 50%;
+ background: #105E9E;
+ border-radius: 100% 0 0 0;
+ position: absolute;
+ top: 0;
+ left: 0;
+ content: '';
+}
+.loader:after {
+ background: #fff;
+ width: 75%;
+ height: 75%;
+ border-radius: 50%;
+ content: '';
+ margin: auto;
+ position: absolute;
+ top: 0;
+ left: 0;
+ bottom: 0;
+ right: 0;
+}
+@-webkit-keyframes load3 {
+ 0% {
+ -webkit-transform: rotate(0deg);
+ transform: rotate(0deg);
+ }
+ 100% {
+ -webkit-transform: rotate(360deg);
+ transform: rotate(360deg);
+ }
+}
+@keyframes load3 {
+ 0% {
+ -webkit-transform: rotate(0deg);
+ transform: rotate(0deg);
+ }
+ 100% {
+ -webkit-transform: rotate(360deg);
+ transform: rotate(360deg);
+ }
+}
+
+/* VIEW ANIMATION */
+
+[ui-view] {
+ position: absolute;
+ top: 0;
+ bottom: 0;
+ width: 100%;
+}
+
+/* FROM DASHBOARD TO DETAIL */
+
+/* dash out */
+[ui-view].ceilometerDashboard.ng-leave {
+ animation:1s bounceOutLeft ease;
+}
+/* samples in */
+[ui-view].samples.ng-enter {
+ animation:1s bounceInRight ease;
+}
+
+/* FROM DETAIL TO DASHBOARD */
+
+/* samples out */
+[ui-view].samples.ng-leave {
+ animation:1s bounceOutRight ease;
+}
+/* dash in */
+[ui-view].ceilometerDashboard.ng-enter {
+ animation:1s bounceInLeft ease;
+}
+
+/* COLUMS ANIMATION */
+/* when showing the thing */
+.animate .animate-slide-left.ng-hide-remove {
+ animation:0.5s bounceInRight ease;
+}
+
+/* when hiding the picture */
+.animate .animate-slide-left.ng-hide-add {
+ animation:0.5s bounceOutRight ease;
+}
+
+/* ANIMATIONS */
+
+@keyframes bounceInRight {
+ from, 60%, 75%, 90%, to {
+ animation-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000);
}
- /* Panel Layout */
- .panel {
- margin-top: 10px;
+ from {
+ opacity: 0;
+ transform: translate3d(3000px, 0, 0);
}
- .panel-body:not(:first-child) {
- border-top: 1px solid #e3e3e3;
+ 60% {
+ opacity: 1;
+ transform: translate3d(-25px, 0, 0);
}
- .panel-body .row {
- margin-top: 10px;
+ 75% {
+ transform: translate3d(10px, 0, 0);
}
- /* Chart details */
- .chart {
- width: 100%;
- height: 300px;
+ 90% {
+ transform: translate3d(-5px, 0, 0);
}
- .btn-chart, .btn-chart:hover {
- color: #fff;
+ to {
+ transform: none;
+ }
+}
+
+@keyframes bounceInLeft {
+ from, 60%, 75%, 90%, to {
+ animation-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000);
}
- .side-container {
- position: relative;
+ 0% {
+ opacity: 0;
+ transform: translate3d(-3000px, 0, 0);
}
- .service-list {
- margin-top: -10px;
+ 60% {
+ opacity: 1;
+ transform: translate3d(25px, 0, 0);
}
- .service-list h3 {
- margin-top: 0px;
- margin-bottom: 0px;
+ 75% {
+ transform: translate3d(-10px, 0, 0);
}
- .service-list a {
- text-decoration: none;
- color: #333;
+ 90% {
+ transform: translate3d(5px, 0, 0);
}
- .meters, .stats {
- margin-top: 25px;
- position: absolute;
- top: 0;
- left: 0;
- width: 100%;
+ to {
+ transform: none;
+ }
+}
+
+@keyframes slideInUp {
+ from {
+ transform: translate3d(0, 100%, 0);
+ visibility: visible;
}
- /* LOADER */
- .loader {
- font-size: 10px;
- margin: 150px auto;
- text-indent: -9999em;
- width: 11em;
- height: 11em;
- border-radius: 50%;
- background: #ffffff;
- background: -moz-linear-gradient(left, #ffffff 10%, rgba(255, 255, 255, 0) 42%);
- background: -webkit-linear-gradient(left, #ffffff 10%, rgba(255, 255, 255, 0) 42%);
- background: -o-linear-gradient(left, #ffffff 10%, rgba(255, 255, 255, 0) 42%);
- background: -ms-linear-gradient(left, #ffffff 10%, rgba(255, 255, 255, 0) 42%);
- background: linear-gradient(to right, #ffffff 10%, rgba(255, 255, 255, 0) 42%);
- position: relative;
- -webkit-animation: load3 1.4s infinite linear;
- animation: load3 1.4s infinite linear;
- -webkit-transform: translateZ(0);
- -ms-transform: translateZ(0);
- transform: translateZ(0);
+ to {
+ transform: translate3d(0, 0, 0);
}
- .loader:before {
- width: 50%;
- height: 50%;
- background: #105E9E;
- border-radius: 100% 0 0 0;
- position: absolute;
- top: 0;
- left: 0;
- content: '';
- }
- .loader:after {
- background: #fff;
- width: 75%;
- height: 75%;
- border-radius: 50%;
- content: '';
- margin: auto;
- position: absolute;
- top: 0;
- left: 0;
- bottom: 0;
- right: 0;
- }
- @-webkit-keyframes load3 {
- 0% {
- -webkit-transform: rotate(0deg);
- transform: rotate(0deg);
- }
- 100% {
- -webkit-transform: rotate(360deg);
- transform: rotate(360deg);
- }
- }
- @keyframes load3 {
- 0% {
- -webkit-transform: rotate(0deg);
- transform: rotate(0deg);
- }
- 100% {
- -webkit-transform: rotate(360deg);
- transform: rotate(360deg);
- }
+}
+
+@keyframes bounceOutRight {
+ 20% {
+ opacity: 1;
+ transform: translate3d(-20px, 0, 0);
}
- /* VIEW ANIMATION */
+ to {
+ opacity: 0;
+ transform: translate3d(2000px, 0, 0);
+ }
+}
- [ui-view] {
- position: absolute;
- top: 0;
- bottom: 0;
- width: 100%;
+@keyframes bounceOutLeft {
+ 20% {
+ opacity: 1;
+ transform: translate3d(20px, 0, 0);
}
- /* FROM DASHBOARD TO DETAIL */
-
- /* dash out */
- [ui-view].ceilometerDashboard.ng-leave {
- animation:1s bounceOutLeft ease;
+ to {
+ opacity: 0;
+ transform: translate3d(-2000px, 0, 0);
}
- /* samples in */
- [ui-view].samples.ng-enter {
- animation:1s bounceInRight ease;
+}
+
+@keyframes slideOutDown {
+ from {
+ transform: translate3d(0, 0, 0);
}
- /* FROM DETAIL TO DASHBOARD */
-
- /* samples out */
- [ui-view].samples.ng-leave {
- animation:1s bounceOutRight ease;
+ to {
+ visibility: hidden;
+ transform: translate3d(0, 100%, 0);
}
- /* dash in */
- [ui-view].ceilometerDashboard.ng-enter {
- animation:1s bounceInLeft ease;
- }
-
- /* COLUMS ANIMATION */
- /* when showing the thing */
- .animate .animate-slide-left.ng-hide-remove {
- animation:0.5s bounceInRight ease;
- }
-
- /* when hiding the picture */
- .animate .animate-slide-left.ng-hide-add {
- animation:0.5s bounceOutRight ease;
- }
-
- /* ANIMATIONS */
-
- @keyframes bounceInRight {
- from, 60%, 75%, 90%, to {
- animation-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000);
- }
-
- from {
- opacity: 0;
- transform: translate3d(3000px, 0, 0);
- }
-
- 60% {
- opacity: 1;
- transform: translate3d(-25px, 0, 0);
- }
-
- 75% {
- transform: translate3d(10px, 0, 0);
- }
-
- 90% {
- transform: translate3d(-5px, 0, 0);
- }
-
- to {
- transform: none;
- }
- }
-
- @keyframes bounceInLeft {
- from, 60%, 75%, 90%, to {
- animation-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000);
- }
-
- 0% {
- opacity: 0;
- transform: translate3d(-3000px, 0, 0);
- }
-
- 60% {
- opacity: 1;
- transform: translate3d(25px, 0, 0);
- }
-
- 75% {
- transform: translate3d(-10px, 0, 0);
- }
-
- 90% {
- transform: translate3d(5px, 0, 0);
- }
-
- to {
- transform: none;
- }
- }
-
- @keyframes slideInUp {
- from {
- transform: translate3d(0, 100%, 0);
- visibility: visible;
- }
-
- to {
- transform: translate3d(0, 0, 0);
- }
- }
-
- @keyframes bounceOutRight {
- 20% {
- opacity: 1;
- transform: translate3d(-20px, 0, 0);
- }
-
- to {
- opacity: 0;
- transform: translate3d(2000px, 0, 0);
- }
- }
-
- @keyframes bounceOutLeft {
- 20% {
- opacity: 1;
- transform: translate3d(20px, 0, 0);
- }
-
- to {
- opacity: 0;
- transform: translate3d(-2000px, 0, 0);
- }
- }
-
- @keyframes slideOutDown {
- from {
- transform: translate3d(0, 0, 0);
- }
-
- to {
- visibility: hidden;
- transform: translate3d(0, 100%, 0);
- }
- }
-
-/*}
\ No newline at end of file
+}
\ No newline at end of file
diff --git a/xos/core/xoslib/ngXosViews/ceilometerDashboard/src/css/dev.css b/xos/core/xoslib/ngXosViews/ceilometerDashboard/src/css/dev.css
index b72bfdc..228d394 100644
--- a/xos/core/xoslib/ngXosViews/ceilometerDashboard/src/css/dev.css
+++ b/xos/core/xoslib/ngXosViews/ceilometerDashboard/src/css/dev.css
@@ -9,6 +9,6 @@
@media (min-width: 768px) {
#xosCeilometerDashboard {
- margin: 10px:;
+ margin: 10px
}
}
\ No newline at end of file
diff --git a/xos/core/xoslib/ngXosViews/ceilometerDashboard/src/css/grips/vertical.png b/xos/core/xoslib/ngXosViews/ceilometerDashboard/src/css/grips/vertical.png
deleted file mode 100644
index 0ac8fa1..0000000
--- a/xos/core/xoslib/ngXosViews/ceilometerDashboard/src/css/grips/vertical.png
+++ /dev/null
Binary files differ
diff --git a/xos/core/xoslib/ngXosViews/ceilometerDashboard/src/js/main.js b/xos/core/xoslib/ngXosViews/ceilometerDashboard/src/js/main.js
index e85a26e..a20d563 100644
--- a/xos/core/xoslib/ngXosViews/ceilometerDashboard/src/js/main.js
+++ b/xos/core/xoslib/ngXosViews/ceilometerDashboard/src/js/main.js
@@ -33,24 +33,12 @@
})
.service('Ceilometer', function($http, $q, lodash){
- this.resourceMap = {};
-
this.getMeters = () => {
let deferred = $q.defer();
$http.get('/xoslib/meters/', {cache: true})
// $http.get('../meters_mock.json', {cache: true})
.then((res) => {
-
- // saving resources name and ids for later user,
- // {resource_id: resource_name}
- // NOTE REMOVE IF NOT ANYMORE NEEDED
- const resourceObj = lodash.groupBy(res.data, 'resource_id');
- this.resourceMap = lodash.reduce(Object.keys(resourceObj), (map, item) => {
- map[item] = resourceObj[item][0].resource_name;
- return map;
- }, {});
-
deferred.resolve(res.data)
})
.catch((e) => {
@@ -88,6 +76,11 @@
return deferred.promise;
};
+
+ // hold dashboard status (opened service, slice, resource)
+ this.selectedService = null;
+ this.selectedSlice = null;
+ this.selectedResource = null;
})
.directive('ceilometerDashboard', function(lodash){
return {
@@ -98,9 +91,34 @@
templateUrl: 'templates/ceilometer-dashboard.tpl.html',
controller: function(Ceilometer){
+ console.log(Ceilometer.selectedService, Ceilometer.selectedSlice, Ceilometer.selectedResource);
+
+ // this open the accordion
+ this.accordion = {
+ open: {}
+ }
+
+ /**
+ * Open the active panel base on the service stored values
+ */
+ this.openPanels = () => {
+ if(Ceilometer.selectedService){
+ this.accordion.open[Ceilometer.selectedService] = true;
+ if(Ceilometer.selectedSlice){
+ this.selectedSlice = Ceilometer.selectedSlice;
+ this.selectedResources = this.projects[Ceilometer.selectedService][Ceilometer.selectedSlice]
+ if(Ceilometer.selectedResource){
+ this.selectedResource = Ceilometer.selectedResource;
+ this.selectedMeters = this.selectedResources[Ceilometer.selectedResource];
+ }
+ }
+ }
+ }
+
this.loadMeters = () => {
this.loader = true;
+ // TODO rename projects in meters
Ceilometer.getMeters()
.then(meters => {
//group project by service
@@ -113,6 +131,9 @@
this.projects[project][slice] = lodash.groupBy(this.projects[project][slice], 'resource_name');
});
});
+
+ // open selected panels
+ this.openPanels();
})
.catch(err => {
this.error = err.data.detail;
@@ -125,33 +146,26 @@
this.loadMeters();
/**
- * Select the current service
- */
-
- this.selectService = (service) => {
- //cleaning
- this.selectedResources = null;
- this.selectedResource = null;
- this.selectedMeters = null;
-
- this.selectedService = service;
- };
-
- /**
* Select Resources for a slice
*
* @param Array resources The list of selected resources
* @returns void
*/
this.selectedResources = null;
- this.selectResources = (resources, slice) => {
+ this.selectResources = (resources, slice, service) => {
//cleaning
this.selectedResources = null;
this.selectedResource = null;
this.selectedMeters = null;
+ // hold the resource list for the current slice
this.selectedResources = resources;
this.selectedSlice = slice;
+ this.selectedService = service;
+
+ // store the status
+ Ceilometer.selectedSlice = slice;
+ Ceilometer.selectedService = service;
}
/**
@@ -163,6 +177,8 @@
this.selectedMeters = null;
this.selectMeters = (meters, resource) => {
this.selectedMeters = meters;
+
+ Ceilometer.selectedResource = resource;
this.selectedResource = resource;
}
@@ -181,6 +197,8 @@
templateUrl: 'templates/ceilometer-samples.tpl.html',
controller: function(Ceilometer) {
+ // console.log(Ceilometer.selectResource);
+
this.chartColors = [
'#286090',
'#F7464A',
@@ -204,9 +222,11 @@
if($stateParams.name && $stateParams.tenant){
this.name = $stateParams.name;
this.tenant = $stateParams.tenant;
+ // TODO rename tenant in project_id
}
-
- // Mock
+ else{
+ throw new Error('Missing Name and Tenant Params!');
+ }
/**
* Goes trough the array and format date to be used as labels
@@ -243,22 +263,21 @@
* @param string resource_id
*/
this.chartMeters = [];
- this.addMeterToChart = (resource_id) => {
- this.chart['labels'] = this.getLabels(lodash.sortBy(this.samplesList[resource_id], 'timestamp'));
- this.chart['series'].push(resource_id);
- this.chart['data'].push(this.getData(lodash.sortBy(this.samplesList[resource_id], 'timestamp')));
- console.log(this.samplesList[resource_id]);
- this.chartMeters.push(this.samplesList[resource_id][0]); //use the 0 as are all samples for the same resource and I need the name
- lodash.remove(this.sampleLabels, {id: resource_id});
+ this.addMeterToChart = (project_id) => {
+ this.chart['labels'] = this.getLabels(lodash.sortBy(this.samplesList[project_id], 'timestamp'));
+ this.chart['series'].push(project_id);
+ this.chart['data'].push(this.getData(lodash.sortBy(this.samplesList[project_id], 'timestamp')));
+ this.chartMeters.push(this.samplesList[project_id][0]); //use the 0 as are all samples for the same resource and I need the name
+ lodash.remove(this.sampleLabels, {id: project_id});
}
this.removeFromChart = (meter) => {
- this.chart.data.splice(this.chart.series.indexOf(meter.resource_id), 1);
- this.chart.series.splice(this.chart.series.indexOf(meter.resource_id), 1);
- this.chartMeters.splice(this.chartMeters.indexOf(meter.resource_id), 1);
+ this.chart.data.splice(this.chart.series.indexOf(meter.project_id), 1);
+ this.chart.series.splice(this.chart.series.indexOf(meter.project_id), 1);
+ this.chartMeters.splice(lodash.findIndex(this.chartMeters, {project_id: meter.project_id}), 1);
this.sampleLabels.push({
- id: meter.resource_id,
- name: meter.resource_name
+ id: meter.project_id,
+ name: meter.resource_name || meter.project_id
})
};
@@ -268,13 +287,14 @@
this.formatSamplesLabels = (samples) => {
- return lodash.uniq(samples.reduce((labels, item) => {
+ return lodash.uniq(samples, 'project_id')
+ .reduce((labels, item) => {
labels.push({
- id: item.resource_id,
- name: item.resource_name
+ id: item.project_id,
+ name: item.resource_name || item.project_id
});
return labels;
- }, []), item => item.id);
+ }, []);
}
@@ -289,7 +309,7 @@
.then(res => {
// setup data for visualization
- this.samplesList = lodash.groupBy(res, 'resource_id');
+ this.samplesList = lodash.groupBy(res, 'project_id');
this.sampleLabels = this.formatSamplesLabels(res);
// add current meter to chart
diff --git a/xos/core/xoslib/ngXosViews/ceilometerDashboard/src/templates/ceilometer-dashboard.tpl.html b/xos/core/xoslib/ngXosViews/ceilometerDashboard/src/templates/ceilometer-dashboard.tpl.html
index 2d880b5..f04a974 100644
--- a/xos/core/xoslib/ngXosViews/ceilometerDashboard/src/templates/ceilometer-dashboard.tpl.html
+++ b/xos/core/xoslib/ngXosViews/ceilometerDashboard/src/templates/ceilometer-dashboard.tpl.html
@@ -30,11 +30,12 @@
<uib-accordion-group
ng-repeat="(service, slices) in vm.projects | orderObjectByKey"
template-url="templates/accordion-group.html"
+ is-open="vm.accordion.open[service]"
heading="{{service}}">
<h4>Slices:</h4>
<a ng-repeat="(slice, resources) in slices"
ng-class="{active: slice === vm.selectedSlice}"
- ng-click="vm.selectResources(resources, slice)"
+ ng-click="vm.selectResources(resources, slice, service)"
href="#" class="list-group-item" >
{{slice}} <i class="glyphicon glyphicon-chevron-right pull-right"></i>
</a>
@@ -85,7 +86,7 @@
</div>
<div class="col-xs-3"></div>
</div>
- <div class="row" ng-click="vm.selectMeters(meters)" ng-repeat="meter in vm.selectedMeters" style="margin-bottom: 10px;">
+ <div class="row" ng-repeat="meter in vm.selectedMeters" style="margin-bottom: 10px;">
<div class="col-xs-6">
{{meter.name}}
</div>
@@ -93,7 +94,7 @@
{{meter.unit}}
</div>
<div class="col-xs-3">
- <a ui-sref="samples({name: meter.name, tenant: meter.resource_id})" class="btn btn-primary">
+ <a ui-sref="samples({name: meter.name, tenant: meter.project_id})" class="btn btn-primary">
<i class="glyphicon glyphicon-search"></i>
</a>
</div>
diff --git a/xos/core/xoslib/ngXosViews/ceilometerDashboard/src/templates/ceilometer-samples.tpl.html b/xos/core/xoslib/ngXosViews/ceilometerDashboard/src/templates/ceilometer-samples.tpl.html
index f323802e..b279123 100644
--- a/xos/core/xoslib/ngXosViews/ceilometerDashboard/src/templates/ceilometer-samples.tpl.html
+++ b/xos/core/xoslib/ngXosViews/ceilometerDashboard/src/templates/ceilometer-samples.tpl.html
@@ -42,7 +42,7 @@
<div class="row" ng-if="!vm.loader">
<div class="col-xs-12">
<a ng-click="vm.removeFromChart(meter)" class="btn btn-chart" ng-style="{'background-color': vm.chartColors[$index]}" ng-repeat="meter in vm.chartMeters">
- {{meter.resource_name}}
+ {{meter.resource_name || meter.resource_id}}
</a>
</div>
</div>
diff --git a/xos/core/xoslib/ngXosViews/ceilometerDashboard/src/templates/ceilometer-stats.tpl.html b/xos/core/xoslib/ngXosViews/ceilometerDashboard/src/templates/ceilometer-stats.tpl.html
index fabce0a..1f5ff11 100644
--- a/xos/core/xoslib/ngXosViews/ceilometerDashboard/src/templates/ceilometer-stats.tpl.html
+++ b/xos/core/xoslib/ngXosViews/ceilometerDashboard/src/templates/ceilometer-stats.tpl.html
@@ -14,7 +14,7 @@
<th>Value:</th>
</tr>
<tr ng-repeat="item in vm.stats">
- <td>{{item.type}}</td>
+ <td>{{item.category}}</td>
<td>{{item.meter}}</td>
<td>{{item.unit}}</td>
<td>{{item.value}}</td>
diff --git a/xos/core/xoslib/static/css/xosCeilometerDashboard.css b/xos/core/xoslib/static/css/xosCeilometerDashboard.css
new file mode 100644
index 0000000..8aad3b2
--- /dev/null
+++ b/xos/core/xoslib/static/css/xosCeilometerDashboard.css
@@ -0,0 +1 @@
+#xosCeilometerDashboard{position:relative}.panel{margin-top:10px}.panel-body:not(:first-child){border-top:1px solid #e3e3e3}.panel-body .row{margin-top:10px}.chart{width:100%;height:300px}.btn-chart,.btn-chart:hover{color:#fff}.side-container{position:relative}.service-list{margin-top:-10px}.service-list h3{margin-top:0;margin-bottom:0}.service-list a{text-decoration:none;color:#333}.meters,.stats{margin-top:25px;position:absolute;top:0;left:0;width:100%}.loader{font-size:10px;margin:150px auto;text-indent:-9999em;width:11em;height:11em;border-radius:50%;background:#fff;background:linear-gradient(to right,#fff 10%,rgba(255,255,255,0) 42%);position:relative;animation:load3 1.4s infinite linear;transform:translateZ(0)}.loader:before{width:50%;height:50%;background:#105e9e;border-radius:100% 0 0;position:absolute;top:0;left:0;content:''}.loader:after{background:#fff;width:75%;height:75%;border-radius:50%;content:'';margin:auto;position:absolute;top:0;left:0;bottom:0;right:0}@keyframes load3{0%{transform:rotate(0deg)}100%{transform:rotate(360deg)}}[ui-view]{position:absolute;top:0;bottom:0;width:100%}[ui-view].ceilometerDashboard.ng-leave{animation:1s bounceOutLeft ease}[ui-view].samples.ng-enter{animation:1s bounceInRight ease}[ui-view].samples.ng-leave{animation:1s bounceOutRight ease}[ui-view].ceilometerDashboard.ng-enter{animation:1s bounceInLeft ease}.animate .animate-slide-left.ng-hide-remove{animation:.5s bounceInRight ease}.animate .animate-slide-left.ng-hide-add{animation:.5s bounceOutRight ease}@keyframes bounceInRight{from,60%,75%,90%,to{animation-timing-function:cubic-bezier(.215,.61,.355,1.000)}from{opacity:0;transform:translate3d(3000px,0,0)}60%{opacity:1;transform:translate3d(-25px,0,0)}75%{transform:translate3d(10px,0,0)}90%{transform:translate3d(-5px,0,0)}to{transform:none}}@keyframes bounceInLeft{from,60%,75%,90%,to{animation-timing-function:cubic-bezier(.215,.61,.355,1.000)}0%{opacity:0;transform:translate3d(-3000px,0,0)}60%{opacity:1;transform:translate3d(25px,0,0)}75%{transform:translate3d(-10px,0,0)}90%{transform:translate3d(5px,0,0)}to{transform:none}}@keyframes slideInUp{from{transform:translate3d(0,100%,0);visibility:visible}to{transform:translate3d(0,0,0)}}@keyframes bounceOutRight{20%{opacity:1;transform:translate3d(-20px,0,0)}to{opacity:0;transform:translate3d(2000px,0,0)}}@keyframes bounceOutLeft{20%{opacity:1;transform:translate3d(20px,0,0)}to{opacity:0;transform:translate3d(-2000px,0,0)}}@keyframes slideOutDown{from{transform:translate3d(0,0,0)}to{visibility:hidden;transform:translate3d(0,100%,0)}}
\ No newline at end of file
diff --git a/xos/core/xoslib/static/js/xosCeilometerDashboard.js b/xos/core/xoslib/static/js/xosCeilometerDashboard.js
index 9e314d4..5aa7234 100644
--- a/xos/core/xoslib/static/js/xosCeilometerDashboard.js
+++ b/xos/core/xoslib/static/js/xosCeilometerDashboard.js
@@ -1 +1 @@
-"use strict";angular.module("xos.ceilometerDashboard",["ngResource","ngCookies","ngLodash","ui.router","xos.helpers","ngAnimate","chart.js","ui.bootstrap.accordion"]).config(["$stateProvider","$urlRouterProvider",function(e,t){e.state("ceilometerDashboard",{url:"/",template:"<ceilometer-dashboard></ceilometer-dashboard>"}).state("samples",{url:"/:name/:tenant/samples",template:"<ceilometer-samples></ceilometer-samples>"}),t.otherwise("/")}]).config(["$httpProvider",function(e){e.interceptors.push("NoHyperlinks")}]).run(["$rootScope",function(e){e.stateName="ceilometerDashboard",e.$on("$stateChangeStart",function(t,s){e.stateName=s.name})}]).service("Ceilometer",["$http","$q","lodash",function(e,t,s){var n=this;this.resourceMap={},this.getMeters=function(){var r=t.defer();return e.get("/xoslib/meters/",{cache:!0}).then(function(e){var t=s.groupBy(e.data,"resource_id");n.resourceMap=s.reduce(Object.keys(t),function(e,s){return e[s]=t[s][0].resource_name,e},{}),r.resolve(e.data)})["catch"](function(e){r.reject(e)}),r.promise},this.getSamples=function(s,n){var r=t.defer();return e.get("/xoslib/metersamples/",{params:{meter:s,tenant:n}}).then(function(e){r.resolve(e.data)})["catch"](function(e){r.reject(e)}),r.promise},this.getStats=function(n){var r=t.defer();return e.get("/xoslib/meterstatistics/",{cache:!0}).then(function(e){r.resolve(s.filter(e.data,{slice:n}))})["catch"](function(e){r.reject(e)}),r.promise}}]).directive("ceilometerDashboard",["lodash",function(e){return{restrict:"E",scope:{},bindToController:!0,controllerAs:"vm",templateUrl:"templates/ceilometer-dashboard.tpl.html",controller:["Ceilometer",function(t){var s=this;this.loadMeters=function(){s.loader=!0,t.getMeters().then(function(t){s.projects=e.groupBy(t,"service"),e.forEach(Object.keys(s.projects),function(t){s.projects[t]=e.groupBy(s.projects[t],"slice"),e.forEach(Object.keys(s.projects[t]),function(n){s.projects[t][n]=e.groupBy(s.projects[t][n],"resource_name")})})})["catch"](function(e){s.error=e.data.detail})["finally"](function(){s.loader=!1})},this.loadMeters(),this.selectService=function(e){s.selectedResources=null,s.selectedResource=null,s.selectedMeters=null,s.selectedService=e},this.selectedResources=null,this.selectResources=function(e,t){s.selectedResources=null,s.selectedResource=null,s.selectedMeters=null,s.selectedResources=e,s.selectedSlice=t},this.selectedMeters=null,this.selectMeters=function(e,t){s.selectedMeters=e,s.selectedResource=t}}]}}]).directive("ceilometerSamples",["lodash","$stateParams",function(e,t){return{restrict:"E",scope:{name:"=name",tenant:"=tenant"},bindToController:!0,controllerAs:"vm",templateUrl:"templates/ceilometer-samples.tpl.html",controller:["Ceilometer",function(s){var n=this;this.chartColors=["#286090","#F7464A","#46BFBD","#FDB45C","#97BBCD","#4D5360","#8c4f9f"],this.chart={series:[],labels:[],data:[]},Chart.defaults.global.colours=this.chartColors,this.chartType="line",t.name&&t.tenant&&(this.name=t.name,this.tenant=t.tenant),this.getLabels=function(e){return e.reduce(function(e,t){var s=new Date(t.timestamp);return e.push(s.getHours()+":"+((s.getMinutes()<10?"0":"")+s.getMinutes())+":"+s.getSeconds()),e},[])},this.getData=function(e){return e.reduce(function(e,t){return e.push(t.volume),e},[])},this.chartMeters=[],this.addMeterToChart=function(t){n.chart.labels=n.getLabels(e.sortBy(n.samplesList[t],"timestamp")),n.chart.series.push(t),n.chart.data.push(n.getData(e.sortBy(n.samplesList[t],"timestamp"))),console.log(n.samplesList[t]),n.chartMeters.push(n.samplesList[t][0]),e.remove(n.sampleLabels,{id:t})},this.removeFromChart=function(e){n.chart.data.splice(n.chart.series.indexOf(e.resource_id),1),n.chart.series.splice(n.chart.series.indexOf(e.resource_id),1),n.chartMeters.splice(n.chartMeters.indexOf(e.resource_id),1),n.sampleLabels.push({id:e.resource_id,name:e.resource_name})},this.formatSamplesLabels=function(t){return e.uniq(t.reduce(function(e,t){return e.push({id:t.resource_id,name:t.resource_name}),e},[]),function(e){return e.id})},this.showSamples=function(){n.loader=!0,s.getSamples(n.name).then(function(t){n.samplesList=e.groupBy(t,"resource_id"),n.sampleLabels=n.formatSamplesLabels(t),n.addMeterToChart(n.tenant)})["catch"](function(e){n.error=e.data.detail})["finally"](function(){n.loader=!1})},this.showSamples()}]}}]).directive("ceilometerStats",function(){return{restrict:"E",scope:{name:"=name"},bindToController:!0,controllerAs:"vm",templateUrl:"templates/ceilometer-stats.tpl.html",controller:["$scope","Ceilometer",function(e,t){var s=this;this.getStats=function(){s.loader=!0,t.getStats(s.name).then(function(e){s.stats=e})["catch"](function(e){s.error=e.data})["finally"](function(){s.loader=!1})},this.getStats(),e.$watch(function(){return s.name},function(){s.getStats()})}]}}).filter("orderObjectByKey",["lodash",function(e){return function(t){return t?e.reduce(Object.keys(t).reverse(),function(e,s){return e[s]=t[s],e},{}):void 0}}]),angular.module("xos.ceilometerDashboard").run(["$templateCache",function(e){e.put("templates/accordion-group.html",'<div class="panel {{panelClass || \'panel-default\'}}">\n <div class="panel-heading" ng-keypress="toggleOpen($event)">\n <h3>\n <a href tabindex="0" class="accordion-toggle" ng-click="toggleOpen()" uib-accordion-transclude="heading"><span ng-class="{\'text-muted\': isDisabled}">{{heading}}</span></a>\n </h3>\n </div>\n <div class="panel-collapse collapse" uib-collapse="!isOpen">\n <div class="panel-body" ng-transclude></div>\n </div>\n</div>\n'),e.put("templates/accordion.html",'<div class="panel-group" ng-transclude></div>'),e.put("templates/ceilometer-dashboard.tpl.html",'<div class="row">\n <div class="col-sm-10">\n <h1>XOS Monitoring Statistics</h1>\n </div>\n <div class="col-xs-2 text-right">\n <a href="" class="btn btn-default" \n ng-show="vm.selectedResources && !vm.showStats"\n ng-click="vm.showStats = true">\n <i class="glyphicon glyphicon-transfer"></i>\n </a>\n <a href="" class="btn btn-default" \n ng-show="vm.selectedResources && vm.showStats"\n ng-click="vm.showStats = false">\n <i class="glyphicon glyphicon-transfer"></i>\n </a>\n </div>\n</div>\n\n<div class="row" ng-show="vm.loader">\n <div class="col-xs-12">\n <div class="loader">Loading</div>\n </div>\n</div>\n\n<section ng-hide="vm.loader" ng-class="{animate: !vm.loader}">\n <div class="row">\n <div class="col-sm-3 service-list">\n <h3>XOS Service: </h3>\n <uib-accordion close-others="true" template-url="templates/accordion.html">\n <uib-accordion-group\n ng-repeat="(service, slices) in vm.projects | orderObjectByKey"\n template-url="templates/accordion-group.html"\n heading="{{service}}">\n <h4>Slices:</h4>\n <a ng-repeat="(slice, resources) in slices" \n ng-class="{active: slice === vm.selectedSlice}"\n ng-click="vm.selectResources(resources, slice)"\n href="#" class="list-group-item" >\n {{slice}} <i class="glyphicon glyphicon-chevron-right pull-right"></i>\n </a>\n </uib-accordion-group>\n </uib-accordion>\n </div>\n <section class="side-container col-sm-9">\n <div class="row">\n <article ng-hide="!vm.showStats" class="stats animate-slide-left">\n <div class="col-xs-12">\n <div class="list-group">\n <div class="list-group-item">\n <h3>Stats</h3>\n </div>\n <div class="list-group-item">\n <ceilometer-stats ng-if="vm.selectedSlice" name="vm.selectedSlice"></ceilometer-stats>\n </div>\n </div>\n </div>\n </article>\n <article ng-hide="vm.showStats" class="meters animate-slide-left">\n <div class="col-sm-4 animate-slide-left" ng-hide="!vm.selectedResources">\n <div class="list-group">\n <div class="list-group-item">\n <h3>Resources</h3>\n </div>\n <a href="#" \n ng-click="vm.selectMeters(meters, resource)" \n class="list-group-item" \n ng-repeat="(resource, meters) in vm.selectedResources" \n ng-class="{active: resource === vm.selectedResource}">\n {{resource}} <i class="glyphicon glyphicon-chevron-right pull-right"></i>\n </a>\n </div>\n </div>\n <div class="col-sm-8 animate-slide-left" ng-hide="!vm.selectedMeters">\n <div class="list-group">\n <div class="list-group-item">\n <h3>Meters</h3>\n </div>\n <div class="list-group-item">\n <div class="row">\n <div class="col-xs-6">\n <label>Name:</label>\n </div>\n <div class="col-xs-3">\n <label>Unit:</label>\n </div>\n <div class="col-xs-3"></div>\n </div>\n <div class="row" ng-click="vm.selectMeters(meters)" ng-repeat="meter in vm.selectedMeters" style="margin-bottom: 10px;">\n <div class="col-xs-6">\n {{meter.name}}\n </div>\n <div class="col-xs-3">\n {{meter.unit}}\n </div>\n <div class="col-xs-3">\n <a ui-sref="samples({name: meter.name, tenant: meter.resource_id})" class="btn btn-primary">\n <i class="glyphicon glyphicon-search"></i>\n </a>\n </div>\n </div>\n </div>\n </div>\n </div>\n </article>\n </div>\n </section>\n </div>\n</section>\n<section ng-if="!vm.loader && vm.error">\n <div class="alert alert-danger">\n {{vm.error}}\n </div>\n</section>\n'),e.put("templates/ceilometer-samples.tpl.html",'<!-- <pre>{{ vm | json}}</pre> -->\n\n<div class="row">\n <div class="col-xs-10">\n <h1>{{vm.name | uppercase}}</h1>\n </div>\n <div class="col-xs-2">\n <a ui-sref="ceilometerDashboard" class="btn btn-primary pull-right">\n <i class="glyphicon glyphicon-arrow-left"></i> Back to list\n </a>\n </div>\n</div>\n<div class="row" ng-show="vm.loader">\n <div class="col-xs-12">\n <div class="loader">Loading</div>\n </div>\n</div>\n<section ng-if="!vm.loader && !vm.error">\n <div class="row">\n <form class="form-inline col-xs-8" ng-submit="vm.addMeterToChart(vm.addMeterValue)">\n <select ng-model="vm.addMeterValue" class="form-control" ng-options="resource.id as resource.name for resource in vm.sampleLabels"></select>\n <button class="btn btn-success"> \n <i class="glyphicon glyphicon-plus"></i> Add\n </button>\n </form>\n <div class="col-xs-4 text-right">\n <a ng-click="vm.chartType = \'line\'" class="btn" ng-class="{\'btn-default\': vm.chartType != \'bar\', \'btn-primary\': vm.chartType == \'line\'}">Lines</a>\n <a ng-click="vm.chartType = \'bar\'" class="btn" ng-class="{\'btn-default\': vm.chartType != \'line\', \'btn-primary\': vm.chartType == \'bar\'}">Bars</a>\n </div>\n </div>\n <div class="row" ng-if="!vm.loader">\n <div class="col-xs-12">\n <canvas ng-if="vm.chartType === \'line\'" id="line" class="chart chart-line" chart-data="vm.chart.data" chart-options="{datasetFill: false}"\n chart-labels="vm.chart.labels" chart-legend="false" chart-series="vm.chart.series">\n </canvas>\n <canvas ng-if="vm.chartType === \'bar\'" id="bar" class="chart chart-bar" chart-data="vm.chart.data"\n chart-labels="vm.chart.labels" chart-legend="false" chart-series="vm.chart.series">\n </canvas>\n <!-- <pre>{{vm.chartMeters | json}}</pre> -->\n </div>\n </div>\n <div class="row" ng-if="!vm.loader">\n <div class="col-xs-12">\n <a ng-click="vm.removeFromChart(meter)" class="btn btn-chart" ng-style="{\'background-color\': vm.chartColors[$index]}" ng-repeat="meter in vm.chartMeters">\n {{meter.resource_name}}\n </a>\n </div>\n </div>\n</section>\n<section ng-if="!vm.loader && vm.error">\n <div class="alert alert-danger">\n {{vm.error}}\n </div>\n</section>'),e.put("templates/ceilometer-stats.tpl.html",'<div ng-show="vm.loader" class="loader">Loading</div>\n\n<section ng-if="!vm.loader && !vm.error">\n\n <div class="alert alert-danger" ng-if="vm.stats.length == 0">\n No result\n </div> \n\n <table class="table" ng-if="vm.stats.length > 0">\n <tr>\n <th>Type:</th>\n <th>Meter:</th>\n <th>Unit:</th>\n <th>Value:</th>\n </tr>\n <tr ng-repeat="item in vm.stats">\n <td>{{item.type}}</td>\n <td>{{item.meter}}</td>\n <td>{{item.unit}}</td>\n <td>{{item.value}}</td>\n </tr>\n </table>\n</section>\n\n<section ng-if="!vm.loader && vm.error">\n <div class="alert alert-danger">\n {{vm.error}}\n </div>\n</section>\n')}]),angular.module("xos.ceilometerDashboard").run(["$location",function(e){e.path("/")}]),angular.bootstrap(angular.element("#xosCeilometerDashboard"),["xos.ceilometerDashboard"]);
\ No newline at end of file
+"use strict";angular.module("xos.ceilometerDashboard",["ngResource","ngCookies","ngLodash","ui.router","xos.helpers","ngAnimate","chart.js","ui.bootstrap.accordion"]).config(["$stateProvider","$urlRouterProvider",function(e,t){e.state("ceilometerDashboard",{url:"/",template:"<ceilometer-dashboard></ceilometer-dashboard>"}).state("samples",{url:"/:name/:tenant/samples",template:"<ceilometer-samples></ceilometer-samples>"}),t.otherwise("/")}]).config(["$httpProvider",function(e){e.interceptors.push("NoHyperlinks")}]).run(["$rootScope",function(e){e.stateName="ceilometerDashboard",e.$on("$stateChangeStart",function(t,s){e.stateName=s.name})}]).service("Ceilometer",["$http","$q","lodash",function(e,t,s){var n=this;this.resourceMap={},this.getMeters=function(){var r=t.defer();return e.get("/xoslib/meters/",{cache:!0}).then(function(e){var t=s.groupBy(e.data,"resource_id");n.resourceMap=s.reduce(Object.keys(t),function(e,s){return e[s]=t[s][0].resource_name,e},{}),r.resolve(e.data)})["catch"](function(e){r.reject(e)}),r.promise},this.getSamples=function(s,n){var r=t.defer();return e.get("/xoslib/metersamples/",{params:{meter:s,tenant:n}}).then(function(e){r.resolve(e.data)})["catch"](function(e){r.reject(e)}),r.promise},this.getStats=function(n){var r=t.defer();return e.get("/xoslib/meterstatistics/",{cache:!0}).then(function(e){r.resolve(s.filter(e.data,{slice:n}))})["catch"](function(e){r.reject(e)}),r.promise}}]).directive("ceilometerDashboard",["lodash",function(e){return{restrict:"E",scope:{},bindToController:!0,controllerAs:"vm",templateUrl:"templates/ceilometer-dashboard.tpl.html",controller:["Ceilometer",function(t){var s=this;this.loadMeters=function(){s.loader=!0,t.getMeters().then(function(t){s.projects=e.groupBy(t,"service"),e.forEach(Object.keys(s.projects),function(t){s.projects[t]=e.groupBy(s.projects[t],"slice"),e.forEach(Object.keys(s.projects[t]),function(n){s.projects[t][n]=e.groupBy(s.projects[t][n],"resource_name")})})})["catch"](function(e){s.error=e.data.detail})["finally"](function(){s.loader=!1})},this.loadMeters(),this.selectService=function(e){s.selectedResources=null,s.selectedResource=null,s.selectedMeters=null,s.selectedService=e},this.selectedResources=null,this.selectResources=function(e,t){s.selectedResources=null,s.selectedResource=null,s.selectedMeters=null,s.selectedResources=e,s.selectedSlice=t},this.selectedMeters=null,this.selectMeters=function(e,t){s.selectedMeters=e,s.selectedResource=t}}]}}]).directive("ceilometerSamples",["lodash","$stateParams",function(e,t){return{restrict:"E",scope:{name:"=name",tenant:"=tenant"},bindToController:!0,controllerAs:"vm",templateUrl:"templates/ceilometer-samples.tpl.html",controller:["Ceilometer",function(s){var n=this;if(this.chartColors=["#286090","#F7464A","#46BFBD","#FDB45C","#97BBCD","#4D5360","#8c4f9f"],this.chart={series:[],labels:[],data:[]},Chart.defaults.global.colours=this.chartColors,this.chartType="line",!t.name||!t.tenant)throw new Error("Missing Name and Tenant Params!");this.name=t.name,this.tenant=t.tenant,this.getLabels=function(e){return e.reduce(function(e,t){var s=new Date(t.timestamp);return e.push(s.getHours()+":"+((s.getMinutes()<10?"0":"")+s.getMinutes())+":"+s.getSeconds()),e},[])},this.getData=function(e){return e.reduce(function(e,t){return e.push(t.volume),e},[])},this.chartMeters=[],this.addMeterToChart=function(t){n.chart.labels=n.getLabels(e.sortBy(n.samplesList[t],"timestamp")),n.chart.series.push(t),n.chart.data.push(n.getData(e.sortBy(n.samplesList[t],"timestamp"))),n.chartMeters.push(n.samplesList[t][0]),e.remove(n.sampleLabels,{id:t})},this.removeFromChart=function(t){n.chart.data.splice(n.chart.series.indexOf(t.resource_id),1),n.chart.series.splice(n.chart.series.indexOf(t.resource_id),1),n.chartMeters.splice(e.findIndex(n.chartMeters,{resource_id:t.resource_id}),1),n.sampleLabels.push({id:t.resource_id,name:t.resource_name})},this.formatSamplesLabels=function(t){return e.uniq(t,"resource_id").reduce(function(e,t){return e.push({id:t.resource_id,name:t.resource_name}),e},[])},this.showSamples=function(){n.loader=!0,s.getSamples(n.name).then(function(t){n.samplesList=e.groupBy(t,"resource_id"),n.sampleLabels=n.formatSamplesLabels(t),n.addMeterToChart(n.tenant)})["catch"](function(e){n.error=e.data.detail})["finally"](function(){n.loader=!1})},this.showSamples()}]}}]).directive("ceilometerStats",function(){return{restrict:"E",scope:{name:"=name"},bindToController:!0,controllerAs:"vm",templateUrl:"templates/ceilometer-stats.tpl.html",controller:["$scope","Ceilometer",function(e,t){var s=this;this.getStats=function(){s.loader=!0,t.getStats(s.name).then(function(e){s.stats=e})["catch"](function(e){s.error=e.data})["finally"](function(){s.loader=!1})},this.getStats(),e.$watch(function(){return s.name},function(){s.getStats()})}]}}).filter("orderObjectByKey",["lodash",function(e){return function(t){return t?e.reduce(Object.keys(t).reverse(),function(e,s){return e[s]=t[s],e},{}):void 0}}]),angular.module("xos.ceilometerDashboard").run(["$templateCache",function(e){e.put("templates/accordion-group.html",'<div class="panel {{panelClass || \'panel-default\'}}">\n <div class="panel-heading" ng-keypress="toggleOpen($event)">\n <h3>\n <a href tabindex="0" class="accordion-toggle" ng-click="toggleOpen()" uib-accordion-transclude="heading"><span ng-class="{\'text-muted\': isDisabled}">{{heading}}</span></a>\n </h3>\n </div>\n <div class="panel-collapse collapse" uib-collapse="!isOpen">\n <div class="panel-body" ng-transclude></div>\n </div>\n</div>\n'),e.put("templates/accordion.html",'<div class="panel-group" ng-transclude></div>'),e.put("templates/ceilometer-dashboard.tpl.html",'<div class="row">\n <div class="col-sm-10">\n <h1>XOS Monitoring Statistics</h1>\n </div>\n <div class="col-xs-2 text-right">\n <a href="" class="btn btn-default" \n ng-show="vm.selectedResources && !vm.showStats"\n ng-click="vm.showStats = true">\n <i class="glyphicon glyphicon-transfer"></i>\n </a>\n <a href="" class="btn btn-default" \n ng-show="vm.selectedResources && vm.showStats"\n ng-click="vm.showStats = false">\n <i class="glyphicon glyphicon-transfer"></i>\n </a>\n </div>\n</div>\n\n<div class="row" ng-show="vm.loader">\n <div class="col-xs-12">\n <div class="loader">Loading</div>\n </div>\n</div>\n\n<section ng-hide="vm.loader" ng-class="{animate: !vm.loader}">\n <div class="row">\n <div class="col-sm-3 service-list">\n <h3>XOS Service: </h3>\n <uib-accordion close-others="true" template-url="templates/accordion.html">\n <uib-accordion-group\n ng-repeat="(service, slices) in vm.projects | orderObjectByKey"\n template-url="templates/accordion-group.html"\n heading="{{service}}">\n <h4>Slices:</h4>\n <a ng-repeat="(slice, resources) in slices" \n ng-class="{active: slice === vm.selectedSlice}"\n ng-click="vm.selectResources(resources, slice)"\n href="#" class="list-group-item" >\n {{slice}} <i class="glyphicon glyphicon-chevron-right pull-right"></i>\n </a>\n </uib-accordion-group>\n </uib-accordion>\n </div>\n <section class="side-container col-sm-9">\n <div class="row">\n <article ng-hide="!vm.showStats" class="stats animate-slide-left">\n <div class="col-xs-12">\n <div class="list-group">\n <div class="list-group-item">\n <h3>Stats</h3>\n </div>\n <div class="list-group-item">\n <ceilometer-stats ng-if="vm.selectedSlice" name="vm.selectedSlice"></ceilometer-stats>\n </div>\n </div>\n </div>\n </article>\n <article ng-hide="vm.showStats" class="meters animate-slide-left">\n <div class="col-sm-4 animate-slide-left" ng-hide="!vm.selectedResources">\n <div class="list-group">\n <div class="list-group-item">\n <h3>Resources</h3>\n </div>\n <a href="#" \n ng-click="vm.selectMeters(meters, resource)" \n class="list-group-item" \n ng-repeat="(resource, meters) in vm.selectedResources" \n ng-class="{active: resource === vm.selectedResource}">\n {{resource}} <i class="glyphicon glyphicon-chevron-right pull-right"></i>\n </a>\n </div>\n </div>\n <div class="col-sm-8 animate-slide-left" ng-hide="!vm.selectedMeters">\n <div class="list-group">\n <div class="list-group-item">\n <h3>Meters</h3>\n </div>\n <div class="list-group-item">\n <div class="row">\n <div class="col-xs-6">\n <label>Name:</label>\n </div>\n <div class="col-xs-3">\n <label>Unit:</label>\n </div>\n <div class="col-xs-3"></div>\n </div>\n <div class="row" ng-click="vm.selectMeters(meters)" ng-repeat="meter in vm.selectedMeters" style="margin-bottom: 10px;">\n <div class="col-xs-6">\n {{meter.name}}\n </div>\n <div class="col-xs-3">\n {{meter.unit}}\n </div>\n <div class="col-xs-3">\n <a ui-sref="samples({name: meter.name, tenant: meter.resource_id})" class="btn btn-primary">\n <i class="glyphicon glyphicon-search"></i>\n </a>\n </div>\n </div>\n </div>\n </div>\n </div>\n </article>\n </div>\n </section>\n </div>\n</section>\n<section ng-if="!vm.loader && vm.error">\n <div class="alert alert-danger">\n {{vm.error}}\n </div>\n</section>\n'),e.put("templates/ceilometer-samples.tpl.html",'<!-- <pre>{{ vm | json}}</pre> -->\n\n<div class="row">\n <div class="col-xs-10">\n <h1>{{vm.name | uppercase}}</h1>\n </div>\n <div class="col-xs-2">\n <a ui-sref="ceilometerDashboard" class="btn btn-primary pull-right">\n <i class="glyphicon glyphicon-arrow-left"></i> Back to list\n </a>\n </div>\n</div>\n<div class="row" ng-show="vm.loader">\n <div class="col-xs-12">\n <div class="loader">Loading</div>\n </div>\n</div>\n<section ng-if="!vm.loader && !vm.error">\n <div class="row">\n <form class="form-inline col-xs-8" ng-submit="vm.addMeterToChart(vm.addMeterValue)">\n <select ng-model="vm.addMeterValue" class="form-control" ng-options="resource.id as resource.name for resource in vm.sampleLabels"></select>\n <button class="btn btn-success"> \n <i class="glyphicon glyphicon-plus"></i> Add\n </button>\n </form>\n <div class="col-xs-4 text-right">\n <a ng-click="vm.chartType = \'line\'" class="btn" ng-class="{\'btn-default\': vm.chartType != \'bar\', \'btn-primary\': vm.chartType == \'line\'}">Lines</a>\n <a ng-click="vm.chartType = \'bar\'" class="btn" ng-class="{\'btn-default\': vm.chartType != \'line\', \'btn-primary\': vm.chartType == \'bar\'}">Bars</a>\n </div>\n </div>\n <div class="row" ng-if="!vm.loader">\n <div class="col-xs-12">\n <canvas ng-if="vm.chartType === \'line\'" id="line" class="chart chart-line" chart-data="vm.chart.data" chart-options="{datasetFill: false}"\n chart-labels="vm.chart.labels" chart-legend="false" chart-series="vm.chart.series">\n </canvas>\n <canvas ng-if="vm.chartType === \'bar\'" id="bar" class="chart chart-bar" chart-data="vm.chart.data"\n chart-labels="vm.chart.labels" chart-legend="false" chart-series="vm.chart.series">\n </canvas>\n <!-- <pre>{{vm.chartMeters | json}}</pre> -->\n </div>\n </div>\n <div class="row" ng-if="!vm.loader">\n <div class="col-xs-12">\n <a ng-click="vm.removeFromChart(meter)" class="btn btn-chart" ng-style="{\'background-color\': vm.chartColors[$index]}" ng-repeat="meter in vm.chartMeters">\n {{meter.resource_name}}\n </a>\n </div>\n </div>\n</section>\n<section ng-if="!vm.loader && vm.error">\n <div class="alert alert-danger">\n {{vm.error}}\n </div>\n</section>'),e.put("templates/ceilometer-stats.tpl.html",'<div ng-show="vm.loader" class="loader">Loading</div>\n\n<section ng-if="!vm.loader && !vm.error">\n\n <div class="alert alert-danger" ng-if="vm.stats.length == 0">\n No result\n </div> \n\n <table class="table" ng-if="vm.stats.length > 0">\n <tr>\n <th>Type:</th>\n <th>Meter:</th>\n <th>Unit:</th>\n <th>Value:</th>\n </tr>\n <tr ng-repeat="item in vm.stats">\n <td>{{item.type}}</td>\n <td>{{item.meter}}</td>\n <td>{{item.unit}}</td>\n <td>{{item.value}}</td>\n </tr>\n </table>\n</section>\n\n<section ng-if="!vm.loader && vm.error">\n <div class="alert alert-danger">\n {{vm.error}}\n </div>\n</section>\n')}]),angular.module("xos.ceilometerDashboard").run(["$location",function(e){e.path("/")}]),angular.bootstrap(angular.element("#xosCeilometerDashboard"),["xos.ceilometerDashboard"]);
\ No newline at end of file
diff --git a/xos/xos_configuration/xos_frontend_config b/xos/xos_configuration/xos_frontend_config
deleted file mode 100755
index 13fe53b..0000000
--- a/xos/xos_configuration/xos_frontend_config
+++ /dev/null
@@ -1,4 +0,0 @@
-[gui]
-branding_name=CORD
-branding_css=/static/cord.css
-branding_icon=/static/onos-logo.png