(react) add DataList

Implement DataList that is a wrapper of DataGrid without header, sorting
nor pagination.
This commit is contained in:
Romain Le Cellier
2023-05-04 11:22:33 +02:00
parent 0e6532f098
commit b53afcb4af
7 changed files with 142 additions and 45 deletions

View File

@@ -0,0 +1,5 @@
---
"@openfun/cunningham-react": minor
---
Add DataList component

View File

@@ -0,0 +1,36 @@
import { render, screen } from "@testing-library/react";
import React from "react";
import { faker } from "@faker-js/faker";
import { getAllByRole, queryAllByRole } from "@testing-library/dom";
import { expect } from "vitest";
import { CunninghamProvider } from ":/components/Provider";
import { DataList } from ":/components/DataGrid/DataList";
describe("<DataList/>", () => {
it("should render a DataList", async () => {
const rows = Array.from(Array(3)).map((_value, index) => ({
id: `list key for element ${index}`,
firstName: faker.name.firstName(),
lastName: faker.name.lastName(),
}));
render(
<CunninghamProvider>
<DataList
columns={[{ field: "firstName" }, { field: "lastName" }]}
rows={rows}
/>
</CunninghamProvider>
);
const table = screen.getByRole("table");
expect(queryAllByRole(table, "columnheader")).toEqual([]);
rows.forEach((row) => {
const element = screen.getByTestId(row.id);
const tds = getAllByRole(element, "cell");
expect(tds.length).toBe(2);
expect(tds[0].textContent).toEqual(row.firstName);
expect(tds[1].textContent).toEqual(row.lastName);
});
});
});

View File

@@ -0,0 +1,6 @@
import React from "react";
import { BaseProps, DataGrid } from ":/components/DataGrid/index";
export const DataList = ({ rows, ...props }: BaseProps) => {
return <DataGrid {...props} displayHeader={false} rows={rows} />;
};

View File

@@ -1,6 +1,7 @@
import { Canvas, Meta, Story, Source, ArgsTable } from '@storybook/addon-docs';
import { DataGrid } from './index';
import { SimpleDataGrid } from './SimpleDataGrid';
import { DataList } from './DataList';
<Meta title="Components/DataGrid/Doc" component={DataGrid}/>
@@ -26,6 +27,27 @@ The `rows` props is an array of objects that describe the rows of the table. Eac
We will explore the possibilities that those props provide through the following examples.
## DataList
<Source
language='ts'
dark
format={false}
code={`import { DataList } from "@openfun/cunningham-react";`}
/>
This component is a wrapper around the more complicated DataGrid component. It is made to be used for simple lists of elements that don't need pagination nor sorting. Also, it doesn't display any header.
Here a quick usage example
<Canvas withSource="open">
<Story id="components-datagrid--data-list-only"/>
</Canvas>
### Props
<ArgsTable of={DataList} />
## SimpleDataGrid
<Source

View File

@@ -6,6 +6,7 @@ import { usePagination } from ":/components/Pagination";
import { CunninghamProvider } from ":/components/Provider";
import { Button } from ":/components/Button";
import { SimpleDataGrid } from ":/components/DataGrid/SimpleDataGrid";
import { DataList } from ":/components/DataGrid/DataList";
export default {
title: "Components/DataGrid",
@@ -249,3 +250,27 @@ export const FullServerSide = () => {
</CunninghamProvider>
);
};
export const DataListOnly = () => {
const database = useMemo(
() =>
Array.from(Array(5)).map((_value, index) => ({
id: `list key for element ${index}`,
title: faker.random.word(),
date: faker.date.past(1).toISOString(),
action: (
<Button size="small" color="secondary">
Do it
</Button>
),
})),
[]
);
const columns = [{ field: "title" }, { field: "date" }, { field: "action" }];
return (
<CunninghamProvider>
<DataList rows={database} columns={columns} />
</CunninghamProvider>
);
};

View File

@@ -1,4 +1,3 @@
// import { Button } from "components/Button";
import React, { useMemo } from "react";
import classNames from "classnames";
import {
@@ -49,6 +48,7 @@ interface Props<T extends Row = Row> extends BaseProps<T> {
onSortModelChange?: (newSortModel: SortModel) => void;
/** Options for the underlying tanstack table. */
tableOptions?: TableOptions<Row>;
displayHeader?: boolean;
}
export const DataGrid = ({
@@ -62,6 +62,7 @@ export const DataGrid = ({
onRowSelectionChange,
rowSelection,
tableOptions,
displayHeader = true,
}: Props) => {
const { t } = useCunningham();
const headlessColumns = useHeadlessColumns({ columns, enableRowSelection });
@@ -147,50 +148,51 @@ export const DataGrid = ({
<>
<table>
<thead>
{table.getHeaderGroups().map((headerGroup) => (
<tr key={headerGroup.id}>
{headerGroup.headers.map((header) => {
return (
<th key={header.id} colSpan={header.colSpan}>
{header.isPlaceholder ? null : (
<div
className={classNames("c__datagrid__header", {
"c__datagrid__header--sortable":
header.column.getCanSort(),
})}
{...(header.column.getCanSort()
? {
role: "button",
tabIndex: 0,
onClick:
header.column.getToggleSortingHandler(),
}
: {})}
>
{flexRender(
header.column.columnDef.header,
header.getContext()
)}
{header.column.getIsSorted() === "asc" && (
<span className="material-icons">
arrow_drop_up
</span>
)}
{header.column.getIsSorted() === "desc" && (
<span className="material-icons">
arrow_drop_down
</span>
)}
{!header.column.getIsSorted() && (
<span className="c__datagrid__header__icon-placeholder" />
)}
</div>
)}
</th>
);
})}
</tr>
))}
{displayHeader &&
table.getHeaderGroups().map((headerGroup) => (
<tr key={headerGroup.id}>
{headerGroup.headers.map((header) => {
return (
<th key={header.id} colSpan={header.colSpan}>
{header.isPlaceholder ? null : (
<div
className={classNames("c__datagrid__header", {
"c__datagrid__header--sortable":
header.column.getCanSort(),
})}
{...(header.column.getCanSort()
? {
role: "button",
tabIndex: 0,
onClick:
header.column.getToggleSortingHandler(),
}
: {})}
>
{flexRender(
header.column.columnDef.header,
header.getContext()
)}
{header.column.getIsSorted() === "asc" && (
<span className="material-icons">
arrow_drop_up
</span>
)}
{header.column.getIsSorted() === "desc" && (
<span className="material-icons">
arrow_drop_down
</span>
)}
{!header.column.getIsSorted() && (
<span className="c__datagrid__header__icon-placeholder" />
)}
</div>
)}
</th>
);
})}
</tr>
))}
</thead>
<tbody>
{table.getRowModel().rows.map((row) => (

View File

@@ -3,6 +3,7 @@ import "./index.scss";
export * from "./components/Button";
export * from "./components/DataGrid";
export * from "./components/DataGrid/SimpleDataGrid";
export * from "./components/DataGrid/DataList";
export * from "./components/Forms/Field";
export * from "./components/Forms/Input";
export * from "./components/Loader";