diff --git a/horizon/karma.conf.js b/horizon/karma.conf.js
index 9972fe5a89..c32fb35759 100644
--- a/horizon/karma.conf.js
+++ b/horizon/karma.conf.js
@@ -76,7 +76,7 @@ module.exports = function(config) {
'framework/framework.module.js',
'framework/util/util.module.js',
'framework/util/tech-debt/tech-debt.module.js',
- 'framework/widgets/charts/charts.js',
+ 'framework/widgets/charts/charts.module.js',
'framework/widgets/metadata-tree/metadata-tree.js',
'framework/widgets/modal/modal.module.js',
'framework/widgets/table/table.js',
diff --git a/horizon/static/framework/widgets/charts/chart-tooltip.directive.js b/horizon/static/framework/widgets/charts/chart-tooltip.directive.js
new file mode 100644
index 0000000000..c800e5bdcf
--- /dev/null
+++ b/horizon/static/framework/widgets/charts/chart-tooltip.directive.js
@@ -0,0 +1,67 @@
+/*
+ * (c) Copyright 2015 Hewlett-Packard Development Company, L.P.
+ *
+ * Licensed 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';
+
+ /**
+ * @ngdoc directive
+ * @name horizon.framework.widgets.charts.directive:chartTooltip
+ * @element
+ * @param {object} tooltip-data The tooltip data model and styles
+ * @description
+ * The `chartTooltip` directive renders a tooltip showing a colored
+ * icon, label, and value.
+ *
+ * Data Model and Styles:
+ * ```
+ * var tooltipData = {
+ * enabled: true,
+ * label: 'Applied',
+ * value: 1,
+ * icon: 'fa-square',
+ * iconColor: '#333333',
+ * iconClass: 'warning',
+ * style: { left: '10px', top: '10px' }
+ * };
+ * ```
+ *
+ * @restrict E
+ * @scope tooltip: '=tooltipData'
+ *
+ * @example
+ * ```
+ *
+ * ```
+ *
+ */
+ angular
+ .module('horizon.framework.widgets.charts')
+ .directive('chartTooltip', chartTooltip);
+
+ chartTooltip.$inject = ['horizon.framework.widgets.basePath'];
+
+ function chartTooltip(path) {
+ var directive = {
+ restrict: 'E',
+ scope: {
+ tooltip: '=tooltipData'
+ },
+ templateUrl: path + 'charts/chart-tooltip.html'
+ };
+
+ return directive;
+ }
+})();
diff --git a/horizon/static/framework/widgets/charts/chart-tooltip.js b/horizon/static/framework/widgets/charts/chart-tooltip.js
deleted file mode 100644
index d314ab1fa5..0000000000
--- a/horizon/static/framework/widgets/charts/chart-tooltip.js
+++ /dev/null
@@ -1,47 +0,0 @@
-(function () {
- 'use strict';
-
- angular.module('horizon.framework.widgets.charts')
-
- /**
- * @ngdoc directive
- * @name horizon.framework.widgets.charts.directive:chartTooltip
- * @element
- * @param {object} tooltip-data The tooltip data model and styles
- * @description
- * The `chartTooltip` directive renders a tooltip showing a colored
- * icon, label, and value.
- *
- * Data Model and Styles:
- * ```
- * var tooltipData = {
- * enabled: true,
- * label: 'Applied',
- * value: 1,
- * icon: 'fa-square',
- * iconColor: '#333333',
- * iconClass: 'warning',
- * style: { left: '10px', top: '10px' }
- * };
- * ```
- *
- * @restrict E
- * @scope tooltip: '=tooltipData'
- *
- * @example
- * ```
- *
- * ```
- *
- */
- .directive('chartTooltip', [ 'horizon.framework.widgets.basePath', function (path) {
- return {
- restrict: 'E',
- scope: {
- tooltip: '=tooltipData'
- },
- templateUrl: path + 'charts/chart-tooltip.html'
- };
- }]);
-
-})();
diff --git a/horizon/static/framework/widgets/charts/chart-tooltip.spec.js b/horizon/static/framework/widgets/charts/chart-tooltip.spec.js
index 081d5352c3..4f26e724f4 100644
--- a/horizon/static/framework/widgets/charts/chart-tooltip.spec.js
+++ b/horizon/static/framework/widgets/charts/chart-tooltip.spec.js
@@ -41,7 +41,6 @@
$element = angular.element(markup);
$compile($element)($scope);
$scope.$digest();
-
}));
it('compiles', function () {
@@ -77,7 +76,6 @@
it('has the correct icon', function () {
var iconSpan = $element.find('span.fa');
expect(iconSpan.hasClass('fa-square')).toBe(true);
-
});
it('has the correct icon color', function () {
@@ -89,7 +87,5 @@
expect(styleColor).toBe('#333333');
}
});
-
});
-
})();
diff --git a/horizon/static/framework/widgets/charts/charts.js b/horizon/static/framework/widgets/charts/charts.js
deleted file mode 100644
index 0c1a049dae..0000000000
--- a/horizon/static/framework/widgets/charts/charts.js
+++ /dev/null
@@ -1,114 +0,0 @@
-(function () {
- 'use strict';
-
- /**
- * @ngdoc overview
- * @name horizon.framework.widgets.charts
- * @description
- *
- * # horizon.framework.widgets.charts
- *
- * The `horizon.framework.widgets.charts` module provides directives for simple charts
- * used in Horizon, such as the pie and donut chart. Charts are
- * implemented using D3.
- *
- * Requires {@link http://d3js.org `D3`} to be installed.
- *
- * | Constants |
- * |---------------------------------------------------------------------------|
- * | {@link horizon.framework.widgets.charts.constant:donutChartSettings `donutChartSettings`} |
- * | {@link horizon.framework.widgets.charts.constant:quotaChartDefaults `quotaChartDefaults`} |
- *
- * | Directives |
- * |---------------------------------------------------------------------------|
- * | {@link horizon.framework.widgets.charts.directive:pieChart `pieChart`} |
- *
- */
- angular.module('horizon.framework.widgets.charts', [])
-
- /**
- * @ngdoc parameters
- * @name horizon.framework.widgets.charts.constant:donutChartSettings
- * @param {number} innerRadius Pie chart inner radius in pixels, default: 24
- * @param {number} outerRadius Pie chart outer radius in pixels, default: 30
- * @param {object} label with properties font-size and fill (optional)
- * @param {string} titleClass CSS class to override title,
- * default: pie-chart-title-medium
- * alternative: pie-chart-title-large
- * @param {boolean} showTitle Show title, default: true
- * @param {boolean} showLabel Show label, default: true
- * @param {boolean} showLegend Show legend default: true
- * @param {string} tooltipIcon Tooltip key icon, default: 'fa-square'
- *
- */
- .constant('horizon.framework.widgets.charts.donutChartSettings', {
- innerRadius: 24,
- outerRadius: 30,
- titleClass: 'pie-chart-title-medium',
- showTitle: true,
- showLabel: true,
- showLegend: true,
- tooltipIcon: 'fa-square'
- })
-
- /**
- * @ngdoc parameters
- * @name horizon.framework.widgets.charts.constant:pieChartSettings
- * @param {number} innerRadius Pie chart inner radius in pixels, default: 0
- * @param {number} outerRadius Pie chart outer radius in pixels, default: 30
- * @param {object} label with properties font-size and fill (optional)
- * @param {string} titleClass CSS class to override title,
- * default: pie-chart-title-medium
- * alternative: pie-chart-title-large
- * @param {boolean} showTitle Show title, default: true
- * @param {boolean} showLabel Show label, default: true
- * @param {boolean} showLegend Show legend default: true
- * @param {string} tooltipIcon Tooltip key icon, default: 'fa-square'
- *
- */
- .constant('horizon.framework.widgets.charts.pieChartSettings', {
- innerRadius: 0,
- outerRadius: 30,
- titleClass: 'pie-chart-title-medium',
- showTitle: true,
- showLabel: true,
- showLegend: true,
- tooltipIcon: 'fa-square'
- })
-
- /**
- * @ngdoc parameters
- * @name horizon.framework.widgets.charts.constant:quotaChartDefaults
- * @param {string} usageLabel label text for Usage, default: 'Current Usage'
- * @param {string} usageColorClass css class for Usage , default: 'usage'
- * @param {string} addedLabel label text for Added, default: 'Added'
- * @param {string} addedColorClass CSS class for Added , default: 'added'
- * @param {string} remainingLabel label text for Remaining, default: 'Remaining'
- * @param {string} remainingColorClass CSS class for Remaining , default: 'remaining'
- *
- */
- .constant('horizon.framework.widgets.charts.quotaChartDefaults', {
- usageLabel: gettext('Current Usage'),
- usageColorClass: 'usage',
- addedLabel: gettext('Added'),
- addedColorClass: 'added',
- remainingLabel: gettext('Remaining'),
- remainingColorClass: 'remaining'
- })
-
- /**
- * @ngdoc filter
- * @name horizon.framework.widgets.charts.filter:showKeyFilter
- * @function Filter based on 'hideKey' value of each slice
- * @returns {function} A filtered list of keys to show in legend
- *
- */
- .filter('showKeyFilter', function () {
- return function (items) {
- return items.filter(function (item) {
- return !item.hideKey;
- });
- };
- });
-
-})();
diff --git a/horizon/static/framework/widgets/charts/charts.module.js b/horizon/static/framework/widgets/charts/charts.module.js
new file mode 100644
index 0000000000..3a102ecfdd
--- /dev/null
+++ b/horizon/static/framework/widgets/charts/charts.module.js
@@ -0,0 +1,131 @@
+/*
+ * (c) Copyright 2015 Hewlett-Packard Development Company, L.P.
+ *
+ * Licensed 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';
+
+ /**
+ * @ngdoc overview
+ * @name horizon.framework.widgets.charts
+ * @description
+ *
+ * # horizon.framework.widgets.charts
+ *
+ * The `horizon.framework.widgets.charts` module provides directives for simple charts
+ * used in Horizon, such as the pie and donut chart. Charts are
+ * implemented using D3.
+ *
+ * Requires {@link http://d3js.org `D3`} to be installed.
+ *
+ * | Constants |
+ * |---------------------------------------------------------------------------|
+ * | {@link horizon.framework.widgets.charts.constant:donutChartSettings `donutChartSettings`} |
+ * | {@link horizon.framework.widgets.charts.constant:quotaChartDefaults `quotaChartDefaults`} |
+ *
+ * | Directives |
+ * |---------------------------------------------------------------------------|
+ * | {@link horizon.framework.widgets.charts.directive:pieChart `pieChart`} |
+ *
+ */
+ angular
+ .module('horizon.framework.widgets.charts', [])
+
+ /**
+ * @ngdoc parameters
+ * @name horizon.framework.widgets.charts.constant:donutChartSettings
+ * @param {number} innerRadius Pie chart inner radius in pixels, default: 24
+ * @param {number} outerRadius Pie chart outer radius in pixels, default: 30
+ * @param {object} label with properties font-size and fill (optional)
+ * @param {string} titleClass CSS class to override title,
+ * default: pie-chart-title-medium
+ * alternative: pie-chart-title-large
+ * @param {boolean} showTitle Show title, default: true
+ * @param {boolean} showLabel Show label, default: true
+ * @param {boolean} showLegend Show legend default: true
+ * @param {string} tooltipIcon Tooltip key icon, default: 'fa-square'
+ *
+ */
+ .constant('horizon.framework.widgets.charts.donutChartSettings', {
+ innerRadius: 24,
+ outerRadius: 30,
+ titleClass: 'pie-chart-title-medium',
+ showTitle: true,
+ showLabel: true,
+ showLegend: true,
+ tooltipIcon: 'fa-square'
+ })
+
+ /**
+ * @ngdoc parameters
+ * @name horizon.framework.widgets.charts.constant:pieChartSettings
+ * @param {number} innerRadius Pie chart inner radius in pixels, default: 0
+ * @param {number} outerRadius Pie chart outer radius in pixels, default: 30
+ * @param {object} label with properties font-size and fill (optional)
+ * @param {string} titleClass CSS class to override title,
+ * default: pie-chart-title-medium
+ * alternative: pie-chart-title-large
+ * @param {boolean} showTitle Show title, default: true
+ * @param {boolean} showLabel Show label, default: true
+ * @param {boolean} showLegend Show legend default: true
+ * @param {string} tooltipIcon Tooltip key icon, default: 'fa-square'
+ *
+ */
+ .constant('horizon.framework.widgets.charts.pieChartSettings', {
+ innerRadius: 0,
+ outerRadius: 30,
+ titleClass: 'pie-chart-title-medium',
+ showTitle: true,
+ showLabel: true,
+ showLegend: true,
+ tooltipIcon: 'fa-square'
+ })
+
+ /**
+ * @ngdoc parameters
+ * @name horizon.framework.widgets.charts.constant:quotaChartDefaults
+ * @param {string} usageLabel label text for Usage, default: 'Current Usage'
+ * @param {string} usageColorClass css class for Usage , default: 'usage'
+ * @param {string} addedLabel label text for Added, default: 'Added'
+ * @param {string} addedColorClass CSS class for Added , default: 'added'
+ * @param {string} remainingLabel label text for Remaining, default: 'Remaining'
+ * @param {string} remainingColorClass CSS class for Remaining , default: 'remaining'
+ *
+ */
+ .constant('horizon.framework.widgets.charts.quotaChartDefaults', {
+ usageLabel: gettext('Current Usage'),
+ usageColorClass: 'usage',
+ addedLabel: gettext('Added'),
+ addedColorClass: 'added',
+ remainingLabel: gettext('Remaining'),
+ remainingColorClass: 'remaining'
+ })
+
+ /**
+ * @ngdoc filter
+ * @name horizon.framework.widgets.charts.filter:showKeyFilter
+ * @function Filter based on 'hideKey' value of each slice
+ * @returns {function} A filtered list of keys to show in legend
+ *
+ */
+ .filter('showKeyFilter', showKeyFilter);
+
+ function showKeyFilter() {
+ return function (items) {
+ return items.filter(function (item) {
+ return !item.hideKey;
+ });
+ };
+ }
+})();
diff --git a/horizon/static/framework/widgets/charts/pie-chart.directive.js b/horizon/static/framework/widgets/charts/pie-chart.directive.js
new file mode 100644
index 0000000000..7bf838e04d
--- /dev/null
+++ b/horizon/static/framework/widgets/charts/pie-chart.directive.js
@@ -0,0 +1,232 @@
+/*
+ * (c) Copyright 2015 Hewlett-Packard Development Company, L.P.
+ *
+ * Licensed 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';
+
+ /**
+ * @ngdoc directive
+ * @name horizon.framework.widgets.charts.directive:pieChart
+ * @element
+ * @param {object} chart-data The chart data model
+ * @param {string} chart-settings The custom chart settings (JSON), optional
+ * @description
+ * The `pieChart` directive renders a pie or donut chart using D3. The title
+ * and legend is shown by default. Each slice is represented by a label, value,
+ * and color (hex value or CSS class). See below for the data model.
+ *
+ * Data Model:
+ * ```
+ * var chartData = {
+ * title: 'Total Instances',
+ * label: '25%',
+ * maxLimit: 10,
+ * overMax: false,
+ * data: [
+ * { label: quotaChartDefaults.usageLabel, value: 1, colorClass: quotaChartDefaults.usageColorClass},
+ * { label: quotaChartDefaults.addedLabel, value: 1, colorClass: quotaChartDefaults.addedColorClass },
+ * { label: quotaChartDefaults.remainingLabel, value: 1, colorClass: quotaChartDefaults.remainingColorClass }
+ * ]
+ * };
+ *
+ * title - the chart title
+ * label - the text to show in center of chart
+ * maxLimit - the max limit for current item (optional)
+ * - if a maxLimit is specified, (# Max) will get added to the chart title
+ * - otherwise (# Total) will be added to the chart title
+ * overMax - used to notify view when max is surpassed so that we can
+ * dynamically alter UI to warn the user (optional)
+ * data - the data used to render chart
+ *
+ * Donut chart settings (donutChartSettings) and pie chart settings (pieChartSettings)
+ * are conveniently defined as angular constants in order to encourage consistency.
+ * To leverage the constant values, you will need to specify them as dependencies
+ * in your controller or directive. You can also create a custom styled chart
+ * by defining a chartSettings object in your controller and passing it in as
+ * the chart-settings attribute value.
+ *
+ * var chartSettings = {
+ * innerRadius: 24,
+ * outerRadius: 30,
+ * titleClass: 'pie-chart-title-medium',
+ * showTitle: true,
+ * showLabel: true,
+ * showLegend: true,
+ * tooltipIcon: 'fa-square'
+ * };
+ * ```
+ *
+ * @restrict E
+ * @scope true
+ *
+ * @example
+ * ```
+ * Pie Chart using predefined constant:
+ *
+ *
+ * Donut Chart using predefined constant:
+ *
+ *
+ * Custom Chart using custom settings:
+ *
+ * ```
+ *
+ */
+ angular
+ .module('horizon.framework.widgets.charts')
+ .directive('pieChart', pieChart);
+
+ pieChart.$inject = [
+ 'horizon.framework.widgets.basePath',
+ 'horizon.framework.widgets.charts.donutChartSettings'
+ ];
+
+ function pieChart(path, donutChartSettings) {
+ var directive = {
+ link: link,
+ replace: true,
+ restrict: 'E',
+ scope: {
+ chartData: '=',
+ chartSettings: '='
+ },
+ templateUrl: path + 'charts/pie-chart.html'
+ };
+
+ return directive;
+
+ function link(scope, element) {
+ var settings = {};
+ // if chartSettings is defined via the attribute value, use it
+ if (angular.isObject(scope.chartSettings)) {
+ settings = scope.chartSettings;
+ } else {
+ // else default to a donut chart
+ settings = angular.extend({}, donutChartSettings, scope.chartSettings);
+ }
+ settings.diameter = settings.outerRadius * 2;
+
+ var model = {
+ settings: settings,
+ tooltipData: {
+ enabled: false,
+ icon: settings.tooltipIcon,
+ style: angular.extend({}, settings.tooltip)
+ }
+ };
+
+ var d3Elt = d3.select(element[0]);
+
+ var arc = d3.svg.arc()
+ .outerRadius(settings.outerRadius)
+ .innerRadius(settings.innerRadius);
+
+ var pie = d3.layout.pie()
+ .sort(null)
+ .value(function (d) { return d.value; });
+
+ var unwatch = scope.$watch('chartData', updateChart);
+ scope.$on('$destroy', unwatch);
+
+ scope.model = model;
+
+ function updateChart() {
+ // set labels depending on whether this is a max or total chart
+ if (angular.isDefined(scope.chartData.maxLimit)) {
+ scope.model.total = scope.chartData.maxLimit;
+ scope.model.totalLabel = gettext('Max');
+ } else {
+ scope.model.total = d3.sum(scope.chartData.data, function (d) { return d.value; });
+ scope.model.totalLabel = gettext('Total');
+ }
+ scope.model.tooltipData.enabled = false;
+
+ // Generate or update slices
+ var chart = d3Elt.select('.slices')
+ .selectAll('path.slice')
+ .data(pie(scope.chartData.data));
+
+ chart.enter().append('path')
+ .attr('class', 'slice')
+ .attr('d', arc);
+
+ // Set the color or CSS class for the fill
+ chart.each(function (d) {
+ var slice = d3.select(this);
+ if (d.data.color) {
+ slice.style('fill', d.data.color);
+ } else if (d.data.colorClass) {
+ slice.classed(d.data.colorClass, true);
+ }
+ });
+
+ chart.on('mouseenter', function (d) { showTooltip(d, this); })
+ .on('mouseleave', clearTooltip);
+
+ // Animate the slice rendering
+ chart.transition()
+ .duration(500)
+ .attrTween('d', function animate(d) {
+ this.lastAngle = this.lastAngle || { startAngle: 0, endAngle: 0 };
+ var interpolate = d3.interpolate(this.lastAngle, d);
+ this.lastAngle = interpolate(0);
+
+ return function (t) {
+ return arc(interpolate(t));
+ };
+ });
+
+ chart.exit().remove();
+ }
+
+ function showTooltip(d, elt) {
+ scope.$apply(function () {
+ var chartElt = element[0];
+ var eltHeight = chartElt.getBoundingClientRect().height;
+ var titleHeight = chartElt.querySelector('div.pie-chart-title')
+ .getBoundingClientRect()
+ .height;
+
+ var point = d3.mouse(elt);
+ var outerRadius = scope.model.settings.outerRadius;
+ var x = point[0] + outerRadius;
+ var y = eltHeight - point[1] - outerRadius - titleHeight;
+
+ var newTooltipData = {
+ label: d.data.label,
+ value: d.data.value,
+ enabled: true,
+ iconColor: d.data.color,
+ iconClass: d.data.colorClass,
+ style: {
+ left: x + 'px',
+ bottom: y + 'px'
+ }
+ };
+ angular.extend(scope.model.tooltipData, newTooltipData);
+ });
+ }
+
+ function clearTooltip() {
+ scope.$apply(function () {
+ scope.model.tooltipData.enabled = false;
+ });
+ }
+ }
+ }
+})();
diff --git a/horizon/static/framework/widgets/charts/pie-chart.js b/horizon/static/framework/widgets/charts/pie-chart.js
deleted file mode 100644
index 42a7760dfe..0000000000
--- a/horizon/static/framework/widgets/charts/pie-chart.js
+++ /dev/null
@@ -1,206 +0,0 @@
-(function () {
- 'use strict';
-
- angular.module('horizon.framework.widgets.charts')
-
- /**
- * @ngdoc directive
- * @name horizon.framework.widgets.charts.directive:pieChart
- * @element
- * @param {object} chart-data The chart data model
- * @param {string} chart-settings The custom chart settings (JSON), optional
- * @description
- * The `pieChart` directive renders a pie or donut chart using D3. The title
- * and legend is shown by default. Each slice is represented by a label, value,
- * and color (hex value or CSS class). See below for the data model.
- *
- * Data Model:
- * ```
- * var chartData = {
- * title: 'Total Instances',
- * label: '25%',
- * maxLimit: 10,
- * overMax: false,
- * data: [
- * { label: quotaChartDefaults.usageLabel, value: 1, colorClass: quotaChartDefaults.usageColorClass},
- * { label: quotaChartDefaults.addedLabel, value: 1, colorClass: quotaChartDefaults.addedColorClass },
- * { label: quotaChartDefaults.remainingLabel, value: 1, colorClass: quotaChartDefaults.remainingColorClass }
- * ]
- * };
- *
- * title - the chart title
- * label - the text to show in center of chart
- * maxLimit - the max limit for current item (optional)
- * - if a maxLimit is specified, (# Max) will get added to the chart title
- * - otherwise (# Total) will be added to the chart title
- * overMax - used to notify view when max is surpassed so that we can
- * dynamically alter UI to warn the user (optional)
- * data - the data used to render chart
- *
- * Donut chart settings (donutChartSettings) and pie chart settings (pieChartSettings)
- * are conveniently defined as angular constants in order to encourage consistency.
- * To leverage the constant values, you will need to specify them as dependencies
- * in your controller or directive. You can also create a custom styled chart
- * by defining a chartSettings object in your controller and passing it in as
- * the chart-settings attribute value.
- *
- * var chartSettings = {
- * innerRadius: 24,
- * outerRadius: 30,
- * titleClass: 'pie-chart-title-medium',
- * showTitle: true,
- * showLabel: true,
- * showLegend: true,
- * tooltipIcon: 'fa-square'
- * };
- * ```
- *
- * @restrict E
- * @scope true
- *
- * @example
- * ```
- * Pie Chart using predefined constant:
- *
- *
- * Donut Chart using predefined constant:
- *
- *
- * Custom Chart using custom settings:
- *
- * ```
- *
- */
- .directive('pieChart', [
- 'horizon.framework.widgets.basePath',
- 'horizon.framework.widgets.charts.donutChartSettings',
- function (path, donutChartSettings) {
- return {
- restrict: 'E',
- scope: {
- chartData: '=',
- chartSettings: '='
- },
- replace: true,
- templateUrl: path + 'charts/pie-chart.html',
- link: function (scope, element) {
- var settings = {};
- // if chartSettings is defined via the attribute value, use it
- if (angular.isObject(scope.chartSettings)) {
- settings = scope.chartSettings;
- } else {
- // else default to a donut chart
- settings = angular.extend({}, donutChartSettings, scope.chartSettings);
- }
- settings.diameter = settings.outerRadius * 2;
-
- var model = {
- settings: settings,
- tooltipData: {
- enabled: false,
- icon: settings.tooltipIcon,
- style: angular.extend({}, settings.tooltip)
- }
- };
-
- var d3Elt = d3.select(element[0]);
-
- var arc = d3.svg.arc()
- .outerRadius(settings.outerRadius)
- .innerRadius(settings.innerRadius);
-
- var pie = d3.layout.pie()
- .sort(null)
- .value(function (d) { return d.value; });
-
- var unwatch = scope.$watch('chartData', updateChart);
- scope.$on('$destroy', unwatch);
-
- scope.model = model;
-
- function updateChart() {
- // set labels depending on whether this is a max or total chart
- if (angular.isDefined(scope.chartData.maxLimit)) {
- scope.model.total = scope.chartData.maxLimit;
- scope.model.totalLabel = gettext('Max');
- } else {
- scope.model.total = d3.sum(scope.chartData.data, function (d) { return d.value; });
- scope.model.totalLabel = gettext('Total');
- }
- scope.model.tooltipData.enabled = false;
-
- // Generate or update slices
- var chart = d3Elt.select('.slices')
- .selectAll('path.slice')
- .data(pie(scope.chartData.data));
-
- chart.enter().append('path')
- .attr('class', 'slice')
- .attr('d', arc);
-
- // Set the color or CSS class for the fill
- chart.each(function (d) {
- var slice = d3.select(this);
- if (d.data.color) {
- slice.style('fill', d.data.color);
- } else if (d.data.colorClass) {
- slice.classed(d.data.colorClass, true);
- }
- });
-
- chart.on('mouseenter', function (d) { showTooltip(d, this); })
- .on('mouseleave', clearTooltip);
-
- // Animate the slice rendering
- chart.transition()
- .duration(500)
- .attrTween('d', function animate(d) {
- this.lastAngle = this.lastAngle || { startAngle: 0, endAngle: 0 };
- var interpolate = d3.interpolate(this.lastAngle, d);
- this.lastAngle = interpolate(0);
-
- return function (t) {
- return arc(interpolate(t));
- };
- });
-
- chart.exit().remove();
- }
-
- function showTooltip(d, elt) {
- scope.$apply(function () {
- var chartElt = element[0];
- var eltHeight = chartElt.getBoundingClientRect().height;
- var titleHeight = chartElt.querySelector('div.pie-chart-title')
- .getBoundingClientRect()
- .height;
-
- var point = d3.mouse(elt);
- var outerRadius = scope.model.settings.outerRadius;
- var x = point[0] + outerRadius;
- var y = eltHeight - point[1] - outerRadius - titleHeight;
-
- scope.model.tooltipData.label = d.data.label;
- scope.model.tooltipData.value = d.data.value;
- scope.model.tooltipData.enabled = true;
- scope.model.tooltipData.iconColor = d.data.color;
- scope.model.tooltipData.iconClass = d.data.colorClass;
- scope.model.tooltipData.style.left = x + 'px';
- scope.model.tooltipData.style.bottom = y + 'px';
- });
- }
-
- function clearTooltip() {
- scope.$apply(function () {
- scope.model.tooltipData.enabled = false;
- });
- }
- }
- };
- }
- ]);
-
-})();
diff --git a/horizon/static/framework/widgets/charts/pie-chart.spec.js b/horizon/static/framework/widgets/charts/pie-chart.spec.js
index ce685d3ade..eb28f921ca 100644
--- a/horizon/static/framework/widgets/charts/pie-chart.spec.js
+++ b/horizon/static/framework/widgets/charts/pie-chart.spec.js
@@ -1,3 +1,18 @@
+/*
+ * (c) Copyright 2015 Hewlett-Packard Development Company, L.P.
+ *
+ * Licensed 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';
diff --git a/horizon/test/jasmine/jasmine_tests.py b/horizon/test/jasmine/jasmine_tests.py
index 176d4a7995..cc8725be15 100644
--- a/horizon/test/jasmine/jasmine_tests.py
+++ b/horizon/test/jasmine/jasmine_tests.py
@@ -52,9 +52,9 @@ class ServicesTests(test.JasmineTests):
'framework/widgets/widgets.module.js',
'framework/widgets/action-list/action-list.js',
'framework/widgets/action-list/button-tooltip.js',
- 'framework/widgets/charts/charts.js',
- 'framework/widgets/charts/chart-tooltip.js',
- 'framework/widgets/charts/pie-chart.js',
+ 'framework/widgets/charts/charts.module.js',
+ 'framework/widgets/charts/chart-tooltip.directive.js',
+ 'framework/widgets/charts/pie-chart.directive.js',
'framework/widgets/help-panel/help-panel.js',
'framework/widgets/magic-search/magic-search.js',
'framework/widgets/metadata-tree/metadata-tree.js',
diff --git a/openstack_dashboard/templates/horizon/_scripts.html b/openstack_dashboard/templates/horizon/_scripts.html
index fe63942731..bc32b5d2ce 100644
--- a/openstack_dashboard/templates/horizon/_scripts.html
+++ b/openstack_dashboard/templates/horizon/_scripts.html
@@ -60,9 +60,9 @@
-
-
-
+
+
+