Skip to content

Commit

Permalink
Merge pull request #983 from visualize-admin/fix/sorting
Browse files Browse the repository at this point in the history
  • Loading branch information
ptbrowne authored Feb 28, 2023
2 parents 0b8ca31 + 1b20ce0 commit 9ce79bb
Show file tree
Hide file tree
Showing 12 changed files with 350 additions and 294 deletions.
20 changes: 15 additions & 5 deletions app/components/metadata-panel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,9 @@ import match from "autosuggest-highlight/match";
import parse from "autosuggest-highlight/parse";
import clsx from "clsx";
import { AnimatePresence, Transition } from "framer-motion";
import orderBy from "lodash/orderBy";
import { useRouter } from "next/router";
import React from "react";
import React, { useMemo } from "react";
import { createStore, useStore } from "zustand";
import shallow from "zustand/shallow";

Expand All @@ -32,6 +33,7 @@ import { Icon } from "@/icons";
import SvgIcArrowRight from "@/icons/components/IcArrowRight";
import SvgIcClose from "@/icons/components/IcClose";
import { useEmbedOptions } from "@/utils/embed";
import { makeDimensionValueSorters } from "@/utils/sorting-values";
import useEvent from "@/utils/use-event";

import Flex from "./flex";
Expand Down Expand Up @@ -603,8 +605,16 @@ const TabPanelDataDimension = ({
};

const DimensionValues = ({ dim }: { dim: DimensionMetadataFragment }) => {
const sortedValues = useMemo(() => {
const sorters = makeDimensionValueSorters(dim);
return orderBy(
dim.values,
sorters.map((s) => (dv) => s(dv.label))
) as DimensionValue[];
}, [dim]);

if (isStandardErrorDimension(dim)) {
return <DimensionValuesNumeric values={dim.values} />;
return <DimensionValuesNumeric values={sortedValues} />;
}

switch (dim.__typename) {
Expand All @@ -613,11 +623,11 @@ const DimensionValues = ({ dim }: { dim: DimensionMetadataFragment }) => {
case "OrdinalMeasure":
case "GeoCoordinatesDimension":
case "GeoShapesDimension":
return <DimensionValuesNominal values={dim.values} />;
return <DimensionValuesNominal values={sortedValues} />;
case "NumericalMeasure":
case "TemporalDimension":
return dim.values.length > 0 ? (
<DimensionValuesNumeric values={dim.values} />
return sortedValues.length > 0 ? (
<DimensionValuesNumeric values={sortedValues} />
) : null;
default:
const _exhaustiveCheck: never = dim;
Expand Down
2 changes: 1 addition & 1 deletion app/components/publish-actions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -324,7 +324,7 @@ export const Embed = ({ configKey, locale }: EmbedShareProps) => {
<CopyToClipboardTextInput
mt={1}
mb={2}
content={`<iframe src="${embedIframeUrl}" style="border:0px #ffffff none;" name="visualize.admin.ch" scrolling="no" frameborder="1" marginheight="0px" marginwidth="0px" height="${iFrameHeight}" width="600px" allowfullscreen></iframe>`}
content={`<iframe src="${embedIframeUrl}" style="border:0px #ffffff none; max-width: 100%" name="visualize.admin.ch" scrolling="no" frameborder="1" marginheight="0px" marginwidth="0px" height="${iFrameHeight}" width="600px" allowfullscreen></iframe>`}
/>
</div>

Expand Down
13 changes: 12 additions & 1 deletion app/configurator/components/chart-configurator.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ const DataFilterSelectGeneric = ({
onClick={onRemove}
size="small"
>
<Icon name="trash" width="16" height="16" />
<Icon name="trash" size="16" />
</IconButton>
</Box>
);
Expand Down Expand Up @@ -624,6 +624,17 @@ export const ChartConfigurator = ({
</Trans>
</Typography>
) : null}
{filterDimensions.length === 0 ? (
<Typography
variant="body2"
color="text.secondary"
sx={{ mb: -4 }}
>
<Trans id="controls.section.data.filters.none">
No filters
</Trans>
</Typography>
) : null}
<DragDropContext onDragEnd={handleDragEnd}>
<Droppable droppableId="filters">
{(provided) => (
Expand Down
8 changes: 4 additions & 4 deletions app/configurator/components/chart-options-selector.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import get from "lodash/get";
import keyBy from "lodash/keyBy";
import { useCallback, useEffect, useMemo, useRef } from "react";

import { getFieldComponentIri } from "@/charts";
import { DEFAULT_SORTING, getFieldComponentIri } from "@/charts";
import {
chartConfigOptionsUISpec,
EncodingFieldType,
Expand Down Expand Up @@ -552,7 +552,7 @@ const ChartFieldSorting = ({
const locale = useLocale();
const [, dispatch] = useConfiguratorState();

const getSortingTypeLabel = (type: SortingType) => {
const getSortingTypeLabel = (type: SortingType): string => {
switch (type) {
case "byDimensionLabel":
return t({ id: "controls.sorting.byDimensionLabel", message: `Name` });
Expand All @@ -565,7 +565,7 @@ const ChartFieldSorting = ({
default:
const _sanityCheck: never = type;
console.warn(`Sorting type label is ${_sanityCheck}`);
return t({ id: "controls.sorting.byDimensionLabel", message: `Name` });
return getSortingTypeLabel(DEFAULT_SORTING["sortingType"]);
}
};

Expand Down Expand Up @@ -593,7 +593,7 @@ const ChartFieldSorting = ({
const activeSortingType = get(
state,
["chartConfig", "fields", field, "sorting", "sortingType"],
"byDimensionLabel"
DEFAULT_SORTING["sortingType"]
);

// FIXME: Remove this once it's properly encoded in chart-config-ui-options
Expand Down
79 changes: 46 additions & 33 deletions app/configurator/components/field.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,6 @@ import {
useConfiguratorState,
} from "@/configurator/configurator-state";
import { FIELD_VALUE_NONE } from "@/configurator/constants";
import { DimensionValue } from "@/domain/data";
import { truthy } from "@/domain/types";
import { useTimeFormatLocale } from "@/formatters";
import { DimensionMetadataFragment, TimeUnit } from "@/graphql/query-hooks";
Expand All @@ -81,6 +80,14 @@ const FieldEditIcon = () => {
};

const useStyles = makeStyles<Theme>((theme) => ({
root: {
display: "flex",
alignItems: "center",
gap: "0.25rem",
},
optional: {
paddingBottom: "4px",
},
loadingIndicator: {
color: theme.palette.grey[700],
display: "inline-block",
Expand Down Expand Up @@ -169,14 +176,12 @@ export const DataFilterSelect = ({
message: `No Filter`,
});

const optionalLabel = t({
id: "controls.select.optional",
message: `optional`,
});

const sortedValues = useMemo(() => {
const sorters = makeDimensionValueSorters(dimension);
const sortedValues = orderBy(dimension.values, sorters) as DimensionValue[];
const sortedValues = orderBy(
dimension.values,
sorters.map((s) => (dv) => s(dv.label))
);

return sortedValues;
}, [dimension]);
Expand Down Expand Up @@ -217,7 +222,7 @@ export const DataFilterSelect = ({
if (hierarchy && hierarchyOptions) {
return (
<SelectTree
label={isOptional ? `${label} (${optionalLabel})` : label}
label={<FieldLabel label={label} isOptional={isOptional} />}
options={hierarchyOptions}
onClose={handleClose}
onOpen={handleOpen}
Expand All @@ -232,7 +237,7 @@ export const DataFilterSelect = ({
return (
<Select
id={id}
label={isOptional ? `${label} (${optionalLabel})` : label}
label={<FieldLabel label={label} isOptional={isOptional} />}
disabled={disabled}
options={allValues}
sortOptions={false}
Expand Down Expand Up @@ -687,6 +692,34 @@ export const ColorPickerField = ({
);
};

const FieldLabel = ({
label,
isOptional,
isFetching,
}: {
label: React.ReactNode;
isOptional?: boolean;
isFetching?: boolean;
}) => {
const classes = useStyles();
const optionalLabel = t({
id: "controls.select.optional",
message: `optional`,
});
return (
<div className={classes.root}>
{label}

{isOptional ? (
<span className={classes.optional}>({optionalLabel})</span>
) : null}
{isFetching ? (
<CircularProgress size={12} className={classes.loadingIndicator} />
) : null}
</div>
);
};

export const ChartFieldField = ({
label,
field,
Expand All @@ -700,36 +733,19 @@ export const ChartFieldField = ({
optional?: boolean;
disabled?: boolean;
}) => {
const classes = useStyles();
const { fetching, ...fieldProps } = useChartFieldField({ field });

const noneLabel = t({
id: "controls.none",
message: "None",
});

const optionalLabel = t({
id: "controls.select.optional",
message: `optional`,
});

return (
<Select
key={`select-${field}-dimension`}
id={field}
label={
<>
{optional ? (
<span>
{label} ({optionalLabel})
</span>
) : (
<span>{label}</span>
)}
{fetching ? (
<CircularProgress size={12} className={classes.loadingIndicator} />
) : null}
</>
<FieldLabel isOptional={optional} isFetching={fetching} label={label} />
}
disabled={disabled || fetching}
options={
Expand Down Expand Up @@ -880,11 +896,6 @@ export const ChartOptionSelectField = <ValueType extends {} = string>({
message: "None",
});

const optionalLabel = t({
id: "controls.select.optional",
message: "optional",
});

const allOptions = useMemo(() => {
return isOptional
? [
Expand All @@ -902,7 +913,9 @@ export const ChartOptionSelectField = <ValueType extends {} = string>({
<Select
id={id}
disabled={disabled}
label={isOptional ? `${label} (${optionalLabel})` : label}
label={
<FieldLabel isOptional={isOptional} isFetching={false} label={label} />
}
options={allOptions}
{...fieldProps}
/>
Expand Down
10 changes: 5 additions & 5 deletions app/domain/data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ export type DimensionValue = {
description?: string;
position?: number;
color?: string;
identifier?: string;
identifier?: string | number;
alternateName?: string;
};

Expand Down Expand Up @@ -71,13 +71,13 @@ export type GeoData = {
};

const xmlSchema = "http://www.w3.org/2001/XMLSchema#";
export const parseRDFLiteral = (value: Literal): ObservationValue => {
export const parseRDFLiteral = <T = ObservationValue>(value: Literal): T => {
const v = value.value;
const dt = value.datatype.value.replace(xmlSchema, "");
switch (dt) {
case "string":
case "boolean":
return v;
return v as T;
// return v === "true" ? true : false;
case "float":
case "integer":
Expand All @@ -95,7 +95,7 @@ export const parseRDFLiteral = (value: Literal): ObservationValue => {
case "byte":
case "unsignedShort":
case "unsignedByte":
return +v;
return +v as T;
// TODO: Figure out how to preserve granularity of date (maybe include interval?)
// case "date":
// case "time":
Expand All @@ -104,7 +104,7 @@ export const parseRDFLiteral = (value: Literal): ObservationValue => {
// case "gYearMonth":
// return new Date(v);
default:
return v;
return v as T;
}
};

Expand Down
Loading

1 comment on commit 9ce79bb

@vercel
Copy link

@vercel vercel bot commented on 9ce79bb Feb 28, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

visualization-tool – ./

visualization-tool-ixt1.vercel.app
visualization-tool-git-main-ixt1.vercel.app
visualization-tool-alpha.vercel.app

Please sign in to comment.