diff --git a/package.json b/package.json
index b35646ba..44d0fe15 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "@netdata/charts",
- "version": "6.10.6",
+ "version": "6.10.7",
"description": "Netdata frontend SDK and chart utilities",
"main": "dist/index.js",
"module": "dist/es6/index.js",
@@ -80,6 +80,7 @@
"svgo-loader": "^4.0.0"
},
"dependencies": {
+ "@tanstack/react-virtual": "^3.13.18",
"d3": "^7.9.0",
"d3-scale": "^4.0.2",
"dygraphs": "^2.2.1",
diff --git a/src/chartLibraries/dygraph/index.js b/src/chartLibraries/dygraph/index.js
index 0a9b57ca..946f4a97 100644
--- a/src/chartLibraries/dygraph/index.js
+++ b/src/chartLibraries/dygraph/index.js
@@ -308,10 +308,12 @@ export default (sdk, chart) => {
const makeChartTypeOptions = () => {
const { labels } = chart.getPayload()
- const { chartType, includeZero, enabledXAxis, enabledYAxis, yAxisLabelWidth } =
+ const { chartType, includeZero, enabledXAxis, enabledYAxis, yAxisLabelWidth, stepPlot } =
chart.getAttributes()
- const plotter = plotterByChartType[chartType] || plotterByChartType.default
+ const plotter = stepPlot
+ ? plotterByChartType.default
+ : plotterByChartType[chartType] || plotterByChartType.default
const {
strokeWidth,
@@ -346,6 +348,7 @@ export default (sdk, chart) => {
(forceIncludeZero && dimensionIds.length > 1 && selectedLegendDimensions.length > 1),
stackedGraphNaNFill: "none",
plotter,
+ stepPlot,
errorBars,
axes: {
x: enabledXAxis
diff --git a/src/chartLibraries/dygraph/index.test.js b/src/chartLibraries/dygraph/index.test.js
index 75e7a733..1e77798a 100644
--- a/src/chartLibraries/dygraph/index.test.js
+++ b/src/chartLibraries/dygraph/index.test.js
@@ -219,6 +219,50 @@ describe("dygraphChart", () => {
expect(instance.getChartHeight()).toBe(400)
})
+ it("enables dygraph stepPlot when the stepPlot attribute is set", () => {
+ const { sdk, chart } = makeTestChart({
+ attributes: { theme: "dark", chartType: "line", stepPlot: true },
+ })
+
+ chart.getPayload = () => ({ data: [[1617946860000, 1]], labels: ["time", "value"] })
+ chart.getDateWindow = () => [1617946860000, 1617947750000]
+ chart.formatXAxis = x => x.toString()
+ chart.getThemeAttribute = () => "#333"
+ chart.getUnitSign = () => ""
+
+ const instance = dygraphChart(sdk, chart)
+ instance.mount(document.createElement("div"))
+
+ const Dygraph = require("dygraphs")
+ expect(Dygraph).toHaveBeenCalledWith(
+ expect.any(Object),
+ expect.any(Array),
+ expect.objectContaining({ stepPlot: true })
+ )
+ })
+
+ it("does not enable dygraph stepPlot by default", () => {
+ const { sdk, chart } = makeTestChart({
+ attributes: { theme: "dark", chartType: "line" },
+ })
+
+ chart.getPayload = () => ({ data: [[1617946860000, 10]], labels: ["time", "value"] })
+ chart.getDateWindow = () => [1617946860000, 1617947750000]
+ chart.formatXAxis = x => x.toString()
+ chart.getThemeAttribute = () => "#333"
+ chart.getUnitSign = () => ""
+
+ const instance = dygraphChart(sdk, chart)
+ instance.mount(document.createElement("div"))
+
+ const Dygraph = require("dygraphs")
+ expect(Dygraph).toHaveBeenCalledWith(
+ expect.any(Object),
+ expect.any(Array),
+ expect.objectContaining({ stepPlot: false })
+ )
+ })
+
it("returns axis range from dygraph", () => {
const { sdk, chart } = makeTestChart()
diff --git a/src/components/header/index.js b/src/components/header/index.js
index d641fdab..83243931 100644
--- a/src/components/header/index.js
+++ b/src/components/header/index.js
@@ -30,6 +30,7 @@ const Header = ({ hasFilters }) => {
const isMinimal = useIsMinimal()
const leftHeaderElements = useAttributeValue("leftHeaderElements")
const hasToolbox = useAttributeValue("hasToolbox")
+ const hideTitle = useAttributeValue("hideTitle")
const focused = useAttributeValue("focused")
return (
@@ -40,7 +41,7 @@ const Header = ({ hasFilters }) => {
{arr[index + 1] ? : null}
))}
-
+ {!hideTitle && }
{isMinimal && hasFilters && }
{hasToolbox && }
diff --git a/src/components/header/index.test.js b/src/components/header/index.test.js
new file mode 100644
index 00000000..349628cd
--- /dev/null
+++ b/src/components/header/index.test.js
@@ -0,0 +1,23 @@
+import React from "react"
+import { screen } from "@testing-library/react"
+import "@testing-library/jest-dom"
+import { renderWithChart } from "@jest/testUtilities"
+import Header from "./index"
+
+describe("Header component", () => {
+ it("renders the title by default", () => {
+ renderWithChart(, {
+ attributes: { title: "CPU Usage" },
+ })
+
+ expect(screen.getByText("CPU Usage")).toBeInTheDocument()
+ })
+
+ it("hides the title when hideTitle is true", () => {
+ renderWithChart(, {
+ attributes: { title: "CPU Usage", hideTitle: true },
+ })
+
+ expect(screen.queryByText("CPU Usage")).not.toBeInTheDocument()
+ })
+})
diff --git a/src/components/helpers/shortener.js b/src/components/helpers/shortener.js
index 7c72d872..db782425 100644
--- a/src/components/helpers/shortener.js
+++ b/src/components/helpers/shortener.js
@@ -1,6 +1,6 @@
import React, { useState, useEffect } from "react"
import { mergeRefs } from "@netdata/netdata-ui"
-import shorten from "@/helpers/shorten"
+import { shortenToWidth } from "@/helpers/shorten"
import Tooltip from "@/components/tooltip"
const Shortener = ({ text, Component = "div", noTooltip, ref: forwardedRef, ...rest }) => {
@@ -12,14 +12,12 @@ const Shortener = ({ text, Component = "div", noTooltip, ref: forwardedRef, ...r
if (!ref) return
const containerWidth = ref.offsetWidth
- let round = 0
+ const contentWidth = ref.scrollWidth
- while (ref.scrollWidth > containerWidth) {
- ref.textContent = shorten(ref.textContent, round)
- round = round + 1
- }
+ const next = shortenToWidth(text, contentWidth, containerWidth)
- if (ref.textContent !== text) {
+ if (next !== text) {
+ ref.textContent = next
setShortenText(text)
}
}, [text, ref])
diff --git a/src/components/line/footer/index.js b/src/components/line/footer/index.js
index 688e46f8..7b7b0cc5 100644
--- a/src/components/line/footer/index.js
+++ b/src/components/line/footer/index.js
@@ -36,7 +36,7 @@ const Footer = () => {
{!showingInfo && legend && (
<>
{isHeatmap && }
-
+
{!isMinimal && !isHeatmap && }
diff --git a/src/components/line/legend/index.js b/src/components/line/legend/index.js
index 54b97d7e..99f7c358 100644
--- a/src/components/line/legend/index.js
+++ b/src/components/line/legend/index.js
@@ -1,7 +1,8 @@
-import React, { memo, useRef, useEffect } from "react"
+import React, { useRef, useEffect, useState } from "react"
import styled from "styled-components"
import { debounce } from "throttle-debounce"
-import { Flex, useNavigationArrows } from "@netdata/netdata-ui"
+import { useVirtualizer } from "@tanstack/react-virtual"
+import { Box, Flex } from "@netdata/netdata-ui"
import navLeft from "@netdata/netdata-ui/dist/components/icon/assets/nav_left.svg"
import navRight from "@netdata/netdata-ui/dist/components/icon/assets/nav_right.svg"
import {
@@ -27,18 +28,11 @@ const Container = styled(Flex).attrs(props => ({
overflow-x: overlay;
overflow-y: hidden;
- ::-webkit-scrollbar {
- height: 6px;
+ &::-webkit-scrollbar {
+ height: 0;
}
`
-const getPositions = el => {
- if (!el) return { x: 0 }
- return {
- x: el.scrollLeft,
- }
-}
-
const skeletonDimensions = Array.from(Array(5))
const SkeletonDimensions = () => (
@@ -49,23 +43,34 @@ const SkeletonDimensions = () => (
)
-const Dimensions = memo(({ lastItemRef }) => {
- const dimensionIds = useDimensionIds()
+const VirtualItem = styled(Flex).attrs({
+ alignItems: "center",
+ padding: [0, 0.5, 0, 0],
+})`
+ position: absolute;
+ top: 0;
+ left: 0;
+ height: 100%;
+`
- if (!dimensionIds) return null
+const VirtualDimensions = ({ virtualizer, dimensionIds }) => (
+
+ {virtualizer.getVirtualItems().map(virtualItem => {
+ const id = dimensionIds[virtualItem.index]
- return (
-
- {dimensionIds.map((id, index) => (
-
- ))}
-
- )
-})
+ data-index={virtualItem.index}
+ ref={virtualizer.measureElement}
+ style={{ transform: `translateX(${virtualItem.start}px)` }}
+ >
+
+
+ )
+ })}
+
+)
const Legend = props => {
const dimensionIds = useDimensionIds()
@@ -75,14 +80,27 @@ const Legend = props => {
const active = useAttributeValue("active")
const legendRef = useRef(null)
- const lastItemRef = useRef()
- const [arrowLeft, arrowRight, onScroll] = useNavigationArrows(
- legendRef,
- lastItemRef,
- dimensionIds.length,
- true
- )
+ const [arrowLeft, setArrowLeft] = useState(false)
+ const [arrowRight, setArrowRight] = useState(false)
+
+ const virtualizer = useVirtualizer({
+ horizontal: true,
+ count: dimensionIds?.length || 0,
+ getScrollElement: () => legendRef.current,
+ estimateSize: () => 200,
+ overscan: 5,
+ })
+
+ const totalSize = virtualizer.getTotalSize()
+
+ const updateArrows = () => {
+ const el = legendRef.current
+ if (!el) return
+
+ setArrowLeft(el.scrollLeft > 20)
+ setArrowRight(el.scrollLeft + el.clientWidth < el.scrollWidth - 20)
+ }
useEffect(() => {
if (legendRef.current && active) {
@@ -90,11 +108,15 @@ const Legend = props => {
}
}, [legendRef.current, active])
+ useEffect(updateArrows, [totalSize])
+
useEffect(() => {
const scroll = () => {
- const { x } = getPositions(legendRef.current)
- chart.updateAttribute("legendScroll", x)
- onScroll()
+ const el = legendRef.current
+ if (!el) return
+
+ chart.updateAttribute("legendScroll", el.scrollLeft)
+ updateArrows()
}
scroll()
@@ -134,7 +156,7 @@ const Legend = props => {
}
return (
-
+
{arrowLeft && (
{
)}
- {!initialLoading && !empty && }
+ {!initialLoading && !empty && dimensionIds && (
+
+ )}
{initialLoading && }
{!initialLoading && empty && }
diff --git a/src/components/line/overlays/types.js b/src/components/line/overlays/types.js
index f8f8f97b..3bb5781a 100644
--- a/src/components/line/overlays/types.js
+++ b/src/components/line/overlays/types.js
@@ -66,13 +66,13 @@ const LatestTimeOverlay = props => (
)
const AnnotationOverlay = ({ id, ...rest }) => (
-
+
)
const DraftAnnotationOverlay = ({ id, ...rest }) => (
-
+
)
diff --git a/src/components/title/index.js b/src/components/title/index.js
index bd8982b3..87057dc2 100644
--- a/src/components/title/index.js
+++ b/src/components/title/index.js
@@ -18,6 +18,8 @@ export const Title = props => {
const name = useName()
const isMinimal = useIsMinimal()
const contextScope = useAttributeValue("contextScope")
+ const hideName = useAttributeValue("hideName")
+ const hideUnits = useAttributeValue("hideUnits")
return (
{
{title}
- {!!name && (!isMinimal || !title) && (
+ {!!name && !hideName && (!isMinimal || !title) && (
@@ -41,7 +43,7 @@ export const Title = props => {
)}
- {!!units && !isMinimal && (
+ {!!units && !hideUnits && !isMinimal && (
{
// TextSmall component should have truncate prop
expect(titleElement).toBeInTheDocument()
})
+
+ it("hides the context name when hideName is true", () => {
+ renderWithChart(, {
+ attributes: {
+ title: "CPU Usage",
+ name: "system.cpu",
+ isMinimal: false,
+ hideName: true,
+ },
+ })
+
+ expect(screen.getByText("CPU Usage")).toBeInTheDocument()
+ expect(screen.queryByText(/system\.cpu/)).not.toBeInTheDocument()
+ })
+
+ it("hides the units when hideUnits is true", () => {
+ renderWithChart(, {
+ attributes: {
+ title: "Memory Usage",
+ name: "system.memory",
+ isMinimal: false,
+ units: ["%"],
+ hideUnits: true,
+ },
+ })
+
+ expect(screen.getByText("Memory Usage")).toBeInTheDocument()
+ expect(screen.queryByText(/\[.*\]/)).not.toBeInTheDocument()
+ })
})
diff --git a/src/helpers/shorten/index.js b/src/helpers/shorten/index.js
index c062dcf2..3ed63a7d 100644
--- a/src/helpers/shorten/index.js
+++ b/src/helpers/shorten/index.js
@@ -44,11 +44,25 @@ export const shortForLength = (string, maxLength = 30) => {
let round = 0
while (string.length > maxLength) {
- string = shorten(string, round)
+ const next = shorten(string, round)
round = round + 1
+
+ if (next === string) {
+ if (round > 3) break
+ } else {
+ string = next
+ }
}
return string
}
+export const shortenToWidth = (text, contentWidth, containerWidth) => {
+ if (!text || contentWidth <= 0 || contentWidth <= containerWidth) return text
+
+ const targetChars = Math.max(3, Math.floor(text.length * (containerWidth / contentWidth)))
+
+ return shortForLength(text, targetChars)
+}
+
export default shorten
diff --git a/src/helpers/shorten/index.test.js b/src/helpers/shorten/index.test.js
index 9e3a1c71..0e9d817e 100644
--- a/src/helpers/shorten/index.test.js
+++ b/src/helpers/shorten/index.test.js
@@ -1,4 +1,4 @@
-import shorten, { shortForLength } from "."
+import shorten, { shortForLength, shortenToWidth } from "."
describe("shorten", () => {
it("returns string as-is for non-string inputs", () => {
@@ -84,4 +84,41 @@ describe("shortForLength", () => {
expect(result.length).toBeLessThanOrEqual(10)
expect(result).toContain("...")
})
+
+ it("terminates instead of hanging for maxLength below the ellipsis floor", () => {
+ expect(shortForLength("systemd-journald-eu-west-1b", 0)).toBe("...")
+ expect(shortForLength("systemd-journald-eu-west-1b", 1)).toBe("...")
+ expect(shortForLength("systemd-journald-eu-west-1b", 2)).toBe("...")
+ })
+})
+
+describe("shortenToWidth", () => {
+ it("returns text as-is for non-string inputs", () => {
+ expect(shortenToWidth(null, 100, 50)).toBeNull()
+ expect(shortenToWidth(undefined, 100, 50)).toBeUndefined()
+ expect(shortenToWidth("", 100, 50)).toBe("")
+ })
+
+ it("returns text unchanged when it already fits", () => {
+ expect(shortenToWidth("nginx", 40, 100)).toBe("nginx")
+ expect(shortenToWidth("nginx", 100, 100)).toBe("nginx")
+ })
+
+ it("returns text unchanged when content has no measurable width", () => {
+ expect(shortenToWidth("systemd-journald-eu-west-1b", 0, 0)).toBe("systemd-journald-eu-west-1b")
+ })
+
+ it("shortens text that overflows its container", () => {
+ const text = "systemd-journald-audit.service@cgroup_pod_1234567890-eu-west-1b"
+ const result = shortenToWidth(text, 600, 150)
+
+ expect(result.length).toBeLessThan(text.length)
+ expect(result).toContain("...")
+ })
+
+ it("never produces output shorter than the ellipsis floor", () => {
+ const result = shortenToWidth("systemd-journald-eu-west-1b", 600, 1)
+
+ expect(result).toBe("...")
+ })
})
diff --git a/src/helpers/stepped.js b/src/helpers/stepped.js
new file mode 100644
index 00000000..d4d70b61
--- /dev/null
+++ b/src/helpers/stepped.js
@@ -0,0 +1,6 @@
+export const stateUnits = new Set(["state", "{state}", "status", "{status}"])
+
+export const isStateUnits = units => {
+ const list = (Array.isArray(units) ? units : [units]).filter(Boolean)
+ return list.length > 0 && list.every(unit => stateUnits.has(unit))
+}
diff --git a/src/helpers/stepped.test.js b/src/helpers/stepped.test.js
new file mode 100644
index 00000000..8ca5f2ef
--- /dev/null
+++ b/src/helpers/stepped.test.js
@@ -0,0 +1,32 @@
+import { isStateUnits } from "./stepped"
+
+describe("isStateUnits", () => {
+ it("returns true for state units", () => {
+ expect(isStateUnits(["{state}"])).toBe(true)
+ expect(isStateUnits(["state"])).toBe(true)
+ })
+
+ it("returns true for status units", () => {
+ expect(isStateUnits(["{status}"])).toBe(true)
+ expect(isStateUnits(["status"])).toBe(true)
+ })
+
+ it("accepts a plain string", () => {
+ expect(isStateUnits("state")).toBe(true)
+ })
+
+ it("returns false for non-state units", () => {
+ expect(isStateUnits(["bytes/s"])).toBe(false)
+ expect(isStateUnits(["%"])).toBe(false)
+ })
+
+ it("returns false when mixed with non-state units", () => {
+ expect(isStateUnits(["state", "bytes/s"])).toBe(false)
+ })
+
+ it("returns false for empty or missing units", () => {
+ expect(isStateUnits([])).toBe(false)
+ expect(isStateUnits([""])).toBe(false)
+ expect(isStateUnits(undefined)).toBe(false)
+ })
+})
diff --git a/src/sdk/initialAttributes.js b/src/sdk/initialAttributes.js
index 0952021f..0d43fad9 100644
--- a/src/sdk/initialAttributes.js
+++ b/src/sdk/initialAttributes.js
@@ -64,6 +64,7 @@ export default {
active: false,
sparkline: false,
chartType: "",
+ stepPlot: false,
selectedLegendDimensions: [],
contextItems: [],
@@ -137,6 +138,9 @@ export default {
enabledXAxis: true,
hasToolbox: true,
+ hideTitle: false,
+ hideName: false,
+ hideUnits: false,
hasHoverPopover: true,
expandable: true,
showAnnotations: true,
diff --git a/src/sdk/makeChart/camelizePayload.js b/src/sdk/makeChart/camelizePayload.js
index c9208b13..4b733e70 100644
--- a/src/sdk/makeChart/camelizePayload.js
+++ b/src/sdk/makeChart/camelizePayload.js
@@ -1,4 +1,5 @@
import { heatmapOrChartType } from "@/helpers/heatmap"
+import { isStateUnits } from "@/helpers/stepped"
import { getAlias } from "@/helpers/units"
import normalizeSelectedInstances from "@/helpers/normalizeSelectedInstances"
@@ -231,15 +232,18 @@ export default (payload, chart) => {
contextsArray
)
+ const aliasedUnits = Array.isArray(units) ? units.map(getAlias) : [getAlias(units)]
+
const details = {
viewDimensions: {
...viewDimensions,
contexts: dimContexts,
grouped,
},
- units: Array.isArray(units) ? units.map(getAlias) : [getAlias(units)],
+ units: aliasedUnits,
unitsStsByContext,
chartType: heatmapOrChartType(viewDimensions.ids, chartType),
+ stepPlot: isStateUnits(aliasedUnits),
title,
tiers,
perTier,
diff --git a/src/sdk/makeChart/camelizePayload.test.js b/src/sdk/makeChart/camelizePayload.test.js
index 41a2d448..cbd83bf8 100644
--- a/src/sdk/makeChart/camelizePayload.test.js
+++ b/src/sdk/makeChart/camelizePayload.test.js
@@ -50,6 +50,27 @@ describe("camelizePayload", () => {
expect(result.title).toBe("Test Chart")
expect(result.chartType).toBe("line")
expect(result.units).toEqual(["By"])
+ expect(result.stepPlot).toBe(false)
+ })
+
+ it("derives stepPlot for state units", () => {
+ const payload = {
+ view: {
+ title: "Connection State",
+ chart_type: "line",
+ units: "state",
+ },
+ result: {
+ data: [],
+ labels: [],
+ point: { value: 0 },
+ },
+ }
+
+ const result = camelizePayload(payload)
+
+ expect(result.stepPlot).toBe(true)
+ expect(result.chartType).toBe("line")
})
it("handles summary data", () => {
diff --git a/src/sdk/makeChart/filters/getAggregateMethod.js b/src/sdk/makeChart/filters/getAggregateMethod.js
index 93841ecb..349c27ba 100644
--- a/src/sdk/makeChart/filters/getAggregateMethod.js
+++ b/src/sdk/makeChart/filters/getAggregateMethod.js
@@ -1,3 +1,5 @@
+import { stateUnits } from "@/helpers/stepped"
+
const averageUnits = new Set([
"%",
"percentage",
@@ -52,8 +54,6 @@ const averageUnits = new Set([
"[degF]",
])
-const sumUnits = new Set(["state", "{state}", "status", "{status}"])
-
const averageRegex = /(%|\/operation|\/run| run|\/request)/
export default chart => {
@@ -66,7 +66,7 @@ export default chart => {
let lowerUnit = unit.toLowerCase()
if (averageUnits.has(unit) || averageRegex.test(lowerUnit)) return "avg"
- if (sumUnits.has(unit) || sumUnits.has(lowerUnit)) return "sum"
+ if (stateUnits.has(unit) || stateUnits.has(lowerUnit)) return "sum"
return "avg"
}
diff --git a/src/sdk/makeChart/filters/getInitialAttributes.js b/src/sdk/makeChart/filters/getInitialAttributes.js
index 900935dc..0ecdb035 100644
--- a/src/sdk/makeChart/filters/getInitialAttributes.js
+++ b/src/sdk/makeChart/filters/getInitialAttributes.js
@@ -1,11 +1,6 @@
import getAggregateMethod from "./getAggregateMethod"
import getDimensions from "./getDimensions"
-export const stackedAggregations = {
- avg: true,
- sum: true,
-}
-
export default chart => {
const dimensionIds = chart.getAttribute("dimensionIds")
const aggregationMethodAttr = chart.getAttribute("aggregationMethod")
diff --git a/src/sdk/makeChart/filters/getInitialAttributes.test.js b/src/sdk/makeChart/filters/getInitialAttributes.test.js
index 5ce9028f..d605917c 100644
--- a/src/sdk/makeChart/filters/getInitialAttributes.test.js
+++ b/src/sdk/makeChart/filters/getInitialAttributes.test.js
@@ -1,4 +1,4 @@
-import getInitialAttributes, { stackedAggregations } from "./getInitialAttributes"
+import getInitialAttributes from "./getInitialAttributes"
import { makeTestChart } from "@jest/testUtilities"
describe("getInitialAttributes", () => {
@@ -17,13 +17,6 @@ describe("getInitialAttributes", () => {
chart = testChart.chart
})
- it("exports stackedAggregations constant", () => {
- expect(stackedAggregations).toEqual({
- avg: true,
- sum: true,
- })
- })
-
it("returns correct initial attributes with no aggregationMethod", () => {
const result = getInitialAttributes(chart)
diff --git a/src/sdk/makeChart/filters/makeControllers.js b/src/sdk/makeChart/filters/makeControllers.js
index 92da6b0b..1d7f5b23 100644
--- a/src/sdk/makeChart/filters/makeControllers.js
+++ b/src/sdk/makeChart/filters/makeControllers.js
@@ -1,36 +1,16 @@
import deepEqual from "@/helpers/deepEqual"
import pristine, { pristineKey } from "@/sdk/pristine"
-import getInitialFilterAttributes, { stackedAggregations } from "./getInitialAttributes"
+import getInitialFilterAttributes from "./getInitialAttributes"
import { isHeatmap } from "@/helpers/heatmap"
import makeLog from "@/sdk/makeLog"
export default chart => {
- const chartType = chart.getAttribute("chartType")
- let prevChartType = chartType
-
const log = ({ value, ...rest }) =>
makeLog(chart)({
...rest,
value: value && typeof value !== "string" ? JSON.stringify(value) : value,
})
- const onGroupChange = groupBy => {
- chart.updateAttribute("selectedLegendDimensions", [])
- if (chart.getAttribute("selectedChartType")) return
-
- if (groupBy.length > 1 || groupBy[0] !== "dimension") {
- prevChartType = prevChartType || chart.getAttribute("chartType")
- const aggregationMethod = chart.getAttribute("aggregationMethod")
- return chart.updateAttribute(
- "chartType",
- stackedAggregations[aggregationMethod] ? "stacked" : chartType
- )
- } else {
- chart.updateAttributes({ chartType: prevChartType, processing: true })
- }
- prevChartType = chartType
- }
-
const allowedGroupByValues = {
node: true,
instance: true,
@@ -85,8 +65,9 @@ export default chart => {
const changed = baseUpdateGroupBy(selected, {})
if (!changed) return
+ chart.updateAttribute("selectedLegendDimensions", [])
chart.updateAttributes(getInitialFilterAttributes(chart))
- chart.fetch({ processing: true }).then(() => onGroupChange(chart.getAttribute("groupBy")))
+ chart.fetch({ processing: true })
log({
chartAction: "chart-groupby-change",