From fb4ffebe6444bce18a9a76054a750bcb5fdd20b4 Mon Sep 17 00:00:00 2001
From: David Taylor
Date: Thu, 14 Jun 2018 16:37:29 -0400
Subject: [PATCH 1/2] fix(pfVerticalNavigation): Added mobileOnly property to
nav. item objects; when 'true' items only display in mobile mode.
---
.../examples/vertical-navigation-basic.js | 20 ++++++--
.../examples/vertical-navigation-router.js | 49 ++++++++++++++++++-
src/navigation/vertical-navigation.html | 3 +-
3 files changed, 66 insertions(+), 6 deletions(-)
diff --git a/src/navigation/examples/vertical-navigation-basic.js b/src/navigation/examples/vertical-navigation-basic.js
index 7eb833d3b..b3d8e9fc3 100644
--- a/src/navigation/examples/vertical-navigation-basic.js
+++ b/src/navigation/examples/vertical-navigation-basic.js
@@ -35,6 +35,8 @@
*
.tooltip - (string) Tooltip to display for the badge
*
.badgeClass: - (string) Additional class(es) to add to the badge container
*
+ *
.mobileOnly - (boolean) When set to 'true', menu item will only be displayed when browser is in mobile mode (<768px).
+ * When ignoreMobile flag set to 'true', mobileOnly items are not displayed.
*
* @param {function} navigateCallback function(item) Callback method invoked on a navigation item click (one with no submenus)
* @param {function} itemClickCallback function(item) Callback method invoked on an item click
@@ -76,7 +78,7 @@
.uiSref - (string) Optional Angular UI Router state name. If specified, href must be not defined, and vice versa.
*
.uiSrefOptions - (object) Optional object to be passed to Angular UI Router $state.go() function
+ *
.mobileOnly - (boolean) When set to 'true', menu item will only be displayed when browser is in mobile mode (<768px).
+ * When ignoreMobile flag set to 'true', mobileOnly items are not displayed.
*
* @param {function} navigateCallback function(item) Callback method invoked on a navigation item click (one with no submenus)
* @param {function} itemClickCallback function(item) Callback method invoked on an item click
@@ -67,7 +69,7 @@
.title - the main title of the aggregate status card
+ *
.count - the number count of the main statuses
+ *
.href - the href to navigate to if one clicks on the title or count
+ *
.iconClass - an icon to display to the left of the count
+ *
.iconImage - an image to display to the left of the count
+ *
.notifications - an array of status icons & counts
+ *
+ *
.iconClass - an icon to display to the right of the notification count
+ *
.iconImage - an image to display to the left of the notification count
+ *
.count - the number count of the notification status
+ *
.href - href to navigate to if one clicks on the notification status icon or count
+ *
+ *
+ * When layout='mini', only one notification can be specified:
+ *
+ *
...
+ *
.notification - an object of containing a single notification icon & count
+ *
+ *
.iconClass - an icon to display to the right of the notification count
+ *
.iconImage - an image to display to the left of the notification count
+ *
.count - the number count of the notification status
+ *
.href - href to navigate to if one clicks on the notification status icon or count
+ *
+ *
+ * @param {boolean=} show-top-border Show/hide the top border, true shows top border, false (default) hides top border
+ * @param {boolean=} showSpinner Show/Hide the spinner for loading state. True shows the spinner, false (default) hides the spinner
+ * @param {string=} spinnerText Text for the card spinner
+ * @param {string=} spinnerCardHeight Height to set for the card when data is loading and spinner is shown
+ * @param {string=} layout Various alternative layouts the aggregate status card may have:
+ *
+ *
'mini' displays a mini aggregate status card. Note: when using 'mini' layout, only one notification can be specified in the status object
+ *
'tall' displays a tall aggregate status card. This equals the depreciated 'alt-layout' param.
+ *
+ * @deprecated {boolean=} alt-layout Display the aggregate status card in a 'alternate tall' layout. false (default) displays normal layout, true displays tall layout
+ *
+ * @description
+ * Component for easily displaying status information
+ *
+ * @example
+
+
+
+
.iconClass - (optional) the icon to show on the bottom left of the footer panel
+ *
.text - (optional) the text to show on the bottom left of the footer panel, to the right of the icon
+ *
.href - (optional) the href link to navigate to when the footer href is clicked
+ *
.callBackFn - (optional) user defined function to call when the footer href is clicked
+ *
+ * *Note: If a href link and a callBackFn are specified, the href link will be called
+ * @param {object=} filter filter configuration properties:
+ *
.iconClass - (optional) the icon to show on the bottom left of the footer panel
+ *
.text - (optional) the text to show on the bottom left of the footer panel, to the right of the icon
+ *
.href - (optional) the href link to navigate to when the footer href is clicked
+ *
.callBackFn - (optional) user defined function to call when the footer href is clicked
+ *
+ * *Note: If a href link and a callBackFn are specified, the href link will be called
+ * @param {object=} filter filter configuration properties:
+ *
.defaultFilter - integer, 0 based index into the filters array
+ *
.callBackFn - user defined function to call when a filter is selected
+ *
.position - (optional) If not specified, or set to 'footer'; the position of the filter dropdown will appear in the
+ * card footer. If set to 'header', the filter dropdown will appear in the card header.
+ *
+ * @description
+ * Component for easily displaying a card with html content
+ *
+ * @example
+
+
+
+
+
+
+ angular.module( 'demo', ['patternfly.charts', 'patternfly.card'] ).controller( 'ChartCtrl', function( $scope, $timeout ) {
+
+ $scope.dataLoading = true;
+
+ $timeout(function () {
+ $scope.dataLoading = false;
+ }, 3000 );
+
+ $scope.footerConfig = {
+ 'iconClass' : 'fa fa-flag',
+ 'text' : 'View All Events',
+ 'callBackFn': function () {
+ alert("Footer Callback Fn Called");
+ }
+ };
+
+ $scope.filterConfigHeader = {
+ 'filters' : [{label:'Last 30 Days', value:'30'},
+ {label:'Last 15 Days', value:'15'},
+ {label:'Today', value:'today'}],
+ 'callBackFn': function (f) {
+ alert("Header Filter Callback Fn Called for '" + f.label + "' value = " + f.value);
+ },
+ 'position' : 'header'
+ };
+
+ $scope.filterConfig = {
+ 'filters' : [{label:'Last 30 Days', value:'30'},
+ {label:'Last 15 Days', value:'15'},
+ {label:'Today', value:'today'}],
+ 'callBackFn': function (f) {
+ alert("Filter Callback Fn Called for '" + f.label + "' value = " + f.value);
+ },
+ 'defaultFilter' : '1'
+ };
+ });
+
+
+ */
+;/**
+ * @ngdoc directive
+ * @name patternfly.card.component:pfCard - Trends
+ * @restrict E
+ *
+ * @param {string} headTitle Title for the card
+ * @param {string=} subTitle Sub-Title for the card
+ * @param {string=} spinnerText Text for the card spinner
+ * @param {string=} spinnerCardHeight Height to set for the card when data is loading and spinner is shown
+ * @param {boolean=} showTopBorder Show/Hide the blue top border. True shows top border, false (default) hides top border
+ * @param {boolean=} showSpinner Show/Hide the spinner for loading state. True shows the spinner, false (default) hides the spinner
+ * @param {boolean=} showTitlesSeparator Show/Hide the grey line between the title and sub-title.
+ * True (default) shows the line, false hides the line
+ * @param {object=} footer footer configuration properties:
+ *
+ *
.iconClass - (optional) the icon to show on the bottom left of the footer panel
+ *
.text - (optional) the text to show on the bottom left of the footer panel, to the right of the icon
+ *
.href - (optional) the href link to navigate to when the footer href is clicked
+ *
.callBackFn - (optional) user defined function to call when the footer href is clicked
+ *
+ * *Note: If a href link and a callBackFn are specified, the href link will be called
+ * @param {object=} filter filter configuration properties:
+ *
.title - the main title of the info status card
+ *
.href - the href to navigate to if one clicks on the title or count
+ *
.iconClass - an icon to display to the left of the count
+ *
.iconImage - an image to display to the left of Infrastructure
+ *
.info - an array of strings to display, each element in the array is on a new line, accepts HTML content
+ *
+ * @param {boolean=} show-top-border Show/hide the top border, true shows top border, false (default) hides top border
+ * @param {boolean} htmlContent Flag to allow HTML content within the info options
+ * @param {boolean=} showSpinner Show/Hide the spinner for loading state. True shows the spinner, false (default) hides the spinner
+ * @param {string=} spinnerText Text for the card spinner
+ * @param {string=} spinnerCardHeight Height to set for the card when data is loading and spinner is shown
+ *
+ * @description
+ * Component for easily displaying textual information
+ *
+ * @example
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ angular.module( 'patternfly.card' ).controller( 'CardDemoCtrl', function( $scope, $window, $timeout ) {
+ var imagePath = $window.IMAGE_PATH || "img";
+
+ $scope.dataLoading = true;
+
+ $scope.infoStatus = {
+ "title":"TinyCore-local",
+ "href":"#",
+ "iconClass": "fa fa-shield",
+ "info":[
+ "VM Name: aapdemo002",
+ "Host Name: localhost.localdomian",
+ "IP Address: 10.9.62.100",
+ "Power status: on"
+ ]
+ };
+
+ $scope.infoStatus2 = {
+ "title":"TinyCore-local",
+ "iconClass": "fa fa-shield"
+ };
+
+ $scope.infoStatusTitless = {
+ "iconImage": imagePath + "/OpenShift-logo.svg",
+ "info":[
+ "Infastructure: VMware",
+ "Vmware: 1 CPU (1 socket x 1 core), 1024 MB",
+ "12 Snapshots",
+ "Drift History: 1"
+ ]
+ };
+
+ $scope.infoStatusAlt = {};
+
+ $timeout(function () {
+ $scope.dataLoading = false;
+
+ $scope.infoStatus2 = {
+ "title":"TinyCore-local",
+ "href":"#",
+ "iconClass": "fa fa-shield",
+ "info":[
+ "VM Name: aapdemo002",
+ "Host Name: localhost.localdomian",
+ "IP Address: 10.9.62.100",
+ "Power status: on"
+ ]
+ };
+
+ $scope.infoStatusAlt = {
+ "title":"Favorite Things",
+ "iconClass":"fa fa-heart",
+ "info":[
+ "",
+ "",
+ "Tacos"
+ ]
+ };
+ }, 6000 );
+ });
+
+
+
+ */
+
+angular.module( 'patternfly.card' ).component('pfInfoStatusCard', {
+ bindings: {
+ status: '=',
+ showTopBorder: '@?',
+ showSpinner: '',
+ spinnerText: '@?',
+ spinnerCardHeight: '@?',
+ htmlContent: '@?'
+ },
+ templateUrl: 'card/info-status/info-status-card.html',
+ controller: ["$sce", function ($sce) {
+ 'use strict';
+ var ctrl = this;
+ ctrl.$onInit = function () {
+ ctrl.shouldShowTopBorder = (ctrl.showTopBorder === 'true');
+ ctrl.shouldShowHtmlContent = (ctrl.htmlContent === 'true');
+ ctrl.showSpinner = ctrl.showSpinner === true;
+ ctrl.trustAsHtml = function (html) {
+ return $sce.trustAsHtml(html);
+ };
+
+ if (ctrl.spinnerCardHeight) {
+ ctrl.spinnerHeight = {'height': ctrl.spinnerCardHeight};
+ }
+ };
+ }]
+});
+;(function () {
+ 'use strict';
+
+ var patternflyDefaults = patternfly.c3ChartDefaults();
+
+ angular.module('patternfly.charts').constant('c3ChartDefaults', {
+ getDefaultColors: patternflyDefaults.getDefaultColors,
+ getDefaultDonut: patternflyDefaults.getDefaultDonut,
+ getDefaultDonutSize: patternflyDefaults.getDefaultDonutSize,
+ getDefaultDonutColor: patternflyDefaults.getDefaultDonutColors,
+ getDefaultDonutLegend: patternflyDefaults.getDefaultDonutLegend,
+ getDefaultDonutConfig: patternflyDefaults.getDefaultDonutConfig,
+ getDefaultSparklineArea: patternflyDefaults.getDefaultSparklineArea,
+ getDefaultSparklineSize: patternflyDefaults.getDefaultSparklineSize,
+ getDefaultSparklineAxis: patternflyDefaults.getDefaultSparklineAxis,
+ getDefaultSparklineColor: patternflyDefaults.getDefaultColors,
+ getDefaultSparklineLegend: patternflyDefaults.getDefaultSparklineLegend,
+ getDefaultSparklinePoint: patternflyDefaults.getDefaultSparklinePoint,
+ getDefaultSparklineTooltip: patternflyDefaults.getDefaultSparklineTooltip,
+ getDefaultSparklineConfig: patternflyDefaults.getDefaultSparklineConfig,
+ getDefaultLineConfig: patternflyDefaults.getDefaultLineConfig
+ });
+})();
+;/**
+ * @ngdoc directive
+ * @name patternfly.charts.component:pfC3Chart
+ * @restrict E
+ *
+ * @description
+ * Component for wrapping c3 library
+ *
+ * Note: The 'patternfly.charts' module is not a dependency in the default angular 'patternfly' module.
+ * In order to use patternfly charts you must add 'patternfly.charts' as a dependency in your application.
+ *
+ *
+ * @param {string} id the ID of the container that the chart should bind to
+ * @param {expression} config the c3 configuration options for the chart
+ * @param {function (chart))=} getChartCallback the callback user function to be called once the chart is generated, containing the c3 chart object
+ * @example
+
+
+
+
+
+
+
+
+
+
+
+ angular.module( 'patternfly.charts' ).controller( 'ChartCtrl', function( $scope ) {
+ $scope.used = 950;
+ $scope.total = 1000;
+ $scope.available = $scope.total - $scope.used;
+
+ $scope.chartConfig = patternfly.c3ChartDefaults().getDefaultDonutConfig('MHz Used');
+ $scope.chartConfig.data = {
+ type: "donut",
+ columns: [
+ ["Used", $scope.used],
+ ["Available", $scope.total - $scope.used]
+ ],
+ groups: [
+ ["used", "available"]
+ ],
+ order: null
+ };
+
+ $scope.getChart = function (chart) {
+ $scope.chart = chart;
+ };
+
+ $scope.focusUsed = function () {
+ $scope.chart.focus("Used");
+ };
+
+ $scope.updateAvailable = function (val) {
+ $scope.available = $scope.total - $scope.used;
+ };
+
+ $scope.submitform = function (val) {
+ console.log("submitform");
+ $scope.used = val;
+ $scope.updateAvailable();
+ $scope.chartConfig.data.columns = [["Used",$scope.used],["Available",$scope.available]];
+ };
+ });
+
+
+ */
+(function () {
+ 'use strict';
+
+ angular.module('patternfly.charts').component('pfC3Chart', {
+ bindings: {
+ config: '<',
+ getChartCallback: '<'
+ },
+ template: '',
+ controller: ["$timeout", "$attrs", function ($timeout, $attrs) {
+ var ctrl = this, prevConfig;
+
+ // store the chart object
+ var chart;
+ ctrl.generateChart = function () {
+ var chartData;
+
+ // Need to deep watch changes in chart config
+ prevConfig = angular.copy(ctrl.config);
+
+ $timeout(function () {
+ chartData = ctrl.config;
+ if (chartData) {
+ chartData.bindto = '#' + $attrs.id;
+ // only re-generate donut pct chart if it has a threshold object
+ // because it's colors will change based on data and thresholds
+ if (!chart || ($attrs.id.indexOf('donutPctChart') !== -1 && chartData.thresholds)) {
+ chart = c3.generate(chartData);
+ } else {
+ //if chart is already created, then we only need to re-load data
+ chart.load(ctrl.config.data);
+ }
+ if (ctrl.getChartCallback) {
+ ctrl.getChartCallback(chart);
+ }
+ prevConfig = angular.copy(ctrl.config);
+ }
+ });
+ };
+
+ ctrl.$doCheck = function () {
+ // do a deep compare on config
+ if (!angular.equals(ctrl.config, prevConfig)) {
+ ctrl.generateChart();
+ }
+ };
+ }]
+ });
+}());
+;angular.module('patternfly.charts').component('pfDonutChart', {
+ bindings: {
+ config: '<',
+ data: '<',
+ chartHeight: ''
+ },
+ templateUrl: 'charts/donut/donut-chart.html',
+ controller: ["pfUtils", "$element", "$timeout", "$log", function (pfUtils, $element, $timeout, $log) {
+ 'use strict';
+ var ctrl = this, prevData;
+
+ ctrl.$onInit = function () {
+ ctrl.donutChartId = 'donutChart';
+ if (ctrl.config.chartId) {
+ ctrl.donutChartId = ctrl.config.chartId + ctrl.donutChartId;
+ }
+
+ ctrl.updateAll();
+ };
+
+ ctrl.getDonutData = function () {
+ return {
+ type: 'donut',
+ columns: ctrl.data,
+ order: null,
+ colors: ctrl.config.colors
+ };
+ };
+
+ ctrl.updateAll = function () {
+ // Need to deep watch changes in chart data
+ prevData = angular.copy(ctrl.data);
+
+ ctrl.config = pfUtils.merge(patternfly.c3ChartDefaults().getDefaultDonutConfig(), ctrl.config);
+ ctrl.config.tooltip = { contents: patternfly.pfDonutTooltipContents };
+ ctrl.config.data = ctrl.getDonutData();
+ ctrl.config.data.onclick = ctrl.config.onClickFn;
+
+ };
+
+ ctrl.getTotal = function () {
+ var total = 0;
+ angular.forEach(ctrl.data, function (value) {
+ angular.forEach(value, function (value) {
+ if (!isNaN(value)) {
+ total += Number(value);
+ }
+ });
+ });
+ return total;
+ };
+
+ ctrl.getCenterLabelText = function () {
+ var centerLabelText;
+
+ // default
+ centerLabelText = { bigText: ctrl.getTotal(),
+ smText: ctrl.config.donut.title};
+
+ if (ctrl.config.centerLabelFn) {
+ centerLabelText.bigText = ctrl.config.centerLabelFn();
+ centerLabelText.smText = '';
+ }
+
+ return centerLabelText;
+ };
+
+ ctrl.setupDonutChartTitle = function () {
+ var donutChartTitle, centerLabelText;
+
+ if (angular.isUndefined(ctrl.chart)) {
+ return;
+ }
+
+ donutChartTitle = d3.select(ctrl.chart.element).select('text.c3-chart-arcs-title');
+ if (!donutChartTitle) {
+ return;
+ }
+
+ centerLabelText = ctrl.getCenterLabelText();
+
+ // Remove any existing title.
+ donutChartTitle.text('');
+ if (centerLabelText.bigText && !centerLabelText.smText) {
+ donutChartTitle.text(centerLabelText.bigText);
+ } else {
+ donutChartTitle.insert('tspan').text(centerLabelText.bigText).classed('donut-title-big-pf', true).attr('dy', 0).attr('x', 0);
+ donutChartTitle.insert('tspan').text(centerLabelText.smText).classed('donut-title-small-pf', true).attr('dy', 20).attr('x', 0);
+ }
+ };
+
+ ctrl.setChart = function (chart) {
+ ctrl.chart = chart;
+ ctrl.setupDonutChartTitle();
+ };
+
+ ctrl.$onChanges = function (changesObj) {
+ if (changesObj.config || changesObj.data) {
+ ctrl.updateAll();
+ }
+ if (changesObj.chartHeight) {
+ ctrl.config.size.height = changesObj.chartHeight.currentValue;
+ }
+ };
+
+ ctrl.$doCheck = function () {
+ // do a deep compare on data
+ if (!angular.equals(ctrl.data, prevData)) {
+ ctrl.updateAll();
+ }
+ };
+ }]
+});
+;angular.module('patternfly.charts').component('pfDonutPctChart', {
+ bindings: {
+ config: '<',
+ data: '<',
+ tooltip: '<',
+ chartHeight: '',
+ centerLabel: '',
+ onThresholdChange: '&'
+ },
+ templateUrl: 'charts/donut/donut-pct-chart.html',
+ controller: ["pfUtils", "$scope", function (pfUtils, $scope) {
+ 'use strict';
+ var ctrl = this, prevData;
+ ctrl.$id = $scope.$id;
+
+ ctrl.$onInit = function () {
+ ctrl.donutChartId = 'donutPctChart' + ctrl.$id;
+
+ if (ctrl.config.chartId) {
+ ctrl.donutChartId = ctrl.config.chartId + ctrl.donutChartId;
+ }
+
+ ctrl.updateAll();
+ };
+
+ ctrl.updateAvailable = function () {
+ ctrl.data.available = ctrl.data.total - ctrl.data.used;
+ };
+
+ ctrl.updatePercentage = function () {
+ ctrl.data.percent = Math.round(ctrl.data.used / ctrl.data.total * 100.0);
+ };
+
+ ctrl.getStatusColor = function (used, thresholds) {
+ var threshold = "none";
+ var color = pfUtils.colorPalette.blue;
+
+ if (thresholds) {
+ threshold = "ok";
+ color = pfUtils.colorPalette.green;
+ if (used >= thresholds.error) {
+ threshold = "error";
+ color = pfUtils.colorPalette.red;
+ } else if (used >= thresholds.warning) {
+ threshold = "warning";
+ color = pfUtils.colorPalette.orange;
+ }
+ }
+
+ if (!ctrl.threshold || ctrl.threshold !== threshold) {
+ ctrl.threshold = threshold;
+ ctrl.onThresholdChange({ threshold: ctrl.threshold });
+ }
+
+ return color;
+ };
+
+ ctrl.statusDonutColor = function () {
+ var color, percentUsed;
+
+ color = { pattern: [] };
+ percentUsed = ctrl.data.used / ctrl.data.total * 100.0;
+ color.pattern[0] = ctrl.getStatusColor(percentUsed, ctrl.config.thresholds);
+ color.pattern[1] = pfUtils.colorPalette.black300;
+ return color;
+ };
+
+ ctrl.donutTooltip = function () {
+ return {
+ contents: function (d) {
+ // Default to percent format
+ var tooltipContent =
+ '' +
+ Math.round(d[0].ratio * 100) + '% ' + d[0].name +
+ '';
+ if (ctrl.config.tooltipFn) {
+ tooltipContent =
+ '' +
+ ctrl.config.tooltipFn(d) +
+ '';
+ } else if (ctrl.tooltip === "amount") {
+ tooltipContent =
+ '' +
+ d[0].value + ' ' + ctrl.config.units + ' ' + d[0].name +
+ '';
+ } else if (ctrl.tooltip === "both") {
+ tooltipContent =
+ '
';
+ }
+ return tooltipContent;
+ }
+ };
+ };
+
+ ctrl.getDonutData = function () {
+ return {
+ columns: [
+ ['Used', ctrl.data.used],
+ ['Available', ctrl.data.available]
+ ],
+ type: 'donut',
+ donut: {
+ label: {
+ show: false
+ }
+ },
+ groups: [
+ ['used', 'available']
+ ],
+ order: null
+ };
+ };
+
+ ctrl.getCenterLabelText = function () {
+ var centerLabelText;
+
+ // default to 'used' info.
+ centerLabelText = { bigText: ctrl.data.used,
+ smText: ctrl.config.units + ' Used' };
+
+ if (ctrl.config.centerLabelFn) {
+ centerLabelText.bigText = ctrl.config.centerLabelFn();
+ centerLabelText.smText = '';
+ } else if (ctrl.centerLabel === 'none') {
+ centerLabelText.bigText = '';
+ centerLabelText.smText = '';
+ } else if (ctrl.centerLabel === 'available') {
+ centerLabelText.bigText = ctrl.data.available;
+ centerLabelText.smText = ctrl.config.units + ' Available';
+ } else if (ctrl.centerLabel === 'percent') {
+ centerLabelText.bigText = Math.round(ctrl.data.used / ctrl.data.total * 100.0) + '%';
+ centerLabelText.smText = 'of ' + ctrl.data.total + ' ' + ctrl.config.units;
+ }
+
+ return centerLabelText;
+ };
+
+ ctrl.updateAll = function () {
+ // Need to deep watch changes in chart data
+ prevData = angular.copy(ctrl.data);
+
+ ctrl.config = pfUtils.merge(patternfly.c3ChartDefaults().getDefaultDonutConfig(), ctrl.config);
+ ctrl.updateAvailable();
+ ctrl.updatePercentage();
+ ctrl.config.data = pfUtils.merge(ctrl.config.data, ctrl.getDonutData());
+ ctrl.config.color = ctrl.statusDonutColor(ctrl);
+ ctrl.config.tooltip = ctrl.donutTooltip();
+ ctrl.config.data.onclick = ctrl.config.onClickFn;
+ };
+
+ ctrl.setupDonutChartTitle = function () {
+ var donutChartTitle, centerLabelText;
+
+ if (angular.isUndefined(ctrl.chart)) {
+ return;
+ }
+
+ donutChartTitle = d3.select(ctrl.chart.element).select('text.c3-chart-arcs-title');
+ if (!donutChartTitle) {
+ return;
+ }
+
+ centerLabelText = ctrl.getCenterLabelText();
+
+ // Remove any existing title.
+ donutChartTitle.selectAll('*').remove();
+ if (centerLabelText.bigText && !centerLabelText.smText) {
+ donutChartTitle.text(centerLabelText.bigText);
+ } else {
+ donutChartTitle.insert('tspan').text(centerLabelText.bigText).classed('donut-title-big-pf', true).attr('dy', 0).attr('x', 0);
+ donutChartTitle.insert('tspan').text(centerLabelText.smText).classed('donut-title-small-pf', true).attr('dy', 20).attr('x', 0);
+ }
+ };
+
+ ctrl.setChart = function (chart) {
+ ctrl.chart = chart;
+ ctrl.setupDonutChartTitle();
+ };
+
+ ctrl.$onChanges = function (changesObj) {
+ if (changesObj.config || changesObj.data) {
+ ctrl.updateAll();
+ }
+ if (changesObj.chartHeight) {
+ ctrl.config.size.height = changesObj.chartHeight.currentValue;
+ }
+ if (changesObj.centerLabel) {
+ ctrl.setupDonutChartTitle();
+ }
+ };
+
+ ctrl.$doCheck = function () {
+ // do a deep compare on data
+ if (!angular.equals(ctrl.data, prevData)) {
+ ctrl.updateAll();
+ }
+ };
+ }]
+});
+;/**
+ * @ngdoc directive
+ * @name patternfly.charts.component:pfDonutChart
+ * @restrict E
+ *
+ * @description
+ * Component for rendering a donut chart which shows the relationships of a set of values to a whole. When using a
+ * Donut Chart to show the relationship of a set of values to a whole, there should be no more than six
+ * categories.
+ *
+ *
+ * See http://c3js.org/reference.html for a full list of C3 chart options.
+ *
+ * @param {object} config configuration properties for the donut chart:
+ *
+ *
.chartId - the unique id of the donut chart
+ *
.centerLabelFn - user defined function to customize the text of the center label (optional)
+ *
.onClickFn(d,i) - user defined function to handle when donut arc is clicked upon.
+ *
+ *
+ * @param {object} data an array of values for the donut chart.
+ *
+ *
.key - string representing an arc within the donut chart
+ *
.value - number representing the value of the arc
+ *
+ *
+ * @param {number} chartHeight height of the donut chart
+
+ * @example
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ angular.module( 'patternfly.charts' ).controller( 'ChartCtrl', function( $scope, $interval ) {
+ $scope.config = {
+ 'chartId': 'chartOne',
+ 'legend': {"show":true},
+ 'colors' : {
+ 'Cats': '#0088ce', // blue
+ 'Hamsters': '#3f9c35', // green
+ 'Fish': '#ec7a08', // orange
+ 'Dogs': '#cc0000' // red
+ },
+ donut: {
+ title: "Animals"
+ },
+ 'onClickFn': function (d, i) {
+ alert("You clicked on donut arc: " + d.id);
+ }
+ };
+
+ $scope.custConfig = angular.copy($scope.config);
+ $scope.custConfig.chartId = 'chartTwo';
+ $scope.custConfig.legend.position = 'right';
+ $scope.custConfig.centerLabelFn = function () {
+ return "Pets";
+ };
+ $scope.chartHeight = 120;
+
+ $scope.data = [
+ ['Cats', 2],
+ ['Hamsters', 1],
+ ['Fish', 3],
+ ['Dogs', 2]
+ ];
+
+
+ });
+
+
+ */
+;/**
+ * @ngdoc directive
+ * @name patternfly.charts.component:pfDonutPctChart
+ * @restrict E
+ *
+ * @description
+ * Component for rendering a percentage used donut/radial chart. The Used Percentage fill starts at 12 o’clock and
+ * moves clockwise. Whatever portion of the donut not Used, will be represented as Available, and rendered as a
+ * gray fill.
+ * There are three possible fill colors for Used Percentage, dependent on whether or not there are thresholds:
+ *
+ *
When no thresholds exist, or if the used percentage has not surpassed any thresholds, the indicator is blue.
+ *
When the used percentage has surpassed the warning threshold, but not the error threshold, the indicator is orange.
+ *
When the used percentage has surpassed the error threshold, the indicator is is red.
+ *
+ * The directive will calculate the Available Percentage (Total - Used), and display it as a grey radial fill.
+ *
+ *
+ * See http://c3js.org/reference.html for a full list of C3 chart options.
+ *
+ * @param {object} config configuration properties for the donut chart:
+ *
+ *
.chartId - the unique id of the donut chart
+ *
.units - unit label for values, ex: 'MHz','GB', etc..
+ *
.thresholds - warning and error percentage thresholds used to determine the Usage Percentage fill color (optional)
+ *
.tooltipFn(d) - user defined function to customize the tool tip (optional)
+ *
.centerLabelFn - user defined function to customize the text of the center label (optional)
+ *
.onClickFn(d,i) - user defined function to handle when donut arc is clicked upon.
+ *
.orientation - string with possible values: 'left', 'right' (optional) - default: 'center'
+ *
.title - string representing a prefix or title (optional) - default: empty string
+ *
.label - the wording format to display, possible values: 'used', 'available', 'percent', 'none' (optional) - default: 'used'
+ *
.units - unit label for values, ex: 'MHz','GB', etc.. (optional) - default: empty string
+ *
.labelFn - function to customize the text of the external label. This callback returns no data. Updated display data can be accessed through the passed and updated parameter 'data'. (optional) - default: undefined
+ *
+ *
+ *
+ *
+ * @param {object} data the Total and Used values for the donut chart. Available is calculated as Total - Used.
+ *
+ *
.used - number representing the amount used
+ *
.percent - number representing the percentage used
+ *
.total - number representing the total amount
+ *
.dataAvailable - Flag if there is data available - default: true
+ *
+ *
+ * @param {string=} center-label specifies the contents of the donut's center label.
+ * Values:
+ *
+ *
'used' - displays the Used amount in the center label (default)
+ *
'available' - displays the Available amount in the center label
+ *
'percent' - displays the Usage Percent of the Total amount in the center label
+ *
'none' - does not display the center label
+ *
+ *
+ * @param {string=} tooltip specifies the value to show in the tooltip when hovering Used or Available chart segments
+ * Values:
+ *
+ *
'percent' - displays the Used or Available percentage of the Total in the tooltop (default)
+ *
'amount' - displays the Used or Available amount and units in the tooltip
+ *
'both' - displays both the percentage and amount in the tooltip
+ *
+ *
+ * @param {int=} chartHeight height of the donut chart
+ * @param {function (threshold)} on-threshold-change user defined function to handle when thresolds change
+ * 'threshold' Values:
+ *
+ *
+ * @param {boolean=} chartDataAvailable flag if the chart data is available - default: true
+ * @param {number=} height height of the chart (no units) - default: 200
+ * @param {string=} chartTitle title of the chart
+ * @param {boolean=} showLegend flag to show the legend, defaults to true
+ * @param {array=} legendLabels the labels for the legend - defaults: ['< 70%', '70-80%' ,'80-90%', '> 90%']
+ * @param {number=} maxBlockSize the maximum size for blocks in the heatmap. Default: 50, Range: 5 - 50
+ * @param {number=} minBlockSize the minimum size for blocks in the heatmap. Default: 2
+ * @param {number=} blockPadding the padding in pixels between blocks (default: 2)
+ * @param {array=} thresholds the threshold values for the heapmap - defaults: [0.7, 0.8, 0.9]
+ * @param {array=} heatmapColorPattern the colors that correspond to the various threshold values (lowest to hightest value ex: <70& to >90%) - defaults: ['#d4f0fa', '#F9D67A', '#EC7A08', '#CE0000']
+ * @param {function=} clickAction function(block) function to call when a block is clicked on
+ * @param {number=} rangeHoverSize the maximum size for highlighting blocks in the same range. Default: 15
+ * @param {boolean=} rangeOnHover flag to highlight blocks in the same range on hover, defaults to true
+ * @param {array=} rangeTooltips the tooltips for blocks in the same range - defaults: ['< 70%', '70-80%' ,'80-90%', '> 90%']
+ * @example
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ angular.module( 'patternfly.charts' ).controller( 'ChartCtrl', function( $scope) {
+ $scope.data = [
+ {'id': 9,'value': 0.96,'tooltip': 'Node 8 : My OpenShift Provider 96% : 96 Used of 100 Total 4 Available'},
+ {'id': 44, 'value': 0.94, 'tooltip': 'Node 19 : My Kubernetes Provider 94% : 94 Used of 100 Total 6 Available'},
+ {'id': 0, 'value': 0.91, 'tooltip': 'Node 9 : My OpenShift Provider 91% : 91 Used of 100 Total 9 Available'},
+ {'id': 43, 'value': 0.9, 'tooltip': 'Node 18 : My Kubernetes Provider 90% : 90 Used of 100 Total 10 Available'},
+ {'id': 7, 'value': 0.89, 'tooltip': 'Node 12 : My OpenShift Provider 89% : 89 Used of 100 Total 11 Available'},
+ {'id': 41, 'value': 0.82, 'tooltip': 'Node 16 : My Kubernetes Provider 82% : 82 Used of 100 Total 18 Available'},
+ {'id': 21, 'value': 0.81, 'tooltip': 'Node 21 : My OpenShift Provider 81% : 81 Used of 100 Total 19 Available'},
+ {'id': 26, 'value': 0.8, 'tooltip': 'Node 1 : My Kubernetes Provider 80% : 80 Used of 100 Total 20 Available'},
+ {'id': 48, 'value': 0.74, 'tooltip': 'Node 23 : My Kubernetes Provider 74% : 74 Used of 100 Total 26 Available'},
+ {'id': 27, 'value': 0.72, 'tooltip': 'Node 2 : My Kubernetes Provider 72% : 72 Used of 100 Total 28 Available'},
+ {'id': 42, 'value': 0.71, 'tooltip': 'Node 17 : My Kubernetes Provider 71% : 71 Used of 100 Total 29 Available'},
+ {'id': 23, 'value': 0.71, 'tooltip': 'Node 23 : My OpenShift Provider 71% : 71 Used of 100 Total 29 Available'},
+ {'id': 22, 'value': 0.69, 'tooltip': 'Node 22 : My OpenShift Provider 69% : 69 Used of 100 Total 31 Available'},
+ {'id': 2, 'value': 0.66, 'tooltip': 'Node 2 : M8y OpenShift Provider 66% : 66 Used of 100 Total 34 Available'},
+ {'id': 39, 'value': 0.66, 'tooltip': 'Node 14 : My Kubernetes Provider 66% : 66 Used of 100 Total 34 Available'},
+ {'id': 3, 'value': 0.65, 'tooltip': 'Node 39 : My OpenShift Provider 65% : 65 Used of 100 Total 35 Available'},
+ {'id': 29, 'value': 0.65, 'tooltip': 'Node 4 : My Kubernetes Provider 65% : 65 Used of 100 Total 35 Available'},
+ {'id': 32, 'value': 0.56, 'tooltip': 'Node 7 : My Kubernetes Provider 56% : 56 Used of 100 Total 44 Available'},
+ {'id': 13, 'value': 0.56, 'tooltip': 'Node 13 : My OpenShift Provider 56% : 56 Used of 100 Total 44 Available'},
+ {'id': 49, 'value': 0.52, 'tooltip': 'Node 24 : My Kubernetes Provider 52% : 52 Used of 100 Total 48 Available'},
+ {'id': 36, 'value': 0.5, 'tooltip': 'Node 11 : My Kubernetes Provider 50% : 50 Used of 100 Total 50 Available'},
+ {'id': 6, 'value': 0.5, 'tooltip': 'Node 5 : My OpenShift Provider 50% : 50 Used of 100 Total 50 Available'},
+ {'id': 38, 'value': 0.49, 'tooltip': 'Node 13 : My Kubernetes Provider 49% : 49 Used of 100 Total 51 Available'},
+ {'id': 15, 'value': 0.48, 'tooltip': 'Node 15 : My OpenShift Provider 48% : 48 Used of 100 Total 52 Available'},
+ {'id': 30, 'value': 0.48, 'tooltip': 'Node 5 : My Kubernetes Provider 48% : 48 Used of 100 Total 52 Available'},
+ {'id': 11, 'value': 0.47, 'tooltip': 'Node 11 : My OpenShift Provider 47% : 47 Used of 100 Total 53 Available'},
+ {'id': 17, 'value': 0.46, 'tooltip': 'Node 17 : My OpenShift Provider 46% : 46 Used of 100 Total 54 Available'},
+ {'id': 25, 'value': 0.45, 'tooltip': 'Node 0 : My Kubernetes Provider 45% : 45 Used of 100 Total 55 Available'},
+ {'id': 50, 'value': 0.45, 'tooltip': 'Node 25 : My Kubernetes Provider 45% : 45 Used of 100 Total 55 Available'},
+ {'id': 46, 'value': 0.45, 'tooltip': 'Node 21 : My Kubernetes Provider 45% : 45 Used of 100 Total 55 Available'},
+ {'id': 47, 'value': 0.45, 'tooltip': 'Node 22 : My Kubernetes Provider 45% : 45 Used of 100 Total 55 Available'},
+ {'id': 1, 'value': 0.44, 'tooltip': 'Node 1 : My OpenShift Provider 44% : 44 Used of 100 Total 56 Available'},
+ {'id': 31, 'value': 0.44, 'tooltip': 'Node 6 : My Kubernetes Provider 44% : 44 Used of 100 Total 56 Available'},
+ {'id': 37, 'value': 0.44, 'tooltip': 'Node 12 : My Kubernetes Provider 44% : 44 Used of 100 Total 56 Available'},
+ {'id': 24, 'value': 0.44, 'tooltip': 'Node 24 : My OpenShift Provider 44% : 44 Used of 100 Total 56 Available'},
+ {'id': 40, 'value': 0.43, 'tooltip': 'Node 40 : My Kubernetes Provider 43% : 43 Used of 100 Total 57 Available'},
+ {'id': 20, 'value': 0.39, 'tooltip': 'Node 20 : My OpenShift Provider 39% : 39 Used of 100 Total 61 Available'},
+ {'id': 8, 'value': 0.39, 'tooltip': 'Node 8 : My OpenShift Provider 39% : 39 Used of 100 Total 61 Available'},
+ {'id': 5, 'value': 0.38, 'tooltip': 'Node 5 : My OpenShift Provider 38% : 38 Used of 100 Total 62 Available'},
+ {'id': 45, 'value': 0.37, 'tooltip': 'Node 20 : My Kubernetes Provider 37% : 37 Used of 100 Total 63 Available'},
+ {'id': 12, 'value': 0.37, 'tooltip': 'Node 12 : My OpenShift Provider 37% : 37 Used of 100 Total 63 Available'},
+ {'id': 34, 'value': 0.37, 'tooltip': 'Node 9 : My Kubernetes Provider 37% : 37 Used of 100 Total 63 Available'},
+ {'id': 33, 'value': 0.33, 'tooltip': 'Node 8 : My Kubernetes Provider 33% : 33 Used of 100 Total 67 Available'},
+ {'id': 16, 'value': 0.32, 'tooltip': 'Node 16 : My OpenShift Provider 32% : 32 Used of 100 Total 68 Available'},
+ {'id': 10, 'value': 0.29, 'tooltip': 'Node 10 : My OpenShift Provider 28% : 29 Used of 100 Total 71 Available'},
+ {'id': 35, 'value': 0.28, 'tooltip': 'Node 35 : My Kubernetes Provider 28% : 28 Used of 100 Total 72 Available'},
+ {'id': 18, 'value': 0.27, 'tooltip': 'Node 18 : My OpenShift Provider 27% : 27 Used of 100 Total 73 Available'},
+ {'id': 4, 'value': 0.26, 'tooltip': 'Node 4 : My OpenShift Provider 26% : 26 Used of 100 Total 74 Available'},
+ {'id': 19, 'value': 0.25, 'tooltip': 'Node 19 : My OpenShift Provider 25% : 25 Used of 100 Total 75 Available'},
+ {'id': 28, 'value': 0.25, 'tooltip': 'Node 3 : My Kubernetes Provider 25% : 25 Used of 100 Total 75 Available'},
+ {'id': 51, 'value': 0.22, 'tooltip': 'Node 26 : My Kubernetes Provider 22% : 22 Used of 100 Total 78 Available'},
+ {'id': 14, 'value': 0.2, 'tooltip': 'Node 14 : My OpenShift Provider 20% : 20 Used of 100 Total 80 Available'}];
+
+ $scope.dataAvailable = true;
+ $scope.title = 'Utilization - Using Defaults';
+ $scope.titleAlt = 'Utilization - Overriding Defaults';
+ $scope.titleSmall = 'Utilization - Small Blocks';
+ $scope.legendLabels = ['< 60%','70%', '70-80%' ,'80-90%', '> 90%'];
+ $scope.rangeTooltips = ['Memory Utilization < 70% 40 Nodes', 'Memory Utilization 70-80% 4 Nodes', 'Memory Utilization 80-90% 4 Nodes', 'Memory Utilization > 90% 4 Nodes'];
+ $scope.thresholds = [0.6, 0.7, 0.8, 0.9];
+ $scope.heatmapColorPattern = ['#d4f0fa', '#F9D67A', '#EC7A08', '#CE0000', '#f00'];
+
+ $scope.showLegends = true;
+ var clickAction = function (block) {
+ console.log(block);
+ };
+ $scope.clickAction = clickAction;
+ });
+
+
+ */
+angular.module('patternfly.charts').component('pfHeatmap', {
+ bindings: {
+ data: '<',
+ chartDataAvailable: '',
+ height: '',
+ chartTitle: '',
+ showLegend: '',
+ legendLabels: '',
+ maxBlockSize: '@',
+ minBlockSize: '@',
+ blockPadding: '@',
+ thresholds: '',
+ heatmapColorPattern: '',
+ clickAction: '',
+ rangeOnHover: '',
+ rangeHoverSize: '@',
+ rangeTooltips: ''
+ },
+ templateUrl: 'charts/heatmap/heatmap.html',
+ controller: ["$element", "$window", "$compile", "$scope", "$timeout", function ($element, $window, $compile, $scope, $timeout) {
+ 'use strict';
+ var ctrl = this, prevData;
+
+ var containerWidth, containerHeight, blockSize, numberOfRows;
+
+ var thresholdDefaults = [0.7, 0.8, 0.9];
+ var heatmapColorPatternDefaults = ['#d4f0fa', '#F9D67A', '#EC7A08', '#CE0000'];
+ var legendLabelDefaults = ['< 70%', '70-80%' ,'80-90%', '> 90%'];
+ var rangeTooltipDefaults = ['< 70%', '70-80%' ,'80-90%', '> 90%'];
+ var heightDefault = 200;
+
+ var setStyles = function () {
+ ctrl.containerStyles = {
+ height: ctrl.height + 'px',
+ display: ctrl.chartDataAvailable === false ? 'none' : 'block'
+ };
+ };
+
+ var setSizes = function () {
+ var parentContainer = $element[0].querySelector('.heatmap-container');
+ containerWidth = parentContainer.clientWidth;
+ containerHeight = parentContainer.clientHeight;
+ blockSize = determineBlockSize();
+
+ if ((blockSize - ctrl.padding) > ctrl.maxSize) {
+ blockSize = ctrl.padding + ctrl.maxSize;
+
+ // Attempt to square off the area, check if square fits
+ numberOfRows = Math.ceil(Math.sqrt(ctrl.data.length));
+ if (blockSize * numberOfRows > containerWidth ||
+ blockSize * numberOfRows > containerHeight) {
+ numberOfRows = (blockSize === 0) ? 0 : Math.floor(containerHeight / blockSize);
+ }
+ } else if ((blockSize - ctrl.padding) < ctrl.minSize) {
+ blockSize = ctrl.padding + ctrl.minSize;
+
+ // Attempt to square off the area, check if square fits
+ numberOfRows = Math.ceil(Math.sqrt(ctrl.data.length));
+ if (blockSize * numberOfRows > containerWidth ||
+ blockSize * numberOfRows > containerHeight) {
+ numberOfRows = (blockSize === 0) ? 0 : Math.floor(containerHeight / blockSize);
+ }
+ } else {
+ numberOfRows = (blockSize === 0) ? 0 : Math.floor(containerHeight / blockSize);
+ }
+ };
+
+ var determineBlockSize = function () {
+ var x = containerWidth;
+ var y = containerHeight;
+ var n = ctrl.data ? ctrl.data.length : 0;
+ var px = Math.ceil(Math.sqrt(n * x / y));
+ var py = Math.ceil(Math.sqrt(n * y / x));
+ var sx, sy;
+
+ if (Math.floor(px * y / x) * px < n) {
+ sx = y / Math.ceil(px * y / x);
+ } else {
+ sx = x / px;
+ }
+
+ if (Math.floor(py * x / y) * py < n) {
+ sy = x / Math.ceil(x * py / y);
+ } else {
+ sy = y / py;
+ }
+ return Math.max(sx, sy);
+ };
+
+ var redraw = function () {
+ var data = ctrl.data;
+ var color = d3.scale.threshold().domain(ctrl.thresholds).range(ctrl.heatmapColorPattern);
+ var rangeTooltip = d3.scale.threshold().domain(ctrl.thresholds).range(ctrl.rangeTooltips);
+ var blocks;
+ var fillSize = blockSize - ctrl.padding;
+ var highlightBlock = function (block, active) {
+ block.style('fill-opacity', active ? 1 : 0.4);
+ };
+ var highlightBlockColor = function (block, fillColor) {
+ // Get fill color from given block
+ var blockColor = color(block.map(function (d) {
+ return d[0].__data__.value;
+ }));
+ // If given color matches, apply highlight
+ if (blockColor === fillColor) {
+ block.style('fill-opacity', 1);
+ }
+ };
+
+ var svg = window.d3.select(ctrl.thisComponent);
+ svg.selectAll('*').remove();
+ blocks = svg.selectAll('rect').data(data).enter().append('rect');
+ blocks.attr('x', function (d, i) {
+ return Math.floor(i / numberOfRows) * blockSize;
+ }).attr('y', function (d, i) {
+ return i % numberOfRows * blockSize;
+ }).attr('width', fillSize).attr('height', fillSize).style('fill', function (d) {
+ return color(d.value);
+ }).attr('uib-tooltip-html', function (d, i) { //tooltip-html is throwing an exception
+ if (ctrl.rangeOnHover && fillSize <= ctrl.rangeHoverSize) {
+ return '"' + rangeTooltip(d.value) + '"';
+ }
+ return "'" + d.tooltip + "'";
+ }).attr('tooltip-append-to-body', function (d, i) {
+ return true;
+ }).attr('tooltip-animation', function (d, i) {
+ return false;
+ });
+
+ //Adding events
+ blocks.on('mouseover', function () {
+ var fillColor;
+ blocks.call(highlightBlock, false);
+ if (ctrl.rangeOnHover && fillSize <= ctrl.rangeHoverSize) {
+ // Get fill color for current block
+ fillColor = color(d3.select(this).map(function (d) {
+ return d[0].__data__.value;
+ }));
+ // Highlight all blocks matching fill color
+ blocks[0].forEach(function (block) {
+ highlightBlockColor(d3.select(block), fillColor);
+ });
+ } else {
+ d3.select(this).call(highlightBlock, true);
+ }
+ });
+ blocks.on('click', function (d) {
+ if (ctrl.clickAction) {
+ ctrl.clickAction(d);
+ }
+ });
+
+ //Compiles the tooltips
+ angular.forEach(angular.element(blocks), function (block) {
+ var el = angular.element(block);
+ // TODO: get heatmap tooltips to work without using $compile or $scope
+ $compile(el)($scope);
+ });
+
+ svg.on('mouseleave', function () {
+ blocks.call(highlightBlock, true);
+ });
+ };
+
+ var updateDisplay = function () {
+ setStyles();
+
+ if (ctrl.chartDataAvailable !== false && ctrl.data) {
+ ctrl.loadingDone = true;
+
+ // Allow the style change to take effect to update the container size
+ $timeout(function () {
+ setSizes();
+ redraw();
+ });
+ }
+ };
+
+ var handleDataUpdate = function () {
+ prevData = angular.copy(ctrl.data);
+ updateDisplay();
+ };
+
+ var debounceResize = _.debounce(function () {
+ updateDisplay();
+ }, 250, 500);
+
+ var updateConfig = function () {
+ //Allow overriding of defaults
+ if (ctrl.maxBlockSize === undefined || isNaN(ctrl.maxBlockSize)) {
+ ctrl.maxSize = 64;
+ } else {
+ ctrl.maxSize = parseInt(ctrl.maxBlockSize);
+ if (ctrl.maxSize < 5) {
+ ctrl.maxSize = 5;
+ } else if (ctrl.maxSize > 50) {
+ ctrl.maxSize = 50;
+ }
+ }
+
+ if (ctrl.minBlockSize === undefined || isNaN(ctrl.minBlockSize)) {
+ ctrl.minSize = 2;
+ } else {
+ ctrl.minSize = parseInt(ctrl.minBlockSize);
+ }
+
+ if (ctrl.blockPadding === undefined || isNaN(ctrl.blockPadding)) {
+ ctrl.padding = 2;
+ } else {
+ ctrl.padding = parseInt(ctrl.blockPadding);
+ }
+
+ if (ctrl.rangeHoverSize === undefined || isNaN(ctrl.rangeHoverSize)) {
+ ctrl.rangeHoverSize = 15;
+ } else {
+ ctrl.rangeHoverSize = parseInt(ctrl.rangeHoverSize);
+ }
+
+ ctrl.rangeOnHover = (ctrl.rangeOnHover === undefined || ctrl.rangeOnHover) ? true : false;
+
+ if (!ctrl.rangeTooltips) {
+ ctrl.rangeTooltips = rangeTooltipDefaults;
+ }
+
+ if (!ctrl.thresholds) {
+ ctrl.thresholds = thresholdDefaults;
+ }
+
+ if (!ctrl.heatmapColorPattern) {
+ ctrl.heatmapColorPattern = heatmapColorPatternDefaults;
+ }
+
+ if (!ctrl.legendLabels) {
+ ctrl.legendLabels = legendLabelDefaults;
+ }
+ ctrl.height = ctrl.height || heightDefault;
+ ctrl.showLegend = ctrl.showLegend || (ctrl.showLegend === undefined);
+ };
+
+ ctrl.loadingDone = false;
+
+ ctrl.$onChanges = function (changesObj) {
+ if (changesObj.chartDataAvailable && !changesObj.chartDataAvailable.isFirstChange()) {
+ setStyles();
+ } else if (!changesObj.data) {
+ updateConfig();
+ updateDisplay();
+ }
+ };
+
+ ctrl.$doCheck = function () {
+ // do a deep compare on chartData and config
+ if (!angular.equals(ctrl.data, prevData)) {
+ handleDataUpdate();
+ }
+ };
+
+ ctrl.$postLink = function () {
+ ctrl.thisComponent = $element[0].querySelector('.heatmap-pf-svg');
+ updateConfig();
+ handleDataUpdate();
+
+ angular.element($window).on('resize', debounceResize);
+ };
+
+ ctrl.$onDestroy = function () {
+ angular.element($window).off('resize', debounceResize);
+ };
+ }]
+});
+;/**
+ * @ngdoc directive
+ * @name patternfly.charts.component:pfLineChart
+ * @restrict E
+ *
+ * @description
+ * Component for rendering a line chart.
+ *
+ * See http://c3js.org/reference.html for a full list of C3 chart options.
+ *
+ * @param {object} config configuration settings for the line chart:
+ *
+ *
.chartId - the ID of the container that the chart should bind to
+ *
.units - unit label for values, ex: 'MHz','GB', etc..
+ *
.tooltipFn - (optional) override the tooltip contents generation functions. Should take a data point and
+ * return HTML markup for the tooltip contents. Setting this overrides the tooltipType value.
+ *
.area - (optional) overrides the default Area properties of the C3 chart
+ *
.size - (optional) overrides the default Size properties of the C3 chart
+ *
.axis - (optional) overrides the default Axis properties of the C3 chart
+ *
.color - (optional) overrides the default Color properties of the C3 chart
+ *
.legend - (optional) overrides the default Legend properties of the C3 chart
+ *
.point - (optional) overrides the default Point properties of the C3 chart
+ *
+ *
+ * @param {object} chartData the data to be shown as an area chart
+ * First and second Array elements, xData and yData, must exist, next data arrays are optional.
+ *
+ *
.xData - Array, X values for the data points, first element must be the name of the data
+ *
.yData - Array, Y Values for the data points, first element must be the name of the data
+ *
.yData1 - Array, Y Values for the data points, first element must be the name of the data
+ *
.[...] - Array, Y Values for the data points, first element must be the name of the data
+ *
+ *
+ * @param {boolean=} showXAxis override config settings for showing the X Axis
+ * @param {boolean=} showYAxis override config settings for showing the Y Axis
+ * @param {boolean=} setAreaChart override config settings for showing area type chart
+
+ * @example
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ angular.module( 'patternfly.charts' ).controller( 'ChartCtrl', function( $scope, pfUtils ) {
+
+ $scope.config = {
+ chartId: 'exampleLine',
+ grid: {y: {show: false}},
+ point: {r: 1},
+ color: {pattern: [pfUtils.colorPalette.blue, pfUtils.colorPalette.green]}
+ };
+
+ var today = new Date();
+ var dates = ['dates'];
+ for (var d = 20 - 1; d >= 0; d--) {
+ dates.push(new Date(today.getTime() - (d * 24 * 60 * 60 * 1000)));
+ }
+
+ $scope.data = {
+ dataAvailable: true,
+ xData: dates,
+ yData0: ['Created', 12, 10, 10, 62, 17, 10, 15, 13, 17, 10, 12, 10, 10, 12, 17, 16, 15, 13, 17, 10],
+ yData1: ['Deleted', 10, 17, 76, 14, 10, 10, 10, 10, 10, 10, 10, 17, 17, 14, 10, 10, 10, 10, 10, 10]
+ };
+
+ $scope.custShowXAxis = false;
+ $scope.custShowYAxis = false;
+ $scope.custAreaChart = false;
+
+ $scope.addDataPoint = function () {
+ $scope.data.xData.push(new Date($scope.data.xData[$scope.data.xData.length - 1].getTime() + (24 * 60 * 60 * 1000)));
+ $scope.data.yData0.push(Math.round(Math.random() * 100));
+ $scope.data.yData1.push(Math.round(Math.random() * 100));
+ };
+
+ $scope.resetData = function () {
+ $scope.data = {
+ xData: dates,
+ yData0: ['Created', 12, 10, 10, 62],
+ yData1: ['Deleted', 10, 17, 76, 14]
+ };
+ };
+ });
+
+
+ */
+angular.module('patternfly.charts').component('pfLineChart', {
+ bindings: {
+ config: '<',
+ chartData: '<',
+ showXAxis: '',
+ showYAxis: '',
+ setAreaChart: ''
+ },
+ templateUrl: 'charts/line/line-chart.html',
+ controller: ["pfUtils", function (pfUtils) {
+ 'use strict';
+ var ctrl = this, prevChartData;
+
+ ctrl.updateAll = function () {
+ // Need to deep watch changes in chart data
+ prevChartData = angular.copy(ctrl.chartData);
+
+ // Create an ID for the chart based on the chartId in the config if given
+ if (ctrl.lineChartId === undefined) {
+ ctrl.lineChartId = 'lineChart';
+ if (ctrl.config.chartId) {
+ ctrl.lineChartId = ctrl.config.chartId + ctrl.lineChartId;
+ }
+ }
+
+ /*
+ * Setup Axis options. Default is to not show either axis. This can be overridden in two ways:
+ * 1) in the config, setting showAxis to true will show both axes
+ * 2) in the attributes showXAxis and showYAxis will override the config if set
+ *
+ * By default only line and the tick marks are shown, no labels. This is a line and should be used
+ * only to show a brief idea of trending. This can be overridden by setting the config.axis options per C3
+ */
+
+ if (ctrl.showXAxis === undefined) {
+ ctrl.showXAxis = (ctrl.config.showAxis !== undefined) && ctrl.config.showAxis;
+ }
+
+ if (ctrl.showYAxis === undefined) {
+ ctrl.showYAxis = (ctrl.config.showAxis !== undefined) && ctrl.config.showAxis;
+ }
+
+ ctrl.defaultConfig = patternfly.c3ChartDefaults().getDefaultLineConfig();
+ ctrl.defaultConfig.axis = {
+ x: {
+ show: ctrl.showXAxis === true,
+ type: 'timeseries',
+ tick: {
+ format: function () {
+ return '';
+ }
+ }
+ },
+ y: {
+ show: ctrl.showYAxis === true,
+ tick: {
+ format: function () {
+ return '';
+ }
+ }
+ }
+ };
+
+ /*
+ * Setup Chart type option. Default is Line Chart.
+ */
+ if (ctrl.setAreaChart === undefined) {
+ ctrl.setAreaChart = (ctrl.config.setAreaChart !== undefined) && ctrl.config.setAreaChart;
+ }
+
+ // Convert the given data to C3 chart format
+ ctrl.config.data = ctrl.getLineData(ctrl.chartData);
+
+ // Override defaults with callers specifications
+ ctrl.defaultConfig = pfUtils.merge(ctrl.defaultConfig, ctrl.config);
+
+ // Will trigger c3 chart generation
+ ctrl.chartConfig = pfUtils.merge(ctrl.defaultConfig, ctrl.config);
+ };
+
+ /*
+ * Convert the config data to C3 Data
+ */
+ ctrl.getLineData = function (chartData) {
+ var lineData = {
+ type: ctrl.setAreaChart ? "area" : "line"
+ };
+
+ if (chartData && chartData.dataAvailable !== false && chartData.xData) {
+ lineData.x = chartData.xData[0];
+ // Convert the chartData dictionary into a C3 columns data arrays
+ lineData.columns = Object.keys(chartData).map(function (key) {
+ return chartData[key];
+ });
+ }
+
+ return lineData;
+ };
+
+ ctrl.$onChanges = function (changesObj) {
+ ctrl.updateAll();
+ };
+
+ ctrl.$doCheck = function () {
+ // do a deep compare on chartData
+ if (!angular.equals(ctrl.chartData, prevChartData)) {
+ ctrl.updateAll();
+ }
+ };
+ }]
+});
+;/**
+ * @ngdoc directive
+ * @name patternfly.charts.component:pfSparklineChart
+ * @restrict E
+ *
+ * @description
+ * Component for rendering a sparkline chart.
+ *
+ * See http://c3js.org/reference.html for a full list of C3 chart options.
+ *
+ * @param {object} config configuration settings for the sparkline chart:
+ *
+ *
.chartId - the ID of the container that the chart should bind to
+ *
.units - unit label for values, ex: 'MHz','GB', etc..
+ *
.tooltipType - (optional) set the type of tooltip, valid values:
+ *
+ *
'default' - show the data point value and the data point name.
+ *
'usagePerDay' - show the date, percent used, and used value for the data point.
+ *
'valuePerDay' - show the date and value for the data point.
+ *
'percentage' - show the current data point as a percentage.
+ *
+ *
.tooltipFn - (optional) override the tooltip contents generation functions. Should take a data point and
+ * return HTML markup for the tooltip contents. Setting this overrides the tooltipType value.
+ *
.area - (optional) overrides the default Area properties of the C3 chart
+ *
.size - (optional) overrides the default Size properties of the C3 chart
+ *
.axis - (optional) overrides the default Axis properties of the C3 chart
+ *
.color - (optional) overrides the default Color properties of the C3 chart
+ *
.legend - (optional) overrides the default Legend properties of the C3 chart
+ *
.point - (optional) overrides the default Point properties of the C3 chart
+ *
+ *
+ * @param {object} chartData the data to be shown as an area chart
+ *
+ *
.xData - Array, X values for the data points, first element must be the name of the data
+ *
.yData - Array, Y Values for the data points, first element must be the name of the data
+ *
.total - (optional) The Total amount, used when determining percentages
+ *
.dataAvailable - Flag if there is data available - default: true
+ *
+ *
+ * @param {int=} chartHeight height of the sparkline chart
+ * @param {boolean=} showXAxis override config settings for showing the X Axis
+ * @param {boolean=} showYAxis override config settings for showing the Y Axis
+
+ * @example
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ angular.module( 'patternfly.charts' ).controller( 'ChartCtrl', function( $scope ) {
+
+ $scope.config = {
+ chartId: 'exampleSparkline',
+ tooltipType: 'default'
+ };
+
+ var today = new Date();
+ var dates = ['dates'];
+ for (var d = 20 - 1; d >= 0; d--) {
+ dates.push(new Date(today.getTime() - (d * 24 * 60 * 60 * 1000)));
+ }
+
+ $scope.data = {
+ dataAvailable: true,
+ total: 100,
+ xData: dates,
+ yData: ['used', 10, 20, 30, 20, 30, 10, 14, 20, 25, 68, 54, 56, 78, 56, 67, 88, 76, 65, 87, 76]
+ };
+
+ $scope.custShowXAxis = false;
+ $scope.custShowYAxis = false;
+ $scope.custChartHeight = 60;
+
+ $scope.addDataPoint = function () {
+ $scope.data.xData.push(new Date($scope.data.xData[$scope.data.xData.length - 1].getTime() + (24 * 60 * 60 * 1000)));
+ $scope.data.yData.push(Math.round(Math.random() * 100));
+ };
+ });
+
+
+ */
+angular.module('patternfly.charts').component('pfSparklineChart', {
+ bindings: {
+ config: '<',
+ chartData: '<',
+ chartHeight: '',
+ showXAxis: '',
+ showYAxis: ''
+ },
+ templateUrl: 'charts/sparkline/sparkline-chart.html',
+ controller: ["pfUtils", function (pfUtils) {
+ 'use strict';
+ var ctrl = this, prevChartData;
+
+ ctrl.updateAll = function () {
+ // Need to deep watch changes in chart data
+ prevChartData = angular.copy(ctrl.chartData);
+
+ // Create an ID for the chart based on the chartId in the config if given
+ if (ctrl.sparklineChartId === undefined) {
+ ctrl.sparklineChartId = 'sparklineChart';
+ if (ctrl.config.chartId) {
+ ctrl.sparklineChartId = ctrl.config.chartId + ctrl.sparklineChartId;
+ }
+ }
+
+ /*
+ * Setup Axis options. Default is to not show either axis. This can be overridden in two ways:
+ * 1) in the config, setting showAxis to true will show both axes
+ * 2) in the attributes showXAxis and showYAxis will override the config if set
+ *
+ * By default only line and the tick marks are shown, no labels. This is a sparkline and should be used
+ * only to show a brief idea of trending. This can be overridden by setting the config.axis options per C3
+ */
+
+ if (ctrl.showXAxis === undefined) {
+ ctrl.showXAxis = (ctrl.config.showAxis !== undefined) && ctrl.config.showAxis;
+ }
+
+ if (ctrl.showYAxis === undefined) {
+ ctrl.showYAxis = (ctrl.config.showAxis !== undefined) && ctrl.config.showAxis;
+ }
+
+ ctrl.defaultConfig = patternfly.c3ChartDefaults().getDefaultSparklineConfig();
+ ctrl.defaultConfig.axis = {
+ x: {
+ show: ctrl.showXAxis === true,
+ type: 'timeseries',
+ tick: {
+ format: function () {
+ return '';
+ }
+ }
+ },
+ y: {
+ show: ctrl.showYAxis === true,
+ tick: {
+ format: function () {
+ return '';
+ }
+ }
+ }
+ };
+
+ // Setup the default configuration
+ ctrl.defaultConfig.tooltip = ctrl.sparklineTooltip();
+ if (ctrl.chartHeight) {
+ ctrl.defaultConfig.size.height = ctrl.chartHeight;
+ }
+ ctrl.defaultConfig.units = '';
+
+ // Convert the given data to C3 chart format
+ ctrl.config.data = pfUtils.merge(ctrl.config.data, ctrl.getSparklineData(ctrl.chartData));
+
+ // Override defaults with callers specifications
+ ctrl.chartConfig = pfUtils.merge(ctrl.defaultConfig, ctrl.config);
+ };
+
+ /*
+ * Convert the config data to C3 Data
+ */
+ ctrl.getSparklineData = function (chartData) {
+ var sparklineData = {
+ type: 'area'
+ };
+
+ if (chartData && chartData.dataAvailable !== false && chartData.xData && chartData.yData) {
+ sparklineData.x = chartData.xData[0];
+ sparklineData.columns = [
+ chartData.xData,
+ chartData.yData
+ ];
+ }
+
+ return sparklineData;
+ };
+
+ ctrl.getTooltipTableHTML = function (tipRows) {
+ return '
';
+ break;
+ default:
+ tipRows = patternfly.c3ChartDefaults().getDefaultSparklineTooltip().contents(d);
+ }
+ }
+ return ctrl.getTooltipTableHTML(tipRows);
+ },
+ position: function (data, width, height, element) {
+ var center;
+ var top;
+ var chartBox;
+ var graphOffsetX;
+ var x;
+
+ try {
+ center = parseInt(element.getAttribute('x'));
+ top = parseInt(element.getAttribute('y'));
+ chartBox = document.querySelector('#' + ctrl.sparklineChartId).getBoundingClientRect();
+ graphOffsetX = document.querySelector('#' + ctrl.sparklineChartId + ' g.c3-axis-y').getBoundingClientRect().right;
+ x = Math.max(0, center + graphOffsetX - chartBox.left - Math.floor(width / 2));
+
+ return {
+ top: top - height,
+ left: Math.min(x, chartBox.width - width)
+ };
+ } catch (e) {
+ }
+ }
+ };
+ };
+
+ ctrl.$onChanges = function (changesObj) {
+ ctrl.updateAll();
+ };
+
+ ctrl.$doCheck = function () {
+ // do a deep compare on chartData
+ if (!angular.equals(ctrl.chartData, prevChartData)) {
+ ctrl.updateAll();
+ }
+ };
+ }]
+});
+;/**
+ * @ngdoc directive
+ * @name patternfly.charts.component:pfTopologyMap
+ * @restrict E
+ *
+ * @param {array} nodes array containing objects representing graph nodes. Each node has these attributes. Only node id is mandatory parameter.
+ *
+ *
id: unique node identifier
+ *
title: node title
+ *
size: node radius; default value is 17
+ *
fileicon: this attribute specifies path to image file. eg: '/some/path/to/image/image.png'. File icon has higher priority than fonticon.
+ *
fonticon: css class of node icon eg: 'fa fa-info' File icon has higher priority than fonticon.
+ *
fill: string containing color code (basic, RGB, HEX) of node background.
+ *
borderColor: string containing color code (basic, RGB, HEX) of node border.
+ *
iconColor: string containing color code (basic, RGB, HEX) of node icon, if iconType is fonticon.
+ *
opacity: number from 〈0,1〉range, representing node opacity
+ *
utilization: number from〈0,100〉range, representing node utilization percentage
+ *
+ * @param {array} edges array of objects. Each object represents one edge between two nodes. Source and target are mandatory attributes.
+ *
+ *
source: id of source node
+ *
target: id of target node
+ *
lineStyle: stroke style of edge; currently only 'dashed' is avaliable
+ *
title: label of edge
+ *
+ *
+ * @param {boolean=} show-node-labels show/hide all node tooltips
+ *
+ * @param {boolean=} show-edge-labels show/hode all edge tooltips
+ *
+ * @param {object=} tooltip-style object used for tooltip styling. This is an optional parameter.
+ *
+ *
size: text size in px
+ *
font: font name. eg: 'Arial'
+ *
textColor: string containing color code (basic, RGB, HEX) of title text.
+ *
background: string containing color code (basic, RGB, HEX) of title background
+ *
+ * @param {function (node) =} select-node function that return selected(clicked) node from graph
+ * @param {function (array) =} multi-select-nodes function that returns array of selected nodes. Multiple nodes are selected while holding the ctrl/shift key and clicking
+ * @param {function (edge) =} select-edge function that return selected(clicked) edge from graph
+ * @param {function (array) =} multi-select-edges function that returns array of selected edges. Multiple edges are selected while holding the ctrl/shift key and clicking
+ *
+ * @description
+ * Component for rendering topology chart on Canvas element. This is just a simple component. It has no searching/filtering or other methods. Will only render given data and return data about selected objects.
+ * Component also supports semantic zooming. Only distance between nodes is growing/shrinking, but node size remains the same. Canvas will zoom around the mouse cursor.
+ * @example
+
+
+
.status - optional status of the node (can be used to differentiate the circle color)
+ *
.kind - the kind of node - this is a general key that needs to be unique for grouping the nodes Filtering and styles use this value as well to correctly select the nodes.
+ *
+ *
+ * @param {object} relations the object containing all of the node relationships:
+ *
+ *
.source - the key of the source node
+ *
.target - the key of the target node
+ *
+ *
+ * @param {object} icons The different icons to be used in the node representations
+ * @param {object} selection The item to be selected
+ * @param {object} force Optional. A D3 force layout to use instead of creating one by default. The force layout size will be updated, and layout will be started as appropriate.
+ * @param {object} nodes The node configuration for the various types of nodes
+ * @param {string} searchText Search text which is watched for changes and highlights the nodes matching the search text
+ * @param {object} kinds The different kinds of nodes represented in the topology chart
+ * @param {function (vertices, added) } chartRendered The argument will be D3 selection of elements that correspond to items. Each item has its data set to one of the items. The default implementation of this event sets the title from Kubernetes metadata and tweaks the look of for certain statuses. Use event.preventDefault() to prevent this default behavior.
+ * @param {boolean} itemSelected A function that is dispatched when an item is selected (along with the node data associated with the function
+ * @param {boolean} showLabels A watched boolean that determines whether or not lables should be displayed beneath the nodes
+ * @param {function (node) } tooltipFunction A passed in tooltip function which can be used to overwrite the default tooltip behavior
+ *
+ * @example
+
+
+
+ * See http://c3js.org/reference.html for a full list of C3 chart options.
+ * See also: {@link patternfly.charts.component:pfSparklineChart}
+ *
+ * @param {object} config configuration settings for the trends chart:
+ *
+ *
.chartId - the unique id of this trends chart
+ *
.title - (optional) title of the Trends chart
+ *
.layout - (optional) the layout and sizes of titles and chart. Values are 'large' (default), 'small', 'compact', and 'inline'
+ *
.compactLabelPosition - (optional) the trend label positioning when the layout value is 'compact'. Values are 'left' (default) or 'right'
+ *
.trendLabel - (optional) the trend label used in the 'inline' layout
+ *
.timeFrame - (optional) the time frame for the data in the pfSparklineChart, ex: 'Last 30 Days'
+ *
.units - unit label for values, ex: 'MHz','GB', etc..
+ *
.valueType - (optional) the format of the latest data point which is shown in the title. Values are 'actual'(default) or 'percentage'
+ *
+ *
+ * @param {object} chartData the data to be shown in the sparkline charts
+ *
+ *
.total - number representing the total amount
+ *
.xData - Array, X values for the data points, first element must be the name of the data
+ *
.yData - Array, Y Values for the data points, first element must be the name of the data
+ *
.dataAvailable - Flag if there is data available - default: true
+ *
+ *
+ * @param {int=} chartHeight height of the sparkline chart
+ * @param {boolean=} showXAxis override sparkline config settings for showing the X Axis
+ * @param {boolean=} showYAxis override sparkline config settings for showing the Y Axis
+ * @example
+
+
+
When no thresholds exist, or if the used percentage has not surpassed any thresholds, the indicator is blue.
+ *
When the used percentage has surpassed the warning threshold, but not the error threshold, the indicator is orange.
+ *
When the used percentage has surpassed the error threshold, the indicator is is red.
+ *
+ *
+ * @param {object} chartData the data to be shown in the utilization bar chart
+ *
+ *
.used - number representing the amount used
+ *
.total - number representing the total amount
+ *
.dataAvailable - Flag if there is data available - default: true
+ *
+ *
+ * @param {object=} chart-title The title displayed on the left-hand side of the chart
+ * @param {object=} chart-footer The label displayed on the right-hand side of the chart. If chart-footer is not
+ * specified, the automatic footer-label-format will be used.
+ * @param {object=} layout Various alternative layouts the utilization bar chart may have:
+ *
+ *
.type - The type of layout to use. Valid values are 'regular' (default) displays the standard chart layout,
+ * and 'inline' displays a smaller, inline layout.
+ *
.titleLabelWidth - Width of the left-hand title label when using 'inline' layout. Example values are "120px", "20%", "10em", etc..
+ *
.footerLabelWidth - Width of the right-hand used label when using 'inline' layout. Example values are "120px", "20%", "10em", etc..
+ *
+ * @param {string=} footer-label-format The auto-format of the label on the right side of the bar chart when chart-footer
+ * has not been specified. Values may be:
+ *
+ *
'actual' - (default) displays the standard label of '(n) of (m) (units) Used'.
+ *
'percent' - displays a percentage label of '(n)% Used'.
+ *
+ * @param {object=} units to be displayed on the chart. Examples: "GB", "MHz", "I/Ops", etc...
+ * @param {string=} threshold-error The percentage used, when reached, denotes an error. Valid values are 1-100. When the error threshold
+ * has been reached, the used donut arc will be red.
+ * @param {string=} threshold-warning The percentage usage, when reached, denotes a warning. Valid values are 1-100. When the warning threshold
+ * has been reached, the used donut arc will be orange.
+ * @param {function(items)} avaliableTooltipFunction A passed in tooltip function which can be used to overwrite the default available tooltip behavior
+ * @param {function(items)} usedTooltipFunction A passed in tooltip function which can be used to overwrite the default usedtooltip behavior
+ *
+ * @example
+
+
+
';
+ };
+ });
+
+
+*/
+
+angular.module('patternfly.charts').component('pfUtilizationBarChart', {
+ bindings: {
+ chartData: '=',
+ chartTitle: '=',
+ chartFooter: '=',
+ units: '=',
+ thresholdError: '=?',
+ thresholdWarning: '=?',
+ footerLabelFormat: '@?',
+ layout: '=?',
+ usedTooltipFunction: '&?',
+ availableTooltipFunction: '&?'
+ },
+
+ templateUrl: 'charts/utilization-bar/utilization-bar-chart.html',
+ controller: ["$timeout", function ($timeout) {
+ 'use strict';
+ var ctrl = this, prevChartData, prevLayout;
+
+ ctrl.updateAll = function () {
+ // Need to deep watch changes
+ prevChartData = angular.copy(ctrl.chartData);
+ prevLayout = angular.copy(ctrl.layout);
+
+ if (!ctrl.chartData) {
+ return;
+ }
+
+ //Calculate the percentage used
+ if (!isNaN(ctrl.chartData.used) && !isNaN(ctrl.chartData.total) && (ctrl.chartData.total > 0)) {
+ ctrl.chartData.percentageUsed = Math.round(100 * (ctrl.chartData.used / ctrl.chartData.total));
+ } else {
+ ctrl.chartData.percentageUsed = 0;
+ }
+
+ if (ctrl.thresholdError || ctrl.thresholdWarning) {
+ ctrl.isError = (ctrl.chartData.percentageUsed >= ctrl.thresholdError);
+ ctrl.isWarn = (ctrl.chartData.percentageUsed >= ctrl.thresholdWarning &&
+ ctrl.chartData.percentageUsed < ctrl.thresholdError);
+ ctrl.isOk = (ctrl.chartData.percentageUsed < ctrl.thresholdWarning);
+ }
+
+ //Animate in the chart load.
+ ctrl.animate = true;
+ $timeout(function () {
+ ctrl.animate = false;
+ }, 0);
+ };
+
+ ctrl.$onChanges = function (changesObj) {
+ ctrl.updateAll();
+ };
+
+ ctrl.$doCheck = function () {
+ // do a deep compare on chartData and layout
+ if (!angular.equals(ctrl.chartData, prevChartData) || !angular.equals(ctrl.layout, prevLayout)) {
+ ctrl.updateAll();
+ }
+ };
+
+ ctrl.usedTooltipMessage = function () {
+ return ctrl.usedTooltipFunction ? ctrl.usedTooltipFunction() : _.get(ctrl.chartData, 'percentageUsed', 'N/A') + '% Used';
+ };
+
+ ctrl.availableTooltipMessage = function () {
+ return ctrl.availableTooltipFunction ? ctrl.availableTooltipFunction() : (100 - _.get(ctrl.chartData, 'percentageUsed', 0)) + '% Available';
+ };
+ }]
+});
+;/**
+ * @ngdoc directive
+ * @name patternfly.charts.directive:pfUtilizationTrendChart
+ * @restrict E
+ *
+ * @description
+ * Component for rendering a utilization trend chart. The utilization trend chart combines overall
+ * data with a pfDonutPctChart and a pfSparklineChart. Add the options for the pfDonutChart via
+ * the donutConfig parameter. Add the options for the pfSparklineChart via the sparklineConfig
+ * parameter.
+ *
+ * See http://c3js.org/reference.html for a full list of C3 chart options.
+ *
+ * @param {object} config configuration settings for the utilization trend chart:
+ *
+ *
.title - title of the Utilization chart
+ *
.units - unit label for values, ex: 'MHz','GB', etc..
+ *
+ *
+ * @param {object} donutConfig configuration settings for the donut pct chart, see pfDonutPctChart for specifics
+ * @param {object} sparklineConfig configuration settings for the sparkline chart, see pfSparklineChart for specifics
+ *
+ * @param {object} chartData the data to be shown in the donut and sparkline charts
+ *
+ *
.used - number representing the amount used
+ *
.total - number representing the total amount
+ *
.xData - Array, X values for the data points, first element must be the name of the data
+ *
.yData - Array, Y Values for the data points, first element must be the name of the data
+ *
.dataAvailable - Flag if there is data available - default: true
+ *
+ *
+ * @param {string=} donutCenterLabel specifies the contents of the donut's center label.
+ * Values:
+ *
+ *
'used' - displays the Used amount in the center label (default)
+ *
'available' - displays the Available amount in the center label
+ *
'percent' - displays the Usage Percent of the Total amount in the center label
+ *
'none' - does not display the center label
+ *
+ * @param {int=} sparklineChartHeight height of the sparkline chart
+ * @param {boolean=} showSparklineXAxis override sparkline config settings for showing the X Axis
+ * @param {boolean=} showSparklineYAxis override sparkline config settings for showing the Y Axis
+
+ * @example
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ angular.module( 'patternfly.charts' ).controller( 'ChartCtrl', function( $scope ) {
+ $scope.config = {
+ title: 'Memory',
+ units: 'GB'
+ };
+ $scope.donutConfig = {
+ chartId: 'chartA',
+ thresholds: {'warning':'60','error':'90'}
+ };
+ $scope.sparklineConfig = {
+ 'chartId': 'exampleSparkline',
+ 'tooltipType': 'default',
+ 'units': 'GB'
+ };
+
+ var today = new Date();
+ var dates = ['dates'];
+ for (var d = 20 - 1; d >= 0; d--) {
+ dates.push(new Date(today.getTime() - (d * 24 * 60 * 60 * 1000)));
+ }
+
+ $scope.data = {
+ dataAvailable: true,
+ used: 76,
+ total: 100,
+ xData: dates,
+ yData: ['used', '10', '20', '30', '20', '30', '10', '14', '20', '25', '68', '54', '56', '78', '56', '67', '88', '76', '65', '87', '76']
+ };
+
+ $scope.centerLabel = 'used';
+
+ $scope.custShowXAxis = false;
+ $scope.custShowYAxis = false;
+ $scope.custChartHeight = 60;
+
+ $scope.addDataPoint = function () {
+ var newData = Math.round(Math.random() * 100);
+ var newDate = new Date($scope.data.xData[$scope.data.xData.length - 1].getTime() + (24 * 60 * 60 * 1000));
+
+ $scope.data.used = newData;
+ $scope.data.xData.push(newDate);
+ $scope.data.yData.push(newData);
+ };
+ });
+
+
+ */
+angular.module('patternfly.charts').component('pfUtilizationTrendChart', {
+ bindings: {
+ chartData: '<',
+ config: '<',
+ centerLabel: '',
+ donutConfig: '<',
+ sparklineConfig: '<',
+ sparklineChartHeight: '',
+ showSparklineXAxis: '',
+ showSparklineYAxis: ''
+ },
+ templateUrl: 'charts/utilization-trend/utilization-trend-chart.html',
+ controller: ["pfUtils", function (pfUtils) {
+ 'use strict';
+ var ctrl = this, prevChartData, prevConfig;
+
+ ctrl.updateAll = function () {
+ // Need to deep watch changes
+ prevChartData = angular.copy(ctrl.chartData);
+ prevConfig = angular.copy(ctrl.config);
+
+ if (ctrl.centerLabel === undefined) {
+ ctrl.centerLabel = 'used';
+
+ }
+
+ if (ctrl.donutConfig.units === undefined) {
+ ctrl.donutConfig.units = ctrl.config.units;
+ }
+
+ if (ctrl.chartData.available === undefined) {
+ ctrl.chartData.available = ctrl.chartData.total - ctrl.chartData.used;
+ }
+
+ ctrl.config.units = ctrl.config.units || ctrl.units;
+
+ if (ctrl.centerLabel === 'available') {
+ ctrl.currentValue = ctrl.chartData.used;
+ ctrl.currentText = 'Used';
+ } else {
+ ctrl.currentValue = ctrl.chartData.total - ctrl.chartData.used;
+ ctrl.currentText = 'Available';
+ }
+ };
+
+ ctrl.$onChanges = function (changesObj) {
+ ctrl.updateAll();
+ };
+
+ ctrl.$doCheck = function () {
+ // do a deep compare on chartData and config
+ if (!angular.equals(ctrl.chartData, prevChartData) || !angular.equals(ctrl.config, prevConfig)) {
+ ctrl.updateAll();
+ }
+ };
+ }]
+});
+;angular.module('patternfly.datepicker').component('pfBootstrapDatepicker', {
+ bindings: {
+ date: '<',
+ format: '@?',
+ dateOptions: '',
+ isOpen: '',
+ popupPlacement: '@?'
+ },
+ templateUrl: 'datepicker/datepicker.html',
+ controller: function () {
+ 'use strict';
+
+ var ctrl = this;
+
+ ctrl.defaultDateOptions = {
+ showWeeks : false,
+ formatDay : "d"
+ };
+ ctrl.defaultIsOpen = false;
+
+ ctrl.$onInit = function () {
+ ctrl.format = "MM/dd/yyyy";
+ ctrl.showButtonBar = true;
+ ctrl.popupPlacement = "auto bottom-left";
+
+ if (angular.isUndefined(ctrl.dateOptions)) {
+ ctrl.dateOptions = {};
+ }
+ _.defaults(ctrl.dateOptions, ctrl.defaultDateOptions);
+ _.defaults(ctrl.isOpen, ctrl.defaultIsOpen);
+ };
+
+ ctrl.$onChanges = function (changes) {
+ _.defaults(ctrl.isOpen, ctrl.defaultIsOpen);
+ };
+
+ }
+});
+;/**
+ * @ngdoc directive
+ * @name patternfly.datepicker.componenet:pfBootstrapDatepicker
+ * @element pf-bootstrap-datepicker
+ *
+ * @param {date} date Must be a Javascript Date - to be displayed in the input. Can be left empty.
+ * @param {string} format Optional date format for displayed dates ('MM/dd/yyyy' by default).
+ * @param {boolean} isOpen Optional boolean for determining whether or not to have the datepicker default to open (false by default).
+ * @param {string} popupPlacement Optional configuration string used to position the popup datepicker relative to the input element. See {@link https://angular-ui.github.io/bootstrap/#datepickerPopup Angular UI Datepicker Popup}.
+ * @param {object} dateOptions Optional uib-datepicker configuration object. See {@link https://angular-ui.github.io/bootstrap/#datepicker Angular UI Datepicker}.
+ *
+ * @description
+ * A wrapper for the Angular UI {@link http://angular-ui.github.io/bootstrap/#!#datepickerPopup datepicker}.
+ *
+ * @example
+
+
+
+
+
+
+
+
+
+
+
+
+ angular.module('patternfly.datepicker').controller('DemoBootstrapDatepicker', function( $scope ) {
+
+ // first datepicker
+ $scope.date = new Date("Jan 1, 2000");
+
+ // second datepicker
+ $scope.format1 = "MM/dd/yy";
+ $scope.dateOptions = {
+ showWeeks : true
+ };
+ $scope.isOpen = true;
+ $scope.popupPlacement = "bottom-left";
+ });
+
+
+
+ */
+;/**
+ * @ngdoc directive
+ * @name patternfly.filters.component:pfFilterPanel
+ * @restrict E
+ *
+ * @description
+ * The Filter Panel is opened and closed by clicking on the Filter button. It can contain any HTML desired by
+ * the application developer. As such, the application developer is repsonsible for constructing the appliedFilters array which is passed to
+ * the filter results tags.
+ * The application developer is responsible for filtering items based on the appliedFilters array; both when a
+ * filter is changed on the panel, or when a filter tag is 'cleared' (by user clicking on 'x' in the filter results tag).
+ *
+ *
+ * @param {object} config configuration settings for the filters:
+ *
+ *
.appliedFilters - (Array) List of the currently applied filters. Used to render the filter results tags and returned
+ * in the onFilterChange function where it can be used to filter a set of items.
+ *
+ *
.id - (String) Id for the filter, useful for comparisons
+ *
.title - (String) The title to display for the filter results tag
+ *
.values - (Array) The value(s) to display for the filter results tag. Ie. [title: [value1 x] [value2 x]]
+ *
+ *
.resultsCount - (int) The number of results returned after the current applied filters have been applied
+ *
.totalCount - (int) The total number of items before any filters have been applied. The 'm' in the label: 'n' of 'm'
+ *
.resultsLabel - (String) Optional label for the result units. Default is "Results". Ex: "'n' of 'm' Results"
+ *
.onFilterChange - ( function(appliedFilters, changedFilterId, changedFilterValue) ) Function to call when the applied
+ * filters list changes. Triggered by user clicking on 'x' or 'Clear All Filters' in the filter result tags.
+ * changedFilterId and changedFilterValue are returned after user clicks on an 'x' in a tag to
+ * denote which filter and filter value was cleared. changedFilterId and changedFilterValue are
+ * not returned when 'Clear All Filters' link is clicked.
+ *
+ *
+ * @param {object} config configuration settings for the filters:
+ *
+ *
.fields - (Array) List of filterable fields containing:
+ *
+ *
.id - (String) Optional unique Id for the filter field, useful for comparisons
+ *
.title - (String) The title to display for the filter field
+ *
.placeholder - (String) Text to display when no filter value has been entered
+ *
.filterMultiselect - (Boolean) In `complex-select`, allow selection of multiple categories and values. Optional, default is `false`
+ *
.filterType - (String) The filter input field type (any html input type, or 'select' for a single select box or 'complex-select' for a category select box)
+ *
.filterValues - (Array) List of valid select values used when filterType is 'select' or 'complex-select' (in where these values serve as case insensitve keys for .filterCategories objects)
+ *
.filterCategories - (Array of (Objects)) For 'complex-select' only, array of objects whoes keys (case insensitive) match the .filterValues, these objects include each of the filter fields above (sans .placeholder)
+ *
.filterCategoriesPlaceholder - (String) Text to display in `complex-select` category value select when no filter value has been entered, Optional
+ *
.filterDelimiter - (String) Delimiter separating 'complex-select' category and value. Optional, default is a space, ' '
+ *
+ *
.inlineResults - (Boolean) Flag to show results inline with the filter selection (default: false)
+ *
.appliedFilters - (Array) List of the currently applied filters
+ *
.resultsCount - (int) The number of results returned after the current applied filters have been applied
+ *
.totalCount - (int) The total number of items before any filters have been applied. The 'm' in the label: 'n' of 'm' selected
+ *
.showTotalCountResults - (Boolean) Optional, flag to show the total count in the filter results as well (ie. 'n' of 'm' Results)
+ *
.itemsLabel - (String) Optional label to use for the items in the results count (default: Result)
+ *
.itemsLabelPlural - (String) Optional label to use for the items in the resuults count when plural (default: Results)
+ *
.onFilterChange - ( function(array of filters) ) Function to call when the applied filters list changes
+ *
+ *
+ * @param {object} config configuration settings for the filter panel results:
+ *
+ *
.appliedFilters - (Array) List of the currently applied filters. Used to render the filter results tags and returned
+ * in the onFilterChange function where it can be used to filter a set of items.
+ *
+ *
.id - (String) Id for the filter, useful for comparisons
+ *
.title - (String) The title to display for the filter results tag
+ *
.values - (Array) The value(s) to display for the filter results tag. Ie. [title: [value1 x] [value2 x]]
+ *
+ *
.resultsCount - (int) The number of results returned after the current applied filters have been applied
+ *
.totalCount - (int) The total number of items before any filters have been applied. The 'm' in the label: 'n' of 'm'
+ *
.resultsLabel - (String) Optional label for the result units. Default is "Results". Ex: "'n' of 'm' Results"
+ *
.onFilterChange - ( function(appliedFilters, changedFilterId, changedFilterValue) ) Function to call when the applied
+ * filters list changes. Triggered by user clicking on 'x' or 'Clear All Filters' in the filter result tags.
+ * changedFilterId and changedFilterValue are returned after user clicks on an 'x' in a tag to
+ * denote which filter and filter value was cleared. changedFilterId and changedFilterValue are
+ * not returned when 'Clear All Filters' link is clicked.
+ *
+ *
+ * @param {object} config configuration settings for the filters:
+ *
+ *
.fields - (Array) List of filterable fields containing:
+ *
+ *
.id - (String) Optional unique Id for the filter field, useful for comparisons
+ *
.title - (String) The title to display for the filter field
+ *
.placeholder - (String) Text to display when no filter value has been entered
+ *
.filterMultiselect - (Boolean) In `complex-select`, allow selection of multiple categories and values. Optional, default is `false`
+ *
.filterType - (String) The filter input field type (any html input type, or 'select' for a single select box or 'complex-select' for a category select box)
+ *
.filterValues - (Array) List of valid select values used when filterType is 'select' or 'complex-select' (in where these values serve as case insensitve keys for .filterCategories objects)
+ *
.filterCategories - (Array of (Objects)) For 'complex-select' only, array of objects whoes keys (case insensitive) match the .filterValues, these objects include each of the filter fields above (sans .placeholder)
+ *
.filterCategoriesPlaceholder - (String) Text to display in `complex-select` category value select when no filter value has been entered, Optional
+ *
.filterDelimiter - (String) Delimiter separating 'complex-select' category and value. Optional, default is a space, ' '
+ *
+ *
.appliedFilters - (Array) List of the currently applied filters
+ *