mirror of
https://github.com/getredash/redash.git
synced 2026-03-22 19:00:09 -04:00
137 lines
3.6 KiB
JavaScript
137 lines
3.6 KiB
JavaScript
import { filter, has, isNumber, isObject, isUndefined, map, max, min } from "lodash";
|
|
import { getPieDimensions } from "./preparePieData";
|
|
|
|
function getAxisTitle(axis) {
|
|
return isObject(axis.title) ? axis.title.text : null;
|
|
}
|
|
|
|
function getAxisScaleType(axis) {
|
|
switch (axis.type) {
|
|
case "datetime":
|
|
return "date";
|
|
case "logarithmic":
|
|
return "log";
|
|
default:
|
|
return axis.type;
|
|
}
|
|
}
|
|
|
|
function calculateAxisRange(seriesList, minValue, maxValue) {
|
|
if (!isNumber(minValue)) {
|
|
minValue = Math.min(0, min(map(seriesList, series => min(series.y))));
|
|
}
|
|
if (!isNumber(maxValue)) {
|
|
maxValue = max(map(seriesList, series => max(series.y)));
|
|
}
|
|
return [minValue, maxValue];
|
|
}
|
|
|
|
function prepareXAxis(axisOptions, additionalOptions) {
|
|
const axis = {
|
|
title: getAxisTitle(axisOptions),
|
|
type: getAxisScaleType(axisOptions),
|
|
automargin: true,
|
|
};
|
|
|
|
if (additionalOptions.sortX && axis.type === "category") {
|
|
if (additionalOptions.reverseX) {
|
|
axis.categoryorder = "category descending";
|
|
} else {
|
|
axis.categoryorder = "category ascending";
|
|
}
|
|
}
|
|
|
|
if (!isUndefined(axisOptions.labels)) {
|
|
axis.showticklabels = axisOptions.labels.enabled;
|
|
}
|
|
|
|
return axis;
|
|
}
|
|
|
|
function prepareYAxis(axisOptions, additionalOptions, data) {
|
|
const axis = {
|
|
title: getAxisTitle(axisOptions),
|
|
type: getAxisScaleType(axisOptions),
|
|
automargin: true,
|
|
};
|
|
|
|
if (isNumber(axisOptions.rangeMin) || isNumber(axisOptions.rangeMax)) {
|
|
axis.range = calculateAxisRange(data, axisOptions.rangeMin, axisOptions.rangeMax);
|
|
}
|
|
|
|
return axis;
|
|
}
|
|
|
|
function preparePieLayout(layout, options, data) {
|
|
const hasName = /{{\s*@@name\s*}}/.test(options.textFormat);
|
|
|
|
const { cellsInRow, cellWidth, cellHeight, xPadding } = getPieDimensions(data);
|
|
|
|
if (hasName) {
|
|
layout.annotations = [];
|
|
} else {
|
|
layout.annotations = filter(
|
|
map(data, (series, index) => {
|
|
const xPosition = (index % cellsInRow) * cellWidth;
|
|
const yPosition = Math.floor(index / cellsInRow) * cellHeight;
|
|
return {
|
|
x: xPosition + (cellWidth - xPadding) / 2,
|
|
y: yPosition + cellHeight - 0.015,
|
|
xanchor: "center",
|
|
yanchor: "top",
|
|
text: series.name,
|
|
showarrow: false,
|
|
};
|
|
})
|
|
);
|
|
}
|
|
|
|
return layout;
|
|
}
|
|
|
|
function prepareDefaultLayout(layout, options, data) {
|
|
const ySeries = data.filter(s => s.yaxis !== "y2");
|
|
const y2Series = data.filter(s => s.yaxis === "y2");
|
|
|
|
layout.xaxis = prepareXAxis(options.xAxis, options);
|
|
|
|
layout.yaxis = prepareYAxis(options.yAxis[0], options, ySeries);
|
|
if (y2Series.length > 0) {
|
|
layout.yaxis2 = prepareYAxis(options.yAxis[1], options, y2Series);
|
|
layout.yaxis2.overlaying = "y";
|
|
layout.yaxis2.side = "right";
|
|
}
|
|
|
|
if (options.series.stacking) {
|
|
layout.barmode = "relative";
|
|
}
|
|
|
|
return layout;
|
|
}
|
|
|
|
function prepareBoxLayout(layout, options, data) {
|
|
layout = prepareDefaultLayout(layout, options, data);
|
|
layout.boxmode = "group";
|
|
layout.boxgroupgap = 0.5;
|
|
return layout;
|
|
}
|
|
|
|
export default function prepareLayout(element, options, data) {
|
|
const layout = {
|
|
margin: { l: 10, r: 10, b: 5, t: 20, pad: 4 },
|
|
width: Math.floor(element.offsetWidth),
|
|
height: Math.floor(element.offsetHeight),
|
|
autosize: false,
|
|
showlegend: has(options, "legend") ? options.legend.enabled : true,
|
|
};
|
|
|
|
switch (options.globalSeriesType) {
|
|
case "pie":
|
|
return preparePieLayout(layout, options, data);
|
|
case "box":
|
|
return prepareBoxLayout(layout, options, data);
|
|
default:
|
|
return prepareDefaultLayout(layout, options, data);
|
|
}
|
|
}
|