Skip to content

Commit 82a5892

Browse files
committed
Merge branch 'main' of github.com:visualize-admin/visualization-tool into explore/table-interactive-filters
2 parents 2c9c7eb + ae5aecf commit 82a5892

276 files changed

Lines changed: 2163 additions & 1688 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.eslintrc.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
"extends": "next",
33
"plugins": ["import", "visualize-admin", "deprecate", "unused-imports"],
44
"rules": {
5+
"no-duplicate-case": "error",
56
"no-restricted-imports": [
67
"error",
78
{

.storybook/decorators.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,14 @@ import { CssBaseline, ThemeProvider } from "@mui/material";
33
import { NextPage } from "next";
44
import { SessionProvider } from "next-auth/react";
55
import Router from "next/router";
6-
import * as React from "react";
76
import { Decorator } from "@storybook/react";
87
import { Client, Provider } from "urql";
98

109
import { i18n } from "../app/locales/locales";
1110
import { theme } from "../app/themes/theme";
12-
import AsyncLocalizationProvider from "../app/utils/l10n-provider";
11+
import { AsyncLocalizationProvider } from "../app/utils/async-localization-provider";
1312
import { SnackbarProvider } from "../app/components/snackbar";
13+
import { useEffect, useState } from "react";
1414

1515
export const AppContextDecorator = (Story: NextPage) => (
1616
<SessionProvider refetchOnWindowFocus={false} refetchWhenOffline={false}>
@@ -28,8 +28,8 @@ export const AppContextDecorator = (Story: NextPage) => (
2828
);
2929

3030
export const RouterDecorator = (Story: NextPage) => {
31-
const [_, setIsRouterReady] = React.useState(false);
32-
React.useEffect(() => {
31+
const [_, setIsRouterReady] = useState(false);
32+
useEffect(() => {
3333
Router.ready(() => {
3434
setIsRouterReady(true);
3535
});

CHANGELOG.md

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,42 @@ You can also check the
1111

1212
# Unreleased
1313

14+
- Features
15+
- Improved UX of interacting with conversion units multiplier input
16+
- Updated WMS & WMTS providers list
17+
- Fixes
18+
- Interactive calculation is now correctly reset when removing segmentation
19+
- Tooltips are now correctly displayed in data preview table
20+
- Grid lines do not overlap the chart elements anymore in case of negative
21+
values
22+
- Color squares in color palette picker are now correctly reset when changing
23+
the palette
24+
- Use most recent value toggle is now correctly displaying in the single
25+
filters section
26+
- Security
27+
- Added additional protection against data source URL injection
28+
- Removed feature flag for custom GraphQL endpoint
29+
30+
# 5.8.3 - 2025-06-10
31+
32+
- Fixes
33+
- Segmented bar and column charts now correctly display value labels when
34+
downloading an image
35+
- Ticks of X and Y axes in bar and column charts are now correctly formatted
36+
37+
# 5.8.2 - 2025-06-03
38+
1439
- Features
1540
- Invalid URL error message is now translated
1641
- Improved UX of interacting with conversion units multiplier input
42+
- Added additional WMS & WMTS providers
1743
- Fixes
1844
- Fixed an infinite render loop when adding a custom map layer
45+
- Styles
46+
- Fixed some smaller UI inconsistencies, mostly in table charts
47+
- Maintenance
48+
- Consolidated file names, to use kebab-case everywhere
49+
- Simplified exports and imports, to prefer named exports over default exports
1950

2051
# 5.8.1 - 2025-05-27
2152

CODEOWNERS

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
* @bprusinowski @noahonyejese
1+
* @bprusinowski

app/auth-providers/adfs.ts

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { OAuthConfig, OAuthUserConfig } from "next-auth/providers";
22

3-
interface ADFSProfile extends Record<string, any> {
3+
type ADFSProfile = Record<string, any> & {
44
/**
55
* The subject of the JWT (user)
66
*/
@@ -20,19 +20,19 @@ interface ADFSProfile extends Record<string, any> {
2020
* The assigned role(s) of the user.
2121
*/
2222
role: string | string[];
23-
}
23+
};
2424

2525
/**
2626
* Configures Active Directory Federation Services as a NextAuth provider.
2727
*/
28-
export default function ADFS<P extends ADFSProfile>(
28+
export const ADFS = <P extends ADFSProfile>(
2929
options: OAuthUserConfig<P> & {
3030
/**
3131
* The OAuth Authorize URL
3232
*/
3333
authorizeUrl: string;
3434
}
35-
): OAuthConfig<P> {
35+
): OAuthConfig<P> => {
3636
return {
3737
id: "adfs",
3838
name: "eIAM (ADFS)",
@@ -43,9 +43,7 @@ export default function ADFS<P extends ADFSProfile>(
4343
scope: "openid",
4444
},
4545
},
46-
4746
idToken: true,
48-
4947
async profile(profile: P, tokens) {
5048
// Usually the user only has one role, which is a string.
5149
let role = profile.role;
@@ -72,7 +70,6 @@ export default function ADFS<P extends ADFSProfile>(
7270
idToken: tokens.id_token,
7371
};
7472
},
75-
7673
options,
7774
};
78-
}
75+
};

app/browse/component-label.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,9 @@ export const ComponentLabel = ({
2020
</OpenMetadataPanelWrapper>
2121
) : component.description ? (
2222
<MaybeTooltip title={component.description} tooltipProps={tooltipProps}>
23-
<ComponentLabelInner component={component} />
23+
<div>
24+
<ComponentLabelInner component={component} />
25+
</div>
2426
</MaybeTooltip>
2527
) : (
2628
<ComponentLabelInner component={component} />

app/browse/data-table-preview.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import { ComponentLabel } from "@/browse/component-label";
1313
import { Component, isNumericalMeasure, Observation } from "@/domain/data";
1414
import { useDimensionFormatters } from "@/formatters";
1515
import SvgIcChevronDown from "@/icons/components/IcChevronDown";
16-
import { uniqueMapBy } from "@/utils/uniqueMapBy";
16+
import { uniqueMapBy } from "@/utils/unique-map-by";
1717

1818
export const DataTablePreview = ({
1919
title,

app/browser/context.tsx

Lines changed: 28 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -6,24 +6,26 @@ import pickBy from "lodash/pickBy";
66
import { Url } from "next/dist/shared/lib/router/router";
77
import Link from "next/link";
88
import { Router, useRouter } from "next/router";
9-
import React, {
9+
import {
10+
ComponentProps,
1011
createContext,
12+
ReactNode,
1113
useContext,
1214
useEffect,
1315
useMemo,
1416
useRef,
1517
useState,
1618
} from "react";
1719

18-
import { SearchCubeResultOrder } from "@/graphql/query-hooks";
19-
import { BrowseParams } from "@/pages/browse";
20-
import useEvent from "@/utils/use-event";
21-
2220
import {
2321
BrowseFilter,
2422
getFiltersFromParams,
2523
getParamsFromFilters,
26-
} from "./filters";
24+
} from "@/browser/filters";
25+
import { truthy } from "@/domain/types";
26+
import { SearchCubeResultOrder } from "@/graphql/query-hooks";
27+
import { BrowseParams } from "@/pages/browse";
28+
import { useEvent } from "@/utils/use-event";
2729

2830
export const getBrowseParamsFromQuery = (
2931
query: Router["query"]
@@ -75,10 +77,15 @@ export const getBrowseParamsFromQuery = (
7577
);
7678
};
7779

78-
export const buildURLFromBrowseState = (browseState: BrowseParams) => {
79-
const { type, iri, subtype, subiri, subsubtype, subsubiri, ...queryParams } =
80-
browseState;
81-
80+
export const buildURLFromBrowseState = ({
81+
type,
82+
iri,
83+
subtype,
84+
subiri,
85+
subsubtype,
86+
subsubiri,
87+
...queryParams
88+
}: BrowseParams) => {
8289
const typePart =
8390
type && iri
8491
? `${encodeURIComponent(type)}/${encodeURIComponent(iri)}`
@@ -91,15 +98,16 @@ export const buildURLFromBrowseState = (browseState: BrowseParams) => {
9198
subsubtype && subsubiri
9299
? `${encodeURIComponent(subsubtype)}/${encodeURIComponent(subsubiri)}`
93100
: undefined;
94-
95101
const pathname = ["/browse", typePart, subtypePart, subsubtypePart]
96-
.filter(Boolean)
102+
.filter(truthy)
97103
.join("/");
104+
98105
return {
99106
pathname,
100107
query: queryParams,
101-
} as React.ComponentProps<typeof Link>["href"];
108+
} satisfies ComponentProps<typeof Link>["href"];
102109
};
110+
103111
const extractParamFromPath = (path: string, param: string) =>
104112
path.match(new RegExp(`[&?]${param}=(.*?)(&|$)`));
105113

@@ -140,22 +148,22 @@ const useBrowseParamsStateWithUrlSync = (initialState: BrowseParams) => {
140148
}, [router.isReady, router.query]);
141149

142150
const setState = useEvent(
143-
(
144-
stateUpdate: BrowseParams | ((prevState: BrowseParams) => BrowseParams)
145-
) => {
146-
rawSetState((curState) => {
151+
(stateUpdate: BrowseParams | ((prev: BrowseParams) => BrowseParams)) => {
152+
rawSetState((prev) => {
147153
const newState = {
148154
...(stateUpdate instanceof Function
149-
? stateUpdate(curState)
155+
? stateUpdate(prev)
150156
: stateUpdate),
151-
} as BrowseParams;
157+
} satisfies BrowseParams;
152158
router.replace(urlCodec.serialize(newState), undefined, {
153159
shallow: true,
154160
});
161+
155162
return newState;
156163
});
157164
}
158165
);
166+
159167
return [state, setState] as const;
160168
};
161169

@@ -283,7 +291,7 @@ export const BrowseStateProvider = ({
283291
children,
284292
syncWithUrl,
285293
}: {
286-
children: React.ReactNode;
294+
children: ReactNode;
287295
syncWithUrl: boolean;
288296
}) => {
289297
const browseState = useBrowseState({ syncWithUrl });

app/browser/dataset-browse.spec.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ describe("getFiltersFromParams", () => {
88
const params = {
99
type: "organization",
1010
iri: "https://fake-iri-organization",
11-
} as BrowseParams;
11+
} satisfies BrowseParams;
1212
const filters = getFiltersFromParams(params);
1313
expect(filters).toEqual([
1414
{
@@ -24,7 +24,7 @@ describe("getFiltersFromParams", () => {
2424
iri: "https://fake-iri-theme",
2525
subtype: "organization",
2626
subiri: "https://fake-iri-organization",
27-
} as BrowseParams;
27+
} satisfies BrowseParams;
2828
const filters = getFiltersFromParams(params);
2929
expect(filters).toEqual([
3030
{ iri: "https://fake-iri-theme", __typename: "DataCubeTheme" },
@@ -41,7 +41,7 @@ describe("getFiltersFromParams", () => {
4141
iri: "https://fake-iri-organization",
4242
subtype: "theme",
4343
subiri: "https://fake-iri-theme",
44-
} as BrowseParams;
44+
} satisfies BrowseParams;
4545
const filters = getFiltersFromParams(params);
4646
expect(filters).toEqual([
4747
{
@@ -59,7 +59,7 @@ describe("getFiltersFromParams", () => {
5959
const params = {
6060
type: "dataset",
6161
iri: "https://fake-iri-dataset",
62-
} as BrowseParams;
62+
} satisfies BrowseParams;
6363
const filters = getFiltersFromParams(params);
6464
expect(filters).toEqual([]);
6565
});

0 commit comments

Comments
 (0)