Skip to content

Commit

Permalink
feat(component): localize Tables
Browse files Browse the repository at this point in the history
  • Loading branch information
jorgemoya committed Apr 28, 2023
1 parent d445188 commit 4865b06
Show file tree
Hide file tree
Showing 16 changed files with 265 additions and 25 deletions.
6 changes: 3 additions & 3 deletions packages/big-design/src/components/Pagination/Pagination.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import { Flex, FlexItem } from '../Flex';

import { StyledButton } from './styled';

interface Localization {
export interface PaginationLocalization {
of: string;
previousPage: string;
nextPage: string;
Expand All @@ -25,15 +25,15 @@ export interface PaginationProps extends MarginProps {
onPageChange(page: number): void;
onItemsPerPageChange(range: number): void;
label?: string;
localization?: Localization;
localization?: PaginationLocalization;
getRangeLabel?(start: number, end: number, totalItems: number): string;
}

const defaultGetRangeLabel = (
start: number,
end: number,
totalItems: number,
localization: Localization,
localization: PaginationLocalization,
): string => {
if (start === end) {
return `${start} ${localization.of} ${totalItems}`;
Expand Down
4 changes: 2 additions & 2 deletions packages/big-design/src/components/Search/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@ import { InputHTMLAttributes } from 'react';
import { FormProps } from '../Form';
import { InputProps } from '../Input';

interface Localization {
export interface SearchLocalization {
search: string;
}

export interface SearchProps extends Omit<InputHTMLAttributes<HTMLInputElement>, 'onSubmit'> {
localization?: Localization;
localization?: SearchLocalization;
value: InputProps['value'];
onChange: InputProps['onChange'];
onSubmit: FormProps['onSubmit'];
Expand Down
52 changes: 48 additions & 4 deletions packages/big-design/src/components/StatefulTable/StatefulTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@ import React, { useCallback, useEffect, useMemo, useReducer } from 'react';
import { useDidUpdate } from '../../hooks';
import { typedMemo } from '../../utils';
import { Box } from '../Box';
import { PaginationLocalization } from '../Pagination/Pagination';
import { PillTabItem, PillTabs, PillTabsProps } from '../PillTabs';
import { Search } from '../Search';
import { SearchLocalization } from '../Search/types';
import {
Table,
TableColumn,
Expand All @@ -16,6 +18,11 @@ import {

import { createReducer, createReducerInit } from './reducer';

type Localization =
| PaginationLocalization
| SearchLocalization
| (PaginationLocalization & SearchLocalization);

export interface StatefulTablePillTabFilter<T> {
pillTabs: PillTabItem[];
filter(itemId: string, items: T[]): T[];
Expand All @@ -31,9 +38,17 @@ export interface StatefulTableColumn<T> extends Omit<TableColumn<T>, 'isSortable
export interface StatefulTableProps<T>
extends Omit<
TableProps<T>,
'columns' | 'pagination' | 'filters' | 'search' | 'selectable' | 'sortable' | 'onRowDrop'
| 'columns'
| 'pagination'
| 'filters'
| 'search'
| 'selectable'
| 'sortable'
| 'onRowDrop'
| 'localization'
> {
columns: Array<StatefulTableColumn<T>>;
localization?: Localization;
pagination?: boolean;
filters?: StatefulTablePillTabFilter<T>;
selectable?: boolean;
Expand Down Expand Up @@ -62,6 +77,7 @@ const InternalStatefulTable = <T extends TableItem>({
itemName,
items = [],
keyField,
localization: localizationObj,
onSelectionChange,
onRowDrop,
search,
Expand All @@ -71,6 +87,14 @@ const InternalStatefulTable = <T extends TableItem>({
stickyHeader = false,
...rest
}: StatefulTableProps<T>): React.ReactElement<StatefulTableProps<T>> => {
const localization = {
of: 'of',
nextPage: 'Next page',
previousPage: 'Previous page',
search: 'Search',
...localizationObj,
};

const reducer = useMemo(() => createReducer<T>(), []);
const reducerInit = useMemo(() => createReducerInit<T>(), []);
const sortable = useMemo(
Expand Down Expand Up @@ -121,8 +145,28 @@ const InternalStatefulTable = <T extends TableItem>({
);

const paginationOptions = useMemo(
() => (pagination ? { ...state.pagination, onItemsPerPageChange, onPageChange } : undefined),
[pagination, state.pagination, onItemsPerPageChange, onPageChange],
() =>
pagination
? {
...state.pagination,
onItemsPerPageChange,
onPageChange,
localization: {
of: localization.of,
previousPage: localization.previousPage,
nextPage: localization.nextPage,
},
}
: undefined,
[
pagination,
state.pagination,
onItemsPerPageChange,
onPageChange,
localization?.of,
localization?.previousPage,
localization?.nextPage,
],
);

const selectableOptions = useMemo(
Expand Down Expand Up @@ -199,7 +243,7 @@ const InternalStatefulTable = <T extends TableItem>({

return (
<Box marginBottom="medium">
<Search {...searchProps} />
<Search localization={{ search: localization.search }} {...searchProps} />
</Box>
);
};
Expand Down
25 changes: 25 additions & 0 deletions packages/big-design/src/components/StatefulTable/spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -552,3 +552,28 @@ describe('test search in the StatefulTable', () => {
expect(rows).toHaveLength(105);
});
});

test('renders localized labels', async () => {
render(
getSimpleTable({
pagination: true,
localization: {
of: 'de',
nextPage: 'Pagina siguiente',
previousPage: 'Pagina previa',
search: 'Buscar',
},
search: true,
}),
);

const input = screen.getByLabelText('Buscar');
const dropdown = await screen.findByRole('button', { name: '1 - 25 de 104' });
const prevPage = await screen.findByRole('button', { name: 'Pagina previa' });
const nextPage = await screen.findByRole('button', { name: 'Pagina siguiente' });

expect(input).toBeInTheDocument();
expect(dropdown).toBeInTheDocument();
expect(prevPage).toBeInTheDocument();
expect(nextPage).toBeInTheDocument();
});
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,10 @@ export interface HeaderCellProps<T>
extends TableHTMLAttributes<HTMLTableCellElement>,
TableColumnDisplayProps {
actionsRef: RefObject<HTMLDivElement>;
ascendingOrderLabel?: string;
children?: React.ReactNode;
column: TableColumn<T>;
descendingOrderLabel?: string;
id: string;
hide?: boolean;
isSorted?: boolean;
Expand All @@ -40,8 +42,10 @@ export interface DragIconCellProps {

const InternalHeaderCell = <T extends TableItem>({
actionsRef,
ascendingOrderLabel = 'Ascending order',
children,
column,
descendingOrderLabel = 'Desceding order',
display,
hide = false,
id,
Expand All @@ -60,9 +64,9 @@ const InternalHeaderCell = <T extends TableItem>({
}

return sortDirection === 'ASC' ? (
<ArrowUpwardIcon data-testid="asc-icon" size="medium" title="Ascending order" />
<ArrowUpwardIcon data-testid="asc-icon" size="medium" title={ascendingOrderLabel} />
) : (
<ArrowDownwardIcon data-testid="desc-icon" size="medium" title="Descending order" />
<ArrowDownwardIcon data-testid="desc-icon" size="medium" title={descendingOrderLabel} />
);
};

Expand Down
3 changes: 3 additions & 0 deletions packages/big-design/src/components/Table/Table.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ const InternalTable = <T extends TableItem>(
itemName,
items,
keyField = 'id',
localization,
onRowDrop,
pagination,
selectable,
Expand Down Expand Up @@ -149,7 +150,9 @@ const InternalTable = <T extends TableItem>(
return (
<HeaderCell
actionsRef={actionsRef}
ascendingOrderLabel={localization?.ascendingOrder}
column={{ ...column, width: widthColumn }}
descendingOrderLabel={localization?.descendingOrder}
display={display}
hide={hideHeader}
id={`header-cell-${index}`}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,7 @@ export const TablePagination: React.FC<TablePaginationProps> = memo(
onPageChange,
totalItems,
label,
previousLabel,
nextLabel,
localization,
getRangeLabel,
}) => {
return (
Expand All @@ -26,10 +25,9 @@ export const TablePagination: React.FC<TablePaginationProps> = memo(
itemsPerPage={itemsPerPage}
itemsPerPageOptions={itemsPerPageOptions}
label={label}
nextLabel={nextLabel}
localization={localization}
onItemsPerPageChange={onItemsPerPageChange}
onPageChange={onPageChange}
previousLabel={previousLabel}
totalItems={totalItems}
/>
</StyledPaginationContainer>
Expand Down
73 changes: 71 additions & 2 deletions packages/big-design/src/components/Table/spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -265,8 +265,11 @@ test('renders a pagination component with custom button labels', async () => {
onPageChange,
getRangeLabel,
label: '[Custom] Pagination',
previousLabel: '[Custom] Previous page',
nextLabel: '[Custom] Next page',
localization: {
of: 'of',
previousPage: '[Custom] Previous page',
nextPage: '[Custom] Next page',
},
}}
/>,
);
Expand Down Expand Up @@ -615,3 +618,69 @@ describe('draggable', () => {
expect(onRowDrop).toHaveBeenCalledWith(0, 1);
});
});

test('renders localized ascending label', async () => {
const onSort = jest.fn();
const items = [
{ sku: 'SM13', name: '[Sample] Smith Journal 13', stock: 25 },
{ sku: 'DPB', name: '[Sample] Dustpan & Brush', stock: 34 },
{ sku: 'OFSUC', name: '[Sample] Utility Caddy', stock: 45 },
{ sku: 'CLC', name: '[Sample] Canvas Laundry Cart', stock: 2 },
{ sku: 'CGLD', name: '[Sample] Laundry Detergent', stock: 29 },
];
const columns = [
{ header: 'Sku', hash: 'sku', render: ({ sku }: any) => sku, isSortable: true },
{ header: 'Name', hash: 'name', render: ({ name }: any) => name },
{ header: 'Stock', hash: 'stock', render: ({ stock }: any) => stock },
];

render(
<Table
columns={columns}
items={items}
localization={{ ascendingOrder: 'Orden ascendiente', descendingOrder: 'Orden descendiente' }}
sortable={{
columnHash: 'sku',
direction: 'ASC',
onSort,
}}
/>,
);

const ascSortIcon = screen.getByTitle('Orden ascendiente');

expect(ascSortIcon).toBeInTheDocument();
});

test('renders localized descending label', async () => {
const onSort = jest.fn();
const items = [
{ sku: 'SM13', name: '[Sample] Smith Journal 13', stock: 25 },
{ sku: 'DPB', name: '[Sample] Dustpan & Brush', stock: 34 },
{ sku: 'OFSUC', name: '[Sample] Utility Caddy', stock: 45 },
{ sku: 'CLC', name: '[Sample] Canvas Laundry Cart', stock: 2 },
{ sku: 'CGLD', name: '[Sample] Laundry Detergent', stock: 29 },
];
const columns = [
{ header: 'Sku', hash: 'sku', render: ({ sku }: any) => sku, isSortable: true },
{ header: 'Name', hash: 'name', render: ({ name }: any) => name },
{ header: 'Stock', hash: 'stock', render: ({ stock }: any) => stock },
];

render(
<Table
columns={columns}
items={items}
localization={{ ascendingOrder: 'Orden ascendiente', descendingOrder: 'Orden descendiente' }}
sortable={{
columnHash: 'sku',
direction: 'DESC',
onSort,
}}
/>,
);

const descSortIcon = await screen.queryByTitle('Orden descendiente');

expect(descSortIcon).toBeInTheDocument();
});
6 changes: 6 additions & 0 deletions packages/big-design/src/components/Table/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,11 @@ export interface TableColumn<T> extends TableColumnDisplayProps {

export type TablePaginationProps = Omit<PaginationProps, keyof MarginProps>;

interface Localization {
ascendingOrder: string;
descendingOrder: string;
}

export interface TableProps<T> extends React.TableHTMLAttributes<HTMLTableElement> {
actions?: React.ReactNode;
columns: Array<TableColumn<T>>;
Expand All @@ -48,6 +53,7 @@ export interface TableProps<T> extends React.TableHTMLAttributes<HTMLTableElemen
itemName?: string;
items: T[];
keyField?: string;
localization?: Localization;
onRowDrop?(from: number, to: number): void;
pagination?: TablePaginationProps;
selectable?: TableSelectable<T>;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,10 @@ export interface HeaderCellProps<T>
extends TableHTMLAttributes<HTMLTableCellElement>,
TableColumnDisplayProps {
actionsRef: RefObject<HTMLDivElement>;
ascendingOrderLabel?: string;
children?: React.ReactNode;
column: TableColumn<T>;
descendingOrderLabel?: string;
id: string;
hide?: boolean;
isSorted?: boolean;
Expand All @@ -40,8 +42,10 @@ export interface DragIconCellProps {

const InternalHeaderCell = <T extends TableItem>({
actionsRef,
ascendingOrderLabel = 'Ascending order',
children,
column,
descendingOrderLabel = 'Desceding order',
display,
hide = false,
id,
Expand All @@ -60,9 +64,9 @@ const InternalHeaderCell = <T extends TableItem>({
}

return sortDirection === 'ASC' ? (
<ArrowUpwardIcon data-testid="asc-icon" size="medium" title="Ascending order" />
<ArrowUpwardIcon data-testid="asc-icon" size="medium" title={ascendingOrderLabel} />
) : (
<ArrowDownwardIcon data-testid="desc-icon" size="medium" title="Descending order" />
<ArrowDownwardIcon data-testid="desc-icon" size="medium" title={descendingOrderLabel} />
);
};

Expand Down
Loading

0 comments on commit 4865b06

Please sign in to comment.