diff --git a/app/charts/area/areas-state.tsx b/app/charts/area/areas-state.tsx index 5aae3466d..f80ab4dcd 100644 --- a/app/charts/area/areas-state.tsx +++ b/app/charts/area/areas-state.tsx @@ -19,7 +19,7 @@ import { sum, } from "d3"; import keyBy from "lodash/keyBy"; -import sortBy from "lodash/sortBy" +import sortBy from "lodash/sortBy"; import { ReactNode, useCallback, useMemo } from "react"; import { LEFT_MARGIN_OFFSET } from "@/charts/area/constants"; @@ -68,6 +68,7 @@ export interface AreasState { segments: string[]; colors: ScaleOrdinal; yAxisLabel: string; + yAxisDescription: string | undefined; chartWideData: ArrayLike; allDataWide: ArrayLike; series: $FixMe[]; @@ -207,6 +208,7 @@ const useAreasState = ( } const yAxisLabel = getLabelWithUnit(yMeasure); + const yAxisDescription = yMeasure.description || undefined; /** Ordered segments */ const segmentSortingType = fields.segment?.sorting?.sortingType; @@ -426,6 +428,7 @@ const useAreasState = ( yScale, getSegment, yAxisLabel, + yAxisDescription, segments, colors, chartWideData, diff --git a/app/charts/bar/bars-state.tsx b/app/charts/bar/bars-state.tsx index 6bbb17a71..352419128 100644 --- a/app/charts/bar/bars-state.tsx +++ b/app/charts/bar/bars-state.tsx @@ -41,6 +41,7 @@ export interface BarsState { getSegment: (d: Observation) => string; segments: string[]; xAxisLabel: string; + xAxisDescription: string | undefined; colors: ScaleOrdinal; } @@ -64,9 +65,10 @@ const useBarsState = ({ const getY = useStringVariable(fields.y.componentIri); const getSegment = useSegment(fields.segment?.componentIri); - const xAxisLabel = - measures.find((d) => d.iri === fields.x.componentIri)?.label ?? - fields.y.componentIri; + const xMeasure = measures.find((d) => d.iri === fields.x.componentIri); + + const xAxisLabel = xMeasure?.label ?? fields.y.componentIri; + const xAxisDescription = xMeasure?.description || undefined; // Sort data const sortingType = fields.y.sorting?.sortingType; @@ -123,6 +125,7 @@ const useBarsState = ({ getSegment, segments, xAxisLabel, + xAxisDescription, colors, }; }; diff --git a/app/charts/column/columns-state.tsx b/app/charts/column/columns-state.tsx index 76f22e54f..3e9764a6c 100644 --- a/app/charts/column/columns-state.tsx +++ b/app/charts/column/columns-state.tsx @@ -75,6 +75,7 @@ export interface ColumnsState { segments: string[]; colors: ScaleOrdinal; yAxisLabel: string; + yAxisDescription: string | undefined; getAnnotationInfo: (d: Observation) => TooltipInfo; showStandardError: boolean; } @@ -221,6 +222,7 @@ const useColumnsState = ( } const yAxisLabel = getLabelWithUnit(yMeasure); + const yAxisDescription = yMeasure.description || undefined; const { left, bottom } = useChartPadding( yScale, @@ -343,6 +345,7 @@ const useColumnsState = ( getSegment, getSegmentLabel, yAxisLabel, + yAxisDescription, segments, colors, getAnnotationInfo, diff --git a/app/charts/line/lines-state.tsx b/app/charts/line/lines-state.tsx index 81a1ac0eb..427d9837b 100644 --- a/app/charts/line/lines-state.tsx +++ b/app/charts/line/lines-state.tsx @@ -12,7 +12,7 @@ import { scaleTime, } from "d3"; import keyBy from "lodash/keyBy"; -import sortBy from "lodash/sortBy" +import sortBy from "lodash/sortBy"; import { ReactNode, useCallback, useMemo } from "react"; import { LEFT_MARGIN_OFFSET } from "@/charts/line/constants"; @@ -62,6 +62,7 @@ export interface LinesState { colors: ScaleOrdinal; xAxisLabel: string; yAxisLabel: string; + yAxisDescription: string | undefined; grouped: Map; chartWideData: ArrayLike; allDataWide: ArrayLike; @@ -187,6 +188,7 @@ const useLinesState = ( } const yAxisLabel = getLabelWithUnit(yMeasure); + const yAxisDescription = yMeasure.description || undefined; const segmentDimension = useMemo(() => { return ( @@ -344,6 +346,7 @@ const useLinesState = ( getSegmentLabel, xAxisLabel, yAxisLabel, + yAxisDescription, segments, colors, grouped: preparedDataGroupedBySegment, diff --git a/app/charts/scatterplot/scatterplot-state.tsx b/app/charts/scatterplot/scatterplot-state.tsx index 71f1e711a..bbd289989 100644 --- a/app/charts/scatterplot/scatterplot-state.tsx +++ b/app/charts/scatterplot/scatterplot-state.tsx @@ -45,7 +45,9 @@ export interface ScatterplotState { getSegment: (d: Observation) => string; colors: ScaleOrdinal; xAxisLabel: string; + xAxisDescription: string | undefined; yAxisLabel: string; + yAxisDescription: string | undefined; getSegmentLabel: (s: string) => string; getAnnotationInfo: (d: Observation, values: Observation[]) => TooltipInfo; } @@ -79,7 +81,7 @@ const useScatterplotState = ({ const plottableSortedData = usePlottableData({ data: sortedData, - plotters: [getX, getY] + plotters: [getX, getY], }); // Data for chart @@ -96,6 +98,7 @@ const useScatterplotState = ({ } const xAxisLabel = getLabelWithUnit(xMeasure); + const xAxisDescription = xMeasure.description || undefined; const xMinValue = Math.min(mkNumber(min(preparedData, (d) => getX(d))), 0); const xMaxValue = max(preparedData, (d) => getX(d)) as number; @@ -109,6 +112,7 @@ const useScatterplotState = ({ } const yAxisLabel = getLabelWithUnit(yMeasure); + const yAxisDescription = yMeasure.description || undefined; const yMinValue = Math.min(mkNumber(min(preparedData, (d) => getY(d))), 0); const yMaxValue = max(preparedData, getY) as number; @@ -240,7 +244,9 @@ const useScatterplotState = ({ getSegment, colors, xAxisLabel, + xAxisDescription, yAxisLabel, + yAxisDescription, getAnnotationInfo, getSegmentLabel, }; diff --git a/app/charts/shared/axis-height-linear.tsx b/app/charts/shared/axis-height-linear.tsx index 80e3017c3..65d3de8f0 100644 --- a/app/charts/shared/axis-height-linear.tsx +++ b/app/charts/shared/axis-height-linear.tsx @@ -5,9 +5,11 @@ import { useEffect, useRef } from "react"; import { AreasState } from "@/charts/area/areas-state"; import { ColumnsState } from "@/charts/column/columns-state"; import { LinesState } from "@/charts/line/lines-state"; +import { ScatterplotState } from "@/charts/scatterplot/scatterplot-state"; import { useChartState } from "@/charts/shared/use-chart-state"; import { useChartTheme } from "@/charts/shared/use-chart-theme"; import { useFormatNumber } from "@/configurator/components/ui-helpers"; +import { MaybeTooltip } from "@/utils/maybe-tooltip"; export const TICK_MIN_HEIGHT = 50; @@ -19,10 +21,11 @@ export const AxisHeightLinear = () => { const ref = useRef(null); const formatNumber = useFormatNumber(); - const { yScale, yAxisLabel, bounds } = useChartState() as + const { yScale, yAxisLabel, yAxisDescription, bounds } = useChartState() as + | AreasState | ColumnsState | LinesState - | AreasState; + | ScatterplotState; const ticks = getTickNumber(bounds.chartHeight); @@ -55,9 +58,17 @@ export const AxisHeightLinear = () => { return ( <> - - {yAxisLabel} - + + + {yAxisLabel} + + { const formatNumber = useFormatNumber(); - const { xScale, bounds, xAxisLabel, chartType } = useChartState() as - | ScatterplotState - | BarsState; + const { xScale, bounds, xAxisLabel, xAxisDescription, chartType } = + useChartState() as ScatterplotState | BarsState; const { chartWidth, chartHeight, margins } = bounds; const { domainColor, labelColor, labelFontSize, gridColor, fontFamily } = useChartTheme(); @@ -62,15 +62,18 @@ export const AxisWidthLinear = () => { return ( <> - - {xAxisLabel} - + + + {xAxisLabel} + + ) : dimension.timeUnit === TimeUnit.Year ? ( @@ -203,12 +204,14 @@ const DataFilterBaseDimension = ({ label, options, value, + tooltipText, onChange, }: { isKeyDimension: boolean; label: string; options: Array<{ label: string; value: string }>; value: string; + tooltipText?: string; onChange: (e: SelectChangeEvent) => void; }) => { const noneLabel = t({ @@ -234,6 +237,7 @@ const DataFilterBaseDimension = ({ label={label} options={allOptions} value={value} + tooltipText={tooltipText} onChange={onChange} /> ); @@ -246,6 +250,7 @@ const DataFilterTemporalDimension = ({ timeUnit, timeFormat, value, + tooltipText, onChange, }: { isKeyDimension: boolean; @@ -254,6 +259,7 @@ const DataFilterTemporalDimension = ({ timeUnit: TimeUnit; timeFormat: string; value: string; + tooltipText?: string; onChange: (e: SelectChangeEvent) => void; }) => { const formatLocale = useTimeFormatLocale(); @@ -279,6 +285,7 @@ const DataFilterTemporalDimension = ({ label={label} options={timeIntervalOptions} value={value} + tooltipText={tooltipText} onChange={onChange} /> ); @@ -289,6 +296,7 @@ const DataFilterTemporalDimension = ({ id="dataFilterTemporalDimension" label={label} value={value} + tooltipText={tooltipText} timeFormat={timeFormat} formatLocale={formatLocale} isOptional={!isKeyDimension} diff --git a/app/charts/table/table-content.tsx b/app/charts/table/table-content.tsx index ec765706c..f780b24a9 100644 --- a/app/charts/table/table-content.tsx +++ b/app/charts/table/table-content.tsx @@ -1,9 +1,11 @@ -import { Box, TableSortLabel, Theme, Tooltip } from "@mui/material"; +import { Box, TableSortLabel, Theme } from "@mui/material"; import { makeStyles } from "@mui/styles"; import clsx from "clsx"; import React, { useMemo, useContext } from "react"; import { HeaderGroup } from "react-table"; +import { MaybeTooltip } from "@/utils/maybe-tooltip"; + import Flex from "../../components/flex"; import { Observation } from "../../domain/data"; @@ -105,15 +107,17 @@ export const TableContent = ({ children }: { children: React.ReactNode }) => { active={isCustomSorted} direction={column.isSortedDesc ? "desc" : "asc"} > - {description ? ( - - - {column.render("Header")} - - - ) : ( - column.render("Header") - )} + + + {column.render("Header")} + + ); diff --git a/app/components/chart-filters-list.tsx b/app/components/chart-filters-list.tsx index fa2733329..9b0c31c7e 100644 --- a/app/components/chart-filters-list.tsx +++ b/app/components/chart-filters-list.tsx @@ -1,4 +1,4 @@ -import { Box, Typography, Tooltip } from "@mui/material"; +import { Box, Typography } from "@mui/material"; import { Fragment } from "react"; import { useQueryFilters } from "@/charts/shared/chart-helpers"; @@ -6,6 +6,7 @@ import { ChartConfig, DataSource } from "@/configurator"; import { useTimeFormatUnit } from "@/configurator/components/ui-helpers"; import { useDataCubeMetadataWithComponentValuesQuery } from "@/graphql/query-hooks"; import { useLocale } from "@/locales/use-locale"; +import { MaybeTooltip } from "@/utils/maybe-tooltip"; export const ChartFiltersList = ({ dataSetIri, @@ -74,15 +75,17 @@ export const ChartFiltersList = ({ {namedFilters.map(({ dimension, value }, i) => ( - {dimension.description ? ( - - - {dimension.label} - - - ) : ( - dimension.label - )} + + + {dimension.label} + + {": "} diff --git a/app/components/form.tsx b/app/components/form.tsx index c782fe8fb..b7ac0ce59 100644 --- a/app/components/form.tsx +++ b/app/components/form.tsx @@ -34,29 +34,41 @@ import { import { useBrowseContext } from "@/configurator/components/dataset-browse"; import { Icon } from "@/icons"; import { useLocale } from "@/locales/use-locale"; +import { MaybeTooltip } from "@/utils/maybe-tooltip"; export const Label = ({ htmlFor, + tooltipText, smaller = false, children, sx, }: { htmlFor: string; + tooltipText?: string; smaller?: boolean; children: ReactNode; sx?: TypographyProps["sx"]; -}) => ( - - {children} - -); +}) => { + return ( + + + {children} + + + ); +}; export const Radio = ({ label, @@ -250,6 +262,7 @@ export const Select = ({ sortOptions = true, controls, optionGroups, + tooltipText, }: { id: string; options: Option[]; @@ -258,6 +271,7 @@ export const Select = ({ sortOptions?: boolean; controls?: React.ReactNode; optionGroups?: [OptionGroup, Option[]][]; + tooltipText?: string; } & SelectProps) => { const locale = useLocale(); @@ -276,10 +290,11 @@ export const Select = ({ return getSelectOptions(options, sortOptions, locale); } }, [optionGroups, sortOptions, locale, options]); + return ( {label && ( -