Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions lib/src/resultset-table/ResultsetTable.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -260,6 +260,10 @@ export const Chromatic = () => (
<Title title="Scroll resultset table" theme="light" level={4} />
<DxcResultsetTable columns={longColumns} rows={longRows} />
</ExampleContainer>
<ExampleContainer>
<Title title="Without paginator" theme="light" level={4} />
<DxcResultsetTable columns={columns} rows={rows} hidePaginator />
</ExampleContainer>
<ExampleContainer>
<SmallContainer>
<Title title="Small container and text overflow" theme="light" level={4} />
Expand Down
6 changes: 6 additions & 0 deletions lib/src/resultset-table/ResultsetTable.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -310,6 +310,12 @@ describe("Resultset table component tests", () => {
expect(getAllByRole("row").length - 1).toEqual(1);
});

test("Resultset table may not use the paginator", () => {
const { getAllByRole } = render(<DxcResultsetTable columns={columns} rows={rows} hidePaginator />);
const nextButton = getAllByRole("button")[3];
expect(nextButton).not.toBeTruthy();
});

test("Resultset table with ActionsCell", () => {
const onSelectOption = jest.fn();
const onClick = jest.fn();
Expand Down
54 changes: 32 additions & 22 deletions lib/src/resultset-table/ResultsetTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,15 @@ import { spaces } from "../common/variables";
import DxcPaginator from "../paginator/Paginator";
import DxcTable, { DxcActionsCell } from "../table/Table";
import useTheme from "../useTheme";
import ResultsetTablePropsType, { Column } from "./types";
import ResultsetTablePropsType, { Column, Row } from "./types";
import icons from "./Icons";
import { getMargin } from "../common/utils";
import CoreTokens from "../common/coreTokens";

const normalizeSortValue = (sortValue) => (typeof sortValue === "string" ? sortValue.toUpperCase() : sortValue);
const normalizeSortValue = (sortValue: string | React.ReactNode) =>
typeof sortValue === "string" ? sortValue.toUpperCase() : sortValue;

const sortArray = (index, order, resultset) =>
const sortArray = (index: number, order: "ascending" | "descending", resultset: Row[][]) =>
resultset.slice().sort((element1, element2) => {
const sortValueA = normalizeSortValue(element1[index].sortValue || element1[index].displayValue);
const sortValueB = normalizeSortValue(element2[index].sortValue || element2[index].displayValue);
Expand All @@ -28,15 +29,20 @@ const sortArray = (index, order, resultset) =>
return order === "descending" ? comparison * -1 : comparison;
});

const getMinItemsPerPageIndex = (currentPageInternal, itemsPerPage, page) =>
const getMinItemsPerPageIndex = (currentPageInternal: number, itemsPerPage: number, page: number) =>
currentPageInternal === 1 ? 0 : itemsPerPage * (page - 1);

const getMaxItemsPerPageIndex = (minItemsPerPageIndex, itemsPerPage, resultset, page) =>
minItemsPerPageIndex + itemsPerPage > resultset.length ? resultset.length : itemsPerPage * page - 1;
const getMaxItemsPerPageIndex = (
minItemsPerPageIndex: number,
itemsPerPage: number,
resultset: Row[][],
page: number
) => (minItemsPerPageIndex + itemsPerPage > resultset.length ? resultset.length : itemsPerPage * page - 1);

const DxcResultsetTable = ({
columns,
rows,
hidePaginator = false,
showGoToPage = true,
itemsPerPage = 5,
itemsPerPageOptions,
Expand Down Expand Up @@ -81,7 +87,9 @@ const DxcResultsetTable = ({
};

useEffect(() => {
rows.length > 0 ? changePage(1) : changePage(0);
if (!hidePaginator) {
rows.length > 0 ? changePage(1) : changePage(0);
}
}, [rows]);

return (
Expand Down Expand Up @@ -121,31 +129,33 @@ const DxcResultsetTable = ({
</tr>
</thead>
<tbody>
{filteredResultset.map((cells, index) => (
<tr key={`resultSetTableCell_${page}_${index}`}>
{cells.map((cellContent, index) => (
<td key={`resultSetTableCellContent_${index}`}>{cellContent.displayValue}</td>
{filteredResultset.map((cells, rowIndex) => (
<tr key={`resultSetTableCell_${page}_${rowIndex}`}>
{cells.map((cellContent, cellIndex) => (
<td key={`resultSetTableCellContent_${cellIndex}`}>{cellContent.displayValue}</td>
))}
</tr>
))}
</tbody>
</DxcTable>
<DxcPaginator
totalItems={rows.length}
itemsPerPage={itemsPerPage}
itemsPerPageOptions={itemsPerPageOptions}
itemsPerPageFunction={itemsPerPageFunction}
currentPage={page}
showGoToPage={showGoToPage}
onPageChange={goToPage}
tabIndex={tabIndex}
/>
{!hidePaginator && (
<DxcPaginator
totalItems={rows.length}
itemsPerPage={itemsPerPage}
itemsPerPageOptions={itemsPerPageOptions}
itemsPerPageFunction={itemsPerPageFunction}
currentPage={page}
showGoToPage={showGoToPage}
onPageChange={goToPage}
tabIndex={tabIndex}
/>
)}
</DxcResultsetTableContainer>
</ThemeProvider>
);
};

const calculateWidth = (margin) => `calc(100% - ${getMargin(margin, "left")} - ${getMargin(margin, "right")})`;
const calculateWidth = (margin: string | object) => `calc(100% - ${getMargin(margin, "left")} - ${getMargin(margin, "right")})`;

const DxcResultsetTableContainer = styled.div<{ margin: ResultsetTablePropsType["margin"] }>`
width: ${(props) => calculateWidth(props.margin)};
Expand Down
52 changes: 41 additions & 11 deletions lib/src/resultset-table/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ export type Column = {
isSortable?: boolean;
};

type Row = {
export type Row = {
/**
* Value to be displayed in the cell.
*/
Expand All @@ -29,7 +29,7 @@ type Row = {
sortValue?: string;
};

type Props = {
type CommonProps = {
/**
* An array of objects representing the columns of the table.
*/
Expand All @@ -39,6 +39,25 @@ type Props = {
* as many objects as columns in the table.
*/
rows: Row[][];
/**
* Size of the margin to be applied to the component. You can pass an object with 'top',
* 'bottom', 'left' and 'right' properties in order to specify different margin sizes.
*/
margin?: Space | Margin;
/**
* Value of the tabindex attribute applied to the sortable icon.
*/
tabIndex?: number;
/**
* Determines the visual style and layout
* - "default": The default mode with big spacing
* - "reduced": A reduced mode with minimal spacing for dense tables
*/
mode?: "default" | "reduced";
};

type PaginatedProps = CommonProps & {
hidePaginator?: false;
/**
* If true, a select component for navigation between pages will be displayed.
*/
Expand All @@ -56,21 +75,32 @@ type Props = {
* option. The value selected will be passed as a parameter.
*/
itemsPerPageFunction?: (value: number) => void;
};

type NonPaginatedProps = CommonProps & {
/**
* Size of the margin to be applied to the component. You can pass an object with 'top',
* 'bottom', 'left' and 'right' properties in order to specify different margin sizes.
* If true, paginator will not be displayed.
*/
margin?: Space | Margin;
hidePaginator: true;
/**
* Value of the tabindex attribute applied to the sortable icon.
* If true, a select component for navigation between pages will be displayed.
*/
tabIndex?: number;
showGoToPage?: never;
/**
* Determines the visual style and layout
* - "default": The default mode with big spacing
* - "reduced": A reduced mode with minimal spacing for dense tables
* Number of items per page.
*/
mode?: "default" | "reduced";
itemsPerPage?: never;
/**
* An array of numbers representing the items per page options.
*/
itemsPerPageOptions?: never;
/**
* This function will be called when the user selects an item per page
* option. The value selected will be passed as a parameter.
*/
itemsPerPageFunction?: never;
};

type Props = PaginatedProps | NonPaginatedProps;

export default Props;