Skip to content

Commit

Permalink
Merge pull request #1516 from visualize-admin/feat/preparation-dashboard
Browse files Browse the repository at this point in the history
Preparation dashboard
  • Loading branch information
ptbrowne authored May 16, 2024
2 parents dbf2931 + 90367c1 commit ef4dd08
Show file tree
Hide file tree
Showing 30 changed files with 1,734 additions and 689 deletions.
6 changes: 1 addition & 5 deletions .storybook/main.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
import type { StorybookConfig } from "@storybook/nextjs";
import { dirname, join, resolve } from "path";

// @ts-ignore

/**
* This function is used to resolve the absolute path of a package.
* It is needed in projects that use Yarn PnP or are set up within a monorepo.
Expand All @@ -22,9 +20,7 @@ const config: StorybookConfig = {
name: getAbsolutePath("@storybook/nextjs"),
options: {},
},
docs: {
autodocs: "tag",
},
docs: {},
webpackFinal: async (config) => {
if (!config.resolve) {
config.resolve = {};
Expand Down
6 changes: 3 additions & 3 deletions app/browser/dataset-browse.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -250,8 +250,8 @@ const termsetNavItemTheme: NavItemTheme = {
activeBg: "grey.300",
activeTextColor: "grey.900",
textColor: "grey.700",
countColor: "grey.200",
countBg: "grey.600",
countColor: "grey.800",
countBg: "grey.300",
closeColor: "grey.700",
showAllColor: "grey.600",
iconColor: "grey.700",
Expand Down Expand Up @@ -651,7 +651,7 @@ const TermsetNavSection = ({
);
return {
counts,
termsets,
termsets: sortBy(termsets, (t) => t.label),
};
}, [termsetCounts]);

Expand Down
4 changes: 2 additions & 2 deletions app/charts/area/areas-state.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ import { AreaConfig } from "@/configurator";
import { Observation } from "@/domain/data";
import { useFormatNumber, useTimeFormatUnit } from "@/formatters";
import { getPalette } from "@/palettes";
import { useInteractiveFilters } from "@/stores/interactive-filters";
import { useChartInteractiveFilters } from "@/stores/interactive-filters";
import { sortByIndex } from "@/utils/array";
import {
getSortingOrders,
Expand Down Expand Up @@ -107,7 +107,7 @@ const useAreasState = (
const formatNumber = useFormatNumber({ decimals: "auto" });
const formatters = useChartFormatters(chartProps);
const timeFormatUnit = useTimeFormatUnit();
const calculationType = useInteractiveFilters((d) => d.calculation.type);
const calculationType = useChartInteractiveFilters((d) => d.calculation.type);

const segmentsByValue = useMemo(() => {
const values = segmentDimension?.values ?? [];
Expand Down
4 changes: 2 additions & 2 deletions app/charts/column/columns-stacked-state.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ import { ColumnConfig } from "@/configurator";
import { Observation } from "@/domain/data";
import { useFormatNumber } from "@/formatters";
import { getPalette } from "@/palettes";
import { useInteractiveFilters } from "@/stores/interactive-filters";
import { useChartInteractiveFilters } from "@/stores/interactive-filters";
import { sortByIndex } from "@/utils/array";
import {
getSortingOrders,
Expand Down Expand Up @@ -114,7 +114,7 @@ const useColumnsStackedState = (
const width = useWidth();
const formatNumber = useFormatNumber({ decimals: "auto" });
const formatters = useChartFormatters(chartProps);
const calculationType = useInteractiveFilters((d) => d.calculation.type);
const calculationType = useChartInteractiveFilters((d) => d.calculation.type);

const xKey = fields.x.componentIri;

Expand Down
6 changes: 3 additions & 3 deletions app/charts/shared/axis-height-linear.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { axisLeft, axisRight } from "d3-axis";
import { NumberValue, ScaleLinear } from "d3-scale";
import React, { useEffect, useRef, useState, useCallback } from "react";
import { useCallback, useEffect, useRef, useState } from "react";

import type { AreasState } from "@/charts/area/areas-state";
import type { GroupedColumnsState } from "@/charts/column/columns-grouped-state";
Expand All @@ -18,7 +18,7 @@ import { getTickNumber } from "@/charts/shared/ticks";
import { useChartTheme } from "@/charts/shared/use-chart-theme";
import { OpenMetadataPanelWrapper } from "@/components/metadata-panel";
import { useFormatNumber } from "@/formatters";
import { useInteractiveFilters } from "@/stores/interactive-filters";
import { useChartInteractiveFilters } from "@/stores/interactive-filters";
import { useTransitionStore } from "@/stores/transition";
import { getTextWidth } from "@/utils/get-text-width";

Expand Down Expand Up @@ -101,7 +101,7 @@ export const useRenderAxisHeightLinear = (
const transitionDuration = useTransitionStore((state) => state.duration);
const { labelFontSize, fontFamily } = useChartTheme();
const formatNumber = useFormatNumber({ decimals: "auto" });
const calculationType = useInteractiveFilters((d) => d.calculation.type);
const calculationType = useChartInteractiveFilters((d) => d.calculation.type);
const normalized = calculationType === "percent";
const ticks = getTickNumber(height);
const tickFormat = useCallback(
Expand Down
12 changes: 6 additions & 6 deletions app/charts/shared/brush/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ import { useChartTheme } from "@/charts/shared/use-chart-theme";
import { Observation } from "@/domain/data";
import { useFormatFullDateAuto } from "@/formatters";
import {
useInteractiveFilters,
useInteractiveFiltersRaw,
useChartInteractiveFilters,
useInteractiveFiltersGetState,
} from "@/stores/interactive-filters";
import { useTransitionStore } from "@/stores/transition";
import { getTextWidth } from "@/utils/get-text-width";
Expand All @@ -27,9 +27,9 @@ export const HEIGHT = HANDLE_HEIGHT + BRUSH_HEIGHT;

export const BrushTime = () => {
const ref = useRef<SVGGElement>(null);
const timeRange = useInteractiveFilters((d) => d.timeRange);
const setTimeRange = useInteractiveFilters((d) => d.setTimeRange);
const IFStateRaw = useInteractiveFiltersRaw();
const timeRange = useChartInteractiveFilters((d) => d.timeRange);
const setTimeRange = useChartInteractiveFilters((d) => d.setTimeRange);
const getInteractiveFiltersState = useInteractiveFiltersGetState();
const setEnableTransition = useTransitionStore((d) => d.setEnable);
const formatDateAuto = useFormatFullDateAuto();
const [brushedIsEnded, updateBrushEndedStatus] = useState(true);
Expand Down Expand Up @@ -109,7 +109,7 @@ export const BrushTime = () => {
// and the local state accessed here is not up to date. This leads to
// making a dispatch on each brush move, which makes the animations laggy
// and generally shouldn't happen.
const { from, to } = IFStateRaw.getState().timeRange;
const { from, to } = getInteractiveFiltersState().timeRange;

if (
from?.getTime() !== newFrom.getTime() ||
Expand Down
20 changes: 11 additions & 9 deletions app/charts/shared/chart-data-filters.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { t, Trans } from "@lingui/macro";
import { Box, Button, SelectChangeEvent, Typography } from "@mui/material";
import isEmpty from "lodash/isEmpty";
import isEqual from "lodash/isEqual";
import React, { useMemo, useState, useEffect, useRef } from "react";
import React, { useEffect, useMemo, useRef, useState } from "react";
import { useClient } from "urql";

import { useQueryFilters } from "@/charts/shared/chart-helpers";
Expand Down Expand Up @@ -49,8 +49,8 @@ import { Icon } from "@/icons";
import { useLocale } from "@/locales/use-locale";
import {
DataFilters,
useInteractiveFilters,
useInteractiveFiltersRaw,
useChartInteractiveFilters,
useInteractiveFiltersGetState,
} from "@/stores/interactive-filters";
import { hierarchyToOptions } from "@/utils/hierarchy";
import useEvent from "@/utils/use-event";
Expand All @@ -70,7 +70,7 @@ type ChartDataFiltersProps = {
export const ChartDataFilters = (props: ChartDataFiltersProps) => {
const { dataSource, chartConfig } = props;
const { loading } = useLoadingState();
const dataFilters = useInteractiveFilters((d) => d.dataFilters);
const dataFilters = useChartInteractiveFilters((d) => d.dataFilters);
const componentIris = chartConfig.interactiveFiltersConfig?.dataFilters
.componentIris as string[];
const queryFilters = useQueryFilters({
Expand Down Expand Up @@ -228,7 +228,9 @@ const DataFilter = (props: DataFilterProps) => {
const locale = useLocale();
const filters = useChartConfigFilters(chartConfig);
const chartLoadingState = useLoadingState();
const updateDataFilter = useInteractiveFilters((d) => d.updateDataFilter);
const updateDataFilter = useChartInteractiveFilters(
(d) => d.updateDataFilter
);
const otherKeys = Object.keys(interactiveFilters).filter(
(key) => key !== dimensionIri
);
Expand Down Expand Up @@ -557,8 +559,8 @@ const useEnsurePossibleInteractiveFilters = (
const [error, setError] = useState<Error>();
const lastFilters = useRef<Record<string, Filters>>({});
const client = useClient();
const IFRaw = useInteractiveFiltersRaw();
const setDataFilters = useInteractiveFilters((d) => d.setDataFilters);
const getInteractiveFiltersState = useInteractiveFiltersGetState();
const setDataFilters = useChartInteractiveFilters((d) => d.setDataFilters);
const filtersByCubeIri = useMemo(() => {
return preparedFilters?.reduce<Record<string, PreparedFilter>>((acc, d) => {
acc[d.cubeIri] = d;
Expand Down Expand Up @@ -633,7 +635,7 @@ const useEnsurePossibleInteractiveFilters = (

// We need to get the values dynamically, as they can get updated by
// useSyncInteractiveFilters and this callback runs with old value.
const dataFilters = { ...IFRaw.getState().dataFilters };
const dataFilters = { ...getInteractiveFiltersState().dataFilters };
const filtersToUpdate = Object.fromEntries(
Object.entries(filters).filter(
([k, v]) => k in dataFilters && v.type === "single"
Expand Down Expand Up @@ -664,8 +666,8 @@ const useEnsurePossibleInteractiveFilters = (
dataSource,
setDataFilters,
loadingState,
IFRaw,
filtersByCubeIri,
getInteractiveFiltersState,
]);

return { error };
Expand Down
2 changes: 1 addition & 1 deletion app/charts/shared/chart-helpers.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ jest.mock("../../rdf/extended-cube", () => ({
}));

jest.mock("@/stores/interactive-filters", () => ({
useInteractiveFilters: jest.fn(() => ({
useChartInteractiveFilters: jest.fn(() => ({
A_1: { type: "single", value: "A_1_1" },
A_2: { type: "single", value: "A_2_1" },
B_1: { type: "single", value: "B_1_1" },
Expand Down
6 changes: 4 additions & 2 deletions app/charts/shared/chart-helpers.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ import { getOriginalIris, isJoinById } from "@/graphql/join";
import { DataCubeObservationFilter } from "@/graphql/resolver-types";
import {
InteractiveFiltersState,
useInteractiveFilters,
useChartInteractiveFilters,
} from "@/stores/interactive-filters";

// Prepare filters used in data query:
Expand Down Expand Up @@ -82,7 +82,9 @@ export const useQueryFilters = ({
allowNoneValues?: boolean;
componentIris?: string[];
}): DataCubeObservationFilter[] => {
const allInteractiveDataFilters = useInteractiveFilters((d) => d.dataFilters);
const allInteractiveDataFilters = useChartInteractiveFilters(
(d) => d.dataFilters
);
return useMemo(() => {
return chartConfig.cubes.map((cube) => {
const cubeFilters = getChartConfigFilters(chartConfig.cubes, {
Expand Down
8 changes: 4 additions & 4 deletions app/charts/shared/chart-state.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ import {
} from "@/domain/data";
import { Has } from "@/domain/types";
import { TimeUnit } from "@/graphql/resolver-types";
import { useInteractiveFilters } from "@/stores/interactive-filters";
import { useChartInteractiveFilters } from "@/stores/interactive-filters";

export type ChartState =
| AreasState
Expand Down Expand Up @@ -400,9 +400,9 @@ export const useChartData = (
}
): Omit<ChartStateData, "allData"> => {
const { interactiveFiltersConfig } = chartConfig;
const categories = useInteractiveFilters((d) => d.categories);
const timeRange = useInteractiveFilters((d) => d.timeRange);
const timeSlider = useInteractiveFilters((d) => d.timeSlider);
const categories = useChartInteractiveFilters((d) => d.categories);
const timeRange = useChartInteractiveFilters((d) => d.timeRange);
const timeSlider = useChartInteractiveFilters((d) => d.timeSlider);

// time range
const timeRangeFilterComponentIri =
Expand Down
10 changes: 6 additions & 4 deletions app/charts/shared/interactive-filter-calculation-toggle.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
import { t } from "@lingui/macro";
import React, { useCallback } from "react";
import { useCallback } from "react";

import { Switch } from "@/components/form";
import { useInteractiveFilters } from "@/stores/interactive-filters";
import { useChartInteractiveFilters } from "@/stores/interactive-filters";

export const CalculationToggle = () => {
const calculation = useInteractiveFilters((d) => d.calculation);
const setCalculationType = useInteractiveFilters((d) => d.setCalculationType);
const calculation = useChartInteractiveFilters((d) => d.calculation);
const setCalculationType = useChartInteractiveFilters(
(d) => d.setCalculationType
);

const onChange = useCallback(() => {
setCalculationType(calculation.type === "percent" ? "identity" : "percent");
Expand Down
8 changes: 4 additions & 4 deletions app/charts/shared/legend-color.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ import {
isOrdinalMeasure,
} from "@/domain/data";
import SvgIcChevronRight from "@/icons/components/IcChevronRight";
import { useInteractiveFilters } from "@/stores/interactive-filters";
import { useChartInteractiveFilters } from "@/stores/interactive-filters";
import { interlace } from "@/utils/interlace";
import { MaybeTooltip } from "@/utils/maybe-tooltip";
import { makeDimensionValueSorters } from "@/utils/sorting-values";
Expand Down Expand Up @@ -286,9 +286,9 @@ const LegendColorContent = (props: LegendColorContentProps) => {
numberOfOptions,
} = props;
const classes = useStyles();
const categories = useInteractiveFilters((d) => d.categories);
const addCategory = useInteractiveFilters((d) => d.addCategory);
const removeCategory = useInteractiveFilters((d) => d.removeCategory);
const categories = useChartInteractiveFilters((d) => d.categories);
const addCategory = useChartInteractiveFilters((d) => d.addCategory);
const removeCategory = useChartInteractiveFilters((d) => d.removeCategory);
const activeInteractiveFilters = useMemo(() => {
return new Set(Object.keys(categories));
}, [categories]);
Expand Down
10 changes: 9 additions & 1 deletion app/charts/shared/overlay-voronoi.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import { ScatterplotState } from "@/charts/scatterplot/scatterplot-state";
import { useChartState } from "@/charts/shared/chart-state";
import { useInteraction } from "@/charts/shared/use-interaction";

const atLeastZero = (n: number) => (n < 0 ? 0 : n);

export const InteractionVoronoi = memo(function InteractionVoronoi({
debug,
}: {
Expand All @@ -26,7 +28,13 @@ export const InteractionVoronoi = memo(function InteractionVoronoi({
(d) => xScale(getX(d) ?? NaN),
(d) => yScale(getY(d) ?? NaN)
);
const voronoi = delaunay.voronoi([0, 0, chartWidth, chartHeight]);

const voronoi = delaunay.voronoi([
0,
0,
atLeastZero(chartWidth),
atLeastZero(chartHeight),
]);

const findLocation = (e: ReactMouseEvent) => {
const [x, y] = pointer(e, ref.current!);
Expand Down
11 changes: 7 additions & 4 deletions app/charts/shared/use-sync-interactive-filters.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@ import { useState } from "react";
import useSyncInteractiveFilters from "@/charts/shared/use-sync-interactive-filters";
import { ChartConfig, InteractiveFiltersConfig } from "@/config-types";
import {
InteractiveFiltersChartProvider,
InteractiveFiltersProvider,
useInteractiveFilters,
useChartInteractiveFilters,
} from "@/stores/interactive-filters";
import fixture from "@/test/__fixtures/config/dev/4YL1p4QTFQS4.json";
import { migrateChartConfig } from "@/utils/chart-config/versioning";
Expand Down Expand Up @@ -55,7 +56,7 @@ const setup = ({
modifiedChartConfig: ChartConfig;
}) => {
const Component = () => {
const IFState = useInteractiveFilters((d) => ({
const IFState = useChartInteractiveFilters((d) => ({
categories: d.categories,
timeRange: d.timeRange,
timeSlider: d.timeSlider,
Expand All @@ -78,8 +79,10 @@ const setup = ({
);
};
const root = render(
<InteractiveFiltersProvider>
<Component />
<InteractiveFiltersProvider chartConfigs={[chartConfig]}>
<InteractiveFiltersChartProvider chartConfigKey={chartConfig.key}>
<Component />
</InteractiveFiltersChartProvider>
</InteractiveFiltersProvider>
);
const getIFState = () =>
Expand Down
18 changes: 11 additions & 7 deletions app/charts/shared/use-sync-interactive-filters.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import {
import { parseDate } from "@/configurator/components/ui-helpers";
import { FIELD_VALUE_NONE } from "@/configurator/constants";
import useFilterChanges from "@/configurator/use-filter-changes";
import { useInteractiveFilters } from "@/stores/interactive-filters";
import { useChartInteractiveFilters } from "@/stores/interactive-filters";

/**
* Makes sure interactive filters are in sync with chart config.
Expand All @@ -21,12 +21,16 @@ import { useInteractiveFilters } from "@/stores/interactive-filters";
const useSyncInteractiveFilters = (chartConfig: ChartConfig) => {
const { interactiveFiltersConfig } = chartConfig;
const filters = useChartConfigFilters(chartConfig);
const resetCategories = useInteractiveFilters((d) => d.resetCategories);
const dataFilters = useInteractiveFilters((d) => d.dataFilters);
const setDataFilters = useInteractiveFilters((d) => d.setDataFilters);
const updateDataFilter = useInteractiveFilters((d) => d.updateDataFilter);
const setTimeRange = useInteractiveFilters((d) => d.setTimeRange);
const setCalculationType = useInteractiveFilters((d) => d.setCalculationType);
const resetCategories = useChartInteractiveFilters((d) => d.resetCategories);
const dataFilters = useChartInteractiveFilters((d) => d.dataFilters);
const setDataFilters = useChartInteractiveFilters((d) => d.setDataFilters);
const updateDataFilter = useChartInteractiveFilters(
(d) => d.updateDataFilter
);
const setTimeRange = useChartInteractiveFilters((d) => d.setTimeRange);
const setCalculationType = useChartInteractiveFilters(
(d) => d.setCalculationType
);

// Time range filter
const presetFrom =
Expand Down
Loading

0 comments on commit ef4dd08

Please sign in to comment.