/*
* Pim
* Free Extension
* Copyright (c) TreoLabs GmbH
* Copyright (c) Kenner Soft Service GmbH
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
Espo.define('pim:views/dashlets/product-status-overview', ['views/dashlets/abstract/base','lib!Flotr'],
(Dep, Flotr) => Dep.extend({
_template: '<div class="chart-container"></div><div class="legend-container"></div>',
name: 'ProductStatusOverview',
decimalMark: '.',
thousandSeparator: '',
colorList: ['#6FA8D6', '#4E6CAD', '#EDC555', '#ED8F42', '#DE6666', '#7CC4A4', '#8A7CC2', '#D4729B'],
textColor: '#333333',
hoverColor: '#FF3F19',
legendColumnWidth: 110,
legendColumnNumber: 6,
chartContainerMarginBottom: 10,
chartData: null,
chartContainer: null,
legendContainer: null,
init: function () {
Dep.prototype.init.call(this);
this.colorList = this.getThemeManager().getParam('chartColorList') || this.colorList;
this.textColor = this.getThemeManager().getParam('textColor') || this.textColor;
this.hoverColor = this.getThemeManager().getParam('hoverColor') || this.hoverColor;
this.decimalMark = this.getPreferenceValue('decimalMark') || this.decimalMark;
this.thousandSeparator = this.getPreferenceValue('thousandSeparator') || this.thousandSeparator;
this.listenToOnce(this, 'after:render', () => {
$(window).on('resize.chart' + this.name, () => {
this.adjustChartContainer();
this.draw();
this.adjustLegend();
});
});
this.listenToOnce(this, 'remove', () => {
$(window).off('resize.chart' + this.name)
});
this.listenTo(this, 'resize', () => {
window.setTimeout(() => {
this.adjustChartContainer();
this.draw();
this.adjustLegend();
}, 10);
});
},
afterRender() {
this.chartContainer = this.$el.find('.chart-container');
this.legendContainer = this.$el.find('.legend-container');
this.buildChart();
},
buildChart() {
this.fetch().then(data => {
this.chartData = this.prepareData(data);
let colorList = [];
let optionColors = this.getMetadata().get(['entityDefs', 'Product', 'fields', 'productStatus', 'optionColors']);
(data.list || []).forEach(item => {
colorList.push('#' + optionColors[item.name]);
});
this.colorList = colorList;
this.adjustChartContainer();
this.draw();
this.adjustLegend();
});
},
getPreferenceValue(key) {
if (this.getPreferences().has(key)) {
return this.getPreferences().get(key)
} else if (this.getConfig().has(key)) {
return this.getConfig().get(key);
}
return null;
},
getUrl() {
return 'Dashlet/ProductsByStatus';
},
fetch() {
return this.ajaxGetRequest(this.getUrl());
},
prepareData(data) {
return (data.list || []).map(item => {
return {
label: this.getLanguage().translateOption(item.name, 'productStatus', 'Product'),
data: [[0, item.amount]]
};
});
},
adjustChartContainer() {
let height = Math.ceil(this.getLegendHeight()) + this.chartContainerMarginBottom;
this.chartContainer.css({
height: `calc(100% - ${height}px)`,
marginBottom: `${this.chartContainerMarginBottom}px`
});
},
adjustLegend() {
var number = this.getLegendColumnNumber();
if (number) {
let dashletChartLegendBoxWidth = this.getThemeManager().getParam('dashletChartLegendBoxWidth') || 21;
let containerWidth = this.legendContainer.width();
let width = Math.floor((containerWidth - dashletChartLegendBoxWidth * number) / number);
let columnNumber = this.legendContainer.find('> table tr:first-child > td').size() / 2;
let tableWidth = (width + dashletChartLegendBoxWidth) * columnNumber;
this.legendContainer.find('> table').css('table-layout', 'fixed').attr('width', tableWidth);
this.legendContainer.find('td.flotr-legend-label').attr('width', width);
this.legendContainer.find('td.flotr-legend-color-box').attr('width', dashletChartLegendBoxWidth);
this.legendContainer.find('td.flotr-legend-label > span').each((i, span) => {
span.setAttribute('title', span.textContent);
});
}
},
getLegendHeight() {
let lineNumber = Math.ceil(this.chartData.length / this.getLegendColumnNumber());
let lineHeight = this.getThemeManager().getParam('dashletChartLegendRowHeight') || 19;
let paddingTopHeight = this.getThemeManager().getParam('dashletChartLegendPaddingTopHeight') || 7;
return lineNumber ? (lineHeight * lineNumber + paddingTopHeight) : 0;
},
getLegendColumnNumber: function () {
return Math.floor(this.$el.closest('.panel-body').width() / this.legendColumnWidth) || this.legendColumnNumber;
},
draw() {
let self = this;
Flotr.draw(this.chartContainer.get(0), this.chartData, {
colors: this.colorList,
shadowSize: false,
pie: {
show: true,
explode: 0,
lineWidth: 1,
fillOpacity: 1,
sizeRatio: 0.8,
labelFormatter(total, value) {
let percent = self.formatNumber(Math.round(value / total * 10000) / 100);
return `<span class="small" style="font-size: 0.8em; color:${self.textColor}">${percent}%</span>`;
}
},
grid: {
horizontalLines: false,
verticalLines: false,
outline: '',
},
yaxis: {
showLabels: false,
},
xaxis: {
showLabels: false,
},
mouse: {
track: true,
relative: true,
lineColor: this.hoverColor,
trackFormatter: function (obj) {
return `${obj.series.label || self.translate('None')}:<br>${self.formatNumber(parseInt(obj.y))} / ${(100 * (obj.fraction || 0)).toFixed(2)}%`;
}
},
legend: {
show: true,
noColumns: self.getLegendColumnNumber(),
container: self.legendContainer,
labelBoxMargin: 0,
labelBoxBorderColor: 'transparent',
backgroundOpacity: 0,
labelFormatter(label) {
return `<span style="color: ${self.textColor};">${label}</span>`;
},
}
});
},
formatNumber(value) {
if (value !== null) {
let parts = value.toString().split(".");
parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, this.thousandSeparator);
return parts.join(this.decimalMark);
}
return '';
},
actionRefresh: function () {
this.buildChart();
},
})
);
|