diff --git a/app/configurator/components/chart-configurator.tsx b/app/configurator/components/chart-configurator.tsx index 15bf3235e..85818ffb8 100644 --- a/app/configurator/components/chart-configurator.tsx +++ b/app/configurator/components/chart-configurator.tsx @@ -2,6 +2,12 @@ import { Trans } from "@lingui/macro"; import { sortBy } from "lodash"; import * as React from "react"; import { useCallback } from "react"; +import { + DragDropContext, + Droppable, + Draggable, + OnDragEndResponder, +} from "react-beautiful-dnd"; import { Box, Spinner } from "theme-ui"; import { ChartConfig, @@ -13,6 +19,7 @@ import { chartConfigOptionsUISpec } from "../../charts/chart-config-ui-options"; import { Loading } from "../../components/hint"; import { useDataCubeMetadataWithComponentValuesQuery } from "../../graphql/query-hooks"; import { DataCubeMetadata } from "../../graphql/types"; +import { Icon } from "../../icons"; import { useLocale } from "../../locales/use-locale"; import { ensureFilterValuesCorrect, @@ -69,7 +76,7 @@ const DataFilterSelectGeneric = ({ ); return ( - + {dimension.__typename === "TemporalDimension" && dimension.timeUnit !== "Day" ? ( !mappedIris.has(dim.iri)), [(x) => keysOrder[x.iri] ?? Infinity] ); + + const handleDragEnd: OnDragEndResponder = (result) => { + const sourceIndex = result.source?.index; + const destinationIndex = result.destination?.index; + if ( + typeof sourceIndex !== "number" || + typeof destinationIndex !== "number" || + result.source === result.destination + ) { + return; + } + const delta = destinationIndex - sourceIndex; + handleMove(result.draggableId, delta); + }; return ( <> @@ -212,7 +233,6 @@ export const ChartConfigurator = ({ /> - Filters{" "} @@ -220,16 +240,51 @@ export const ChartConfigurator = ({ ) : null} + - {filterDimensions.map((dimension, i) => ( - handleMove(dimension.iri, n)} - disabled={fetching} - /> - ))} + + + {(provided) => ( +
+ {filterDimensions.map((dimension, i) => ( + + {(provided) => ( +
+ + handleMove(dimension.iri, n)} + disabled={fetching} + /> + + +
+ )} +
+ ))} + {provided.placeholder} +
+ )} +
+
diff --git a/app/configurator/configurator-state.tsx b/app/configurator/configurator-state.tsx index a3ae55518..251e05484 100644 --- a/app/configurator/configurator-state.tsx +++ b/app/configurator/configurator-state.tsx @@ -233,7 +233,10 @@ export const ensureFilterValuesCorrect = produce( export const moveFilterField = produce( (chartConfig: ChartConfig, { dimensionIri, delta, possibleValues }) => { - const keys = Object.keys(chartConfig.filters); + // Use getOwnPropertyNames instead of keys since the spec ensures that + // the order of the keys received is in insertion order + // https://262.ecma-international.org/6.0/#sec-ordinary-object-internal-methods-and-internal-slots-ownpropertykeys + const keys = Object.getOwnPropertyNames(chartConfig.filters); const fieldIndex = Object.keys(chartConfig.filters).indexOf(dimensionIri); if (fieldIndex === 0 && delta === -1) { return;