diff --git a/roadside-forms-frontend/frontend_web_app/package-lock.json b/roadside-forms-frontend/frontend_web_app/package-lock.json index 8bfe965a..890c2e5d 100644 --- a/roadside-forms-frontend/frontend_web_app/package-lock.json +++ b/roadside-forms-frontend/frontend_web_app/package-lock.json @@ -31,6 +31,7 @@ "react-bootstrap-table-next": "^4.0.3", "react-bootstrap-table2-filter": "^1.3.3", "react-bootstrap-table2-paginator": "^2.1.2", + "react-bootstrap-table2-toolkit": "^2.1.3", "react-dom": "^18.3.1", "react-redux": "^9.1.2", "react-router-dom": "6.19.0", @@ -16557,6 +16558,11 @@ "node": ">= 10.13.0" } }, + "node_modules/file-saver": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/file-saver/-/file-saver-2.0.2.tgz", + "integrity": "sha512-Wz3c3XQ5xroCxd1G8b7yL0Ehkf0TC9oYC6buPFkNnU9EnaPlifeAFCyCh+iewXTyFRcg0a6j3J7FmJsIhlhBdw==" + }, "node_modules/file-system-cache": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/file-system-cache/-/file-system-cache-2.3.0.tgz", @@ -25697,6 +25703,19 @@ "react-dom": "^16.3.0" } }, + "node_modules/react-bootstrap-table2-toolkit": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/react-bootstrap-table2-toolkit/-/react-bootstrap-table2-toolkit-2.1.3.tgz", + "integrity": "sha512-nKBSezHTOkO9k8YMMuJfPEZtBVfIYrJbmP8n3u7+AXRcOrOGygXyauNVKWqdKLchQlG/cW5QR0sPkFknpp5rjQ==", + "dependencies": { + "file-saver": "2.0.2" + }, + "peerDependencies": { + "prop-types": "^15.0.0", + "react": "^16.3.0", + "react-dom": "^16.3.0" + } + }, "node_modules/react-colorful": { "version": "5.6.1", "resolved": "https://registry.npmjs.org/react-colorful/-/react-colorful-5.6.1.tgz", @@ -45143,6 +45162,11 @@ } } }, + "file-saver": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/file-saver/-/file-saver-2.0.2.tgz", + "integrity": "sha512-Wz3c3XQ5xroCxd1G8b7yL0Ehkf0TC9oYC6buPFkNnU9EnaPlifeAFCyCh+iewXTyFRcg0a6j3J7FmJsIhlhBdw==" + }, "file-system-cache": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/file-system-cache/-/file-system-cache-2.3.0.tgz", @@ -52650,6 +52674,14 @@ "resolved": "https://registry.npmjs.org/react-bootstrap-table2-paginator/-/react-bootstrap-table2-paginator-2.1.2.tgz", "integrity": "sha512-LC5znEphhgKJvaSY1q8d+Gj0Nc/1X+VS3tKJjkmWmfv9P61YC/BnwJ+aoqEmQzsLiVGowrzss+i/u+Tip5H+Iw==" }, + "react-bootstrap-table2-toolkit": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/react-bootstrap-table2-toolkit/-/react-bootstrap-table2-toolkit-2.1.3.tgz", + "integrity": "sha512-nKBSezHTOkO9k8YMMuJfPEZtBVfIYrJbmP8n3u7+AXRcOrOGygXyauNVKWqdKLchQlG/cW5QR0sPkFknpp5rjQ==", + "requires": { + "file-saver": "2.0.2" + } + }, "react-colorful": { "version": "5.6.1", "resolved": "https://registry.npmjs.org/react-colorful/-/react-colorful-5.6.1.tgz", diff --git a/roadside-forms-frontend/frontend_web_app/package.json b/roadside-forms-frontend/frontend_web_app/package.json index a5c4487c..5f44c8a6 100644 --- a/roadside-forms-frontend/frontend_web_app/package.json +++ b/roadside-forms-frontend/frontend_web_app/package.json @@ -27,6 +27,7 @@ "react-bootstrap-table-next": "^4.0.3", "react-bootstrap-table2-filter": "^1.3.3", "react-bootstrap-table2-paginator": "^2.1.2", + "react-bootstrap-table2-toolkit": "^2.1.3", "react-dom": "^18.3.1", "react-redux": "^9.1.2", "react-router-dom": "6.19.0", diff --git a/roadside-forms-frontend/frontend_web_app/src/components/userAdminDashboard/userAdminDashboard.js b/roadside-forms-frontend/frontend_web_app/src/components/userAdminDashboard/userAdminDashboard.js index 36d38cc5..663589c3 100644 --- a/roadside-forms-frontend/frontend_web_app/src/components/userAdminDashboard/userAdminDashboard.js +++ b/roadside-forms-frontend/frontend_web_app/src/components/userAdminDashboard/userAdminDashboard.js @@ -4,6 +4,7 @@ import { useNavigate } from "react-router-dom"; import BootstrapTable from 'react-bootstrap-table-next'; import filterFactory, { textFilter } from 'react-bootstrap-table2-filter'; import paginationFactory from 'react-bootstrap-table2-paginator'; +import ToolkitProvider, { CSVExport } from 'react-bootstrap-table2-toolkit/dist/react-bootstrap-table2-toolkit'; import Button from "react-bootstrap/Button"; import Row from "react-bootstrap/Row"; import Col from "react-bootstrap/Col"; @@ -19,6 +20,8 @@ import { UserApi } from "../../api/userApi"; import { SearchableSelect } from "../common/Select/SearchableSelect"; import "./userAdminDashboard.scss"; +const { ExportCSVButton } = CSVExport; + export const UserAdminDashboard = () => { const initialValues = { user: {}, @@ -135,7 +138,6 @@ export const UserAdminDashboard = () => { setTimeout(() => setShowSuccessMessage(false), 10000); // Hide after 10 seconds }; - const filteredData = useMemo(() => { if (showNewUsersOnly) { return data.filter(user => !user.approved_dt); @@ -216,6 +218,12 @@ export const UserAdminDashboard = () => { text: 'Date Applied', sort: true, formatter: (cell) => moment(cell).tz("America/Vancouver").format("YYYY-MM-DD HH:mm"), + csvFormatter: (cell) => { + if (cell === null || cell === undefined) { + return ''; + } + return moment(cell).tz("America/Vancouver").format("YYYY-MM-DD HH:mm"); + }, }, { dataField: 'last_active', @@ -227,10 +235,17 @@ export const UserAdminDashboard = () => { } return moment(cell).tz("America/Vancouver").format("YYYY-MM-DD HH:mm"); }, + csvFormatter: (cell) => { + if (cell === null || cell === undefined) { + return ''; + } + return moment(cell).tz("America/Vancouver").format("YYYY-MM-DD HH:mm"); + }, }, { dataField: 'action', text: 'Action', + csvExport: false, // This line excludes the column from CSV export formatter: (cellContent, row) => ( row.approved_dt ? ( + ); + }; + const renderTable = () => { if (filteredData.length === 0) { return ( @@ -263,18 +294,45 @@ export const UserAdminDashboard = () => { ); } + const currentDateTime = moment().format('YYYY-MM-DD_HH-mm-ss'); return ( - + exportCSV={{ + fileName: `DF_User_List_${currentDateTime}.csv`, + noAutoBOM: false, + exportAll: false, + onlyExportFiltered: true, + }} + > + { + props => ( +
+
+ setShowNewUsersOnly(e.target.checked)} + /> + +
+ +
+ ) + } + ); }; @@ -283,53 +341,44 @@ export const UserAdminDashboard = () => { } else { return ( <> - {showSuccessMessage && ( + {showSuccessMessage && ( setShowSuccessMessage(false)} dismissible> {successMessage} )}
-
- setShowNewUsersOnly(e.target.checked)} - /> -
{renderTable()} { - setSelectedUser(values.user.value); - setShowAddAdminModal(true); - }}> - {({ isSubmitting, values }) => ( - - - - - - - - - - - - - )} - + setSelectedUser(values.user.value); + setShowAddAdminModal(true); + }}> + {({ isSubmitting, values }) => ( + + + + + + + + + + + + + )} +
setShowConfirmModal(false)}> @@ -352,25 +401,24 @@ export const UserAdminDashboard = () => { - {/* Confirmation modal for adding administrator */} setShowAddAdminModal(false)}> - - Confirm Action - - - Are you sure you want to grant administrator role to {selectedUser?.first_name} {selectedUser?.last_name}? - - - - - - + + Confirm Action + + + Are you sure you want to grant administrator role to {selectedUser?.first_name} {selectedUser?.last_name}? + + + + + + ); }