UNPKG

@gooddata/react-components

Version:

GoodData.UI - A powerful JavaScript library for building analytical applications

497 lines • 21.2 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); // (C) 2007-2020 GoodData Corporation var range = require("lodash/range"); var get = require("lodash/get"); var head = require("lodash/head"); var last = require("lodash/last"); var isEmpty = require("lodash/isEmpty"); var inRange = require("lodash/inRange"); var PositionTypes_1 = require("./PositionTypes"); var common_1 = require("../../utils/common"); var chartOptionsBuilder_1 = require("../chartOptionsBuilder"); var visualizationTypes_1 = require("../../../../constants/visualizationTypes"); exports.RESPONSIVE_ITEM_MIN_WIDTH = 200; exports.RESPONSIVE_VISIBLE_ROWS = 2; exports.FLUID_PAGING_WIDTH = 30; exports.LEGEND_PADDING = 12; exports.ITEM_HEIGHT = 20; exports.SKIPPED_LABEL_TEXT = "..."; exports.UTF_NON_BREAKING_SPACE = "\u00A0"; var STATIC_PAGING_HEIGHT = 44; function getEmptyBlock(style, index) { return { key: "empty-" + index, label: exports.UTF_NON_BREAKING_SPACE, style: style, }; } function getLabelStyle(width, textAlign) { return { width: width, textAlign: textAlign }; } var ALEFT = "left"; var ARIGHT = "right"; var ACENTER = "center"; var DOTS_WIDTH = 10; function getSkippedLabelBlock(index) { return { key: "dots-" + index, label: exports.SKIPPED_LABEL_TEXT, style: getLabelStyle(DOTS_WIDTH, ACENTER), }; } var verticalHeatmapMiddleLabelStyle = { height: 30, textAlign: ALEFT, lineHeight: "30px" }; exports.verticalHeatmapConfig = [ { type: "label", labelIndex: 0, style: { height: 15, textAlign: ALEFT, lineHeight: "11px" } }, { type: "label", labelIndex: 1, style: verticalHeatmapMiddleLabelStyle }, { type: "label", labelIndex: 2, style: verticalHeatmapMiddleLabelStyle }, { type: "label", labelIndex: 3, style: verticalHeatmapMiddleLabelStyle }, { type: "label", labelIndex: 4, style: verticalHeatmapMiddleLabelStyle }, { type: "label", labelIndex: 5, style: verticalHeatmapMiddleLabelStyle }, { type: "label", labelIndex: 6, style: verticalHeatmapMiddleLabelStyle }, { type: "label", labelIndex: 7, style: { height: 15, textAlign: ALEFT, lineHeight: "20px" } }, ]; var defaultHeatmapLegendLabelStyle = { width: 40, textAlign: ACENTER }; exports.heatmapLegendConfigMatrix = [ [ { type: "label", labelIndex: 0, style: { width: 175, textAlign: ALEFT } }, { type: "label", labelIndex: 7, style: { width: 175, textAlign: ARIGHT } }, ], [ { type: "label", labelIndex: 0, style: { width: 145, textAlign: ALEFT } }, { type: "dots" }, { type: "space", style: { width: 40 } }, { type: "dots" }, { type: "label", labelIndex: 7, style: { width: 145, textAlign: ARIGHT } }, ], [ { type: "label", labelIndex: 0, style: { width: 95, textAlign: ALEFT } }, { type: "dots" }, { type: "space", style: { width: 40 } }, { type: "dots" }, { type: "space", style: { width: 40 } }, { type: "dots" }, { type: "space", style: { width: 40 } }, { type: "dots" }, { type: "label", labelIndex: 7, style: { width: 95, textAlign: ARIGHT } }, ], [ { type: "label", labelIndex: 0, style: { width: 55, textAlign: ALEFT } }, { type: "label", labelIndex: 2, style: { width: 90, textAlign: ACENTER } }, { type: "dots" }, { type: "space", style: { width: 40 } }, { type: "dots" }, { type: "label", labelIndex: 5, style: { width: 90, textAlign: ACENTER } }, { type: "label", labelIndex: 7, style: { width: 55, textAlign: ARIGHT } }, ], [ { type: "label", labelIndex: 0, style: { width: 45, textAlign: ALEFT } }, { type: "dots" }, { type: "label", labelIndex: 2, style: { width: 90, textAlign: ACENTER } }, { type: "dots" }, { type: "space", style: { width: 40 } }, { type: "dots" }, { type: "label", labelIndex: 5, style: { width: 90, textAlign: ACENTER } }, { type: "dots" }, { type: "label", labelIndex: 7, style: { width: 45, textAlign: ARIGHT } }, ], [ { type: "label", labelIndex: 0, style: { width: 30, textAlign: ALEFT } }, { type: "label", labelIndex: 1, style: defaultHeatmapLegendLabelStyle }, { type: "space", style: { width: 10 } }, { type: "label", labelIndex: 2, style: defaultHeatmapLegendLabelStyle }, { type: "space", style: { width: 10 } }, { type: "label", labelIndex: 3, style: defaultHeatmapLegendLabelStyle }, { type: "space", style: { width: 10 } }, { type: "label", labelIndex: 4, style: defaultHeatmapLegendLabelStyle }, { type: "space", style: { width: 10 } }, { type: "label", labelIndex: 5, style: defaultHeatmapLegendLabelStyle }, { type: "space", style: { width: 10 } }, { type: "label", labelIndex: 6, style: defaultHeatmapLegendLabelStyle }, { type: "label", labelIndex: 7, style: { width: 30, textAlign: ARIGHT } }, ], ]; exports.colorLegendConfigMatrix = [ [ { type: "label", labelIndex: 0, style: { width: 175, textAlign: ALEFT } }, { type: "label", labelIndex: 6, style: { width: 175, textAlign: ARIGHT } }, ], [ { type: "label", labelIndex: 0, style: { width: 145, textAlign: ALEFT } }, { type: "dots" }, { type: "space", style: { width: 40 } }, { type: "dots" }, { type: "label", labelIndex: 6, style: { width: 145, textAlign: ARIGHT } }, ], [ { type: "label", labelIndex: 0, style: { width: 95, textAlign: ALEFT } }, { type: "dots" }, { type: "space", style: { width: 40 } }, { type: "dots" }, { type: "space", style: { width: 40 } }, { type: "dots" }, { type: "space", style: { width: 40 } }, { type: "dots" }, { type: "label", labelIndex: 6, style: { width: 95, textAlign: ARIGHT } }, ], [ { type: "label", labelIndex: 0, style: { width: 55, textAlign: ALEFT } }, { type: "label", labelIndex: 2, style: { width: 90, textAlign: ACENTER } }, { type: "dots" }, { type: "space", style: { width: 40 } }, { type: "dots" }, { type: "label", labelIndex: 4, style: { width: 90, textAlign: ACENTER } }, { type: "label", labelIndex: 6, style: { width: 55, textAlign: ARIGHT } }, ], [ { type: "label", labelIndex: 0, style: { width: 45, textAlign: ALEFT } }, { type: "dots" }, { type: "label", labelIndex: 2, style: { width: 90, textAlign: ACENTER } }, { type: "dots" }, { type: "space", style: { width: 40 } }, { type: "dots" }, { type: "label", labelIndex: 4, style: { width: 90, textAlign: ACENTER } }, { type: "dots" }, { type: "label", labelIndex: 6, style: { width: 45, textAlign: ARIGHT } }, ], [ { type: "label", labelIndex: 0, style: { width: 30, textAlign: ALEFT } }, { type: "label", labelIndex: 1, style: defaultHeatmapLegendLabelStyle }, { type: "space", style: { width: 10 } }, { type: "label", labelIndex: 2, style: defaultHeatmapLegendLabelStyle }, { type: "space", style: { width: 10 } }, { type: "label", labelIndex: 3, style: defaultHeatmapLegendLabelStyle }, { type: "space", style: { width: 10 } }, { type: "label", labelIndex: 4, style: defaultHeatmapLegendLabelStyle }, { type: "space", style: { width: 10 } }, { type: "label", labelIndex: 5, style: defaultHeatmapLegendLabelStyle }, { type: "label", labelIndex: 6, style: { width: 30, textAlign: ARIGHT } }, ], ]; var defaultHeatmapSmallLegendStyle = { width: 40, textAlign: ACENTER }; exports.heatmapSmallLegendConfigMatrix = [ [ { type: "label", labelIndex: 0, style: { width: 138, textAlign: ALEFT } }, { type: "label", labelIndex: 7, style: { width: 138, textAlign: ARIGHT } }, ], [ { type: "label", labelIndex: 0, style: { width: 115, textAlign: ALEFT } }, { type: "dots" }, { type: "space", style: { width: 26 } }, { type: "dots" }, { type: "label", labelIndex: 7, style: { width: 115, textAlign: ARIGHT } }, ], [ { type: "label", labelIndex: 0, style: { width: 75, textAlign: ALEFT } }, { type: "dots" }, { type: "space", style: { width: 30 } }, { type: "dots" }, { type: "space", style: { width: 26 } }, { type: "dots" }, { type: "space", style: { width: 30 } }, { type: "dots" }, { type: "label", labelIndex: 7, style: { width: 75, textAlign: ARIGHT } }, ], [ { type: "label", labelIndex: 0, style: { width: 45, textAlign: ALEFT } }, { type: "label", labelIndex: 2, style: { width: 70, textAlign: ACENTER } }, { type: "dots" }, { type: "space", style: { width: 26 } }, { type: "dots" }, { type: "label", labelIndex: 5, style: { width: 70, textAlign: ACENTER } }, { type: "label", labelIndex: 7, style: { width: 45, textAlign: ARIGHT } }, ], [ { type: "label", labelIndex: 0, style: { width: 35, textAlign: ALEFT } }, { type: "dots" }, { type: "label", labelIndex: 2, style: { width: 70, textAlign: ACENTER } }, { type: "dots" }, { type: "space", style: { width: 26 } }, { type: "dots" }, { type: "label", labelIndex: 5, style: { width: 70, textAlign: ACENTER } }, { type: "dots" }, { type: "label", labelIndex: 7, style: { width: 35, textAlign: ARIGHT } }, ], [ { type: "label", labelIndex: 0, style: { width: 20, textAlign: ALEFT } }, { type: "label", labelIndex: 1, style: defaultHeatmapSmallLegendStyle }, { type: "label", labelIndex: 2, style: defaultHeatmapSmallLegendStyle }, { type: "label", labelIndex: 3, style: { width: 38, textAlign: ACENTER } }, { type: "label", labelIndex: 4, style: { width: 38, textAlign: ACENTER } }, { type: "label", labelIndex: 5, style: defaultHeatmapSmallLegendStyle }, { type: "label", labelIndex: 6, style: defaultHeatmapSmallLegendStyle }, { type: "label", labelIndex: 7, style: { width: 20, textAlign: ARIGHT } }, ], ]; function buildColorLabelsConfig(labels, config) { return config.map(function (element, index) { switch (element.type) { case "label": return { label: labels[element.labelIndex], style: element.style, key: element.type + "-" + index, }; case "space": return getEmptyBlock(element.style, index); case "dots": return getSkippedLabelBlock(index); } }); } exports.buildColorLabelsConfig = buildColorLabelsConfig; var LABEL_LENGHT_THRESHOLDS = [5, 8, 10, 15, 18]; var SMALL_LABEL_LENGHT_THRESHOLDS = [4, 7, 9, 13, 15]; function getColorLegendLabelsConfiguration(legendLabels, isSmall, isVertical) { var numberOfLabels = legendLabels.length; var firstLabelLength = head(legendLabels).length; var lastLabelLength = last(legendLabels).length; var maxLabelLength = firstLabelLength > lastLabelLength ? firstLabelLength : lastLabelLength; var labelLengths = isSmall ? SMALL_LABEL_LENGHT_THRESHOLDS : LABEL_LENGHT_THRESHOLDS; var shorteningConfig = isVertical ? exports.verticalHeatmapConfig : getHorizontalShorteningLabelConfig(labelLengths, maxLabelLength, isSmall, numberOfLabels); return buildColorLabelsConfig(legendLabels, shorteningConfig); } function getHorizontalShorteningLabelConfig(labelLengths, maxLabelLength, isSmall, numberOfLabels) { var shorteningLevel = getColorLabelShorteningLevel(labelLengths, maxLabelLength); if (isSmall) { return exports.heatmapSmallLegendConfigMatrix[shorteningLevel]; } if (numberOfLabels === 8) { return exports.heatmapLegendConfigMatrix[shorteningLevel]; } return exports.colorLegendConfigMatrix[shorteningLevel]; } function getColorLabelShorteningLevel(labelLengths, maxLabelLength) { var shorteningLevel; if (inRange(maxLabelLength, 0, labelLengths[0])) { shorteningLevel = 5; } else if (inRange(maxLabelLength, labelLengths[0], labelLengths[1])) { shorteningLevel = 4; } else if (inRange(maxLabelLength, labelLengths[1], labelLengths[2])) { shorteningLevel = 3; } else if (inRange(maxLabelLength, labelLengths[2], labelLengths[3])) { shorteningLevel = 2; } else if (inRange(maxLabelLength, labelLengths[3], labelLengths[4])) { shorteningLevel = 1; } else { shorteningLevel = 0; } return shorteningLevel; } function calculateFluidLegend(seriesCount, containerWidth) { // -1 because flex dimensions provide rounded number and the real width can be float var realWidth = containerWidth - 2 * exports.LEGEND_PADDING - 1; if (seriesCount <= 2) { return { hasPaging: false, itemWidth: realWidth / seriesCount, visibleItemsCount: seriesCount, }; } var columnsCount = Math.floor(realWidth / exports.RESPONSIVE_ITEM_MIN_WIDTH); var itemWidth = realWidth / columnsCount; var hasPaging = false; var rowsCount = Math.ceil(seriesCount / columnsCount); // Recalculate with paging if (rowsCount > exports.RESPONSIVE_VISIBLE_ROWS) { var legendWidthWithPaging = realWidth - exports.FLUID_PAGING_WIDTH; columnsCount = Math.floor(legendWidthWithPaging / exports.RESPONSIVE_ITEM_MIN_WIDTH); itemWidth = legendWidthWithPaging / columnsCount; hasPaging = true; } var visibleItemsCount = columnsCount * exports.RESPONSIVE_VISIBLE_ROWS; return { itemWidth: itemWidth, hasPaging: hasPaging, visibleItemsCount: visibleItemsCount, }; } exports.calculateFluidLegend = calculateFluidLegend; function getStaticVisibleItemsCount(containerHeight, withPaging) { if (withPaging === void 0) { withPaging = false; } var pagingHeight = withPaging ? STATIC_PAGING_HEIGHT : 0; return Math.floor((containerHeight - pagingHeight) / exports.ITEM_HEIGHT); } function calculateStaticLegend(seriesCount, containerHeight) { var visibleItemsCount = getStaticVisibleItemsCount(containerHeight); if (visibleItemsCount >= seriesCount) { return { hasPaging: false, visibleItemsCount: visibleItemsCount, }; } return { hasPaging: true, visibleItemsCount: getStaticVisibleItemsCount(containerHeight, true), }; } exports.calculateStaticLegend = calculateStaticLegend; function getColorLegendLabels(series, format, numericSymbols) { var min = get(head(series), "range.from", 0); var max = get(last(series), "range.to", 0); var diff = max - min; return range(series.length + 1).map(function (index) { var value; if (index === 0) { value = get(series, "0.range.from", 0); } else if (index === series.length) { value = get(series, index - 1 + ".range.to", 0); } else { value = get(series, index + ".range.from", 0); } return common_1.formatLegendLabel(value, format, diff, numericSymbols); }); } var MIDDLE_LEGEND_BOX_INDEX = 3; function getColorBoxes(series) { var getBoxStyle = function (item) { return ({ backgroundColor: item.color, border: item.color === "rgb(255,255,255)" ? "1px solid #ccc" : "none", }); }; return series.map(function (item, index) { var style = getBoxStyle(item); var middle = index === MIDDLE_LEGEND_BOX_INDEX ? "middle" : null; return { class: middle, key: "item-" + index, style: style, }; }); } function getColorLegendConfiguration(series, format, numericSymbols, isSmall, position) { var legendLabels = getColorLegendLabels(series, format, numericSymbols); var small = isSmall ? "small" : null; var finalPosition; // tslint:disable-next-line:prefer-conditional-expression if (isSmall) { finalPosition = position === PositionTypes_1.TOP ? PositionTypes_1.TOP : PositionTypes_1.BOTTOM; } else { finalPosition = position || PositionTypes_1.RIGHT; } var classes = ["viz-legend", "color-legend", "position-" + finalPosition, small]; var isVertical = finalPosition === PositionTypes_1.LEFT || finalPosition === PositionTypes_1.RIGHT; var finalLabels = getColorLegendLabelsConfiguration(legendLabels, isSmall, isVertical); var boxes = getColorBoxes(series); return { classes: classes, labels: finalLabels, boxes: boxes, position: finalPosition, }; } exports.getColorLegendConfiguration = getColorLegendConfiguration; var LEGEND_TEXT_KEYS = { column: ["left", "right"], line: ["left", "right"], bar: ["bottom", "top"], area: ["left", "right"], combo: ["left", "right"], combo2: ["left", "right"], }; exports.LEGEND_AXIS_INDICATOR = "legendAxisIndicator"; exports.LEGEND_SEPARATOR = "legendSeparator"; function separateLegendItems(series) { return series.reduce(function (result, item) { // for now, it assumes that GDC chart only has 2 Y axes in maximum // yAxis only takes 0 (left/bottom axis) or 1 (right/top axis) var yAxis = item.yAxis; if (!yAxis) { // 0 result.itemsOnFirstAxis.push(item); } else { result.itemsOnSecondAxis.push(item); } return result; }, { itemsOnFirstAxis: [], itemsOnSecondAxis: [], }); } function groupSeriesItemsByType(series) { var primaryType = get(head(series), "type"); return series.reduce(function (result, item) { if (primaryType === item.type) { result.primaryItems.push(item); } else { result.secondaryItems.push(item); } return result; }, { primaryItems: [], secondaryItems: [], }); } exports.groupSeriesItemsByType = groupSeriesItemsByType; function getComboChartSeries(series) { var _a = groupSeriesItemsByType(series), primaryItems = _a.primaryItems, secondaryItems = _a.secondaryItems; var primaryItem = head(primaryItems) || {}; var secondaryItem = head(secondaryItems) || {}; var primaryType = primaryItem.type || visualizationTypes_1.VisualizationTypes.COLUMN; var secondaryType = secondaryItem.type || visualizationTypes_1.VisualizationTypes.LINE; var _b = LEGEND_TEXT_KEYS.combo, firstAxisKey = _b[0], secondAxisKey = _b[1]; // convert to dual axis series when there is only one chart type if (isEmpty(secondaryItems)) { return transformToDualAxesSeries(series, primaryType); } // all measures display on same axis if (primaryItem.yAxis === secondaryItem.yAxis) { return [ { type: exports.LEGEND_AXIS_INDICATOR, labelKey: primaryType } ].concat(primaryItems, [ { type: exports.LEGEND_SEPARATOR }, { type: exports.LEGEND_AXIS_INDICATOR, labelKey: secondaryType } ], secondaryItems); } return [ { type: exports.LEGEND_AXIS_INDICATOR, labelKey: visualizationTypes_1.VisualizationTypes.COMBO, data: [primaryType, firstAxisKey], } ].concat(primaryItems, [ { type: exports.LEGEND_SEPARATOR }, { type: exports.LEGEND_AXIS_INDICATOR, labelKey: visualizationTypes_1.VisualizationTypes.COMBO, data: [secondaryType, secondAxisKey], } ], secondaryItems); } exports.getComboChartSeries = getComboChartSeries; function transformToDualAxesSeries(series, chartType) { var _a = separateLegendItems(series), itemsOnFirstAxis = _a.itemsOnFirstAxis, itemsOnSecondAxis = _a.itemsOnSecondAxis; if (!common_1.isOneOfTypes(chartType, chartOptionsBuilder_1.supportedDualAxesChartTypes) || !itemsOnFirstAxis.length || !itemsOnSecondAxis.length) { return series; } var _b = LEGEND_TEXT_KEYS[chartType], firstAxisKey = _b[0], secondAxisKey = _b[1]; return [ { type: exports.LEGEND_AXIS_INDICATOR, labelKey: firstAxisKey } ].concat(itemsOnFirstAxis, [ { type: exports.LEGEND_SEPARATOR }, { type: exports.LEGEND_AXIS_INDICATOR, labelKey: secondAxisKey } ], itemsOnSecondAxis); } exports.transformToDualAxesSeries = transformToDualAxesSeries; function isStackedChart(chartOptions) { var seriesLength = get(chartOptions, "data.series.length"); var type = chartOptions.type, stacking = chartOptions.stacking, hasStackByAttribute = chartOptions.hasStackByAttribute; var hasMoreThanOneSeries = seriesLength > 1; var isAreaChartWithOneSerie = common_1.isAreaChart(type) && !hasMoreThanOneSeries && !hasStackByAttribute; return !isAreaChartWithOneSerie && !common_1.isTreemap(type) && Boolean(stacking); } exports.isStackedChart = isStackedChart; //# sourceMappingURL=helpers.js.map