Skip to content

Commit

Permalink
feat(Table): sortable columns (#233)
Browse files Browse the repository at this point in the history
  • Loading branch information
etienneburdet authored May 27, 2024
1 parent 53d2faf commit 8addb80
Show file tree
Hide file tree
Showing 12 changed files with 22,655 additions and 20,013 deletions.
42,463 changes: 22,458 additions & 20,005 deletions package-lock.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
},
"devDependencies": {
"lerna": "^8.1.2",
"nx": "^18.0.8"
"nx": "^19.0.7"
},
"dependencies": {
"-": "^0.0.1"
Expand Down
79 changes: 79 additions & 0 deletions packages/visualizations-react/stories/Table/Sort.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
import React, { useState, useEffect } from 'react';
import { ComponentMeta, ComponentStory } from '@storybook/react';
import type { TableData, Async, ColumnSortValues, DataFrame } from '@opendatasoft/visualizations';
import { ColumnSort } from '@opendatasoft/visualizations';
import { Table } from '../../src';
import value from './data';
import options from './options';
import { fetchData } from './utils';

import './custom-style.css';

const meta: ComponentMeta<typeof Table> = {
title: 'Table/Sort',
component: Table,
};
export default meta;

const data: Async<TableData> = {
value,
loading: false,
};

const sortColumn = (sort: [string, ColumnSortValues], key: string) =>
sort[0] === key && sort[1] === 'ASC' ? 'DESC' : 'ASC';

const Template: ComponentStory<typeof Table> = args => {
const { options: unsortedOptions } = args;
const [sort, setSort] = useState<[string, ColumnSortValues]>(['title', ColumnSort.asc]);
const [records, setRecords] = useState<DataFrame>();

useEffect(() => {
(async () => {
const newRecords = await fetchData({
size: 5,
data: value,
sort,
page: 1,
});
setRecords(newRecords);
})();
}, [setRecords, sort]);

const sortedData = { value: records, isLoading: false };

const sortableColumns = unsortedOptions.columns.map((col, i) => ({
...col,
sorted: sort[0] === col.key ? sort[1] : undefined,
// cheap way to have some not sortable
onClick: i < 2 ? () => setSort([col.key, sortColumn(sort, col.key)]) : undefined,
}));

const sortedOptions = {
...options,
columns: sortableColumns,
};
return <Table data={sortedData} options={sortedOptions} />;
};

export const Sort = Template.bind({});
Sort.args = {
data,
options: {
...options,
},
};

const ColoredTemplate: ComponentStory<typeof Table> = args => (
<div className="design-system">
<Template {...args} />
</div>
);

export const ColorSort = ColoredTemplate.bind({});
ColorSort.args = {
data,
options: {
...options,
},
};
5 changes: 5 additions & 0 deletions packages/visualizations-react/stories/Table/custom-style.css
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,8 @@
.table-story--custom-style .numbering {
color: #808080;
}

.design-system svg {
--selected: #142e7b;
--neutral: #cbd2db;
}
25 changes: 25 additions & 0 deletions packages/visualizations-react/stories/Table/utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import type { ColumnSortValues, DataFrame } from '@opendatasoft/visualizations';
import { ColumnSort } from '@opendatasoft/visualizations';
// eslint-disable-next-line import/prefer-default-export
export const fetchData = async ({
size,
page,
data,
sort,
}: {
size: number;
page: number;
data: DataFrame;
sort?: [string, ColumnSortValues];
}) => {
const startIndex = (page - 1) * size;
const endIndex = startIndex + size;
await setTimeout(() => {}, 300);
const dataFrame: DataFrame = data?.slice(startIndex, endIndex);
if (sort) {
return dataFrame.sort((r1, r2) =>
sort[1] === ColumnSort.asc ? r1[sort[0]] - r2[sort[0]] : r2[sort[0]] - r1[sort[0]]
);
}
return dataFrame;
};
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
<script lang="ts">
import type { Column } from './types';
import SortButton from './SortButton.svelte';
import type { Column } from '../types';
export let columns: Column[];
</script>
Expand All @@ -8,9 +9,18 @@
<tr>
{#each columns as column}
<th class={`table-header--${column.dataFormat}`}>
{column.title}
</th>
{/each}
{#if column.onClick}
<SortButton
sorted={column?.sorted}
on:click={column.onClick}
labels={column.sortLabels}
>
{column.title}
</SortButton>
{:else}
{column.title}
{/if}
</th>{/each}
</tr>
</thead>

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<script lang="ts">
import { ColumnSort, type ColumnSortValues } from '../types';
import SortIcon from './SortIcon.svelte';
export let sorted: ColumnSortValues | undefined;
export let labels = {
asc: 'Sort ascending',
desc: 'Sort descending',
};
</script>

<button on:click type="button" aria-label={sorted === ColumnSort.asc ? labels.asc : labels.desc}>
<slot />
<SortIcon {sorted} />
</button>

<style>
button {
font-size: inherit;
font-weight: inherit;
text-align: inherit;
border: none;
background: transparent;
box-shadow: none;
cursor: pointer;
width: 100%;
height: 100%;
padding: 0;
display: flex;
justify-content: space-between;
}
</style>
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<script lang="ts">
import { ColumnSort, type ColumnSortValues } from "../types";
export let sorted: ColumnSortValues | undefined;
</script>

<svg width="16" height="17" viewBox="0 0 16 17" fill="none" xmlns="http://www.w3.org/2000/svg">
<path
d="m12 10.5-4 4-4-4h8zM12"
fill={sorted === ColumnSort.asc ? 'var(--selected)' : 'var(--neutral)'}
/>
<path
d="m12 6.5l-4-4-4 4h8z"
fill={sorted === ColumnSort.desc ? 'var(--selected)' : 'var(--neutral)'}
/>
</svg>

<style>
svg {
--selected: black;
--neutral: grey;
}
</style>
3 changes: 3 additions & 0 deletions packages/visualizations/src/components/Table/Headers/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import Headers from './Headers.svelte';

export default Headers;
4 changes: 2 additions & 2 deletions packages/visualizations/src/components/Table/Table.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import type { DataFrame } from '../types';
import type { Column } from './types';
import { generateId } from '../utils';
import Header from './Header.svelte';
import Headers from './Headers';
import Body from './Body.svelte';
export let columns: Column[];
Expand All @@ -14,7 +14,7 @@

<div>
<table aria-describedby={description ? tableId : undefined}>
<Header {columns} />
<Headers {columns} />
{#if records}
<Body {records} {columns} />
{/if}
Expand Down
13 changes: 13 additions & 0 deletions packages/visualizations/src/components/Table/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,22 @@ export type DataFormat = typeof DATA_FORMAT[DataFormatKey];

export type TableData = DataFrame;

export const ColumnSort = {
asc: 'ASC',
desc: 'DESC',
} as const;
export type ColumnSortValues = typeof ColumnSort[keyof typeof ColumnSort];

type BaseColumn = {
key: string;
title: string;
/** Wtether the column is sorted ascendimg, descending or not */
sorted?: ColumnSortValues;
sortLabels?: {
asc: string;
desc: string;
};
onClick?: () => void;
};

export type ShortTextColumn = BaseColumn & {
Expand Down
1 change: 0 additions & 1 deletion packages/visualizations/src/components/utils/Card.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@
{/if}
</div>

<!-- markup (zero or more items) goes here -->
<style>
h3,
p {
Expand Down

2 comments on commit 8addb80

@github-actions
Copy link

Choose a reason for hiding this comment

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

Coverage for this commit

94.64%

Coverage Report
FileBranchesFuncsLinesUncovered Lines
src
   index.ts100%100%100%
src/client
   error.ts100%100%100%
   index.ts74.03%100%95.31%102–103, 124, 13, 146, 148, 148–149, 15, 15, 151, 162, 169, 169, 17, 17, 171, 176, 179, 182, 184, 52, 82
   types.ts100%100%100%
src/odsql
   clauses.ts71.43%80%90.91%14, 32, 42
   index.ts83.72%95.74%94.19%111, 146, 25, 28, 56–57, 57, 57–58, 68, 78–79

@github-actions
Copy link

Choose a reason for hiding this comment

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

Coverage for this commit

94.64%

Coverage Report
FileBranchesFuncsLinesUncovered Lines
src
   index.ts100%100%100%
src/client
   error.ts100%100%100%
   index.ts74.03%100%95.31%102–103, 124, 13, 146, 148, 148–149, 15, 15, 151, 162, 169, 169, 17, 17, 171, 176, 179, 182, 184, 52, 82
   types.ts100%100%100%
src/odsql
   clauses.ts71.43%80%90.91%14, 32, 42
   index.ts83.72%95.74%94.19%111, 146, 25, 28, 56–57, 57, 57–58, 68, 78–79

Please sign in to comment.