Skip to content

Commit 520faa9

Browse files
authored
Merge pull request #2411 from visualize-admin/fix/most-recent-interactive-value
fix: Most recent interactive value
2 parents fdcb11a + e9da08d commit 520faa9

4 files changed

Lines changed: 91 additions & 4 deletions

File tree

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ You can also check the
1414
- Fixes
1515
- Chart more button is now correctly hidden when there are no actions
1616
available
17+
- Most recent value is now correctly resolved in interactive filters
1718

1819
# 5.9.0 - 2025-07-28
1920

app/charts/shared/chart-data-filters.tsx

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ import {
5858
} from "@/stores/interactive-filters";
5959
import { assert } from "@/utils/assert";
6060
import { hierarchyToOptions } from "@/utils/hierarchy";
61+
import { useResolveMostRecentValue } from "@/utils/most-recent-value";
6162
import { useEvent } from "@/utils/use-event";
6263

6364
type PreparedFilter = {
@@ -320,18 +321,29 @@ const DataFilter = ({
320321
? configFilter.value
321322
: undefined;
322323
const dataFilterValue = dimension ? dataFilters[dimension.id]?.value : null;
323-
const value = dataFilterValue ?? configFilterValue ?? FIELD_VALUE_NONE;
324+
325+
const resolvedDataFilterValue = useResolveMostRecentValue(
326+
dataFilterValue,
327+
dimension
328+
);
329+
const resolvedConfigFilterValue = useResolveMostRecentValue(
330+
configFilterValue,
331+
dimension
332+
);
333+
const value =
334+
resolvedDataFilterValue ?? resolvedConfigFilterValue ?? FIELD_VALUE_NONE;
324335

325336
useEffect(() => {
326337
const values = dimension?.values.map((d) => d.value) ?? [];
327338

328339
// We only want to disable loading state when the filter is actually valid.
329340
// It can be invalid when the application is ensuring possible filters.
330341
if (
331-
(dataFilterValue && values.includes(dataFilterValue)) ||
332-
dataFilterValue === FIELD_VALUE_NONE
342+
(resolvedDataFilterValue && values.includes(resolvedDataFilterValue)) ||
343+
resolvedDataFilterValue === FIELD_VALUE_NONE
333344
) {
334-
updateDataFilter(dimensionId, dataFilterValue);
345+
updateDataFilter(dimensionId, resolvedDataFilterValue);
346+
335347
chartLoadingState.set(`interactive-filter-${dimensionId}`, fetching);
336348
} else if (fetching || values.length === 0) {
337349
chartLoadingState.set(`interactive-filter-${dimensionId}`, fetching);
@@ -345,6 +357,7 @@ const DataFilter = ({
345357
setDataFilter,
346358
configFilterValue,
347359
updateDataFilter,
360+
resolvedDataFilterValue,
348361
]);
349362

350363
return dimension ? (
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
import { describe, expect, it } from "vitest";
2+
3+
import { VISUALIZE_MOST_RECENT_VALUE } from "@/domain/most-recent-value";
4+
import { resolveMostRecentValue } from "@/utils/most-recent-value";
5+
6+
describe("resolveMostRecentValue", () => {
7+
it("should return the value when not VISUALIZE_MOST_RECENT_VALUE", () => {
8+
const result = resolveMostRecentValue("test-value", undefined);
9+
expect(result).toBe("test-value");
10+
});
11+
12+
it("should return VISUALIZE_MOST_RECENT_VALUE when dimension is undefined", () => {
13+
const result = resolveMostRecentValue(
14+
VISUALIZE_MOST_RECENT_VALUE,
15+
undefined
16+
);
17+
expect(result).toBe(VISUALIZE_MOST_RECENT_VALUE);
18+
});
19+
20+
it("should return VISUALIZE_MOST_RECENT_VALUE when dimension has no values", () => {
21+
const dimension = { values: [] };
22+
const result = resolveMostRecentValue(
23+
VISUALIZE_MOST_RECENT_VALUE,
24+
dimension as any
25+
);
26+
expect(result).toBe(VISUALIZE_MOST_RECENT_VALUE);
27+
});
28+
29+
it("should return the last sorted value when dimension has values", () => {
30+
const dimension = {
31+
values: [
32+
{ value: "2020", label: "2020" },
33+
{ value: "2022", label: "2022" },
34+
{ value: "2021", label: "2021" },
35+
],
36+
};
37+
const result = resolveMostRecentValue(
38+
VISUALIZE_MOST_RECENT_VALUE,
39+
dimension as any
40+
);
41+
expect(result).toBe("2022");
42+
});
43+
});

app/utils/most-recent-value.ts

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import orderBy from "lodash/orderBy";
2+
import { useMemo } from "react";
3+
4+
import { Dimension, DimensionValue } from "@/domain/data";
5+
import { VISUALIZE_MOST_RECENT_VALUE } from "@/domain/most-recent-value";
6+
import { makeDimensionValueSorters } from "@/utils/sorting-values";
7+
8+
export const resolveMostRecentValue = (
9+
value: DimensionValue["value"] | null | undefined,
10+
dimension: Dimension | undefined
11+
) => {
12+
if (value === VISUALIZE_MOST_RECENT_VALUE && dimension?.values.length) {
13+
const sorters = makeDimensionValueSorters(dimension);
14+
const sortedValues = orderBy(
15+
dimension.values,
16+
sorters.map((s) => (dv) => s(dv.label))
17+
);
18+
return sortedValues[sortedValues.length - 1]?.value;
19+
}
20+
return value;
21+
};
22+
23+
export const useResolveMostRecentValue = (
24+
value: DimensionValue["value"] | null | undefined,
25+
dimension: Dimension | undefined
26+
) => {
27+
return useMemo(() => {
28+
return resolveMostRecentValue(value, dimension);
29+
}, [value, dimension]);
30+
};

0 commit comments

Comments
 (0)