mirror of
https://github.com/Kingsrook/qqq-frontend-material-dashboard.git
synced 2025-07-18 05:10:45 +00:00
SPRINT-12: added pagination to top of entity list table, fix for record not found view enttity, store rowsperpage in local storage per table
This commit is contained in:
@ -34,28 +34,7 @@ import Icon from "@mui/material/Icon";
|
|||||||
import LinearProgress from "@mui/material/LinearProgress";
|
import LinearProgress from "@mui/material/LinearProgress";
|
||||||
import Menu from "@mui/material/Menu";
|
import Menu from "@mui/material/Menu";
|
||||||
import MenuItem from "@mui/material/MenuItem";
|
import MenuItem from "@mui/material/MenuItem";
|
||||||
import {
|
import {DataGridPro, getGridDateOperators, getGridNumericOperators, getGridStringOperators, GridCallbackDetails, GridColDef, GridColumnOrderChangeParams, GridColumnVisibilityModel, GridExportMenuItemProps, GridFilterItem, GridFilterModel, GridRowId, GridRowParams, GridRowsProp, GridSelectionModel, GridSortItem, GridSortModel, GridToolbarColumnsButton, GridToolbarContainer, GridToolbarDensitySelector, GridToolbarExportContainer, GridToolbarFilterButton, MuiEvent} from "@mui/x-data-grid-pro";
|
||||||
DataGridPro, getGridDateOperators, getGridNumericOperators, getGridStringOperators,
|
|
||||||
GridCallbackDetails,
|
|
||||||
GridColDef,
|
|
||||||
GridColumnOrderChangeParams,
|
|
||||||
GridColumnVisibilityModel,
|
|
||||||
GridExportMenuItemProps,
|
|
||||||
GridFilterItem,
|
|
||||||
GridFilterModel,
|
|
||||||
GridRowId,
|
|
||||||
GridRowParams,
|
|
||||||
GridRowsProp,
|
|
||||||
GridSelectionModel,
|
|
||||||
GridSortItem,
|
|
||||||
GridSortModel,
|
|
||||||
GridToolbarColumnsButton,
|
|
||||||
GridToolbarContainer,
|
|
||||||
GridToolbarDensitySelector,
|
|
||||||
GridToolbarExportContainer,
|
|
||||||
GridToolbarFilterButton,
|
|
||||||
MuiEvent
|
|
||||||
} from "@mui/x-data-grid-pro";
|
|
||||||
import {GridFilterOperator} from "@mui/x-data-grid/models/gridFilterOperator";
|
import {GridFilterOperator} from "@mui/x-data-grid/models/gridFilterOperator";
|
||||||
import React, {useCallback, useContext, useEffect, useReducer, useRef, useState} from "react";
|
import React, {useCallback, useContext, useEffect, useReducer, useRef, useState} from "react";
|
||||||
import {Link, useNavigate, useParams, useSearchParams} from "react-router-dom";
|
import {Link, useNavigate, useParams, useSearchParams} from "react-router-dom";
|
||||||
@ -74,6 +53,7 @@ import QValueUtils from "qqq/utils/QValueUtils";
|
|||||||
const COLUMN_VISIBILITY_LOCAL_STORAGE_KEY_ROOT = "qqq.columnVisibility";
|
const COLUMN_VISIBILITY_LOCAL_STORAGE_KEY_ROOT = "qqq.columnVisibility";
|
||||||
const COLUMN_SORT_LOCAL_STORAGE_KEY_ROOT = "qqq.columnSort";
|
const COLUMN_SORT_LOCAL_STORAGE_KEY_ROOT = "qqq.columnSort";
|
||||||
const FILTER_LOCAL_STORAGE_KEY_ROOT = "qqq.filter";
|
const FILTER_LOCAL_STORAGE_KEY_ROOT = "qqq.filter";
|
||||||
|
const ROWS_PER_PAGE_LOCAL_STORAGE_KEY_ROOT = "qqq.rowsPerPage";
|
||||||
|
|
||||||
interface Props
|
interface Props
|
||||||
{
|
{
|
||||||
@ -140,10 +120,12 @@ function EntityList({table}: Props): JSX.Element
|
|||||||
// look for defaults in the local storage //
|
// look for defaults in the local storage //
|
||||||
////////////////////////////////////////////
|
////////////////////////////////////////////
|
||||||
const sortLocalStorageKey = `${COLUMN_SORT_LOCAL_STORAGE_KEY_ROOT}.${tableName}`;
|
const sortLocalStorageKey = `${COLUMN_SORT_LOCAL_STORAGE_KEY_ROOT}.${tableName}`;
|
||||||
|
const rowsPerPageLocalStorageKey = `${ROWS_PER_PAGE_LOCAL_STORAGE_KEY_ROOT}.${tableName}`;
|
||||||
const columnVisibilityLocalStorageKey = `${COLUMN_VISIBILITY_LOCAL_STORAGE_KEY_ROOT}.${tableName}`;
|
const columnVisibilityLocalStorageKey = `${COLUMN_VISIBILITY_LOCAL_STORAGE_KEY_ROOT}.${tableName}`;
|
||||||
const filterLocalStorageKey = `${FILTER_LOCAL_STORAGE_KEY_ROOT}.${tableName}`;
|
const filterLocalStorageKey = `${FILTER_LOCAL_STORAGE_KEY_ROOT}.${tableName}`;
|
||||||
let defaultSort = [] as GridSortItem[];
|
let defaultSort = [] as GridSortItem[];
|
||||||
let defaultVisibility = {};
|
let defaultVisibility = {};
|
||||||
|
let defaultRowsPerPage = 10;
|
||||||
|
|
||||||
if (localStorage.getItem(sortLocalStorageKey))
|
if (localStorage.getItem(sortLocalStorageKey))
|
||||||
{
|
{
|
||||||
@ -153,10 +135,15 @@ function EntityList({table}: Props): JSX.Element
|
|||||||
{
|
{
|
||||||
defaultVisibility = JSON.parse(localStorage.getItem(columnVisibilityLocalStorageKey));
|
defaultVisibility = JSON.parse(localStorage.getItem(columnVisibilityLocalStorageKey));
|
||||||
}
|
}
|
||||||
|
if (localStorage.getItem(rowsPerPageLocalStorageKey))
|
||||||
|
{
|
||||||
|
defaultRowsPerPage = JSON.parse(localStorage.getItem(rowsPerPageLocalStorageKey));
|
||||||
|
}
|
||||||
|
|
||||||
const [filterModel, setFilterModel] = useState({items: []} as GridFilterModel);
|
const [filterModel, setFilterModel] = useState({items: []} as GridFilterModel);
|
||||||
const [columnSortModel, setColumnSortModel] = useState(defaultSort);
|
const [columnSortModel, setColumnSortModel] = useState(defaultSort);
|
||||||
const [columnVisibilityModel, setColumnVisibilityModel] = useState(defaultVisibility);
|
const [columnVisibilityModel, setColumnVisibilityModel] = useState(defaultVisibility);
|
||||||
|
const [rowsPerPage, setRowsPerPage] = useState(defaultRowsPerPage);
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// for some reason, if we set the filterModel to what is in local storage, an onChange event //
|
// for some reason, if we set the filterModel to what is in local storage, an onChange event //
|
||||||
@ -174,7 +161,6 @@ function EntityList({table}: Props): JSX.Element
|
|||||||
const [tableProcesses, setTableProcesses] = useState([] as QProcessMetaData[]);
|
const [tableProcesses, setTableProcesses] = useState([] as QProcessMetaData[]);
|
||||||
const [pageNumber, setPageNumber] = useState(0);
|
const [pageNumber, setPageNumber] = useState(0);
|
||||||
const [totalRecords, setTotalRecords] = useState(0);
|
const [totalRecords, setTotalRecords] = useState(0);
|
||||||
const [rowsPerPage, setRowsPerPage] = useState(10);
|
|
||||||
const [selectedIds, setSelectedIds] = useState([] as string[]);
|
const [selectedIds, setSelectedIds] = useState([] as string[]);
|
||||||
const [selectFullFilterState, setSelectFullFilterState] = useState("n/a" as "n/a" | "checked" | "filter");
|
const [selectFullFilterState, setSelectFullFilterState] = useState("n/a" as "n/a" | "checked" | "filter");
|
||||||
const [columns, setColumns] = useState([] as GridColDef[]);
|
const [columns, setColumns] = useState([] as GridColDef[]);
|
||||||
@ -356,7 +342,7 @@ function EntityList({table}: Props): JSX.Element
|
|||||||
const getCustomGridBooleanOperators = (): GridFilterOperator[] =>
|
const getCustomGridBooleanOperators = (): GridFilterOperator[] =>
|
||||||
{
|
{
|
||||||
return [booleanTrueOperator, booleanFalseOperator, booleanEmptyOperator, booleanNotEmptyOperator];
|
return [booleanTrueOperator, booleanFalseOperator, booleanEmptyOperator, booleanNotEmptyOperator];
|
||||||
}
|
};
|
||||||
|
|
||||||
///////////////////////////
|
///////////////////////////
|
||||||
// display query results //
|
// display query results //
|
||||||
@ -557,6 +543,7 @@ function EntityList({table}: Props): JSX.Element
|
|||||||
const handleRowsPerPageChange = (size: number) =>
|
const handleRowsPerPageChange = (size: number) =>
|
||||||
{
|
{
|
||||||
setRowsPerPage(size);
|
setRowsPerPage(size);
|
||||||
|
localStorage.setItem(rowsPerPageLocalStorageKey, JSON.stringify(size));
|
||||||
};
|
};
|
||||||
|
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
@ -901,6 +888,9 @@ function EntityList({table}: Props): JSX.Element
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
|
<div className="pagination">
|
||||||
|
<CustomPagination />
|
||||||
|
</div>
|
||||||
</GridToolbarContainer>
|
</GridToolbarContainer>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import {QException} from "@kingsrook/qqq-frontend-core/lib/exceptions/QException";
|
||||||
import {QProcessMetaData} from "@kingsrook/qqq-frontend-core/lib/model/metaData/QProcessMetaData";
|
import {QProcessMetaData} from "@kingsrook/qqq-frontend-core/lib/model/metaData/QProcessMetaData";
|
||||||
import {QTableMetaData} from "@kingsrook/qqq-frontend-core/lib/model/metaData/QTableMetaData";
|
import {QTableMetaData} from "@kingsrook/qqq-frontend-core/lib/model/metaData/QTableMetaData";
|
||||||
import {QTableSection} from "@kingsrook/qqq-frontend-core/lib/model/metaData/QTableSection";
|
import {QTableSection} from "@kingsrook/qqq-frontend-core/lib/model/metaData/QTableSection";
|
||||||
@ -80,8 +81,9 @@ function ViewContents({id, table}: Props): JSX.Element
|
|||||||
const [tableProcesses, setTableProcesses] = useState([] as QProcessMetaData[]);
|
const [tableProcesses, setTableProcesses] = useState([] as QProcessMetaData[]);
|
||||||
const [actionsMenu, setActionsMenu] = useState(null);
|
const [actionsMenu, setActionsMenu] = useState(null);
|
||||||
const [tableWidgets, setTableWidgets] = useState([] as QWidgetMetaData[]);
|
const [tableWidgets, setTableWidgets] = useState([] as QWidgetMetaData[]);
|
||||||
|
const [notFoundMessage, setNotFoundMessage] = useState(null);
|
||||||
const [searchParams] = useSearchParams();
|
const [searchParams] = useSearchParams();
|
||||||
const {pageHeader, setPageHeader} = useContext(QContext);
|
const {setPageHeader} = useContext(QContext);
|
||||||
const [, forceUpdate] = useReducer((x) => x + 1, 0);
|
const [, forceUpdate] = useReducer((x) => x + 1, 0);
|
||||||
|
|
||||||
const openActionsMenu = (event: any) => setActionsMenu(event.currentTarget);
|
const openActionsMenu = (event: any) => setActionsMenu(event.currentTarget);
|
||||||
@ -126,8 +128,24 @@ function ViewContents({id, table}: Props): JSX.Element
|
|||||||
/////////////////////
|
/////////////////////
|
||||||
// load the record //
|
// load the record //
|
||||||
/////////////////////
|
/////////////////////
|
||||||
const record = await qController.get(tableName, id);
|
let record: QRecord;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
record = await qController.get(tableName, id);
|
||||||
setRecord(record);
|
setRecord(record);
|
||||||
|
}
|
||||||
|
catch (e)
|
||||||
|
{
|
||||||
|
if (e instanceof QException)
|
||||||
|
{
|
||||||
|
if ((e as QException).status === "404")
|
||||||
|
{
|
||||||
|
setNotFoundMessage(`${tableMetaData.label} ${id} could not be found.`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
setPageHeader(record.recordLabel);
|
setPageHeader(record.recordLabel);
|
||||||
|
|
||||||
///////////////////////////
|
///////////////////////////
|
||||||
@ -254,7 +272,10 @@ function ViewContents({id, table}: Props): JSX.Element
|
|||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
notFoundMessage
|
||||||
|
?
|
||||||
|
<MDBox>{notFoundMessage}</MDBox>
|
||||||
|
:
|
||||||
<MDBox pb={3}>
|
<MDBox pb={3}>
|
||||||
{
|
{
|
||||||
(searchParams.get("createSuccess") || searchParams.get("updateSuccess")) ? (
|
(searchParams.get("createSuccess") || searchParams.get("updateSuccess")) ? (
|
||||||
|
@ -111,6 +111,13 @@
|
|||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.MuiDataGrid-toolbarContainer .pagination
|
||||||
|
{
|
||||||
|
display: flex;
|
||||||
|
flex-grow: 1;
|
||||||
|
justify-content: flex-end;
|
||||||
|
}
|
||||||
|
|
||||||
/* Help make the radio, text, and icon wrap in a good way */
|
/* Help make the radio, text, and icon wrap in a good way */
|
||||||
.doFullValidationRadios label
|
.doFullValidationRadios label
|
||||||
{
|
{
|
||||||
|
Reference in New Issue
Block a user