import { inject as service } from '@ember/service'; import { get, set, observer } from '@ember/object'; import ThrottledResize from 'shared/mixins/throttled-resize'; import { escapeHtml } from 'shared/utils/util'; import Component from '@ember/component'; import { all } from 'rsvp' import { theme as THEME } from './theme'; import { roundValue, formatPercent, formatMib, formatSecond, formatKbps } from 'shared/utils/util'; import layout from './template'; function getFormatter(unit, full = false) { switch (unit) { case 'seconds': return formatSecond; case 'pps': return (value) => { return `${ roundValue(value) } ${ full ? 'Packets Per Second' : 'Pps' }` } case 'ops': return (value) => { return `${ roundValue(value) } ${ full ? 'Operation Per Second' : 'Ops' }` } case 'ms': return (value) => { return `${ roundValue(value) } ms` } case 'mcpu': return (value) => { return `${ roundValue(value) } mCPU` } case 'percent': return formatPercent; case 'bps': case 'kbps': return formatKbps; case 'byte': return formatMib; default: return roundValue; } } function getConverter(unit) { switch (unit) { case 'percent': return (value) => value * 100; case 'mcpu': return (value) => value * 1000; case 'bps': return (value) => value / 1024; case 'byte': return (value) => value / 1048576; default: return (value) => value; } } const LOADING_PARAMS = { text: '', color: '#3d3d3d', textColor: '#3d3d3d', maskColor: 'rgba(255, 255, 255, 0.8)', zlevel: 0 } var ECharts = null; export default Component.extend(ThrottledResize, { intl: service(), layout, tagName: 'div', classNames: ['graph-area'], model: null, fields: null, chart: null, formatter: 'value', needRefresh: false, init() { this._super(...arguments); if ( !ECharts ) { all([ import('echarts/lib/echarts'), import('echarts/lib/chart/line'), import('echarts/lib/component/tooltip'), ]).then( (modules) => { ECharts = modules[0].default; ECharts.registerTheme('walden', THEME); this.didRender(); }); } }, willDestroyElement() { const chart = get(this, 'chart'); if ( chart ) { chart.clear(); chart.dispose(); } }, didRender() { if ( ECharts && !get(this, 'chart') ) { this.create(); setTimeout(() => { const chart = get(this, 'chart'); if ( chart ) { chart.resize(); } }, 200); } }, loadingDidChange: observer('loading', function() { const chart = get(this, 'chart'); if ( chart && get(this, 'loading') ) { chart.showLoading(LOADING_PARAMS); } else if (chart) { chart.hideLoading(); } }), dataDidChange: observer('series', function() { if ( get(this, 'chart') ) { this.draw(); } }), onResize() { if ( !ECharts || this.isDestroyed || this.isDestroying ) { return; } if ( get(this, 'chart') ) { get(this, 'chart').resize(); } }, create() { const chart = ECharts.init(this.$('.content')[0], 'walden'); set(this, 'chart', chart); chart.showLoading(LOADING_PARAMS); this.draw(); }, draw() { const chart = get(this, 'chart'); if ( !chart ) { return; } const minMax = get(this, 'formatter') === 'percent' ? 100 : null; let setMax = true; const series = []; const fields = (get(this, 'series') || []).filter((serie) => get(serie, 'points.length') > 1).map((serie) => { return { id: get(serie, 'name'), data: (get(serie, 'points') || []).map((p) => [p[1], getConverter(get(this, 'formatter'))(p[0])]) } }); fields.forEach((field) => { const serie = field.data || []; const data = []; serie.forEach((d) => { if ( minMax && setMax && d[1] > minMax ) { setMax = false; } data.push(d); }); series.push({ name: field.id, type: 'line', showSymbol: false, animation: false, data, itemStyle: { normal: { lineStyle: { width: 1 } } } }); }); const formatter = getFormatter(get(this, 'formatter'), true); let option = { tooltip: { trigger: 'axis', position(pos, params, dom, rect, size) { const obj = { top: 60 }; obj[['left', 'right'][+(pos[0] < size.viewSize[0] / 2)]] = 5; return obj; }, formatter(params) { let html = ''; params.forEach((p, i) => { if ( i === 0 ) { html = `
${ p.axisValueLabel }` } const value = escapeHtml(formatter(p.data[1])); let label = escapeHtml(p.seriesName); html += `
${ label } : ${ value }`; }); html += '
'; return html.htmlSafe(); } }, grid: { top: '10px', left: '30px', right: '30px', bottom: '3%', containLabel: true }, xAxis: { type: 'time', boundaryGap: false, }, yAxis: { type: 'value', axisLabel: { formatter: getFormatter(get(this, 'formatter')) }, splitArea: { show: true }, }, series, }; if ( setMax && minMax ) { option.yAxis.max = minMax; } chart.clear(); chart.setOption(option, true); chart.hideLoading(); }, });