Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dashboard filters #1545

Merged
merged 37 commits into from
Jun 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
737f540
feat: WIP Add shared filters configurator panel
ptbrowne May 14, 2024
0e09000
feat: Add dashboard interactive filters (time)
ptbrowne May 10, 2024
01659ab
feat: Hide brushes if we find a dashboard shared filter
ptbrowne May 14, 2024
71e58ef
feat: Show dashboard interactive filters in chart panel layout
ptbrowne May 22, 2024
7ed0b55
docs: Add comment on what to do
ptbrowne May 22, 2024
408f3d0
feat: Connect dimension time unit to slider
ptbrowne May 30, 2024
8a92505
refactor: Remove unnecessary property
ptbrowne May 30, 2024
220bad3
refactor: Extract logic to show brush
ptbrowne May 30, 2024
c45ea82
feat: Show correctly shared filters, not when configuring
ptbrowne May 30, 2024
3b24ace
feat: Add dashboard filters
ptbrowne May 30, 2024
f787f93
refactor: Move configurator-state and add dashboardFilters in mock data
ptbrowne May 30, 2024
52d73b5
refactor: Auto format
ptbrowne May 30, 2024
1cdbc13
refactor: Explode the configurator-state giant file
ptbrowne May 30, 2024
794db0b
feat: Saving state in chart config as dashboardFilters
ptbrowne May 30, 2024
b18d702
fix: Use correct attributes
ptbrowne May 31, 2024
e41a8f3
fix: Errors in console
ptbrowne May 31, 2024
dec193c
feat: Dashboard filters can be toggled on/off and are not tied to int…
ptbrowne May 31, 2024
1c6b2fa
feat: Only 1 type of shared filter right now
ptbrowne May 31, 2024
64f7579
feat: Only show dashboard interactive filters on dashboard layout
ptbrowne May 31, 2024
b41626b
refactor: Rename file
ptbrowne May 31, 2024
d423a78
fix: Make sure the default version is the latest one
ptbrowne May 31, 2024
811b63e
fix: Correctly mock
ptbrowne May 31, 2024
34ee5d2
refactor: Extract helper
ptbrowne Jun 3, 2024
030c3c3
fix: Adjust mocks and providers for test
ptbrowne Jun 3, 2024
00f4fab
feat: Ability to update temporal shared filter
ptbrowne Jun 3, 2024
452be97
docs: Add comment
ptbrowne Jun 3, 2024
f681d03
fix: Our tooltip have arrows
ptbrowne Jun 3, 2024
04c2611
refactor: Remove unnecessary
ptbrowne Jun 3, 2024
5a3cc6b
refactor: Rename for clarity
ptbrowne Jun 3, 2024
ac6c54f
refactor: Simplify time formatters and parsers definition
ptbrowne Jun 3, 2024
4e2fce5
fix: Can add a new chart when cube is joined
ptbrowne Jun 3, 2024
dffc190
fix: Hide information icon when on second page of add dataset dialog
ptbrowne Jun 4, 2024
63c935b
fix: Dashboard interactive filters do not crash when there are merged…
ptbrowne Jun 4, 2024
fb4614e
fix: Support charts with merged data and not merged data for dashboar…
ptbrowne Jun 4, 2024
374fa09
fix: Shared filter layout configurator collapses correctly
ptbrowne Jun 4, 2024
ec0ef5f
fix: Dashboard shared filter can work on merged cubes
ptbrowne Jun 4, 2024
910bf8a
fix: Add translations
ptbrowne Jun 4, 2024
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
15 changes: 11 additions & 4 deletions app/charts/column/chart-column.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import {
AxisWidthBand,
AxisWidthBandDomain,
} from "@/charts/shared/axis-width-band";
import { BrushTime } from "@/charts/shared/brush";
import { BrushTime, shouldShowBrush } from "@/charts/shared/brush";
import {
ChartContainer,
ChartControlsContainer,
Expand All @@ -26,6 +26,7 @@ import { Tooltip } from "@/charts/shared/interaction/tooltip";
import { LegendColor } from "@/charts/shared/legend-color";
import { ColumnConfig, useChartConfigFilters } from "@/config-types";
import { TimeSlider } from "@/configurator/interactive-filters/time-slider";
import { useDashboardInteractiveFilters } from "@/stores/interactive-filters";

import { ChartProps, VisualizationProps } from "../shared/ChartProps";

Expand All @@ -39,6 +40,12 @@ export const ChartColumns = memo((props: ChartProps<ColumnConfig>) => {
const { chartConfig, dimensions } = props;
const { fields, interactiveFiltersConfig } = chartConfig;
const filters = useChartConfigFilters(chartConfig);
const { sharedFilters } = useDashboardInteractiveFilters();

const showTimeBrush = shouldShowBrush(
interactiveFiltersConfig,
sharedFilters
);

return (
<>
Expand All @@ -49,7 +56,7 @@ export const ChartColumns = memo((props: ChartProps<ColumnConfig>) => {
<AxisHeightLinear /> <AxisWidthBand />
<ColumnsStacked /> <AxisWidthBandDomain />
<InteractionColumns />
{interactiveFiltersConfig?.timeRange.active && <BrushTime />}
{showTimeBrush && <BrushTime />}
</ChartSvg>
<Tooltip type="multiple" />
</ChartContainer>
Expand Down Expand Up @@ -80,7 +87,7 @@ export const ChartColumns = memo((props: ChartProps<ColumnConfig>) => {
<ErrorWhiskersGrouped />
<AxisWidthBandDomain />
<InteractionColumns />
{interactiveFiltersConfig?.timeRange.active && <BrushTime />}
{showTimeBrush && <BrushTime />}
</ChartSvg>
<Tooltip type="multiple" />
</ChartContainer>
Expand Down Expand Up @@ -111,7 +118,7 @@ export const ChartColumns = memo((props: ChartProps<ColumnConfig>) => {
<ErrorWhiskers />
<AxisWidthBandDomain />
<InteractionColumns />
{interactiveFiltersConfig?.timeRange.active && <BrushTime />}
{showTimeBrush && <BrushTime />}
</ChartSvg>
<Tooltip type="single" />
</ChartContainer>
Expand Down
8 changes: 6 additions & 2 deletions app/charts/combo/chart-combo-line-column.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,13 @@ import { AxisHeightLinearDual } from "@/charts/combo/axis-height-linear-dual";
import { ComboLineColumn } from "@/charts/combo/combo-line-column";
import { ComboLineColumnChart } from "@/charts/combo/combo-line-column-state";
import { AxisWidthBand } from "@/charts/shared/axis-width-band";
import { BrushTime } from "@/charts/shared/brush";
import { BrushTime, shouldShowBrush } from "@/charts/shared/brush";
import { ChartContainer, ChartSvg } from "@/charts/shared/containers";
import { HoverDotMultiple } from "@/charts/shared/interaction/hover-dots-multiple";
import { Ruler } from "@/charts/shared/interaction/ruler";
import { Tooltip } from "@/charts/shared/interaction/tooltip";
import { ComboLineColumnConfig } from "@/config-types";
import { useDashboardInteractiveFilters } from "@/stores/interactive-filters";

import { ChartProps, VisualizationProps } from "../shared/ChartProps";

Expand All @@ -25,6 +26,7 @@ export const ChartComboLineColumn = memo(
(props: ChartProps<ComboLineColumnConfig>) => {
const { chartConfig } = props;
const { interactiveFiltersConfig } = chartConfig;
const { sharedFilters } = useDashboardInteractiveFilters();

return (
<ComboLineColumnChart {...props}>
Expand All @@ -35,7 +37,9 @@ export const ChartComboLineColumn = memo(
<AxisWidthBand />
<ComboLineColumn />
<InteractionColumns />
{interactiveFiltersConfig?.timeRange.active && <BrushTime />}
{shouldShowBrush(interactiveFiltersConfig, sharedFilters) && (
<BrushTime />
)}
</ChartSvg>
<HoverDotMultiple />
<Ruler rotate />
Expand Down
8 changes: 6 additions & 2 deletions app/charts/combo/chart-combo-line-dual.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,14 @@ import { AxisHeightLinearDual } from "@/charts/combo/axis-height-linear-dual";
import { ComboLineDual } from "@/charts/combo/combo-line-dual";
import { ComboLineDualChart } from "@/charts/combo/combo-line-dual-state";
import { AxisTime, AxisTimeDomain } from "@/charts/shared/axis-width-time";
import { BrushTime } from "@/charts/shared/brush";
import { BrushTime, shouldShowBrush } from "@/charts/shared/brush";
import { ChartContainer, ChartSvg } from "@/charts/shared/containers";
import { HoverDotMultiple } from "@/charts/shared/interaction/hover-dots-multiple";
import { Ruler } from "@/charts/shared/interaction/ruler";
import { Tooltip } from "@/charts/shared/interaction/tooltip";
import { InteractionHorizontal } from "@/charts/shared/overlay-horizontal";
import { ComboLineDualConfig } from "@/config-types";
import { useDashboardInteractiveFilters } from "@/stores/interactive-filters";

import { ChartProps, VisualizationProps } from "../shared/ChartProps";

Expand All @@ -25,6 +26,7 @@ export const ChartComboLineDual = memo(
(props: ChartProps<ComboLineDualConfig>) => {
const { chartConfig } = props;
const { interactiveFiltersConfig } = chartConfig;
const { sharedFilters } = useDashboardInteractiveFilters();

return (
<ComboLineDualChart {...props}>
Expand All @@ -35,7 +37,9 @@ export const ChartComboLineDual = memo(
<AxisTimeDomain />
<ComboLineDual />
<InteractionHorizontal />
{interactiveFiltersConfig?.timeRange.active && <BrushTime />}
{shouldShowBrush(interactiveFiltersConfig, sharedFilters) && (
<BrushTime />
)}
</ChartSvg>
<HoverDotMultiple />
<Ruler />
Expand Down
9 changes: 7 additions & 2 deletions app/charts/combo/chart-combo-line-single.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { ComboLineSingle } from "@/charts/combo/combo-line-single";
import { ComboLineSingleChart } from "@/charts/combo/combo-line-single-state";
import { AxisHeightLinear } from "@/charts/shared/axis-height-linear";
import { AxisTime, AxisTimeDomain } from "@/charts/shared/axis-width-time";
import { BrushTime } from "@/charts/shared/brush";
import { BrushTime, shouldShowBrush } from "@/charts/shared/brush";
import {
ChartContainer,
ChartControlsContainer,
Expand All @@ -17,6 +17,7 @@ import { Tooltip } from "@/charts/shared/interaction/tooltip";
import { LegendColor } from "@/charts/shared/legend-color";
import { InteractionHorizontal } from "@/charts/shared/overlay-horizontal";
import { ComboLineSingleConfig } from "@/config-types";
import { useDashboardInteractiveFilters } from "@/stores/interactive-filters";

import { ChartProps, VisualizationProps } from "../shared/ChartProps";

Expand All @@ -30,6 +31,8 @@ export const ChartComboLineSingle = memo(
(props: ChartProps<ComboLineSingleConfig>) => {
const { chartConfig, measures } = props;
const { interactiveFiltersConfig } = chartConfig;
const { sharedFilters } = useDashboardInteractiveFilters();

const getLegendItemDimension = useCallback(
(label: string) => {
return measures.find((measure) => measure.label === label);
Expand All @@ -44,7 +47,9 @@ export const ChartComboLineSingle = memo(
<AxisHeightLinear /> <AxisTime /> <AxisTimeDomain />
<ComboLineSingle />
<InteractionHorizontal />
{interactiveFiltersConfig?.timeRange.active && <BrushTime />}
{shouldShowBrush(interactiveFiltersConfig, sharedFilters) && (
<BrushTime />
)}
</ChartSvg>
<HoverDotMultiple />
<Ruler />
Expand Down
5 changes: 3 additions & 2 deletions app/charts/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -338,7 +338,7 @@ export const META: Meta = {

type GetInitialConfigOptions = {
key?: string;
iris: { iri: string; publishIri: string }[];
iris: { iri: string; publishIri: string; joinBy?: string[] }[];
chartType: ChartType;
dimensions: Dimension[];
measures: Measure[];
Expand All @@ -364,10 +364,11 @@ export const getInitialConfig = (
// Technically, we should scope filters per cube; but as we only set initial
// filters for area charts, and we can only have multi-cubes for combo charts,
// we can ignore the filters scoping for now.
cubes: iris.map(({ iri, publishIri }) => ({
cubes: iris.map(({ iri, publishIri, joinBy }) => ({
iri,
publishIri,
filters: filters ?? {},
joinBy,
})),
activeField: undefined,
};
Expand Down
8 changes: 6 additions & 2 deletions app/charts/line/chart-lines.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { Lines } from "@/charts/line/lines";
import { LineChart } from "@/charts/line/lines-state";
import { AxisHeightLinear } from "@/charts/shared/axis-height-linear";
import { AxisTime, AxisTimeDomain } from "@/charts/shared/axis-width-time";
import { BrushTime } from "@/charts/shared/brush";
import { BrushTime, shouldShowBrush } from "@/charts/shared/brush";
import {
ChartContainer,
ChartControlsContainer,
Expand All @@ -17,6 +17,7 @@ import { Tooltip } from "@/charts/shared/interaction/tooltip";
import { LegendColor } from "@/charts/shared/legend-color";
import { InteractionHorizontal } from "@/charts/shared/overlay-horizontal";
import { LineConfig } from "@/config-types";
import { useDashboardInteractiveFilters } from "@/stores/interactive-filters";

import { ChartProps, VisualizationProps } from "../shared/ChartProps";

Expand All @@ -29,6 +30,7 @@ export const ChartLinesVisualization = (
export const ChartLines = memo((props: ChartProps<LineConfig>) => {
const { chartConfig } = props;
const { fields, interactiveFiltersConfig } = chartConfig;
const { sharedFilters } = useDashboardInteractiveFilters();

return (
<LineChart {...props}>
Expand All @@ -37,7 +39,9 @@ export const ChartLines = memo((props: ChartProps<LineConfig>) => {
<AxisHeightLinear /> <AxisTime /> <AxisTimeDomain />
<Lines />
<InteractionHorizontal />
{interactiveFiltersConfig?.timeRange.active && <BrushTime />}
{shouldShowBrush(interactiveFiltersConfig, sharedFilters) && (
<BrushTime />
)}
</ChartSvg>

<Ruler />
Expand Down
30 changes: 30 additions & 0 deletions app/charts/shared/brush/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,17 @@ import { makeGetClosestDatesFromDateRange } from "@/charts/shared/brush/utils";
import type { ChartWithInteractiveXTimeRangeState } from "@/charts/shared/chart-state";
import { useChartState } from "@/charts/shared/chart-state";
import { useChartTheme } from "@/charts/shared/use-chart-theme";
import {
ColumnConfig,
ComboLineColumnConfig,
ComboLineDualConfig,
ComboLineSingleConfig,
LineConfig,
} from "@/configurator";
import { Observation } from "@/domain/data";
import { useFormatFullDateAuto } from "@/formatters";
import {
SharedFilter,
useChartInteractiveFilters,
useInteractiveFiltersGetState,
} from "@/stores/interactive-filters";
Expand All @@ -26,6 +34,28 @@ export const HANDLE_HEIGHT = 14;
export const BRUSH_HEIGHT = 3;
export const HEIGHT = HANDLE_HEIGHT + BRUSH_HEIGHT;

export const shouldShowBrush = (
interactiveFiltersConfig:
| (
| LineConfig
| ComboLineSingleConfig
| ComboLineDualConfig
| ComboLineColumnConfig
| ColumnConfig
)["interactiveFiltersConfig"]
| undefined,
sharedFilters: SharedFilter[] | undefined
) => {
const chartTimeRange = interactiveFiltersConfig?.timeRange;
const chartTimeRangeIri = chartTimeRange?.componentIri;
const sharedFilter = sharedFilters?.find(
(x) => x.type === "timeRange" && x.componentIri === chartTimeRangeIri
);
return (
(chartTimeRange?.active && !sharedFilter) || sharedFilter?.active == false
);
};

export const BrushTime = () => {
const ref = useRef<SVGGElement>(null);
const timeRange = useChartInteractiveFilters((d) => d.timeRange);
Expand Down
50 changes: 11 additions & 39 deletions app/charts/shared/chart-data-filters.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import {
canRenderDatePickerField,
DatePickerField,
} from "@/configurator/components/field-date-picker";
import { extractDataPickerOptionsFromDimension } from "@/configurator/components/ui-helpers";
import { FIELD_VALUE_NONE } from "@/configurator/constants";
import {
Dimension,
Expand Down Expand Up @@ -340,15 +341,17 @@ const DataFilter = (props: DataFilterProps) => {
);
};

type DataFilterGenericDimensionProps = {
export type DataFilterGenericDimensionProps = {
dimension: Dimension;
value: string;
onChange: (e: SelectChangeEvent<unknown>) => void;
options?: Array<{ label: string; value: string }>;
disabled: boolean;
};

const DataFilterGenericDimension = (props: DataFilterGenericDimensionProps) => {
export const DataFilterGenericDimension = (
props: DataFilterGenericDimensionProps
) => {
const { dimension, value, onChange, options: propOptions, disabled } = props;
const { label, isKeyDimension } = dimension;
const noneLabel = t({
Expand Down Expand Up @@ -465,48 +468,17 @@ const DataFilterTemporalDimension = ({
) => void;
disabled: boolean;
}) => {
const { isKeyDimension, label, values, timeUnit, timeFormat } = dimension;
const { label, timeUnit, timeFormat } = dimension;
const formatLocale = useTimeFormatLocale();
const formatDate = formatLocale.format(timeFormat);
const parseDate = formatLocale.parse(timeFormat);

const noneLabel = t({
id: "controls.dimensionvalue.none",
message: "No Filter",
});
const { minDate, maxDate, options, optionValues } = useMemo(() => {
if (values.length) {
const options = values.map((d) => {
return {
label: `${d.value}`,
value: `${d.value}`,
};
});

return {
minDate: parseDate(values[0].value as string) as Date,
maxDate: parseDate(values[values.length - 1].value as string) as Date,
options: isKeyDimension
? options
: [
{
value: FIELD_VALUE_NONE,
label: noneLabel,
isNoneValue: true,
},
...options,
],
optionValues: options.map((d) => d.value),
};
} else {
return {
minDate: new Date(),
maxDate: new Date(),
options: [],
optionValues: [],
};
}
}, [isKeyDimension, noneLabel, values, parseDate]);
return extractDataPickerOptionsFromDimension({
dimension,
parseDate,
});
}, [dimension, parseDate]);

return canRenderDatePickerField(timeUnit) ? (
<DatePickerField
Expand Down
Loading
Loading