Skip to content

Commit d1b6b86

Browse files
committed
feat: Sort table rows by position -> label
1 parent 0cd8b67 commit d1b6b86

2 files changed

Lines changed: 43 additions & 17 deletions

File tree

app/charts/table/table-state.tsx

Lines changed: 34 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,12 @@ import {
99
scaleOrdinal,
1010
scaleDiverging,
1111
scaleLinear,
12+
ascending,
1213
} from "d3";
1314
import mapKeys from "lodash/mapKeys";
1415
import mapValues from "lodash/mapValues";
1516
import { ReactNode, useMemo } from "react";
16-
import { Cell, Column } from "react-table";
17+
import { Cell, Column, Row } from "react-table";
1718

1819
import {
1920
getLabelWithUnit,
@@ -38,6 +39,7 @@ import { useFormatNumber, useDimensionFormatters } from "@/formatters";
3839
import { getColorInterpolator } from "@/palettes";
3940
import { useTheme } from "@/themes";
4041
import { estimateTextWidth } from "@/utils/estimate-text-width";
42+
import { makeDimensionValueSorters } from "@/utils/sorting-values";
4143

4244
export type MKColumnMeta<T> = {
4345
iri: string;
@@ -145,7 +147,7 @@ const useTableState = ({
145147
// Data used by react-table
146148
const memoizedData = useMemo(
147149
function replaceKeys() {
148-
//Only read keys once
150+
// Only read keys once
149151
const keys = Object.keys(data[0]);
150152
const slugifiedKeys = keys.map(getSlugifiedIri);
151153

@@ -165,18 +167,25 @@ const useTableState = ({
165167
},
166168
[data, types]
167169
);
170+
168171
// Columns used by react-table
169172
const tableColumns = useMemo(() => {
173+
const allComponents = [...dimensions, ...measures];
174+
170175
return orderedTableColumns.map((c) => {
171-
const headerDimension = [...dimensions, ...measures].find(
172-
(dim) => dim.iri === c.componentIri
176+
const headerComponent = allComponents.find(
177+
(d) => d.iri === c.componentIri
173178
);
174179

175-
if (!headerDimension) {
180+
if (!headerComponent) {
176181
throw Error(`No dimension <${c.componentIri}> in cube!`);
177182
}
178183

179-
const headerLabel = getLabelWithUnit(headerDimension);
184+
const sorters = makeDimensionValueSorters(headerComponent, {
185+
sorting: { sortingType: "byTableSortingType", sortingOrder: "asc" },
186+
});
187+
188+
const headerLabel = getLabelWithUnit(headerComponent);
180189

181190
// The column width depends on the estimated width of the
182191
// longest value in the column, with a minimum of 150px.
@@ -203,9 +212,24 @@ const useTableState = ({
203212
accessor: getSlugifiedIri(c.componentIri),
204213

205214
width,
206-
// If sort type is not "basic", react-table default to "alphanumeric"
207-
// which doesn't sort negative values properly.
208-
sortType: "basic",
215+
sortType: (
216+
rowA: Row<Observation>,
217+
rowB: Row<Observation>,
218+
colId: string
219+
) => {
220+
for (const d of sorters) {
221+
const result = ascending(
222+
d(rowA.values[colId]),
223+
d(rowB.values[colId])
224+
);
225+
226+
if (result) {
227+
return result;
228+
}
229+
}
230+
231+
return 0;
232+
},
209233
};
210234
});
211235
}, [orderedTableColumns, data, dimensions, measures, formatNumber]);
@@ -337,22 +361,16 @@ const useTableState = ({
337361
),
338362
];
339363
const columnItemSizes = columnItems.map((item) => {
340-
// @ts-ignore
341364
const itemAsString = formatter(item);
342365
return estimateTextWidth(`${itemAsString}`, 16) + 80;
343366
});
344367
const width =
345368
Math.max(max(columnItemSizes, (d) => d) || 150, 150) -
346369
BAR_CELL_PADDING * 2;
347-
// const hasNegativeValue =
348-
// (min(data, (d) => Math.abs(+d[iri])) || 0) < 0;
349370
const domain = extent(columnItems, (d) => d) as [number, number];
350371
const widthScale = scaleLinear().domain(domain).range([0, width]);
351372

352-
return {
353-
...common,
354-
widthScale,
355-
} as BarColumnMeta;
373+
return { ...common, widthScale } as BarColumnMeta;
356374
} else {
357375
return null as never;
358376
}

app/utils/sorting-values.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,13 @@ export const makeDimensionValueSorters = (
2424
>["dimensions"][number]
2525
| undefined,
2626
options: {
27-
sorting?: NonNullable<SortingField["sorting"]> | undefined;
27+
sorting?:
28+
| NonNullable<SortingField["sorting"]>
29+
| {
30+
sortingType: "byTableSortingType";
31+
sortingOrder: "asc";
32+
}
33+
| undefined;
2834
sumsBySegment?: Record<string, number | null>;
2935
measureBySegment?: Record<string, number | null>;
3036
} = {}
@@ -74,6 +80,8 @@ export const makeDimensionValueSorters = (
7480
case "byAuto":
7581
sorters = [getPosition, getIdentifier];
7682
break;
83+
case "byTableSortingType":
84+
sorters = [getPosition, getLabel];
7785
default:
7886
sorters = defaultSorters;
7987
}

0 commit comments

Comments
 (0)