diff --git a/source/console/src/Components/Dashboard/Dashboard.js b/source/console/src/Components/Dashboard/Dashboard.js
index 7009fdb..e8696a6 100644
--- a/source/console/src/Components/Dashboard/Dashboard.js
+++ b/source/console/src/Components/Dashboard/Dashboard.js
@@ -2,7 +2,7 @@
// SPDX-License-Identifier: Apache-2.0
import React from "react";
-import { Table, Spinner } from "reactstrap";
+import { Table, Spinner, Input, Pagination, PaginationItem, PaginationLink } from "reactstrap";
import { Link } from "react-router-dom";
import { get } from "aws-amplify/api";
@@ -14,13 +14,19 @@ class Dashboard extends React.Component {
super(props);
this.state = {
Items: [],
+ filteredItems: [],
isLoading: true,
+ searchQuery: '',
+ currentPage: 1,
+ itemsPerPage: 10,
+ totalTests: 0,
};
}
getItems = async () => {
this.setState({
Items: [],
+ filteredItems: [],
isLoading: true,
});
@@ -38,19 +44,135 @@ class Dashboard extends React.Component {
this.setState({
Items: data.Items,
+ filteredItems: data.Items,
isLoading: false,
+ totalTests: data.Items.length,
});
} catch (err) {
- alert(err);
+ alert(err);
}
};
+ filterItems = (items, query) => {
+ if (!query) return items;
+
+ const normalizedQuery = query.toLowerCase();
+
+ return items.filter(item =>
+ Object.values(item).some(value =>
+ value && value.toString().toLowerCase().includes(normalizedQuery)
+ )
+ );
+ };
+
+ handleSearchChange = (event) => {
+ const searchQuery = event.target.value;
+ this.setState({ searchQuery, currentPage: 1 }, this.updateFilteredItems);
+ };
+
+ updateFilteredItems = () => {
+ const { Items, searchQuery } = this.state;
+ const filteredItems = this.filterItems(Items, searchQuery);
+ this.setState({ filteredItems });
+ };
+
+
+ handlePageChange = (pageNumber) => {
+ this.setState({ currentPage: pageNumber });
+ };
+
+ calculatePaginationIndices = (currentPage, itemsPerPage, totalItems) => {
+ const indexOfLastItem = currentPage * itemsPerPage;
+ const indexOfFirstItem = indexOfLastItem - itemsPerPage;
+ const currentItems = totalItems.slice(indexOfFirstItem, indexOfLastItem);
+ const currentLoadRangeStart = indexOfFirstItem + 1;
+ const currentLoadRangeEnd = Math.min(indexOfLastItem, totalItems.length);
+
+ return { currentItems, currentLoadRangeStart, currentLoadRangeEnd };
+ };
+
+
componentDidMount() {
this.getItems();
}
+ renderTableBody = (items) => {
+ const { currentPage, itemsPerPage } = this.state;
+ const { currentItems } = this.calculatePaginationIndices(currentPage, itemsPerPage, items);
+
+ return (
+
+ {currentItems.map((item) => {
+ return (
+
+ {item.testName} |
+ {item.testId} |
+ {item.testDescription} |
+ {item.startTime ? item.startTime : ""} |
+ {item.status} |
+ {item.nextRun} |
+ {item.scheduleRecurrence} |
+
+
+
+
+ |
+
+ );
+ })}
+
+ );
+ };
+
+ renderPagination = (items) => {
+ const { currentPage, itemsPerPage } = this.state;
+ const totalPages = Math.ceil(items.length / itemsPerPage);
+
+ if (totalPages <= 1) return null;
+
+ const pageNumbers = [];
+ for (let i = 1; i <= totalPages; i++) {
+ pageNumbers.push(i);
+ }
+
+ const previousPageItem = (
+
+ this.handlePageChange(currentPage - 1)}>
+ Previous page
+
+
+ );
+
+ const nextPageItem = (
+ = totalPages}>
+ this.handlePageChange(currentPage + 1)}>
+ Next page
+
+
+ );
+
+ return (
+
+ {previousPageItem}
+ {pageNumbers.map((number) => (
+
+ this.handlePageChange(number)}>
+ {number}
+
+
+ ))}
+ {nextPageItem}
+
+ );
+ };
+
render() {
- const { Items } = this.state;
+ const { filteredItems, isLoading, searchQuery, currentPage, itemsPerPage } = this.state;
+ const { currentLoadRangeStart, currentLoadRangeEnd } = this.calculatePaginationIndices(currentPage, itemsPerPage, filteredItems);
+ const loadTests = filteredItems;
const welcome = (
@@ -58,30 +180,6 @@ class Dashboard extends React.Component {
);
- const tableBody = (
-
- {Items.map((item) => (
-
- {item.testName} |
- {item.testId} |
- {item.testDescription} |
- {item.startTime} |
- {item.status} |
- {item.nextRun} |
- {item.scheduleRecurrence} |
-
-
-
-
- |
-
- ))}
-
- );
-
return (
}
/>
-
-
-
- Name |
- Id |
- Description |
- Last Run (UTC) |
- Status |
- Next Run (UTC) |
- Recurrence |
- Details |
-
-
- {tableBody}
-
- {this.state.isLoading && (
+
+
+
+
+ Name |
+ Id |
+ Description |
+ Last Run (UTC) |
+ Status |
+ Next Run (UTC) |
+ Recurrence |
+ Details |
+
+
+ {this.renderTableBody(loadTests)}
+
+
+ {filteredItems.length === 0 ? (
+
+ The search didn't find anything
+
+ ) : (
+
+ Showing rows {currentLoadRangeStart} to {currentLoadRangeEnd} of {loadTests.length}
+
+ )}
+ {this.renderPagination(loadTests)}
+
+ {isLoading && (
)}
- {!this.state.isLoading && Items.length === 0 && welcome}
+ {!isLoading && (
+ (this.state.totalTests === 0 && welcome)
+ )}
);
- }
+}
}
export default Dashboard;
diff --git a/source/console/src/index.css b/source/console/src/index.css
index 96f2705..838e620 100644
--- a/source/console/src/index.css
+++ b/source/console/src/index.css
@@ -555,3 +555,34 @@ img {
font-weight: 600;
}
}
+
+.pagination .disabled {
+ display: none;
+}
+.page-item .page-link{
+ color: black !important;
+ box-shadow: none;
+}
+.page-item.active .page-link{
+ color: white !important;
+ background-color: #ffa500;
+ border-color: #ffa500;
+}
+.page-container {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ height: 100%;
+}
+.page-container.no-results {
+ justify-content: center;
+}
+.rows-info, .pagination {
+ flex: 1;
+}
+.search-info {
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ text-align: center;
+}