@cryptotaxi247 / netdata-1 / commits / e38f00a98

added d3pie and d3dpie charts; updated d3 to latest v4.12.2

Costa Tsaousis (ktsaou) committed Jan 25, 2018 at 02:04 UTC e38f00a9891ef173a214692f461a7653bff2e0a8
5 files changed +784 -3
web/Makefile.am
+1
@@ -47,6 +47,7 @@ dist_weblib_DATA = \
47 lib/clipboard-polyfill-be05dad.js \
48 lib/c3-0.4.11.min.js \
49 lib/d3-3.5.17.min.js \
50 + lib/d3pie-0.2.1.min.js \
51 lib/dygraph-combined-dd74404.js \
52 lib/dygraph-smooth-plotter-dd74404.js \
53 lib/fontawesome-all-5.0.1.min.js \
web/dashboard.css
+31
@@ -432,6 +432,37 @@ body {
432 height: auto !important;
433 }
434
435 +.d3dpieChart {
436 + border-radius: 5px 5px 0 0;
437 + padding-top: 0px;
438 + margin: 0px auto 0;
439 + height: 100%;
440 + background-color: #fff;
441 +}
442 +.d3dpieChart svg {
443 + width: 100% !important;
444 + height: 100%;
445 +}
446 +.d3dpieChart path.slice {
447 + stroke-width: 2px;
448 +}
449 +.d3dpieChart .slice {
450 + stroke: white;
451 + stroke-width: 2px;
452 +}
453 +.d3dpieChart .slice:hover{
454 + opacity: .5;
455 +}
456 +.d3dpieChart .labels text{
457 + background-color: #333;
458 + width: 200px;
459 +}
460 +.d3dpieChart polyline{
461 + stroke: #333;
462 + stroke-width: 1px;
463 + fill: none;
464 +}
465 +
466 .easyPieChart {
467 position: relative;
468 text-align: center;
web/dashboard.html
+58
@@ -643,6 +643,64 @@ So, to avoid flashing the charts, we destroy and re-create the charts on each up
643 <small>rendered in <span id="time803">X</span> ms</small>
644 </div>
645
646 +
647 + <hr>
648 + <h1>d3pie Charts</h1>
649 +
650 + <div style="width: 33%; display: inline-block;">
651 + <div data-netdata="acquiring.responses_by_errorcode"
652 + data-dimensions="!*.0000|*"
653 + data-append-options="match-ids|unaligned"
654 + data-method="sum"
655 + data-units="trns / hour"
656 + data-update-every="30"
657 + data-host="https://jira.viva.gr/netdata/"
658 + data-chart-library="d3pie"
659 + data-d3pie-pieinnerradius="70%"
660 + data-d3pie-pieouterradius="90%"
661 + data-d3pie-smallsegmentgrouping-value="0.5"
662 + data-d3pie-smallsegmentgrouping-enabled="true"
663 + data-d3pie-labels-inner-hidewhenlessthanpercentage="3"
664 + data-title="Rejected Transactions Reasons"
665 + data-width="100%"
666 + data-height="300px"
667 + data-after="-3600"
668 + data-points="1"
669 + data-decimal-digits="0"
670 + data-dt-element-name="time901"
671 + ></div>
672 + <br/>
673 + <small>rendered in <span id="time901">X</span> ms</small>
674 + </div>
675 +
676 + <div style="width: 33%; display: inline-block;">
677 + <div data-netdata="apps.cpu"
678 + data-chart-library="d3dpie"
679 + data-width="100%"
680 + data-height="250px"
681 + data-after="-60"
682 + data-points="60"
683 + data-debug="false"
684 + data-decimal-digits="0"
685 + data-dt-element-name="time902"
686 + ></div>
687 + <br/>
688 + <small>rendered in <span id="time902">X</span> ms</small>
689 + </div>
690 +
691 + <div style="width: 33%; display: inline-block;">
692 + <div data-netdata="apps.cpu"
693 + data-width="100%"
694 + data-height="300px"
695 + data-after="-60"
696 + data-points="60"
697 + data-debug="false"
698 + data-decimal-digits="0"
699 + data-dt-element-name="time902"
700 + ></div>
701 + <br/>
702 + <small>rendered in <span id="time902">X</span> ms</small>
703 + </div>
704 </div> <!-- 1st container -->
705 </body>
706 </html>
web/dashboard.js
+663 -3
@@ -19,6 +19,10 @@
19 * (default: false) */
20 /*global netdataNoC3 *//* boolean, disable c3 charts
21 * (default: false) */
22 +/*global netdataNoD3pie *//* boolean, disable d3pie charts
23 + * (default: false) */
24 +/*global netdataNoD3dpie *//* boolean, disable d3dpie charts
25 + * (default: false) */
26 /*global netdataNoBootstrap *//* boolean, disable bootstrap - disables help too
27 * (default: false) */
28 /*global netdataDontStart *//* boolean, do not start the thread to process the charts
@@ -160,7 +164,8 @@ var NETDATA = window.NETDATA || {};
164 NETDATA.raphael_js = NETDATA.serverStatic + 'lib/raphael-2.2.4-min.js';
165 NETDATA.c3_js = NETDATA.serverStatic + 'lib/c3-0.4.11.min.js';
166 NETDATA.c3_css = NETDATA.serverStatic + 'css/c3-0.4.11.min.css';
163 - NETDATA.d3_js = NETDATA.serverStatic + 'lib/d3-3.5.17.min.js';
167 + NETDATA.d3pie_js = NETDATA.serverStatic + 'lib/d3pie-0.2.1.min.js';
168 + NETDATA.d3_js = NETDATA.serverStatic + 'lib/d3-4.12.2.min.js';
169 NETDATA.morris_js = NETDATA.serverStatic + 'lib/morris-0.5.1.min.js';
170 NETDATA.morris_css = NETDATA.serverStatic + 'css/morris-0.5.1.css';
171 NETDATA.google_js = 'https://www.google.com/jsapi';
@@ -168,7 +173,7 @@ var NETDATA = window.NETDATA || {};
173 NETDATA.themes = {
174 white: {
175 bootstrap_css: NETDATA.serverStatic + 'css/bootstrap-3.3.7.css',
171 - dashboard_css: NETDATA.serverStatic + 'dashboard.css?v20180120-1',
176 + dashboard_css: NETDATA.serverStatic + 'dashboard.css?v20180124-3',
177 background: '#FFFFFF',
178 foreground: '#000000',
179 grid: '#F0F0F0',
@@ -186,7 +191,7 @@ var NETDATA = window.NETDATA || {};
191 },
192 slate: {
193 bootstrap_css: NETDATA.serverStatic + 'css/bootstrap-slate-flat-3.3.7.css?v20161229-1',
189 - dashboard_css: NETDATA.serverStatic + 'dashboard.slate.css?v20180120-1',
194 + dashboard_css: NETDATA.serverStatic + 'dashboard.slate.css?v20180124-3',
195 background: '#272b30',
196 foreground: '#C8C8C8',
197 grid: '#283236',
@@ -7101,6 +7106,623 @@ var NETDATA = window.NETDATA || {};
7106 return true;
7107 };
7108
7109 + // ----------------------------------------------------------------------------------------------------------------
7110 + // d3pie
7111 +
7112 + NETDATA.d3pieInitialize = function(callback) {
7113 + if(typeof netdataNoD3pie === 'undefined' || !netdataNoD3pie) {
7114 +
7115 + // d3pie requires D3
7116 + if(!NETDATA.chartLibraries.d3.initialized) {
7117 + if(NETDATA.chartLibraries.d3.enabled) {
7118 + NETDATA.d3Initialize(function() {
7119 + NETDATA.d3pieInitialize(callback);
7120 + });
7121 + }
7122 + else {
7123 + NETDATA.chartLibraries.d3pie.enabled = false;
7124 + if(typeof callback === "function")
7125 + return callback();
7126 + }
7127 + }
7128 + else {
7129 + $.ajax({
7130 + url: NETDATA.d3pie_js,
7131 + cache: true,
7132 + dataType: "script",
7133 + xhrFields: { withCredentials: true } // required for the cookie
7134 + })
7135 + .done(function() {
7136 + NETDATA.registerChartLibrary('d3pie', NETDATA.d3pie_js);
7137 + })
7138 + .fail(function() {
7139 + NETDATA.chartLibraries.d3pie.enabled = false;
7140 + NETDATA.error(100, NETDATA.d3pie_js);
7141 + })
7142 + .always(function() {
7143 + if(typeof callback === "function")
7144 + return callback();
7145 + });
7146 + }
7147 + }
7148 + else {
7149 + NETDATA.chartLibraries.d3pie.enabled = false;
7150 + if(typeof callback === "function")
7151 + return callback();
7152 + }
7153 + };
7154 +
7155 + NETDATA.d3pieSetContent = function(state, data, index) {
7156 + state.legendFormatValueDecimalsFromMinMax(
7157 + data.min,
7158 + data.max
7159 + );
7160 +
7161 + var content = [];
7162 + var colors = state.chartColors();
7163 + var len = data.result.labels.length;
7164 + for(var i = 1; i < len ; i++) {
7165 + var label = data.result.labels[i];
7166 + var value = data.result.data[index][label];
7167 + var color = colors[i - 1];
7168 +
7169 + content.push({
7170 + label: label,
7171 + value: value,
7172 + color: color
7173 + });
7174 + }
7175 +
7176 + return content;
7177 + };
7178 +
7179 + NETDATA.d3pieChartUpdate = function(state, data) {
7180 + var content = NETDATA.d3pieSetContent(state, data, 0);
7181 +
7182 + var subtitle = NETDATA.dataAttribute(state.element, 'd3pie-subtitle', state.units_current);
7183 + if(subtitle !== state.d3pie_subtitle) {
7184 + state.d3pie_subtitle = subtitle;
7185 + state.d3pie_instance.updateProp("header.subtitle.text", state.d3pie_subtitle);
7186 + }
7187 +
7188 + state.d3pie_instance.updateProp("data.content", content);
7189 + return true;
7190 + };
7191 +
7192 + NETDATA.d3pieChartCreate = function(state, data) {
7193 +
7194 + state.element_chart.id = 'd3pie-' + state.uuid;
7195 + // console.log('id = ' + state.element_chart.id);
7196 +
7197 + var content = NETDATA.d3pieSetContent(state, data, 0);
7198 + state.d3pie_subtitle = NETDATA.dataAttribute(state.element, 'd3pie-subtitle', state.units_current);
7199 +
7200 + state.d3pie_options = {
7201 + header: {
7202 + title: {
7203 + text: NETDATA.dataAttribute(state.element, 'd3pie-title', state.title),
7204 + color: NETDATA.dataAttribute(state.element, 'd3pie-title-color', "#333333"),
7205 + fontSize: NETDATA.dataAttribute(state.element, 'd3pie-title-fontsize', 14),
7206 + font: NETDATA.dataAttribute(state.element, 'd3pie-title-font', "arial")
7207 + },
7208 + subtitle: {
7209 + text: state.d3pie_subtitle,
7210 + color: NETDATA.dataAttribute(state.element, 'd3pie-subtitle-color', "#666666"),
7211 + fontSize: NETDATA.dataAttribute(state.element, 'd3pie-subtitle-fontsize', 11),
7212 + font: NETDATA.dataAttribute(state.element, 'd3pie-subtitle-font', "arial")
7213 + },
7214 + titleSubtitlePadding: 1
7215 + },
7216 + footer: {
7217 + text: NETDATA.dataAttribute(state.element, 'd3pie-footer', ''),
7218 + color: NETDATA.dataAttribute(state.element, 'd3pie-footer-color', "#999999"),
7219 + fontSize: NETDATA.dataAttribute(state.element, 'd3pie-footer-fontsize', 10),
7220 + font: NETDATA.dataAttribute(state.element, 'd3pie-footer-font', "arial"),
7221 + location: NETDATA.dataAttribute(state.element, 'd3pie-footer-location', "bottom-left")
7222 + },
7223 + size: {
7224 + canvasHeight: state.chartHeight(),
7225 + canvasWidth: state.chartWidth(),
7226 + pieInnerRadius: NETDATA.dataAttribute(state.element, 'd3pie-pieinnerradius', "0%"),
7227 + pieOuterRadius: NETDATA.dataAttribute(state.element, 'd3pie-pieouterradius', "80%")
7228 + },
7229 + data: {
7230 + // none, random, value-asc, value-desc, label-asc, label-desc
7231 + sortOrder: NETDATA.dataAttribute(state.element, 'd3pie-sortorder', "value-desc"),
7232 + smallSegmentGrouping: {
7233 + enabled: NETDATA.dataAttributeBoolean(state.element, "d3pie-smallsegmentgrouping-enabled", true),
7234 + value: NETDATA.dataAttribute(state.element, 'd3pie-smallsegmentgrouping-value', 1),
7235 + // percentage, value
7236 + valueType: NETDATA.dataAttribute(state.element, 'd3pie-smallsegmentgrouping-valuetype', "percentage"),
7237 + label: NETDATA.dataAttribute(state.element, 'd3pie-smallsegmentgrouping-label', "other"),
7238 + color: NETDATA.dataAttribute(state.element, 'd3pie-smallsegmentgrouping-color', "#cccccc")
7239 + },
7240 +
7241 + // REQUIRED! This is where you enter your pie data; it needs to be an array of objects
7242 + // of this form: { label: "label", value: 1.5, color: "#000000" } - color is optional
7243 + content: content
7244 + },
7245 + labels: {
7246 + outer: {
7247 + // label, value, percentage, label-value1, label-value2, label-percentage1, label-percentage2
7248 + format: NETDATA.dataAttribute(state.element, 'd3pie-labels-outer-format', "label-value1"),
7249 + hideWhenLessThanPercentage: NETDATA.dataAttribute(state.element, 'd3pie-labels-outer-hidewhenlessthanpercentage', null),
7250 + pieDistance: 20
7251 + },
7252 + inner: {
7253 + // label, value, percentage, label-value1, label-value2, label-percentage1, label-percentage2
7254 + format: NETDATA.dataAttribute(state.element, 'd3pie-labels-inner-format', "percentage"),
7255 + hideWhenLessThanPercentage: NETDATA.dataAttribute(state.element, 'd3pie-labels-inner-hidewhenlessthanpercentage', null)
7256 + },
7257 + mainLabel: {
7258 + color: NETDATA.dataAttribute(state.element, 'd3pie-labels-mainLabel-color', "#333333"),
7259 + font: NETDATA.dataAttribute(state.element, 'd3pie-labels-mainLabel-font', "arial"),
7260 + fontSize: NETDATA.dataAttribute(state.element, 'd3pie-labels-mainLabel-fontsize', 10)
7261 + },
7262 + percentage: {
7263 + color: NETDATA.dataAttribute(state.element, 'd3pie-labels-percentage-color', "#dddddd"),
7264 + font: NETDATA.dataAttribute(state.element, 'd3pie-labels-percentage-font', "arial"),
7265 + fontSize: NETDATA.dataAttribute(state.element, 'd3pie-labels-percentage-fontsize', 10),
7266 + decimalPlaces: 0
7267 + },
7268 + value: {
7269 + color: NETDATA.dataAttribute(state.element, 'd3pie-labels-value-color', "#cccc44"),
7270 + font: NETDATA.dataAttribute(state.element, 'd3pie-labels-value-font', "arial"),
7271 + fontSize: NETDATA.dataAttribute(state.element, 'd3pie-labels-value-fontsize', 10)
7272 + },
7273 + lines: {
7274 + enabled: NETDATA.dataAttributeBoolean(state.element, 'd3pie-labels-lines-enabled', true),
7275 + style: NETDATA.dataAttribute(state.element, 'd3pie-labels-lines-style', "curved"),
7276 + color: NETDATA.dataAttribute(state.element, 'd3pie-labels-lines-color', "segment") // "segment" or a hex color
7277 + },
7278 + formatter: function(context) {
7279 + // console.log(context);
7280 + if(context.part === 'value')
7281 + return state.legendFormatValue(context.value);
7282 + if(context.part === 'percentage')
7283 + return context.label + '%';
7284 +
7285 + return context.label;
7286 + }
7287 + },
7288 + effects: {
7289 + load: {
7290 + effect: "none", // none / default
7291 + speed: 0
7292 + },
7293 + pullOutSegmentOnClick: {
7294 + effect: "none", // none / linear / bounce / elastic / back
7295 + speed: 300,
7296 + size: 10
7297 + },
7298 + highlightSegmentOnMouseover: false,
7299 + highlightLuminosity: 1
7300 + },
7301 + tooltips: {
7302 + enabled: false,
7303 + type: "placeholder", // caption|placeholder
7304 + string: "",
7305 + placeholderParser: null,
7306 + styles: {
7307 + fadeInSpeed: 250,
7308 + backgroundColor: "#000000",
7309 + backgroundOpacity: 0.5,
7310 + color: "#efefef",
7311 + borderRadius: 2,
7312 + font: "arial",
7313 + fontSize: 10,
7314 + padding: 4
7315 + }
7316 + },
7317 + misc: {
7318 + colors: {
7319 + background: null, // transparent
7320 + // segments: state.chartColors(),
7321 + segmentStroke: NETDATA.dataAttribute(state.element, 'd3pie-misc-colors-segmentstroke', "#ffffff")
7322 + },
7323 + gradient: {
7324 + enabled: NETDATA.dataAttributeBoolean(state.element, 'd3pie-misc-gradient-enabled', false),
7325 + percentage: NETDATA.dataAttribute(state.element, 'd3pie-misc-colors-percentage', 95),
7326 + color: NETDATA.dataAttribute(state.element, 'd3pie-misc-colors-segmentstroke', "#000000")
7327 + },
7328 + canvasPadding: {
7329 + top: 5,
7330 + right: 5,
7331 + bottom: 5,
7332 + left: 5
7333 + },
7334 + pieCenterOffset: {
7335 + x: 0,
7336 + y: 0
7337 + },
7338 + cssPrefix: null
7339 + },
7340 + callbacks: {
7341 + onload: null,
7342 + onMouseoverSegment: null,
7343 + onMouseoutSegment: null,
7344 + onClickSegment: null
7345 + }
7346 + };
7347 +
7348 + state.d3pie_instance = new d3pie(state.element_chart, state.d3pie_options);
7349 +
7350 + // console.log(state.d3pie_instance);
7351 +
7352 + return true;
7353 + };
7354 +
7355 + // ----------------------------------------------------------------------------------------------------------------
7356 + // d3dpie
7357 +
7358 + NETDATA.d3dpieInitialize = function(callback) {
7359 + if(typeof netdataNod3dpie === 'undefined' || !netdataNod3dpie) {
7360 +
7361 + // d3dpie requires D3
7362 + if(!NETDATA.chartLibraries.d3.initialized) {
7363 + if(NETDATA.chartLibraries.d3.enabled) {
7364 + NETDATA.d3Initialize(function() {
7365 + NETDATA.d3dpieInitialize(callback);
7366 + });
7367 + }
7368 + else {
7369 + NETDATA.chartLibraries.d3dpie.enabled = false;
7370 + if(typeof callback === "function")
7371 + return callback();
7372 + }
7373 + }
7374 + else {
7375 + NETDATA.registerChartLibrary('d3dpie', "lib/d3dpie.js");
7376 + if(typeof callback === "function")
7377 + return callback();
7378 + }
7379 + }
7380 + else {
7381 + NETDATA.chartLibraries.d3dpie.enabled = false;
7382 + if(typeof callback === "function")
7383 + return callback();
7384 + }
7385 + };
7386 +
7387 + NETDATA.d3dpieSetContent = function(state, data, index) {
7388 + state.legendFormatValueDecimalsFromMinMax(
7389 + data.min,
7390 + data.max
7391 + );
7392 +
7393 + var content = [];
7394 + var colors = state.chartColors();
7395 + var len = data.result.labels.length;
7396 + var sum = 0;
7397 + for(var i = 1; i < len ; i++) {
7398 + var label = data.result.labels[i];
7399 + var value = data.result.data[index][label];
7400 + var color = colors[i - 1];
7401 +
7402 + sum += value;
7403 +
7404 + content.push({
7405 + label: label,
7406 + value: value,
7407 + color: color
7408 + });
7409 + }
7410 +
7411 + len = content.length;
7412 + for(i = 0; i < len ; i++) {
7413 + content[i].percent = content[i].value * 100 / sum;
7414 + }
7415 +
7416 + return content;
7417 + };
7418 +
7419 + NETDATA.d3dpieChange = function(d3dpie, data, duration) {
7420 + var svg = d3dpie.svg;
7421 + var width = d3dpie.width;
7422 + var height = d3dpie.height;
7423 + var radius = d3dpie.radius;
7424 + var pie = d3dpie.pie;
7425 + var arc = d3dpie.arc;
7426 + var outerArc = d3dpie.outerArc;
7427 + var key = d3dpie.key;
7428 +
7429 + function mergeWithFirstEqualZero(first, second) {
7430 + var secondSet = d3.set();
7431 + second.forEach(function (d) {
7432 + secondSet.add(d.label);
7433 + });
7434 +
7435 + var onlyFirst = first
7436 + .filter(function (d) {
7437 + return !secondSet.has(d.label)
7438 + })
7439 + .map(function (d) {
7440 + return {label: d.label, value: 0};
7441 + });
7442 + return d3.merge([second, onlyFirst])
7443 + .sort(function (a, b) {
7444 + return d3.ascending(a.label, b.label);
7445 + });
7446 + }
7447 +
7448 + var data0 = svg.select(".slices").selectAll("path.slice")
7449 + .data().map(function (d) {
7450 + return d.data
7451 + });
7452 + if (data0.length === 0) data0 = data;
7453 + var was = mergeWithFirstEqualZero(data, data0);
7454 + var is = mergeWithFirstEqualZero(data0, data);
7455 +
7456 + /* ------- SLICE ARCS -------*/
7457 +
7458 + var slice = svg.select(".slices").selectAll("path.slice")
7459 + .data(pie(was), key);
7460 +
7461 + slice.enter()
7462 + .insert("path")
7463 + .attr("class", "slice")
7464 + .style("fill", function (d) {
7465 + return d.data.color;
7466 + })
7467 + .each(function (d) {
7468 + this._current = d;
7469 + });
7470 +
7471 + slice = svg.select(".slices").selectAll("path.slice")
7472 + .data(pie(is), key);
7473 +
7474 + slice
7475 + .transition().duration(duration)
7476 + .attrTween("d", function (d) {
7477 + var interpolate = d3.interpolate(this._current, d);
7478 + var _this = this;
7479 + return function (t) {
7480 + _this._current = interpolate(t);
7481 + return arc(_this._current);
7482 + };
7483 + });
7484 +
7485 + slice = svg.select(".slices").selectAll("path.slice")
7486 + .data(pie(data), key);
7487 +
7488 + slice
7489 + .exit().transition().delay(duration).duration(0)
7490 + .remove();
7491 +
7492 + /* ------- TEXT LABELS -------*/
7493 +
7494 + var text = svg.select(".labels").selectAll("text")
7495 + .data(pie(was), key);
7496 +
7497 + text.enter()
7498 + .append("text")
7499 + .attr("dy", ".35em")
7500 + .style("opacity", 0)
7501 + .text(function (d) {
7502 + return d.data.label;
7503 + })
7504 + .each(function (d) {
7505 + this._current = d;
7506 + });
7507 +
7508 + function midAngle(d) {
7509 + return d.startAngle + (d.endAngle - d.startAngle) / 2;
7510 + }
7511 +
7512 + var slotsLeft = {}, slotsRight = {};
7513 + var setLeft = {}, setRight = {};
7514 + var fontSize = 14;
7515 +
7516 + function verticalAlign(d, pos) {
7517 + if(d.data.value === 0)
7518 + return;
7519 +
7520 + var slots = (pos[0] < 0)?slotsLeft:slotsRight;
7521 + var set = (pos[0] < 0)?setLeft:setRight;
7522 +
7523 + if(typeof(set[d.data.label]) !== 'undefined') {
7524 + pos[1] = set[d.data.label];
7525 + return;
7526 + }
7527 +
7528 + var y = Math.round(pos[1]);
7529 + y -= y % fontSize;
7530 + var idx = Math.round(y / fontSize);
7531 +
7532 + for(var i = 0; i < 10 ;i++) {
7533 + if (typeof(slots[idx + i]) === 'undefined') {
7534 + //console.log(d.data.label + ': x = ' + pos[0].toString() + ', y = ' + y.toString() + ', idx = ' + idx.toString() + ', found i = ', i.toString() + ', new y = ' + ((idx + i) * fontSize).toString());
7535 + slots[idx + i] = 1;
7536 + y = (idx + i) * fontSize;
7537 + break;
7538 + }
7539 + else if (typeof(slots[idx - i]) === 'undefined') {
7540 + //console.log(d.data.label + ': x = ' + pos[0].toString() + ', y = ' + y.toString() + ', idx = ' + idx.toString() + ', found i = ', (-i).toString() + ', new y = ' + ((idx - i) * fontSize).toString());
7541 + slots[idx - i] = 1;
7542 + y = (idx - i) * fontSize;
7543 + break;
7544 + }
7545 + }
7546 +
7547 + pos[1] = y;
7548 + set[d.data.label] = y;
7549 + }
7550 +
7551 + text = svg.select(".labels").selectAll("text")
7552 + .data(pie(is), key);
7553 +
7554 + text.transition().duration(duration)
7555 + .style("opacity", function (d) {
7556 + return (d.data.value === 0) ? 0 : 1;
7557 + })
7558 + .attrTween("transform", function (d) {
7559 + var interpolate = d3.interpolate(this._current, d);
7560 + var _this = this;
7561 + return function (t) {
7562 + var d2 = interpolate(t);
7563 + _this._current = d2;
7564 + var pos = outerArc.centroid(d2);
7565 + pos[0] = radius * (midAngle(d2) < Math.PI ? 1 : -1);
7566 + verticalAlign(d2, pos);
7567 + return "translate(" + pos + ")";
7568 + };
7569 + })
7570 + .styleTween("text-anchor", function (d) {
7571 + var interpolate = d3.interpolate(this._current, d);
7572 + return function (t) {
7573 + var d2 = interpolate(t);
7574 + return midAngle(d2) < Math.PI ? "start" : "end";
7575 + };
7576 + });
7577 +
7578 + text = svg.select(".labels").selectAll("text")
7579 + .data(pie(data), key);
7580 +
7581 + text
7582 + .exit().transition().delay(duration)
7583 + .remove();
7584 +
7585 + /* ------- SLICE TO TEXT POLYLINES -------*/
7586 +
7587 + var polyline = svg.select(".lines").selectAll("polyline")
7588 + .data(pie(was), key);
7589 +
7590 + polyline.enter()
7591 + .append("polyline")
7592 + .style("opacity", 0)
7593 + .each(function (d) {
7594 + this._current = d;
7595 + });
7596 +
7597 + polyline = svg.select(".lines").selectAll("polyline")
7598 + .data(pie(is), key);
7599 +
7600 + polyline.transition().duration(duration)
7601 + .style("opacity", function (d) {
7602 + return (d.data.value === 0) ? 0 : 1;
7603 + })
7604 + .attrTween("points", function (d) {
7605 + // this._current = this._current;
7606 + var interpolate = d3.interpolate(this._current, d);
7607 + var _this = this;
7608 + return function (t) {
7609 + var d2 = interpolate(t);
7610 + _this._current = d2;
7611 + var pos = outerArc.centroid(d2);
7612 + pos[0] = radius * 0.95 * (midAngle(d2) < Math.PI ? 1 : -1);
7613 + verticalAlign(d2, pos);
7614 +
7615 + var pos2 = outerArc.centroid(d2);
7616 + verticalAlign(d2, pos2);
7617 + return [arc.centroid(d2), pos2, pos];
7618 + };
7619 + });
7620 +
7621 + polyline = svg.select(".lines").selectAll("polyline")
7622 + .data(pie(data), key);
7623 +
7624 + polyline
7625 + .exit().transition().delay(duration)
7626 + .remove();
7627 + };
7628 +
7629 + NETDATA.d3dpieSetSelection = function(state, t) {
7630 + if(state.timeIsVisible(t) !== true)
7631 + return NETDATA.d3dpieClearSelection(state, true);
7632 +
7633 + var slot = state.calculateRowForTime(t);
7634 + slot = state.data.result.data.length - slot - 1;
7635 +
7636 + if(slot < 0 || slot >= state.data.result.length)
7637 + return NETDATA.d3dpieClearSelection(state, true);
7638 +
7639 + if(state.tmp.d3pie_timer === undefined) {
7640 + state.tmp.d3pie_timer = NETDATA.timeout.set(function() {
7641 + state.tmp.d3pie_timer = undefined;
7642 + NETDATA.d3dpieChange(state.d3dpie_instance, NETDATA.d3dpieSetContent(state, state.data, slot), 0);
7643 + }, 0);
7644 + }
7645 +
7646 + return true;
7647 + };
7648 +
7649 + NETDATA.d3dpieClearSelection = function(state, force) {
7650 + if(typeof state.tmp.d3dpie_timer !== 'undefined') {
7651 + NETDATA.timeout.clear(state.tmp.d3dpie_timer);
7652 + state.tmp.d3dpie_timer = undefined;
7653 + }
7654 +
7655 + if(state.isAutoRefreshable() === true && state.data !== null && force !== true) {
7656 + NETDATA.d3dpieChartUpdate(state, state.data);
7657 + }
7658 + else {
7659 + // FIXME: we should show empty chart here
7660 + NETDATA.d3dpieChange(state.d3dpie_instance, NETDATA.d3dpieSetContent(state, state.data, 0), 0);
7661 + }
7662 +
7663 + return true;
7664 + };
7665 +
7666 + NETDATA.d3dpieChartUpdate = function(state, data) {
7667 + NETDATA.d3dpieChange(state.d3dpie_instance, NETDATA.d3dpieSetContent(state, data, 0), 500);
7668 + return true;
7669 + };
7670 +
7671 + NETDATA.d3dpieChartCreate = function(state, data) {
7672 + state.element_chart.className = 'd3dpieChart';
7673 +
7674 + var svg = d3.select(state.element_chart)
7675 + .append("svg")
7676 + .append("g");
7677 +
7678 + svg.append("g")
7679 + .attr("class", "slices");
7680 +
7681 + svg.append("g")
7682 + .attr("class", "labels");
7683 +
7684 + svg
7685 + .append("g")
7686 + .attr("class", "lines");
7687 +
7688 + var width = state.chartWidth(),
7689 + height = state.chartHeight(),
7690 + radius = Math.min(width,height) / 2;
7691 +
7692 + var pie = d3.pie()
7693 + .sort(null)
7694 + .value(function(d) {
7695 + return d.value;
7696 + });
7697 +
7698 + var arc = d3.arc()
7699 + .outerRadius(radius * 0.9)
7700 + .innerRadius(radius * 0.6);
7701 +
7702 + var outerArc = d3.arc()
7703 + .innerRadius(radius * 0.7)
7704 + .outerRadius(radius * 0.9);
7705 +
7706 + svg.attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");
7707 +
7708 + var key = function(d) { return d.data.label; };
7709 +
7710 + state.d3dpie_instance = {
7711 + svg: svg,
7712 + width: width,
7713 + height: height,
7714 + radius: radius,
7715 + pie: pie,
7716 + arc: arc,
7717 + outerArc: outerArc,
7718 + key: key
7719 + };
7720 +
7721 + NETDATA.d3dpieChange(state.d3dpie_instance, NETDATA.d3dpieSetContent(state, data, 0), 500);
7722 +
7723 + return true;
7724 + };
7725 +
7726 // ----------------------------------------------------------------------------------------------------------------
7727 // D3
7728
@@ -8064,6 +8686,44 @@ var NETDATA = window.NETDATA || {};
8686 pixels_per_point: function(state) { void(state); return 15; },
8687 container_class: function(state) { void(state); return 'netdata-container'; }
8688 },
8689 + "d3pie": {
8690 + initialize: NETDATA.d3pieInitialize,
8691 + create: NETDATA.d3pieChartCreate,
8692 + update: NETDATA.d3pieChartUpdate,
8693 + resize: null,
8694 + setSelection: undefined, // function(state, t) { void(state); return true; },
8695 + clearSelection: undefined, // function(state) { void(state); return true; },
8696 + toolboxPanAndZoom: null,
8697 + initialized: false,
8698 + enabled: true,
8699 + format: function(state) { void(state); return 'json'; },
8700 + options: function(state) { void(state); return 'objectrows|ms'; },
8701 + legend: function(state) { void(state); return null; },
8702 + autoresize: function(state) { void(state); return false; },
8703 + max_updates_to_recreate: function(state) { void(state); return 5000; },
8704 + track_colors: function(state) { void(state); return false; },
8705 + pixels_per_point: function(state) { void(state); return 15; },
8706 + container_class: function(state) { void(state); return 'netdata-container'; }
8707 + },
8708 + "d3dpie": {
8709 + initialize: NETDATA.d3dpieInitialize,
8710 + create: NETDATA.d3dpieChartCreate,
8711 + update: NETDATA.d3dpieChartUpdate,
8712 + resize: null,
8713 + setSelection: NETDATA.d3dpieSetSelection,
8714 + clearSelection: NETDATA.d3dpieClearSelection,
8715 + toolboxPanAndZoom: null,
8716 + initialized: false,
8717 + enabled: true,
8718 + format: function(state) { void(state); return 'json'; },
8719 + options: function(state) { void(state); return 'objectrows|ms'; },
8720 + legend: function(state) { void(state); return null; },
8721 + autoresize: function(state) { void(state); return false; },
8722 + max_updates_to_recreate: function(state) { void(state); return 5000; },
8723 + track_colors: function(state) { void(state); return false; },
8724 + pixels_per_point: function(state) { void(state); return 15; },
8725 + container_class: function(state) { void(state); return 'netdata-container'; }
8726 + },
8727 "d3": {
8728 initialize: NETDATA.d3Initialize,
8729 create: NETDATA.d3ChartCreate,
web/dashboard.slate.css
+31
@@ -450,6 +450,37 @@ code {
450 height: auto !important;
451 }
452
453 +.d3dpieChart {
454 + border-radius: 5px 5px 0 0;
455 + padding-top: 0px;
456 + margin: 0px auto 0;
457 + height: 100%;
458 + background-color: #fff;
459 +}
460 +.d3dpieChart svg {
461 + width: 100% !important;
462 + height: 100%;
463 +}
464 +.d3dpieChart path.slice {
465 + stroke-width: 2px;
466 +}
467 +.d3dpieChart .slice {
468 + stroke: white;
469 + stroke-width: 2px;
470 +}
471 +.d3dpieChart .slice:hover{
472 + opacity: .5;
473 +}
474 +.d3dpieChart .labels text{
475 + background-color: #333;
476 + width: 200px;
477 +}
478 +.d3dpieChart polyline{
479 + stroke: #333;
480 + stroke-width: 1px;
481 + fill: none;
482 +}
483 +
484 .easyPieChart {
485 position: relative;
486 text-align: center;