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
17 changes: 9 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,14 +33,15 @@ Hooks

#### HalTable Props

| Name | Default | Description |
| :------------------------------------------- | :-------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| collectionUrl: `string` | | The URL of the collection resource to be used for the table. `Required` |
| headers: `object` | | Contains the HTTP headers to be sent along with the HTTP requests to the collectionUrl. `Optional` |
| itemsPerPage: `number` | 5 | The amount of items to be displayed per page. Will be used to calculate the `_start` and `_num` query parameters that will be sent to the collection for pagination. `Optional` |
| asyncHeadersHandler: `() => Promise<object>` | | Async function that will be executed right before every HTTP request in order to retrieve dynamic headers. It must return a promise that resolves into an object with the keys and values of the headers. These headers will be merged with the ones indicated in the `headers` prop. `Optional` |
| columns: `Column[]` | [] | Array of objects specifying the columns to be displayed in the table. Each Column object has:<br> - <b>header</b>: Column label to be place at the table header.<br> - <b>displayProperty</b>: The name of the property in the items summary to be rendered for this column in the table.<br> - <b>sortProperty</b>: The name of the property in the items summary to be used for sorting the table.<br> - <b>onClickItemFunction</b>: Callback function that will be executed when the user clicks an item in that column. The collection item will be passed to this function when executed.<br> - <b>mapFunction</b>: Callback function that must return the value to be rendered in that column for a specific item. The item will be passed to this function as a parameter. |
| mode: `'default'` \| `'reduced'` | `default` | The available table modes:<br>- <b>default</b>: Default table size.<br> - <b>reduced</b>: More compact table with less spacing for high density information. |
| Name | Default | Description |
| :------------------------------------------- | :---------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| collectionUrl: `string` | | The URL of the collection resource to be used for the table. `Required` |
| headers: `object` | | Contains the HTTP headers to be sent along with the HTTP requests to the collectionUrl. `Optional` |
| itemsPerPage: `number` | `5` | The amount of items to be displayed per page. Will be used to calculate the `_start` and `_num` query parameters that will be sent to the collection for pagination. `Optional` |
| asyncHeadersHandler: `() => Promise<object>` | | Async function that will be executed right before every HTTP request in order to retrieve dynamic headers. It must return a promise that resolves into an object with the keys and values of the headers. These headers will be merged with the ones indicated in the `headers` prop. `Optional` |
| columns: `Column[]` | `[]` | Array of objects specifying the columns to be displayed in the table. Each Column object has:<br> - <b>header</b>: Column label to be placed at the table header.<br> - <b>displayProperty</b>: The name of the property in the items summary to be rendered for this column in the table.<br> - <b>sortProperty</b>: The name of the property in the items summary to be used for sorting the table.<br> - <b>onClickItemFunction</b>: Callback function that will be executed when the user clicks an item in that column. The collection item will be passed to this function when executed.<br> - <b>mapFunction</b>: Callback function that must return the value to be rendered in that column for a specific item. The item will be passed to this function as a parameter. |
| hidePaginator: `boolean` | `false` | If true, paginator will not be displayed. `Optional` |
| mode: `"default" \| "reduced"` | `"default"` | Determines the visual style and layout of the table:<br> - `"default"`: Standard table size.<br> - `"reduced"`: More compact table with less spacing, suitable for high-density information. `Optional` |

#### HalTable Example

Expand Down
60 changes: 42 additions & 18 deletions lib/src/components/HalTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,24 +5,36 @@ import {
DxcPaginator,
DxcFlex,
DxcTypography,
HalstackProvider,
} from "@dxc-technology/halstack-react";
import { HalApiCaller } from "@dxc-technology/halstack-client";
import styled from "styled-components";
import icons from "./Icons";
import { HalTableProps } from "./types";

const addPageParams = ({ collectionUrl, page, itemsPerPage, sortColumn }) => {
return `${collectionUrl}${collectionUrl.includes("?") ? "&" : "?"}_start=${
(page - 1) * itemsPerPage + 1
}&_num=${itemsPerPage}${sortColumn ? `&_sort=${sortColumn}` : ``}`;
const addPageParams = ({ collectionUrl, page, itemsPerPage, sortColumn, handlePagination }) => {
let url = collectionUrl;
if (handlePagination) {
url += `${url.includes("?") ? "&" : "?"}_start=${
(page - 1) * itemsPerPage + 1
}&_num=${itemsPerPage}`;
}
if (sortColumn) {
url += `&_sort=${sortColumn}`;
}
return url;
};

type NavigationFunctions = {
onPageChange: (newPage: number) => void;
sort: (column: string) => void;
};
const useCollection = (collectionUrl, asyncHeadersHandler, headers, itemsPerPage) => {
const useCollection = (
collectionUrl,
asyncHeadersHandler,
headers,
itemsPerPage,
handlePagination
) => {
const [isLoading, changeIsLoading] = useState(true);
const [navigationFunctions, changeNavigationFunctions] = useState<NavigationFunctions>({
onPageChange: () => {},
Expand All @@ -40,7 +52,7 @@ const useCollection = (collectionUrl, asyncHeadersHandler, headers, itemsPerPage
try {
const asyncHeadears = asyncHeadersHandler ? await asyncHeadersHandler() : {};
const response = await HalApiCaller.get({
url: addPageParams({ collectionUrl, page, itemsPerPage, sortColumn }),
url: addPageParams({ collectionUrl, page, itemsPerPage, sortColumn, handlePagination }),
headers: { ...headers, ...asyncHeadears },
});
changeIsLoading(false);
Expand All @@ -67,7 +79,15 @@ const useCollection = (collectionUrl, asyncHeadersHandler, headers, itemsPerPage
};

fetchList();
}, [collectionUrl, asyncHeadersHandler, headers, page, itemsPerPage, sortColumn]);
}, [
collectionUrl,
asyncHeadersHandler,
headers,
page,
itemsPerPage,
handlePagination,
sortColumn,
]);

return {
isLoading,
Expand Down Expand Up @@ -102,6 +122,7 @@ const HalTable = ({
collectionUrl,
asyncHeadersHandler,
headers,
hidePaginator = false,
columns,
itemsPerPage = 5,
mode = "default",
Expand All @@ -114,7 +135,7 @@ const HalTable = ({
totalCollectionItems,
error,
sortColumn,
} = useCollection(collectionUrl, asyncHeadersHandler, headers, itemsPerPage);
} = useCollection(collectionUrl, asyncHeadersHandler, headers, itemsPerPage, !hidePaginator);
const { onPageChange, sort } = navigationFunctions;

return (
Expand Down Expand Up @@ -184,15 +205,18 @@ const HalTable = ({
</MessageContainer>
)
)}
{!error && totalCollectionItems > 0 && (
<DxcPaginator
totalItems={totalCollectionItems}
itemsPerPage={itemsPerPage}
currentPage={page}
showGoToPage={true}
onPageChange={onPageChange}
/>
)}
{!error &&
!hidePaginator &&
totalCollectionItems > 0 &&
totalCollectionItems > itemsPerPage && (
<DxcPaginator
totalItems={totalCollectionItems}
itemsPerPage={itemsPerPage}
currentPage={page}
showGoToPage={true}
onPageChange={onPageChange}
/>
)}
{error && (
<MessageContainer hasError={true}>
<DxcTypography color="#d0011b">{error}</DxcTypography>
Expand Down
4 changes: 4 additions & 0 deletions lib/src/components/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,10 @@ export type HalTableProps = {
* Contains the HTTP headers to be sent along with the HTTP requests to the collectionUrl.
*/
headers?: object;
/**
* If true, paginator will not be displayed.
*/
hidePaginator?: boolean;
/**
* The amount of items to be displayed per page.
* Will be used to calculate the _start and _num query parameters that will be sent to the collection for pagination.
Expand Down
47 changes: 46 additions & 1 deletion lib/src/tests/halTable.test.jsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { fireEvent, render, waitFor } from "@testing-library/react";
import { fireEvent, queryByText, render, waitFor } from "@testing-library/react";
import HalTable from "../components/HalTable";

describe("HalTable component tests", () => {
Expand Down Expand Up @@ -69,4 +69,49 @@ describe("HalTable component tests", () => {
fireEvent.click(getByText("trewqasdfgyhujikolpyt"));
expect(onCellClick).toHaveBeenCalledWith("trewqasdfgyhujikolpyt");
});
test("HalTable is not including paginator when itemsPerPage exceeds total", async () => {
const onCellClick = jest.fn();
const { queryByText } = render(
<HalTable
collectionUrl="http://localhost:3000/response"
columns={[
{
header: "identifier",
displayProperty: "identifier",
sortProperty: "identifier",
onClickItemFunction: (item) => onCellClick(item.summary.identifier),
},
{
header: "baseCompany",
displayProperty: "baseCompany",
sortProperty: "baseCompany",
},
]}
itemsPerPage={100}
/>
);
await waitFor(() => expect(queryByText("Go to page:")).toBeFalsy());
});
test("HalTable is including paginator by default", async () => {
const onCellClick = jest.fn();
const { getByText } = render(
<HalTable
collectionUrl="http://localhost:3000/response"
columns={[
{
header: "identifier",
displayProperty: "identifier",
sortProperty: "identifier",
onClickItemFunction: (item) => onCellClick(item.summary.identifier),
},
{
header: "baseCompany",
displayProperty: "baseCompany",
sortProperty: "baseCompany",
},
]}
/>
);
await waitFor(() => expect(getByText("Go to page:")).toBeTruthy());
});
});