eagle-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ji...@apache.org
Subject incubator-eagle git commit: EAGLE-106 Use nvd3 replace flot for UI chart flot is no maintenance for more than 1 year. Some feature need additional work. Use nvd3 to replace.
Date Thu, 31 Dec 2015 09:05:25 GMT
Repository: incubator-eagle
Updated Branches:
  refs/heads/master 23b32b12a -> 8537d4557


EAGLE-106 Use nvd3 replace flot for UI chart
flot is no maintenance for more than 1 year. Some feature need additional work. Use nvd3 to replace.

https://issues.apache.org/jira/browse/EAGLE-106

Author: @zombieJ
Reviewer: @haoch

Closes #44


Project: http://git-wip-us.apache.org/repos/asf/incubator-eagle/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-eagle/commit/8537d455
Tree: http://git-wip-us.apache.org/repos/asf/incubator-eagle/tree/8537d455
Diff: http://git-wip-us.apache.org/repos/asf/incubator-eagle/diff/8537d455

Branch: refs/heads/master
Commit: 8537d4557461d107e6e0835971174d8f56a91396
Parents: 23b32b1
Author: jiljiang <jiljiang@ebay.com>
Authored: Thu Dec 31 17:05:19 2015 +0800
Committer: jiljiang <jiljiang@ebay.com>
Committed: Thu Dec 31 17:05:19 2015 +0800

----------------------------------------------------------------------
 eagle-webservice/src/main/webapp/Gruntfile.js   |   1 +
 eagle-webservice/src/main/webapp/app/index.html |  28 +-
 .../src/main/webapp/app/partials/dam/nvd3.html  |  19 +
 .../webapp/app/partials/dam/policyDetail.html   |   8 +-
 .../app/partials/dam/userProfileDetail.html     |  11 +-
 .../public/assets/flot/jquery.flot.legend.js    | 121 ------
 .../public/assets/flot/jquery.flot.tooltip.js   | 395 -------------------
 .../src/main/webapp/app/public/css/main.css     |  18 +-
 .../src/main/webapp/app/public/js/app.js        |   8 +-
 .../src/main/webapp/app/public/js/app.time.js   |  15 +
 .../webapp/app/public/js/components/charts.js   | 192 ---------
 .../app/public/js/components/charts/bar.js      | 296 --------------
 .../webapp/app/public/js/components/nvd3.js     | 300 ++++++++++++++
 .../webapp/app/public/js/ctrl/damController.js  |   2 +-
 .../app/public/js/ctrl/policyController.js      |  21 +-
 .../app/public/js/ctrl/userProfileController.js |  29 +-
 eagle-webservice/src/main/webapp/grunt.json     |   9 +-
 eagle-webservice/src/main/webapp/package.json   |   4 +-
 18 files changed, 411 insertions(+), 1066 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/8537d455/eagle-webservice/src/main/webapp/Gruntfile.js
----------------------------------------------------------------------
diff --git a/eagle-webservice/src/main/webapp/Gruntfile.js b/eagle-webservice/src/main/webapp/Gruntfile.js
index 7b1f3e1..a32b1da 100644
--- a/eagle-webservice/src/main/webapp/Gruntfile.js
+++ b/eagle-webservice/src/main/webapp/Gruntfile.js
@@ -52,6 +52,7 @@ module.exports = function (grunt) {
 
 					'app/public/js/components/main.js',
 					'app/public/js/components/**.js',
+					'app/public/js/components/**/**.js',
 
 					'app/public/js/ctrl/damController.js',
 					'app/public/js/ctrl/*.js',

http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/8537d455/eagle-webservice/src/main/webapp/app/index.html
----------------------------------------------------------------------
diff --git a/eagle-webservice/src/main/webapp/app/index.html b/eagle-webservice/src/main/webapp/app/index.html
index e645ba4..82b543f 100644
--- a/eagle-webservice/src/main/webapp/app/index.html
+++ b/eagle-webservice/src/main/webapp/app/index.html
@@ -33,6 +33,7 @@
 		<link href="../node_modules/bootstrap/dist/css/bootstrap.min.css" rel="stylesheet" type="text/css" media="screen">
 		<link href="../node_modules/zombiej-bootstrap-components/bootstrap-components/css/bootstrap-components.min.css" rel="stylesheet" type="text/css" media="screen">
 		<link href="../node_modules/font-awesome/css/font-awesome.min.css" rel="stylesheet" type="text/css" />
+		<link href="../node_modules/zombiej-nvd3/build/nv.d3.min.css" rel="stylesheet" type="text/css" />
 		<link href="../node_modules/admin-lte/dist/css/AdminLTE.min.css" rel="stylesheet" type="text/css" />
 		<link href="../node_modules/admin-lte/dist/css/skins/skin-blue.min.css" rel="stylesheet" type="text/css" />
 		<!-- endref -->
@@ -48,7 +49,7 @@
 				<!-- Header Navbar: style can be found in header.less -->
 				<nav class="navbar navbar-static-top" role="navigation">
 					<!-- Sidebar toggle button-->
-					<a href="#" ng-hide="globalContent.hideSidebar" class="sidebar-toggle" data-toggle="offcanvas" role="button">
+					<a ng-hide="globalContent.hideSidebar" class="sidebar-toggle" data-toggle="offcanvas" role="button">
 						<span class="sr-only">Toggle navigation</span>
 						<span class="icon-bar"></span>
 						<span class="icon-bar"></span>
@@ -165,26 +166,20 @@
 		</div><!-- ./wrapper -->
 
 		<!-- ref:js public/js/doc.js -->
-		<script src="../node_modules/jquery/dist/jquery.min.js"></script>
+		<script src="../node_modules/jquery/dist/jquery.js"></script>
 		<script src="../node_modules/jquery-slimscroll/jquery.slimscroll.min.js"></script>
 		<script src="../node_modules/bootstrap/dist/js/bootstrap.min.js"></script>
 		<script src="../node_modules/zombiej-bootstrap-components/bootstrap-components/js/bootstrap-components.min.js"></script>
 		<script src="../node_modules/moment/min/moment-with-locales.min.js"></script>
 		<script src="../node_modules/moment-timezone/builds/moment-timezone-with-data.min.js"></script>
 		<script src="../node_modules/admin-lte/dist/js/app.min.js"></script>
-		<script src="../node_modules/angular/angular.min.js"></script>
-		<script src="../node_modules/angular-resource/angular-resource.min.js"></script>
-		<script src="../node_modules/angular-route/angular-route.min.js"></script>
-		<script src="../node_modules/angular-cookies/angular-cookies.min.js"></script>
-		<script src="../node_modules/angular-ui-bootstrap/ui-bootstrap-tpls.min.js"></script>
-		<script src="../node_modules/Flot/jquery.flot.js"></script>
-		<script src="../node_modules/Flot/jquery.flot.stack.js"></script>
-		<script src="../node_modules/Flot/jquery.flot.pie.js"></script>
-		<script src="../node_modules/Flot/jquery.flot.time.js"></script>
-		<script src="../node_modules/Flot/jquery.flot.crosshair.js"></script>
-		<script src="public/assets/flot/jquery.flot.tooltip.js"></script>
-		<script src="public/assets/flot/jquery.flot.legend.js"></script>
-		<script src="../node_modules/d3/d3.min.js"></script>
+		<script src="../node_modules/angular/angular.js"></script>
+		<script src="../node_modules/angular-resource/angular-resource.js"></script>
+		<script src="../node_modules/angular-route/angular-route.js"></script>
+		<script src="../node_modules/angular-cookies/angular-cookies.js"></script>
+		<script src="../node_modules/angular-ui-bootstrap/ui-bootstrap-tpls.js"></script>
+		<script src="../node_modules/d3/d3.js"></script>
+		<script src="../node_modules/zombiej-nvd3/build/nv.d3.js"></script>
 
 
 		<script src="public/js/app.js" type="text/javascript" charset="utf-8"></script>
@@ -198,9 +193,8 @@
 		<script src="public/js/components/sortTable.js" type="text/javascript" charset="utf-8"></script>
 		<script src="public/js/components/tabs.js" type="text/javascript" charset="utf-8"></script>
 		<script src="public/js/components/file.js" type="text/javascript" charset="utf-8"></script>
-		<script src="public/js/components/charts.js" type="text/javascript" charset="utf-8"></script>
-		<script src="public/js/components/charts/bar.js" type="text/javascript" charset="utf-8"></script>
 		<script src="public/js/components/charts/line3d.js" type="text/javascript" charset="utf-8"></script>
+		<script src="public/js/components/nvd3.js" type="text/javascript" charset="utf-8"></script>
 
 
 		<script src="public/js/ctrl/damController.js" type="text/javascript" charset="utf-8"></script>

http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/8537d455/eagle-webservice/src/main/webapp/app/partials/dam/nvd3.html
----------------------------------------------------------------------
diff --git a/eagle-webservice/src/main/webapp/app/partials/dam/nvd3.html b/eagle-webservice/src/main/webapp/app/partials/dam/nvd3.html
new file mode 100644
index 0000000..1a0196d
--- /dev/null
+++ b/eagle-webservice/src/main/webapp/app/partials/dam/nvd3.html
@@ -0,0 +1,19 @@
+<style>
+	.nvd3-chart-cntr > h3 {
+		text-align: center;
+	}
+
+	.nvd3-chart-cntr > svg {
+		height: 300px;
+	}
+</style>
+
+<button class="btn btn-primary" ng-click="randomChartData()">Random</button>
+<button class="btn btn-primary" ng-click="chart = 'column'">To Column</button>
+<button class="btn btn-primary" ng-click="chart = 'line'">To Line</button>
+<button class="btn btn-primary" ng-click="chart = 'area'">To Area</button>
+<button class="btn btn-primary" ng-click="chart = 'pie'">To Pie</button>
+<button class="btn btn-warning" ng-click="chartConfig.xType = 'number'">Number</button>
+<button class="btn btn-warning" ng-click="chartConfig.xType = 'time'">Time</button>
+
+<div nvd3="data" data-title="Test" data-chart="{{chart}}" data-watching="true" data-config="chartConfig" class="nvd3-chart-cntr"></div>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/8537d455/eagle-webservice/src/main/webapp/app/partials/dam/policyDetail.html
----------------------------------------------------------------------
diff --git a/eagle-webservice/src/main/webapp/app/partials/dam/policyDetail.html b/eagle-webservice/src/main/webapp/app/partials/dam/policyDetail.html
index 5587ae0..9540ac6 100644
--- a/eagle-webservice/src/main/webapp/app/partials/dam/policyDetail.html
+++ b/eagle-webservice/src/main/webapp/app/partials/dam/policyDetail.html
@@ -81,16 +81,16 @@
 		<div class="tab-pane active" data-id="visualization">
 			<div class="row">
 				<div class="col-xs-6">
-					<chart title="Policy Eval Count" data="policyEvalSeries"></chart>
+					<div nvd3="policyEvalSeries" data-title="Policy Eval Count" data-config="chartConfig" class="nvd3-chart-cntr"></div>
 				</div>
 				<div class="col-xs-6">
-					<chart title="Policy Eval Fail Count" data="policyEvalFailSeries"></chart>
+					<div nvd3="policyEvalFailSeries" data-title="Policy Eval Fail Count" data-config="chartConfig" class="nvd3-chart-cntr"></div>
 				</div>
 				<div class="col-xs-6">
-					<chart title="Alert Count" data="alertSeries"></chart>
+					<div nvd3="alertSeries" data-title="Alert Count" data-config="chartConfig" class="nvd3-chart-cntr"></div>
 				</div>
 				<div class="col-xs-6">
-					<chart title="Alert Fail Count" data="alertFailSeries"></chart>
+					<div nvd3="alertFailSeries" data-title="Alert Fail Count" data-config="chartConfig" class="nvd3-chart-cntr"></div>
 				</div>
 			</div>
 		</div><!-- /.tab-pane -->

http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/8537d455/eagle-webservice/src/main/webapp/app/partials/dam/userProfileDetail.html
----------------------------------------------------------------------
diff --git a/eagle-webservice/src/main/webapp/app/partials/dam/userProfileDetail.html b/eagle-webservice/src/main/webapp/app/partials/dam/userProfileDetail.html
index 3ee22e4..7c6e19a 100644
--- a/eagle-webservice/src/main/webapp/app/partials/dam/userProfileDetail.html
+++ b/eagle-webservice/src/main/webapp/app/partials/dam/userProfileDetail.html
@@ -43,18 +43,20 @@
 <div class="nav-tabs-custom">
 	<ul class="nav nav-tabs">
 		<li class="active">
-			<a href="[data-id='DE']" data-toggle="tab">DE</a>
+			<a href="[data-id='DE']" data-toggle="tab" ng-click=" currentTab='DE'">DE</a>
 		</li>
 		<li>
-			<a href="[data-id='EigenDecomposition']" data-toggle="tab">EigenDecomposition</a>
+			<a href="[data-id='EigenDecomposition']" data-toggle="tab" ng-click=" currentTab='EigenDecomposition'">EigenDecomposition</a>
+		</li>
+		<li class="pull-right">
+			<button class="btn btn-primary" ng-click="showRawData(currentTab === 'EigenDecomposition' ? profiles.EigenDecomposition.content : profiles.DE.content)">Raw Data</button>
 		</li>
 	</ul>
 	<div class="tab-content">
 		<div class="tab-pane active" data-id="DE">
 			<div class="row">
 				<div class="col-md-9">
-					<button class="btn btn-primary fixed-right" ng-click="showRawData(profiles.DE.content)">Raw Data</button>
-					<div bar-chart height="400" data="profiles.DE._chart.series"> </div>
+					<div nvd3="profiles.DE._chart.series" data-config="{chart: 'column', xType: 'text', height: 400}" class="nvd3-chart-cntr" height="400"></div>
 					<div class="inline-group text-center">
 						<dl ng-repeat="(key, value) in profiles.DE.estimates"><dt>{{key}}</dt><dd>{{value}}</dd></dl>
 					</div>
@@ -79,7 +81,6 @@
 			</div>
 		</div><!-- /.tab-pane -->
 		<div class="tab-pane" data-id="EigenDecomposition">
-			<button class="btn btn-primary fixed-right" ng-click="showRawData(profiles.EigenDecomposition.content)">Raw Data</button>
 			<div line3d-chart height="400" data="profiles.EigenDecomposition._chart.series"> </div>
 		</div><!-- /.tab-pane -->
 	</div><!-- /.tab-content -->

http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/8537d455/eagle-webservice/src/main/webapp/app/public/assets/flot/jquery.flot.legend.js
----------------------------------------------------------------------
diff --git a/eagle-webservice/src/main/webapp/app/public/assets/flot/jquery.flot.legend.js b/eagle-webservice/src/main/webapp/app/public/assets/flot/jquery.flot.legend.js
deleted file mode 100644
index b0d2edc..0000000
--- a/eagle-webservice/src/main/webapp/app/public/assets/flot/jquery.flot.legend.js
+++ /dev/null
@@ -1,121 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-(function($) {
-	"use strict";
-
-	var defaultOptions = {
-		legend : {
-			clickSelect: false,
-			autoAdjust: true,
-		}
-	};
-
-	var init = function(plot) {
-		var $cntr = $(plot.getPlaceholder());
-		var _statusList = [];
-		var _init = false;
-
-		function getIndex(series) {
-			var _index;
-			$.each(plot.getData(), function(index, _series) {
-				if(_series === series) {
-					_index = index;
-					return false;
-				}
-			});
-			return _index;
-		}
-
-		function isShow(index) {
-			var _data = plot.getData();
-			if(!_data) return null;
-
-			var _series = _data[index];
-			var _oriSeries = _statusList[index];
-
-			return	(_series.bars.show && _oriSeries.bars) || 
-					(_series.lines.show && _oriSeries.lines) || 
-					(_series.points.show && _oriSeries.points);
-		}
-		function show(index, display) {
-			var _data = plot.getData();
-			var series = _data[index];
-			series.lines.show = display && _statusList[index].lines;
-			series.bars.show = display && _statusList[index].bars;
-			series.points.show = display && _statusList[index].points;
-		}
-
-		$cntr.off("click.legend").on("click.legend", ".legend table tbody tr", function() {
-			var _my = $(this);
-			var _index = _my.index();
-			var _data = plot.getData();
-
-			var _myShow = isShow(_index);
-
-			if(plot.getOptions().legend.clickSelect === true) {
-				var _showAll = _myShow && $.grep(_data, function(_series, i) {
-					return !isShow(i);
-				}).length !== 0;
-				$.each(_data, function(i, _series) {
-					show(i, _showAll);
-				});
-				show(_index, true);
-			} else {
-				show(_index, !_myShow);
-			}
-			plot.setData(_data);
-
-			plot.setupGrid();
-			plot.draw();
-		});
-
-		plot.hooks.bindEvents.push(function(plot, eventHolder) {
-			var _data = plot.getData();
-			$.each(_data, function(i, series) {
-				_statusList[i] = {
-					bars: series.bars.show,
-					lines: series.lines.show,
-					points: series.points.show,
-				};
-			});
-
-			_init = true;
-		});
-
-		plot.hooks.processDatapoints.push(function(plot, series, dataPoints) {
-			var _option = plot.getOptions();
-			// Auto adjust view size
-			if(_init && (_option.series && !_option.series.stack) && _option.legend.autoAdjust === true) {
-				var index = getIndex(series);
-
-				if(isShow(index) === false) {
-					dataPoints.points = [];
-				}
-			}
-		});
-	};
-
-	// define Flot plugin
-	$.plot.plugins.push({
-		init : init,
-		options : defaultOptions,
-		name : 'legend',
-		version : '0.8.3'
-	});
-})(jQuery);

http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/8537d455/eagle-webservice/src/main/webapp/app/public/assets/flot/jquery.flot.tooltip.js
----------------------------------------------------------------------
diff --git a/eagle-webservice/src/main/webapp/app/public/assets/flot/jquery.flot.tooltip.js b/eagle-webservice/src/main/webapp/app/public/assets/flot/jquery.flot.tooltip.js
deleted file mode 100644
index ca763a5..0000000
--- a/eagle-webservice/src/main/webapp/app/public/assets/flot/jquery.flot.tooltip.js
+++ /dev/null
@@ -1,395 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-(function($) {
-	"use strict";
-
-	// Common
-	function getValueByPath(unit, path, defaultValue) {
-		if(unit === null || unit === undefined) throw "Unit or path can't be empty!";
-		if(path === "" || path === null || path === undefined) return unit;
-
-		path = path.split(/\./);
-		$.each(path, function(i, path) {
-			unit = unit[path];
-			if(unit === null || unit === undefined) {
-				unit = null;
-				return false;
-			}
-		});
-		if(unit === null && defaultValue !== undefined) {
-			unit = defaultValue;
-		}
-		return unit;
-	}
-
-	var OFFSET_X = 15;
-	var OFFSET_Y = 20;
-	var OFFSET_DES = 20;
-
-	var defaultOptions = {
-		tooltip : {
-			show: true,
-			share: true,
-			id: null,						// Define the tool tip id. Will share tool tip if use same id
-			className: "flotToolTip",
-			container: "body",
-			useCSS: true,
-			css: {
-				display: "inline-block",
-				background: "rgba(0,0,0,0.7)",
-				padding: "3px 5px",
-				color: "#FFFFFF",
-				position: "fixed",
-				"z-index": 3,
-				"border-radius": "3px",
-				"font-size": "12px",
-			},
-			chartVisibleCheck: false,		// True will create timer to loop check the chart exist or not. Always suggest use 'plot.destroy' to destroy chart.
-			//xFormat: "YYYY-MM-DD HH:mm:ss",
-			xFormat: "%Y-%M-%D %H:%m:%s",	// %W:weekday, %MS:millionSecond
-			yFormat: "%value",				// %value.number: support to fixed the value
-			formatter: null,				// Customize formatter function. Return DOM element as tooltip content. Return null will not display tool tip.
-		}
-	};
-
-	// ================================================
-	// =                    Format                    =
-	// ================================================
-	function _fillZero(num, len) {
-		if(len === undefined) len = 2;
-		var str = num + "";
-		while(str.length < len) {
-			str = "0" + str;
-		}
-		return str;
-	}
-
-	function _parseValue(value, format, plot) {
-		if(typeof format === "function") {
-			return format(value, plot);
-		} else {
-			var _date = new Date(value);
-
-			return format
-			.replace(/(%value)((\.)(\w+))?/, function() {
-				var _decimal = arguments[4];
-				if(_decimal !== undefined) {
-					return value.toFixed(Number(_decimal));
-				} else {
-					return value;
-				}
-			})
-
-			.replace(/%MS/g, _fillZero(_date.getUTCMilliseconds(), 3))
-			.replace(/%Y/g, _fillZero(_date.getUTCFullYear(), 4))
-			.replace(/%M/g, _fillZero(_date.getUTCMonth() + 1))
-			.replace(/%W/g, _date.getUTCDay() + 1)
-			.replace(/%D/g, _fillZero(_date.getUTCDate()))
-			.replace(/%H/g, _fillZero(_date.getUTCHours()))
-			.replace(/%m/g, _fillZero(_date.getUTCMinutes()))
-			.replace(/%s/g, _fillZero(_date.getUTCSeconds()));
-		}
-	}
-
-	function parseContent(plot, dataList, item, pos, closestSeriesIndex) {
-		var _options = plot.getOptions();
-		var _data = plot.getData();
-		var _tooltipOps = _options.tooltip;
-
-		var $cntr = $("<div>");
-
-		if(getValueByPath(_options, "series.pie.show")) {
-			// Pie Chart
-			if(!item) return null;
-
-			var _series = item.series;
-			var _title = _series.label;
-			if(typeof _title === "number") {
-				_title = _parseValue(_title, _tooltipOps.xFormat, plot);
-			}
-
-			$("<span>")
-			.append($("<span>").html("\u25CF").css("color", _series.color)).append(" ")
-			.append(_title)
-			.append(": ")
-			.append($("<b>").text(_parseValue(item.datapoint[1][0][1], _tooltipOps.yFormat, plot)))
-			.appendTo($cntr);
-		} else {
-			// Other Chart
-			if(!dataList.length) return null;
-
-			var _share = _tooltipOps.share !== false;
-
-			// Check x-axis is same or not
-			var _time = getValueByPath(dataList, "0.0", null);
-			var _multiTime = false;
-			if(_share) {
-				$.each(dataList, function(index, point) {
-					if(point[0] !== _time) {
-						_multiTime = true;
-						return false;
-					}
-				});
-			} else {
-				_multiTime = true;
-			}
-
-			// Display Content
-			$.each(dataList, function(index, point) {
-				if(!_share && closestSeriesIndex !== index) {
-					return;
-				}
-
-				if(point[1] === null) {
-					return;
-				}
-
-				// X-Axis
-				if(index === 0 || _multiTime) {
-					if(index !== 0) $cntr.append("<br/>");
-					$("<span>").text(_parseValue(point[0], _tooltipOps.xFormat, plot)).appendTo($cntr);
-				}
-
-				var _series = _data[index];
-
-				$cntr.append("<br/>");
-				var $row = $("<span>")
-				.append($("<span>").html("\u25CF").css("color", _series.color)).append(" ")
-				.append(_series.label)
-				.append(": ")
-				.append($("<b>").text(_parseValue(point[1], _tooltipOps.yFormat, plot)))
-				.appendTo($cntr);
-			});
-
-			if($($cntr.children()[0]).is("br")) {
-				$($cntr.children()[0]).remove();
-			}
-		}
-
-		return $cntr;
-	}
-
-	// ================================================
-	// =                      UI                      =
-	// ================================================
-	var init = function(plot) {
-		var $cntr = $(plot.getPlaceholder());
-		var _lastToolTip = null;
-		var _checkID = null;
-		var _showID;
-		var _lastPos;
-		var _lastItem;
-		var _elementID;
-
-		function tooltip(ele) {
-			if(ele === null) {
-				$cntr.removeData("flot-tooltip");
-			} else if(ele) {
-				_lastToolTip = ele;
-				$cntr.data("flot-tooltip", ele);
-			}
-			if(_elementID) {
-				ele = $("#" + _elementID);
-				return ele.length ? ele : null;
-			} else {
-				return $cntr.data("flot-tooltip");
-			}
-		}
-
-		function removeTooltip(immediately) {
-			var _timeoutID = $cntr.data("flot-tooltip-timeout");
-			clearTimeout(_timeoutID);
-
-			_timeoutID = setTimeout(function() {
-				_lastToolTip = _elementID ? tooltip() : (_lastToolTip || tooltip());
-				if(!_lastToolTip) return;
-
-				_lastToolTip.fadeOut(function() {
-					$(this).remove();
-				});
-				tooltip(null);
-			}, immediately === true ? 0 : 250);
-
-			$cntr.data("flot-tooltip-timeout", _timeoutID);
-			if(tooltip()) tooltip().data("flot-tooltip-timeout", _timeoutID);
-		}
-
-		// Show tool tip
-		function tracker(plot, eventHolder) {
-			var _options = plot.getOptions();
-			var _tooltipOps = _options.tooltip;
-			var _className = _tooltipOps.className;
-			_elementID = _tooltipOps.id;
-
-			if(!_options.grid.hoverable) return;
-
-			// Loop checker
-			if(_tooltipOps.chartVisibleCheck) {
-				_checkID = setInterval(function() {
-					if(_lastToolTip && !$cntr.is(":visible")) {
-						tooltip(null);
-						_lastToolTip.remove();
-						_lastToolTip = null;
-					}
-				}, 1000);
-			}
-
-			eventHolder.on("mousemove.flot-tooltip", function(event) {
-				clearTimeout($cntr.data("flot-tooltip-timeout"));
-				var _content;
-
-				var $tooltip = tooltip();
-				if(!$tooltip) {
-					_content = getContent();
-					if(_content === null) return;
-
-					$tooltip = $("<div>").addClass(_className).appendTo(_tooltipOps.container);
-					if(_elementID) $tooltip.attr("id", _elementID);
-
-					if(_tooltipOps.useCSS) {
-						$.each(_tooltipOps.css, function(key, value) {
-							$tooltip.css(key, value);
-						});
-					}
-					tooltip($tooltip);
-					showContent(_content);
-				}
-				if(_elementID) {
-					$tooltip.stop().css("opacity", 1);
-					clearTimeout($tooltip.data("flot-tooltip-timeout"));
-				}
-				
-
-				var _x = event.pageX + OFFSET_X;
-				var _y = event.pageY + OFFSET_Y;
-				var _width = $tooltip.outerWidth();
-				var _height = $tooltip.outerHeight();
-				var _winWidth = $(window).width();
-				var _winHeight = $(window).height();
-				var _winLeft = $(window).scrollLeft();
-				var _winTop = $(window).scrollTop();
-
-				if(_x + _width + OFFSET_DES - _winLeft > _winWidth) {
-					_x = event.pageX - _width - OFFSET_X;
-				}
-				if(_y + _height + OFFSET_DES - _winTop > _winHeight) {
-					_y = event.pageY - _height - OFFSET_Y;
-				}
-
-				$tooltip.offset({
-					left: _x,
-					top: _y
-				});
-
-				if(!_showID) {
-					_showID = setTimeout(showContent, tooltip() ? 50 : 0);
-				}
-			});
-			eventHolder.on("mouseout.flot-tooltip", function(event) {
-				removeTooltip();
-			});
-
-			// Tool tip Content
-			function getContent() {
-				var _x = _lastPos.x;
-				var _y = _lastPos.y;
-
-				var axes = plot.getAxes();
-				if(_x < axes.xaxis.min) _x = axes.xaxis.min;
-				if(_x > axes.xaxis.max) _x = axes.xaxis.max;
-				if(_y < axes.yaxis.min) _y = axes.yaxis.min;
-				if(_y > axes.yaxis.max) _y = axes.yaxis.max;
-
-				var _dataList = [];
-				var _closestSeriesIndex = 0;
-				var _closestSeriesDist;
-				$.each(plot.getData(), function(index, series) {
-					var _hasPoint = false;
-					for(var i = 0 ; i < series.data.length - 1 ; i += 1) {
-						var _unitL = series.data[i];
-						var _unitR = series.data[i + 1];
-						var _unitClose;
-
-						if(_unitL[0] <= _x && _x <= _unitR[0]) {
-							// Find Closest
-							if(getValueByPath(series, "bars.show") || Math.abs(_unitL[0] - _x) < Math.abs(_x - _unitR[0])) {
-								_unitClose = _unitL;
-							} else {
-								_unitClose = _unitR;
-							}
-							_dataList.push(_unitClose);
-
-							// Calculate Closest Series
-							var _desX = _x - _unitClose[0];
-							var _desY = _y - _unitClose[1];
-							var _dist = Math.sqrt(_desX * _desX + _desY * _desY);
-							if(_closestSeriesDist === undefined || _dist < _closestSeriesDist) {
-								_closestSeriesIndex = index;
-								_closestSeriesDist = _dist;
-							}
-
-							_hasPoint = true;
-							break;
-						}
-					}
-					if(!_hasPoint) _dataList.push([null, null]);
-				});
-
-				return _tooltipOps.formatter ? _tooltipOps.formatter(plot, _dataList, _lastItem, _lastPos, _closestSeriesIndex) : parseContent(plot, _dataList, _lastItem, _lastPos, _closestSeriesIndex);
-			}
-			function showContent(content) {
-				_showID = 0;
-
-				if(!content) content = getContent();
-
-				if(tooltip()) {
-					if(content) {
-						tooltip().html(content);
-					} else {
-						removeTooltip(true);
-					}
-					return content;
-				}
-				return false;
-			}
-			$cntr.on("plothover.flot-tooltip", function (event, pos, item) {
-				_lastPos = pos;
-				_lastItem = item;
-			});
-		}
-
-		plot.hooks.bindEvents.push(tracker);
-		plot.hooks.shutdown.push(function (plot, eventHolder) {
-			eventHolder.off("mousemove.flot-tooltip");
-			eventHolder.off("mouseout.flot-tooltip");
-			$(plot.getPlaceholder()).off("plothover.flot-tooltip");
-
-			removeTooltip();
-			clearInterval(_checkID);
-		});
-	};
-
-	// define Flot plugin
-	$.plot.plugins.push({
-		init : init,
-		options : defaultOptions,
-		name : 'tooltip',
-		version : '0.8.3.2'
-	});
-})(jQuery);

http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/8537d455/eagle-webservice/src/main/webapp/app/public/css/main.css
----------------------------------------------------------------------
diff --git a/eagle-webservice/src/main/webapp/app/public/css/main.css b/eagle-webservice/src/main/webapp/app/public/css/main.css
index a82f336..5e80728 100644
--- a/eagle-webservice/src/main/webapp/app/public/css/main.css
+++ b/eagle-webservice/src/main/webapp/app/public/css/main.css
@@ -223,6 +223,10 @@ td.text-ellipsis {
 }
 
 /* Navigation Tab */
+ul.nav.nav-tabs li .btn {
+	margin-top: 1px;
+}
+
 .modal-body ul.nav.nav-tabs {
 	border-bottom-color: #F4F4F4;
 	margin-bottom: 15px;
@@ -407,7 +411,17 @@ ul.tree.tree-bordered > li > ul > li > a {
 }
 
 /* Chart */
-.chart .chart-header h3 {
+.nvd3-chart-cntr > h3 {
+	text-align: center;
+	font-size: 16px;
+	font-weight: bolder;
+}
+
+.nvd3-chart-cntr > svg.nvd3-svg {
+	height: 200px;
+}
+
+/*.chart .chart-header h3 {
 	text-align: center;
 	margin: 10px 0 5px 0;
 }
@@ -423,7 +437,7 @@ ul.tree.tree-bordered > li > ul > li > a {
 
 .chart .chart-body .bar {
 	fill: steelblue;
-}
+}*/
 
 /* Tab */
 body .tab-content>.tab-pane {

http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/8537d455/eagle-webservice/src/main/webapp/app/public/js/app.js
----------------------------------------------------------------------
diff --git a/eagle-webservice/src/main/webapp/app/public/js/app.js b/eagle-webservice/src/main/webapp/app/public/js/app.js
index 097db77..777844d 100644
--- a/eagle-webservice/src/main/webapp/app/public/js/app.js
+++ b/eagle-webservice/src/main/webapp/app/public/js/app.js
@@ -571,7 +571,10 @@ eagleApp.service('Entities', function($http, $q, $rootScope, $location, Authoriz
 				if(_list._convert) {
 					var _current = _cond.additionalCondition._startTime.clone();
 					$.each(_list, function(i, value) {
-						_list[i] = [_current.valueOf(), value];
+						_list[i] = {
+							x: _current.valueOf(),
+							y: value
+						};
 						_current.add(intervalmin, "m");
 					});
 				}
@@ -628,13 +631,14 @@ eagleApp.filter('reverse', function() {
 	};
 });
 
-eagleApp.controller('MainCtrl', function($scope, $location, $http, globalContent, Site, Authorization, Entities) {
+eagleApp.controller('MainCtrl', function($scope, $location, $http, globalContent, Site, Authorization, Entities, nvd3) {
 	'use strict';
 
 	window.globalContent = $scope.globalContent = globalContent;
 	window.site = $scope.site = Site;
 	window.auth = $scope.auth = Authorization;
 	window.entities = $scope.entities = Entities;
+	window.nvd3 = nvd3;
 	$scope.app = app;
 
 	// Clean up

http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/8537d455/eagle-webservice/src/main/webapp/app/public/js/app.time.js
----------------------------------------------------------------------
diff --git a/eagle-webservice/src/main/webapp/app/public/js/app.time.js b/eagle-webservice/src/main/webapp/app/public/js/app.time.js
index fb4bfc6..d61506a 100644
--- a/eagle-webservice/src/main/webapp/app/public/js/app.time.js
+++ b/eagle-webservice/src/main/webapp/app/public/js/app.time.js
@@ -52,4 +52,19 @@
 	moment.fn.toISO = function() {
 		return this.format("YYYY-MM-DDTHH:mm:ss.000Z");
 	};
+
+	// Force convert date
+	var _toDate = moment.fn.toDate;
+	moment.fn.toDate = function(ignoreTimeZone) {
+		if(!ignoreTimeZone) return _toDate.bind(this)();
+		return new Date(
+			this.year(),
+			this.month(),
+			this.date(),
+			this.hour(),
+			this.minute(),
+			this.second(),
+			this.millisecond()
+		);
+	};
 })();
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/8537d455/eagle-webservice/src/main/webapp/app/public/js/components/charts.js
----------------------------------------------------------------------
diff --git a/eagle-webservice/src/main/webapp/app/public/js/components/charts.js b/eagle-webservice/src/main/webapp/app/public/js/components/charts.js
deleted file mode 100644
index 9d5d0f9..0000000
--- a/eagle-webservice/src/main/webapp/app/public/js/components/charts.js
+++ /dev/null
@@ -1,192 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-eagleComponents.directive('chart', function($compile) {
-	'use strict';
-
-	return {
-		restrict : 'E',
-		scope: {
-			title: "@",
-			data: "=",
-		},
-		controller: function(charts, $scope, $element) {
-			var _charts = charts($scope);
-
-			_charts.gen($element.find(".chart-body"), [{
-				data: "data",
-			}]);
-		},
-		template :	'<div class="chart">' +
-						'<div class="chart-header">' +
-							'<h3>{{title}}</h3>' +
-						'</div>' +
-						'<div class="chart-body">' +
-						'</div>' +
-					'</div>',
-		replace: true
-	};
-});
-
-/*
- * config:
- * 		type:	"line"(default), "area". Chart type is the default type of all series. Will be replaced by each series configure.
- */
-eagleComponents.service('charts', function() {
-	'use strict';
-
-	/*
-	 * Destroy chart
-	 */
-	function _destroy(ele) {
-		$(ele).each(function() {
-			var _plot = $(this).data("plot");
-			_plot.shutdown();
-			_plot.destroy();
-		});
-	}
-
-	var charts = function($scope) {
-		var _id = 0;
-
-		return {
-			/*
-			 * Generate chart
-			 */
-			gen: function(ele, series, config) {
-				// Initialization
-				ele = $(ele);
-
-				series = series || [];
-				config = config || {};
-
-				var _listenList = [];
-
-				var _config = {
-					grid: {
-						hoverable: true,
-						clickable: true,
-						borderWidth: 0,
-					},
-					type: "line",
-					colors: [
-						"#7cb5ec", "#f7a35c", "#90ee7e", "#7798BF", "#aaeeee",
-					],
-					series: {
-						shadowSize: 0,
-					},
-					crosshair: {
-						color: "#3c8dbc"
-					},
-					tooltip: {
-						id: "chartTooltip",
-					},
-					xaxis: {
-						mode: "time",
-					},
-					yaxis: {
-						min: 0,
-					},
-					legend: {},
-				};
-
-				$.extend(_config, config);
-
-				// Series process
-				// > Series type
-				$.each(series, function(i, _series) {
-					// Data source
-					if(typeof _series.data === "string") {
-						_listenList.push(_series.data);
-						_series._key = _series.data;
-						_series.data = [];
-					}
-
-					// Chart type
-					switch((_series.type || _config.type || "").toLowerCase()) {
-					case "area":
-						common.setValueByPath(_series, "lines.show", true);
-						common.setValueByPath(_series, "lines.fill", true);
-						/* falls through */
-					default:
-						common.setValueByPath(_series, "lines.show", true);
-					}
-
-					if(_config.xaxis.mode === "time" && $.isArray(_series.data)) {
-						$.each(_series.data, function(i, unit) {
-							unit[0] += app.time.UTC_OFFSET * 1000 * 60;
-						});
-					}
-				});
-
-				// > Data source
-				function _updateSeriesSource() {
-					$.each(series, function(i, _series) {
-						if(typeof _series._key === "string" && $scope[_series._key]) {
-							_series.data = $scope[_series._key];
-							delete _series._key;
-						}
-					});
-				}
-
-				// Chart process
-				_config.type = _config.type.toLowerCase();
-				if(_config.type === "line" || _config.type === "area") {
-					common.setValueByPath(_config, "crosshair.mode", "x");
-				}
-
-				// Draw charts
-				function _drawChart() {
-					_updateSeriesSource();
-
-					ele.each(function() {
-						var _my = $(this);
-						var _plot = _my.data("plot");
-						if(!_plot) {
-							_plot = $.plot(this, series, _config);
-							_plot._id = ++_id;
-							_my.data("plot", _plot);
-						} else {
-							_plot.setData(series);
-							_plot.setupGrid();
-							_plot.draw();
-						}
-					});
-				}
-
-				// Watch
-				$.each(_listenList, function(i, item) {
-					$scope.$watchCollection(item, function() {
-						_drawChart();
-					});
-				});
-
-				// Destroy
-				$scope.$on('$destroy', function() {
-					_destroy(ele);
-				});
-			},
-
-			destroy: _destroy,
-		};
-	};
-
-	charts.destroy = _destroy;
-
-	return charts;
-});

http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/8537d455/eagle-webservice/src/main/webapp/app/public/js/components/charts/bar.js
----------------------------------------------------------------------
diff --git a/eagle-webservice/src/main/webapp/app/public/js/components/charts/bar.js b/eagle-webservice/src/main/webapp/app/public/js/components/charts/bar.js
deleted file mode 100644
index ee58046..0000000
--- a/eagle-webservice/src/main/webapp/app/public/js/components/charts/bar.js
+++ /dev/null
@@ -1,296 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-eagleComponents.directive('barChart', function($compile) {
-	'use strict';
-
-	return {
-		restrict : 'AE',
-		scope : {
-			title : "@",
-			data : "=",
-
-			height : "=?height"
-		},
-		controller : function(barCharts, $scope, $element, $attrs) {
-			$scope.height = $scope.height || 200;
-
-			var _chart = barCharts($scope);
-
-			var _chartBody = $element.find(".chart-body");
-			_chartBody.height($scope.height);
-
-			_chart.gen($element.find(".chart-body"), $attrs.data, {
-				height : $scope.height,
-			});
-		},
-		template : '<div class="chart">' + '<div class="chart-header">' + '<h3>{{title}}</h3>' + '</div>' + '<div class="chart-body">' + '</div>' + '</div>',
-		replace : true
-	};
-});
-
-eagleComponents.service('barCharts', function() {
-	'use strict';
-
-	/*$(window).resize(function() {
-	 });
-	 $("body").on("collapsed.pushMenu", function() {
-	 });
-	 $("body").on("expanded.pushMenu", function() {
-	 });*/
-
-	var charts = function($scope) {
-		return {
-			gen : function(ele, series, config) {
-				// ======================= Initialization =======================
-				ele = $(ele);
-
-				series = series || [];
-				config = config || {};
-
-				// ========================== ToolTips ==========================
-				var $tooltip = $("<div>").css({
-					display: "inline-block",
-					background: "rgba(0,0,0,0.7)",
-					padding: "3px 5px",
-					color: "#FFFFFF",
-					position: "fixed",
-					"z-index": 3,
-					"border-radius": "3px",
-					"font-size": "12px",
-				}).appendTo("body");
-
-				// ======================= Set Up D3 View =======================
-				var margin = {
-					top : 20,
-					right : 20,
-					bottom : 50,
-					left : 40
-				}, width = ele.innerWidth() - margin.left - margin.right, height = config.height - margin.top - margin.bottom;
-
-				var x0 = d3.scale.ordinal().rangeRoundBands([0, width], 0.1);
-				var x1 = d3.scale.ordinal();
-				var y = d3.scale.linear().range([height, 0]);
-
-				var color = d3.scale.ordinal().range(["#7cb5ec", "#f7a35c", "#90ee7e", "#7798BF", "#aaeeee"]);
-
-				var xAxis = d3.svg.axis().scale(x0).orient("bottom");
-				var yAxis = d3.svg.axis().scale(y).orient("left").tickFormat(d3.format("0.2f"));
-
-				var cntr = d3.select(ele[0]).append("svg").attr("width", width + margin.left + margin.right).attr("height", height + margin.top + margin.bottom);
-				var svg = cntr.append("g").attr("transform", "translate(" + margin.left + "," + margin.top + ")");
-
-				// =========================== Render ===========================
-				function _render() {
-					// ======== Parse Data ========
-					var _series = typeof series === "string" ? $scope.data : series;
-					if(!_series) return;
-
-					var _data = [];
-					// > Detect category
-					var _categoryList = [];
-					_series = $.grep(_series, function(unit) {
-						if(unit.type === "category") _categoryList = unit.data;
-						return !unit.type;
-					});
-
-					// > Keys
-					var _keys = $.map(_series, function(unit) {
-						return unit.name;
-					});
-
-					// > Merge values
-					var _maxLen = 0;
-					$.each(_series, function(i, unit) {
-						_maxLen = Math.max(_maxLen, unit.data.length);
-					});
-					function _fillValue(id) {
-						$.each(_keys, function(j, key) {
-							_data[id][key] = _series[j].data[id] || 0;
-						});
-					}
-					for(var i = 0 ; i < _maxLen ; i += 1) {
-						_data[i] = {};
-
-						// Category
-						if(_categoryList[i]) {
-							_data[i]._category = _categoryList[i];
-						} else {
-							_data[i]._category = "CAT" + i;
-						}
-
-						// Value
-						_fillValue(i);
-					}
-
-					// ====== Convert Format ======
-					var ageNames = d3.keys(_data[0]).filter(function(key) {
-						return key !== "_category";
-					});
-
-					_data.forEach(function(d) {
-						d.items = ageNames.map(function(name) {
-							return {
-								name : name,
-								value : +d[name]
-							};
-						});
-					});
-
-					x0.domain(_data.map(function(d) {
-						return d._category;
-					}));
-					x1.domain(ageNames).rangeRoundBands([0, x0.rangeBand()]);
-					y.domain([0, d3.max(_data, function(d) {
-						return d3.max(d.items, function(d) {
-							return d.value;
-						});
-					})]);
-
-					// Axis
-					svg.append("g").attr("class", "y axis").call(yAxis).append("text").attr("transform", "rotate(-90)").attr("y", 6).attr("dy", ".71em").style("text-anchor", "end");
-					svg.append("g").attr("class", "x axis").attr("transform", "translate(0," + height + ")").call(xAxis)
-					.selectAll("text")
-						.attr("transform", "rotate(15)")
-						.attr("x", -x1.rangeBand() * 0.3)
-						.style("text-anchor", "start");
-
-					// Bar
-					var barGroup = svg.selectAll(".barGroup").data(_data).enter().append("g").attr("class", "g").attr("transform", function(d) {
-						return "translate(" + x0(d._category) + ",0)";
-					});
-
-					barGroup.selectAll("rect").data(function(d) {
-						return d.items;
-					}).enter().append("rect").attr("width", x1.rangeBand()).attr("x", function(d) {
-						return x1(d.name);
-					}).attr("y", function(d) {
-						return y(d.value);
-					}).attr("height", function(d) {
-						return height - y(d.value);
-					}).style("fill", function(d) {
-						return color(d.name);
-					});
-
-					// Legend
-					var legend = svg.selectAll(".legend").data(ageNames.slice().reverse()).enter().append("g").attr("class", "legend").attr("transform", function(d, i) {
-						return "translate(0," + (30 + i * 20) + ")";
-					});
-
-					legend.append("rect").attr("x", width - 18).attr("width", 18).attr("height", 18).style("fill", color);
-					legend.append("text").attr("x", width - 24).attr("y", 9).attr("dy", ".35em").style("text-anchor", "end").text(function(d) {
-						return d;
-					});
-
-					// Tool tip
-					var OFFSET_X = 15;
-					var OFFSET_Y = 20;
-					var OFFSET_DES = 20;
-
-					var _tooltipId;
-					var _tooltipPrev;
-					var _xCells = $.map(_data, function(d) {
-						return [[x0(d._category), x0(d._category) + x0.rangeBand(), d]];
-					});
-
-					cntr.on("mousemove", function () {
-						var mouseX = d3.mouse(this.parentNode)[0] - margin.left;
-						var d;
-						for(var i = 0 ; i < _xCells.length ; i += 1) {
-							if(_xCells[i][0] <= mouseX && mouseX <= _xCells[i][1]) {
-								d= _xCells[i][2];
-								break;
-							}
-						}
-
-						if(!d && _tooltipPrev) {
-							_tooltipId = setTimeout(function() {
-								$tooltip.fadeOut('fast');
-							}, _xCells[0] && mouseX < _xCells[0][0] ? 100 : 500);
-						} else if(d) {
-							if(_tooltipPrev !== d) {
-								clearTimeout(_tooltipId);
-
-								$tooltip.empty()
-								.stop().fadeIn('fast');
-
-								var $cntr = $("<div>").appendTo($tooltip);
-								$("<span>").css("display", "block").text(d._category)
-								.appendTo($cntr);
-								$.each(d.items, function(i, item) {
-									$("<span>").css("display", "block")
-									.append($("<span>").html("\u25CF").css("color", color(item.name))).append(" ")
-									.append(item.name)
-									.append(": ")
-									.append($("<b>").text(item.value))
-									.appendTo($cntr);
-								});
-							}
-
-							// Position
-							var _x = event.pageX + OFFSET_X;
-							var _y = event.pageY + OFFSET_Y;
-							var _width = $tooltip.outerWidth();
-							var _height = $tooltip.outerHeight();
-							var _winWidth = $(window).width();
-							var _winHeight = $(window).height();
-							var _winLeft = $(window).scrollLeft();
-							var _winTop = $(window).scrollTop();
-
-							if(_x + _width + OFFSET_DES - _winLeft > _winWidth) {
-								_x = event.pageX - _width - OFFSET_X;
-							}
-							if(_y + _height + OFFSET_DES - _winTop > _winHeight) {
-								_y = event.pageY - _height - OFFSET_Y;
-							}
-
-							$tooltip.offset({
-								left: _x,
-								top: _y
-							});
-						}
-						_tooltipPrev = d;
-					});
-					cntr.on("mouseleave", function () {
-						_tooltipId = setTimeout(function() {
-							$tooltip.fadeOut('fast');
-						}, 100);
-					});
-				}
-
-				// ======================= Dynamic Detect =======================
-				if(typeof series === "string") {
-					$scope.$parent.$watch(series, function() {
-						_render();
-					}, true);
-				} else {
-					_render();
-				}
-
-
-				// ========================== Clean Up ==========================
-				$scope.$on('$destroy', function() {
-					cntr.remove();
-					$tooltip.remove();
-				});
-			},
-		};
-	};
-
-	return charts;
-});

http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/8537d455/eagle-webservice/src/main/webapp/app/public/js/components/nvd3.js
----------------------------------------------------------------------
diff --git a/eagle-webservice/src/main/webapp/app/public/js/components/nvd3.js b/eagle-webservice/src/main/webapp/app/public/js/components/nvd3.js
new file mode 100644
index 0000000..3e51deb
--- /dev/null
+++ b/eagle-webservice/src/main/webapp/app/public/js/components/nvd3.js
@@ -0,0 +1,300 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+eagleComponents.service('nvd3', function() {
+	var nvd3 = {
+		charts: [],
+		colors: [
+			"#7CB5EC", "#F7A35C", "#90EE7E", "#7798BF", "#AAEEEE"
+		]
+	};
+
+	// ============================================
+	// =              Format Convert              =
+	// ============================================
+	nvd3.convert = {};
+	nvd3.convert.eagle = function(seriesList) {
+		return $.map(seriesList, function(series) {
+			var seriesObj = $.isArray(series) ? {values: series} : series;
+			if(!seriesObj.key) seriesObj.key = "value";
+			return seriesObj;
+		});
+	};
+
+	// ============================================
+	// =                    UI                    =
+	// ============================================
+	// Resize with refresh
+	function chartResize() {
+		$.each(nvd3.charts, function(i, chart) {
+			if(chart) chart.update();
+		});
+	}
+	$(window).on("resize.components.nvd3", chartResize);
+	$("body").on("collapsed.pushMenu expanded.pushMenu", function() {
+		setTimeout(chartResize, 300);
+	});
+
+	return nvd3;
+});
+
+/**
+ * config:
+ * 		chart:		Defined chart type: line, column, area
+ * 		xTitle:		Defined x axis title.
+ * 		yTitle:		Defined y axis title.
+ * 		xType:		Defined x axis label type: number, decimal, time
+ * 		yType:		Defined y axis label type
+ */
+eagleComponents.directive('nvd3', function(nvd3) {
+	'use strict';
+
+	return {
+		restrict: 'AE',
+		scope: {
+			nvd3: "=",
+			title: "@?title",				// title
+			chart: "@?chart",				// Same as config.chart
+			config: "=?config",
+			watching: "@?watching"			// Default watching data(nvd3) only. true will also watching chart & config. false do not watching.
+		},
+		controller: function($scope, $element, $attrs, $timeout) {
+			var _config, _chartType;
+			var _chart;
+			var _chartCntr;
+
+			// Destroy
+			function destroy() {
+				var _index = $.inArray(_chart, nvd3.charts);
+				if(!_chartCntr) return _index;
+
+				// Clean events
+				d3.select(_chartCntr)
+					.on("touchmove",null)
+					.on("mousemove",null, true)
+					.on("mouseout" ,null,true)
+					.on("dblclick" ,null)
+					.on("click", null);
+
+				// Clean elements
+				d3.select(_chartCntr).selectAll("*").remove();
+				$element.find(".nvtooltip").remove();
+				$(_chartCntr).remove();
+
+				// Clean chart in nvd3 pool
+				nvd3.charts[_index] = null;
+				_chart = null;
+
+				return _index;
+			}
+
+			// Setup chart environment. Will clean old chart and build new chart if recall.
+			function initChart() {
+				// Clean up if already have chart
+				var _preIndex = destroy();
+
+				// Initialize
+				_config = $.extend({}, $scope.config);
+				_chartType = $scope.chart || _config.chart;
+				_chartCntr = $(document.createElementNS("http://www.w3.org/2000/svg", "svg"))
+					.css("min-height", 50)
+					.attr("_rnd", Math.random())
+					.appendTo($element)[0];
+
+				// Size
+				if(_config.height) {
+					$(_chartCntr).css("height", _config.height);
+				}
+
+				switch(_chartType) {
+					case "line":
+						_chart = nv.models.lineChart()
+							.useInteractiveGuideline(true)
+							.showLegend(true)
+							.showYAxis(true)
+							.showXAxis(true)
+							.options({
+								duration: 350
+							});
+						break;
+					case "column":
+						_chart = nv.models.multiBarChart()
+							.groupSpacing(0.1)
+							.options({
+								duration: 350
+							});
+						break;
+					case "area":
+						_chart = nv.models.stackedAreaChart()
+							.useInteractiveGuideline(true)
+							.showLegend(true)
+							.showYAxis(true)
+							.showXAxis(true)
+							.options({
+								duration: 350
+							});
+						break;
+					case "pie":
+						_chart = nv.models.dimensionalPieChart()
+							.x(function(d) { return d.key; })
+							.y(function(d) { return d.values[0].y; });
+						break;
+					default :
+						throw "Type not defined: " + _chartType;
+				}
+
+				// Define title
+				if(_chartType !== 'pie') {
+					if(_config.xTitle) _chart.xAxis.axisLabel(_config.xTitle);
+					if(_config.yTitle) _chart.yAxis.axisLabel(_config.yTitle);
+				}
+
+				// Define label type
+				var _tickMultiFormat = d3.time.format.multi([
+					["%-I:%M%p", function(d) { return d.getMinutes(); }],
+					["%-I%p", function(d) { return d.getHours(); }],
+					["%b %-d", function(d) { return d.getDate() != 1; }],
+					["%b %-d", function(d) { return d.getMonth(); }],
+					["%Y", function() { return true; }]
+				]);
+
+				function _defineLabelType(axis, type) {
+					if(!_chart) return;
+
+					var _axis = _chart[axis + "Axis"];
+					switch(type) {
+						case "decimal":
+						case "decimals":
+							_axis.tickFormat(d3.format('.02f'));
+							break;
+						case "text":
+							if(axis === "x") {
+								_chart.rotateLabels(10);
+								_chart.reduceXTicks(false).staggerLabels(true);
+							}
+							_axis.tickFormat(function(d) {
+								return d;
+							});
+							break;
+						case "time":
+							if(_chartType !== 'column') {
+								_chart[axis + "Scale"](d3.time.scale());
+							}
+							_axis.tickFormat(function(d) {
+								return _tickMultiFormat(app.time.offset(d).toDate(true));
+							});
+							break;
+						case "number":
+						/* falls through */
+						default:
+							_axis.tickFormat(d3.format(',r'));
+					}
+				}
+
+				if(_chartType !== 'pie') {
+					_defineLabelType("x", _config.xType || "number");
+					_defineLabelType("y", _config.yType || "decimal");
+				}
+
+				// Global chart list update
+				if(_preIndex === -1) {
+					nvd3.charts.push(_chart);
+				} else {
+					nvd3.charts[_preIndex] = _chart;
+				}
+
+				updateData();
+			}
+
+			// Update chart data
+			function updateData() {
+				var _min, _max;
+
+				// Copy series to prevent Angular loop watching
+				var _data = $.map($scope.nvd3 || [], function(series, i) {
+					var _series = $.extend(true, {}, series);
+					_series.color = _series.color || nvd3.colors[i % nvd3.colors.length];
+					return _series;
+				});
+
+				// Chart Y value
+				if(($scope.chart || _config.chart) !== "pie") {
+					$.each(_data, function(i, series) {
+						$.each(series.values, function(j, unit) {
+							if(_min === undefined || unit.y < _min) _min = unit.y;
+							if(_max === undefined || unit.y > _max) _max = unit.y;
+						});
+					});
+					if(_min === 0 && _max === 0) {
+						_chart.forceY([0, 10]);
+					} else {
+						_chart.forceY([]);
+					}
+				}
+
+				// Update data
+				d3.select(_chartCntr)						//Select the <svg> element you want to render the chart in.
+					.datum(_data)							//Populate the <svg> element with chart data...
+					.call(_chart);							//Finally, render the chart!
+			}
+
+			// ================================================================
+			// =                           Watching                           =
+			// ================================================================
+			// Ignore initial checking
+			$timeout(function() {
+				if ($scope.watching !== "false") {
+					$scope.$watch("nvd3", function(newValue, oldValue) {
+						//noinspection JSValidateTypes
+						if (newValue === oldValue) return;
+
+						updateData();
+					}, true);
+
+					// All watching mode
+					if ($scope.watching === "true") {
+						$scope.$watch("[chart, config]", function(newValue, oldValue) {
+							//noinspection JSValidateTypes
+							if (newValue === oldValue) return;
+
+							initChart();
+						}, true);
+					}
+				}
+			});
+
+			// ================================================================
+			// =                           Start Up                           =
+			// ================================================================
+			initChart();
+
+			// ================================================================
+			// =                           Clean Up                           =
+			// ================================================================
+			$scope.$on('$destroy', function() {
+				destroy();
+			});
+		},
+		template :
+		'<div>' +
+			'<h3>{{title || config.title}}</h3>' +
+			//'<svg style="min-height: 50px;"></svg>' +
+		'</div>',
+		replace: true
+	};
+});
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/8537d455/eagle-webservice/src/main/webapp/app/public/js/ctrl/damController.js
----------------------------------------------------------------------
diff --git a/eagle-webservice/src/main/webapp/app/public/js/ctrl/damController.js b/eagle-webservice/src/main/webapp/app/public/js/ctrl/damController.js
index 45c2b6f..f630fb2 100644
--- a/eagle-webservice/src/main/webapp/app/public/js/ctrl/damController.js
+++ b/eagle-webservice/src/main/webapp/app/public/js/ctrl/damController.js
@@ -108,4 +108,4 @@ damControllers.controller('summaryCtrl', function(globalContent, Site, damConten
 
 		$scope.dataReady = true;
 	});
-});
+});
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/8537d455/eagle-webservice/src/main/webapp/app/public/js/ctrl/policyController.js
----------------------------------------------------------------------
diff --git a/eagle-webservice/src/main/webapp/app/public/js/ctrl/policyController.js b/eagle-webservice/src/main/webapp/app/public/js/ctrl/policyController.js
index eff5a33..6061494 100644
--- a/eagle-webservice/src/main/webapp/app/public/js/ctrl/policyController.js
+++ b/eagle-webservice/src/main/webapp/app/public/js/ctrl/policyController.js
@@ -73,7 +73,7 @@ damControllers.controller('policyListCtrl', function(globalContent, Site, damCon
 // =============================================================
 // =                       Policy Detail                       =
 // =============================================================
-damControllers.controller('policyDetailCtrl', function(globalContent, Site, damContent, charts, $scope, $routeParams, Entities) {
+damControllers.controller('policyDetailCtrl', function(globalContent, Site, damContent, $scope, $routeParams, Entities, nvd3) {
 	'use strict';
 
 	var MAX_PAGESIZE = 10000;
@@ -83,9 +83,11 @@ damControllers.controller('policyDetailCtrl', function(globalContent, Site, damC
 	globalContent.navPath = ["Policy View", "Polict List", "Polict Detail"];
 	globalContent.lockSite = true;
 
-	charts = charts($scope);
-
 	$scope.common = common;
+	$scope.chartConfig = {
+		chart: "line",
+		xType: "time"
+	};
 
 	// Query policy
 	if($routeParams.encodedRowkey) {
@@ -121,23 +123,26 @@ damControllers.controller('policyDetailCtrl', function(globalContent, Site, damC
 		}
 
 		// Visualization
+		var _endTime = app.time.now().hour(23).minute(59).second(59).millisecond(0);
+		var _startTime = _endTime.clone().subtract(1, "month").hour(0).minute(0).second(0).millisecond(0);
 		var _cond = {
 			dataSource: policy.tags.dataSource,
 			policyId: policy.tags.policyId,
-			_duration: 1000 * 60 * 60 * 24 * 30,
+			_startTime: _startTime,
+			_endTime: _endTime
 		};
 
 		// > eagle.policy.eval.count
-		$scope.policyEvalSeries = Entities.querySeries("GenericMetricService", $.extend({_metricName: "eagle.policy.eval.count"}, _cond), "@cluster", "sum(value)", 60 * 24);
+		$scope.policyEvalSeries = nvd3.convert.eagle([Entities.querySeries("GenericMetricService", $.extend({_metricName: "eagle.policy.eval.count"}, _cond), "@cluster", "sum(value)", 60 * 24)]);
 
 		// > eagle.policy.eval.fail.count
-		$scope.policyEvalFailSeries = Entities.querySeries("GenericMetricService", $.extend({_metricName: "eagle.policy.eval.fail.count"}, _cond), "@cluster", "sum(value)", 60 * 24);
+		$scope.policyEvalFailSeries = nvd3.convert.eagle([Entities.querySeries("GenericMetricService", $.extend({_metricName: "eagle.policy.eval.fail.count"}, _cond), "@cluster", "sum(value)", 60 * 24)]);
 
 		// > eagle.alert.count
-		$scope.alertSeries = Entities.querySeries("GenericMetricService", $.extend({_metricName: "eagle.alert.count"}, _cond), "@cluster", "sum(value)", 60 * 24);
+		$scope.alertSeries = nvd3.convert.eagle([Entities.querySeries("GenericMetricService", $.extend({_metricName: "eagle.alert.count"}, _cond), "@cluster", "sum(value)", 60 * 24)]);
 
 		// > eagle.alert.fail.count
-		$scope.alertFailSeries = Entities.querySeries("GenericMetricService", $.extend({_metricName: "eagle.alert.fail.count"}, _cond), "@cluster", "sum(value)", 60 * 24);
+		$scope.alertFailSeries = nvd3.convert.eagle([Entities.querySeries("GenericMetricService", $.extend({_metricName: "eagle.alert.fail.count"}, _cond), "@cluster", "sum(value)", 60 * 24)]);
 
 		// Alert list
 		$scope.alertList = Entities.queryEntities("AlertService", {

http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/8537d455/eagle-webservice/src/main/webapp/app/public/js/ctrl/userProfileController.js
----------------------------------------------------------------------
diff --git a/eagle-webservice/src/main/webapp/app/public/js/ctrl/userProfileController.js b/eagle-webservice/src/main/webapp/app/public/js/ctrl/userProfileController.js
index 3d2e130..2d182b0 100644
--- a/eagle-webservice/src/main/webapp/app/public/js/ctrl/userProfileController.js
+++ b/eagle-webservice/src/main/webapp/app/public/js/ctrl/userProfileController.js
@@ -186,6 +186,8 @@ damControllers.controller('userProfileDetailCtrl', function(globalContent, Site,
 
 		// DE
 		if($scope.profiles.DE) {
+			console.log($scope.profiles.DE);
+
 			$scope.profiles.DE._chart = {};
 
 			$scope.profiles.DE.estimates = {};
@@ -197,27 +199,26 @@ damControllers.controller('userProfileDetailCtrl', function(globalContent, Site,
 
 			var _meanList = [];
 			var _stddevList = [];
-			var _categoryList = [];
 
 			$.each($scope.profiles.DE._content.statistics, function(i, unit) {
-				_meanList[i] = unit.mean;
-				_stddevList[i] = unit.stddev;
-
-				_categoryList[i] = unit.commandName;
+				_meanList[i] = {
+					x: unit.commandName,
+					y: unit.mean
+				};
+				_stddevList[i] = {
+					x: unit.commandName,
+					y: unit.stddev
+				};
 			});
 			$scope.profiles.DE._chart.series = [
 				{
-					name: "mean",
-					data: _meanList
-				},
-				{
-					name: "stddev",
-					data: _stddevList
+					key: "mean",
+					values: _meanList
 				},
 				{
-					type: "category",
-					data: _categoryList
-				},
+					key: "stddev",
+					values: _stddevList
+				}
 			];
 
 			// Percentage table list

http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/8537d455/eagle-webservice/src/main/webapp/grunt.json
----------------------------------------------------------------------
diff --git a/eagle-webservice/src/main/webapp/grunt.json b/eagle-webservice/src/main/webapp/grunt.json
index ca8691a..0b8ad5a 100644
--- a/eagle-webservice/src/main/webapp/grunt.json
+++ b/eagle-webservice/src/main/webapp/grunt.json
@@ -17,14 +17,8 @@
 				"node_modules/angular-route/angular-route.min.js",
 				"node_modules/angular-cookies/angular-cookies.min.js",
 				"node_modules/angular-ui-bootstrap/ui-bootstrap-tpls.min.js",
-				"node_modules/Flot/jquery.flot.js",
-				"node_modules/Flot/jquery.flot.stack.js",
-				"node_modules/Flot/jquery.flot.pie.js",
-				"node_modules/Flot/jquery.flot.time.js",
-				"node_modules/Flot/jquery.flot.crosshair.js",
-				"app/public/assets/flot/jquery.flot.tooltip.js",
-				"app/public/assets/flot/jquery.flot.legend.js",
 				"node_modules/d3/d3.min.js",
+				"node_modules/zombiej-nvd3/build/nv.d3.min.js",
 
 				"tmp/public/js/scripts.min.js"
 			],
@@ -35,6 +29,7 @@
 				"node_modules/bootstrap/dist/css/bootstrap.min.css",
 				"node_modules/zombiej-bootstrap-components/bootstrap-components/css/bootstrap-components.min.css",
 				"node_modules/font-awesome/css/font-awesome.min.css",
+				"node_modules/zombiej-nvd3/build/nv.d3.min.css",
 				"node_modules/admin-lte/dist/css/AdminLTE.min.css",
 				"node_modules/admin-lte/dist/css/skins/skin-blue.min.css",
 

http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/8537d455/eagle-webservice/src/main/webapp/package.json
----------------------------------------------------------------------
diff --git a/eagle-webservice/src/main/webapp/package.json b/eagle-webservice/src/main/webapp/package.json
index eccc368..713b93c 100644
--- a/eagle-webservice/src/main/webapp/package.json
+++ b/eagle-webservice/src/main/webapp/package.json
@@ -20,8 +20,8 @@
 		"angular-cookies"		: "1.4.7",
 		"angular-animate"		: "1.4.7",
 		"angular-ui-bootstrap"	: "0.14.3",
-		"Flot": "git+https://github.com/flot/flot.git#v0.8.3",
-		"d3"					: "3.5.9",
+		"d3"					: "~3.5.10",
+		"zombiej-nvd3"			: "~1.8.1-1",
 		"jquery-slimscroll": "1.3.6",
 		"zombiej-bootstrap-components"		: "~1.1.1"
 	},


Mime
View raw message