Skip to content

Commit 3f554f1

Browse files
committed
feat: Add automatic title WIP
1 parent cf29508 commit 3f554f1

File tree

4 files changed

+152
-5
lines changed

4 files changed

+152
-5
lines changed

app/components/chart-panel.tsx

Lines changed: 42 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
import { Box, BoxProps, Theme } from "@mui/material";
22
import { makeStyles } from "@mui/styles";
33
import clsx from "clsx";
4-
import React, { HTMLProps, forwardRef } from "react";
4+
import keyBy from "lodash/keyBy";
5+
import React, { forwardRef, HTMLProps, useMemo } from "react";
56

67
import ChartPanelLayoutCanvas, {
78
chartPanelLayoutGridClasses,
@@ -12,7 +13,8 @@ import { ChartSelectionTabs } from "@/components/chart-selection-tabs";
1213
import { DashboardInteractiveFilters } from "@/components/dashboard-interactive-filters";
1314
import { ChartConfig, Layout, LayoutDashboard } from "@/config-types";
1415
import { hasChartConfigs } from "@/configurator";
15-
import { useConfiguratorState } from "@/src";
16+
import { useDataCubesComponentsQuery } from "@/graphql/hooks";
17+
import { useConfiguratorState, useLocale } from "@/src";
1618

1719
const useStyles = makeStyles((theme: Theme) => ({
1820
panelLayout: {
@@ -48,13 +50,50 @@ export const ChartWrapper = forwardRef<HTMLDivElement, ChartWrapperProps>(
4850
(props, ref) => {
4951
const { children, editing, layoutType, ...rest } = props;
5052
const classes = useStyles();
53+
const [state] = useConfiguratorState(hasChartConfigs);
54+
const dataSource = state.dataSource;
55+
const locale = useLocale();
56+
const commonQueryVariables = {
57+
sourceType: dataSource.type,
58+
sourceUrl: dataSource.url,
59+
locale,
60+
};
61+
62+
const componentIris = undefined;
63+
const chartConfig = state.chartConfigs.find(
64+
(x) => x.key === state.activeChartKey
65+
);
66+
const [{ data: components }] = useDataCubesComponentsQuery({
67+
variables: {
68+
...commonQueryVariables,
69+
cubeFilters:
70+
chartConfig?.cubes.map((cube) => ({
71+
iri: cube.iri,
72+
componentIris,
73+
filters: cube.filters,
74+
joinBy: cube.joinBy,
75+
})) ?? [],
76+
},
77+
});
78+
const dimensionsByIri = useMemo(() => {
79+
return keyBy(
80+
[
81+
...(components?.dataCubesComponents.dimensions ?? []),
82+
...(components?.dataCubesComponents.measures ?? []),
83+
],
84+
(x) => x.iri
85+
);
86+
}, [components?.dataCubesComponents]);
87+
5188
return (
5289
<Box
5390
ref={ref}
5491
{...rest}
5592
className={clsx(classes.chartWrapper, props.className)}
5693
>
57-
{(editing || layoutType === "tab") && <ChartSelectionTabs />}
94+
{(editing || layoutType === "tab") && (
95+
<ChartSelectionTabs dimensionsByIri={dimensionsByIri} />
96+
)}
5897
<Box
5998
className={classes.chartWrapperInner}
6099
sx={{ minHeight: [150, 300, 500] }}

app/components/chart-selection-tabs.tsx

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ import {
4848
import { useSearchDatasetPanelStore } from "@/configurator/components/add-new-dataset-panel";
4949
import { ChartTypeSelector } from "@/configurator/components/chart-type-selector";
5050
import { getIconName } from "@/configurator/components/ui-helpers";
51+
import { Dimension, Measure } from "@/domain/data";
5152
import { useUserConfig } from "@/domain/user-configs";
5253
import { useFlag } from "@/flags";
5354
import { useDataCubesComponentsQuery } from "@/graphql/hooks";
@@ -56,6 +57,7 @@ import { defaultLocale, useLocale } from "@/locales";
5657
import { createConfig, updateConfig } from "@/utils/chart-config/api";
5758
import { createChartId } from "@/utils/create-chart-id";
5859
import { getRouterChartId } from "@/utils/router/helpers";
60+
import { generateChartTitle } from "@/utils/title";
5961
import { replaceLinks } from "@/utils/ui-strings";
6062
import useEvent from "@/utils/use-event";
6163
import { useMutate } from "@/utils/use-fetch-data";
@@ -102,7 +104,11 @@ const TabsStateProvider = (props: React.PropsWithChildren<{}>) => {
102104
);
103105
};
104106

105-
export const ChartSelectionTabs = () => {
107+
export const ChartSelectionTabs = ({
108+
dimensionsByIri,
109+
}: {
110+
dimensionsByIri: Record<string, Dimension | Measure>;
111+
}) => {
106112
const [state] = useConfiguratorState(hasChartConfigs);
107113
const editable =
108114
isConfiguring(state) || isLayouting(state) || isPublishing(state);
@@ -123,7 +129,7 @@ export const ChartSelectionTabs = () => {
123129
? d.meta.title[locale]
124130
: d.meta.title[defaultLocale] !== ""
125131
? d.meta.title[defaultLocale]
126-
: t({ id: "annotation.add.title" }),
132+
: generateChartTitle(d, dimensionsByIri),
127133
};
128134
});
129135

app/utils/title.spec.ts

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
import keyBy from "lodash/keyBy";
2+
3+
import { ChartConfig } from "@/configurator";
4+
import { Dimension } from "@/domain/data";
5+
import { generateChartTitle } from "@/utils/title";
6+
7+
const dimensionsByIri = keyBy(
8+
[
9+
{
10+
iri: "emissions",
11+
label: "Emissions of CO2",
12+
__typename: "OrdinalDimension",
13+
},
14+
{ iri: "emissions", label: "Year", __typename: "TemporalDimension" },
15+
{ iri: "gastype", label: "Type of Gas", __typename: "NominalDimension" },
16+
] as Dimension[],
17+
(x) => x.iri
18+
);
19+
20+
describe("generateChartTitle", () => {
21+
it("should generate the correct title for a column chart", () => {
22+
const columnChartConfig = {
23+
chartType: "column",
24+
fields: {
25+
x: { componentIri: "year" },
26+
y: { componentIri: "emissions" },
27+
},
28+
} as ChartConfig;
29+
const expectedTitle = "Emissions of CO2 per Year";
30+
31+
const actualTitle = generateChartTitle(columnChartConfig, dimensionsByIri);
32+
33+
expect(actualTitle).toBe(expectedTitle);
34+
});
35+
36+
it("should generate the correct title for a line chart", () => {
37+
const lineChartConfig = {
38+
chartType: "line",
39+
fields: {
40+
x: { componentIri: "year" },
41+
y: { componentIri: "emissions" },
42+
},
43+
} as ChartConfig;
44+
const expectedTitle = "Evolution of the Emissions of CO2";
45+
46+
const actualTitle = generateChartTitle(lineChartConfig, dimensionsByIri);
47+
48+
expect(actualTitle).toBe(expectedTitle);
49+
});
50+
51+
it("should generate the correct title for an area chart", () => {
52+
const areaChartConfig = {
53+
chartType: "pie",
54+
fields: {
55+
y: { componentIri: "emissions" },
56+
segment: { componentIri: "gastype" },
57+
},
58+
} as ChartConfig;
59+
const expectedTitle = "Shares of Emissions of CO2 by Type of Gas";
60+
61+
const actualTitle = generateChartTitle(areaChartConfig, dimensionsByIri);
62+
63+
expect(actualTitle).toBe(expectedTitle);
64+
});
65+
});

app/utils/title.ts

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import { t } from "@lingui/macro";
2+
3+
import { ChartConfig } from "@/config-types";
4+
import { Dimension, Measure } from "@/domain/data";
5+
6+
export function generateChartTitle(
7+
chartInfo: ChartConfig,
8+
dimensionsByIri: Record<string, Dimension | Measure>
9+
): string {
10+
const { chartType } = chartInfo;
11+
const getLabel = (type: "x" | "y" | "segment") => {
12+
const field = chartInfo.fields[type as keyof (typeof chartInfo)["fields"]];
13+
// @ts-ignore
14+
const iri = field?.componentIri;
15+
const dimension = dimensionsByIri[iri];
16+
return dimension?.label ?? "";
17+
};
18+
19+
// prettier-ignore
20+
const chartTitleLocales = {
21+
column: t({ id: "columnChart", message: `${getLabel("y")} per ${getLabel("x")}` }),
22+
line: t({ id: "lineChart", message: `Evolution of the ${getLabel("y")}` }),
23+
area: t({ id: "areaChart", message: `Distribution of ${getLabel("y")} over ${getLabel("x")}` }),
24+
areaSegmented: t({ id: `Shares of ${getLabel("y")} by ${getLabel("segment")}` }),
25+
pie: t({ id: "pieChart", message: `${getLabel("y")} per ${getLabel("segment")}` }),
26+
map: t({ id: "mapChart", message: `Geographical distribution of ${getLabel("y")}` }),
27+
scatterplot: t({ id: "scatterplotChart", message: `${getLabel("y")} against ${getLabel("x")}` }),
28+
table: t({ id: "tableChart", message: `Table` }),
29+
comboLineSingle: t({ id: "comboLineSingleChart", message: `Combo line single chart` }),
30+
comboLineDual: t({ id: "comboLineDuoChart", message: `Combo line dual chart` }),
31+
comboLineColumn: t({ id: "comboLineSingleChart", message: `Combo line column chart` }),
32+
};
33+
34+
const defaultChartTitle = `${chartType} Chart`;
35+
const chartTitle = chartTitleLocales[chartType] || defaultChartTitle;
36+
return chartTitle;
37+
}

0 commit comments

Comments
 (0)