import processStructure from '@devoinc/applications-data-library/structures/series';
import objects from '@devoinc/applications-builder/utils/objects';
import highchartsHelper from './helpers/highchartsHelper';
import downloads from '@devoinc/applications-builder/libs/downloads';
import HCP from '@devoinc/applications-builder/widgets/helpers/exportDataSeries';
import { __ } from '@devoinc/applications-builder/i18n';
import widgetFactory from '@devoinc/applications-builder/widgetFactory';
import dependencies from '../data/dependencies';
const LineWidget = dependencies.require('widgets').LineWidget;
/**
* Here all the methods of the widgets based on the
* [Highchart]{@link https://www.highcharts.com/} library are available.
* Most of them are widgets based on the representation of temporal data.
*
* The list of widgets that use these same methods is:
* - [Area](module-area.html)
* - [Column](module-column.html)
* - [Histogram](module-histogram.html)
* - [Lines](module-lines.html)
* - [Stacked Bars](module-stacked-bars.html)
*
* @category Widgets
* @module Series
* @see [base](module-base.html)
* @see [collapser](module-collapser.html)
* @see [dataSearch](module-dataSearch.html)
* @see [download](module-download.html)
* @see [info](module-info.html)
* @see [lifeCycle](module-lifeCycle.html)
* @see [listeners](module-listeners.html)
* @see [loading](module-loading.html)
* @see [menu](module-menu.html)
* @see [screenshot](module-screenshot.html)
* @see [zoom](module-zoom.html)
*/
export function mixin(self) {
HCP.highcharts();
return {
/**
* Set the keys to show.
* @paramĀ {string[]} key - Keys name.
* @instance
*/
setKeys(key) {
self.settings.keyToShow = key;
},
/**
* Set series names to display.
* @param {string[]} series - Series names.
* @instance
*/
setSeriesNames(series) {
self.settings.seriesNames = series;
},
/**
* Set the column with timespamp key.
* @param {string} tsKey - Timestamp column name.
* @instance
*/
setTimestampKey(tsKey) {
self.settings.timestampKey = tsKey;
},
/**
* Set the value to show.
* @param {string} val - Column name with the value.
* @instance
*/
setValue(val) {
self.settings.valToShow = val;
},
/**
* Set the data grouping.
*
* It accepts the moment's get values:
* - <b>date</b>
* - <b>year</b>
* - <b>month</b>
* - <b>day</b>
* - <b>hour</b>
* - <b>minute'</b>
* - <b>second</b>
* - <b>millisecond</b>
* @param {string} grouping - Data grouping.
* @instance
*/
setGrouped(grouping) {
self.settings.groupped = grouping;
},
/**
* Set the Y axis title.
* @param {string} title - Title text.
* @instance
*/
setYAxisTitle(title) {
self.settings.yaxis_title = title;
},
/**
* Set the X axis title.
* @param {string} title - Title text.
* @instance
*/
setXAxisTitle(title) {
self.settings.xaxis_title = title;
},
/**
* Fix the data, if it is true data can not be temporarily grouped
* @param {boolean} bool - Fix the data.
* @instance
*/
setFixedData(bool) {
self.settings.fixData = bool;
},
/**
* Set decimal and thuousands separator.
*
* For example: <i>"##,###,###.00"</i>
* @param {string} str - Format string.
* @instance
*/
setFormat(str) {
self.settings.format = str;
},
/**
* Set the legend visible.
* @param {boolean} bool - Enable the legend.
* @instance
*/
setLegend(bool) {
self.settings.legend = bool;
},
/**
* Set the defautl widget legend format.
*
* The asigned function receives an object with <i>color</i> and
* <i>name</i> values.
* @param {Function} func - Function to set default legend format.
* @instance
*/
setDefaultFormaterLegend(func) {
self.settings.defaultformaterlegend = func;
},
/**
* Set the default tooltip format.
*
* The asigned function receives an object with <i>x</i> and
* <i>y</i> values.
* @param {Function} func - Function to set default tooltip format.
* @instance
*/
setDefaultFormater(func) {
self.settings.defaultformater = func;
},
/**
* Set data accumulation, sum a value with the previous value.
* @param {boolean} bool - Enable the data accumulation.
* @instance
*/
setAccumulated(bool) {
self.settings.accumulated = bool;
},
/**
* Show an average line.
* @param {boolean} bool - Enable the average line.
* @instance
*/
setShowAvgLine(bool) {
self.settings.showAvgLine = bool;
},
/**
* Discard values using a determined method.
*
* The following values are supported:
* - <b>none</b>: Do not apply.
* - <b>stdDev</b>: Discard values using standard deviation.
* @param {String} str - Method to use.
* @instance
*/
setDiscardMethod(str) {
self.settings.discardMethod = str;
},
/**
* Discard values using a determined mode.
*
* The following values are supported:
* - <b>plotBand</b>
* - <b>extremes</b>
* @param {string} str - Mode to use.
* @instance
*/
setDiscardMode(str) {
self.settings.discardMode = str;
},
/**
* Allows add regression series in the chart.
* This function sets <i>fixData</i> to <i>false</i> as a requirement
* to display a regression line.
*
* The following values are supported:
* - <b>none</b>
* - <b>linear</b>
* - <b>exponential</b>
* - <b>polynomial</b>
* - <b>logarithmic</b>
* - <b>loess</b>
* @param {string} str - Regression type.
* @instance
*/
setRegressionLine(str) {
self.settings.regressionLine = str;
self.settings.fixData = false;
},
/**
* Set the Y axis scale.
*
* The following values are supported:
* - <b>none</b>
* - <b>logarithmic</b>
* @param {string} str - Scale type.
* @instance
*/
setYscaleType(str) {
self.settings.yScaleType = str;
},
/**
* Highlights max and min values.
* @param {boolean} bool - Enbale the highlights.
* @instance
*/
setHighlightMaxMin(bool) {
self.settings.highlightMaxMin = bool;
},
/**
* Set the label formatter for the Y axis.
* @param {Function} func - Callback JavaScript function to format the label.
* @instance
*/
setYAxisLabelsFormatter(func) {
objects.set(self.settings, 'widgetTemplate.yAxis.labels.formatter', func);
},
/**
* Set the label formatter for the X axis.
* @param {Function} func -Callback JavaScript function to format the label.
* @instance
*/
setXAxisFormatter(func) {
objects.set(self.settings, 'widgetTemplate.xAxis.labels.formatter', func);
},
/**
* Set the widget start to first element.
* @param {Boolean} bool - Enable to start with the first element.
* @instance
*/
setForceFirstElement(bool) {
self.settings.forceFirstElement = bool;
},
/**
* Set the widget end to last element.
* @param {Boolean} bool - Enable to start with the first element.
* @instance
*/
setForceLastElement(bool) {
self.settings.forceLastElement = bool;
},
/**
* Set the allKeysLimit
* Note: This is not used
* @param {number} [limit=15] - Limit
* @ignore
*/
setAllKeysLimit(limit = 20) {
self.settings.allKeysLimit = limit;
},
/**
* Set the format of the x axis labels.
*
* Avaiable formats are:
* {@link https://api.highcharts.com/highcharts/xAxis.dateTimeLabelFormats}
* @param {Object} obj - Check the Highcharts documentation.
* @instance
*/
setDateTimeLabelFormats(obj) {
objects.set(
self.settings,
'widgetTemplate.xAxis.dateTimeLabelFormats',
obj
);
},
/**
* An array determining what time intervals the ticks are allowed to fall
* on.
* {@link https://api.highcharts.com/highcharts/xAxis.units}
* @param {Array} arr - Check the Highcharts documentation.
* @instance
*/
setXAxisUnits(arr) {
objects.set(self.settings, 'widgetTemplate.xAxis.units', arr);
},
/**
* Set YAxis and values to the bytes format
* @instance
*/
setToBytes() {
objects.set(
self.settings,
'widgetTemplate.yAxis.labels.formatter',
highchartsHelper.axisFormatterByteSize(1, true)
);
objects.set(
self.settings,
'defaultformater',
highchartsHelper.valueFormatterByteSize()
);
},
/**
* Set any settings to the widget.
* For highchart properties use <i>'widgetTemplate'</i> as the base of the path.
* @param {string} path - Path to the settings.
* @param {*} val - Value to set.
* @instance
*/
setProperty(path, val) {
objects.set(self.settings, path, val);
},
/**
* Set the rest of series to a new grouped series called _other_.
* @param {boolean} [bool=false] - Show grouped series.
* @instance
*/
setOthers(bool = false) {
self.settings.others = bool;
},
/**
* Set the number of series to be displayed.
* @param {number} [num=10] - Number of series.
* @instance
*/
setTop(num = 10) {
self.settings.top = num;
},
/**
* Set the aggrupation for the data to add zeros.
* @param {string | Function} string - Text with a unit of time of
* <i>moment.js</i> library or a function that recive a object with
* <i>from</i> and <i>to</i> key date.
* @instance
*/
setGrouping(str = 'days') {
self.settings.grouping = str;
},
/**
* Set the order type for the series.
*
* The following values are supported:
* - <b>alphabetic</b>
* - <b>total</b>
* - Or a function
* @param {string|Function} val - Text with the order type or a
* function to order the series.
* @instance
*/
setSeriesOrder(val = 'alphabetic') {
self.settings.seriesOrder = val;
},
/**
* Set the parser function for the values.
* @param {Function} func - The parser function.
* @instance
*/
setValuesParseFunction(func) {
self.settings.valuesParseFunction = func;
},
/**
* Filter the series by a custom function or using a number
* to limit the number of series to display.
* @param {Function|number} func - Callback function or number to filter.
* the series.
* @instance
*/
setSeriesFilter(func = null) {
self.settings.seriesFilter = func;
},
/**
* Set a custom property available in Highchart for the chart.
* @param {Object[]} props - Array the properties.
* @instance
*/
setSeriesProperties(props) {
self.settings.seriesProperties = props;
},
// Common
// -------------------------------------------------------------------------
/**
* Download in CSV format
* @ignore
*/
downloadCSV() {
let s = self.widget.chart.getCSV();
downloads.downloadCSV(s, `${self.id}-data`);
},
/**
* Redraw function
* @ignore
*/
redraw() {
if (self.widget) {
self.widget.chart.reflow();
}
},
/**
* Resize function
* @ignore
*/
resize() {
this.redraw();
},
// Life Cycle
// -------------------------------------------------------------------------
/**
* Render function
* @param {object} orig - Data for process
* @ignore
*/
render(orig) {
if (!self.el) return; // If not have element not render
// let cfg = Object.assign({}, defaultSettings, self.settings);
let cfg = self.settings;
let data = processStructure(orig, {
keys: cfg.keyToShow || [],
values: cfg.valToShow || [],
seriesNames: cfg.seriesNames || [],
seriesProperties: cfg.seriesProperties || null,
forceFirstElement:
cfg.forceFirstElement == null ? true : cfg.forceFirstElement,
forceLastElement:
cfg.forceLastElement == null ? true : cfg.forceLastElement,
timestampKey: cfg.timestampKey || 'eventdate',
order: cfg.seriesOrder || null,
filter: cfg.seriesFilter || null,
parseFunc: cfg.valuesParseFunction || parseFloat,
zeroFill: cfg.grouping,
});
objects.set(
cfg,
'widgetTemplate.chart.renderTo',
self.el.querySelector('.lt-vapp-widget-graphic')
);
for (let item of data) item.name = __(item.name);
if (data) {
// Default formatter
if (!cfg.defaultformater) {
cfg.defaultformater = highchartsHelper.valueFormatterCount();
}
self.widget = new LineWidget(cfg);
self.widget.setData(data);
self.widget.display({ force: true, data: true });
} else {
this.debugError({
msg: 'NO DATA',
console: {
method: 'error',
msg: 'No data arrive to render function',
},
});
}
},
};
}
export default widgetFactory(mixin);
Source