Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 42 additions & 3 deletions app/components/chart-panel.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { Box, BoxProps, Theme } from "@mui/material";
import { makeStyles } from "@mui/styles";
import clsx from "clsx";
import React, { forwardRef, HTMLProps } from "react";
import keyBy from "lodash/keyBy";
import React, { forwardRef, HTMLProps, useMemo } from "react";

import ChartPanelLayoutCanvas, {
chartPanelLayoutGridClasses,
Expand All @@ -12,7 +13,8 @@ import { ChartSelectionTabs } from "@/components/chart-selection-tabs";
import { DashboardInteractiveFilters } from "@/components/dashboard-interactive-filters";
import { ChartConfig, Layout, LayoutDashboard } from "@/config-types";
import { hasChartConfigs } from "@/configurator";
import { useConfiguratorState } from "@/src";
import { useDataCubesComponentsQuery } from "@/graphql/hooks";
import { useConfiguratorState, useLocale } from "@/src";

const useStyles = makeStyles((theme: Theme) => ({
panelLayout: {
Expand Down Expand Up @@ -48,13 +50,50 @@ export const ChartWrapper = forwardRef<HTMLDivElement, ChartWrapperProps>(
(props, ref) => {
const { children, editing, layoutType, ...rest } = props;
const classes = useStyles();
const [state] = useConfiguratorState(hasChartConfigs);
const dataSource = state.dataSource;
const locale = useLocale();
const commonQueryVariables = {
sourceType: dataSource.type,
sourceUrl: dataSource.url,
locale,
};

const componentIris = undefined;
const chartConfig = state.chartConfigs.find(
(x) => x.key === state.activeChartKey
);
const [{ data: components }] = useDataCubesComponentsQuery({
variables: {
...commonQueryVariables,
cubeFilters:
chartConfig?.cubes.map((cube) => ({
iri: cube.iri,
componentIris,
filters: cube.filters,
joinBy: cube.joinBy,
})) ?? [],
},
});
const dimensionsByIri = useMemo(() => {
return keyBy(
[
...(components?.dataCubesComponents.dimensions ?? []),
...(components?.dataCubesComponents.measures ?? []),
],
(x) => x.iri
);
}, [components?.dataCubesComponents]);

return (
<Box
ref={ref}
{...rest}
className={clsx(classes.chartWrapper, props.className)}
>
{(editing || layoutType === "tab") && <ChartSelectionTabs />}
{(editing || layoutType === "tab") && (
<ChartSelectionTabs dimensionsByIri={dimensionsByIri} />
)}
<Box
className={classes.chartWrapperInner}
sx={{ minHeight: [150, 300, 500] }}
Expand Down
6 changes: 6 additions & 0 deletions app/components/chart-preview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ import {
} from "@/components/chart-table-preview";
import { useChartStyles } from "@/components/chart-utils";
import { ChartWithFilters } from "@/components/chart-with-filters";
import { DashboardInteractiveFilters } from "@/components/dashboard-interactive-filters";
import DebugPanel from "@/components/debug-panel";
import { DragHandle, DragHandleProps } from "@/components/drag-handle";
import Flex from "@/components/flex";
Expand Down Expand Up @@ -85,6 +86,11 @@ export const ChartPreview = (props: ChartPreviewProps) => {
// we switch tabs in the configurator, otherwise we end up with the wrong
// data in the downstream hooks (useDataCubesMetadataQuery, etc.)
<ChartTablePreviewProvider key={state.activeChartKey}>
{state.state !== "CONFIGURING_CHART" ? (
<DashboardInteractiveFilters
key={state.chartConfigs.map((x) => x.key).join(",")}
/>
) : null}
<ChartWrapper editing={editing} layoutType={layout.type}>
<ChartPreviewInner dataSource={dataSource} />
</ChartWrapper>
Expand Down
2 changes: 2 additions & 0 deletions app/components/chart-published.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import {
} from "@/components/chart-table-preview";
import { useChartStyles } from "@/components/chart-utils";
import { ChartWithFilters } from "@/components/chart-with-filters";
import { DashboardInteractiveFilters } from "@/components/dashboard-interactive-filters";
import Flex from "@/components/flex";
import { HintBlue, HintRed, HintYellow } from "@/components/hint";
import {
Expand Down Expand Up @@ -149,6 +150,7 @@ export const ChartPublished = (props: ChartPublishedProps) => {
)}
</Flex>
<ChartTablePreviewProvider>
<DashboardInteractiveFilters />
<ChartWrapper layoutType={state.layout.type}>
<ChartPublishedInner
dataSource={dataSource}
Expand Down
28 changes: 18 additions & 10 deletions app/components/chart-selection-tabs.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ import {
import { useSearchDatasetPanelStore } from "@/configurator/components/add-new-dataset-panel";
import { ChartTypeSelector } from "@/configurator/components/chart-type-selector";
import { getIconName } from "@/configurator/components/ui-helpers";
import { Dimension, Measure } from "@/domain/data";
import { useUserConfig } from "@/domain/user-configs";
import { useFlag } from "@/flags";
import { useDataCubesComponentsQuery } from "@/graphql/hooks";
Expand All @@ -56,6 +57,7 @@ import { defaultLocale, useLocale } from "@/locales";
import { createConfig, updateConfig } from "@/utils/chart-config/api";
import { createChartId } from "@/utils/create-chart-id";
import { getRouterChartId } from "@/utils/router/helpers";
import { generateChartTitle } from "@/utils/title";
import { replaceLinks } from "@/utils/ui-strings";
import useEvent from "@/utils/use-event";
import { useMutate } from "@/utils/use-fetch-data";
Expand Down Expand Up @@ -102,7 +104,11 @@ const TabsStateProvider = (props: React.PropsWithChildren<{}>) => {
);
};

export const ChartSelectionTabs = () => {
export const ChartSelectionTabs = ({
dimensionsByIri,
}: {
dimensionsByIri: Record<string, Dimension | Measure>;
}) => {
const [state] = useConfiguratorState(hasChartConfigs);
const editable =
isConfiguring(state) || isLayouting(state) || isPublishing(state);
Expand All @@ -123,7 +129,7 @@ export const ChartSelectionTabs = () => {
? d.meta.title[locale]
: d.meta.title[defaultLocale] !== ""
? d.meta.title[defaultLocale]
: t({ id: "annotation.add.title" }),
: generateChartTitle(d, dimensionsByIri),
};
});

Expand Down Expand Up @@ -936,14 +942,16 @@ const TabContent = (props: TabContentProps) => {
</Button>

{label ? (
<Button
variant="text"
color="primary"
className={classes.label}
onClick={onSwitchClick}
>
{label}
</Button>
<Tooltip title={label} enterDelay={750}>
<Button
variant="text"
color="primary"
className={classes.label}
onClick={onSwitchClick}
>
{label}
</Button>
</Tooltip>
) : null}
{editable && (
<Button
Expand Down
1 change: 1 addition & 0 deletions app/configurator/components/layout-configurator.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,7 @@ const LayoutSharedFiltersConfigurator = () => {
);

switch (layout.type) {
case "tab":
case "dashboard":
return (
<ControlSection
Expand Down
65 changes: 65 additions & 0 deletions app/utils/title.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import keyBy from "lodash/keyBy";

import { ChartConfig } from "@/configurator";
import { Dimension } from "@/domain/data";
import { generateChartTitle } from "@/utils/title";

const dimensionsByIri = keyBy(
[
{
iri: "emissions",
label: "Emissions of CO2",
__typename: "OrdinalDimension",
},
{ iri: "emissions", label: "Year", __typename: "TemporalDimension" },
{ iri: "gastype", label: "Type of Gas", __typename: "NominalDimension" },
] as Dimension[],
(x) => x.iri
);

describe("generateChartTitle", () => {
it("should generate the correct title for a column chart", () => {
const columnChartConfig = {
chartType: "column",
fields: {
x: { componentIri: "year" },
y: { componentIri: "emissions" },
},
} as ChartConfig;
const expectedTitle = "Emissions of CO2 per Year";

const actualTitle = generateChartTitle(columnChartConfig, dimensionsByIri);

expect(actualTitle).toBe(expectedTitle);
});

it("should generate the correct title for a line chart", () => {
const lineChartConfig = {
chartType: "line",
fields: {
x: { componentIri: "year" },
y: { componentIri: "emissions" },
},
} as ChartConfig;
const expectedTitle = "Evolution of the Emissions of CO2";

const actualTitle = generateChartTitle(lineChartConfig, dimensionsByIri);

expect(actualTitle).toBe(expectedTitle);
});

it("should generate the correct title for an area chart", () => {
const areaChartConfig = {
chartType: "pie",
fields: {
y: { componentIri: "emissions" },
segment: { componentIri: "gastype" },
},
} as ChartConfig;
const expectedTitle = "Shares of Emissions of CO2 by Type of Gas";

const actualTitle = generateChartTitle(areaChartConfig, dimensionsByIri);

expect(actualTitle).toBe(expectedTitle);
});
});
37 changes: 37 additions & 0 deletions app/utils/title.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { t } from "@lingui/macro";

import { ChartConfig } from "@/config-types";
import { Dimension, Measure } from "@/domain/data";

export function generateChartTitle(
chartInfo: ChartConfig,
dimensionsByIri: Record<string, Dimension | Measure>
): string {
const { chartType } = chartInfo;
const getLabel = (type: "x" | "y" | "segment") => {
const field = chartInfo.fields[type as keyof (typeof chartInfo)["fields"]];
// @ts-ignore
const iri = field?.componentIri;
const dimension = dimensionsByIri[iri];
return dimension?.label ?? "";
};

// prettier-ignore
const chartTitleLocales = {
column: t({ id: "columnChart", message: `${getLabel("y")} per ${getLabel("x")}` }),
line: t({ id: "lineChart", message: `Evolution of the ${getLabel("y")}` }),
area: t({ id: "areaChart", message: `Distribution of ${getLabel("y")} over ${getLabel("x")}` }),
areaSegmented: t({ id: `Shares of ${getLabel("y")} by ${getLabel("segment")}` }),
pie: t({ id: "pieChart", message: `${getLabel("y")} per ${getLabel("segment")}` }),
map: t({ id: "mapChart", message: `Geographical distribution of ${getLabel("y")}` }),
scatterplot: t({ id: "scatterplotChart", message: `${getLabel("y")} against ${getLabel("x")}` }),
table: t({ id: "tableChart", message: `Table` }),
comboLineSingle: t({ id: "comboLineSingleChart", message: `Combo line single chart` }),
comboLineDual: t({ id: "comboLineDuoChart", message: `Combo line dual chart` }),
comboLineColumn: t({ id: "comboLineSingleChart", message: `Combo line column chart` }),
};

const defaultChartTitle = `${chartType} Chart`;
const chartTitle = chartTitleLocales[chartType] || defaultChartTitle;
return chartTitle;
}