UNPKG

@domoinc/multiline-chart

Version:

MultiLineChart - Domo Widget

376 lines (320 loc) 13.7 kB
var d3 = require('d3'); var d3Chart = require('d3.chart'); //---------------------------------------------------------------------------------- //---------------------------------------------------------------------------------- // ${1:chartName}: // This is where you can give some high level documentation of your widget. //---------------------------------------------------------------------------------- //---------------------------------------------------------------------------------- module.exports = d3Chart("Notifier", { //********************************************************************************** // Anything in the initialization method will only run once. // i.e. It will not be run every time you call draw. //********************************************************************************** initialize: function () { // Make the chart constructor accessible to all other methods. var _Chart = this; //---------------------------------------------------------------------------------- // Default Values for getter/setters: // Set the default values of your Getter/Setter functions. //---------------------------------------------------------------------------------- _Chart._showMessage = false; _Chart._warningMessages = []; _Chart._failMessages = []; _Chart._noDataMessages = []; _Chart._sampleDataMessages = []; _Chart._discardedValidDataMessages = []; this._config = { height: { description: 'Height of the chart.', value: 100, type: 'number' }, width: { description: 'Width of the chart.', value: 100, type: 'number' }, chartName: { description: 'Name of chart for Reporting.', value: 'VerticalBarCapacityGaugeChart', type: 'string' } }; /*---------------------------------------------------------------------------------- // Static ----------------------------------------------------------------------------------*/ var _iconLayer = _Chart.base.append("g"); _Chart._txtDiscardedValidDataMessage = _Chart.base.append('text') .attr('y', -3) .style({ 'font-family': 'Open Sans', 'font-size': '11px', 'fill': '#8A8D8E', 'opacity': 0 }); /*---------------------------------------------------------------------------------- // DRAW ----------------------------------------------------------------------------------*/ _Chart.transform = function () { var allMessages = {}; allMessages.warningMessages = _Chart._warningMessages; allMessages.failMessages = _Chart._failMessages; allMessages.noDataMessages = _Chart._noDataMessages; allMessages.sampleDataMessages = _Chart._sampleDataMessages; allMessages.discardedValidDataMessages = _Chart._discardedValidDataMessages; _Chart.trigger("notify", allMessages); var label = ""; if (allMessages.warningMessages.length > 0) { console.warn("WARN", allMessages.warningMessages); } if (allMessages.noDataMessages.length > 0) { label = "No Data"; } if (allMessages.sampleDataMessages.length > 0) { label = "Sample Data"; } if (allMessages.failMessages.length > 0) { label = allMessages.failMessages[0];} drawDiscardedValidDataMessages(label, allMessages); return (_Chart.showMessage() && label !== "" ? [label] : []); }; //********************************************************************************** //********************************************************************************** function drawDiscardedValidDataMessages(currentLabel, allMessages) { if (currentLabel === '' && allMessages.discardedValidDataMessages.length > 0) { _Chart._txtDiscardedValidDataMessage .text('Not all data is shown.'); _Chart._txtDiscardedValidDataMessage .transition() .style('opacity', 1); } else { _Chart._txtDiscardedValidDataMessage.transition().style('opacity', 0); } } //---------------------------------------------------------------------------------- // Layers: This is where you'll place your layers. //---------------------------------------------------------------------------------- //********************************************************************************** //********************************************************************************** _Chart.layer("layer", _iconLayer, { //********************************************************************************** //********************************************************************************** dataBind: function (data) { return this.selectAll("g.icon").data(data); /*TODO nothing yet*/ }, //********************************************************************************** //********************************************************************************** insert: function () { return this.append("g").attr("class", "icon");}, //---------------------------------------------------------------------------------- // Element Life Cycle Events //---------------------------------------------------------------------------------- events: { //********************************************************************************** //********************************************************************************** "enter": function () { this.append("rect") .attr({ "class": "whitebox" }) .style({ "pointer-events": "all", "fill": "#FFFFFF", "opacity": 0.80 }); this.append("path") .attr({ "class": "background", "d": "M0,16c8.8,0,16-7.2,16-16S8.8-16,0-16S-16-8.8-16,0 S-8.8,16,0,16L0,16z" }) .style({ "fill": "#8A8D8F", "opacity": 0.50 }); this.append("path") .attr({ "class": "bang", "d": "M0.7,2.9h-1.5L-2.5-7.8c-0.2-1.3,0.7-2.4,2.1-2.4h0.9c1.4,0,2.3,1.1,2.1,2.4L0.7,2.9L0.7,2.9z M0,11c1.3,0,2.8-1.5,2.8-2.8S1.3,5.4,0,5.4s-2.8,1.5-2.8,2.8S-1.3,11,0,11L0,11z" }) .style({ "fill": "#FFFFFF" }); this.append("text") .attr({ "class": "label", "pointer-events": "none", "y": 35 }) .style({ "font-size": '14px', "text-anchor": "middle", "stroke": "none", "fill": "#8A8D8E", "opacity": 0.50 }); return this; }, //********************************************************************************** // This is the selection returned from the dataBind method. It's the selection // that contains all (existing and newly bound) elements. //********************************************************************************** "merge": function () { this.select("rect.whitebox") .attr({ "width": _Chart.config('width'), "height": _Chart.config('height') }); this.select("path.background") .attr("transform", "translate(" + (_Chart.width() / 2) + "," + (_Chart.height() / 2 - 15) + ")"); this.select("path.bang") .attr("transform", "translate(" + (_Chart.width() / 2) + "," + (_Chart.height() / 2 - 15) + ")"); this.select("text.label") .attr("transform", "translate(" + (_Chart.width() / 2) + "," + (_Chart.height() / 2 - 15) + ")") .text(function (d) { return d }); return this; }, //********************************************************************************** // The 'this' context is the exit() selection. //********************************************************************************** "exit": function () { return this.remove(); } } }); //---------------------------------------------------------------------------------- // Helper Functions will go here. //---------------------------------------------------------------------------------- }, //---------------------------------------------------------------------------------- // Public Functions: Getters and Setters will go here. // ** Please document them! ** //---------------------------------------------------------------------------------- //********************************************************************************** // (Number or Function) You can set the width of the entire the widget. //********************************************************************************** width: function (_) { if (arguments.length === 0) { return (typeof this.config('width') === 'function') ? this.config('width')() : this.config('width'); } this.config('width', _); return this; }, //********************************************************************************** // (Number or Function) You can set the height of the entire the widget. //********************************************************************************** height: function (_) { if (arguments.length === 0) { return (typeof this.config('height') === 'function') ? this.config('height')() : this.config('height'); } this.config('height', _); return this; }, //********************************************************************************** // (Boolean or Function) showMessage //********************************************************************************** showMessage: function (_) { if (arguments.length === 0) { return (typeof this._showMessage === 'function') ? this._showMessage() : this._showMessage; } this._showMessage = _; return this; }, //********************************************************************************** // appendMessage //********************************************************************************** appendMessage: function (chartName, type, message, expectedDataFormat, data) { var msg = {}; msg.chartName = chartName; msg.type = type; msg.message = message; msg.expectedDataFormat = expectedDataFormat; msg.data = data; switch (type) { case 'WARN': this._warningMessages.push(message); break; case 'FAIL': this._failMessages.push(message); break; case 'NO_DATA': this._noDataMessages.push(message); break; case 'SAMPLE_DATA': this._sampleDataMessages.push(message); break; case 'DISCARDED_VALID_DATA': this._discardedValidDataMessages.push(message); break; } return this; }, //********************************************************************************** // appendMessages //********************************************************************************** appendMessages: function (messages) { for (var key in messages) { var msgArray = messages[key]; for (var i = 0; i < msgArray.length; i++) { var msg = msgArray[i]; this.appendMessage(msg.chartName, msg.type, msg.message, msg.expectedDataFormat, msg.data); } } }, //********************************************************************************** // clearMessages //********************************************************************************** clearMessages: function () { this.clearDataValidationMessages(); this.clearSampleDataMessages(); return this; }, //********************************************************************************** // clearDataValidationMessages //********************************************************************************** clearDataValidationMessages: function () { this._warningMessages = []; this._failMessages = []; this._noDataMessages = []; this._discardedValidDataMessages = []; }, //********************************************************************************** // clearSampleDataMessages //********************************************************************************** clearSampleDataMessages: function () { this._sampleDataMessages = []; }, //********************************************************************************** // config //********************************************************************************** config: function (item, value) { if (item === undefined) { return this; } else if (value === undefined) { if (typeof item === 'object') { for (var key in item) { if (this._config[key]) { this._config[key].value = item[key]; if (this._config[key].onChange) { this._config[key].onChange.call(this, item[key]); } } else { console.warn(key + " is not a valid config property."); } } return this; } return this._config[item] ? this._config[item].value : undefined; } else { if (this._config[item]) { this._config[item].value = value; if (this._config[item].onChange) { this._config[item].onChange.call(this, value); } } else { console.warn(item + " is not a valid config property."); } } return this; } });